From 0626e7af82e02f8a5bd1e74a7d4d8c916d073ceb Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 24 Apr 2018 15:10:54 +0200 Subject: Add account view --- server/controllers/api/accounts.ts | 37 ++++++++++++-- server/controllers/api/index.ts | 2 +- server/controllers/api/users.ts | 3 +- server/controllers/api/videos/index.ts | 19 ++------ server/controllers/feeds.ts | 29 ++++------- server/helpers/express-utils.ts | 77 ++++++++++++++++++++++++++++++ server/helpers/utils.ts | 62 +----------------------- server/middlewares/servers.ts | 2 +- server/middlewares/validators/webfinger.ts | 2 +- server/models/video/video.ts | 73 +++++++++++++++++----------- 10 files changed, 174 insertions(+), 132 deletions(-) create mode 100644 server/helpers/express-utils.ts (limited to 'server') diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 4dc0cc16d..06ab04033 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts @@ -1,8 +1,11 @@ import * as express from 'express' import { getFormattedObjects } from '../../helpers/utils' -import { asyncMiddleware, paginationValidator, setDefaultSort, setDefaultPagination } from '../../middlewares' -import { accountsGetValidator, accountsSortValidator } from '../../middlewares/validators' +import { asyncMiddleware, optionalAuthenticate, paginationValidator, setDefaultPagination, setDefaultSort } from '../../middlewares' +import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators' import { AccountModel } from '../../models/account/account' +import { VideoModel } from '../../models/video/video' +import { VideoSortField } from '../../../client/src/app/shared/video/sort-field.type' +import { isNSFWHidden } from '../../helpers/express-utils' const accountsRouter = express.Router() @@ -19,6 +22,16 @@ accountsRouter.get('/:id', getAccount ) +accountsRouter.get('/:id/videos', + asyncMiddleware(accountsGetValidator), + paginationValidator, + videosSortValidator, + setDefaultSort, + setDefaultPagination, + optionalAuthenticate, + asyncMiddleware(getAccountVideos) +) + // --------------------------------------------------------------------------- export { @@ -28,7 +41,9 @@ export { // --------------------------------------------------------------------------- function getAccount (req: express.Request, res: express.Response, next: express.NextFunction) { - return res.json(res.locals.account.toFormattedJSON()) + const account: AccountModel = res.locals.account + + return res.json(account.toFormattedJSON()) } async function listAccounts (req: express.Request, res: express.Response, next: express.NextFunction) { @@ -36,3 +51,19 @@ async function listAccounts (req: express.Request, res: express.Response, next: return res.json(getFormattedObjects(resultList.data, resultList.total)) } + +async function getAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { + const account: AccountModel = res.locals.account + + const resultList = await VideoModel.listForApi( + req.query.start as number, + req.query.count as number, + req.query.sort as VideoSortField, + isNSFWHidden(res), + null, + false, + account.id + ) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts index 3b499f3b7..964d5d04c 100644 --- a/server/controllers/api/index.ts +++ b/server/controllers/api/index.ts @@ -1,5 +1,4 @@ import * as express from 'express' -import { badRequest } from '../../helpers/utils' import { configRouter } from './config' import { jobsRouter } from './jobs' import { oauthClientsRouter } from './oauth-clients' @@ -7,6 +6,7 @@ import { serverRouter } from './server' import { usersRouter } from './users' import { accountsRouter } from './accounts' import { videosRouter } from './videos' +import { badRequest } from '../../helpers/express-utils' const apiRouter = express.Router() diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index 6540adb1c..474329b58 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -7,7 +7,7 @@ import { UserCreate, UserRight, UserRole, UserUpdate, UserUpdateMe, UserVideoRat import { retryTransactionWrapper } from '../../helpers/database-utils' import { processImage } from '../../helpers/image-utils' import { logger } from '../../helpers/logger' -import { createReqFiles, getFormattedObjects } from '../../helpers/utils' +import { getFormattedObjects } from '../../helpers/utils' import { AVATARS_SIZE, CONFIG, IMAGE_MIMETYPE_EXT, RATES_LIMIT, sequelizeTypescript } from '../../initializers' import { updateActorAvatarInstance } from '../../lib/activitypub' import { sendUpdateActor } from '../../lib/activitypub/send' @@ -43,6 +43,7 @@ import { UserModel } from '../../models/account/user' import { OAuthTokenModel } from '../../models/oauth/oauth-token' import { VideoModel } from '../../models/video/video' import { VideoSortField } from '../../../client/src/app/shared/video/sort-field.type' +import { createReqFiles } from '../../helpers/express-utils' const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) const loginRateLimiter = new RateLimit({ diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 6e8601fa1..61b6c5826 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -6,7 +6,7 @@ import { retryTransactionWrapper } from '../../../helpers/database-utils' import { getVideoFileResolution } from '../../../helpers/ffmpeg-utils' import { processImage } from '../../../helpers/image-utils' import { logger } from '../../../helpers/logger' -import { createReqFiles, getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' +import { getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' import { CONFIG, IMAGE_MIMETYPE_EXT, @@ -19,11 +19,7 @@ import { VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' -import { - fetchRemoteVideoDescription, - getVideoActivityPubUrl, - shareVideoByServerAndChannel -} from '../../../lib/activitypub' +import { fetchRemoteVideoDescription, getVideoActivityPubUrl, shareVideoByServerAndChannel } from '../../../lib/activitypub' import { sendCreateVideo, sendCreateView, sendUpdateVideo } from '../../../lib/activitypub/send' import { JobQueue } from '../../../lib/job-queue' import { Redis } from '../../../lib/redis' @@ -49,9 +45,9 @@ import { blacklistRouter } from './blacklist' import { videoChannelRouter } from './channel' import { videoCommentRouter } from './comment' import { rateVideoRouter } from './rate' -import { User } from '../../../../shared/models/users' import { VideoFilter } from '../../../../shared/models/videos/video-query.type' import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' +import { isNSFWHidden, createReqFiles } from '../../../helpers/express-utils' const videosRouter = express.Router() @@ -444,12 +440,3 @@ async function searchVideos (req: express.Request, res: express.Response, next: return res.json(getFormattedObjects(resultList.data, resultList.total)) } - -function isNSFWHidden (res: express.Response) { - if (res.locals.oauth) { - const user: User = res.locals.oauth.token.User - if (user) return user.nsfwPolicy === 'do_not_list' - } - - return CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list' -} diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index 4a4dc3820..6a6af3e09 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts @@ -30,29 +30,18 @@ async function generateFeed (req: express.Request, res: express.Response, next: let feed = initFeed() const start = 0 - let resultList: ResultList const account: AccountModel = res.locals.account const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list' - if (account) { - resultList = await VideoModel.listAccountVideosForApi( - account.id, - start, - FEEDS.COUNT, - req.query.sort as VideoSortField, - hideNSFW, - true - ) - } else { - resultList = await VideoModel.listForApi( - start, - FEEDS.COUNT, - req.query.sort as VideoSortField, - hideNSFW, - req.query.filter, - true - ) - } + const resultList = await VideoModel.listForApi( + start, + FEEDS.COUNT, + req.query.sort as VideoSortField, + hideNSFW, + req.query.filter, + true, + account ? account.id : null + ) // Adding video items to the feed, one at a time resultList.data.forEach(video => { diff --git a/server/helpers/express-utils.ts b/server/helpers/express-utils.ts new file mode 100644 index 000000000..d023117a8 --- /dev/null +++ b/server/helpers/express-utils.ts @@ -0,0 +1,77 @@ +import * as express from 'express' +import * as multer from 'multer' +import { CONFIG, REMOTE_SCHEME } from '../initializers' +import { logger } from './logger' +import { User } from '../../shared/models/users' +import { generateRandomString } from './utils' + +function isNSFWHidden (res: express.Response) { + if (res.locals.oauth) { + const user: User = res.locals.oauth.token.User + if (user) return user.nsfwPolicy === 'do_not_list' + } + + return CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list' +} + +function getHostWithPort (host: string) { + const splitted = host.split(':') + + // The port was not specified + if (splitted.length === 1) { + if (REMOTE_SCHEME.HTTP === 'https') return host + ':443' + + return host + ':80' + } + + return host +} + +function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) { + return res.type('json').status(400).end() +} + +function createReqFiles ( + fieldNames: string[], + mimeTypes: { [ id: string ]: string }, + destinations: { [ fieldName: string ]: string } +) { + const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, destinations[ file.fieldname ]) + }, + + filename: async (req, file, cb) => { + const extension = mimeTypes[ file.mimetype ] + let randomString = '' + + try { + randomString = await generateRandomString(16) + } catch (err) { + logger.error('Cannot generate random string for file name.', { err }) + randomString = 'fake-random-string' + } + + cb(null, randomString + extension) + } + }) + + const fields = [] + for (const fieldName of fieldNames) { + fields.push({ + name: fieldName, + maxCount: 1 + }) + } + + return multer({ storage }).fields(fields) +} + +// --------------------------------------------------------------------------- + +export { + isNSFWHidden, + getHostWithPort, + badRequest, + createReqFiles +} diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index c58117219..058c3211e 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts @@ -1,68 +1,13 @@ -import * as express from 'express' -import * as multer from 'multer' import { Model } from 'sequelize-typescript' import { ResultList } from '../../shared' import { VideoResolution } from '../../shared/models/videos' -import { CONFIG, REMOTE_SCHEME } from '../initializers' +import { CONFIG } from '../initializers' import { UserModel } from '../models/account/user' import { ActorModel } from '../models/activitypub/actor' import { ApplicationModel } from '../models/application/application' import { pseudoRandomBytesPromise } from './core-utils' import { logger } from './logger' -function getHostWithPort (host: string) { - const splitted = host.split(':') - - // The port was not specified - if (splitted.length === 1) { - if (REMOTE_SCHEME.HTTP === 'https') return host + ':443' - - return host + ':80' - } - - return host -} - -function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) { - return res.type('json').status(400).end() -} - -function createReqFiles ( - fieldNames: string[], - mimeTypes: { [ id: string ]: string }, - destinations: { [ fieldName: string ]: string } -) { - const storage = multer.diskStorage({ - destination: (req, file, cb) => { - cb(null, destinations[file.fieldname]) - }, - - filename: async (req, file, cb) => { - const extension = mimeTypes[file.mimetype] - let randomString = '' - - try { - randomString = await generateRandomString(16) - } catch (err) { - logger.error('Cannot generate random string for file name.', { err }) - randomString = 'fake-random-string' - } - - cb(null, randomString + extension) - } - }) - - const fields = [] - for (const fieldName of fieldNames) { - fields.push({ - name: fieldName, - maxCount: 1 - }) - } - - return multer({ storage }).fields(fields) -} - async function generateRandomString (size: number) { const raw = await pseudoRandomBytesPromise(size) @@ -151,14 +96,11 @@ type SortType = { sortModel: any, sortValue: string } // --------------------------------------------------------------------------- export { - badRequest, generateRandomString, getFormattedObjects, isSignupAllowed, computeResolutionsToTranscode, resetSequelizeInstance, getServerActor, - SortType, - getHostWithPort, - createReqFiles + SortType } diff --git a/server/middlewares/servers.ts b/server/middlewares/servers.ts index a9dcad2d4..c52f4685b 100644 --- a/server/middlewares/servers.ts +++ b/server/middlewares/servers.ts @@ -1,6 +1,6 @@ import * as express from 'express' import 'express-validator' -import { getHostWithPort } from '../helpers/utils' +import { getHostWithPort } from '../helpers/express-utils' function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) { if (!req.body.hosts) return next() diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts index 3dbec6e44..3b9645048 100644 --- a/server/middlewares/validators/webfinger.ts +++ b/server/middlewares/validators/webfinger.ts @@ -2,9 +2,9 @@ import * as express from 'express' import { query } from 'express-validator/check' import { isWebfingerResourceValid } from '../../helpers/custom-validators/webfinger' import { logger } from '../../helpers/logger' -import { getHostWithPort } from '../../helpers/utils' import { ActorModel } from '../../models/activitypub/actor' import { areValidationErrors } from './utils' +import { getHostWithPort } from '../../helpers/express-utils' const webfingerValidator = [ query('resource').custom(isWebfingerResourceValid).withMessage('Should have a valid webfinger resource'), diff --git a/server/models/video/video.ts b/server/models/video/video.ts index b0fff6526..2ad9c00dd 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -95,7 +95,33 @@ enum ScopeNames { } @Scopes({ - [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean) => { + [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean, accountId?: number) => { + const accountInclude = { + attributes: [ 'name' ], + model: AccountModel.unscoped(), + required: true, + where: {}, + include: [ + { + attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], + model: ActorModel.unscoped(), + required: true, + where: VideoModel.buildActorWhereWithFilter(filter), + include: [ + { + attributes: [ 'host' ], + model: ServerModel.unscoped(), + required: false + }, + { + model: AvatarModel.unscoped(), + required: false + } + ] + } + ] + } + const query: IFindOptions = { where: { id: { @@ -125,30 +151,7 @@ enum ScopeNames { model: VideoChannelModel.unscoped(), required: true, include: [ - { - attributes: [ 'name' ], - model: AccountModel.unscoped(), - required: true, - include: [ - { - attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], - model: ActorModel.unscoped(), - required: true, - where: VideoModel.buildActorWhereWithFilter(filter), - include: [ - { - attributes: [ 'host' ], - model: ServerModel.unscoped(), - required: false - }, - { - model: AvatarModel.unscoped(), - required: false - } - ] - } - ] - } + accountInclude ] } ] @@ -166,6 +169,12 @@ enum ScopeNames { query.where['nsfw'] = false } + if (accountId) { + accountInclude.where = { + id: accountId + } + } + return query }, [ScopeNames.WITH_ACCOUNT_DETAILS]: { @@ -688,7 +697,15 @@ export class VideoModel extends Model { }) } - static async listForApi (start: number, count: number, sort: string, hideNSFW: boolean, filter?: VideoFilter, withFiles = false) { + static async listForApi ( + start: number, + count: number, + sort: string, + hideNSFW: boolean, + filter?: VideoFilter, + withFiles = false, + accountId?: number + ) { const query = { offset: start, limit: count, @@ -696,7 +713,7 @@ export class VideoModel extends Model { } const serverActor = await getServerActor() - return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles ] }) + return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles, accountId ] }) .findAndCountAll(query) .then(({ rows, count }) => { return { @@ -879,8 +896,6 @@ export class VideoModel extends Model { private static getLanguageLabel (id: string) { let languageLabel = VIDEO_LANGUAGES[id] - console.log(VIDEO_LANGUAGES) - console.log(id) if (!languageLabel) languageLabel = 'Unknown' return languageLabel -- cgit v1.2.3