wip
This commit is contained in:
		
							parent
							
								
									0cf7c76d2c
								
							
						
					
					
						commit
						a3bd4ba426
					
				
					 11 changed files with 188 additions and 229 deletions
				
			
		| 
						 | 
					@ -56,6 +56,9 @@
 | 
				
			||||||
		"@types/is-root": "1.0.0",
 | 
							"@types/is-root": "1.0.0",
 | 
				
			||||||
		"@types/is-url": "1.2.28",
 | 
							"@types/is-url": "1.2.28",
 | 
				
			||||||
		"@types/js-yaml": "3.11.1",
 | 
							"@types/js-yaml": "3.11.1",
 | 
				
			||||||
 | 
							"@types/koa": "^2.0.45",
 | 
				
			||||||
 | 
							"@types/koa-bodyparser": "^4.2.0",
 | 
				
			||||||
 | 
							"@types/koa-router": "^7.0.27",
 | 
				
			||||||
		"@types/kue": "^0.11.8",
 | 
							"@types/kue": "^0.11.8",
 | 
				
			||||||
		"@types/license-checker": "15.0.0",
 | 
							"@types/license-checker": "15.0.0",
 | 
				
			||||||
		"@types/mkdirp": "0.5.2",
 | 
							"@types/mkdirp": "0.5.2",
 | 
				
			||||||
