-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore(mellow-react): update dependencies * feat(mellow-react): add routes * feat(mellow-react): add actions * feat(mellow-react): add helpers * feat(mellow-react): add custom hook * feat(mellow-react): add sails mail * feat(mellow-react): add mail config * feat(mellow-vue): use integer id * fix(mellow-react): add url back * feat(mellow-react): add User model * feat(mellow-react): add policies * feat(mellow-react): register policy mappings * feat(mellow-react): add test * feat(mellow-react): update jsconfig * feat(mellow-react): add progressbar color * feat(mellow-react): add GoogleButton * feat(mellow-react): add homepage * feat(mellow-react): setup tailwindcss * chore(mellow-vue): revert to earliest version of prettier * feat(mellow-react): add GoogleButton.jsx * chore(mellow-react): update prettier-config.js * chore(mellow-react): remove typedoc * chore(mellow-vue): remove trailing space * chore(mellow-vue): remove jsdoc * chore(mellow-vue): prettier * chore(mellow-react): prettier * chore(mellow-react): prettier * feat(mellow-react): work on InputBase component * feat(mellow-react): add InputText Co-authored-by: Bayode Emmanuel <[email protected]> * feat(mellow-react): add InputBase * feat(mellow-react): add AppLayout * feat(mellow-react): update homepage * feat(mellow-react): rename to testing env * fix(mellow-react): update environment * fix(mellow-vue): update type in InputEmail * feat(mellow-react): add InputEmail component * feat(mellow-react): add InputPassword * feat(mellow-react): add InputButton * fix(mellow-react): remove unneeded markups * fix(mellow-react): use ternary * fix(mellow-react): passing in props * fix(mellow-vue): spread props * fix(mellow-react): remove manual value and onChange props * fix(mellow-react): fix not passing the input value * fix(mellow-react): resolve issue with check box * feat(mellow-react): submit login form * feat(mellow-react): add signup page * feat(mellow-react): add check-email page * feat(mellow-react): add success page * feat(mellow-react): add link-expired page * feat(mellow-vue): abstract style for inputs in input base * feat(mellow-vue): use components in forgot-password page * feat(mellow-react): add forgot-password page * fix(mellow-vue): add email error * feat(mellow-react): add forgot-password page * fix(mellow-react): fix wrong endpoint * feat(mellow-vue): proper usage of components * feat(mellow-react): add and use label prop * feat(mellow-react): add forms css * feat(mellow-react): add rest password page * fix(mellow-react): remove wrong function call * chore(mellow-react): remove component that no longer exist * feat(mellow-react): add dashboard * feat(mellow-vue): move profile to dashboard * fix(mellow-vue): fix deprecation for back redirect usage * chore(mellow-react): install sails-hook-organics * feat(mellow-react): fix depreaction warning for redirect usage * fix(mellow-react): rename dashboard to index * feat(mellow-react): add custom configs * feat(mellow-react): add email templates * feat(mellow-vue): go to dashboard/profile * feat(mellow-vue): remove user/profile.vue * feat(mellow-vue): remove unused config * feat(mellow-vue): use confirmPassword instead of passwordConfirmation * fix(mellow-react): use confirmPassword not passwordConfirmation * feat(mellow-react): use 'dashboard/profile' * fix(mellow-react): make it easy to merge classes * feat(mellow-react): add profile page * feat(mellow-react): fix issues with updating fields * fix(mellow-react): changed to undefined for forms * feat(mellow-vue): remove accessing user details with .value
- Loading branch information
1 parent
a4dd3bc
commit 747847c
Showing
87 changed files
with
4,830 additions
and
1,663 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-react/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: '[email protected]', | ||
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. "[email protected]".', | ||
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-react/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-react/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.