mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Add sudo-mode 'confirm password' prompt
This commit is contained in:
parent
91f06cfc28
commit
029c96c7cc
4 changed files with 128 additions and 0 deletions
|
@ -0,0 +1,58 @@
|
||||||
|
UserLocator = require "../User/UserLocator"
|
||||||
|
Settings = require "settings-sharelatex"
|
||||||
|
logger = require 'logger-sharelatex'
|
||||||
|
SudoModeHandler = require './SudoModeHandler'
|
||||||
|
AuthenticationController = require '../Authentication/AuthenticationController'
|
||||||
|
AuthenticationManager = require '../Authentication/AuthenticationManager'
|
||||||
|
ObjectId = require('../../infrastructure/Mongoose').mongo.ObjectId
|
||||||
|
UserGetter = require '../User/UserGetter'
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = SudoModeController =
|
||||||
|
|
||||||
|
sudoModePrompt: (req, res, next) ->
|
||||||
|
userId = AuthenticationController.getLoggedInUserId(req)
|
||||||
|
logger.log {userId}, "[SudoMode] rendering sudo mode password page"
|
||||||
|
SudoModeHandler.isSudoModeActive userId, (err, isActive) ->
|
||||||
|
if err?
|
||||||
|
logger.err {err, userId}, "[SudoMode] error checking if sudo mode is active"
|
||||||
|
return next(err)
|
||||||
|
if isActive
|
||||||
|
logger.log {userId}, "[SudoMode] sudo mode already active, redirecting"
|
||||||
|
return res.redirect('/project')
|
||||||
|
res.render 'sudo_mode/sudo_mode_prompt', title: 'confirm_your_password'
|
||||||
|
|
||||||
|
submitPassword: (req, res, next) ->
|
||||||
|
userId = AuthenticationController.getLoggedInUserId(req)
|
||||||
|
redir = AuthenticationController._getRedirectFromSession(req) || "/project"
|
||||||
|
password = req.body.password
|
||||||
|
if !password
|
||||||
|
logger.log {userId}, "[SudoMode] no password supplied, failed authentication"
|
||||||
|
return next(new Error('no password supplied'))
|
||||||
|
logger.log {userId, redir}, "[SudoMode] checking user password"
|
||||||
|
UserGetter.getUser ObjectId(userId), {email: 1}, (err, userRecord) ->
|
||||||
|
if err?
|
||||||
|
logger.err {err, userId}, "[SudoMode] error getting user"
|
||||||
|
return next(err)
|
||||||
|
AuthenticationManager.authenticate email: userRecord.email, password, (err, user) ->
|
||||||
|
if err?
|
||||||
|
logger.err {err, userId}, "[SudoMode] error authenticating user"
|
||||||
|
return next(err)
|
||||||
|
if user?
|
||||||
|
logger.log {userId}, "[SudoMode] authenticated user, activating sudo mode"
|
||||||
|
SudoModeHandler.activateSudoMode userId, (err) ->
|
||||||
|
if err?
|
||||||
|
logger.err {err, userId}, "[SudoMode] error activating sudo mode"
|
||||||
|
return next(err)
|
||||||
|
return res.json {
|
||||||
|
redir: redir
|
||||||
|
}
|
||||||
|
else
|
||||||
|
logger.log {userId}, "[SudoMode] authentication failed for user"
|
||||||
|
return res.json {
|
||||||
|
message: {
|
||||||
|
text: req.i18n.translate("invalid_password"),
|
||||||
|
type: 'error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
RedisWrapper = require('../../infrastructure/RedisWrapper')
|
||||||
|
rclient = RedisWrapper.client('sudomode')
|
||||||
|
logger = require('logger-sharelatex')
|
||||||
|
|
||||||
|
|
||||||
|
TIMEOUT_IN_SECONDS = 60 * 10
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = SudoModeHandler =
|
||||||
|
|
||||||
|
_buildKey: (userId) ->
|
||||||
|
"SudoMode:{#{userId}}"
|
||||||
|
|
||||||
|
activateSudoMode: (userId, callback=(err)->) ->
|
||||||
|
if !userId?
|
||||||
|
return callback(new Error('[SudoMode] user must not be supplied'))
|
||||||
|
duration = TIMEOUT_IN_SECONDS
|
||||||
|
logger.log {userId, duration}, "[SudoMode] activating sudo mode for user"
|
||||||
|
rclient.set SudoModeHandler._buildKey(userId), '1', 'EX', duration, callback
|
||||||
|
|
||||||
|
isSudoModeActive: (userId, callback=(err, isActive)->) ->
|
||||||
|
if !userId?
|
||||||
|
return callback(new Error('[SudoMode] user must not be supplied'))
|
||||||
|
rclient.get SudoModeHandler._buildKey(userId), (err, result) ->
|
||||||
|
if err?
|
||||||
|
return callback(err)
|
||||||
|
callback(null, result == '1')
|
|
@ -38,6 +38,7 @@ ContactRouter = require("./Features/Contacts/ContactRouter")
|
||||||
ReferencesController = require('./Features/References/ReferencesController')
|
ReferencesController = require('./Features/References/ReferencesController')
|
||||||
AuthorizationMiddlewear = require('./Features/Authorization/AuthorizationMiddlewear')
|
AuthorizationMiddlewear = require('./Features/Authorization/AuthorizationMiddlewear')
|
||||||
BetaProgramController = require('./Features/BetaProgram/BetaProgramController')
|
BetaProgramController = require('./Features/BetaProgram/BetaProgramController')
|
||||||
|
SudoModeController = require('./Features/SudoMode/SudoModeController')
|
||||||
AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
|
AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
|
||||||
AnnouncementsController = require("./Features/Announcements/AnnouncementsController")
|
AnnouncementsController = require("./Features/Announcements/AnnouncementsController")
|
||||||
|
|
||||||
|
@ -238,6 +239,9 @@ module.exports = class Router
|
||||||
webRouter.get "/beta/participate", AuthenticationController.requireLogin(), BetaProgramController.optInPage
|
webRouter.get "/beta/participate", AuthenticationController.requireLogin(), BetaProgramController.optInPage
|
||||||
webRouter.post "/beta/opt-in", AuthenticationController.requireLogin(), BetaProgramController.optIn
|
webRouter.post "/beta/opt-in", AuthenticationController.requireLogin(), BetaProgramController.optIn
|
||||||
webRouter.post "/beta/opt-out", AuthenticationController.requireLogin(), BetaProgramController.optOut
|
webRouter.post "/beta/opt-out", AuthenticationController.requireLogin(), BetaProgramController.optOut
|
||||||
|
webRouter.get "/confirm-password", AuthenticationController.requireLogin(), SudoModeController.sudoModePrompt
|
||||||
|
webRouter.post "/confirm-password/submit", AuthenticationController.requireLogin(), SudoModeController.submitPassword
|
||||||
|
|
||||||
|
|
||||||
#Admin Stuff
|
#Admin Stuff
|
||||||
webRouter.get '/admin', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.index
|
webRouter.get '/admin', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.index
|
||||||
|
|
39
services/web/app/views/sudo_mode/sudo_mode_prompt.pug
Normal file
39
services/web/app/views/sudo_mode/sudo_mode_prompt.pug
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
extends ../layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
.content.content-alt
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
|
||||||
|
.card
|
||||||
|
.page-header.text-centered
|
||||||
|
h1 Confirm your password to continue
|
||||||
|
div
|
||||||
|
.container-fluid
|
||||||
|
.row
|
||||||
|
.col-md-8.col-md-offset-2
|
||||||
|
form(async-form="confirmPassword", name="confirmPassword",
|
||||||
|
action='/confirm-password/submit', method="POST", ng-cloak)
|
||||||
|
input(name='_csrf', type='hidden', value=csrfToken)
|
||||||
|
form-messages(for="confirmPassword")
|
||||||
|
.form-group
|
||||||
|
label
|
||||||
|
| #{translate('password')}
|
||||||
|
input.form-control(
|
||||||
|
type='password',
|
||||||
|
name='password',
|
||||||
|
required,
|
||||||
|
placeholder='********',
|
||||||
|
ng-model="password"
|
||||||
|
)
|
||||||
|
span.small.text-primary(
|
||||||
|
ng-show="confirmPassword.password.$invalid && confirmPassword.password.$dirty"
|
||||||
|
)
|
||||||
|
| #{translate("required")}
|
||||||
|
.actions
|
||||||
|
button.btn-primary.btn(
|
||||||
|
style="width: 100%",
|
||||||
|
type='submit',
|
||||||
|
ng-disabled="confirmPassword.inflight"
|
||||||
|
)
|
||||||
|
span #{translate("confirm")}
|
Loading…
Reference in a new issue