| 
						 | 
					@ -140,6 +143,8 @@
 | 
				
			||||||
		"is-url": "1.2.4",
 | 
							"is-url": "1.2.4",
 | 
				
			||||||
		"js-yaml": "3.11.0",
 | 
							"js-yaml": "3.11.0",
 | 
				
			||||||
		"jsdom": "11.7.0",
 | 
							"jsdom": "11.7.0",
 | 
				
			||||||
 | 
							"koa": "^2.5.0",
 | 
				
			||||||
 | 
							"koa-router": "^7.4.0",
 | 
				
			||||||
		"kue": "0.11.6",
 | 
							"kue": "0.11.6",
 | 
				
			||||||
		"license-checker": "18.0.0",
 | 
							"license-checker": "18.0.0",
 | 
				
			||||||
		"loader-utils": "1.1.0",
 | 
							"loader-utils": "1.1.0",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										142
									
								
								src/server/activitypub.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/server/activitypub.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,142 @@
 | 
				
			||||||
 | 
					import * as Router from 'koa-router';
 | 
				
			||||||
 | 
					import { parseRequest } from 'http-signature';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { createHttp } from '../queue';
 | 
				
			||||||
 | 
					import context from '../remote/activitypub/renderer/context';
 | 
				
			||||||
 | 
					import render from '../remote/activitypub/renderer/note';
 | 
				
			||||||
 | 
					import Note from '../models/note';
 | 
				
			||||||
 | 
					import User, { isLocalUser } from '../models/user';
 | 
				
			||||||
 | 
					import renderNote from '../remote/activitypub/renderer/note';
 | 
				
			||||||
 | 
					import renderKey from '../remote/activitypub/renderer/key';
 | 
				
			||||||
 | 
					import renderPerson from '../remote/activitypub/renderer/person';
 | 
				
			||||||
 | 
					import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection';
 | 
				
			||||||
 | 
					//import parseAcct from '../acct/parse';
 | 
				
			||||||
 | 
					import config from '../config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Init router
 | 
				
			||||||
 | 
					const router = new Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#region Routing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// inbox
 | 
				
			||||||
 | 
					router.post('/users/:user/inbox', ctx => {
 | 
				
			||||||
 | 
						let signature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.req.headers.authorization = 'Signature ' + ctx.req.headers.signature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							signature = parseRequest(ctx.req);
 | 
				
			||||||
 | 
						} catch (e) {
 | 
				
			||||||
 | 
							ctx.status = 401;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						createHttp({
 | 
				
			||||||
 | 
							type: 'processInbox',
 | 
				
			||||||
 | 
							activity: ctx.request.body,
 | 
				
			||||||
 | 
							signature
 | 
				
			||||||
 | 
						}).save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.status = 202;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// note
 | 
				
			||||||
 | 
					router.get('/notes/:note', async (ctx, next) => {
 | 
				
			||||||
 | 
						const accepted = ctx.accepts('html', 'application/activity+json', 'application/ld+json');
 | 
				
			||||||
 | 
						if (!['application/activity+json', 'application/ld+json'].includes(accepted as string)) {
 | 
				
			||||||
 | 
							next();
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const note = await Note.findOne({
 | 
				
			||||||
 | 
							_id: ctx.params.note
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (note === null) {
 | 
				
			||||||
 | 
							ctx.status = 404;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const rendered = await render(note);
 | 
				
			||||||
 | 
						rendered['@context'] = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.body = rendered;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// outbot
 | 
				
			||||||
 | 
					router.get('/users/:user/outbox', async ctx => {
 | 
				
			||||||
 | 
						const userId = ctx.params.user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const user = await User.findOne({ _id: userId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (user === null) {
 | 
				
			||||||
 | 
							ctx.status = 404;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const notes = await Note.find({ userId: user._id }, {
 | 
				
			||||||
 | 
							limit: 10,
 | 
				
			||||||
 | 
							sort: { _id: -1 }
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
 | 
				
			||||||
 | 
						const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes);
 | 
				
			||||||
 | 
						rendered['@context'] = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.body = rendered;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// publickey
 | 
				
			||||||
 | 
					router.get('/users/:user/publickey', async ctx => {
 | 
				
			||||||
 | 
						const userId = ctx.params.user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const user = await User.findOne({ _id: userId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (user === null) {
 | 
				
			||||||
 | 
							ctx.status = 404;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (isLocalUser(user)) {
 | 
				
			||||||
 | 
							const rendered = renderKey(user);
 | 
				
			||||||
 | 
							rendered['@context'] = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx.body = rendered;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ctx.status = 400;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// user
 | 
				
			||||||
 | 
					router.get('/users/:user', async ctx => {
 | 
				
			||||||
 | 
						const userId = ctx.params.user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const user = await User.findOne({ _id: userId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (user === null) {
 | 
				
			||||||
 | 
							ctx.status = 404;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const rendered = renderPerson(user);
 | 
				
			||||||
 | 
						rendered['@context'] = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.body = rendered;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// follow form
 | 
				
			||||||
 | 
					router.get('/authorize-follow', async ctx => {
 | 
				
			||||||
 | 
						/* TODO
 | 
				
			||||||
 | 
						const { username, host } = parseAcct(ctx.query.acct);
 | 
				
			||||||
 | 
						if (host === null) {
 | 
				
			||||||
 | 
							res.sendStatus(422);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const finger = await request(`https://${host}`)
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default router;
 | 
				
			||||||
| 
						 | 
					@ -1,32 +0,0 @@
 | 
				
			||||||
import * as bodyParser from 'body-parser';
 | 
					 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import { parseRequest } from 'http-signature';
 | 
					 | 
				
			||||||
import { createHttp } from '../../queue';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express.Router();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.post('/users/:user/inbox', bodyParser.json({
 | 
					 | 
				
			||||||
	type() {
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}), async (req, res) => {
 | 
					 | 
				
			||||||
	let signature;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	req.headers.authorization = 'Signature ' + req.headers.signature;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		signature = parseRequest(req);
 | 
					 | 
				
			||||||
	} catch (exception) {
 | 
					 | 
				
			||||||
		return res.sendStatus(401);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	createHttp({
 | 
					 | 
				
			||||||
		type: 'processInbox',
 | 
					 | 
				
			||||||
		activity: req.body,
 | 
					 | 
				
			||||||
		signature,
 | 
					 | 
				
			||||||
	}).save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return res.status(202).end();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,18 +0,0 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import user from './user';
 | 
					 | 
				
			||||||
import inbox from './inbox';
 | 
					 | 
				
			||||||
import outbox from './outbox';
 | 
					 | 
				
			||||||
import publicKey from './publickey';
 | 
					 | 
				
			||||||
import note from './note';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express();
 | 
					 | 
				
			||||||
app.disable('x-powered-by');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.use(user);
 | 
					 | 
				
			||||||
app.use(inbox);
 | 
					 | 
				
			||||||
app.use(outbox);
 | 
					 | 
				
			||||||
app.use(publicKey);
 | 
					 | 
				
			||||||
app.use(note);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,28 +0,0 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import context from '../../remote/activitypub/renderer/context';
 | 
					 | 
				
			||||||
import render from '../../remote/activitypub/renderer/note';
 | 
					 | 
				
			||||||
import Note from '../../models/note';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express.Router();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.get('/notes/:note', async (req, res, next) => {
 | 
					 | 
				
			||||||
	const accepted = req.accepts(['html', 'application/activity+json', 'application/ld+json']);
 | 
					 | 
				
			||||||
	if (!(['application/activity+json', 'application/ld+json'] as any[]).includes(accepted)) {
 | 
					 | 
				
			||||||
		return next();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const note = await Note.findOne({
 | 
					 | 
				
			||||||
		_id: req.params.note
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (note === null) {
 | 
					 | 
				
			||||||
		return res.sendStatus(404);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const rendered = await render(note);
 | 
					 | 
				
			||||||
	rendered['@context'] = context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res.json(rendered);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,28 +0,0 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import context from '../../remote/activitypub/renderer/context';
 | 
					 | 
				
			||||||
import renderNote from '../../remote/activitypub/renderer/note';
 | 
					 | 
				
			||||||
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
 | 
					 | 
				
			||||||
import config from '../../config';
 | 
					 | 
				
			||||||
import Note from '../../models/note';
 | 
					 | 
				
			||||||
import User from '../../models/user';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express.Router();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.get('/users/:user/outbox', async (req, res) => {
 | 
					 | 
				
			||||||
	const userId = req.params.user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const user = await User.findOne({ _id: userId });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const notes = await Note.find({ userId: user._id }, {
 | 
					 | 
				
			||||||
		limit: 20,
 | 
					 | 
				
			||||||
		sort: { _id: -1 }
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
 | 
					 | 
				
			||||||
	const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes);
 | 
					 | 
				
			||||||
	rendered['@context'] = context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res.json(rendered);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,23 +0,0 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import context from '../../remote/activitypub/renderer/context';
 | 
					 | 
				
			||||||
import render from '../../remote/activitypub/renderer/key';
 | 
					 | 
				
			||||||
import User, { isLocalUser } from '../../models/user';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express.Router();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.get('/users/:user/publickey', async (req, res) => {
 | 
					 | 
				
			||||||
	const userId = req.params.user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const user = await User.findOne({ _id: userId });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (isLocalUser(user)) {
 | 
					 | 
				
			||||||
		const rendered = render(user);
 | 
					 | 
				
			||||||
		rendered['@context'] = context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		res.json(rendered);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		res.sendStatus(400);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,19 +0,0 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import context from '../../remote/activitypub/renderer/context';
 | 
					 | 
				
			||||||
import render from '../../remote/activitypub/renderer/person';
 | 
					 | 
				
			||||||
import User from '../../models/user';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = express.Router();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.get('/users/:user', async (req, res) => {
 | 
					 | 
				
			||||||
	const userId = req.params.user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const user = await User.findOne({ _id: userId });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const rendered = render(user);
 | 
					 | 
				
			||||||
	rendered['@context'] = context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res.json(rendered);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default app;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -5,67 +5,40 @@
 | 
				
			||||||
import * as fs from 'fs';
 | 
					import * as fs from 'fs';
 | 
				
			||||||
import * as http from 'http';
 | 
					import * as http from 'http';
 | 
				
			||||||
import * as https from 'https';
 | 
					import * as https from 'https';
 | 
				
			||||||
import * as express from 'express';
 | 
					import * as Koa from 'koa';
 | 
				
			||||||
import * as morgan from 'morgan';
 | 
					import * as Router from 'koa-router';
 | 
				
			||||||
 | 
					import * as bodyParser from 'koa-bodyparser';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import activityPub from './activitypub';
 | 
					import activityPub from './activitypub';
 | 
				
			||||||
import webFinger from './webfinger';
 | 
					import webFinger from './webfinger';
 | 
				
			||||||
import log from './log-request';
 | 
					 | 
				
			||||||
import config from '../config';
 | 
					import config from '../config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// Init server
 | 
				
			||||||
 * Init app
 | 
					const app = new Koa();
 | 
				
			||||||
 */
 | 
					app.proxy = true;
 | 
				
			||||||
const app = express();
 | 
					app.use(bodyParser);
 | 
				
			||||||
app.disable('x-powered-by');
 | 
					 | 
				
			||||||
app.set('trust proxy', 'loopback');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.use(morgan(process.env.NODE_ENV == 'production' ? 'combined' : 'dev', {
 | 
					// HSTS
 | 
				
			||||||
	// create a write stream (in append mode)
 | 
					// 6months (15552000sec)
 | 
				
			||||||
	stream: config.accesslog ? fs.createWriteStream(config.accesslog) : null
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.use((req, res, next) => {
 | 
					 | 
				
			||||||
	log(req);
 | 
					 | 
				
			||||||
	next();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * HSTS
 | 
					 | 
				
			||||||
 * 6month(15552000sec)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
if (config.url.startsWith('https')) {
 | 
					if (config.url.startsWith('https')) {
 | 
				
			||||||
	app.use((req, res, next) => {
 | 
						app.use((ctx, next) => {
 | 
				
			||||||
		res.header('strict-transport-security', 'max-age=15552000; preload');
 | 
							ctx.set('strict-transport-security', 'max-age=15552000; preload');
 | 
				
			||||||
		next();
 | 
							next();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Drop request when without 'Host' header
 | 
					// Init router
 | 
				
			||||||
app.use((req, res, next) => {
 | 
					const router = new Router();
 | 
				
			||||||
	if (!req.headers['host']) {
 | 
					 | 
				
			||||||
		res.sendStatus(400);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		next();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 互換性のため
 | 
					// Routing
 | 
				
			||||||
app.post('/meta', (req, res) => {
 | 
					router.use('/api', require('./api'));
 | 
				
			||||||
	res.header('Access-Control-Allow-Origin', '*');
 | 
					router.use('/files', require('./file'));
 | 
				
			||||||
	res.json({
 | 
					router.use(activityPub.routes());
 | 
				
			||||||
		version: 'nighthike'
 | 
					router.use(webFinger.routes());
 | 
				
			||||||
	});
 | 
					router.use(require('./web'));
 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// Register router
 | 
				
			||||||
 * Register modules
 | 
					app.use(router.routes());
 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
app.use('/api', require('./api'));
 | 
					 | 
				
			||||||
app.use('/files', require('./file'));
 | 
					 | 
				
			||||||
app.use(activityPub);
 | 
					 | 
				
			||||||
app.use(webFinger);
 | 
					 | 
				
			||||||
app.use(require('./web'));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createServer() {
 | 
					function createServer() {
 | 
				
			||||||
	if (config.https) {
 | 
						if (config.https) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +0,0 @@
 | 
				
			||||||
import * as crypto from 'crypto';
 | 
					 | 
				
			||||||
import * as express from 'express';
 | 
					 | 
				
			||||||
import * as proxyAddr from 'proxy-addr';
 | 
					 | 
				
			||||||
import Xev from 'xev';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ev = new Xev();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default function(req: express.Request) {
 | 
					 | 
				
			||||||
	const ip = proxyAddr(req, () => true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const md5 = crypto.createHash('md5');
 | 
					 | 
				
			||||||
	md5.update(ip);
 | 
					 | 
				
			||||||
	const hashedIp = md5.digest('hex').substr(0, 3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ev.emit('request', {
 | 
					 | 
				
			||||||
		ip: hashedIp,
 | 
					 | 
				
			||||||
		method: req.method,
 | 
					 | 
				
			||||||
		hostname: req.hostname,
 | 
					 | 
				
			||||||
		path: req.originalUrl
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,17 +1,19 @@
 | 
				
			||||||
import * as express from 'express';
 | 
					import * as Router from 'koa-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import config from '../config';
 | 
					import config from '../config';
 | 
				
			||||||
import parseAcct from '../acct/parse';
 | 
					import parseAcct from '../acct/parse';
 | 
				
			||||||
import User from '../models/user';
 | 
					import User from '../models/user';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const app = express.Router();
 | 
					// Init router
 | 
				
			||||||
 | 
					const router = new Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.get('/.well-known/webfinger', async (req, res) => {
 | 
					router.get('/.well-known/webfinger', async ctx => {
 | 
				
			||||||
	if (typeof req.query.resource !== 'string') {
 | 
						if (typeof ctx.query.resource !== 'string') {
 | 
				
			||||||
		return res.sendStatus(400);
 | 
							ctx.status = 400;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const resourceLower = req.query.resource.toLowerCase();
 | 
						const resourceLower = ctx.query.resource.toLowerCase();
 | 
				
			||||||
	const webPrefix = config.url.toLowerCase() + '/@';
 | 
						const webPrefix = config.url.toLowerCase() + '/@';
 | 
				
			||||||
	let acctLower;
 | 
						let acctLower;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,15 +27,21 @@ app.get('/.well-known/webfinger', async (req, res) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const parsedAcctLower = parseAcct(acctLower);
 | 
						const parsedAcctLower = parseAcct(acctLower);
 | 
				
			||||||
	if (![null, config.host.toLowerCase()].includes(parsedAcctLower.host)) {
 | 
						if (![null, config.host.toLowerCase()].includes(parsedAcctLower.host)) {
 | 
				
			||||||
		return res.sendStatus(422);
 | 
							ctx.status = 422;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const user = await User.findOne({ usernameLower: parsedAcctLower.username, host: null });
 | 
						const user = await User.findOne({
 | 
				
			||||||
 | 
							usernameLower: parsedAcctLower.username,
 | 
				
			||||||
 | 
							host: null
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (user === null) {
 | 
						if (user === null) {
 | 
				
			||||||
		return res.sendStatus(404);
 | 
							ctx.status = 404;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return res.json({
 | 
						ctx.body = {
 | 
				
			||||||
		subject: `acct:${user.username}@${config.host}`,
 | 
							subject: `acct:${user.username}@${config.host}`,
 | 
				
			||||||
		links: [{
 | 
							links: [{
 | 
				
			||||||
			rel: 'self',
 | 
								rel: 'self',
 | 
				
			||||||
| 
						 | 
					@ -47,7 +55,7 @@ app.get('/.well-known/webfinger', async (req, res) => {
 | 
				
			||||||
			rel: 'http://ostatus.org/schema/1.0/subscribe',
 | 
								rel: 'http://ostatus.org/schema/1.0/subscribe',
 | 
				
			||||||
			template: `${config.url}/authorize-follow?acct={uri}`
 | 
								template: `${config.url}/authorize-follow?acct={uri}`
 | 
				
			||||||
		}]
 | 
							}]
 | 
				
			||||||
	});
 | 
						};
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default app;
 | 
					export default router;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue