* Helper function that contains the shared post-profile OAuth logic * (supports OAuth 1.0a and OAuth 2.0 providers). * Returns User (new or updated) on success or throws Error on failure.
(req, accessToken, refreshToken, providerName, params, providerProfile, sessionAlreadyLoggedIn, tokenSecret, oauth2provider, tokenConfig = {}, refreshTokenExpiration = null)
| 81 | * Returns User (new or updated) on success or throws Error on failure. |
| 82 | */ |
| 83 | async function handleAuthLogin(req, accessToken, refreshToken, providerName, params, providerProfile, sessionAlreadyLoggedIn, tokenSecret, oauth2provider, tokenConfig = {}, refreshTokenExpiration = null) { |
| 84 | if (sessionAlreadyLoggedIn) { |
| 85 | const existingUser = await User.findOne({ |
| 86 | [providerName]: { $eq: providerProfile.id }, |
| 87 | }); |
| 88 | if (existingUser && existingUser.id !== req.user.id) { |
| 89 | throw new Error('PROVIDER_COLLISION'); |
| 90 | } |
| 91 | let user; |
| 92 | if (oauth2provider) { |
| 93 | user = await saveOAuth2UserTokens(req, accessToken, refreshToken, params.expires_in, refreshTokenExpiration, providerName, tokenConfig); |
| 94 | } else { |
| 95 | user = await User.findById(req.user.id); |
| 96 | user.tokens.push({ kind: providerName, accessToken, ...(tokenSecret && { tokenSecret }) }); |
| 97 | } |
| 98 | user[providerName] = providerProfile.id; |
| 99 | user.profile.name = user.profile.name || providerProfile.name; |
| 100 | user.profile.gender = user.profile.gender || providerProfile.gender; |
| 101 | |
| 102 | if (providerProfile.picture) { |
| 103 | if (!user.profile.pictures || user.profile.pictureSource === undefined) { |
| 104 | // legacy account (pre-multi-picture support) |
| 105 | user.profile.pictures = new Map(); |
| 106 | user.profile.picture = providerProfile.picture; |
| 107 | user.profile.pictureSource = providerName; |
| 108 | } |
| 109 | user.profile.pictures.set(providerName, providerProfile.picture); |
| 110 | if (user.profile.pictureSource === 'gravatar') { |
| 111 | user.profile.picture = providerProfile.picture; |
| 112 | user.profile.pictureSource = providerName; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | user.profile.location = user.profile.location || providerProfile.location; |
| 117 | user.profile.website = user.profile.website || providerProfile.website; |
| 118 | user.profile.email = user.profile.email || providerProfile.email; |
| 119 | await user.save(); |
| 120 | return user; |
| 121 | } |
| 122 | // User is not logged in: |
| 123 | const existingUser = await User.findOne({ [providerName]: { $eq: providerProfile.id } }); |
| 124 | if (existingUser) { |
| 125 | return existingUser; |
| 126 | } |
| 127 | const normalizedEmail = providerProfile.email ? validator.normalizeEmail(providerProfile.email, { gmail_remove_dots: false }) : undefined; |
| 128 | if (!normalizedEmail) { |
| 129 | throw new Error('EMAIL_REQUIRED'); |
| 130 | } |
| 131 | const existingEmailUser = await User.findOne({ |
| 132 | email: { $eq: normalizedEmail }, |
| 133 | }); |
| 134 | if (existingEmailUser) { |
| 135 | throw new Error('EMAIL_COLLISION'); |
| 136 | } |
| 137 | const user = new User(); |
| 138 | user.email = normalizedEmail; |
| 139 | user[providerName] = providerProfile.id; |
| 140 | req.user = user; |
no test coverage detected