From f53790c452d7050aee039f342619d4db5dbabb5b Mon Sep 17 00:00:00 2001 From: yzx9 Date: Thu, 23 Nov 2023 17:06:44 +0800 Subject: [PATCH] Fix bugs --- ldap-overleaf-sl/Dockerfile | 7 +- .../sharelatex/AuthenticationController.js | 68 +++++++++---------- .../sharelatex/AuthenticationManager.js | 33 ++++++++- ldap-overleaf-sl/sharelatex/login.pug | 14 +++- ldap-overleaf-sl/sharelatex/router.js | 51 +++++++++----- 5 files changed, 110 insertions(+), 63 deletions(-) diff --git a/ldap-overleaf-sl/Dockerfile b/ldap-overleaf-sl/Dockerfile index eb134b2..620887b 100644 --- a/ldap-overleaf-sl/Dockerfile +++ b/ldap-overleaf-sl/Dockerfile @@ -42,13 +42,10 @@ COPY sharelatex/navbar.pug /overleaf/services/web/app/views/layout/ # Non LDAP User Registration for Admins COPY sharelatex/admin-index.pug /overleaf/services/web/app/views/admin/index.pug COPY sharelatex/admin-sysadmin.pug /tmp/admin-sysadmin.pug - - ## instead of copying the login.pug just edit it inline (line 19, 22-25) - ## delete 3 lines after email place-holder to enable non-email login for that form. -RUN sed -iE '/type=.*email.*/d' /overleaf/services/web/app/views/user/login.pug && \ + ## comment out this line to prevent sed accidently remove the brackets of the email(username) field # sed -iE '/email@example.com/{n;N;N;d}' /overleaf/services/web/app/views/user/login.pug && \ - sed -iE "s/email@example.com/${login_text:-user}/g" /overleaf/services/web/app/views/user/login.pug && \ +RUN sed -iE "s/email@example.com/${login_text:-user}/g" /overleaf/services/web/app/views/user/login.pug && \ ## Collaboration settings display (share project placeholder) | edit line 146 ## share.pug file was removed in later versions # sed -iE "s%placeholder=.*$%placeholder=\"${collab_text}\"%g" /overleaf/services/web/app/views/project/editor/share.pug && \ diff --git a/ldap-overleaf-sl/sharelatex/AuthenticationController.js b/ldap-overleaf-sl/sharelatex/AuthenticationController.js index 19534ee..36f21b5 100644 --- a/ldap-overleaf-sl/sharelatex/AuthenticationController.js +++ b/ldap-overleaf-sl/sharelatex/AuthenticationController.js @@ -275,81 +275,79 @@ const AuthenticationController = { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> oauth2Redirect(req, res, next) { const redirectURI = encodeURIComponent(`${process.env.SHARELATEX_SITE_URL}/oauth/callback`) - const next = ( + const authURL = ( process.env.OAUTH2_AUTHORIZATION_URL + `?response_type=code` + `&client_id=${process.env.OAUTH2_CLIENT_ID}` + `&redirect_uri=${redirectURI}` + `&scope=${process.env.OAUTH2_SCOPE ?? ""}` // TODO: state ) - res.redirect(next) + res.redirect(authURL) }, async oauth2Callback(req, res, next) { try { - const redirectURI = encodeURIComponent(`${process.env.SHARELATEX_SITE_URL}/oauth/callback`); + console.log("OAuth2 code", req.query.code) const tokenResponse = await fetch(process.env.OAUTH2_TOKEN_URL, { method: 'POST', headers: { - 'Content-Type': 'application/json' + "Accept": "application/json", + "Content-Type": "application/json", }, body: JSON.stringify({ grant_type: "authorization_code", client_id: process.env.OAUTH2_CLIENT_ID, client_secret: process.env.OAUTH2_CLIENT_SECRET, code: req.query.code, - redirect_uri: redirectURI, + redirect_uri: `${process.env.SHARELATEX_SITE_URL}/oauth/callback`, }) }) const tokenData = await tokenResponse.json() - console.log("OAuth2 respond", JSON.stringify(tokenData)) // TODO: remove - console.log("OAuth2 accessToken", tokenData.access_token) // TODO: remove + console.log("OAuth2 respond", JSON.stringify(tokenData)) const profileResponse = await fetch(process.env.OAUTH2_PROFILE_URL, { method: 'GET', headers: { + "Accept": "application/json", + "Authorization": `Bearer ${tokenData.access_token}`, "Content-Type": "application/json", - "Authorization": `Bearer ${tokenData.access_token}` } }) const profile = await profileResponse.json() - console.log("OAuth2 user info", JSON.stringify(profile.data)) + console.log("OAuth2 user profile", JSON.stringify(profile)) const email = profile[process.env.OAUTH2_USER_ATTR_EMAIL ?? "email"] const uid = profile[process.env.OAUTH2_USER_ATTR_UID ?? "uid"] const firstname = profile?.[process.env.OAUTH2_USER_ATTR_FIRSTNAME] ?? email - const lastname = profile?.[process.env.OAUTH2_USER_ATTR_LASTNAME] ?? "" - - const isAdmin = false // TODO: how to determine? + const lastname = process.env.OAUTH2_USER_ATTR_LASTNAME + ? profile?.[process.env.OAUTH2_USER_ATTR_LASTNAME] ?? "" + : "" + const isAdmin = process.env.OAUTH2_USER_ATTR_IS_ADMIN + ? !!profile?.[process.env.OAUTH2_USER_ATTR_IS_ADMIN] ?? false + : false const query = { email } - User.findOne(query, (error, user) => { + const callback = (error, user) => { if (error) { - console.log(error) + res.json({message: error}); + } else { + console.log("OAuth user", JSON.stringify(user)); + AuthenticationController.finishLogin(user, req, res, next); } - - const callback = (error, user) => { - if (error) { - res.json({message: error}); - } else { - // console.log("real_user: ", user); - AuthenticationController.finishLogin(user, req, res, next); - } - } - AuthenticationManager.createIfNotExistAndLogin( - query, - user, - callback, - uid, - firstname, - lastname, - email, - isAdmin - ) - }) + } + AuthenticationManager.createIfNotFoundAndLogin( + query, + callback, + uid, + firstname, + lastname, + email, + isAdmin + ) } catch(e) { - console.log("Fails to access by OAuth2: " + String(e)) + res.redirect("/login") + console.error("Fails to access by OAuth2: " + String(e)) } }, // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js index 5f474c6..bd2741e 100644 --- a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js +++ b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js @@ -184,6 +184,33 @@ const AuthenticationManager = { callback(null, user, true) }, + createIfNotFoundAndLogin( + query, + callback, + uid, + firstname, + lastname, + mail, + isAdmin + ) { + User.findOne(query, (error, user) => { + if (error) { + console.log(error) + } + + AuthenticationManager.createIfNotExistAndLogin( + query, + user, + callback, + uid, + firstname, + lastname, + mail, + isAdmin + ) + }) + }, + createIfNotExistAndLogin( query, user, @@ -195,10 +222,9 @@ const AuthenticationManager = { isAdmin ) { if (!user) { - //console.log('Creating User:' + JSON.stringify(query)) //create random pass for local userdb, does not get checked for ldap users during login - let pass = require("crypto").randomBytes(32).toString("hex") - //console.log('Creating User:' + JSON.stringify(query) + 'Random Pass' + pass) + const pass = require("crypto").randomBytes(32).toString("hex") + console.log('Creating User', { mail, uid, firstname, lastname, isAdmin, pass }) const userRegHand = require("../User/UserRegistrationHandler.js") userRegHand.registerNewUser( @@ -228,6 +254,7 @@ const AuthenticationManager = { } ) // end register user } else { + console.log('User exists', { mail }) AuthenticationManager.login(user, "randomPass", callback) } }, diff --git a/ldap-overleaf-sl/sharelatex/login.pug b/ldap-overleaf-sl/sharelatex/login.pug index 6705e17..80f8010 100644 --- a/ldap-overleaf-sl/sharelatex/login.pug +++ b/ldap-overleaf-sl/sharelatex/login.pug @@ -16,13 +16,21 @@ block content input(name='_csrf', type='hidden', value=csrfToken) +formMessages() .form-group + //- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + //- input.form-control( + //- type='email', + //- name='email', + //- required, + //- placeholder='email@example.com', + //- autofocus="true" + //- ) input.form-control( - type='email', name='email', required, placeholder='email@example.com', autofocus="true" ) + //- <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .form-group input.form-control( type='password', @@ -38,8 +46,8 @@ block content span(data-ol-inflight="idle") #{translate("login")} span(hidden data-ol-inflight="pending") #{translate("logging_in")}… a.pull-right(href='/user/password/reset') #{translate("forgot_your_password")}? - //- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + //- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .form-group.text-center(style="padding-top: 10px") a.btn-block.login-btn(href="/oauth/redirect" style='padding-left: 0px') | Log in via OAuth - //- <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + //- <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/ldap-overleaf-sl/sharelatex/router.js b/ldap-overleaf-sl/sharelatex/router.js index a424756..71c91f8 100644 --- a/ldap-overleaf-sl/sharelatex/router.js +++ b/ldap-overleaf-sl/sharelatex/router.js @@ -1,6 +1,6 @@ /** * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - * Modified from 6408d15 + * Modified from bf92436 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ @@ -27,7 +27,6 @@ const UserInfoController = require('./Features/User/UserInfoController') const UserController = require('./Features/User/UserController') const UserEmailsController = require('./Features/User/UserEmailsController') const UserPagesController = require('./Features/User/UserPagesController') -const TutorialController = require('./Features/Tutorial/TutorialController') const DocumentController = require('./Features/Documents/DocumentController') const CompileManager = require('./Features/Compile/CompileManager') const CompileController = require('./Features/Compile/CompileController') @@ -105,6 +104,10 @@ const rateLimiters = { points: 10, duration: 60, }), + confirmUniversityDomain: new RateLimiter('confirm-university-domain', { + points: 1, + duration: 60, + }), createProject: new RateLimiter('create-project', { points: 20, duration: 60, @@ -149,6 +152,10 @@ const rateLimiters = { points: 30, duration: 60, }), + indexProjectReferences: new RateLimiter('index-project-references', { + points: 30, + duration: 60, + }), miscOutputDownload: new RateLimiter('misc-output-download', { points: 1000, duration: 60 * 60, @@ -185,7 +192,7 @@ const rateLimiters = { duration: 60, }), resendConfirmation: new RateLimiter('resend-confirmation', { - points: 1, + points: 10, duration: 60, }), sendChatMessage: new RateLimiter('send-chat-message', { @@ -256,12 +263,12 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) { AuthenticationController.addEndpointToLoginWhitelist('/register') } -// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -webRouter.get('/oauth/redirect', AuthenticationController.oauth2Redirect) -webRouter.get('/oauth/callback', AuthenticationController.oauth2Callback) -AuthenticationController.addEndpointToLoginWhitelist('/oauth/redirect') -AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + webRouter.get('/oauth/redirect', AuthenticationController.oauth2Redirect) + webRouter.get('/oauth/callback', AuthenticationController.oauth2Callback) + AuthenticationController.addEndpointToLoginWhitelist('/oauth/redirect') + AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') + // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< EditorRouter.apply(webRouter, privateApiRouter) CollaboratorsRouter.apply(webRouter, privateApiRouter) @@ -433,12 +440,6 @@ AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') TpdsController.getQueues ) - webRouter.post( - '/tutorial/:tutorialKey/complete', - AuthenticationController.requireLogin(), - TutorialController.completeTutorial - ) - webRouter.get( '/user/projects', AuthenticationController.requireLogin(), @@ -734,6 +735,16 @@ AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') AuthorizationMiddleware.ensureUserCanReadProject, HistoryController.proxyToHistoryApi ) + webRouter.post( + '/project/:Project_id/doc/:doc_id/version/:version_id/restore', + AuthorizationMiddleware.ensureUserCanWriteProjectContent, + HistoryController.proxyToHistoryApi + ) + webRouter.post( + '/project/:project_id/doc/:doc_id/restore', + AuthorizationMiddleware.ensureUserCanWriteProjectContent, + HistoryController.restoreDocFromDeletedDoc + ) webRouter.post( '/project/:project_id/restore_file', AuthorizationMiddleware.ensureUserCanWriteProjectContent, @@ -1082,6 +1093,12 @@ AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') ChatController.sendMessage ) + webRouter.post( + '/project/:Project_id/references/index', + AuthorizationMiddleware.ensureUserCanReadProject, + RateLimiterMiddleware.rateLimit(rateLimiters.indexProjectReferences), + ReferencesController.index + ) webRouter.post( '/project/:Project_id/references/indexAll', AuthorizationMiddleware.ensureUserCanReadProject, @@ -1130,6 +1147,7 @@ AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') ) publicApiRouter.post( '/api/institutions/confirm_university_domain', + RateLimiterMiddleware.rateLimit(rateLimiters.confirmUniversityDomain), AuthenticationController.requirePrivateApiAuth(), InstitutionsController.confirmDomain ) @@ -1357,5 +1375,4 @@ AuthenticationController.addEndpointToLoginWhitelist('/oauth/callback') webRouter.get('*', ErrorController.notFound) } - -module.exports = { initialize, rateLimiters } \ No newline at end of file +module.exports = { initialize, rateLimiters }