add user account email verificiation (#977)

* add user account email verificiation

includes server and client code to:

* enable verificationRequired via custom config
* send verification email with registration
* ask for verification email
* verify via email
* prevent login if not verified and required
* conditional client links to ask for new verification email

* allow login for verified=null

these are users created when verification not required
should still be able to login when verification is enabled

* refactor email verifcation pr

* change naming from verified to emailVerified
* change naming from askVerifyEmail to askSendVerifyEmail
* undo unrelated automatic prettier formatting on api/config
* use redirectService for home
* remove redundant success notification on email verified

* revert test.yaml smpt host
This commit is contained in:
Josh Morel 2018-08-31 03:18:19 -04:00 committed by Chocobozzz
parent 04291e1ba4
commit d9eaee3939
42 changed files with 715 additions and 24 deletions

View file

@ -25,7 +25,10 @@ import {
usersSortValidator,
usersUpdateValidator
} from '../../../middlewares'
import { usersAskResetPasswordValidator, usersBlockingValidator, usersResetPasswordValidator } from '../../../middlewares/validators'
import {
usersAskResetPasswordValidator, usersBlockingValidator, usersResetPasswordValidator,
usersAskSendVerifyEmailValidator, usersVerifyEmailValidator
} from '../../../middlewares/validators'
import { UserModel } from '../../../models/account/user'
import { OAuthTokenModel } from '../../../models/oauth/oauth-token'
import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger'
@ -110,6 +113,17 @@ usersRouter.post('/:id/reset-password',
asyncMiddleware(resetUserPassword)
)
usersRouter.post('/ask-send-verify-email',
loginRateLimiter,
asyncMiddleware(usersAskSendVerifyEmailValidator),
asyncMiddleware(askSendVerifyUserEmail)
)
usersRouter.post('/:id/verify-email',
asyncMiddleware(usersVerifyEmailValidator),
asyncMiddleware(verifyUserEmail)
)
usersRouter.post('/token',
loginRateLimiter,
token,
@ -165,7 +179,8 @@ async function registerUser (req: express.Request, res: express.Response) {
autoPlayVideo: true,
role: UserRole.USER,
videoQuota: CONFIG.USER.VIDEO_QUOTA,
videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY
videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY,
emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null
})
const { user } = await createUserAccountAndChannel(userToCreate)
@ -173,6 +188,10 @@ async function registerUser (req: express.Request, res: express.Response) {
auditLogger.create(body.username, new UserAuditView(user.toFormattedJSON()))
logger.info('User %s with its channel and account registered.', body.username)
if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) {
await sendVerifyUserEmail(user)
}
return res.type('json').status(204).end()
}
@ -261,6 +280,30 @@ async function resetUserPassword (req: express.Request, res: express.Response, n
return res.status(204).end()
}
async function sendVerifyUserEmail (user: UserModel) {
const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id)
const url = CONFIG.WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString
await Emailer.Instance.addVerifyEmailJob(user.email, url)
return
}
async function askSendVerifyUserEmail (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.user as UserModel
await sendVerifyUserEmail(user)
return res.status(204).end()
}
async function verifyUserEmail (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.user as UserModel
user.emailVerified = true
await user.save()
return res.status(204).end()
}
function success (req: express.Request, res: express.Response, next: express.NextFunction) {
res.end()
}