From 51548b31815c6f96f314ae96588a9adca150519d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 15 Nov 2017 10:10:41 +0100 Subject: Add follow tabs Following Follow Followers --- server/controllers/api/application/follows.ts | 127 ++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 server/controllers/api/application/follows.ts (limited to 'server/controllers/api/application/follows.ts') diff --git a/server/controllers/api/application/follows.ts b/server/controllers/api/application/follows.ts new file mode 100644 index 000000000..000bbd23e --- /dev/null +++ b/server/controllers/api/application/follows.ts @@ -0,0 +1,127 @@ +import * as express from 'express' +import { UserRight } from '../../../../shared/models/users/user-right.enum' +import { getFormattedObjects } from '../../../helpers' +import { logger } from '../../../helpers/logger' +import { getApplicationAccount } from '../../../helpers/utils' +import { getAccountFromWebfinger } from '../../../helpers/webfinger' +import { SERVER_ACCOUNT_NAME } from '../../../initializers/constants' +import { database as db } from '../../../initializers/database' +import { sendFollow } from '../../../lib/activitypub/send-request' +import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares' +import { authenticate } from '../../../middlewares/oauth' +import { setBodyHostsPort } from '../../../middlewares/pods' +import { setFollowingSort } from '../../../middlewares/sort' +import { ensureUserHasRight } from '../../../middlewares/user-right' +import { followValidator } from '../../../middlewares/validators/pods' +import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort' + +const applicationFollowsRouter = express.Router() + +applicationFollowsRouter.get('/following', + paginationValidator, + followingSortValidator, + setFollowingSort, + setPagination, + asyncMiddleware(listFollowing) +) + +applicationFollowsRouter.post('/follow', + authenticate, + ensureUserHasRight(UserRight.MANAGE_APPLICATION_FOLLOW), + followValidator, + setBodyHostsPort, + asyncMiddleware(follow) +) + +applicationFollowsRouter.get('/followers', + paginationValidator, + followersSortValidator, + setFollowersSort, + setPagination, + asyncMiddleware(listFollowers) +) + +// --------------------------------------------------------------------------- + +export { + applicationFollowsRouter +} + +// --------------------------------------------------------------------------- + +async function listFollowing (req: express.Request, res: express.Response, next: express.NextFunction) { + const applicationAccount = await getApplicationAccount() + const resultList = await db.AccountFollow.listFollowingForApi(applicationAccount.id, req.query.start, req.query.count, req.query.sort) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} + +async function listFollowers (req: express.Request, res: express.Response, next: express.NextFunction) { + const applicationAccount = await getApplicationAccount() + const resultList = await db.AccountFollow.listFollowersForApi(applicationAccount.id, req.query.start, req.query.count, req.query.sort) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} + +async function follow (req: express.Request, res: express.Response, next: express.NextFunction) { + const hosts = req.body.hosts as string[] + const fromAccount = await getApplicationAccount() + + const tasks: Promise[] = [] + const accountName = SERVER_ACCOUNT_NAME + + for (const host of hosts) { + + // We process each host in a specific transaction + // First, we add the follow request in the database + // Then we send the follow request to other account + const p = loadLocalOrGetAccountFromWebfinger(accountName, host) + .then(accountResult => { + let targetAccount = accountResult.account + + return db.sequelize.transaction(async t => { + if (accountResult.loadedFromDB === false) { + targetAccount = await targetAccount.save({ transaction: t }) + } + + const [ accountFollow ] = await db.AccountFollow.findOrCreate({ + where: { + accountId: fromAccount.id, + targetAccountId: targetAccount.id + }, + defaults: { + state: 'pending', + accountId: fromAccount.id, + targetAccountId: targetAccount.id + }, + transaction: t + }) + + // Send a notification to remote server + if (accountFollow.state === 'pending') { + await sendFollow(fromAccount, targetAccount, t) + } + }) + }) + .catch(err => logger.warn('Cannot follow server %s.', `${accountName}@${host}`, err)) + + tasks.push(p) + } + + await Promise.all(tasks) + + return res.status(204).end() +} + +async function loadLocalOrGetAccountFromWebfinger (name: string, host: string) { + let loadedFromDB = true + let account = await db.Account.loadByNameAndHost(name, host) + + if (!account) { + const nameWithDomain = name + '@' + host + account = await getAccountFromWebfinger(nameWithDomain) + loadedFromDB = false + } + + return { account, loadedFromDB } +} -- cgit v1.2.3