diff options
Diffstat (limited to 'server/controllers/api')
-rw-r--r-- | server/controllers/api/blocklist.ts | 108 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 12 | ||||
-rw-r--r-- | server/controllers/api/index.ts | 2 | ||||
-rw-r--r-- | server/controllers/api/plugins.ts | 7 | ||||
-rw-r--r-- | server/controllers/api/users/my-subscriptions.ts | 21 | ||||
-rw-r--r-- | server/controllers/api/videos/upload.ts | 9 |
6 files changed, 139 insertions, 20 deletions
diff --git a/server/controllers/api/blocklist.ts b/server/controllers/api/blocklist.ts new file mode 100644 index 000000000..1e936ad10 --- /dev/null +++ b/server/controllers/api/blocklist.ts | |||
@@ -0,0 +1,108 @@ | |||
1 | import express from 'express' | ||
2 | import { handleToNameAndHost } from '@server/helpers/actors' | ||
3 | import { AccountBlocklistModel } from '@server/models/account/account-blocklist' | ||
4 | import { getServerActor } from '@server/models/application/application' | ||
5 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' | ||
6 | import { MActorAccountId, MUserAccountId } from '@server/types/models' | ||
7 | import { BlockStatus } from '@shared/models' | ||
8 | import { asyncMiddleware, blocklistStatusValidator, optionalAuthenticate } from '../../middlewares' | ||
9 | import { logger } from '@server/helpers/logger' | ||
10 | |||
11 | const blocklistRouter = express.Router() | ||
12 | |||
13 | blocklistRouter.get('/status', | ||
14 | optionalAuthenticate, | ||
15 | blocklistStatusValidator, | ||
16 | asyncMiddleware(getBlocklistStatus) | ||
17 | ) | ||
18 | |||
19 | // --------------------------------------------------------------------------- | ||
20 | |||
21 | export { | ||
22 | blocklistRouter | ||
23 | } | ||
24 | |||
25 | // --------------------------------------------------------------------------- | ||
26 | |||
27 | async function getBlocklistStatus (req: express.Request, res: express.Response) { | ||
28 | const hosts = req.query.hosts as string[] | ||
29 | const accounts = req.query.accounts as string[] | ||
30 | const user = res.locals.oauth?.token.User | ||
31 | |||
32 | const serverActor = await getServerActor() | ||
33 | |||
34 | const byAccountIds = [ serverActor.Account.id ] | ||
35 | if (user) byAccountIds.push(user.Account.id) | ||
36 | |||
37 | const status: BlockStatus = { | ||
38 | accounts: {}, | ||
39 | hosts: {} | ||
40 | } | ||
41 | |||
42 | const baseOptions = { | ||
43 | byAccountIds, | ||
44 | user, | ||
45 | serverActor, | ||
46 | status | ||
47 | } | ||
48 | |||
49 | await Promise.all([ | ||
50 | populateServerBlocklistStatus({ ...baseOptions, hosts }), | ||
51 | populateAccountBlocklistStatus({ ...baseOptions, accounts }) | ||
52 | ]) | ||
53 | |||
54 | return res.json(status) | ||
55 | } | ||
56 | |||
57 | async function populateServerBlocklistStatus (options: { | ||
58 | byAccountIds: number[] | ||
59 | user?: MUserAccountId | ||
60 | serverActor: MActorAccountId | ||
61 | hosts: string[] | ||
62 | status: BlockStatus | ||
63 | }) { | ||
64 | const { byAccountIds, user, serverActor, hosts, status } = options | ||
65 | |||
66 | if (!hosts || hosts.length === 0) return | ||
67 | |||
68 | const serverBlocklistStatus = await ServerBlocklistModel.getBlockStatus(byAccountIds, hosts) | ||
69 | |||
70 | logger.debug('Got server blocklist status.', { serverBlocklistStatus, byAccountIds, hosts }) | ||
71 | |||
72 | for (const host of hosts) { | ||
73 | const block = serverBlocklistStatus.find(b => b.host === host) | ||
74 | |||
75 | status.hosts[host] = getStatus(block, serverActor, user) | ||
76 | } | ||
77 | } | ||
78 | |||
79 | async function populateAccountBlocklistStatus (options: { | ||
80 | byAccountIds: number[] | ||
81 | user?: MUserAccountId | ||
82 | serverActor: MActorAccountId | ||
83 | accounts: string[] | ||
84 | status: BlockStatus | ||
85 | }) { | ||
86 | const { byAccountIds, user, serverActor, accounts, status } = options | ||
87 | |||
88 | if (!accounts || accounts.length === 0) return | ||
89 | |||
90 | const accountBlocklistStatus = await AccountBlocklistModel.getBlockStatus(byAccountIds, accounts) | ||
91 | |||
92 | logger.debug('Got account blocklist status.', { accountBlocklistStatus, byAccountIds, accounts }) | ||
93 | |||
94 | for (const account of accounts) { | ||
95 | const sanitizedHandle = handleToNameAndHost(account) | ||
96 | |||
97 | const block = accountBlocklistStatus.find(b => b.name === sanitizedHandle.name && b.host === sanitizedHandle.host) | ||
98 | |||
99 | status.accounts[sanitizedHandle.handle] = getStatus(block, serverActor, user) | ||
100 | } | ||
101 | } | ||
102 | |||
103 | function getStatus (block: { accountId: number }, serverActor: MActorAccountId, user?: MUserAccountId) { | ||
104 | return { | ||
105 | blockedByServer: !!(block && block.accountId === serverActor.Account.id), | ||
106 | blockedByUser: !!(block && user && block.accountId === user.Account.id) | ||
107 | } | ||
108 | } | ||
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 805ad99c7..b253db397 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -169,6 +169,18 @@ function customConfig (): CustomConfig { | |||
169 | whitelisted: CONFIG.SERVICES.TWITTER.WHITELISTED | 169 | whitelisted: CONFIG.SERVICES.TWITTER.WHITELISTED |
170 | } | 170 | } |
171 | }, | 171 | }, |
172 | client: { | ||
173 | videos: { | ||
174 | miniature: { | ||
175 | preferAuthorDisplayName: CONFIG.CLIENT.VIDEOS.MINIATURE.PREFER_AUTHOR_DISPLAY_NAME | ||
176 | } | ||
177 | }, | ||
178 | menu: { | ||
179 | login: { | ||
180 | redirectOnSingleExternalAuth: CONFIG.CLIENT.MENU.LOGIN.REDIRECT_ON_SINGLE_EXTERNAL_AUTH | ||
181 | } | ||
182 | } | ||
183 | }, | ||
172 | cache: { | 184 | cache: { |
173 | previews: { | 185 | previews: { |
174 | size: CONFIG.CACHE.PREVIEWS.SIZE | 186 | size: CONFIG.CACHE.PREVIEWS.SIZE |
diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts index 9949b378a..5f49336b1 100644 --- a/server/controllers/api/index.ts +++ b/server/controllers/api/index.ts | |||
@@ -6,6 +6,7 @@ import { badRequest } from '../../helpers/express-utils' | |||
6 | import { CONFIG } from '../../initializers/config' | 6 | import { CONFIG } from '../../initializers/config' |
7 | import { abuseRouter } from './abuse' | 7 | import { abuseRouter } from './abuse' |
8 | import { accountsRouter } from './accounts' | 8 | import { accountsRouter } from './accounts' |
9 | import { blocklistRouter } from './blocklist' | ||
9 | import { bulkRouter } from './bulk' | 10 | import { bulkRouter } from './bulk' |
10 | import { configRouter } from './config' | 11 | import { configRouter } from './config' |
11 | import { customPageRouter } from './custom-page' | 12 | import { customPageRouter } from './custom-page' |
@@ -49,6 +50,7 @@ apiRouter.use('/search', searchRouter) | |||
49 | apiRouter.use('/overviews', overviewsRouter) | 50 | apiRouter.use('/overviews', overviewsRouter) |
50 | apiRouter.use('/plugins', pluginRouter) | 51 | apiRouter.use('/plugins', pluginRouter) |
51 | apiRouter.use('/custom-pages', customPageRouter) | 52 | apiRouter.use('/custom-pages', customPageRouter) |
53 | apiRouter.use('/blocklist', blocklistRouter) | ||
52 | apiRouter.use('/ping', pong) | 54 | apiRouter.use('/ping', pong) |
53 | apiRouter.use('/*', badRequest) | 55 | apiRouter.use('/*', badRequest) |
54 | 56 | ||
diff --git a/server/controllers/api/plugins.ts b/server/controllers/api/plugins.ts index 2de7fe41f..de9e055dc 100644 --- a/server/controllers/api/plugins.ts +++ b/server/controllers/api/plugins.ts | |||
@@ -144,8 +144,13 @@ async function installPlugin (req: express.Request, res: express.Response) { | |||
144 | 144 | ||
145 | const fromDisk = !!body.path | 145 | const fromDisk = !!body.path |
146 | const toInstall = body.npmName || body.path | 146 | const toInstall = body.npmName || body.path |
147 | |||
148 | const pluginVersion = body.pluginVersion && body.npmName | ||
149 | ? body.pluginVersion | ||
150 | : undefined | ||
151 | |||
147 | try { | 152 | try { |
148 | const plugin = await PluginManager.Instance.install(toInstall, undefined, fromDisk) | 153 | const plugin = await PluginManager.Instance.install(toInstall, pluginVersion, fromDisk) |
149 | 154 | ||
150 | return res.json(plugin.toFormattedJSON()) | 155 | return res.json(plugin.toFormattedJSON()) |
151 | } catch (err) { | 156 | } catch (err) { |
diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts index 6799ca8c5..fb1f68635 100644 --- a/server/controllers/api/users/my-subscriptions.ts +++ b/server/controllers/api/users/my-subscriptions.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import 'multer' | 1 | import 'multer' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { handlesToNameAndHost } from '@server/helpers/actors' | ||
3 | import { pickCommonVideoQuery } from '@server/helpers/query' | 4 | import { pickCommonVideoQuery } from '@server/helpers/query' |
4 | import { sendUndoFollow } from '@server/lib/activitypub/send' | 5 | import { sendUndoFollow } from '@server/lib/activitypub/send' |
5 | import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' | 6 | import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' |
@@ -7,7 +8,6 @@ import { VideoChannelModel } from '@server/models/video/video-channel' | |||
7 | import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' | 8 | import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' |
8 | import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' | 9 | import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' |
9 | import { getFormattedObjects } from '../../../helpers/utils' | 10 | import { getFormattedObjects } from '../../../helpers/utils' |
10 | import { WEBSERVER } from '../../../initializers/constants' | ||
11 | import { sequelizeTypescript } from '../../../initializers/database' | 11 | import { sequelizeTypescript } from '../../../initializers/database' |
12 | import { JobQueue } from '../../../lib/job-queue' | 12 | import { JobQueue } from '../../../lib/job-queue' |
13 | import { | 13 | import { |
@@ -89,28 +89,23 @@ async function areSubscriptionsExist (req: express.Request, res: express.Respons | |||
89 | const uris = req.query.uris as string[] | 89 | const uris = req.query.uris as string[] |
90 | const user = res.locals.oauth.token.User | 90 | const user = res.locals.oauth.token.User |
91 | 91 | ||
92 | const handles = uris.map(u => { | 92 | const sanitizedHandles = handlesToNameAndHost(uris) |
93 | let [ name, host ] = u.split('@') | ||
94 | if (host === WEBSERVER.HOST) host = null | ||
95 | 93 | ||
96 | return { name, host, uri: u } | 94 | const results = await ActorFollowModel.listSubscriptionsOf(user.Account.Actor.id, sanitizedHandles) |
97 | }) | ||
98 | |||
99 | const results = await ActorFollowModel.listSubscriptionsOf(user.Account.Actor.id, handles) | ||
100 | 95 | ||
101 | const existObject: { [id: string ]: boolean } = {} | 96 | const existObject: { [id: string ]: boolean } = {} |
102 | for (const handle of handles) { | 97 | for (const sanitizedHandle of sanitizedHandles) { |
103 | const obj = results.find(r => { | 98 | const obj = results.find(r => { |
104 | const server = r.ActorFollowing.Server | 99 | const server = r.ActorFollowing.Server |
105 | 100 | ||
106 | return r.ActorFollowing.preferredUsername === handle.name && | 101 | return r.ActorFollowing.preferredUsername === sanitizedHandle.name && |
107 | ( | 102 | ( |
108 | (!server && !handle.host) || | 103 | (!server && !sanitizedHandle.host) || |
109 | (server.host === handle.host) | 104 | (server.host === sanitizedHandle.host) |
110 | ) | 105 | ) |
111 | }) | 106 | }) |
112 | 107 | ||
113 | existObject[handle.uri] = obj !== undefined | 108 | existObject[sanitizedHandle.handle] = obj !== undefined |
114 | } | 109 | } |
115 | 110 | ||
116 | return res.json(existObject) | 111 | return res.json(existObject) |
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts index 6773b500f..c827f6bf0 100644 --- a/server/controllers/api/videos/upload.ts +++ b/server/controllers/api/videos/upload.ts | |||
@@ -8,6 +8,7 @@ import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | |||
8 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' | 8 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' |
9 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' | 9 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' |
10 | import { Redis } from '@server/lib/redis' | 10 | import { Redis } from '@server/lib/redis' |
11 | import { uploadx } from '@server/lib/uploadx' | ||
11 | import { | 12 | import { |
12 | addMoveToObjectStorageJob, | 13 | addMoveToObjectStorageJob, |
13 | addOptimizeOrMergeAudioJob, | 14 | addOptimizeOrMergeAudioJob, |
@@ -19,7 +20,6 @@ import { VideoPathManager } from '@server/lib/video-path-manager' | |||
19 | import { buildNextVideoState } from '@server/lib/video-state' | 20 | import { buildNextVideoState } from '@server/lib/video-state' |
20 | import { openapiOperationDoc } from '@server/middlewares/doc' | 21 | import { openapiOperationDoc } from '@server/middlewares/doc' |
21 | import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | 22 | import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
22 | import { Uploadx } from '@uploadx/core' | ||
23 | import { VideoCreate, VideoState } from '../../../../shared' | 23 | import { VideoCreate, VideoState } from '../../../../shared' |
24 | import { HttpStatusCode } from '../../../../shared/models' | 24 | import { HttpStatusCode } from '../../../../shared/models' |
25 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' | 25 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' |
@@ -41,8 +41,8 @@ import { | |||
41 | authenticate, | 41 | authenticate, |
42 | videosAddLegacyValidator, | 42 | videosAddLegacyValidator, |
43 | videosAddResumableInitValidator, | 43 | videosAddResumableInitValidator, |
44 | videosResumableUploadIdValidator, | 44 | videosAddResumableValidator, |
45 | videosAddResumableValidator | 45 | videosResumableUploadIdValidator |
46 | } from '../../../middlewares' | 46 | } from '../../../middlewares' |
47 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' | 47 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' |
48 | import { VideoModel } from '../../../models/video/video' | 48 | import { VideoModel } from '../../../models/video/video' |
@@ -52,9 +52,6 @@ const lTags = loggerTagsFactory('api', 'video') | |||
52 | const auditLogger = auditLoggerFactory('videos') | 52 | const auditLogger = auditLoggerFactory('videos') |
53 | const uploadRouter = express.Router() | 53 | const uploadRouter = express.Router() |
54 | 54 | ||
55 | const uploadx = new Uploadx({ directory: getResumableUploadPath() }) | ||
56 | uploadx.getUserId = (_, res: express.Response) => res.locals.oauth?.token.user.id | ||
57 | |||
58 | const reqVideoFileAdd = createReqFiles( | 55 | const reqVideoFileAdd = createReqFiles( |
59 | [ 'videofile', 'thumbnailfile', 'previewfile' ], | 56 | [ 'videofile', 'thumbnailfile', 'previewfile' ], |
60 | Object.assign({}, MIMETYPES.VIDEO.MIMETYPE_EXT, MIMETYPES.IMAGE.MIMETYPE_EXT), | 57 | Object.assign({}, MIMETYPES.VIDEO.MIMETYPE_EXT, MIMETYPES.IMAGE.MIMETYPE_EXT), |