chore(backend): Use signin instead of login
This commit is contained in:
parent
2c2961144a
commit
34de608351
14 changed files with 178 additions and 81 deletions
|
@ -391,8 +391,8 @@ Also: Introvert 🙊
|
||||||
example: 'en',
|
example: 'en',
|
||||||
enum: ['en', 'es', 'de', 'fr', 'nl'],
|
enum: ['en', 'es', 'de', 'fr', 'nl'],
|
||||||
},
|
},
|
||||||
lastLogin: {
|
lastSignIn: {
|
||||||
description: 'Timestamp of when the User last authenticated, in ISO 8601 format.',
|
description: 'Timestamp of when the User last signed in, in ISO 8601 format.',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
example: '2022-12-18T18:14:30.460Z',
|
example: '2022-12-18T18:14:30.460Z',
|
||||||
},
|
},
|
||||||
|
@ -462,7 +462,7 @@ for (const remove of [
|
||||||
'email',
|
'email',
|
||||||
'github',
|
'github',
|
||||||
'initial',
|
'initial',
|
||||||
'lastLogin',
|
'lastSignIn',
|
||||||
'lusername',
|
'lusername',
|
||||||
'mfaEnabled',
|
'mfaEnabled',
|
||||||
'newsletter',
|
'newsletter',
|
||||||
|
|
|
@ -24,7 +24,7 @@ import {
|
||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
const common = {
|
const common = {
|
||||||
tags: ['Signup & Login'],
|
tags: ['Sign Up & Sign In'],
|
||||||
security: [jwt, key],
|
security: [jwt, key],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,10 @@ const local = {
|
||||||
// Paths
|
// Paths
|
||||||
export const paths = {}
|
export const paths = {}
|
||||||
|
|
||||||
// Create account (signup)
|
// Create account (sign up)
|
||||||
paths['/signup'] = {
|
paths['/signup'] = {
|
||||||
post: {
|
post: {
|
||||||
tags: ['Signup & Login'],
|
tags: ['Sign Up & Sign In'],
|
||||||
summary: 'Sign up for a FreeSewing account',
|
summary: 'Sign up for a FreeSewing account',
|
||||||
description:
|
description:
|
||||||
'Creates a new inactive account. The account will require confirmation via a link sent to the email address that the user submitted.',
|
'Creates a new inactive account. The account will require confirmation via a link sent to the email address that the user submitted.',
|
||||||
|
@ -114,7 +114,7 @@ paths['/signup'] = {
|
||||||
// Confirm account
|
// Confirm account
|
||||||
paths['/confirm/signup/{id}'] = {
|
paths['/confirm/signup/{id}'] = {
|
||||||
post: {
|
post: {
|
||||||
tags: ['Signup & Login'],
|
tags: ['Sign Up & Sign In'],
|
||||||
parameters: [local.params.id],
|
parameters: [local.params.id],
|
||||||
summary: 'Confirm a FreeSewing account',
|
summary: 'Confirm a FreeSewing account',
|
||||||
description: 'Confirmes a new inactive account.',
|
description: 'Confirmes a new inactive account.',
|
||||||
|
@ -152,13 +152,13 @@ paths['/confirm/signup/{id}'] = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login
|
// Sign In
|
||||||
paths['/login'] = {
|
paths['/signin'] = {
|
||||||
post: {
|
post: {
|
||||||
tags: ['Signup & Login'],
|
tags: ['Sign Up & Sign In'],
|
||||||
summary: 'Log in to a FreeSewing account',
|
summary: 'Sign in to a FreeSewing account',
|
||||||
description:
|
description:
|
||||||
"Logs in to an existing and active account. If MFA is enabled, you must also send the `token`. <br>The `username` field used for the login can contain one the User's `username`, `email`, or `id`.",
|
"Signs in to an existing and active account. If MFA is enabled, you must also send the `token`. <br>The `username` field used for the sign in can contain one the User's `username`, `email`, or `id`.",
|
||||||
requestBody: {
|
requestBody: {
|
||||||
required: true,
|
required: true,
|
||||||
content: {
|
content: {
|
||||||
|
@ -195,6 +195,45 @@ paths['/login'] = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send sign In Link
|
||||||
|
paths['/signinlink'] = {
|
||||||
|
post: {
|
||||||
|
tags: ['Sign Up & Sign In'],
|
||||||
|
summary: 'Send a sign in link via email (aka magic link)',
|
||||||
|
description:
|
||||||
|
"Sends an email containing a sign in link that will sign in the user without the need for a password (also known as a 'magic link'). <br>The `username` field used for the sign in can contain one the User's `username`, `email`, or `id`.",
|
||||||
|
requestBody: {
|
||||||
|
required: true,
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
username: response.body.userAccount.properties.email,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
...response.status['200'],
|
||||||
|
...jsonResponse({
|
||||||
|
result: { ...fields.result, example: 'sent' },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
...response.status['400'],
|
||||||
|
description:
|
||||||
|
response.status['400'].description +
|
||||||
|
errorExamples(['postBodyMissing', 'usernameMissing']),
|
||||||
|
},
|
||||||
|
401: response.status['401'],
|
||||||
|
500: response.status['500'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Load user account
|
// Load user account
|
||||||
paths['/account/{auth}'] = {
|
paths['/account/{auth}'] = {
|
||||||
get: {
|
get: {
|
||||||
|
@ -209,10 +248,7 @@ paths['/account/{auth}'] = {
|
||||||
'**Success - Account data returned**\n\n' +
|
'**Success - Account data returned**\n\n' +
|
||||||
'Status code `200` indicates that the resource was returned successfully.',
|
'Status code `200` indicates that the resource was returned successfully.',
|
||||||
...jsonResponse({
|
...jsonResponse({
|
||||||
result: {
|
result: fields.result,
|
||||||
...fields.result,
|
|
||||||
example: 'success',
|
|
||||||
},
|
|
||||||
account: response.body.userAccount,
|
account: response.body.userAccount,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -522,7 +558,7 @@ paths['/available/username'] = {
|
||||||
tags: ['Users'],
|
tags: ['Users'],
|
||||||
summary: `Checks whether a username is available`,
|
summary: `Checks whether a username is available`,
|
||||||
description:
|
description:
|
||||||
'This allows a background check to see whether a username is available during signup',
|
'This allows a background check to see whether a username is available during sign up',
|
||||||
requestBody: {
|
requestBody: {
|
||||||
required: true,
|
required: true,
|
||||||
content: {
|
content: {
|
||||||
|
|
|
@ -54,7 +54,7 @@ model User {
|
||||||
initial String
|
initial String
|
||||||
imperial Boolean @default(false)
|
imperial Boolean @default(false)
|
||||||
language String @default("en")
|
language String @default("en")
|
||||||
lastLogin DateTime?
|
lastSignIn DateTime?
|
||||||
lusername String @unique
|
lusername String @unique
|
||||||
mfaSecret String @default("")
|
mfaSecret String @default("")
|
||||||
mfaEnabled Boolean @default(false)
|
mfaEnabled Boolean @default(false)
|
||||||
|
|
|
@ -29,14 +29,27 @@ UsersController.prototype.confirm = async (req, res, tools) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Login (with username and password)
|
* Sign in (with username and password)
|
||||||
*
|
*
|
||||||
* This is the endpoint that provides traditional username/password login
|
* This is the endpoint that provides traditional username/password sign in
|
||||||
* See: https://freesewing.dev/reference/backend/api
|
* See: https://freesewing.dev/reference/backend/api
|
||||||
*/
|
*/
|
||||||
UsersController.prototype.login = async function (req, res, tools) {
|
UsersController.prototype.signin = async function (req, res, tools) {
|
||||||
const User = new UserModel(tools)
|
const User = new UserModel(tools)
|
||||||
await User.passwordLogin(req)
|
await User.passwordSignIn(req)
|
||||||
|
|
||||||
|
return User.sendResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a magic link to sign in
|
||||||
|
*
|
||||||
|
* This is the endpoint that provides sign in via magic link
|
||||||
|
* See: https://freesewing.dev/reference/backend/api
|
||||||
|
*/
|
||||||
|
UsersController.prototype.signinlink = async function (req, res, tools) {
|
||||||
|
const User = new UserModel(tools)
|
||||||
|
await User.sendSigninlink(req)
|
||||||
|
|
||||||
return User.sendResponse(res)
|
return User.sendResponse(res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,42 +279,86 @@ UserModel.prototype.guardedCreate = async function ({ body }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Login based on username + password
|
* Sign in based on username + password
|
||||||
*/
|
*/
|
||||||
UserModel.prototype.passwordLogin = async function (req) {
|
UserModel.prototype.passwordSignIn = async function (req) {
|
||||||
if (Object.keys(req.body).length < 1) return this.setResponse(400, 'postBodyMissing')
|
if (Object.keys(req.body).length < 1) return this.setResponse(400, 'postBodyMissing')
|
||||||
if (!req.body.username) return this.setResponse(400, 'usernameMissing')
|
if (!req.body.username) return this.setResponse(400, 'usernameMissing')
|
||||||
if (!req.body.password) return this.setResponse(400, 'passwordMissing')
|
if (!req.body.password) return this.setResponse(400, 'passwordMissing')
|
||||||
|
|
||||||
await this.find(req.body)
|
await this.find(req.body)
|
||||||
if (!this.exists) {
|
if (!this.exists) {
|
||||||
log.warn(`Login attempt for non-existing user: ${req.body.username} from ${req.ip}`)
|
log.warn(`Sign-in attempt for non-existing user: ${req.body.username} from ${req.ip}`)
|
||||||
return this.setResponse(401, 'loginFailed')
|
return this.setResponse(401, 'signInFailed')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account found, check password
|
// Account found, check password
|
||||||
const [valid, updatedPasswordField] = verifyPassword(req.body.password, this.record.password)
|
const [valid, updatedPasswordField] = verifyPassword(req.body.password, this.record.password)
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
log.warn(`Wrong password for existing user: ${req.body.username} from ${req.ip}`)
|
log.warn(`Wrong password for existing user: ${req.body.username} from ${req.ip}`)
|
||||||
return this.setResponse(401, 'loginFailed')
|
return this.setResponse(401, 'signInFailed')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for MFA
|
// Check for MFA
|
||||||
if (this.record.mfaEnabled) {
|
if (this.record.mfaEnabled) {
|
||||||
if (!req.body.token) return this.setResponse(403, 'mfaTokenRequired')
|
if (!req.body.token) return this.setResponse(403, 'mfaTokenRequired')
|
||||||
else if (!this.mfa.verify(req.body.token, this.clear.mfaSecret)) {
|
else if (!this.mfa.verify(req.body.token, this.clear.mfaSecret)) {
|
||||||
return this.setResponse(401, 'loginFailed')
|
return this.setResponse(401, 'signInFailed')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login success
|
// Sign in success
|
||||||
log.info(`Login by user ${this.record.id} (${this.record.username})`)
|
log.info(`Sign-in by user ${this.record.id} (${this.record.username})`)
|
||||||
if (updatedPasswordField) {
|
if (updatedPasswordField) {
|
||||||
// Update the password field with a v3 hash
|
// Update the password field with a v3 hash
|
||||||
await this.unguardedUpdate({ password: updatedPasswordField })
|
await this.unguardedUpdate({ password: updatedPasswordField })
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.isOk() ? this.loginOk() : this.setResponse(401, 'loginFailed')
|
return this.isOk() ? this.signInOk() : this.setResponse(401, 'signInFailed')
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a magic link for user sign in
|
||||||
|
*/
|
||||||
|
UserModel.prototype.sendSigninlink = async function (req) {
|
||||||
|
if (Object.keys(req.body).length < 1) return this.setResponse(400, 'postBodyMissing')
|
||||||
|
if (!req.body.username) return this.setResponse(400, 'usernameMissing')
|
||||||
|
|
||||||
|
await this.find(req.body)
|
||||||
|
if (!this.exists) {
|
||||||
|
log.warn(`Magic link attempt for non-existing user: ${req.body.username} from ${req.ip}`)
|
||||||
|
return this.setResponse(401, 'signinFailed')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account found, create confirmation
|
||||||
|
const check = randomString()
|
||||||
|
this.confirmation = await this.Confirmation.create({
|
||||||
|
type: 'signinlink',
|
||||||
|
data: {
|
||||||
|
language: this.record.language,
|
||||||
|
check,
|
||||||
|
},
|
||||||
|
userId: this.record.id,
|
||||||
|
})
|
||||||
|
const isUnitTest = this.isUnitTest(req.body)
|
||||||
|
if (!isUnitTest) {
|
||||||
|
// Send sign-in link email
|
||||||
|
await this.mailer.send({
|
||||||
|
template: 'signinlink',
|
||||||
|
language: this.record.language,
|
||||||
|
to: this.clear.email,
|
||||||
|
replacements: {
|
||||||
|
actionUrl: i18nUrl(
|
||||||
|
this.record.language,
|
||||||
|
`/confirm/signin/${this.Confirmation.record.id}/${check}`
|
||||||
|
),
|
||||||
|
whyUrl: i18nUrl(this.record.language, `/docs/faq/email/why-signin-link`),
|
||||||
|
supportUrl: i18nUrl(this.record.language, `/patrons/join`),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.setResponse(200, 'emailSent')
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -348,19 +392,19 @@ UserModel.prototype.confirm = async function ({ body, params }) {
|
||||||
await this.read({ id: this.Confirmation.record.user.id })
|
await this.read({ id: this.Confirmation.record.user.id })
|
||||||
if (this.error) return this
|
if (this.error) return this
|
||||||
|
|
||||||
// Update user status, consent, and last login
|
// Update user status, consent, and last sign in
|
||||||
await this.unguardedUpdate({
|
await this.unguardedUpdate({
|
||||||
status: 1,
|
status: 1,
|
||||||
consent: body.consent,
|
consent: body.consent,
|
||||||
lastLogin: new Date(),
|
lastSignIn: new Date(),
|
||||||
})
|
})
|
||||||
if (this.error) return this
|
if (this.error) return this
|
||||||
|
|
||||||
// Before we return, remove the confirmation so it works only once
|
// Before we return, remove the confirmation so it works only once
|
||||||
await this.Confirmation.unguardedDelete()
|
await this.Confirmation.unguardedDelete()
|
||||||
|
|
||||||
// Account is now active, let's return a passwordless login
|
// Account is now active, let's return a passwordless sign in
|
||||||
return this.loginOk()
|
return this.signInOk()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -599,7 +643,7 @@ UserModel.prototype.asAccount = function () {
|
||||||
imperial: this.record.imperial,
|
imperial: this.record.imperial,
|
||||||
initial: this.clear.initial,
|
initial: this.clear.initial,
|
||||||
language: this.record.language,
|
language: this.record.language,
|
||||||
lastLogin: this.record.lastLogin,
|
lastSignIn: this.record.lastSignIn,
|
||||||
mfaEnabled: this.record.mfaEnabled,
|
mfaEnabled: this.record.mfaEnabled,
|
||||||
newsletter: this.record.newsletter,
|
newsletter: this.record.newsletter,
|
||||||
patron: this.record.patron,
|
patron: this.record.patron,
|
||||||
|
@ -689,9 +733,9 @@ UserModel.prototype.isOk = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper method to return from successful login
|
* Helper method to return from successful sign in
|
||||||
*/
|
*/
|
||||||
UserModel.prototype.loginOk = function () {
|
UserModel.prototype.signInOk = function () {
|
||||||
return this.setResponse(200, false, {
|
return this.setResponse(200, false, {
|
||||||
result: 'success',
|
result: 'success',
|
||||||
token: this.getToken(),
|
token: this.getToken(),
|
||||||
|
|
|
@ -7,14 +7,17 @@ const bsc = ['basic', { session: false }]
|
||||||
export function usersRoutes(tools) {
|
export function usersRoutes(tools) {
|
||||||
const { app, passport } = tools
|
const { app, passport } = tools
|
||||||
|
|
||||||
// Sign up
|
// Sign Up
|
||||||
app.post('/signup', (req, res) => Users.signup(req, res, tools))
|
app.post('/signup', (req, res) => Users.signup(req, res, tools))
|
||||||
|
|
||||||
// Confirm account
|
// Confirm account
|
||||||
app.post('/confirm/signup/:id', (req, res) => Users.confirm(req, res, tools))
|
app.post('/confirm/signup/:id', (req, res) => Users.confirm(req, res, tools))
|
||||||
|
|
||||||
// Login
|
// Sign In
|
||||||
app.post('/login', (req, res) => Users.login(req, res, tools))
|
app.post('/signin', (req, res) => Users.signin(req, res, tools))
|
||||||
|
|
||||||
|
// Send magic link to sign in
|
||||||
|
app.post('/signinlink', (req, res) => Users.signinlink(req, res, tools))
|
||||||
|
|
||||||
// Read current jwt
|
// Read current jwt
|
||||||
app.get('/whoami/jwt', passport.authenticate(...jwt), (req, res) => Users.whoami(req, res, tools))
|
app.get('/whoami/jwt', passport.authenticate(...jwt), (req, res) => Users.whoami(req, res, tools))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { emailchange, translations as emailchangeTranslations } from './emailchange/index.mjs'
|
import { emailchange, translations as emailchangeTranslations } from './emailchange/index.mjs'
|
||||||
import { goodbye, translations as goodbyeTranslations } from './goodbye/index.mjs'
|
import { goodbye, translations as goodbyeTranslations } from './goodbye/index.mjs'
|
||||||
import { loginlink, translations as loginlinkTranslations } from './loginlink/index.mjs'
|
import { signinlink, translations as signinlinkTranslations } from './signinlink/index.mjs'
|
||||||
import { newslettersub, translations as newslettersubTranslations } from './newslettersub/index.mjs'
|
import { newslettersub, translations as newslettersubTranslations } from './newslettersub/index.mjs'
|
||||||
import { passwordreset, translations as passwordresetTranslations } from './passwordreset/index.mjs'
|
import { passwordreset, translations as passwordresetTranslations } from './passwordreset/index.mjs'
|
||||||
import { signup, translations as signupTranslations } from './signup/index.mjs'
|
import { signup, translations as signupTranslations } from './signup/index.mjs'
|
||||||
|
@ -19,7 +19,7 @@ import nl from '../../../public/locales/nl/shared.json' assert { type: 'json' }
|
||||||
export const templates = {
|
export const templates = {
|
||||||
emailchange,
|
emailchange,
|
||||||
goodbye,
|
goodbye,
|
||||||
loginlink,
|
signinlink,
|
||||||
newslettersub,
|
newslettersub,
|
||||||
passwordreset,
|
passwordreset,
|
||||||
signup,
|
signup,
|
||||||
|
@ -30,7 +30,7 @@ export const templates = {
|
||||||
export const translations = {
|
export const translations = {
|
||||||
emailchange: emailchangeTranslations,
|
emailchange: emailchangeTranslations,
|
||||||
goodbye: goodbyeTranslations,
|
goodbye: goodbyeTranslations,
|
||||||
loginlink: loginlinkTranslations,
|
signinlink: signinlinkTranslations,
|
||||||
newslettersub: newslettersubTranslations,
|
newslettersub: newslettersubTranslations,
|
||||||
passwordreset: passwordresetTranslations,
|
passwordreset: passwordresetTranslations,
|
||||||
signup: signupTranslations,
|
signup: signupTranslations,
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
subject: '[FreeSewing] Loginlink fixme'
|
|
||||||
heading: FIXME
|
|
||||||
lead: fixme
|
|
||||||
text-lead: fixme
|
|
||||||
closing: fixme
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { buttonRow, closingRow, headingRow, wrap } from '../shared/blocks.mjs'
|
import { buttonRow, closingRow, headingRow, wrap } from '../shared/blocks.mjs'
|
||||||
// Translations
|
// Translations
|
||||||
import en from '../../../../public/locales/en/loginlink.json' assert { type: 'json' }
|
import en from '../../../../public/locales/en/signinlink.json' assert { type: 'json' }
|
||||||
import de from '../../../../public/locales/de/loginlink.json' assert { type: 'json' }
|
import de from '../../../../public/locales/de/signinlink.json' assert { type: 'json' }
|
||||||
import es from '../../../../public/locales/es/loginlink.json' assert { type: 'json' }
|
import es from '../../../../public/locales/es/signinlink.json' assert { type: 'json' }
|
||||||
import fr from '../../../../public/locales/fr/loginlink.json' assert { type: 'json' }
|
import fr from '../../../../public/locales/fr/signinlink.json' assert { type: 'json' }
|
||||||
import nl from '../../../../public/locales/nl/loginlink.json' assert { type: 'json' }
|
import nl from '../../../../public/locales/nl/signinlink.json' assert { type: 'json' }
|
||||||
|
|
||||||
export const loginlink = {
|
export const signinlink = {
|
||||||
html: wrap.html(`
|
html: wrap.html(`
|
||||||
${headingRow}
|
${headingRow}
|
||||||
<tr>
|
<tr>
|
|
@ -0,0 +1,6 @@
|
||||||
|
subject: "[FreeSewing] Sign in to FreeSewing.org with this link"
|
||||||
|
heading: Password are so has-been
|
||||||
|
lead: 'To sign in to FreeSewing.org, click the big black rectangle below:'
|
||||||
|
text-lead: 'To sign in to FreeSewing.org, click the link below:'
|
||||||
|
button: Sign in
|
||||||
|
closing: That was easy, wasn't it?
|
|
@ -1,4 +1,4 @@
|
||||||
subject: "[FreeSewing] Here's that signup link we promised you"
|
subject: "[FreeSewing] Here is your sign-up link for FreeSewing.org"
|
||||||
heading: Join FreeSewing
|
heading: Join FreeSewing
|
||||||
lead: 'To create a FreeSewing account linked to this email address, click the big black rectangle below:'
|
lead: 'To create a FreeSewing account linked to this email address, click the big black rectangle below:'
|
||||||
text-lead: 'To create a FreeSewing account linked to this email address, click the link below:'
|
text-lead: 'To create a FreeSewing account linked to this email address, click the link below:'
|
||||||
|
|
|
@ -51,7 +51,7 @@ export const accountTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update password - Check with login
|
// Update password - Check with sign in
|
||||||
const password = store.randomString()
|
const password = store.randomString()
|
||||||
it(`${store.icon('user', auth)} Should update the password (${auth})`, (done) => {
|
it(`${store.icon('user', auth)} Should update the password (${auth})`, (done) => {
|
||||||
const body = {}
|
const body = {}
|
||||||
|
@ -79,11 +79,11 @@ export const accountTests = async (chai, config, expect, store) => {
|
||||||
it(`${store.icon(
|
it(`${store.icon(
|
||||||
'user',
|
'user',
|
||||||
auth
|
auth
|
||||||
)} Should be able to login with the updated password (${auth})`, (done) => {
|
)} Should be able to sign in with the updated password (${auth})`, (done) => {
|
||||||
const body = {}
|
const body = {}
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post(`/login`)
|
.post(`/signin`)
|
||||||
.send({
|
.send({
|
||||||
username: store.account.username,
|
username: store.account.username,
|
||||||
password,
|
password,
|
||||||
|
@ -122,11 +122,11 @@ export const accountTests = async (chai, config, expect, store) => {
|
||||||
it(`${store.icon(
|
it(`${store.icon(
|
||||||
'user',
|
'user',
|
||||||
auth
|
auth
|
||||||
)} Should be able to login with the original password (${auth})`, (done) => {
|
)} Should be able to sign in with the original password (${auth})`, (done) => {
|
||||||
const body = {}
|
const body = {}
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post(`/login`)
|
.post(`/signin`)
|
||||||
.send({
|
.send({
|
||||||
username: store.account.username,
|
username: store.account.username,
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
|
|
@ -133,10 +133,10 @@ export const mfaTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`${store.icon('mfa', auth)} Should not login with username/password only`, (done) => {
|
it(`${store.icon('mfa', auth)} Should not sign in with username/password only`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: secret[auth].username,
|
username: secret[auth].username,
|
||||||
password: secret[auth].password,
|
password: secret[auth].password,
|
||||||
|
@ -150,10 +150,10 @@ export const mfaTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`${store.icon('mfa')} Should login with username/password/token`, (done) => {
|
it(`${store.icon('mfa')} Should sign in with username/password/token`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: secret[auth].username,
|
username: secret[auth].username,
|
||||||
password: secret[auth].password,
|
password: secret[auth].password,
|
||||||
|
@ -168,10 +168,10 @@ export const mfaTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`${store.icon('mfa')} Should not login with a wrong token`, (done) => {
|
it(`${store.icon('mfa')} Should not sign in with a wrong token`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: secret[auth].username,
|
username: secret[auth].username,
|
||||||
password: secret[auth].password,
|
password: secret[auth].password,
|
||||||
|
@ -181,7 +181,7 @@ export const mfaTests = async (chai, config, expect, store) => {
|
||||||
expect(err === null).to.equal(true)
|
expect(err === null).to.equal(true)
|
||||||
expect(res.status).to.equal(401)
|
expect(res.status).to.equal(401)
|
||||||
expect(res.body.result).to.equal('error')
|
expect(res.body.result).to.equal('error')
|
||||||
expect(res.body.error).to.equal('loginFailed')
|
expect(res.body.error).to.equal('signInFailed')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -58,10 +58,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should not login with the wrong password`, (done) => {
|
step(`${store.icon('user')} Should not sign in with the wrong password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.username,
|
username: store.account.username,
|
||||||
password: store.account.username,
|
password: store.account.username,
|
||||||
|
@ -71,7 +71,7 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
expect(res.type).to.equal('application/json')
|
expect(res.type).to.equal('application/json')
|
||||||
expect(res.charset).to.equal('utf-8')
|
expect(res.charset).to.equal('utf-8')
|
||||||
expect(res.body.result).to.equal(`error`)
|
expect(res.body.result).to.equal(`error`)
|
||||||
expect(res.body.error).to.equal(`loginFailed`)
|
expect(res.body.error).to.equal(`signInFailed`)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -108,10 +108,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should login with username and password`, (done) => {
|
step(`${store.icon('user')} Should sign in with username and password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.username,
|
username: store.account.username,
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
@ -131,10 +131,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should login with USERNAME and password`, (done) => {
|
step(`${store.icon('user')} Should sign in with USERNAME and password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.username.toUpperCase(),
|
username: store.account.username.toUpperCase(),
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
@ -154,10 +154,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should login with email and password`, (done) => {
|
step(`${store.icon('user')} Should sign in with email and password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.email,
|
username: store.account.email,
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
@ -177,10 +177,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should login with EMAIL and password`, (done) => {
|
step(`${store.icon('user')} Should signin with EMAIL and password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.email.toUpperCase(),
|
username: store.account.email.toUpperCase(),
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
@ -200,10 +200,10 @@ export const userTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
step(`${store.icon('user')} Should login with id and password`, (done) => {
|
step(`${store.icon('user')} Should signin with id and password`, (done) => {
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
.post('/login')
|
.post('/signin')
|
||||||
.send({
|
.send({
|
||||||
username: store.account.id,
|
username: store.account.id,
|
||||||
password: store.account.password,
|
password: store.account.password,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue