From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 31 Jul 2023 14:34:36 +0200 Subject: Migrate server to ESM Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports) --- server/controllers/api/users/registrations.ts | 249 -------------------------- 1 file changed, 249 deletions(-) delete mode 100644 server/controllers/api/users/registrations.ts (limited to 'server/controllers/api/users/registrations.ts') diff --git a/server/controllers/api/users/registrations.ts b/server/controllers/api/users/registrations.ts deleted file mode 100644 index 5e213d6cc..000000000 --- a/server/controllers/api/users/registrations.ts +++ /dev/null @@ -1,249 +0,0 @@ -import express from 'express' -import { Emailer } from '@server/lib/emailer' -import { Hooks } from '@server/lib/plugins/hooks' -import { UserRegistrationModel } from '@server/models/user/user-registration' -import { pick } from '@shared/core-utils' -import { - HttpStatusCode, - UserRegister, - UserRegistrationRequest, - UserRegistrationState, - UserRegistrationUpdateState, - UserRight -} from '@shared/models' -import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' -import { logger } from '../../../helpers/logger' -import { CONFIG } from '../../../initializers/config' -import { Notifier } from '../../../lib/notifier' -import { buildUser, createUserAccountAndChannelAndPlaylist, sendVerifyRegistrationEmail, sendVerifyUserEmail } from '../../../lib/user' -import { - acceptOrRejectRegistrationValidator, - asyncMiddleware, - asyncRetryTransactionMiddleware, - authenticate, - buildRateLimiter, - ensureUserHasRight, - ensureUserRegistrationAllowedFactory, - ensureUserRegistrationAllowedForIP, - getRegistrationValidator, - listRegistrationsValidator, - paginationValidator, - setDefaultPagination, - setDefaultSort, - userRegistrationsSortValidator, - usersDirectRegistrationValidator, - usersRequestRegistrationValidator -} from '../../../middlewares' - -const auditLogger = auditLoggerFactory('users') - -const registrationRateLimiter = buildRateLimiter({ - windowMs: CONFIG.RATES_LIMIT.SIGNUP.WINDOW_MS, - max: CONFIG.RATES_LIMIT.SIGNUP.MAX, - skipFailedRequests: true -}) - -const registrationsRouter = express.Router() - -registrationsRouter.post('/registrations/request', - registrationRateLimiter, - asyncMiddleware(ensureUserRegistrationAllowedFactory('request-registration')), - ensureUserRegistrationAllowedForIP, - asyncMiddleware(usersRequestRegistrationValidator), - asyncRetryTransactionMiddleware(requestRegistration) -) - -registrationsRouter.post('/registrations/:registrationId/accept', - authenticate, - ensureUserHasRight(UserRight.MANAGE_REGISTRATIONS), - asyncMiddleware(acceptOrRejectRegistrationValidator), - asyncRetryTransactionMiddleware(acceptRegistration) -) -registrationsRouter.post('/registrations/:registrationId/reject', - authenticate, - ensureUserHasRight(UserRight.MANAGE_REGISTRATIONS), - asyncMiddleware(acceptOrRejectRegistrationValidator), - asyncRetryTransactionMiddleware(rejectRegistration) -) - -registrationsRouter.delete('/registrations/:registrationId', - authenticate, - ensureUserHasRight(UserRight.MANAGE_REGISTRATIONS), - asyncMiddleware(getRegistrationValidator), - asyncRetryTransactionMiddleware(deleteRegistration) -) - -registrationsRouter.get('/registrations', - authenticate, - ensureUserHasRight(UserRight.MANAGE_REGISTRATIONS), - paginationValidator, - userRegistrationsSortValidator, - setDefaultSort, - setDefaultPagination, - listRegistrationsValidator, - asyncMiddleware(listRegistrations) -) - -registrationsRouter.post('/register', - registrationRateLimiter, - asyncMiddleware(ensureUserRegistrationAllowedFactory('direct-registration')), - ensureUserRegistrationAllowedForIP, - asyncMiddleware(usersDirectRegistrationValidator), - asyncRetryTransactionMiddleware(registerUser) -) - -// --------------------------------------------------------------------------- - -export { - registrationsRouter -} - -// --------------------------------------------------------------------------- - -async function requestRegistration (req: express.Request, res: express.Response) { - const body: UserRegistrationRequest = req.body - - const registration = new UserRegistrationModel({ - ...pick(body, [ 'username', 'password', 'email', 'registrationReason' ]), - - accountDisplayName: body.displayName, - channelDisplayName: body.channel?.displayName, - channelHandle: body.channel?.name, - - state: UserRegistrationState.PENDING, - - emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null - }) - - await registration.save() - - if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) { - await sendVerifyRegistrationEmail(registration) - } - - Notifier.Instance.notifyOnNewRegistrationRequest(registration) - - Hooks.runAction('action:api.user.requested-registration', { body, registration, req, res }) - - return res.json(registration.toFormattedJSON()) -} - -// --------------------------------------------------------------------------- - -async function acceptRegistration (req: express.Request, res: express.Response) { - const registration = res.locals.userRegistration - const body: UserRegistrationUpdateState = req.body - - const userToCreate = buildUser({ - username: registration.username, - password: registration.password, - email: registration.email, - emailVerified: registration.emailVerified - }) - // We already encrypted password in registration model - userToCreate.skipPasswordEncryption = true - - // TODO: handle conflicts if someone else created a channel handle/user handle/user email between registration and approval - - const { user } = await createUserAccountAndChannelAndPlaylist({ - userToCreate, - userDisplayName: registration.accountDisplayName, - channelNames: registration.channelHandle && registration.channelDisplayName - ? { - name: registration.channelHandle, - displayName: registration.channelDisplayName - } - : undefined - }) - - registration.userId = user.id - registration.state = UserRegistrationState.ACCEPTED - registration.moderationResponse = body.moderationResponse - - await registration.save() - - logger.info('Registration of %s accepted', registration.username) - - if (body.preventEmailDelivery !== true) { - Emailer.Instance.addUserRegistrationRequestProcessedJob(registration) - } - - return res.sendStatus(HttpStatusCode.NO_CONTENT_204) -} - -async function rejectRegistration (req: express.Request, res: express.Response) { - const registration = res.locals.userRegistration - const body: UserRegistrationUpdateState = req.body - - registration.state = UserRegistrationState.REJECTED - registration.moderationResponse = body.moderationResponse - - await registration.save() - - if (body.preventEmailDelivery !== true) { - Emailer.Instance.addUserRegistrationRequestProcessedJob(registration) - } - - logger.info('Registration of %s rejected', registration.username) - - return res.sendStatus(HttpStatusCode.NO_CONTENT_204) -} - -// --------------------------------------------------------------------------- - -async function deleteRegistration (req: express.Request, res: express.Response) { - const registration = res.locals.userRegistration - - await registration.destroy() - - logger.info('Registration of %s deleted', registration.username) - - return res.sendStatus(HttpStatusCode.NO_CONTENT_204) -} - -// --------------------------------------------------------------------------- - -async function listRegistrations (req: express.Request, res: express.Response) { - const resultList = await UserRegistrationModel.listForApi({ - start: req.query.start, - count: req.query.count, - sort: req.query.sort, - search: req.query.search - }) - - return res.json({ - total: resultList.total, - data: resultList.data.map(d => d.toFormattedJSON()) - }) -} - -// --------------------------------------------------------------------------- - -async function registerUser (req: express.Request, res: express.Response) { - const body: UserRegister = req.body - - const userToCreate = buildUser({ - ...pick(body, [ 'username', 'password', 'email' ]), - - emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null - }) - - const { user, account, videoChannel } = await createUserAccountAndChannelAndPlaylist({ - userToCreate, - userDisplayName: body.displayName || undefined, - channelNames: body.channel - }) - - 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) - } - - Notifier.Instance.notifyOnNewDirectRegistration(user) - - Hooks.runAction('action:api.user.registered', { body, user, account, videoChannel, req, res }) - - return res.sendStatus(HttpStatusCode.NO_CONTENT_204) -} -- cgit v1.2.3