Add action hooks to user routes
This commit is contained in:
parent
349be1eaa9
commit
6f3fe96f40
|
@ -49,6 +49,7 @@ import { sequelizeTypescript } from '../../../initializers/database'
|
||||||
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
|
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
|
||||||
import { UserRegister } from '../../../../shared/models/users/user-register.model'
|
import { UserRegister } from '../../../../shared/models/users/user-register.model'
|
||||||
import { MUser, MUserAccountDefault } from '@server/typings/models'
|
import { MUser, MUserAccountDefault } from '@server/typings/models'
|
||||||
|
import { Hooks } from '@server/lib/plugins/hooks'
|
||||||
|
|
||||||
const auditLogger = auditLoggerFactory('users')
|
const auditLogger = auditLoggerFactory('users')
|
||||||
|
|
||||||
|
@ -172,7 +173,7 @@ usersRouter.post('/:id/verify-email',
|
||||||
usersRouter.post('/token',
|
usersRouter.post('/token',
|
||||||
loginRateLimiter,
|
loginRateLimiter,
|
||||||
token,
|
token,
|
||||||
success
|
tokenSuccess
|
||||||
)
|
)
|
||||||
// TODO: Once https://github.com/oauthjs/node-oauth2-server/pull/289 is merged, implement revoke token route
|
// TODO: Once https://github.com/oauthjs/node-oauth2-server/pull/289 is merged, implement revoke token route
|
||||||
|
|
||||||
|
@ -198,11 +199,13 @@ async function createUser (req: express.Request, res: express.Response) {
|
||||||
adminFlags: body.adminFlags || UserAdminFlag.NONE
|
adminFlags: body.adminFlags || UserAdminFlag.NONE
|
||||||
}) as MUser
|
}) 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()))
|
auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
|
||||||
logger.info('User %s with its channel and account created.', body.username)
|
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({
|
return res.json({
|
||||||
user: {
|
user: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
|
@ -228,7 +231,7 @@ async function registerUser (req: express.Request, res: express.Response) {
|
||||||
emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null
|
emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null
|
||||||
})
|
})
|
||||||
|
|
||||||
const { user } = await createUserAccountAndChannelAndPlaylist({
|
const { user, account, videoChannel } = await createUserAccountAndChannelAndPlaylist({
|
||||||
userToCreate: userToCreate,
|
userToCreate: userToCreate,
|
||||||
userDisplayName: body.displayName || undefined,
|
userDisplayName: body.displayName || undefined,
|
||||||
channelNames: body.channel
|
channelNames: body.channel
|
||||||
|
@ -243,6 +246,8 @@ async function registerUser (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
Notifier.Instance.notifyOnNewUserRegistration(user)
|
Notifier.Instance.notifyOnNewUserRegistration(user)
|
||||||
|
|
||||||
|
Hooks.runAction('action:api.user.registered', { body, user, account, videoChannel })
|
||||||
|
|
||||||
return res.type('json').status(204).end()
|
return res.type('json').status(204).end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +256,8 @@ async function unblockUser (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
await changeUserBlock(res, user, false)
|
await changeUserBlock(res, user, false)
|
||||||
|
|
||||||
|
Hooks.runAction('action:api.user.unblocked', { user })
|
||||||
|
|
||||||
return res.status(204).end()
|
return res.status(204).end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +267,8 @@ async function blockUser (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
await changeUserBlock(res, user, true, reason)
|
await changeUserBlock(res, user, true, reason)
|
||||||
|
|
||||||
|
Hooks.runAction('action:api.user.blocked', { user })
|
||||||
|
|
||||||
return res.status(204).end()
|
return res.status(204).end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +295,8 @@ async function removeUser (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
auditLogger.delete(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
|
auditLogger.delete(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
|
||||||
|
|
||||||
|
Hooks.runAction('action:api.user.deleted', { user })
|
||||||
|
|
||||||
return res.sendStatus(204)
|
return res.sendStatus(204)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +321,8 @@ async function updateUser (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
|
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
|
// Don't need to send this update to followers, these attributes are not federated
|
||||||
|
|
||||||
return res.sendStatus(204)
|
return res.sendStatus(204)
|
||||||
|
@ -356,8 +369,10 @@ async function verifyUserEmail (req: express.Request, res: express.Response) {
|
||||||
return res.status(204).end()
|
return res.status(204).end()
|
||||||
}
|
}
|
||||||
|
|
||||||
function success (req: express.Request, res: express.Response) {
|
function tokenSuccess (req: express.Request) {
|
||||||
res.end()
|
const username = req.body.username
|
||||||
|
|
||||||
|
Hooks.runAction('action:api.user.oauth2-got-token', { username, ip: req.ip })
|
||||||
}
|
}
|
||||||
|
|
||||||
async function changeUserBlock (res: express.Response, user: MUserAccountDefault, block: boolean, reason?: string) {
|
async function changeUserBlock (res: express.Response, user: MUserAccountDefault, block: boolean, reason?: string) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const oAuthServer = new OAuthServer({
|
||||||
useErrorHandler: true,
|
useErrorHandler: true,
|
||||||
accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
|
accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
|
||||||
refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
|
refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
|
||||||
|
continueMiddleware: true,
|
||||||
model: require('../lib/oauth-model')
|
model: require('../lib/oauth-model')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,15 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
||||||
|
|
||||||
'action:api.video-thread.created',
|
'action:api.video-thread.created',
|
||||||
'action:api.video-comment-reply.created',
|
'action:api.video-comment-reply.created',
|
||||||
'action:api.video-comment.deleted'
|
'action:api.video-comment.deleted',
|
||||||
|
|
||||||
|
'action:api.user.blocked',
|
||||||
|
'action:api.user.unblocked',
|
||||||
|
'action:api.user.registered',
|
||||||
|
'action:api.user.created',
|
||||||
|
'action:api.user.deleted',
|
||||||
|
'action:api.user.updated',
|
||||||
|
'action:api.user.oauth2-got-token'
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const h of actionHooks) {
|
for (const h of actionHooks) {
|
||||||
|
|
|
@ -5,19 +5,26 @@ import 'mocha'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
flushAndRunServer, killallServers, reRunServer,
|
killallServers,
|
||||||
|
reRunServer,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
waitUntilLog
|
waitUntilLog
|
||||||
} from '../../../shared/extra-utils/server/servers'
|
} from '../../../shared/extra-utils/server/servers'
|
||||||
import {
|
import {
|
||||||
addVideoCommentReply,
|
addVideoCommentReply,
|
||||||
addVideoCommentThread, deleteVideoComment,
|
addVideoCommentThread,
|
||||||
|
blockUser,
|
||||||
|
createUser,
|
||||||
|
deleteVideoComment,
|
||||||
getPluginTestPath,
|
getPluginTestPath,
|
||||||
installPlugin, removeVideo,
|
installPlugin, login,
|
||||||
|
registerUser, removeUser,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
|
unblockUser, updateUser,
|
||||||
updateVideo,
|
updateVideo,
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
viewVideo
|
viewVideo,
|
||||||
|
userLogin
|
||||||
} from '../../../shared/extra-utils'
|
} from '../../../shared/extra-utils'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@ -48,10 +55,13 @@ describe('Test plugin action hooks', function () {
|
||||||
await reRunServer(servers[0])
|
await reRunServer(servers[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Application hooks', function () {
|
||||||
it('Should run action:application.listening', async function () {
|
it('Should run action:application.listening', async function () {
|
||||||
await checkHook('action:application.listening')
|
await checkHook('action:application.listening')
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Videos hooks', function () {
|
||||||
it('Should run action:api.video.uploaded', async function () {
|
it('Should run action:api.video.uploaded', async function () {
|
||||||
const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
|
const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
|
||||||
videoUUID = res.body.video.uuid
|
videoUUID = res.body.video.uuid
|
||||||
|
@ -70,7 +80,9 @@ describe('Test plugin action hooks', function () {
|
||||||
|
|
||||||
await checkHook('action:api.video.viewed')
|
await checkHook('action:api.video.viewed')
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Comments hooks', function () {
|
||||||
it('Should run action:api.video-thread.created', async function () {
|
it('Should run action:api.video-thread.created', async function () {
|
||||||
const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
|
const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
|
||||||
threadId = res.body.comment.id
|
threadId = res.body.comment.id
|
||||||
|
@ -89,11 +101,58 @@ describe('Test plugin action hooks', function () {
|
||||||
|
|
||||||
await checkHook('action:api.video-comment.deleted')
|
await checkHook('action:api.video-comment.deleted')
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('Should run action:api.video.deleted', async function () {
|
describe('Users hooks', function () {
|
||||||
await removeVideo(servers[0].url, servers[0].accessToken, videoUUID)
|
let userId: number
|
||||||
|
|
||||||
await checkHook('action:api.video.deleted')
|
it('Should run action:api.user.registered', async function () {
|
||||||
|
await registerUser(servers[0].url, 'registered_user', 'super_password')
|
||||||
|
|
||||||
|
await checkHook('action:api.user.registered')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.created', async function () {
|
||||||
|
const res = await createUser({
|
||||||
|
url: servers[0].url,
|
||||||
|
accessToken: servers[0].accessToken,
|
||||||
|
username: 'created_user',
|
||||||
|
password: 'super_password'
|
||||||
|
})
|
||||||
|
userId = res.body.user.id
|
||||||
|
|
||||||
|
await checkHook('action:api.user.created')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.oauth2-got-token', async function () {
|
||||||
|
await userLogin(servers[0], { username: 'created_user', password: 'super_password' })
|
||||||
|
|
||||||
|
await checkHook('action:api.user.oauth2-got-token')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.blocked', async function () {
|
||||||
|
await blockUser(servers[0].url, userId, servers[0].accessToken)
|
||||||
|
|
||||||
|
await checkHook('action:api.user.blocked')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.unblocked', async function () {
|
||||||
|
await unblockUser(servers[0].url, userId, servers[0].accessToken)
|
||||||
|
|
||||||
|
await checkHook('action:api.user.unblocked')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.updated', async function () {
|
||||||
|
await updateUser({ url: servers[0].url, accessToken: servers[0].accessToken, userId, videoQuota: 50 })
|
||||||
|
|
||||||
|
await checkHook('action:api.user.updated')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run action:api.user.deleted', async function () {
|
||||||
|
await removeUser(servers[0].url, userId, servers[0].accessToken)
|
||||||
|
|
||||||
|
await checkHook('action:api.user.deleted')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { userLogin } from './login'
|
||||||
import { UserUpdateMe } from '../../models/users'
|
import { UserUpdateMe } from '../../models/users'
|
||||||
import { omit } from 'lodash'
|
import { omit } from 'lodash'
|
||||||
|
|
||||||
type CreateUserArgs = { url: string,
|
type CreateUserArgs = {
|
||||||
|
url: string,
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
|
|
|
@ -55,7 +55,23 @@ export const serverActionHookObject = {
|
||||||
// Fired when a reply to a thread is created
|
// Fired when a reply to a thread is created
|
||||||
'action:api.video-comment-reply.created': true,
|
'action:api.video-comment-reply.created': true,
|
||||||
// Fired when a comment (thread or reply) is deleted
|
// Fired when a comment (thread or reply) is deleted
|
||||||
'action:api.video-comment.deleted': true
|
'action:api.video-comment.deleted': true,
|
||||||
|
|
||||||
|
// Fired when a user is blocked (banned)
|
||||||
|
'action:api.user.blocked': true,
|
||||||
|
// Fired when a user is unblocked (unbanned)
|
||||||
|
'action:api.user.unblocked': true,
|
||||||
|
// Fired when a user registered on the instance
|
||||||
|
'action:api.user.registered': true,
|
||||||
|
// Fired when an admin/moderator created a user
|
||||||
|
'action:api.user.created': true,
|
||||||
|
// Fired when a user is removed by an admin/moderator
|
||||||
|
'action:api.user.deleted': true,
|
||||||
|
// Fired when a user is updated by an admin/moderator
|
||||||
|
'action:api.user.updated': true,
|
||||||
|
|
||||||
|
// Fired when a user got a new oauth2 token
|
||||||
|
'action:api.user.oauth2-got-token': true
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ServerActionHookName = keyof typeof serverActionHookObject
|
export type ServerActionHookName = keyof typeof serverActionHookObject
|
||||||
|
|
Loading…
Reference in New Issue