-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1027392
commit 9857406
Showing
22 changed files
with
878 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
module.exports = { | ||
friendlyName: 'Callback', | ||
|
||
description: 'Callback auth.', | ||
|
||
inputs: { | ||
provider: { | ||
isIn: ['google'], | ||
required: true | ||
}, | ||
code: { | ||
type: 'string', | ||
required: true | ||
} | ||
}, | ||
|
||
exits: { | ||
success: { | ||
responseType: 'redirect' | ||
} | ||
}, | ||
fn: async function ({ code, provider }, exits) { | ||
const req = this.req | ||
const googleUser = await sails.wish.provider(provider).user(code) | ||
|
||
User.findOrCreate( | ||
{ or: [{ googleId: googleUser.id }, { email: googleUser.email }] }, | ||
{ | ||
googleId: googleUser.id, | ||
email: googleUser.email, | ||
fullName: googleUser.name, | ||
googleAvatarUrl: googleUser.picture, | ||
googleAccessToken: googleUser.accessToken, | ||
googleIdToken: googleUser.idToken, | ||
emailStatus: googleUser.verified_email ? 'verified' : 'unverified' | ||
} | ||
).exec(async (error, user, wasCreated) => { | ||
if (error) throw error | ||
|
||
if (!wasCreated && googleUser.verified_email) { | ||
await User.updateOne({ id: user.id }).set({ | ||
emailStatus: 'verified' | ||
}) | ||
} | ||
if (!wasCreated && user.googleId !== googleUser.id) { | ||
// Checks if the user email has changed since last log in | ||
// And then update the email change candidate which will be used be used to prompt the user to update their email | ||
await User.updateOne({ id: user.id }).set({ | ||
emailChangeCandidate: googleUser.email | ||
}) | ||
} | ||
if (!wasCreated && user.email !== googleUser.email) { | ||
// Checks if the user email has changed since last log in | ||
// And then update the email change candidate which will be used be used to prompt the user to update their email | ||
await User.updateOne({ id: user.id }).set({ | ||
emailChangeCandidate: googleUser.email | ||
}) | ||
} | ||
|
||
// Checks if the user name has changed since last log in | ||
// And then update the name if changed | ||
if (!wasCreated && user.fullName !== googleUser.name) { | ||
await User.updateOne({ id: user.id }).set({ | ||
fullName: googleUser.name | ||
}) | ||
} | ||
|
||
if (!wasCreated && user.googleAvatarUrl !== googleUser.picture) { | ||
await User.updateOne({ id: user.id }).set({ | ||
googleAvatarUrl: googleUser.picture | ||
}) | ||
} | ||
|
||
if (!wasCreated && user.googleAccessToken !== googleUser.accessToken) { | ||
await User.updateOne({ id: user.id }).set({ | ||
googleAccessToken: googleUser.accessToken | ||
}) | ||
} | ||
|
||
if (!wasCreated && user.googleIdToken !== googleUser.idToken) { | ||
await User.updateOne({ id: user.id }).set({ | ||
googleIdToken: googleUser.idToken | ||
}) | ||
} | ||
|
||
req.session.userId = user.id | ||
const urlToRedirectTo = '/dashboard' | ||
return exits.success(urlToRedirectTo) | ||
}) | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
templates/mellow-svelte/api/controllers/auth/forgot-password.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
module.exports = { | ||
friendlyName: 'Forgot password', | ||
|
||
description: | ||
'Send a password recovery notification to the user with the specified email address.', | ||
|
||
inputs: { | ||
email: { | ||
description: | ||
'The email address of the alleged user who wants to recover their password.', | ||
example: 'kelvin@boringstack.com', | ||
type: 'string', | ||
required: true, | ||
isEmail: true | ||
} | ||
}, | ||
|
||
exits: { | ||
success: { | ||
description: | ||
'The email address might have matched a user in the database. (If so, a recovery email was sent.)', | ||
responseType: 'redirect' | ||
} | ||
}, | ||
|
||
fn: async function ({ email }) { | ||
const userExists = await User.count({ email: this.req.session.userEmail }) | ||
if (!userExists) { | ||
return '/check-email' | ||
} | ||
|
||
const token = await sails.helpers.strings.random('url-friendly') | ||
|
||
const user = await User.updateOne({ email }).set({ | ||
passwordResetToken: token, | ||
passwordResetTokenExpiresAt: | ||
Date.now() + sails.config.custom.passwordResetTokenTTL | ||
}) | ||
|
||
await sails.helpers.mail.send.with({ | ||
to: user.email, | ||
subject: 'Password reset instructions', | ||
template: 'email-reset-password', | ||
templateData: { | ||
fullName: user.fullName, | ||
token | ||
} | ||
}) | ||
|
||
this.req.session.userEmail = user.email | ||
return '/check-email' | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
module.exports = { | ||
friendlyName: 'Login', | ||
|
||
description: 'Log in using the provided email and password combination.', | ||
|
||
extendedDescription: `This action attempts to look up the user record in the database with the | ||
specified email address. Then, if such a user exists, it uses | ||
bcrypt to compare the hashed password from the database with the provided | ||
password attempt.`, | ||
|
||
inputs: { | ||
email: { | ||
description: 'The email to try in this attempt, e.g. "irl@example.com".', | ||
type: 'string', | ||
isEmail: true, | ||
required: true | ||
}, | ||
|
||
password: { | ||
description: | ||
'The unencrypted password to try in this attempt, e.g. "passwordlol".', | ||
type: 'string', | ||
required: true | ||
}, | ||
|
||
rememberMe: { | ||
description: "Whether to extend the lifetime of the user's session.", | ||
type: 'boolean' | ||
} | ||
}, | ||
|
||
exits: { | ||
success: { | ||
description: 'The requesting user agent has been successfully logged in.', | ||
extendedDescription: `Under the covers, this stores the id of the logged-in user in the session | ||
as the \`userId\` key. The next time this user agent sends a request, assuming | ||
it includes a cookie (like a web browser), Sails will automatically make this | ||
user id available as req.session.userId in the corresponding action. (Also note | ||
that, thanks to the included "custom" hook, when a relevant request is received | ||
from a logged-in user, that user's entire record from the database will be fetched | ||
and exposed as a shared data via loggedInUser prop.)`, | ||
responseType: 'redirect' | ||
}, | ||
badCombo: { | ||
responseType: 'badRequest' | ||
} | ||
}, | ||
|
||
fn: async function ({ email, password, rememberMe }) { | ||
const user = await User.findOne({ | ||
email: email.toLowerCase() | ||
}) | ||
|
||
if (!user) { | ||
throw { | ||
badCombo: { | ||
problems: [{ login: 'Wrong email/password.' }] | ||
} | ||
} | ||
} | ||
|
||
try { | ||
await sails.helpers.passwords.checkPassword(password, user.password) | ||
} catch (e) { | ||
sails.log.error(e.message) | ||
throw { | ||
badCombo: { | ||
problems: [{ login: 'Wrong email/password.' }] | ||
} | ||
} | ||
} | ||
|
||
if (rememberMe) { | ||
this.req.session.cookie.maxAge = | ||
sails.config.custom.rememberMeCookieMaxAge | ||
} | ||
|
||
this.req.session.userId = user.id | ||
return '/dashboard' | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module.exports = { | ||
friendlyName: 'Redirect', | ||
|
||
description: 'Redirect auth.', | ||
|
||
inputs: { | ||
provider: { | ||
isIn: ['google'], | ||
required: true | ||
} | ||
}, | ||
|
||
exits: { | ||
success: { | ||
responseType: 'redirect' | ||
} | ||
}, | ||
|
||
fn: async function ({ provider }) { | ||
return sails.wish.provider(provider).redirect() | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
templates/mellow-svelte/api/controllers/auth/resend-link.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module.exports = { | ||
friendlyName: 'Resend link', | ||
|
||
description: '', | ||
|
||
inputs: {}, | ||
|
||
exits: { | ||
success: { | ||
responseType: 'redirect' | ||
}, | ||
userNotFound: { | ||
responseType: 'notFound' | ||
} | ||
}, | ||
|
||
fn: async function () { | ||
const userExists = await User.count({ email: this.req.session.userEmail }) | ||
if (!userExists) { | ||
return '/check-email' | ||
} | ||
const unverifiedUser = await User.updateOne(this.req.session.userEmail).set( | ||
{ | ||
emailStatus: 'unverified', | ||
emailProofToken: sails.helpers.strings.random('url-friendly'), | ||
emailProofTokenExpiresAt: | ||
Date.now() + sails.config.custom.emailProofTokenTTL | ||
} | ||
) | ||
|
||
this.req.session.userId = unverifiedUser.id | ||
|
||
await sails.helpers.mail.send.with({ | ||
subject: 'Verify your email', | ||
template: 'email-verify-account', | ||
to: unverifiedUser.email, | ||
templateData: { | ||
token: unverifiedUser.emailProofToken, | ||
fullName: unverifiedUser.fullName | ||
} | ||
}) | ||
return '/check-email' | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
templates/mellow-svelte/api/controllers/auth/reset-password.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
module.exports = { | ||
friendlyName: 'Reset password', | ||
|
||
description: '', | ||
|
||
inputs: { | ||
token: { | ||
description: 'The verification token from the email.', | ||
example: 'lyCap0N9i8wKYz7rhrEPog' | ||
}, | ||
password: { | ||
type: 'string', | ||
required: true, | ||
minLength: 8 | ||
} | ||
}, | ||
|
||
exits: { | ||
success: { | ||
responseType: 'redirect' | ||
}, | ||
invalidOrExpiredToken: { | ||
responseType: 'expired', | ||
description: 'The provided token is expired, invalid, or already used up.' | ||
}, | ||
badSignupRequest: { | ||
responseType: 'badRequest', | ||
description: | ||
'The provided fullName, password and/or email address are invalid.', | ||
extendedDescription: | ||
'If this request was sent from a graphical user interface, the request ' + | ||
'parameters should have been validated/coerced _before_ they were sent.' | ||
} | ||
}, | ||
|
||
fn: async function ({ token, password }) { | ||
if (!token) { | ||
throw 'invalidOrExpiredToken' | ||
} | ||
|
||
const user = await User.findOne({ passwordResetToken: token }) | ||
|
||
if (!user || user.passwordResetTokenExpiresAt <= Date.now()) { | ||
throw 'invalidOrExpiredToken' | ||
} | ||
await User.updateOne({ id: user.id }).set({ | ||
password, | ||
passwordResetToken: '', | ||
passwordResetTokenExpiresAt: 0 | ||
}) | ||
|
||
this.req.session.userId = user.id | ||
|
||
delete this.req.session.userEmail | ||
|
||
return '/reset-password/success' | ||
} | ||
} |
Oops, something went wrong.