mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 21:23:45 +01:00
109 lines
4.1 KiB
JavaScript
109 lines
4.1 KiB
JavaScript
import Settings from '@overleaf/settings'
|
|
import UserCreator from '../../../../../app/src/Features/User/UserCreator.mjs'
|
|
import ThirdPartyIdentityManager from '../../../../../app/src/Features/User/ThirdPartyIdentityManager.js'
|
|
import { ParallelLoginError } from '../../../../../app/src/Features/Authentication/AuthenticationErrors.js'
|
|
import { User } from '../../../../../app/src/models/User.js'
|
|
|
|
const OIDCAuthenticationManager = {
|
|
async findOrCreateUser(profile, auditLog) {
|
|
const {
|
|
attUserId,
|
|
attAdmin,
|
|
valAdmin,
|
|
updateUserDetailsOnLogin,
|
|
providerId,
|
|
} = Settings.oidc
|
|
const email = profile.emails[0].value
|
|
const oidcUserId = (attUserId === 'email') ? email : profile[attUserId]
|
|
const firstName = profile.name?.givenName || ""
|
|
const lastName = profile.name?.familyName || ""
|
|
let isAdmin = false
|
|
if (attAdmin && valAdmin) {
|
|
if (attAdmin === 'email') {
|
|
isAdmin = (email === valAdmin)
|
|
} else {
|
|
isAdmin = (profile[attAdmin] === valAdmin)
|
|
}
|
|
}
|
|
const oidcUserData = null // Possibly it can be used later
|
|
let user
|
|
try {
|
|
user = await ThirdPartyIdentityManager.promises.login(providerId, oidcUserId, oidcUserData)
|
|
} catch {
|
|
// A user with the specified OIDC ID and provider ID is not found. Search for a user with the given email.
|
|
// If no user exists with this email, create a new user and link the OIDC account to it (provided this is allowed by allowedOIDCEmailDomains).
|
|
// If a user exists but no account from the specified OIDC provider is linked to this user, link the OIDC account to this user.
|
|
// If an account from the specified provider is already linked to this user, unlink it, and link the OIDC account to this user.
|
|
// (Is it safe? Concider: If an account from the specified provider is already linked to this user, throw an error)
|
|
user = await User.findOne({ 'email': email }).exec()
|
|
if (!user) {
|
|
const allowedDomains = Settings.oidc.allowedOIDCEmailDomains
|
|
if (
|
|
allowedDomains &&
|
|
!allowedDomains.some(pattern => {
|
|
const domain = email.split('@')[1]
|
|
if (pattern.startsWith('*.')) {
|
|
const base = pattern.slice(2)
|
|
return domain.endsWith(`.${base}`)
|
|
}
|
|
return domain === pattern
|
|
})
|
|
) {
|
|
return null
|
|
}
|
|
user = await UserCreator.promises.createNewUser(
|
|
{
|
|
email: email,
|
|
first_name: firstName,
|
|
last_name: lastName,
|
|
isAdmin: isAdmin,
|
|
holdingAccount: false,
|
|
}
|
|
)
|
|
}
|
|
// const alreadyLinked = user.thirdPartyIdentifiers.some(item => item.providerId === providerId)
|
|
// if (!alreadyLinked) {
|
|
auditLog.initiatorId = user._id
|
|
await ThirdPartyIdentityManager.promises.link(user._id, providerId, oidcUserId, oidcUserData, auditLog)
|
|
await User.updateOne(
|
|
{ _id: user._id },
|
|
{ $set : {
|
|
'emails.0.confirmedAt': Date.now(), //email of external user is confirmed
|
|
},
|
|
}
|
|
).exec()
|
|
// } else {
|
|
// throw new Error(`Overleaf user ${user.email} is already linked to another ${providerId} user`)
|
|
// }
|
|
}
|
|
|
|
let userDetails = updateUserDetailsOnLogin ? { first_name : firstName, last_name: lastName } : {}
|
|
if (attAdmin && valAdmin) {
|
|
user.isAdmin = isAdmin
|
|
userDetails.isAdmin = isAdmin
|
|
}
|
|
const result = await User.updateOne(
|
|
{ _id: user._id, loginEpoch: user.loginEpoch }, { $inc: { loginEpoch: 1 }, $set: userDetails },
|
|
{}
|
|
).exec()
|
|
|
|
if (result.modifiedCount !== 1) {
|
|
throw new ParallelLoginError()
|
|
}
|
|
return user
|
|
},
|
|
async linkAccount(userId, profile, auditLog) {
|
|
const {
|
|
attUserId,
|
|
providerId,
|
|
} = Settings.oidc
|
|
const oidcUserId = (attUserId === 'email') ? profile.emails[0].value : profile[attUserId]
|
|
const oidcUserData = null // Possibly it can be used later
|
|
await ThirdPartyIdentityManager.promises.link(userId, providerId, oidcUserId, oidcUserData, auditLog)
|
|
},
|
|
}
|
|
|
|
export default {
|
|
promises: OIDCAuthenticationManager,
|
|
}
|