]>
Commit | Line | Data |
---|---|---|
4d4e5cd4 | 1 | import * as express from 'express' |
350e31d6 | 2 | import { UserRight } from '../../../shared/models/users/user-right.enum' |
571389d4 | 3 | import { getFormattedObjects } from '../../helpers' |
350e31d6 | 4 | import { logger } from '../../helpers/logger' |
7a7724e6 | 5 | import { getApplicationAccount } from '../../helpers/utils' |
350e31d6 C |
6 | import { getAccountFromWebfinger } from '../../helpers/webfinger' |
7 | import { SERVER_ACCOUNT_NAME } from '../../initializers/constants' | |
e02643f3 | 8 | import { database as db } from '../../initializers/database' |
350e31d6 | 9 | import { sendFollow } from '../../lib/activitypub/send-request' |
7a7724e6 | 10 | import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../middlewares' |
350e31d6 | 11 | import { authenticate } from '../../middlewares/oauth' |
ce548a10 | 12 | import { setBodyHostsPort } from '../../middlewares/pods' |
7a7724e6 | 13 | import { setFollowingSort } from '../../middlewares/sort' |
350e31d6 | 14 | import { ensureUserHasRight } from '../../middlewares/user-right' |
ce548a10 | 15 | import { followValidator } from '../../middlewares/validators/pods' |
7a7724e6 | 16 | import { followersSortValidator, followingSortValidator } from '../../middlewares/validators/sort' |
65fcc311 C |
17 | |
18 | const podsRouter = express.Router() | |
19 | ||
7a7724e6 | 20 | podsRouter.get('/following', |
8a02bd04 | 21 | paginationValidator, |
7a7724e6 C |
22 | followingSortValidator, |
23 | setFollowingSort, | |
8a02bd04 | 24 | setPagination, |
7a7724e6 C |
25 | asyncMiddleware(listFollowing) |
26 | ) | |
27 | ||
ce548a10 | 28 | podsRouter.post('/follow', |
8e696487 C |
29 | authenticate, |
30 | ensureUserHasRight(UserRight.MANAGE_PEERTUBE_FOLLOW), | |
ce548a10 C |
31 | followValidator, |
32 | setBodyHostsPort, | |
33 | asyncMiddleware(follow) | |
34 | ) | |
35 | ||
7a7724e6 C |
36 | podsRouter.get('/followers', |
37 | paginationValidator, | |
38 | followersSortValidator, | |
39 | setFollowersSort, | |
40 | setPagination, | |
41 | asyncMiddleware(listFollowers) | |
65fcc311 | 42 | ) |
65fcc311 C |
43 | |
44 | // --------------------------------------------------------------------------- | |
45 | ||
46 | export { | |
47 | podsRouter | |
48 | } | |
49 | ||
50 | // --------------------------------------------------------------------------- | |
51 | ||
7a7724e6 C |
52 | async function listFollowing (req: express.Request, res: express.Response, next: express.NextFunction) { |
53 | const applicationAccount = await getApplicationAccount() | |
54 | const resultList = await db.Account.listFollowingForApi(applicationAccount.id, req.query.start, req.query.count, req.query.sort) | |
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() | |
61 | const resultList = await db.Account.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 | ||
111 | await Promise.all(tasks) | |
112 | ||
113 | return res.status(204).end() | |
114 | } | |
350e31d6 C |
115 | |
116 | async function loadLocalOrGetAccountFromWebfinger (name: string, host: string) { | |
117 | let loadedFromDB = true | |
118 | let account = await db.Account.loadByNameAndHost(name, host) | |
119 | ||
120 | if (!account) { | |
121 | const nameWithDomain = name + '@' + host | |
122 | account = await getAccountFromWebfinger(nameWithDomain) | |
123 | loadedFromDB = false | |
124 | } | |
125 | ||
126 | return { account, loadedFromDB } | |
127 | } |