From 954605a804da399317ca62afa2fb9244afa11ebf Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 27 Oct 2017 16:55:03 +0200 Subject: Support roles with rights and add moderator role --- server/controllers/api/pods.ts | 9 +++--- server/controllers/api/request-schedulers.ts | 6 ++-- server/controllers/api/users.ts | 20 ++++++------ server/controllers/api/videos/abuse.ts | 6 ++-- server/controllers/api/videos/blacklist.ts | 10 +++--- server/helpers/custom-validators/users.ts | 11 +++---- server/initializers/constants.ts | 13 +------- server/initializers/installer.ts | 5 +-- server/initializers/migrations/0085-user-role.ts | 39 ++++++++++++++++++++++++ server/middlewares/admin.ts | 20 ------------ server/middlewares/index.ts | 2 +- server/middlewares/user-right.ts | 24 +++++++++++++++ server/middlewares/validators/users.ts | 5 ++- server/middlewares/validators/video-channels.ts | 6 ++-- server/middlewares/validators/videos.ts | 3 +- server/models/user/user-interface.ts | 9 +++--- server/models/user/user.ts | 29 +++++++++++------- 17 files changed, 133 insertions(+), 84 deletions(-) create mode 100644 server/initializers/migrations/0085-user-role.ts delete mode 100644 server/middlewares/admin.ts create mode 100644 server/middlewares/user-right.ts (limited to 'server') diff --git a/server/controllers/api/pods.ts b/server/controllers/api/pods.ts index bf1b744e5..b44cd6b83 100644 --- a/server/controllers/api/pods.ts +++ b/server/controllers/api/pods.ts @@ -9,7 +9,7 @@ import { } from '../../lib' import { authenticate, - ensureIsAdmin, + ensureUserHasRight, makeFriendsValidator, setBodyHostsPort, podRemoveValidator, @@ -20,6 +20,7 @@ import { asyncMiddleware } from '../../middlewares' import { PodInstance } from '../../models' +import { UserRight } from '../../../shared' const podsRouter = express.Router() @@ -32,19 +33,19 @@ podsRouter.get('/', ) podsRouter.post('/make-friends', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_PODS), makeFriendsValidator, setBodyHostsPort, asyncMiddleware(makeFriendsController) ) podsRouter.get('/quit-friends', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_PODS), asyncMiddleware(quitFriendsController) ) podsRouter.delete('/:id', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_PODS), podRemoveValidator, asyncMiddleware(removeFriendController) ) diff --git a/server/controllers/api/request-schedulers.ts b/server/controllers/api/request-schedulers.ts index 28f46f3ee..4c8fbe18b 100644 --- a/server/controllers/api/request-schedulers.ts +++ b/server/controllers/api/request-schedulers.ts @@ -7,14 +7,14 @@ import { getRequestVideoQaduScheduler, getRequestVideoEventScheduler } from '../../lib' -import { authenticate, ensureIsAdmin, asyncMiddleware } from '../../middlewares' -import { RequestSchedulerStatsAttributes } from '../../../shared' +import { authenticate, ensureUserHasRight, asyncMiddleware } from '../../middlewares' +import { RequestSchedulerStatsAttributes, UserRight } from '../../../shared' const requestSchedulerRouter = express.Router() requestSchedulerRouter.get('/stats', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_REQUEST_SCHEDULERS), asyncMiddleware(getRequestSchedulersStats) ) diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index 18a094f03..fdc9b0c87 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -1,11 +1,10 @@ import * as express from 'express' -import { database as db } from '../../initializers/database' -import { USER_ROLES, CONFIG } from '../../initializers' +import { database as db, CONFIG } from '../../initializers' import { logger, getFormattedObjects, retryTransactionWrapper } from '../../helpers' import { authenticate, - ensureIsAdmin, + ensureUserHasRight, ensureUserRegistrationAllowed, usersAddValidator, usersRegisterValidator, @@ -25,7 +24,9 @@ import { UserVideoRate as FormattedUserVideoRate, UserCreate, UserUpdate, - UserUpdateMe + UserUpdateMe, + UserRole, + UserRight } from '../../../shared' import { createUserAuthorAndChannel } from '../../lib' import { UserInstance } from '../../models' @@ -58,7 +59,7 @@ usersRouter.get('/:id', usersRouter.post('/', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_USERS), usersAddValidator, createUserRetryWrapper ) @@ -77,14 +78,14 @@ usersRouter.put('/me', usersRouter.put('/:id', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_USERS), usersUpdateValidator, asyncMiddleware(updateUser) ) usersRouter.delete('/:id', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_USERS), usersRemoveValidator, asyncMiddleware(removeUser) ) @@ -119,7 +120,7 @@ async function createUser (req: express.Request, res: express.Response, next: ex password: body.password, email: body.email, displayNSFW: false, - role: USER_ROLES.USER, + role: body.role, videoQuota: body.videoQuota }) @@ -136,7 +137,7 @@ async function registerUser (req: express.Request, res: express.Response, next: password: body.password, email: body.email, displayNSFW: false, - role: USER_ROLES.USER, + role: UserRole.USER, videoQuota: CONFIG.USER.VIDEO_QUOTA }) @@ -203,6 +204,7 @@ async function updateUser (req: express.Request, res: express.Response, next: ex if (body.email !== undefined) user.email = body.email if (body.videoQuota !== undefined) user.videoQuota = body.videoQuota + if (body.role !== undefined) user.role = body.role await user.save() diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts index 4c7abf395..04349042b 100644 --- a/server/controllers/api/videos/abuse.ts +++ b/server/controllers/api/videos/abuse.ts @@ -9,7 +9,7 @@ import { } from '../../../helpers' import { authenticate, - ensureIsAdmin, + ensureUserHasRight, paginationValidator, videoAbuseReportValidator, videoAbusesSortValidator, @@ -18,13 +18,13 @@ import { asyncMiddleware } from '../../../middlewares' import { VideoInstance } from '../../../models' -import { VideoAbuseCreate } from '../../../../shared' +import { VideoAbuseCreate, UserRight } from '../../../../shared' const abuseVideoRouter = express.Router() abuseVideoRouter.get('/abuse', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_VIDEO_ABUSES), paginationValidator, videoAbusesSortValidator, setVideoAbusesSort, diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts index 5a2c3fd80..be7cf6ea4 100644 --- a/server/controllers/api/videos/blacklist.ts +++ b/server/controllers/api/videos/blacklist.ts @@ -4,7 +4,7 @@ import { database as db } from '../../../initializers' import { logger, getFormattedObjects } from '../../../helpers' import { authenticate, - ensureIsAdmin, + ensureUserHasRight, videosBlacklistAddValidator, videosBlacklistRemoveValidator, paginationValidator, @@ -14,20 +14,20 @@ import { asyncMiddleware } from '../../../middlewares' import { BlacklistedVideoInstance } from '../../../models' -import { BlacklistedVideo } from '../../../../shared' +import { BlacklistedVideo, UserRight } from '../../../../shared' const blacklistRouter = express.Router() blacklistRouter.post('/:videoId/blacklist', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), videosBlacklistAddValidator, asyncMiddleware(addVideoToBlacklist) ) blacklistRouter.get('/blacklist', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), paginationValidator, blacklistSortValidator, setBlacklistSort, @@ -37,7 +37,7 @@ blacklistRouter.get('/blacklist', blacklistRouter.delete('/:videoId/blacklist', authenticate, - ensureIsAdmin, + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), videosBlacklistRemoveValidator, asyncMiddleware(removeVideoFromBlacklistController) ) diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts index c180eccda..f423d6317 100644 --- a/server/helpers/custom-validators/users.ts +++ b/server/helpers/custom-validators/users.ts @@ -1,9 +1,8 @@ -import { values } from 'lodash' import * as validator from 'validator' import 'express-validator' import { exists } from './misc' -import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers' +import { CONSTRAINTS_FIELDS } from '../../initializers' import { UserRole } from '../../../shared' const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS @@ -12,10 +11,6 @@ function isUserPasswordValid (value: string) { return validator.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD) } -function isUserRoleValid (value: string) { - return values(USER_ROLES).indexOf(value as UserRole) !== -1 -} - function isUserVideoQuotaValid (value: string) { return exists(value) && validator.isInt(value + '', USERS_CONSTRAINTS_FIELDS.VIDEO_QUOTA) } @@ -30,6 +25,10 @@ function isUserDisplayNSFWValid (value: any) { return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) } +function isUserRoleValid (value: any) { + return exists(value) && validator.isInt('' + value) && UserRole[value] !== undefined +} + // --------------------------------------------------------------------------- export { diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 1581a3195..6dc9737d2 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -5,7 +5,6 @@ import { join } from 'path' import { root, isTestInstance } from '../helpers/core-utils' import { - UserRole, VideoRateType, RequestEndpoint, RequestVideoEventType, @@ -16,7 +15,7 @@ import { // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 80 +const LAST_MIGRATION_VERSION = 85 // --------------------------------------------------------------------------- @@ -283,7 +282,6 @@ const JOB_STATES: { [ id: string ]: JobState } = { } // How many maximum jobs we fetch from the database per cycle const JOBS_FETCH_LIMIT_PER_CYCLE = 10 -const JOBS_CONCURRENCY = 1 // 1 minutes let JOBS_FETCHING_INTERVAL = 60000 @@ -334,13 +332,6 @@ const CACHE = { // --------------------------------------------------------------------------- -const USER_ROLES: { [ id: string ]: UserRole } = { - ADMIN: 'admin', - USER: 'user' -} - -// --------------------------------------------------------------------------- - const OPENGRAPH_AND_OEMBED_COMMENT = '' // --------------------------------------------------------------------------- @@ -367,7 +358,6 @@ export { EMBED_SIZE, FRIEND_SCORE, JOB_STATES, - JOBS_CONCURRENCY, JOBS_FETCH_LIMIT_PER_CYCLE, JOBS_FETCHING_INTERVAL, LAST_MIGRATION_VERSION, @@ -401,7 +391,6 @@ export { STATIC_MAX_AGE, STATIC_PATHS, THUMBNAILS_SIZE, - USER_ROLES, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index 4c04290fc..077472341 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -2,10 +2,11 @@ import * as passwordGenerator from 'password-generator' import * as Bluebird from 'bluebird' import { database as db } from './database' -import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION, CACHE } from './constants' +import { CONFIG, LAST_MIGRATION_VERSION, CACHE } from './constants' import { clientsExist, usersExist } from './checker' import { logger, createCertsIfNotExist, mkdirpPromise, rimrafPromise } from '../helpers' import { createUserAuthorAndChannel } from '../lib' +import { UserRole } from '../../shared' async function installApplication () { await db.sequelize.sync() @@ -88,7 +89,7 @@ async function createOAuthAdminIfNotExist () { logger.info('Creating the administrator.') const username = 'root' - const role = USER_ROLES.ADMIN + const role = UserRole.ADMINISTRATOR const email = CONFIG.ADMIN.EMAIL let validatePassword = true let password = '' diff --git a/server/initializers/migrations/0085-user-role.ts b/server/initializers/migrations/0085-user-role.ts new file mode 100644 index 000000000..e67c5ca24 --- /dev/null +++ b/server/initializers/migrations/0085-user-role.ts @@ -0,0 +1,39 @@ +import * as Sequelize from 'sequelize' +import * as uuidv4 from 'uuid/v4' + +async function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize, + db: any +}): Promise { + const q = utils.queryInterface + + await q.renameColumn('Users', 'role', 'oldRole') + + const data = { + type: Sequelize.INTEGER, + allowNull: true + } + await q.addColumn('Users', 'role', data) + + let query = 'UPDATE "Users" SET "role" = 0 WHERE "oldRole" = \'admin\'' + await utils.sequelize.query(query) + + query = 'UPDATE "Users" SET "role" = 2 WHERE "oldRole" = \'user\'' + await utils.sequelize.query(query) + + data.allowNull = false + await q.changeColumn('Users', 'role', data) + + await q.removeColumn('Users', 'oldRole') +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} diff --git a/server/middlewares/admin.ts b/server/middlewares/admin.ts deleted file mode 100644 index 812397352..000000000 --- a/server/middlewares/admin.ts +++ /dev/null @@ -1,20 +0,0 @@ -import 'express-validator' -import * as express from 'express' - -import { logger } from '../helpers' - -function ensureIsAdmin (req: express.Request, res: express.Response, next: express.NextFunction) { - const user = res.locals.oauth.token.user - if (user.isAdmin() === false) { - logger.info('A non admin user is trying to access to an admin content.') - return res.sendStatus(403) - } - - return next() -} - -// --------------------------------------------------------------------------- - -export { - ensureIsAdmin -} diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts index 0e2c850e1..cec3e0b2a 100644 --- a/server/middlewares/index.ts +++ b/server/middlewares/index.ts @@ -1,5 +1,4 @@ export * from './validators' -export * from './admin' export * from './async' export * from './oauth' export * from './pagination' @@ -7,3 +6,4 @@ export * from './pods' export * from './search' export * from './secure' export * from './sort' +export * from './user-right' diff --git a/server/middlewares/user-right.ts b/server/middlewares/user-right.ts new file mode 100644 index 000000000..bcebe9d7f --- /dev/null +++ b/server/middlewares/user-right.ts @@ -0,0 +1,24 @@ +import 'express-validator' +import * as express from 'express' + +import { UserInstance } from '../models' +import { UserRight } from '../../shared' +import { logger } from '../helpers' + +function ensureUserHasRight (userRight: UserRight) { + return function (req: express.Request, res: express.Response, next: express.NextFunction) { + const user: UserInstance = res.locals.oauth.token.user + if (user.hasRight(userRight) === false) { + logger.info('User %s does not have right %s to access to %s.', user.username, UserRight[userRight], req.path) + return res.sendStatus(403) + } + + return next() + } +} + +// --------------------------------------------------------------------------- + +export { + ensureUserHasRight +} diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 1a33cfd8c..0b463acc0 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts @@ -13,7 +13,8 @@ import { isUserPasswordValid, isUserVideoQuotaValid, isUserDisplayNSFWValid, - isIdOrUUIDValid + isIdOrUUIDValid, + isUserRoleValid } from '../../helpers' import { UserInstance, VideoInstance } from '../../models' @@ -22,6 +23,7 @@ const usersAddValidator = [ body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'), body('email').isEmail().withMessage('Should have a valid email'), body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), + body('role').custom(isUserRoleValid).withMessage('Should have a valid role'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersAdd parameters', { parameters: req.body }) @@ -75,6 +77,7 @@ const usersUpdateValidator = [ param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), body('email').optional().isEmail().withMessage('Should have a valid email attribute'), body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), + body('role').optional().custom(isUserRoleValid).withMessage('Should have a valid role'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersUpdate parameters', { parameters: req.body }) diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index 979fbd34a..7d611728b 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts @@ -11,6 +11,8 @@ import { checkVideoChannelExists, checkVideoAuthorExists } from '../../helpers' +import { UserInstance } from '../../models' +import { UserRight } from '../../../shared' const listVideoAuthorChannelsValidator = [ param('authorId').custom(isIdOrUUIDValid).withMessage('Should have a valid author id'), @@ -106,7 +108,7 @@ export { // --------------------------------------------------------------------------- function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => void) { - const user = res.locals.oauth.token.User + const user: UserInstance = res.locals.oauth.token.User // Retrieve the user who did the request if (res.locals.videoChannel.isOwned() === false) { @@ -118,7 +120,7 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => // Check if the user can delete the video channel // The user can delete it if s/he is an admin // Or if s/he is the video channel's author - if (user.isAdmin() === false && res.locals.videoChannel.Author.userId !== user.id) { + if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && res.locals.videoChannel.Author.userId !== user.id) { return res.status(403) .json({ error: 'Cannot remove video channel of another user' }) .end() diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index a032d14ce..0c07404c5 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -22,6 +22,7 @@ import { checkVideoExists, isIdValid } from '../../helpers' +import { UserRight } from '../../../shared' const videosAddValidator = [ body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage( @@ -231,7 +232,7 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac // Check if the user can delete the video // The user can delete it if s/he is an admin // Or if s/he is the video's author - if (user.isAdmin() === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) { + if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) { return res.status(403) .json({ error: 'Cannot remove video of another user' }) .end() diff --git a/server/models/user/user-interface.ts b/server/models/user/user-interface.ts index 1b5233eaf..49c75aa3b 100644 --- a/server/models/user/user-interface.ts +++ b/server/models/user/user-interface.ts @@ -3,15 +3,16 @@ import * as Promise from 'bluebird' // Don't use barrel, import just what we need import { User as FormattedUser } from '../../../shared/models/users/user.model' -import { UserRole } from '../../../shared/models/users/user-role.type' import { ResultList } from '../../../shared/models/result-list.model' import { AuthorInstance } from '../video/author-interface' +import { UserRight } from '../../../shared/models/users/user-right.enum' +import { UserRole } from '../../../shared/models/users/user-role' export namespace UserMethods { + export type HasRight = (this: UserInstance, right: UserRight) => boolean export type IsPasswordMatch = (this: UserInstance, password: string) => Promise export type ToFormattedJSON = (this: UserInstance) => FormattedUser - export type IsAdmin = (this: UserInstance) => boolean export type IsAbleToUploadVideo = (this: UserInstance, videoFile: Express.Multer.File) => Promise export type CountTotal = () => Promise @@ -31,7 +32,7 @@ export namespace UserMethods { export interface UserClass { isPasswordMatch: UserMethods.IsPasswordMatch, toFormattedJSON: UserMethods.ToFormattedJSON, - isAdmin: UserMethods.IsAdmin, + hasRight: UserMethods.HasRight, isAbleToUploadVideo: UserMethods.IsAbleToUploadVideo, countTotal: UserMethods.CountTotal, @@ -62,7 +63,7 @@ export interface UserInstance extends UserClass, UserAttributes, Sequelize.Insta isPasswordMatch: UserMethods.IsPasswordMatch toFormattedJSON: UserMethods.ToFormattedJSON - isAdmin: UserMethods.IsAdmin + hasRight: UserMethods.HasRight } export interface UserModel extends UserClass, Sequelize.Model {} diff --git a/server/models/user/user.ts b/server/models/user/user.ts index 074c9c121..3c625e450 100644 --- a/server/models/user/user.ts +++ b/server/models/user/user.ts @@ -1,17 +1,17 @@ -import { values } from 'lodash' import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' import { getSort } from '../utils' -import { USER_ROLES } from '../../initializers' import { cryptPassword, comparePassword, isUserPasswordValid, isUserUsernameValid, isUserDisplayNSFWValid, - isUserVideoQuotaValid + isUserVideoQuotaValid, + isUserRoleValid } from '../../helpers' +import { UserRight, USER_ROLE_LABELS, hasUserRight } from '../../../shared' import { addMethodsToModel } from '../utils' import { @@ -23,8 +23,8 @@ import { let User: Sequelize.Model let isPasswordMatch: UserMethods.IsPasswordMatch +let hasRight: UserMethods.HasRight let toFormattedJSON: UserMethods.ToFormattedJSON -let isAdmin: UserMethods.IsAdmin let countTotal: UserMethods.CountTotal let getByUsername: UserMethods.GetByUsername let listForApi: UserMethods.ListForApi @@ -76,8 +76,14 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da } }, role: { - type: DataTypes.ENUM(values(USER_ROLES)), - allowNull: false + type: DataTypes.INTEGER, + allowNull: false, + validate: { + roleValid: value => { + const res = isUserRoleValid(value) + if (res === false) throw new Error('Role is not valid.') + } + } }, videoQuota: { type: DataTypes.BIGINT, @@ -120,9 +126,9 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da loadByUsernameOrEmail ] const instanceMethods = [ + hasRight, isPasswordMatch, toFormattedJSON, - isAdmin, isAbleToUploadVideo ] addMethodsToModel(User, classMethods, instanceMethods) @@ -139,6 +145,10 @@ function beforeCreateOrUpdate (user: UserInstance) { // ------------------------------ METHODS ------------------------------ +hasRight = function (this: UserInstance, right: UserRight) { + return hasUserRight(this.role, right) +} + isPasswordMatch = function (this: UserInstance, password: string) { return comparePassword(password, this.password) } @@ -150,6 +160,7 @@ toFormattedJSON = function (this: UserInstance) { email: this.email, displayNSFW: this.displayNSFW, role: this.role, + roleLabel: USER_ROLE_LABELS[this.role], videoQuota: this.videoQuota, createdAt: this.createdAt, author: { @@ -174,10 +185,6 @@ toFormattedJSON = function (this: UserInstance) { return json } -isAdmin = function (this: UserInstance) { - return this.role === USER_ROLES.ADMIN -} - isAbleToUploadVideo = function (this: UserInstance, videoFile: Express.Multer.File) { if (this.videoQuota === -1) return Promise.resolve(true) -- cgit v1.2.3