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/helpers/audit-logger.ts | 287 ----------------------------------------- 1 file changed, 287 deletions(-) delete mode 100644 server/helpers/audit-logger.ts (limited to 'server/helpers/audit-logger.ts') diff --git a/server/helpers/audit-logger.ts b/server/helpers/audit-logger.ts deleted file mode 100644 index 7e8a03e8f..000000000 --- a/server/helpers/audit-logger.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { diff } from 'deep-object-diff' -import express from 'express' -import flatten from 'flat' -import { chain } from 'lodash' -import { join } from 'path' -import { addColors, config, createLogger, format, transports } from 'winston' -import { AUDIT_LOG_FILENAME } from '@server/initializers/constants' -import { AdminAbuse, CustomConfig, User, VideoChannel, VideoChannelSync, VideoComment, VideoDetails, VideoImport } from '@shared/models' -import { CONFIG } from '../initializers/config' -import { jsonLoggerFormat, labelFormatter } from './logger' - -function getAuditIdFromRes (res: express.Response) { - return res.locals.oauth.token.User.username -} - -enum AUDIT_TYPE { - CREATE = 'create', - UPDATE = 'update', - DELETE = 'delete' -} - -const colors = config.npm.colors -colors.audit = config.npm.colors.info - -addColors(colors) - -const auditLogger = createLogger({ - levels: { audit: 0 }, - transports: [ - new transports.File({ - filename: join(CONFIG.STORAGE.LOG_DIR, AUDIT_LOG_FILENAME), - level: 'audit', - maxsize: 5242880, - maxFiles: 5, - format: format.combine( - format.timestamp(), - labelFormatter(), - format.splat(), - jsonLoggerFormat - ) - }) - ], - exitOnError: true -}) - -function auditLoggerWrapper (domain: string, user: string, action: AUDIT_TYPE, entity: EntityAuditView, oldEntity: EntityAuditView = null) { - let entityInfos: object - if (action === AUDIT_TYPE.UPDATE && oldEntity) { - const oldEntityKeys = oldEntity.toLogKeys() - const diffObject = diff(oldEntityKeys, entity.toLogKeys()) - const diffKeys = Object.entries(diffObject).reduce((newKeys, entry) => { - newKeys[`new-${entry[0]}`] = entry[1] - return newKeys - }, {}) - entityInfos = { ...oldEntityKeys, ...diffKeys } - } else { - entityInfos = { ...entity.toLogKeys() } - } - auditLogger.log('audit', JSON.stringify({ - user, - domain, - action, - ...entityInfos - })) -} - -function auditLoggerFactory (domain: string) { - return { - create (user: string, entity: EntityAuditView) { - auditLoggerWrapper(domain, user, AUDIT_TYPE.CREATE, entity) - }, - update (user: string, entity: EntityAuditView, oldEntity: EntityAuditView) { - auditLoggerWrapper(domain, user, AUDIT_TYPE.UPDATE, entity, oldEntity) - }, - delete (user: string, entity: EntityAuditView) { - auditLoggerWrapper(domain, user, AUDIT_TYPE.DELETE, entity) - } - } -} - -abstract class EntityAuditView { - constructor (private readonly keysToKeep: string[], private readonly prefix: string, private readonly entityInfos: object) { } - - toLogKeys (): object { - return chain(flatten(this.entityInfos, { delimiter: '-', safe: true })) - .pick(this.keysToKeep) - .mapKeys((_value, key) => `${this.prefix}-${key}`) - .value() - } -} - -const videoKeysToKeep = [ - 'tags', - 'uuid', - 'id', - 'uuid', - 'createdAt', - 'updatedAt', - 'publishedAt', - 'category', - 'licence', - 'language', - 'privacy', - 'description', - 'duration', - 'isLocal', - 'name', - 'thumbnailPath', - 'previewPath', - 'nsfw', - 'waitTranscoding', - 'account-id', - 'account-uuid', - 'account-name', - 'channel-id', - 'channel-uuid', - 'channel-name', - 'support', - 'commentsEnabled', - 'downloadEnabled' -] -class VideoAuditView extends EntityAuditView { - constructor (video: VideoDetails) { - super(videoKeysToKeep, 'video', video) - } -} - -const videoImportKeysToKeep = [ - 'id', - 'targetUrl', - 'video-name' -] -class VideoImportAuditView extends EntityAuditView { - constructor (videoImport: VideoImport) { - super(videoImportKeysToKeep, 'video-import', videoImport) - } -} - -const commentKeysToKeep = [ - 'id', - 'text', - 'threadId', - 'inReplyToCommentId', - 'videoId', - 'createdAt', - 'updatedAt', - 'totalReplies', - 'account-id', - 'account-uuid', - 'account-name' -] -class CommentAuditView extends EntityAuditView { - constructor (comment: VideoComment) { - super(commentKeysToKeep, 'comment', comment) - } -} - -const userKeysToKeep = [ - 'id', - 'username', - 'email', - 'nsfwPolicy', - 'autoPlayVideo', - 'role', - 'videoQuota', - 'createdAt', - 'account-id', - 'account-uuid', - 'account-name', - 'account-followingCount', - 'account-followersCount', - 'account-createdAt', - 'account-updatedAt', - 'account-avatar-path', - 'account-avatar-createdAt', - 'account-avatar-updatedAt', - 'account-displayName', - 'account-description', - 'videoChannels' -] -class UserAuditView extends EntityAuditView { - constructor (user: User) { - super(userKeysToKeep, 'user', user) - } -} - -const channelKeysToKeep = [ - 'id', - 'uuid', - 'name', - 'followingCount', - 'followersCount', - 'createdAt', - 'updatedAt', - 'avatar-path', - 'avatar-createdAt', - 'avatar-updatedAt', - 'displayName', - 'description', - 'support', - 'isLocal', - 'ownerAccount-id', - 'ownerAccount-uuid', - 'ownerAccount-name', - 'ownerAccount-displayedName' -] -class VideoChannelAuditView extends EntityAuditView { - constructor (channel: VideoChannel) { - super(channelKeysToKeep, 'channel', channel) - } -} - -const abuseKeysToKeep = [ - 'id', - 'reason', - 'reporterAccount', - 'createdAt' -] -class AbuseAuditView extends EntityAuditView { - constructor (abuse: AdminAbuse) { - super(abuseKeysToKeep, 'abuse', abuse) - } -} - -const customConfigKeysToKeep = [ - 'instance-name', - 'instance-shortDescription', - 'instance-description', - 'instance-terms', - 'instance-defaultClientRoute', - 'instance-defaultNSFWPolicy', - 'instance-customizations-javascript', - 'instance-customizations-css', - 'services-twitter-username', - 'services-twitter-whitelisted', - 'cache-previews-size', - 'cache-captions-size', - 'signup-enabled', - 'signup-limit', - 'signup-requiresEmailVerification', - 'admin-email', - 'user-videoQuota', - 'transcoding-enabled', - 'transcoding-threads', - 'transcoding-resolutions' -] -class CustomConfigAuditView extends EntityAuditView { - constructor (customConfig: CustomConfig) { - const infos: any = customConfig - const resolutionsDict = infos.transcoding.resolutions - const resolutionsArray = [] - - Object.entries(resolutionsDict) - .forEach(([ resolution, isEnabled ]) => { - if (isEnabled) resolutionsArray.push(resolution) - }) - - Object.assign({}, infos, { transcoding: { resolutions: resolutionsArray } }) - super(customConfigKeysToKeep, 'config', infos) - } -} - -const channelSyncKeysToKeep = [ - 'id', - 'externalChannelUrl', - 'channel-id', - 'channel-name' -] -class VideoChannelSyncAuditView extends EntityAuditView { - constructor (channelSync: VideoChannelSync) { - super(channelSyncKeysToKeep, 'channelSync', channelSync) - } -} - -export { - getAuditIdFromRes, - - auditLoggerFactory, - VideoImportAuditView, - VideoChannelAuditView, - CommentAuditView, - UserAuditView, - VideoAuditView, - AbuseAuditView, - CustomConfigAuditView, - VideoChannelSyncAuditView -} -- cgit v1.2.3