From 350e31d6b64e4973dfa5e9f7b46841cb09aeb1ad Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 14 Nov 2017 17:31:26 +0100 Subject: Follow works --- server/controllers/activitypub/client.ts | 4 +- server/controllers/activitypub/inbox.ts | 4 +- server/controllers/activitypub/index.ts | 10 ++--- server/controllers/api/pods.ts | 68 ++++++++++++++++++++++++-------- server/controllers/index.ts | 2 + server/controllers/webfinger.ts | 39 ++++++++++++++++++ 6 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 server/controllers/webfinger.ts (limited to 'server/controllers') diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 461a619dd..56a4054fa 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts @@ -16,12 +16,12 @@ activityPubClientRouter.get('/account/:name', executeIfActivityPub(asyncMiddleware(accountController)) ) -activityPubClientRouter.get('/account/:nameWithHost/followers', +activityPubClientRouter.get('/account/:name/followers', executeIfActivityPub(localAccountValidator), executeIfActivityPub(asyncMiddleware(accountFollowersController)) ) -activityPubClientRouter.get('/account/:nameWithHost/following', +activityPubClientRouter.get('/account/:name/following', executeIfActivityPub(localAccountValidator), executeIfActivityPub(asyncMiddleware(accountFollowingController)) ) diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts index eedb518b9..e62125d85 100644 --- a/server/controllers/activitypub/inbox.ts +++ b/server/controllers/activitypub/inbox.ts @@ -30,7 +30,7 @@ inboxRouter.post('/inbox', asyncMiddleware(inboxController) ) -inboxRouter.post('/:nameWithHost/inbox', +inboxRouter.post('/account/:name/inbox', signatureValidator, asyncMiddleware(checkSignature), localAccountValidator, @@ -59,7 +59,9 @@ async function inboxController (req: express.Request, res: express.Response, nex } // Only keep activities we are able to process + logger.debug('Filtering activities...', { activities }) activities = activities.filter(a => isActivityValid(a)) + logger.debug('We keep %d activities.', activities.length, { activities }) await processActivities(activities, res.locals.account) diff --git a/server/controllers/activitypub/index.ts b/server/controllers/activitypub/index.ts index 6c7bafc6e..0c8574ef7 100644 --- a/server/controllers/activitypub/index.ts +++ b/server/controllers/activitypub/index.ts @@ -4,14 +4,14 @@ import { badRequest } from '../../helpers' import { inboxRouter } from './inbox' import { activityPubClientRouter } from './client' -const remoteRouter = express.Router() +const activityPubRouter = express.Router() -remoteRouter.use('/', inboxRouter) -remoteRouter.use('/', activityPubClientRouter) -remoteRouter.use('/*', badRequest) +activityPubRouter.use('/', inboxRouter) +activityPubRouter.use('/', activityPubClientRouter) +activityPubRouter.use('/*', badRequest) // --------------------------------------------------------------------------- export { - remoteRouter + activityPubRouter } diff --git a/server/controllers/api/pods.ts b/server/controllers/api/pods.ts index 2231a05fa..0bd6971bb 100644 --- a/server/controllers/api/pods.ts +++ b/server/controllers/api/pods.ts @@ -1,19 +1,19 @@ -import * as Bluebird from 'bluebird' import * as express from 'express' +import { UserRight } from '../../../shared/models/users/user-right.enum' import { getFormattedObjects } from '../../helpers' -import { getOrCreateAccount } from '../../helpers/activitypub' +import { logger } from '../../helpers/logger' import { getApplicationAccount } from '../../helpers/utils' -import { REMOTE_SCHEME } from '../../initializers/constants' +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' -import { sendFollow } from '../../lib/activitypub/send-request' -import { authenticate } from '../../middlewares/oauth' -import { ensureUserHasRight } from '../../middlewares/user-right' -import { UserRight } from '../../../shared/models/users/user-right.enum' const podsRouter = express.Router() @@ -67,22 +67,43 @@ async function follow (req: express.Request, res: express.Response, next: expres const hosts = req.body.hosts as string[] const fromAccount = await getApplicationAccount() - const tasks: Bluebird[] = [] + const tasks: Promise[] = [] + const accountName = SERVER_ACCOUNT_NAME + for (const host of hosts) { - const url = REMOTE_SCHEME.HTTP + '://' + host - const targetAccount = await getOrCreateAccount(url) // 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 = db.sequelize.transaction(async t => { - return db.AccountFollow.create({ - accountId: fromAccount.id, - targetAccountId: targetAccount.id, - state: 'pending' + 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) + } + }) }) - .then(() => sendFollow(fromAccount, targetAccount, t)) - }) + .catch(err => logger.warn('Cannot follow server %s.', `${accountName}@${host}`, err)) tasks.push(p) } @@ -91,3 +112,16 @@ async function follow (req: express.Request, res: express.Response, next: expres 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 } +} diff --git a/server/controllers/index.ts b/server/controllers/index.ts index 51cb480a3..457d0a12e 100644 --- a/server/controllers/index.ts +++ b/server/controllers/index.ts @@ -1,4 +1,6 @@ +export * from './activitypub' export * from './static' export * from './client' export * from './services' export * from './api' +export * from './webfinger' diff --git a/server/controllers/webfinger.ts b/server/controllers/webfinger.ts new file mode 100644 index 000000000..1c726f0cb --- /dev/null +++ b/server/controllers/webfinger.ts @@ -0,0 +1,39 @@ +import * as express from 'express' + +import { CONFIG, PREVIEWS_SIZE, EMBED_SIZE } from '../initializers' +import { oembedValidator } from '../middlewares' +import { VideoInstance } from '../models' +import { webfingerValidator } from '../middlewares/validators/webfinger' +import { AccountInstance } from '../models/account/account-interface' + +const webfingerRouter = express.Router() + +webfingerRouter.use('/.well-known/webfinger', + webfingerValidator, + webfingerController +) + +// --------------------------------------------------------------------------- + +export { + webfingerRouter +} + +// --------------------------------------------------------------------------- + +function webfingerController (req: express.Request, res: express.Response, next: express.NextFunction) { + const account: AccountInstance = res.locals.account + + const json = { + subject: req.query.resource, + aliases: [ account.url ], + links: [ + { + rel: 'self', + href: account.url + } + ] + } + + return res.json(json).end() +} -- cgit v1.2.3