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