diff --git a/src/common/remote/activitypub/renderer/key.ts b/src/common/remote/activitypub/renderer/key.ts index 7148c5974..692c71f88 100644 --- a/src/common/remote/activitypub/renderer/key.ts +++ b/src/common/remote/activitypub/renderer/key.ts @@ -3,6 +3,7 @@ import { extractPublic } from '../../../../crypto_key'; import { ILocalAccount } from '../../../../models/user'; export default ({ username, account }) => ({ + id: `${config.url}/@${username}/publickey`, type: 'Key', owner: `${config.url}/@${username}`, publicKeyPem: extractPublic((account as ILocalAccount).keypair) diff --git a/src/server/activitypub/index.ts b/src/server/activitypub/index.ts index c81024d15..ac7a184f2 100644 --- a/src/server/activitypub/index.ts +++ b/src/server/activitypub/index.ts @@ -3,6 +3,7 @@ import * as express from 'express'; import user from './user'; import inbox from './inbox'; import outbox from './outbox'; +import publicKey from './publickey'; import post from './post'; const app = express(); @@ -11,6 +12,7 @@ app.disable('x-powered-by'); app.use(user); app.use(inbox); app.use(outbox); +app.use(publicKey); app.use(post); export default app; diff --git a/src/server/activitypub/outbox.ts b/src/server/activitypub/outbox.ts index c5a42ae0a..c26c4df75 100644 --- a/src/server/activitypub/outbox.ts +++ b/src/server/activitypub/outbox.ts @@ -2,44 +2,26 @@ import * as express from 'express'; import context from '../../common/remote/activitypub/renderer/context'; import renderNote from '../../common/remote/activitypub/renderer/note'; import renderOrderedCollection from '../../common/remote/activitypub/renderer/ordered-collection'; -import parseAcct from '../../common/user/parse-acct'; import config from '../../conf'; import Post from '../../models/post'; -import User from '../../models/user'; +import withUser from './with-user'; const app = express(); app.disable('x-powered-by'); -app.get('/@:user/outbox', async (req, res) => { - const { username, host } = parseAcct(req.params.user); - if (host !== null) { - return res.sendStatus(422); - } - - const user = await User.findOne({ - usernameLower: username.toLowerCase(), - host: null - }); - if (user === null) { - return res.sendStatus(404); - } - - const id = `${config.url}/@${user.username}/inbox`; - - if (username !== user.username) { - return res.redirect(id); - } - +app.get('/@:user/outbox', withUser(username => { + return `${config.url}/@${username}/inbox`; +}, async (user, req, res) => { const posts = await Post.find({ userId: user._id }, { limit: 20, sort: { _id: -1 } }); const renderedPosts = await Promise.all(posts.map(post => renderNote(user, post))); - const rendered = renderOrderedCollection(id, user.postsCount, renderedPosts); + const rendered = renderOrderedCollection(`${config.url}/@${user.username}/inbox`, user.postsCount, renderedPosts); rendered['@context'] = context; res.json(rendered); -}); +})); export default app; diff --git a/src/server/activitypub/publickey.ts b/src/server/activitypub/publickey.ts new file mode 100644 index 000000000..e380309dc --- /dev/null +++ b/src/server/activitypub/publickey.ts @@ -0,0 +1,19 @@ +import * as express from 'express'; +import context from '../../common/remote/activitypub/renderer/context'; +import render from '../../common/remote/activitypub/renderer/key'; +import config from '../../conf'; +import withUser from './with-user'; + +const app = express(); +app.disable('x-powered-by'); + +app.get('/@:user/publickey', withUser(username => { + return `${config.url}/@${username}/publickey`; +}, (user, req, res) => { + const rendered = render(user); + rendered['@context'] = context; + + res.json(rendered); +})); + +export default app; diff --git a/src/server/activitypub/user.ts b/src/server/activitypub/user.ts index d43a9793d..8e8deca4a 100644 --- a/src/server/activitypub/user.ts +++ b/src/server/activitypub/user.ts @@ -2,39 +2,26 @@ import * as express from 'express'; import config from '../../conf'; import context from '../../common/remote/activitypub/renderer/context'; import render from '../../common/remote/activitypub/renderer/person'; -import parseAcct from '../../common/user/parse-acct'; -import User from '../../models/user'; - -const app = express(); -app.disable('x-powered-by'); - -app.get('/@:user', async (req, res, next) => { - const accepted = req.accepts(['html', 'application/activity+json', 'application/ld+json']); - if (!(['application/activity+json', 'application/ld+json'] as Array).includes(accepted)) { - return next(); - } - - const { username, host } = parseAcct(req.params.user); - if (host !== null) { - return res.sendStatus(422); - } - - const user = await User.findOne({ - usernameLower: username.toLowerCase(), - host: null - }); - if (user === null) { - return res.sendStatus(404); - } - - if (username !== user.username) { - return res.redirect(`${config.url}/@${user.username}`); - } +import withUser from './with-user'; +const respond = withUser(username => `${config.url}/@${username}`, (user, req, res) => { const rendered = render(user); rendered['@context'] = context; res.json(rendered); }); +const app = express(); +app.disable('x-powered-by'); + +app.get('/@:user', (req, res, next) => { + const accepted = req.accepts(['html', 'application/activity+json', 'application/ld+json']); + + if ((['application/activity+json', 'application/ld+json'] as Array).includes(accepted)) { + respond(req, res, next); + } else { + next(); + } +}); + export default app; diff --git a/src/server/activitypub/with-user.ts b/src/server/activitypub/with-user.ts new file mode 100644 index 000000000..0bab47b78 --- /dev/null +++ b/src/server/activitypub/with-user.ts @@ -0,0 +1,23 @@ +import parseAcct from '../../common/user/parse-acct'; +import User from '../../models/user'; + +export default (redirect, respond) => async (req, res, next) => { + const { username, host } = parseAcct(req.params.user); + if (host !== null) { + return res.sendStatus(422); + } + + const user = await User.findOne({ + usernameLower: username.toLowerCase(), + host: null + }); + if (user === null) { + return res.sendStatus(404); + } + + if (username !== user.username) { + return res.redirect(redirect(user.username)); + } + + return respond(user, req, res, next); +}