mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-25 02:00:10 +02:00
Wire up account settings forms
This commit is contained in:
@@ -37,6 +37,10 @@ module.exports =
|
||||
user.first_name = req.body.first_name.trim()
|
||||
if req.body.last_name?
|
||||
user.last_name = req.body.last_name.trim()
|
||||
if req.body.role?
|
||||
user.role = req.body.role.trim()
|
||||
if req.body.institution?
|
||||
user.institution = req.body.institution.trim()
|
||||
if req.body.mode?
|
||||
user.ace.mode = req.body.mode
|
||||
if req.body.theme?
|
||||
|
||||
@@ -28,21 +28,6 @@ module.exports = UserController =
|
||||
UserController.sendFormattedPersonalInfo(user, res, next)
|
||||
req.session.destroy()
|
||||
|
||||
updatePersonalInfo: (req, res, next = (error)->) ->
|
||||
{first_name, last_name, role, institution} = req.body
|
||||
user_id = req.session.user._id
|
||||
logger.log data:req.body, user_id:user_id, "getting update for user personal info"
|
||||
update =
|
||||
first_name:sanitize.escape(first_name)
|
||||
last_name:sanitize.escape(last_name)
|
||||
role:sanitize.escape(role)
|
||||
institution:sanitize.escape(institution)
|
||||
UserUpdater.updatePersonalInfo user_id, update, (err)->
|
||||
if err?
|
||||
res.send 500
|
||||
else
|
||||
res.send 204
|
||||
|
||||
sendFormattedPersonalInfo: (user, res, next = (error) ->) ->
|
||||
UserController._formatPersonalInfo user, (error, info) ->
|
||||
return next(error) if error?
|
||||
|
||||
@@ -28,14 +28,3 @@ module.exports = UserUpdater =
|
||||
return callback(err)
|
||||
callback()
|
||||
|
||||
|
||||
updatePersonalInfo: (user_id, info, callback)->
|
||||
self = @
|
||||
update =
|
||||
$set:
|
||||
"first_name": info.first_name || ""
|
||||
"last_name": info.last_name || ""
|
||||
"role": info.role || ""
|
||||
"institution": info.institution || ""
|
||||
self.updateUser user_id.toString(), update, (err)->
|
||||
callback(err)
|
||||
@@ -91,7 +91,6 @@ module.exports = class Router
|
||||
|
||||
app.get '/user/auth_token', AuthenticationController.requireLogin(), AuthenticationController.getAuthToken
|
||||
app.get '/user/personal_info', AuthenticationController.requireLogin(allow_auth_token: true), UserInfoController.getLoggedInUsersPersonalInfo
|
||||
app.post '/user/personal_info', AuthenticationController.requireLogin(), UserInfoController.updatePersonalInfo
|
||||
app.get '/user/:user_id/personal_info', httpAuth, UserInfoController.getPersonalInfo
|
||||
|
||||
app.get '/project', AuthenticationController.requireLogin(), ProjectController.projectListPage
|
||||
|
||||
@@ -101,7 +101,7 @@ block content
|
||||
| complete
|
||||
|
||||
.progress
|
||||
.bar.bar-success(ng-style="{'width' : (percentComplete+'%')}")
|
||||
.progress-bar.progress-bar-info(ng-style="{'width' : (percentComplete+'%')}")
|
||||
|
||||
button#completeUserProfileInformation.btn.btn-primary(
|
||||
ng-hide="formVisable",
|
||||
|
||||
@@ -11,7 +11,7 @@ block content
|
||||
form(async-form="login", name="loginForm", action='/login', ng-cloak)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
input(name='redir', type='hidden', value=redir)
|
||||
form-messages
|
||||
form-messages(for="loginForm")
|
||||
.form-group
|
||||
input.form-control(
|
||||
type='email',
|
||||
|
||||
@@ -16,8 +16,8 @@ block content
|
||||
ng-cloak
|
||||
)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
form-messages
|
||||
.alert.alert-success(ng-show="success")
|
||||
form-messages(for="passwordResetForm")
|
||||
.alert.alert-success(ng-show="passwordResetForm.response.success")
|
||||
| You have been sent an email to complete your password reset.
|
||||
.form-group
|
||||
label(for='email') Please enter your email address
|
||||
|
||||
@@ -21,16 +21,16 @@ block content
|
||||
form(async-form="register", name="registerForm", action="/register", novalidate, ng-cloak)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
input(name='redir', type='hidden', value=redir)
|
||||
form-messages
|
||||
form-messages(for="registerForm")
|
||||
.form-group
|
||||
label(for='email') Email
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
value='#{new_email}',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
ng-model="email"
|
||||
ng-model="email",
|
||||
ng-init="email = #{JSON.stringify(new_email)}"
|
||||
)
|
||||
span.small.text-primary(ng-show="registerForm.email.$invalid && registerForm.email.$dirty")
|
||||
| Must be an email address
|
||||
|
||||
@@ -15,8 +15,8 @@ block content
|
||||
ng-cloak
|
||||
)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
form-messages
|
||||
.alert.alert-success(ng-show="success")
|
||||
form-messages(for="passwordResetForm")
|
||||
.alert.alert-success(ng-show="passwordResetForm.response.success")
|
||||
| Your password has been reset.
|
||||
a(href='/login') Login here
|
||||
|
||||
|
||||
@@ -5,43 +5,93 @@ block content
|
||||
.container
|
||||
.row
|
||||
.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
|
||||
.card
|
||||
.card.account-settings
|
||||
.page-header
|
||||
h1 Account Settings
|
||||
.messageArea
|
||||
form-messages(ng-cloak, for="settingsForm")
|
||||
.alert.alert-success(ng-show="settingsForm.response.success")
|
||||
| Thanks, your settings have been updated.
|
||||
form-messages(ng-cloak, for="changePasswordForm")
|
||||
.container-fluid
|
||||
.row
|
||||
.row(ng-cloak)
|
||||
.col-md-5
|
||||
h3 Update Account Info
|
||||
form#userSettings
|
||||
form(async-form="settings", name="settingsForm", action="/user/settings", novalidate)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.form-group
|
||||
label(for='email') Email
|
||||
input#emailAddress.form-control(type='email', name='email', value=user.email)
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
ng-model="email",
|
||||
ng-init="email = #{JSON.stringify(user.email)}"
|
||||
)
|
||||
span.small.text-primary(ng-show="settingsForm.email.$invalid && settingsForm.email.$dirty")
|
||||
| Must be an email address
|
||||
.form-group
|
||||
label(for='firstName').control-label First Name
|
||||
input#firstName.form-control(type='text', name='first_name', value=user.first_name)
|
||||
input.form-control(
|
||||
type='text',
|
||||
name='first_name',
|
||||
value=user.first_name
|
||||
)
|
||||
.form-group
|
||||
label(for='lastName').control-label Last Name
|
||||
input#lastName.form-control(type='text', name='last_name', value=user.last_name)
|
||||
input.form-control(
|
||||
type='text',
|
||||
name='last_name',
|
||||
value=user.last_name
|
||||
)
|
||||
.actions
|
||||
button.btn.btn-primary(type='submit') Update
|
||||
button.btn.btn-primary(
|
||||
type='submit',
|
||||
ng-disabled="settingsForm.$invalid"
|
||||
) Update
|
||||
|
||||
.col-md-5.col-md-offset-1
|
||||
h3 Change Password
|
||||
form#changePasswordForm(method="post", action="/user/password/update")
|
||||
form(async-form="changepassword", name="changePasswordForm", action="/user/password/update", novalidate)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.form-group
|
||||
label(for='currentPassword') Current Password
|
||||
input#currentPassword.form-control(type='password', name='currentPassword', placeholder='*********')
|
||||
input.form-control(
|
||||
type='password',
|
||||
name='currentPassword',
|
||||
placeholder='*********',
|
||||
ng-model="currentPassword",
|
||||
required
|
||||
)
|
||||
span.small.text-primary(ng-show="changePasswordForm.currentPassword.$invalid && changePasswordForm.currentPassword.$dirty")
|
||||
| Required
|
||||
.form-group
|
||||
label(for='newPassword1') New Password
|
||||
input#newPassword1.form-control(type='password', name='newPassword1', placeholder='************')
|
||||
input.form-control(
|
||||
type='password',
|
||||
name='newPassword1',
|
||||
placeholder='*********',
|
||||
ng-model="newPassword1",
|
||||
required
|
||||
)
|
||||
span.small.text-primary(ng-show="changePasswordForm.newPassword1.$invalid && changePasswordForm.newPassword1.$dirty")
|
||||
| Required
|
||||
.form-group
|
||||
label(for='newPassword2') Confirm New Password
|
||||
input#newPassword2.form-control(type='password', name='newPassword2', placeholder='************')
|
||||
input.form-control(
|
||||
type='password',
|
||||
name='newPassword2',
|
||||
placeholder='*********',
|
||||
ng-model="newPassword2",
|
||||
equals="{{newPassword1}}"
|
||||
)
|
||||
span.small.text-primary(ng-show="changePasswordForm.newPassword2.$invalid && changePasswordForm.newPassword2.$dirty")
|
||||
| Doesn't match
|
||||
.actions
|
||||
button.btn.btn-primary(type='submit') Change
|
||||
button.btn.btn-primary(
|
||||
type='submit',
|
||||
ng-disabled="changePasswordForm.$invalid"
|
||||
) Change
|
||||
|
||||
hr.soften
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ define [
|
||||
link: (scope, element, attrs) ->
|
||||
formName = attrs.asyncForm
|
||||
|
||||
scope[attrs.name].response = response = {}
|
||||
|
||||
element.on "submit", (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
@@ -16,29 +18,29 @@ define [
|
||||
$http
|
||||
.post(element.attr('action'), formData)
|
||||
.success (data, status, headers, config) ->
|
||||
scope.success = true
|
||||
scope.error = false
|
||||
response.success = true
|
||||
response.error = false
|
||||
|
||||
if data.redir?
|
||||
ga('send', 'event', formName, 'success')
|
||||
window.location = data.redir
|
||||
else if data.message?
|
||||
scope.message = data.message
|
||||
response.message = data.message
|
||||
|
||||
if data.message.type == "error"
|
||||
scope.success = false
|
||||
scope.error = true
|
||||
response.success = false
|
||||
response.error = true
|
||||
ga('send', 'event', formName, 'failure', data.message)
|
||||
else
|
||||
ga('send', 'event', formName, 'success')
|
||||
|
||||
.error (data, status, headers, config) ->
|
||||
scope.success = false
|
||||
scope.error = true
|
||||
ga('send', 'event', formName, 'failure', data.message)
|
||||
scope.message =
|
||||
response.success = false
|
||||
response.error = true
|
||||
response.message =
|
||||
text: data.message or "Something went wrong talking to the server :(. Please try again."
|
||||
type: 'error'
|
||||
ga('send', 'event', formName, 'failure', data.message)
|
||||
}
|
||||
|
||||
App.directive "formMessages", () ->
|
||||
@@ -46,12 +48,16 @@ define [
|
||||
restrict: "E"
|
||||
template: """
|
||||
<div class="alert" ng-class="{
|
||||
'alert-danger': message.type == 'error',
|
||||
'alert-success': message.type != 'error'
|
||||
}" ng-show="!!message">
|
||||
{{message.text}}
|
||||
'alert-danger': form.response.message.type == 'error',
|
||||
'alert-success': form.response.message.type != 'error'
|
||||
}" ng-show="!!form.response.message">
|
||||
{{form.response.message.text}}
|
||||
</div>
|
||||
<div ng-transclude></div>
|
||||
"""
|
||||
transclude: true
|
||||
scope: {
|
||||
form: "=for"
|
||||
}
|
||||
|
||||
}
|
||||
15
services/web/public/coffee/app/directives/equals.coffee
Normal file
15
services/web/public/coffee/app/directives/equals.coffee
Normal file
@@ -0,0 +1,15 @@
|
||||
define [
|
||||
"base"
|
||||
], (App) ->
|
||||
|
||||
App.directive 'equals', () ->
|
||||
return {
|
||||
require: "ngModel",
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
scope.$watch attrs.ngModel, () -> validate()
|
||||
attrs.$observe 'equals', () -> validate()
|
||||
|
||||
validate = () ->
|
||||
equal = (attrs.equals == ngModel.$viewValue)
|
||||
ngModel.$setValidity('areEqual', equal)
|
||||
}
|
||||
@@ -5,5 +5,6 @@ define [
|
||||
"directives/stopPropagation"
|
||||
"directives/focusInput"
|
||||
"directives/focusOn"
|
||||
"directives/equals"
|
||||
], () ->
|
||||
angular.bootstrap(document.body, ["SharelatexApp"])
|
||||
@@ -27,7 +27,7 @@ define [
|
||||
$scope.formVisable = true
|
||||
|
||||
$scope.sendUpdate = ->
|
||||
request = $http.post "/user/personal_info", $scope.userInfoForm
|
||||
request = $http.post "/user/settings", $scope.userInfoForm
|
||||
request.success (data, status)->
|
||||
request.error (data, status)->
|
||||
console.log "the request failed"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.account-settings {
|
||||
.alert {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
@@ -53,5 +53,6 @@
|
||||
|
||||
// ShareLaTeX app classes
|
||||
@import "app/base.less";
|
||||
@import "app/account-settings.less";
|
||||
@import "app/project-list.less";
|
||||
@import "app/editor.less";
|
||||
|
||||
@@ -95,6 +95,22 @@ describe "UserController", ->
|
||||
done()
|
||||
@UserController.updateUserSettings @req, @res
|
||||
|
||||
it "should set the role", (done)->
|
||||
@req.body =
|
||||
role: "student"
|
||||
@res.send = (code)=>
|
||||
@user.role.should.equal "student"
|
||||
done()
|
||||
@UserController.updateUserSettings @req, @res
|
||||
|
||||
it "should set the institution", (done)->
|
||||
@req.body =
|
||||
institution: "MIT"
|
||||
@res.send = (code)=>
|
||||
@user.institution.should.equal "MIT"
|
||||
done()
|
||||
@UserController.updateUserSettings @req, @res
|
||||
|
||||
it "should set some props on ace", (done)->
|
||||
@req.body =
|
||||
theme: "something"
|
||||
|
||||
@@ -124,51 +124,3 @@ describe "UserInfoController", ->
|
||||
institution: @user.institution
|
||||
}
|
||||
|
||||
describe "setPersonalInfo", ->
|
||||
|
||||
beforeEach ->
|
||||
@req =
|
||||
session:
|
||||
user:
|
||||
_id:"123123j321jikuj90jlk"
|
||||
@req.body =
|
||||
first_name: "bob"
|
||||
last_name: "smith"
|
||||
role:"student"
|
||||
institution: "Sheffield"
|
||||
notWanted: "something"
|
||||
|
||||
it "should send the data from the body to the user updater", (done)->
|
||||
|
||||
@UserUpdater.updatePersonalInfo.callsArgWith(2, null)
|
||||
@res.send = (statusCode)=>
|
||||
statusCode.should.equal 204
|
||||
@UserUpdater.updatePersonalInfo.args[0][0].should.equal @req.session.user._id
|
||||
args = @UserUpdater.updatePersonalInfo.args[0][1]
|
||||
args.first_name.should.equal @req.body.first_name
|
||||
args.last_name.should.equal @req.body.last_name
|
||||
args.role.should.equal @req.body.role
|
||||
args.institution.should.equal @req.body.institution
|
||||
assert.equal args.notWanted, undefined
|
||||
done()
|
||||
|
||||
@UserInfoController.updatePersonalInfo @req, @res
|
||||
|
||||
it "should sanitize the data", (done)->
|
||||
@UserUpdater.updatePersonalInfo.callsArgWith(2, null)
|
||||
@res.send = (statusCode)=>
|
||||
@sanitizer.escape.calledWith(@req.body.first_name).should.equal true
|
||||
@sanitizer.escape.calledWith(@req.body.last_name).should.equal true
|
||||
@sanitizer.escape.calledWith(@req.body.role).should.equal true
|
||||
@sanitizer.escape.calledWith(@req.body.institution).should.equal true
|
||||
done()
|
||||
@UserInfoController.updatePersonalInfo @req, @res
|
||||
|
||||
it "should send an error if the UpserUpdater returns on", (done)->
|
||||
@UserUpdater.updatePersonalInfo.callsArgWith(2, "error")
|
||||
@res.send = (statusCode)->
|
||||
statusCode.should.equal 500
|
||||
done()
|
||||
@UserInfoController.updatePersonalInfo @req, @res
|
||||
|
||||
|
||||
|
||||
@@ -46,39 +46,3 @@ describe "UserUpdater", ->
|
||||
@UserUpdater.updateUser.calledWith(@user_id, $set: { "email": @newEmail}).should.equal true
|
||||
done()
|
||||
|
||||
describe "updatePersonalInfo", ->
|
||||
|
||||
beforeEach ->
|
||||
@info =
|
||||
first_name:"billy"
|
||||
last_name:"brag"
|
||||
role:"student"
|
||||
institution:"sheffield"
|
||||
|
||||
it "should set the names role and institution", (done)->
|
||||
@UserUpdater.updateUser = sinon.stub().callsArgWith(2)
|
||||
@UserUpdater.updatePersonalInfo @user_id, @info, (err)=>
|
||||
@UserUpdater.updateUser.args[0][0].should.equal @user_id
|
||||
args = @UserUpdater.updateUser.args[0][1]
|
||||
args["$set"].first_name.should.equal @info.first_name
|
||||
args["$set"].last_name.should.equal @info.last_name
|
||||
args["$set"].role.should.equal @info.role
|
||||
args["$set"].institution.should.equal @info.institution
|
||||
done()
|
||||
|
||||
it "should return the error", (done)->
|
||||
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, "error")
|
||||
@UserUpdater.updatePersonalInfo @user_id, @info, (err)=>
|
||||
should.exist(err)
|
||||
done()
|
||||
|
||||
it "should default them to empty strings", (done)->
|
||||
@UserUpdater.updateUser = sinon.stub().callsArgWith(2)
|
||||
@UserUpdater.updatePersonalInfo @user_id, {}, (err)=>
|
||||
args = @UserUpdater.updateUser.args[0][1]
|
||||
args["$set"].first_name.should.equal ""
|
||||
args["$set"].last_name.should.equal ""
|
||||
args["$set"].role.should.equal ""
|
||||
args["$set"].institution.should.equal ""
|
||||
done()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user