]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/controllers/api/blocklist.ts
Fix runner api rate limit bypass
[github/Chocobozzz/PeerTube.git] / server / controllers / api / blocklist.ts
1 import express from 'express'
2 import { handleToNameAndHost } from '@server/helpers/actors'
3 import { logger } from '@server/helpers/logger'
4 import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
5 import { getServerActor } from '@server/models/application/application'
6 import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
7 import { MActorAccountId, MUserAccountId } from '@server/types/models'
8 import { BlockStatus } from '@shared/models'
9 import { apiRateLimiter, asyncMiddleware, blocklistStatusValidator, optionalAuthenticate } from '../../middlewares'
10
11 const blocklistRouter = express.Router()
12
13 blocklistRouter.use(apiRateLimiter)
14
15 blocklistRouter.get('/status',
16 optionalAuthenticate,
17 blocklistStatusValidator,
18 asyncMiddleware(getBlocklistStatus)
19 )
20
21 // ---------------------------------------------------------------------------
22
23 export {
24 blocklistRouter
25 }
26
27 // ---------------------------------------------------------------------------
28
29 async function getBlocklistStatus (req: express.Request, res: express.Response) {
30 const hosts = req.query.hosts as string[]
31 const accounts = req.query.accounts as string[]
32 const user = res.locals.oauth?.token.User
33
34 const serverActor = await getServerActor()
35
36 const byAccountIds = [ serverActor.Account.id ]
37 if (user) byAccountIds.push(user.Account.id)
38
39 const status: BlockStatus = {
40 accounts: {},
41 hosts: {}
42 }
43
44 const baseOptions = {
45 byAccountIds,
46 user,
47 serverActor,
48 status
49 }
50
51 await Promise.all([
52 populateServerBlocklistStatus({ ...baseOptions, hosts }),
53 populateAccountBlocklistStatus({ ...baseOptions, accounts })
54 ])
55
56 return res.json(status)
57 }
58
59 async function populateServerBlocklistStatus (options: {
60 byAccountIds: number[]
61 user?: MUserAccountId
62 serverActor: MActorAccountId
63 hosts: string[]
64 status: BlockStatus
65 }) {
66 const { byAccountIds, user, serverActor, hosts, status } = options
67
68 if (!hosts || hosts.length === 0) return
69
70 const serverBlocklistStatus = await ServerBlocklistModel.getBlockStatus(byAccountIds, hosts)
71
72 logger.debug('Got server blocklist status.', { serverBlocklistStatus, byAccountIds, hosts })
73
74 for (const host of hosts) {
75 const block = serverBlocklistStatus.find(b => b.host === host)
76
77 status.hosts[host] = getStatus(block, serverActor, user)
78 }
79 }
80
81 async function populateAccountBlocklistStatus (options: {
82 byAccountIds: number[]
83 user?: MUserAccountId
84 serverActor: MActorAccountId
85 accounts: string[]
86 status: BlockStatus
87 }) {
88 const { byAccountIds, user, serverActor, accounts, status } = options
89
90 if (!accounts || accounts.length === 0) return
91
92 const accountBlocklistStatus = await AccountBlocklistModel.getBlockStatus(byAccountIds, accounts)
93
94 logger.debug('Got account blocklist status.', { accountBlocklistStatus, byAccountIds, accounts })
95
96 for (const account of accounts) {
97 const sanitizedHandle = handleToNameAndHost(account)
98
99 const block = accountBlocklistStatus.find(b => b.name === sanitizedHandle.name && b.host === sanitizedHandle.host)
100
101 status.accounts[sanitizedHandle.handle] = getStatus(block, serverActor, user)
102 }
103 }
104
105 function getStatus (block: { accountId: number }, serverActor: MActorAccountId, user?: MUserAccountId) {
106 return {
107 blockedByServer: !!(block && block.accountId === serverActor.Account.id),
108 blockedByUser: !!(block && user && block.accountId === user.Account.id)
109 }
110 }