Refactor
This commit is contained in:
parent
ad57e36d0d
commit
e8bde94e5b
9 changed files with 47 additions and 40 deletions
|
@ -1,8 +1,8 @@
|
||||||
import config from '../../../../conf';
|
import config from '../../../../conf';
|
||||||
import { IRemoteAccount } from '../../../../models/user';
|
import { IRemoteUser } from '../../../../models/user';
|
||||||
|
|
||||||
export default ({ username }, { account }) => ({
|
export default ({ username }, followee: IRemoteUser) => ({
|
||||||
type: 'Follow',
|
type: 'Follow',
|
||||||
actor: `${config.url}/@${username}`,
|
actor: `${config.url}/@${username}`,
|
||||||
object: (account as IRemoteAccount).uri
|
object: followee.account.uri
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import config from '../../../../conf';
|
import config from '../../../../conf';
|
||||||
import { extractPublic } from '../../../../crypto_key';
|
import { extractPublic } from '../../../../crypto_key';
|
||||||
import { ILocalAccount } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
|
||||||
export default ({ username, account }) => ({
|
export default (user: ILocalUser) => ({
|
||||||
id: `${config.url}/@${username}/publickey`,
|
id: `${config.url}/@${user.username}/publickey`,
|
||||||
type: 'Key',
|
type: 'Key',
|
||||||
owner: `${config.url}/@${username}`,
|
owner: `${config.url}/@${user.username}`,
|
||||||
publicKeyPem: extractPublic((account as ILocalAccount).keypair)
|
publicKeyPem: extractPublic(user.account.keypair)
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ILocalAccount, IUser } from '../../models/user';
|
import { IUser, isLocalUser } from '../../models/user';
|
||||||
import getAcct from './get-acct';
|
import getAcct from './get-acct';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,8 +9,8 @@ export default function(user: IUser): string {
|
||||||
let string = `${user.name} (@${getAcct(user)})\n` +
|
let string = `${user.name} (@${getAcct(user)})\n` +
|
||||||
`${user.postsCount}投稿、${user.followingCount}フォロー、${user.followersCount}フォロワー\n`;
|
`${user.postsCount}投稿、${user.followingCount}フォロー、${user.followersCount}フォロワー\n`;
|
||||||
|
|
||||||
if (user.host === null) {
|
if (isLocalUser(user)) {
|
||||||
const account = user.account as ILocalAccount;
|
const account = user.account;
|
||||||
string += `場所: ${account.profile.location}、誕生日: ${account.profile.birthday}\n`;
|
string += `場所: ${account.profile.location}、誕生日: ${account.profile.birthday}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function isValidBirthday(birthday: string): boolean {
|
||||||
return typeof birthday == 'string' && /^([0-9]{4})\-([0-9]{2})-([0-9]{2})$/.test(birthday);
|
return typeof birthday == 'string' && /^([0-9]{4})\-([0-9]{2})-([0-9]{2})$/.test(birthday);
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ILocalAccount = {
|
type ILocalAccount = {
|
||||||
keypair: string;
|
keypair: string;
|
||||||
email: string;
|
email: string;
|
||||||
links: string[];
|
links: string[];
|
||||||
|
@ -69,7 +69,7 @@ export type ILocalAccount = {
|
||||||
settings: any;
|
settings: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IRemoteAccount = {
|
type IRemoteAccount = {
|
||||||
inbox: string;
|
inbox: string;
|
||||||
uri: string;
|
uri: string;
|
||||||
publicKey: {
|
publicKey: {
|
||||||
|
@ -78,7 +78,7 @@ export type IRemoteAccount = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IUser = {
|
type IUserBase = {
|
||||||
_id: mongo.ObjectID;
|
_id: mongo.ObjectID;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
deletedAt: Date;
|
deletedAt: Date;
|
||||||
|
@ -97,13 +97,19 @@ export type IUser = {
|
||||||
pinnedPostId: mongo.ObjectID;
|
pinnedPostId: mongo.ObjectID;
|
||||||
isSuspended: boolean;
|
isSuspended: boolean;
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
host: string;
|
|
||||||
hostLower: string;
|
hostLower: string;
|
||||||
account: ILocalAccount | IRemoteAccount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ILocalUser = IUser & { account: ILocalAccount };
|
export type IUser = ILocalUser | IRemoteUser;
|
||||||
export type IRemoteUser = IUser & { account: IRemoteAccount };
|
|
||||||
|
export interface ILocalUser extends IUserBase { host: null; account: ILocalAccount; }
|
||||||
|
export interface IRemoteUser extends IUserBase { host: string; account: IRemoteAccount; }
|
||||||
|
|
||||||
|
export const isLocalUser = (user: any): user is ILocalUser =>
|
||||||
|
user.host === null;
|
||||||
|
|
||||||
|
export const isRemoteUser = (user: any): user is IRemoteUser =>
|
||||||
|
!isLocalUser(user);
|
||||||
|
|
||||||
export function init(user): IUser {
|
export function init(user): IUser {
|
||||||
user._id = new mongo.ObjectID(user._id);
|
user._id = new mongo.ObjectID(user._id);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { request } from 'https';
|
import { request } from 'https';
|
||||||
import { sign } from 'http-signature';
|
import { sign } from 'http-signature';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import User, { ILocalAccount, IRemoteAccount, pack as packUser } from '../../models/user';
|
import User, { isLocalUser, pack as packUser, ILocalUser } from '../../models/user';
|
||||||
import Following from '../../models/following';
|
import Following from '../../models/following';
|
||||||
import event from '../../common/event';
|
import event from '../../common/event';
|
||||||
import notify from '../../common/notify';
|
import notify from '../../common/notify';
|
||||||
|
@ -10,7 +10,7 @@ import render from '../../common/remote/activitypub/renderer/follow';
|
||||||
import config from '../../conf';
|
import config from '../../conf';
|
||||||
|
|
||||||
export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => {
|
export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => {
|
||||||
const promisedFollower = User.findOne({ _id: followerId });
|
const promisedFollower: Promise<ILocalUser> = User.findOne({ _id: followerId });
|
||||||
const promisedFollowee = User.findOne({ _id: followeeId });
|
const promisedFollowee = User.findOne({ _id: followeeId });
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
|
@ -38,7 +38,7 @@ export default ({ data }, done) => Following.findOne({ _id: data.following }).th
|
||||||
.then(packed => event(follower._id, 'follow', packed));
|
.then(packed => event(follower._id, 'follow', packed));
|
||||||
let followeeEvent;
|
let followeeEvent;
|
||||||
|
|
||||||
if (followee.host === null) {
|
if (isLocalUser(followee)) {
|
||||||
followeeEvent = packUser(follower, followee)
|
followeeEvent = packUser(follower, followee)
|
||||||
.then(packed => event(followee._id, 'followed', packed));
|
.then(packed => event(followee._id, 'followed', packed));
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,7 +49,7 @@ export default ({ data }, done) => Following.findOne({ _id: data.following }).th
|
||||||
port,
|
port,
|
||||||
pathname,
|
pathname,
|
||||||
search
|
search
|
||||||
} = new URL((followee.account as IRemoteAccount).inbox);
|
} = new URL(followee.account.inbox);
|
||||||
|
|
||||||
const req = request({
|
const req = request({
|
||||||
protocol,
|
protocol,
|
||||||
|
@ -72,7 +72,7 @@ export default ({ data }, done) => Following.findOne({ _id: data.following }).th
|
||||||
|
|
||||||
sign(req, {
|
sign(req, {
|
||||||
authorizationHeaderName: 'Signature',
|
authorizationHeaderName: 'Signature',
|
||||||
key: (follower.account as ILocalAccount).keypair,
|
key: follower.account.keypair,
|
||||||
keyId: `acct:${follower.username}@${config.host}`
|
keyId: `acct:${follower.username}@${config.host}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import * as bodyParser from 'body-parser';
|
import * as bodyParser from 'body-parser';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import { parseRequest, verifySignature } from 'http-signature';
|
import { parseRequest, verifySignature } from 'http-signature';
|
||||||
import User, { IRemoteAccount } from '../../models/user';
|
import User, { IRemoteUser } from '../../models/user';
|
||||||
import queue from '../../queue';
|
import queue from '../../queue';
|
||||||
|
import parseAcct from '../../common/user/parse-acct';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.disable('x-powered-by');
|
app.disable('x-powered-by');
|
||||||
|
@ -36,13 +37,13 @@ app.post('/@:user/inbox', async (req, res) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await User.findOne(query);
|
const user = await User.findOne(query) as IRemoteUser;
|
||||||
|
|
||||||
if (user === null) {
|
if (user === null) {
|
||||||
return res.sendStatus(401);
|
return res.sendStatus(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verifySignature(parsed, (user.account as IRemoteAccount).publicKey.publicKeyPem)) {
|
if (!verifySignature(parsed, user.account.publicKey.publicKeyPem)) {
|
||||||
return res.sendStatus(401);
|
return res.sendStatus(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as EventEmitter from 'events';
|
import * as EventEmitter from 'events';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import * as bcrypt from 'bcryptjs';
|
||||||
|
|
||||||
import User, { ILocalAccount, IUser, init as initUser } from '../../../models/user';
|
import User, { IUser, init as initUser, ILocalUser } from '../../../models/user';
|
||||||
|
|
||||||
import getPostSummary from '../../../common/get-post-summary';
|
import getPostSummary from '../../../common/get-post-summary';
|
||||||
import getUserSummary from '../../../common/user/get-summary';
|
import getUserSummary from '../../../common/user/get-summary';
|
||||||
|
@ -198,7 +198,7 @@ abstract class Context extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SigninContext extends Context {
|
class SigninContext extends Context {
|
||||||
private temporaryUser: IUser = null;
|
private temporaryUser: ILocalUser = null;
|
||||||
|
|
||||||
public async greet(): Promise<string> {
|
public async greet(): Promise<string> {
|
||||||
return 'まずユーザー名を教えてください:';
|
return 'まずユーザー名を教えてください:';
|
||||||
|
@ -207,14 +207,14 @@ class SigninContext extends Context {
|
||||||
public async q(query: string): Promise<string> {
|
public async q(query: string): Promise<string> {
|
||||||
if (this.temporaryUser == null) {
|
if (this.temporaryUser == null) {
|
||||||
// Fetch user
|
// Fetch user
|
||||||
const user: IUser = await User.findOne({
|
const user = await User.findOne({
|
||||||
usernameLower: query.toLowerCase(),
|
usernameLower: query.toLowerCase(),
|
||||||
host: null
|
host: null
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
data: false
|
data: false
|
||||||
}
|
}
|
||||||
});
|
}) as ILocalUser;
|
||||||
|
|
||||||
if (user === null) {
|
if (user === null) {
|
||||||
return `${query}というユーザーは存在しませんでした... もう一度教えてください:`;
|
return `${query}というユーザーは存在しませんでした... もう一度教えてください:`;
|
||||||
|
@ -225,7 +225,7 @@ class SigninContext extends Context {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Compare password
|
// Compare password
|
||||||
const same = await bcrypt.compare(query, (this.temporaryUser.account as ILocalAccount).password);
|
const same = await bcrypt.compare(query, this.temporaryUser.account.password);
|
||||||
|
|
||||||
if (same) {
|
if (same) {
|
||||||
this.bot.signin(this.temporaryUser);
|
this.bot.signin(this.temporaryUser);
|
||||||
|
|
|
@ -5,9 +5,9 @@ import $ from 'cafy';
|
||||||
import deepEqual = require('deep-equal');
|
import deepEqual = require('deep-equal');
|
||||||
import html from '../../../../common/text/html';
|
import html from '../../../../common/text/html';
|
||||||
import parse from '../../../../common/text/parse';
|
import parse from '../../../../common/text/parse';
|
||||||
import { default as Post, IPost, isValidText, isValidCw } from '../../../../models/post';
|
import Post, { IPost, isValidText, isValidCw } from '../../../../models/post';
|
||||||
import { default as User, ILocalAccount, IUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import { default as Channel, IChannel } from '../../../../models/channel';
|
import Channel, { IChannel } from '../../../../models/channel';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import DriveFile from '../../../../models/drive-file';
|
import DriveFile from '../../../../models/drive-file';
|
||||||
|
@ -29,7 +29,7 @@ import config from '../../../../conf';
|
||||||
* @param {any} app
|
* @param {any} app
|
||||||
* @return {Promise<any>}
|
* @return {Promise<any>}
|
||||||
*/
|
*/
|
||||||
module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
|
module.exports = (params, user: ILocalUser, app) => new Promise(async (res, rej) => {
|
||||||
// Get 'text' parameter
|
// Get 'text' parameter
|
||||||
const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$;
|
const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$;
|
||||||
if (textErr) return rej('invalid text');
|
if (textErr) return rej('invalid text');
|
||||||
|
@ -400,7 +400,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// この投稿をWatchする
|
// この投稿をWatchする
|
||||||
if ((user.account as ILocalAccount).settings.autoWatch !== false) {
|
if (user.account.settings.autoWatch !== false) {
|
||||||
watch(user._id, reply);
|
watch(user._id, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import * as bcrypt from 'bcryptjs';
|
||||||
import * as speakeasy from 'speakeasy';
|
import * as speakeasy from 'speakeasy';
|
||||||
import { default as User, ILocalAccount, IUser } from '../../../models/user';
|
import User, { ILocalUser } from '../../../models/user';
|
||||||
import Signin, { pack } from '../../../models/signin';
|
import Signin, { pack } from '../../../models/signin';
|
||||||
import event from '../../../common/event';
|
import event from '../../../common/event';
|
||||||
import signin from '../common/signin';
|
import signin from '../common/signin';
|
||||||
|
@ -31,7 +31,7 @@ export default async (req: express.Request, res: express.Response) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch user
|
// Fetch user
|
||||||
const user: IUser = await User.findOne({
|
const user = await User.findOne({
|
||||||
usernameLower: username.toLowerCase(),
|
usernameLower: username.toLowerCase(),
|
||||||
host: null
|
host: null
|
||||||
}, {
|
}, {
|
||||||
|
@ -39,7 +39,7 @@ export default async (req: express.Request, res: express.Response) => {
|
||||||
data: false,
|
data: false,
|
||||||
'account.profile': false
|
'account.profile': false
|
||||||
}
|
}
|
||||||
});
|
}) as ILocalUser;
|
||||||
|
|
||||||
if (user === null) {
|
if (user === null) {
|
||||||
res.status(404).send({
|
res.status(404).send({
|
||||||
|
@ -48,7 +48,7 @@ export default async (req: express.Request, res: express.Response) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = user.account as ILocalAccount;
|
const account = user.account;
|
||||||
|
|
||||||
// Compare password
|
// Compare password
|
||||||
const same = await bcrypt.compare(password, account.password);
|
const same = await bcrypt.compare(password, account.password);
|
||||||
|
|
Loading…
Reference in a new issue