mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Remove public registration and require that a user be registered by an admin
This commit is contained in:
@@ -6,25 +6,19 @@ settings = require("settings-sharelatex")
|
|||||||
|
|
||||||
templates = {}
|
templates = {}
|
||||||
|
|
||||||
templates.welcome =
|
templates.registered =
|
||||||
subject: _.template "Welcome to ShareLaTeX"
|
subject: _.template "Activate your #{settings.appName} Account"
|
||||||
layout: PersonalEmailLayout
|
layout: PersonalEmailLayout
|
||||||
type:"lifecycle"
|
type: "notification"
|
||||||
compiledTemplate: _.template '''
|
compiledTemplate: _.template """
|
||||||
<p>Hi <%= first_name %>,</p>
|
<p>Congratulations, you've just had an account created for you on #{settings.appName} with the email address "<%= to %>".</p>
|
||||||
|
|
||||||
<p>Thanks for signing up to ShareLaTeX! If you ever get lost, you can log in again <a href="<%= siteUrl %>/login">here</a> with the email address "<%= to %>".</p>
|
<p><a href="<%= setNewPasswordUrl %>">Click here to set your password and log in.</a></p>
|
||||||
|
|
||||||
<p>If you're new to LaTeX, take a look at our <a href="<%= siteUrl %>/learn">Help Guides</a> and <a href="<%= siteUrl %>/templates">Templates</a>.</p>
|
<p>Once you have reset your password you can <a href="#{settings.siteUrl}/login">log in here</a>.</p>
|
||||||
|
|
||||||
<p>
|
<p>If you have any questions or problems, please contact <a href="mailto:#{settings.adminEmail}">#{settings.adminEmail}</a>.</p>
|
||||||
Regards, <br>
|
"""
|
||||||
Henry <br>
|
|
||||||
ShareLaTeX Co-founder
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>PS. We love talking to our users about ShareLaTeX. Reply to this email to get in touch us with us directly, whatever the reason. Questions, comments, problems, suggestions, all welcome!<p>
|
|
||||||
'''
|
|
||||||
|
|
||||||
templates.canceledSubscription =
|
templates.canceledSubscription =
|
||||||
subject: _.template "ShareLaTeX thoughts"
|
subject: _.template "ShareLaTeX thoughts"
|
||||||
@@ -44,16 +38,16 @@ ShareLaTeX Co-founder
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
templates.passwordResetRequested =
|
templates.passwordResetRequested =
|
||||||
subject: _.template "Password Reset - ShareLatex.com"
|
subject: _.template "Password Reset - #{settings.appName}"
|
||||||
layout: NotificationEmailLayout
|
layout: NotificationEmailLayout
|
||||||
type:"notification"
|
type:"notification"
|
||||||
compiledTemplate: _.template '''
|
compiledTemplate: _.template """
|
||||||
<h1 class="h1">Password Reset</h1>
|
<h2>Password Reset</h2>
|
||||||
<p>
|
<p>
|
||||||
We got a request to reset your ShareLaTeX password.
|
We got a request to reset your #{settings.appName} password.
|
||||||
<p>
|
<p>
|
||||||
<center>
|
<center>
|
||||||
<div style="width:200px;background-color:#a93629;border:1px solid #e24b3b;border-radius:3px;padding:15px; margin:12.5px;">
|
<div style="width:200px;background-color:#a93629;border:1px solid #e24b3b;border-radius:3px;padding:15px; margin:24px;">
|
||||||
<div style="padding-right:10px;padding-left:10px">
|
<div style="padding-right:10px;padding-left:10px">
|
||||||
<a href="<%= setNewPasswordUrl %>" style="text-decoration:none" target="_blank">
|
<a href="<%= setNewPasswordUrl %>" style="text-decoration:none" target="_blank">
|
||||||
<span style= "font-size:16px;font-family:Arial;font-weight:bold;color:#fff;white-space:nowrap;display:block; text-align:center">
|
<span style= "font-size:16px;font-family:Arial;font-weight:bold;color:#fff;white-space:nowrap;display:block; text-align:center">
|
||||||
@@ -70,18 +64,17 @@ If you didn't request a password reset, let us know.
|
|||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p>Thank you</p>
|
<p>Thank you</p>
|
||||||
<p> <a href="<%= siteUrl %>"> ShareLatex.com </a></p>
|
<p> <a href="<%= siteUrl %>">#{settings.appName}</a></p>
|
||||||
'''
|
"""
|
||||||
|
|
||||||
templates.projectSharedWithYou =
|
templates.projectSharedWithYou =
|
||||||
subject: _.template "<%= owner.email %> wants to share <%= project.name %> with you"
|
subject: _.template "<%= owner.email %> wants to share <%= project.name %> with you"
|
||||||
layout: NotificationEmailLayout
|
layout: NotificationEmailLayout
|
||||||
type:"notification"
|
type:"notification"
|
||||||
compiledTemplate: _.template '''
|
compiledTemplate: _.template """
|
||||||
<p>Hi, <%= owner.email %> wants to share <a href="<%= project.url %>">'<%= project.name %>'</a> with you</p>
|
<p>Hi, <%= owner.email %> wants to share <a href="<%= project.url %>">'<%= project.name %>'</a> with you</p>
|
||||||
<p> </p>
|
|
||||||
<center>
|
<center>
|
||||||
<div style="width:200px;background-color:#a93629;border:1px solid #e24b3b;border-radius:3px;padding:15px; margin:12.5px;">
|
<div style="width:200px;background-color:#a93629;border:1px solid #e24b3b;border-radius:3px;padding:15px; margin:24px;">
|
||||||
<div style="padding-right:10px;padding-left:10px">
|
<div style="padding-right:10px;padding-left:10px">
|
||||||
<a href="<%= project.url %>" style="text-decoration:none" target="_blank">
|
<a href="<%= project.url %>" style="text-decoration:none" target="_blank">
|
||||||
<span style= "font-size:16px;font-family:Helvetica,Arial;font-weight:400;color:#fff;white-space:nowrap;display:block; text-align:center">
|
<span style= "font-size:16px;font-family:Helvetica,Arial;font-weight:400;color:#fff;white-space:nowrap;display:block; text-align:center">
|
||||||
@@ -92,9 +85,8 @@ templates.projectSharedWithYou =
|
|||||||
</div>
|
</div>
|
||||||
</center>
|
</center>
|
||||||
<p> Thank you</p>
|
<p> Thank you</p>
|
||||||
<p> <a href="<%= siteUrl %>"> ShareLatex.com </a></p>
|
<p> <a href="<%= siteUrl %>">#{settings.appName}</a></p>
|
||||||
|
"""
|
||||||
'''
|
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
_ = require("underscore")
|
_ = require("underscore")
|
||||||
|
settings = require "settings-sharelatex"
|
||||||
|
|
||||||
module.exports = _.template '''
|
module.exports = _.template """
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@@ -311,12 +312,8 @@ module.exports = _.template '''
|
|||||||
<!-- // Begin Template Header \\ -->
|
<!-- // Begin Template Header \\ -->
|
||||||
<table border="0" cellpadding="0" cellspacing="0" width="600" id="templateHeader">
|
<table border="0" cellpadding="0" cellspacing="0" width="600" id="templateHeader">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="headerContent" style="padding: 25px;border-bottom:#dadf90;background-color:#F6F6F6;text-align:left;">
|
<td class="headerContent" style="padding: 25px;border-bottom:#dadf90;background-color:#F6F6F6;text-align:left;font-size:18px">
|
||||||
|
#{settings.appName}
|
||||||
<!-- // Begin Module: Standard Header Image \\ -->
|
|
||||||
<img src="https://www.sharelatex.com/img/logo.png" style="max-width:600px;" id="headerImage campaign-icon" />
|
|
||||||
<!-- // End Module: Standard Header Image \\ -->
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -346,31 +343,6 @@ module.exports = _.template '''
|
|||||||
<!-- // End Template Body \\ -->
|
<!-- // End Template Body \\ -->
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td align="center" valign="top">
|
|
||||||
<!-- // Begin Template Footer \\ -->
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0" width="600" id="templateFooter">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" class="footerContent">
|
|
||||||
|
|
||||||
<!-- // Begin Module: Standard Footer \\ -->
|
|
||||||
<table border="0" cellpadding="25" cellspacing="0" width="100%">
|
|
||||||
<tr>
|
|
||||||
<td colspan="2" valign="middle" id="social">
|
|
||||||
<div>
|
|
||||||
<a href="http://twitter.com/#!/sharelatex">Follow on Twitter</a> | <a href="http://www.facebook.com/pages/ShareLaTeX/301671376556660">Friend on Facebook</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<!-- // End Module: Standard Footer \\ -->
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<!-- // End Template Footer \\ -->
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@@ -380,4 +352,4 @@ module.exports = _.template '''
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
'''
|
"""
|
||||||
@@ -10,12 +10,17 @@ buildKey = (token)-> return "password_token:#{token}"
|
|||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
|
|
||||||
getNewToken: (user_id, callback)->
|
getNewToken: (user_id, options = {}, callback)->
|
||||||
|
# options is optional
|
||||||
|
if typeof options == "function"
|
||||||
|
callback = options
|
||||||
|
options = {}
|
||||||
|
expiresIn = options.expiresIn or ONE_HOUR_IN_S
|
||||||
logger.log user_id:user_id, "generating token for password reset"
|
logger.log user_id:user_id, "generating token for password reset"
|
||||||
token = crypto.randomBytes(32).toString("hex")
|
token = crypto.randomBytes(32).toString("hex")
|
||||||
multi = rclient.multi()
|
multi = rclient.multi()
|
||||||
multi.set buildKey(token), user_id
|
multi.set buildKey(token), user_id
|
||||||
multi.expire buildKey(token), ONE_HOUR_IN_S
|
multi.expire buildKey(token), expiresIn
|
||||||
multi.exec (err)->
|
multi.exec (err)->
|
||||||
callback(err, token)
|
callback(err, token)
|
||||||
|
|
||||||
|
|||||||
@@ -39,11 +39,14 @@ module.exports = AdminController =
|
|||||||
|
|
||||||
SystemMessageManager.getMessagesFromDB (error, systemMessages) ->
|
SystemMessageManager.getMessagesFromDB (error, systemMessages) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
res.render 'admin',
|
res.render 'admin/index',
|
||||||
title: 'System Admin'
|
title: 'System Admin'
|
||||||
openSockets: openSockets
|
openSockets: openSockets
|
||||||
systemMessages: systemMessages
|
systemMessages: systemMessages
|
||||||
|
|
||||||
|
registerNewUser: (req, res, next) ->
|
||||||
|
res.render 'admin/register'
|
||||||
|
|
||||||
dissconectAllUsers: (req, res)=>
|
dissconectAllUsers: (req, res)=>
|
||||||
logger.warn "disconecting everyone"
|
logger.warn "disconecting everyone"
|
||||||
EditorRealTimeController.emitToAll 'forceDisconnect', "Sorry, we are performing a quick update to the editor and need to close it down. Please refresh the page to continue."
|
EditorRealTimeController.emitToAll 'forceDisconnect', "Sorry, we are performing a quick update to the editor and need to close it down. Please refresh the page to continue."
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ ReferalAllocator = require("../Referal/ReferalAllocator")
|
|||||||
UserUpdater = require("./UserUpdater")
|
UserUpdater = require("./UserUpdater")
|
||||||
SubscriptionDomainAllocator = require("../Subscription/SubscriptionDomainAllocator")
|
SubscriptionDomainAllocator = require("../Subscription/SubscriptionDomainAllocator")
|
||||||
EmailHandler = require("../Email/EmailHandler")
|
EmailHandler = require("../Email/EmailHandler")
|
||||||
|
PasswordResetTokenHandler = require "../PasswordReset/PasswordResetTokenHandler"
|
||||||
|
settings = require "settings-sharelatex"
|
||||||
|
crypto = require "crypto"
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
|
|
||||||
@@ -81,34 +84,37 @@ module.exports =
|
|||||||
res.redirect '/login'
|
res.redirect '/login'
|
||||||
|
|
||||||
register : (req, res, next = (error) ->)->
|
register : (req, res, next = (error) ->)->
|
||||||
logger.log email: req.body.email, "attempted register"
|
email = req.body.email
|
||||||
redir = Url.parse(req.body.redir or "/project").path
|
if !email? or email == ""
|
||||||
UserRegistrationHandler.registerNewUser req.body, (err, user)->
|
res.send 422 # Unprocessable Entity
|
||||||
if err? and err?.message == "EmailAlreadyRegistered"
|
return
|
||||||
return AuthenticationController.login req, res
|
logger.log {email}, "registering new user"
|
||||||
else if err?
|
UserRegistrationHandler.registerNewUser {
|
||||||
next(err)
|
email: email
|
||||||
else
|
password: crypto.randomBytes(32).toString("hex")
|
||||||
metrics.inc "user.register.success"
|
}, (err, user)->
|
||||||
ReferalAllocator.allocate req.session.referal_id, user._id, req.session.referal_source, req.session.referal_medium
|
if err? and err?.message != "EmailAlreadyRegistered"
|
||||||
SubscriptionDomainAllocator.autoAllocate(user)
|
return next(err)
|
||||||
|
|
||||||
EmailHandler.sendEmail "welcome", {
|
if err?.message == "EmailAlreadyRegistered"
|
||||||
first_name:user.first_name
|
logger.log {email}, "user already exists, resending welcome email"
|
||||||
|
|
||||||
|
# TODO: Make a long term token.
|
||||||
|
ONE_WEEK = 7 * 24 * 60 * 60 # seconds
|
||||||
|
PasswordResetTokenHandler.getNewToken user._id, { expiresIn: ONE_WEEK }, (err, token)->
|
||||||
|
return next(err) if err?
|
||||||
|
|
||||||
|
setNewPasswordUrl = "#{settings.siteUrl}/user/password/set?passwordResetToken=#{token}"
|
||||||
|
|
||||||
|
EmailHandler.sendEmail "registered", {
|
||||||
to: user.email
|
to: user.email
|
||||||
|
setNewPasswordUrl: setNewPasswordUrl
|
||||||
}, () ->
|
}, () ->
|
||||||
|
|
||||||
AuthenticationController.establishUserSession req, user, (error) ->
|
res.json {
|
||||||
return callback(error) if error?
|
email: user.email
|
||||||
req.session.justRegistered = true
|
setNewPasswordUrl: setNewPasswordUrl
|
||||||
res.send
|
}
|
||||||
redir:redir
|
|
||||||
id:user._id.toString()
|
|
||||||
first_name: user.first_name
|
|
||||||
last_name: user.last_name
|
|
||||||
email: user.email
|
|
||||||
created: Date.now()
|
|
||||||
|
|
||||||
|
|
||||||
changePassword : (req, res, next = (error) ->)->
|
changePassword : (req, res, next = (error) ->)->
|
||||||
metrics.inc "user.password-change"
|
metrics.inc "user.password-change"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ module.exports =
|
|||||||
if err?
|
if err?
|
||||||
return callback err
|
return callback err
|
||||||
if user?.holdingAccount == false
|
if user?.holdingAccount == false
|
||||||
return callback(new Error("EmailAlreadyRegistered"))
|
return callback(new Error("EmailAlreadyRegistered"), user)
|
||||||
self._createNewUserIfRequired user, userDetails, (err, user)->
|
self._createNewUserIfRequired user, userDetails, (err, user)->
|
||||||
if err?
|
if err?
|
||||||
return callback(err)
|
return callback(err)
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ module.exports = class Router
|
|||||||
app.get '/logout', UserController.logout
|
app.get '/logout', UserController.logout
|
||||||
app.get '/restricted', SecurityManager.restricted
|
app.get '/restricted', SecurityManager.restricted
|
||||||
|
|
||||||
|
# Left as a placeholder for implementing a public register page
|
||||||
app.get '/register', UserPagesController.registerPage
|
app.get '/register', UserPagesController.registerPage
|
||||||
app.post '/register', UserController.register
|
|
||||||
|
|
||||||
EditorRouter.apply(app, httpAuth)
|
EditorRouter.apply(app, httpAuth)
|
||||||
CollaboratorsRouter.apply(app)
|
CollaboratorsRouter.apply(app)
|
||||||
@@ -157,6 +157,8 @@ module.exports = class Router
|
|||||||
|
|
||||||
#Admin Stuff
|
#Admin Stuff
|
||||||
app.get '/admin', SecurityManager.requestIsAdmin, AdminController.index
|
app.get '/admin', SecurityManager.requestIsAdmin, AdminController.index
|
||||||
|
app.get '/admin/register', SecurityManager.requestIsAdmin, AdminController.registerNewUser
|
||||||
|
app.post '/admin/register', SecurityManager.requestIsAdmin, UserController.register
|
||||||
app.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor
|
app.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor
|
||||||
app.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers
|
app.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers
|
||||||
app.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
|
app.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
extends layout
|
extends ../layout
|
||||||
|
|
||||||
block content
|
block content
|
||||||
.content.content-alt
|
.content.content-alt
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
extends ../layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
.content.content-alt
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
.card(ng-controller="RegisterUsersController")
|
||||||
|
.page-header
|
||||||
|
h1 Register New Users
|
||||||
|
form.form
|
||||||
|
.row
|
||||||
|
.col-md-4.col-xs-8
|
||||||
|
input.form-control(
|
||||||
|
name="email",
|
||||||
|
type="text",
|
||||||
|
placeholder="jane@example.com, joe@example.com",
|
||||||
|
ng-model="inputs.emails",
|
||||||
|
on-enter="registerUsers()"
|
||||||
|
)
|
||||||
|
.col-md-8.col-xs-4
|
||||||
|
button.btn.btn-primary(ng-click="registerUsers()") #{translate("register")}
|
||||||
|
|
||||||
|
.row-spaced(ng-show="error").ng-cloak.text-danger
|
||||||
|
p Sorry, an error occured
|
||||||
|
|
||||||
|
.row-spaced(ng-show="users.length > 0").ng-cloak.text-success
|
||||||
|
p We've sent out welcome emails to the registered users.
|
||||||
|
p You can also manually send them URLs below to allow them to reset their password and log in for the first time.
|
||||||
|
p (Password reset tokens will expire after one week and the user will need registering again).
|
||||||
|
|
||||||
|
hr(ng-show="users.length > 0").ng-cloak
|
||||||
|
table(ng-show="users.length > 0").table.table-striped.ng-cloak
|
||||||
|
tr
|
||||||
|
th #{translate("email")}
|
||||||
|
th Set Password Url
|
||||||
|
tr(ng-repeat="user in users")
|
||||||
|
td {{ user.email }}
|
||||||
|
td(style="word-break: break-all;") {{ user.setNewPasswordUrl }}
|
||||||
|
|
||||||
@@ -11,6 +11,15 @@ nav.navbar.navbar-default
|
|||||||
.navbar-collapse.collapse(collapse="navCollapsed")
|
.navbar-collapse.collapse(collapse="navCollapsed")
|
||||||
|
|
||||||
ul.nav.navbar-nav.navbar-right
|
ul.nav.navbar-nav.navbar-right
|
||||||
|
if (session && session.user && session.user.isAdmin)
|
||||||
|
li.dropdown(class="subdued")
|
||||||
|
a.dropdown-toggle(href)
|
||||||
|
| Admin
|
||||||
|
b.caret
|
||||||
|
ul.dropdown-menu
|
||||||
|
li
|
||||||
|
a(href="/admin/register") Register New Users
|
||||||
|
|
||||||
each item in nav.header
|
each item in nav.header
|
||||||
if ((item.only_when_logged_in && session && session.user) || (item.only_when_logged_out && (!session || !session.user)) || (!item.only_when_logged_out && !item.only_when_logged_in))
|
if ((item.only_when_logged_in && session && session.user) || (item.only_when_logged_out && (!session || !session.user)) || (!item.only_when_logged_out && !item.only_when_logged_in))
|
||||||
if item.dropdown
|
if item.dropdown
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ define [
|
|||||||
"main/subscription-dashboard"
|
"main/subscription-dashboard"
|
||||||
"main/new-subscription"
|
"main/new-subscription"
|
||||||
"main/annual-upgrade"
|
"main/annual-upgrade"
|
||||||
|
"main/register-users"
|
||||||
"analytics/AbTestingManager"
|
"analytics/AbTestingManager"
|
||||||
"directives/asyncForm"
|
"directives/asyncForm"
|
||||||
"directives/stopPropagation"
|
"directives/stopPropagation"
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
define [
|
||||||
|
"base"
|
||||||
|
], (App) ->
|
||||||
|
App.controller "RegisterUsersController", ($scope, queuedHttp) ->
|
||||||
|
$scope.users = []
|
||||||
|
|
||||||
|
$scope.inputs =
|
||||||
|
emails: ""
|
||||||
|
|
||||||
|
parseEmails = (emailsString)->
|
||||||
|
regexBySpaceOrComma = /[\s,]+/
|
||||||
|
emails = emailsString.split(regexBySpaceOrComma)
|
||||||
|
emails = _.map emails, (email)->
|
||||||
|
email = email.trim()
|
||||||
|
emails = _.select emails, (email)->
|
||||||
|
email.indexOf("@") != -1
|
||||||
|
return emails
|
||||||
|
|
||||||
|
$scope.registerUsers = () ->
|
||||||
|
emails = parseEmails($scope.inputs.emails)
|
||||||
|
$scope.error = false
|
||||||
|
for email in emails
|
||||||
|
queuedHttp
|
||||||
|
.post("/admin/register", {
|
||||||
|
email: email,
|
||||||
|
_csrf: window.csrfToken
|
||||||
|
})
|
||||||
|
.success (user) ->
|
||||||
|
$scope.users.push user
|
||||||
|
$scope.inputs.emails = ""
|
||||||
|
.error () ->
|
||||||
|
$scope.error = true
|
||||||
@@ -18,20 +18,6 @@ describe "Email Templator ", ->
|
|||||||
"settings-sharelatex":@settings
|
"settings-sharelatex":@settings
|
||||||
"logger-sharelatex": log:->
|
"logger-sharelatex": log:->
|
||||||
|
|
||||||
describe "welcomeEmail", ->
|
|
||||||
|
|
||||||
beforeEach ->
|
|
||||||
@opts =
|
|
||||||
to:"bob@bob.com"
|
|
||||||
first_name:"bob"
|
|
||||||
@email = @EmailBuilder.buildEmail("welcome", @opts)
|
|
||||||
|
|
||||||
it "should insert the first_name into the template", ->
|
|
||||||
@email.html.indexOf(@opts.first_name).should.not.equal -1
|
|
||||||
|
|
||||||
it "should not have undefined in it", ->
|
|
||||||
@email.html.indexOf("undefined").should.equal -1
|
|
||||||
|
|
||||||
describe "projectSharedWithYou", ->
|
describe "projectSharedWithYou", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@opts =
|
@opts =
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ describe "PasswordResetTokenHandler", ->
|
|||||||
err.should.exist
|
err.should.exist
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
it "should allow the expiry time to be overridden", (done) ->
|
||||||
|
@redisMulti.exec.callsArgWith(0)
|
||||||
|
@ttl = 42
|
||||||
|
@PasswordResetTokenHandler.getNewToken @user_id, {expiresIn: @ttl}, (err, token) =>
|
||||||
|
@redisMulti.expire.calledWith("password_token:#{@stubbedToken.toString("hex")}", @ttl).should.equal true
|
||||||
|
done()
|
||||||
|
|
||||||
describe "getUserIdFromTokenAndExpire", ->
|
describe "getUserIdFromTokenAndExpire", ->
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ describe "UserController", ->
|
|||||||
changeEmailAddress:sinon.stub()
|
changeEmailAddress:sinon.stub()
|
||||||
@EmailHandler =
|
@EmailHandler =
|
||||||
sendEmail:sinon.stub().callsArgWith(2)
|
sendEmail:sinon.stub().callsArgWith(2)
|
||||||
|
@PasswordResetTokenHandler =
|
||||||
|
getNewToken: sinon.stub()
|
||||||
|
@settings =
|
||||||
|
siteUrl: "sharelatex.example.com"
|
||||||
@UserController = SandboxedModule.require modulePath, requires:
|
@UserController = SandboxedModule.require modulePath, requires:
|
||||||
"./UserLocator": @UserLocator
|
"./UserLocator": @UserLocator
|
||||||
"./UserDeleter": @UserDeleter
|
"./UserDeleter": @UserDeleter
|
||||||
@@ -54,6 +58,9 @@ describe "UserController", ->
|
|||||||
"../Referal/ReferalAllocator":@ReferalAllocator
|
"../Referal/ReferalAllocator":@ReferalAllocator
|
||||||
"../Subscription/SubscriptionDomainAllocator":@SubscriptionDomainAllocator
|
"../Subscription/SubscriptionDomainAllocator":@SubscriptionDomainAllocator
|
||||||
"../Email/EmailHandler": @EmailHandler
|
"../Email/EmailHandler": @EmailHandler
|
||||||
|
"../PasswordReset/PasswordResetTokenHandler": @PasswordResetTokenHandler
|
||||||
|
"crypto": @crypto = {}
|
||||||
|
"settings-sharelatex": @settings
|
||||||
"logger-sharelatex": {log:->}
|
"logger-sharelatex": {log:->}
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +70,9 @@ describe "UserController", ->
|
|||||||
user :
|
user :
|
||||||
_id : @user_id
|
_id : @user_id
|
||||||
body:{}
|
body:{}
|
||||||
@res = {}
|
@res =
|
||||||
|
send: sinon.stub()
|
||||||
|
json: sinon.stub()
|
||||||
@next = sinon.stub()
|
@next = sinon.stub()
|
||||||
describe "deleteUser", ->
|
describe "deleteUser", ->
|
||||||
|
|
||||||
@@ -165,76 +174,52 @@ describe "UserController", ->
|
|||||||
|
|
||||||
|
|
||||||
describe "register", ->
|
describe "register", ->
|
||||||
|
beforeEach ->
|
||||||
|
@req.body.email = @user.email = "email@example.com"
|
||||||
|
@crypto.randomBytes = sinon.stub().returns({toString: () => @password = "mock-password"})
|
||||||
|
@PasswordResetTokenHandler.getNewToken.callsArgWith(2, null, @token = "mock-token")
|
||||||
|
|
||||||
it "should ask the UserRegistrationHandler to register user", (done)->
|
describe "with a new user", ->
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
beforeEach ->
|
||||||
@res.send = =>
|
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
||||||
@UserRegistrationHandler.registerNewUser.calledWith(@req.body).should.equal true
|
@UserController.register @req, @res
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should try and log the user in if there is an EmailAlreadyRegistered error", (done)->
|
it "should ask the UserRegistrationHandler to register user", ->
|
||||||
|
@UserRegistrationHandler.registerNewUser
|
||||||
|
.calledWith({
|
||||||
|
email: @req.body.email
|
||||||
|
password: @password
|
||||||
|
}).should.equal true
|
||||||
|
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, new Error("EmailAlreadyRegistered"))
|
it "should generate a new password reset token", ->
|
||||||
@AuthenticationController.login = (req, res)=>
|
@PasswordResetTokenHandler.getNewToken
|
||||||
assert.deepEqual req, @req
|
.calledWith(@user_id, expiresIn: 7 * 24 * 60 * 60)
|
||||||
assert.deepEqual res, @res
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should put the user on the session and mark them as justRegistered", (done)->
|
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
|
||||||
@res.send = =>
|
|
||||||
@AuthenticationController.establishUserSession
|
|
||||||
.calledWith(@req, @user)
|
|
||||||
.should.equal true
|
.should.equal true
|
||||||
assert.equal @req.session.justRegistered, true
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should redirect to project page", (done)->
|
it "should send a registered email", ->
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
@EmailHandler.sendEmail
|
||||||
@res.send = (opts)=>
|
.calledWith("registered", {
|
||||||
opts.redir.should.equal "/project"
|
to: @user.email
|
||||||
done()
|
setNewPasswordUrl: "#{@settings.siteUrl}/user/password/set?passwordResetToken=#{@token}"
|
||||||
@UserController.register @req, @res
|
})
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should return the user", ->
|
||||||
|
@res.json
|
||||||
|
.calledWith({
|
||||||
|
email: @user.email
|
||||||
|
setNewPasswordUrl: "#{@settings.siteUrl}/user/password/set?passwordResetToken=#{@token}"
|
||||||
|
})
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
it "should redirect passed redir if it exists", (done)->
|
describe "with a user that already exists", ->
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
beforeEach ->
|
||||||
@req.body.redir = "/somewhere"
|
@UserRegistrationHandler.registerNewUser.callsArgWith(1, new Error("EmailAlreadyRegistered"), @user)
|
||||||
@res.send = (opts)=>
|
@UserController.register @req, @res
|
||||||
opts.redir.should.equal "/somewhere"
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should allocate the referals", (done)->
|
|
||||||
@req.session =
|
|
||||||
referal_id : "23123"
|
|
||||||
referal_source : "email"
|
|
||||||
referal_medium : "bob"
|
|
||||||
|
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
|
||||||
@req.body.redir = "/somewhere"
|
|
||||||
@res.send = (opts)=>
|
|
||||||
@ReferalAllocator.allocate.calledWith(@req.session.referal_id, @user._id, @req.session.referal_source, @req.session.referal_medium).should.equal true
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should auto allocate the subscription for that domain", (done)->
|
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
|
||||||
@res.send = (opts)=>
|
|
||||||
@SubscriptionDomainAllocator.autoAllocate.calledWith(@user).should.equal true
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
it "should send a welcome email", (done)->
|
|
||||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
|
||||||
@res.send = (opts)=>
|
|
||||||
@EmailHandler.sendEmail.calledWith("welcome").should.equal true
|
|
||||||
done()
|
|
||||||
@UserController.register @req, @res
|
|
||||||
|
|
||||||
|
it "should still generate a new password token and email", ->
|
||||||
|
@PasswordResetTokenHandler.getNewToken.called.should.equal true
|
||||||
|
@EmailHandler.sendEmail.called.should.equal true
|
||||||
|
|
||||||
describe "changePassword", ->
|
describe "changePassword", ->
|
||||||
|
|
||||||
|
|||||||
@@ -85,9 +85,10 @@ describe "UserRegistrationHandler", ->
|
|||||||
done()
|
done()
|
||||||
|
|
||||||
it "should return email registered in the error if there is a non holdingAccount there", (done)->
|
it "should return email registered in the error if there is a non holdingAccount there", (done)->
|
||||||
@User.findOne.callsArgWith(1, null, {holdingAccount:false})
|
@User.findOne.callsArgWith(1, null, @user = {holdingAccount:false})
|
||||||
@handler.registerNewUser @passingRequest, (err)=>
|
@handler.registerNewUser @passingRequest, (err, user)=>
|
||||||
err.should.deep.equal new Error("EmailAlreadyRegistered")
|
err.should.deep.equal new Error("EmailAlreadyRegistered")
|
||||||
|
user.should.deep.equal @user
|
||||||
done()
|
done()
|
||||||
|
|
||||||
describe "validRequest", ->
|
describe "validRequest", ->
|
||||||
|
|||||||
Reference in New Issue
Block a user