]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/api/server/follows.ts
Merge remote-tracking branch 'weblate/develop' into develop
[github/Chocobozzz/PeerTube.git] / server / controllers / api / server / follows.ts
CommitLineData
41fb13c3 1import express from 'express'
7d9ba5c0 2import { getServerActor } from '@server/models/application/application'
c0e8b12e 3import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
3fd3ab2d 4import { UserRight } from '../../../../shared/models/users'
da854ddd 5import { logger } from '../../../helpers/logger'
e1c55031 6import { getFormattedObjects } from '../../../helpers/utils'
74dc3bca 7import { SERVER_ACTOR_NAME } from '../../../initializers/constants'
7d9ba5c0
C
8import { sequelizeTypescript } from '../../../initializers/database'
9import { autoFollowBackIfNeeded } from '../../../lib/activitypub/follow'
14893eb7 10import { sendAccept, sendReject, sendUndoFollow } from '../../../lib/activitypub/send'
7d9ba5c0
C
11import { JobQueue } from '../../../lib/job-queue'
12import { removeRedundanciesOfServer } from '../../../lib/redundancy'
3fd3ab2d 13import {
5350fd8e
C
14 asyncMiddleware,
15 authenticate,
16 ensureUserHasRight,
17 paginationValidator,
5350fd8e
C
18 setBodyHostsPort,
19 setDefaultPagination,
20 setDefaultSort
3fd3ab2d 21} from '../../../middlewares'
0e9c48c2 22import {
14893eb7 23 acceptOrRejectFollowerValidator,
9593a78a
C
24 instanceFollowersSortValidator,
25 instanceFollowingSortValidator,
0e9c48c2 26 followValidator,
14893eb7 27 getFollowerValidator,
7d9ba5c0
C
28 listFollowsValidator,
29 removeFollowingValidator
0e9c48c2 30} from '../../../middlewares/validators'
7d9ba5c0 31import { ActorFollowModel } from '../../../models/actor/actor-follow'
4d029ef8 32import { ServerFollowCreate } from '@shared/models'
51548b31 33
4610bc5b 34const serverFollowsRouter = express.Router()
4610bc5b 35serverFollowsRouter.get('/following',
b8f4167f 36 listFollowsValidator,
8a02bd04 37 paginationValidator,
9593a78a 38 instanceFollowingSortValidator,
1174a847 39 setDefaultSort,
f05a1c30 40 setDefaultPagination,
7a7724e6
C
41 asyncMiddleware(listFollowing)
42)
43
9a27cdc2 44serverFollowsRouter.post('/following',
8e696487 45 authenticate,
4610bc5b 46 ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
ce548a10
C
47 followValidator,
48 setBodyHostsPort,
4d029ef8 49 asyncMiddleware(addFollow)
ce548a10
C
50)
51
4d029ef8 52serverFollowsRouter.delete('/following/:hostOrHandle',
54141398
C
53 authenticate,
54 ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
a2431b7d 55 asyncMiddleware(removeFollowingValidator),
0e9c48c2 56 asyncMiddleware(removeFollowing)
54141398
C
57)
58
4610bc5b 59serverFollowsRouter.get('/followers',
b8f4167f 60 listFollowsValidator,
7a7724e6 61 paginationValidator,
9593a78a 62 instanceFollowersSortValidator,
1174a847 63 setDefaultSort,
f05a1c30 64 setDefaultPagination,
7a7724e6 65 asyncMiddleware(listFollowers)
65fcc311 66)
65fcc311 67
0e9c48c2
C
68serverFollowsRouter.delete('/followers/:nameWithHost',
69 authenticate,
70 ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
14893eb7
C
71 asyncMiddleware(getFollowerValidator),
72 asyncMiddleware(removeOrRejectFollower)
73)
74
75serverFollowsRouter.post('/followers/:nameWithHost/reject',
76 authenticate,
77 ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
78 asyncMiddleware(getFollowerValidator),
79 acceptOrRejectFollowerValidator,
80 asyncMiddleware(removeOrRejectFollower)
81)
82
83serverFollowsRouter.post('/followers/:nameWithHost/accept',
84 authenticate,
85 ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
86 asyncMiddleware(getFollowerValidator),
87 acceptOrRejectFollowerValidator,
88 asyncMiddleware(acceptFollower)
0e9c48c2
C
89)
90
65fcc311
C
91// ---------------------------------------------------------------------------
92
93export {
4610bc5b 94 serverFollowsRouter
65fcc311
C
95}
96
97// ---------------------------------------------------------------------------
98
dae86118 99async function listFollowing (req: express.Request, res: express.Response) {
50d6de9c 100 const serverActor = await getServerActor()
4beda9e1 101 const resultList = await ActorFollowModel.listInstanceFollowingForApi({
bae61627 102 followerId: serverActor.id,
b8f4167f
C
103 start: req.query.start,
104 count: req.query.count,
105 sort: req.query.sort,
106 search: req.query.search,
97ecddae 107 actorType: req.query.actorType,
b8f4167f
C
108 state: req.query.state
109 })
7a7724e6
C
110
111 return res.json(getFormattedObjects(resultList.data, resultList.total))
112}
113
dae86118 114async function listFollowers (req: express.Request, res: express.Response) {
50d6de9c 115 const serverActor = await getServerActor()
b8f4167f 116 const resultList = await ActorFollowModel.listFollowersForApi({
4beda9e1 117 actorIds: [ serverActor.id ],
b8f4167f
C
118 start: req.query.start,
119 count: req.query.count,
120 sort: req.query.sort,
121 search: req.query.search,
97ecddae 122 actorType: req.query.actorType,
b8f4167f
C
123 state: req.query.state
124 })
eb080476
C
125
126 return res.json(getFormattedObjects(resultList.data, resultList.total))
65fcc311 127}
ce548a10 128
4d029ef8
C
129async function addFollow (req: express.Request, res: express.Response) {
130 const { hosts, handles } = req.body as ServerFollowCreate
06a05d5f 131 const follower = await getServerActor()
350e31d6 132
ce548a10 133 for (const host of hosts) {
06a05d5f
C
134 const payload = {
135 host,
136 name: SERVER_ACTOR_NAME,
137 followerActorId: follower.id
138 }
139
140 JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
ce548a10
C
141 }
142
4d029ef8
C
143 for (const handle of handles) {
144 const [ name, host ] = handle.split('@')
145
146 const payload = {
147 host,
148 name,
149 followerActorId: follower.id
150 }
151
152 JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
153 }
154
2d53be02 155 return res.status(HttpStatusCode.NO_CONTENT_204).end()
ce548a10 156}
350e31d6 157
0e9c48c2 158async function removeFollowing (req: express.Request, res: express.Response) {
dae86118 159 const follow = res.locals.follow
54141398 160
3fd3ab2d 161 await sequelizeTypescript.transaction(async t => {
bae61627 162 if (follow.state === 'accepted') sendUndoFollow(follow, t)
40ff5707 163
c48e82b5
C
164 // Disable redundancy on unfollowed instances
165 const server = follow.ActorFollowing.Server
166 server.redundancyAllowed = false
167 await server.save({ transaction: t })
168
161b061d 169 // Async, could be long
b764380a 170 removeRedundanciesOfServer(server.id)
161b061d
C
171 .catch(err => logger.error('Cannot remove redundancy of %s.', server.host, err))
172
0f91ae62 173 await follow.destroy({ transaction: t })
54141398
C
174 })
175
2d53be02 176 return res.status(HttpStatusCode.NO_CONTENT_204).end()
54141398 177}
0e9c48c2 178
14893eb7 179async function removeOrRejectFollower (req: express.Request, res: express.Response) {
0e9c48c2
C
180 const follow = res.locals.follow
181
de94ac86 182 await sendReject(follow.url, follow.ActorFollower, follow.ActorFollowing)
0e9c48c2
C
183
184 await follow.destroy()
185
2d53be02 186 return res.status(HttpStatusCode.NO_CONTENT_204).end()
0e9c48c2 187}
14893eb7
C
188
189async function acceptFollower (req: express.Request, res: express.Response) {
190 const follow = res.locals.follow
191
eae0365b 192 sendAccept(follow)
14893eb7
C
193
194 follow.state = 'accepted'
195 await follow.save()
196
8424c402
C
197 await autoFollowBackIfNeeded(follow)
198
2d53be02 199 return res.status(HttpStatusCode.NO_CONTENT_204).end()
14893eb7 200}