]>
Commit | Line | Data |
---|---|---|
4d4e5cd4 | 1 | import * as express from 'express' |
51548b31 C |
2 | import { UserRight } from '../../../../shared/models/users/user-right.enum' |
3 | import { getFormattedObjects } from '../../../helpers' | |
4 | import { logger } from '../../../helpers/logger' | |
5 | import { getApplicationAccount } from '../../../helpers/utils' | |
6 | import { getAccountFromWebfinger } from '../../../helpers/webfinger' | |
7 | import { SERVER_ACCOUNT_NAME } from '../../../initializers/constants' | |
8 | import { database as db } from '../../../initializers/database' | |
9 | import { sendFollow } from '../../../lib/activitypub/send-request' | |
10 | import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares' | |
11 | import { authenticate } from '../../../middlewares/oauth' | |
60862425 | 12 | import { setBodyHostsPort } from '../../../middlewares/servers' |
51548b31 C |
13 | import { setFollowingSort } from '../../../middlewares/sort' |
14 | import { ensureUserHasRight } from '../../../middlewares/user-right' | |
60862425 | 15 | import { followValidator } from '../../../middlewares/validators/servers' |
51548b31 C |
16 | import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort' |
17 | ||
18 | const applicationFollowsRouter = express.Router() | |
19 | ||
20 | applicationFollowsRouter.get('/following', | |
8a02bd04 | 21 | paginationValidator, |
7a7724e6 C |
22 | followingSortValidator, |
23 | setFollowingSort, | |
8a02bd04 | 24 | setPagination, |
7a7724e6 C |
25 | asyncMiddleware(listFollowing) |
26 | ) | |
27 | ||
51548b31 | 28 | applicationFollowsRouter.post('/follow', |
8e696487 | 29 | authenticate, |
51548b31 | 30 | ensureUserHasRight(UserRight.MANAGE_APPLICATION_FOLLOW), |
ce548a10 C |
31 | followValidator, |
32 | setBodyHostsPort, | |
33 | asyncMiddleware(follow) | |
34 | ) | |
35 | ||
51548b31 | 36 | applicationFollowsRouter.get('/followers', |
7a7724e6 C |
37 | paginationValidator, |
38 | followersSortValidator, | |
39 | setFollowersSort, | |
40 | setPagination, | |
41 | asyncMiddleware(listFollowers) | |
65fcc311 | 42 | ) |
65fcc311 C |
43 | |
44 | // --------------------------------------------------------------------------- | |
45 | ||
46 | export { | |
51548b31 | 47 | applicationFollowsRouter |
65fcc311 C |
48 | } |
49 | ||
50 | // --------------------------------------------------------------------------- | |
51 | ||
7a7724e6 C |
52 | async function listFollowing (req: express.Request, res: express.Response, next: express.NextFunction) { |
53 | const applicationAccount = await getApplicationAccount() | |
51548b31 | 54 | const resultList = await db.AccountFollow.listFollowingForApi(applicationAccount.id, req.query.start, req.query.count, req.query.sort) |
7a7724e6 C |
55 | |
56 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | |
57 | } | |
58 | ||
59 | async function listFollowers (req: express.Request, res: express.Response, next: express.NextFunction) { | |
60 | const applicationAccount = await getApplicationAccount() | |
51548b31 | 61 | const resultList = await db.AccountFollow.listFollowersForApi(applicationAccount.id, req.query.start, req.query.count, req.query.sort) |
eb080476 C |
62 | |
63 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | |
65fcc311 | 64 | } |
ce548a10 C |
65 | |
66 | async function follow (req: express.Request, res: express.Response, next: express.NextFunction) { | |
67 | const hosts = req.body.hosts as string[] | |
68 | const fromAccount = await getApplicationAccount() | |
69 | ||
350e31d6 C |
70 | const tasks: Promise<any>[] = [] |
71 | const accountName = SERVER_ACCOUNT_NAME | |
72 | ||
ce548a10 | 73 | for (const host of hosts) { |
ce548a10 C |
74 | |
75 | // We process each host in a specific transaction | |
76 | // First, we add the follow request in the database | |
77 | // Then we send the follow request to other account | |
350e31d6 C |
78 | const p = loadLocalOrGetAccountFromWebfinger(accountName, host) |
79 | .then(accountResult => { | |
80 | let targetAccount = accountResult.account | |
81 | ||
82 | return db.sequelize.transaction(async t => { | |
83 | if (accountResult.loadedFromDB === false) { | |
84 | targetAccount = await targetAccount.save({ transaction: t }) | |
85 | } | |
86 | ||
87 | const [ accountFollow ] = await db.AccountFollow.findOrCreate({ | |
88 | where: { | |
89 | accountId: fromAccount.id, | |
90 | targetAccountId: targetAccount.id | |
91 | }, | |
92 | defaults: { | |
93 | state: 'pending', | |
94 | accountId: fromAccount.id, | |
95 | targetAccountId: targetAccount.id | |
96 | }, | |
97 | transaction: t | |
98 | }) | |
99 | ||
100 | // Send a notification to remote server | |
101 | if (accountFollow.state === 'pending') { | |
102 | await sendFollow(fromAccount, targetAccount, t) | |
103 | } | |
104 | }) | |
ce548a10 | 105 | }) |
350e31d6 | 106 | .catch(err => logger.warn('Cannot follow server %s.', `${accountName}@${host}`, err)) |
ce548a10 C |
107 | |
108 | tasks.push(p) | |
109 | } | |
110 | ||
8e10cf1a C |
111 | // Don't make the client wait the tasks |
112 | Promise.all(tasks) | |
113 | .catch(err => { | |
114 | logger.error('Error in follow.', err) | |
115 | }) | |
ce548a10 C |
116 | |
117 | return res.status(204).end() | |
118 | } | |
350e31d6 C |
119 | |
120 | async function loadLocalOrGetAccountFromWebfinger (name: string, host: string) { | |
121 | let loadedFromDB = true | |
122 | let account = await db.Account.loadByNameAndHost(name, host) | |
123 | ||
124 | if (!account) { | |
125 | const nameWithDomain = name + '@' + host | |
126 | account = await getAccountFromWebfinger(nameWithDomain) | |
127 | loadedFromDB = false | |
128 | } | |
129 | ||
130 | return { account, loadedFromDB } | |
131 | } |