import { UserCreate, UserRight, UserRole, UserUpdate } from '../../../../shared'
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
-import { RATES_LIMIT, WEBSERVER } from '../../../initializers/constants'
+import { WEBSERVER } from '../../../initializers/constants'
import { Emailer } from '../../../lib/emailer'
import { Redis } from '../../../lib/redis'
-import { createUserAccountAndChannelAndPlaylist } from '../../../lib/user'
+import { createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
usersAskSendVerifyEmailValidator,
usersBlockingValidator,
usersResetPasswordValidator,
- usersVerifyEmailValidator
+ usersVerifyEmailValidator,
+ ensureCanManageUser
} from '../../../middlewares/validators'
import { UserModel } from '../../../models/account/user'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
import { sequelizeTypescript } from '../../../initializers/database'
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
import { UserRegister } from '../../../../shared/models/users/user-register.model'
+import { MUser, MUserAccountDefault } from '@server/typings/models'
+import { Hooks } from '@server/lib/plugins/hooks'
const auditLogger = auditLoggerFactory('users')
// FIXME: https://github.com/nfriedly/express-rate-limit/issues/138
// @ts-ignore
const loginRateLimiter = RateLimit({
- windowMs: RATES_LIMIT.LOGIN.WINDOW_MS,
- max: RATES_LIMIT.LOGIN.MAX
+ windowMs: CONFIG.RATES_LIMIT.LOGIN.WINDOW_MS,
+ max: CONFIG.RATES_LIMIT.LOGIN.MAX
+})
+
+// @ts-ignore
+const signupRateLimiter = RateLimit({
+ windowMs: CONFIG.RATES_LIMIT.SIGNUP.WINDOW_MS,
+ max: CONFIG.RATES_LIMIT.SIGNUP.MAX,
+ skipFailedRequests: true
})
// @ts-ignore
const askSendEmailLimiter = new RateLimit({
- windowMs: RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS,
- max: RATES_LIMIT.ASK_SEND_EMAIL.MAX
+ windowMs: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS,
+ max: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.MAX
})
const usersRouter = express.Router()
authenticate,
ensureUserHasRight(UserRight.MANAGE_USERS),
asyncMiddleware(usersBlockingValidator),
+ ensureCanManageUser,
asyncMiddleware(blockUser)
)
usersRouter.post('/:id/unblock',
authenticate,
ensureUserHasRight(UserRight.MANAGE_USERS),
asyncMiddleware(usersBlockingValidator),
+ ensureCanManageUser,
asyncMiddleware(unblockUser)
)
)
usersRouter.post('/register',
+ signupRateLimiter,
asyncMiddleware(ensureUserRegistrationAllowed),
ensureUserRegistrationAllowedForIP,
asyncMiddleware(usersRegisterValidator),
authenticate,
ensureUserHasRight(UserRight.MANAGE_USERS),
asyncMiddleware(usersUpdateValidator),
+ ensureCanManageUser,
asyncMiddleware(updateUser)
)
authenticate,
ensureUserHasRight(UserRight.MANAGE_USERS),
asyncMiddleware(usersRemoveValidator),
+ ensureCanManageUser,
asyncMiddleware(removeUser)
)
usersRouter.post('/ask-send-verify-email',
askSendEmailLimiter,
asyncMiddleware(usersAskSendVerifyEmailValidator),
- asyncMiddleware(askSendVerifyUserEmail)
+ asyncMiddleware(reSendVerifyUserEmail)
)
usersRouter.post('/:id/verify-email',
usersRouter.post('/token',
loginRateLimiter,
token,
- success
+ tokenSuccess
)
// TODO: Once https://github.com/oauthjs/node-oauth2-server/pull/289 is merged, implement revoke token route
videoQuota: body.videoQuota,
videoQuotaDaily: body.videoQuotaDaily,
adminFlags: body.adminFlags || UserAdminFlag.NONE
- })
+ }) as MUser
- const { user, account } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate })
+ const { user, account, videoChannel } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate })
auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
logger.info('User %s with its channel and account created.', body.username)
+ Hooks.runAction('action:api.user.created', { body, user, account, videoChannel })
+
return res.json({
user: {
id: user.id,
emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null
})
- const { user } = await createUserAccountAndChannelAndPlaylist({
+ const { user, account, videoChannel } = await createUserAccountAndChannelAndPlaylist({
userToCreate: userToCreate,
userDisplayName: body.displayName || undefined,
channelNames: body.channel
Notifier.Instance.notifyOnNewUserRegistration(user)
+ Hooks.runAction('action:api.user.registered', { body, user, account, videoChannel })
+
return res.type('json').status(204).end()
}
await changeUserBlock(res, user, false)
+ Hooks.runAction('action:api.user.unblocked', { user })
+
return res.status(204).end()
}
await changeUserBlock(res, user, true, reason)
+ Hooks.runAction('action:api.user.blocked', { user })
+
return res.status(204).end()
}
auditLogger.delete(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
+ Hooks.runAction('action:api.user.deleted', { user })
+
return res.sendStatus(204)
}
auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
+ Hooks.runAction('action:api.user.updated', { user })
+
// Don't need to send this update to followers, these attributes are not federated
return res.sendStatus(204)
return res.status(204).end()
}
-async function sendVerifyUserEmail (user: UserModel) {
- const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id)
- const url = 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) {
+async function reSendVerifyUserEmail (req: express.Request, res: express.Response) {
const user = res.locals.user
await sendVerifyUserEmail(user)
const user = res.locals.user
user.emailVerified = true
+ if (req.body.isPendingEmail === true) {
+ user.email = user.pendingEmail
+ user.pendingEmail = null
+ }
+
await user.save()
return res.status(204).end()
}
-function success (req: express.Request, res: express.Response) {
- res.end()
+function tokenSuccess (req: express.Request) {
+ const username = req.body.username
+
+ Hooks.runAction('action:api.user.oauth2-got-token', { username, ip: req.ip })
}
-async function changeUserBlock (res: express.Response, user: UserModel, block: boolean, reason?: string) {
+async function changeUserBlock (res: express.Response, user: MUserAccountDefault, block: boolean, reason?: string) {
const oldUserAuditView = new UserAuditView(user.toFormattedJSON())
user.blocked = block