mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-26 22:29:28 +09:00
ストリーム経由でAPIにリクエストできるように
This commit is contained in:
parent
91791834be
commit
bd3d57a67f
@ -444,23 +444,28 @@ export default class MiOS extends EventEmitter {
|
|||||||
// Append a credential
|
// Append a credential
|
||||||
if (this.isSignedIn) (data as any).i = this.i.token;
|
if (this.isSignedIn) (data as any).i = this.i.token;
|
||||||
|
|
||||||
// TODO
|
const viaStream = localStorage.getItem('enableExperimental') == 'true';
|
||||||
//const viaStream = localStorage.getItem('enableExperimental') == 'true';
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
/*if (viaStream) {
|
if (viaStream) {
|
||||||
const stream = this.stream.borrow();
|
const stream = this.stream.borrow();
|
||||||
const id = Math.random().toString();
|
const id = Math.random().toString();
|
||||||
|
|
||||||
stream.once(`api-res:${id}`, res => {
|
stream.once(`api-res:${id}`, res => {
|
||||||
resolve(res);
|
if (res.res) {
|
||||||
|
resolve(res.res);
|
||||||
|
} else {
|
||||||
|
reject(res.e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
stream.send({
|
stream.send({
|
||||||
type: 'api',
|
type: 'api',
|
||||||
id,
|
id,
|
||||||
endpoint,
|
endpoint,
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
} else {*/
|
} else {
|
||||||
const req = {
|
const req = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
|
@ -19,7 +19,7 @@ export type IApp = {
|
|||||||
nameId: string;
|
nameId: string;
|
||||||
nameIdLower: string;
|
nameIdLower: string;
|
||||||
description: string;
|
description: string;
|
||||||
permission: string;
|
permission: string[];
|
||||||
callbackUrl: string;
|
callbackUrl: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,55 +2,33 @@ import * as express from 'express';
|
|||||||
|
|
||||||
import { Endpoint } from './endpoints';
|
import { Endpoint } from './endpoints';
|
||||||
import authenticate from './authenticate';
|
import authenticate from './authenticate';
|
||||||
import { IAuthContext } from './authenticate';
|
import call from './call';
|
||||||
import _reply from './reply';
|
import { IUser } from '../../models/user';
|
||||||
import limitter from './limitter';
|
import { IApp } from '../../models/app';
|
||||||
|
|
||||||
export default async (endpoint: Endpoint, req: express.Request, res: express.Response) => {
|
export default async (endpoint: Endpoint, req: express.Request, res: express.Response) => {
|
||||||
const reply = _reply.bind(null, res);
|
const reply = (x?: any, y?: any) => {
|
||||||
let ctx: IAuthContext;
|
if (x === undefined) {
|
||||||
|
res.sendStatus(204);
|
||||||
|
} else if (typeof x === 'number') {
|
||||||
|
res.status(x).send({
|
||||||
|
error: x === 500 ? 'INTERNAL_ERROR' : y
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.send(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let user: IUser;
|
||||||
|
let app: IApp;
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
try {
|
try {
|
||||||
ctx = await authenticate(req);
|
[user, app] = await authenticate(req.body['i']);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return reply(403, 'AUTHENTICATION_FAILED');
|
return reply(403, 'AUTHENTICATION_FAILED');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endpoint.secure && !ctx.isSecure) {
|
|
||||||
return reply(403, 'ACCESS_DENIED');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.withCredential && ctx.user == null) {
|
|
||||||
return reply(401, 'PLZ_SIGNIN');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.app && endpoint.kind) {
|
|
||||||
if (!ctx.app.permission.some(p => p === endpoint.kind)) {
|
|
||||||
return reply(403, 'ACCESS_DENIED');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.withCredential && endpoint.limit) {
|
|
||||||
try {
|
|
||||||
await limitter(endpoint, ctx); // Rate limit
|
|
||||||
} catch (e) {
|
|
||||||
// drop request if limit exceeded
|
|
||||||
return reply(429);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let exec = require(`${__dirname}/endpoints/${endpoint.name}`);
|
|
||||||
|
|
||||||
if (endpoint.withFile) {
|
|
||||||
exec = exec.bind(null, req.file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// API invoking
|
// API invoking
|
||||||
try {
|
call(endpoint, user, app, req.body, req).then(reply).catch(e => reply(400, e));
|
||||||
const res = await exec(req.body, ctx.user, ctx.app, ctx.isSecure);
|
|
||||||
reply(res);
|
|
||||||
} catch (e) {
|
|
||||||
reply(400, e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -1,50 +1,24 @@
|
|||||||
import * as express from 'express';
|
import App, { IApp } from '../../models/app';
|
||||||
import App from '../../models/app';
|
|
||||||
import { default as User, IUser } from '../../models/user';
|
import { default as User, IUser } from '../../models/user';
|
||||||
import AccessToken from '../../models/access-token';
|
import AccessToken from '../../models/access-token';
|
||||||
import isNativeToken from './common/is-native-token';
|
import isNativeToken from './common/is-native-token';
|
||||||
|
|
||||||
export interface IAuthContext {
|
export default (token: string) => new Promise<[IUser, IApp]>(async (resolve, reject) => {
|
||||||
/**
|
|
||||||
* App which requested
|
|
||||||
*/
|
|
||||||
app: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticated user
|
|
||||||
*/
|
|
||||||
user: IUser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether requested with a User-Native Token
|
|
||||||
*/
|
|
||||||
isSecure: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (req: express.Request) => new Promise<IAuthContext>(async (resolve, reject) => {
|
|
||||||
const token = req.body['i'] as string;
|
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
return resolve({
|
resolve([null, null]);
|
||||||
app: null,
|
return;
|
||||||
user: null,
|
|
||||||
isSecure: false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNativeToken(token)) {
|
if (isNativeToken(token)) {
|
||||||
|
// Fetch user
|
||||||
const user: IUser = await User
|
const user: IUser = await User
|
||||||
.findOne({ 'token': token });
|
.findOne({ token });
|
||||||
|
|
||||||
if (user === null) {
|
if (user === null) {
|
||||||
return reject('user not found');
|
return reject('user not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve({
|
resolve([user, null]);
|
||||||
app: null,
|
|
||||||
user: user,
|
|
||||||
isSecure: true
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const accessToken = await AccessToken.findOne({
|
const accessToken = await AccessToken.findOne({
|
||||||
hash: token.toLowerCase()
|
hash: token.toLowerCase()
|
||||||
@ -60,10 +34,6 @@ export default (req: express.Request) => new Promise<IAuthContext>(async (resolv
|
|||||||
const user = await User
|
const user = await User
|
||||||
.findOne({ _id: accessToken.userId });
|
.findOne({ _id: accessToken.userId });
|
||||||
|
|
||||||
return resolve({
|
resolve([user, app]);
|
||||||
app: app,
|
|
||||||
user: user,
|
|
||||||
isSecure: false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
55
src/server/api/call.ts
Normal file
55
src/server/api/call.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import * as express from 'express';
|
||||||
|
|
||||||
|
import endpoints, { Endpoint } from './endpoints';
|
||||||
|
import limitter from './limitter';
|
||||||
|
import { IUser } from '../../models/user';
|
||||||
|
import { IApp } from '../../models/app';
|
||||||
|
|
||||||
|
export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, req?: express.Request) => new Promise(async (ok, rej) => {
|
||||||
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
|
//console.log(endpoint, user, app, data);
|
||||||
|
|
||||||
|
const ep = typeof endpoint == 'string' ? endpoints.find(e => e.name == endpoint) : endpoint;
|
||||||
|
|
||||||
|
if (ep.secure && !isSecure) {
|
||||||
|
return rej('ACCESS_DENIED');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ep.withCredential && user == null) {
|
||||||
|
return rej('SIGNIN_REQUIRED');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app && ep.kind) {
|
||||||
|
if (!app.permission.some(p => p === ep.kind)) {
|
||||||
|
return rej('PERMISSION_DENIED');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ep.withCredential && ep.limit) {
|
||||||
|
try {
|
||||||
|
await limitter(ep, user); // Rate limit
|
||||||
|
} catch (e) {
|
||||||
|
// drop request if limit exceeded
|
||||||
|
return rej('RATE_LIMIT_EXCEEDED');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let exec = require(`${__dirname}/endpoints/${ep.name}`);
|
||||||
|
|
||||||
|
if (ep.withFile && req) {
|
||||||
|
exec = exec.bind(null, req.file);
|
||||||
|
}
|
||||||
|
|
||||||
|
let res;
|
||||||
|
|
||||||
|
// API invoking
|
||||||
|
try {
|
||||||
|
res = await exec(data, user, app);
|
||||||
|
} catch (e) {
|
||||||
|
rej(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(res);
|
||||||
|
});
|
@ -36,14 +36,10 @@ import App, { pack } from '../../../../models/app';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an app
|
* Show an app
|
||||||
*
|
|
||||||
* @param {any} params
|
|
||||||
* @param {any} user
|
|
||||||
* @param {any} _
|
|
||||||
* @param {any} isSecure
|
|
||||||
* @return {Promise<any>}
|
|
||||||
*/
|
*/
|
||||||
module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => {
|
module.exports = (params, user, app) => new Promise(async (res, rej) => {
|
||||||
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
// Get 'appId' parameter
|
// Get 'appId' parameter
|
||||||
const [appId, appIdErr] = $(params.appId).optional.id().$;
|
const [appId, appIdErr] = $(params.appId).optional.id().$;
|
||||||
if (appIdErr) return rej('invalid appId param');
|
if (appIdErr) return rej('invalid appId param');
|
||||||
@ -57,16 +53,16 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lookup app
|
// Lookup app
|
||||||
const app = appId !== undefined
|
const ap = appId !== undefined
|
||||||
? await App.findOne({ _id: appId })
|
? await App.findOne({ _id: appId })
|
||||||
: await App.findOne({ nameIdLower: nameId.toLowerCase() });
|
: await App.findOne({ nameIdLower: nameId.toLowerCase() });
|
||||||
|
|
||||||
if (app === null) {
|
if (ap === null) {
|
||||||
return rej('app not found');
|
return rej('app not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
res(await pack(app, user, {
|
res(await pack(ap, user, {
|
||||||
includeSecret: isSecure && app.userId.equals(user._id)
|
includeSecret: isSecure && ap.userId.equals(user._id)
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,9 @@ import User, { pack } from '../../../models/user';
|
|||||||
/**
|
/**
|
||||||
* Show myself
|
* Show myself
|
||||||
*/
|
*/
|
||||||
module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => {
|
module.exports = (params, user, app) => new Promise(async (res, rej) => {
|
||||||
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
// Serialize
|
// Serialize
|
||||||
res(await pack(user, user, {
|
res(await pack(user, user, {
|
||||||
detail: true,
|
detail: true,
|
||||||
|
@ -7,14 +7,10 @@ import event from '../../../../publishers/stream';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update myself
|
* Update myself
|
||||||
*
|
|
||||||
* @param {any} params
|
|
||||||
* @param {any} user
|
|
||||||
* @param {any} _
|
|
||||||
* @param {boolean} isSecure
|
|
||||||
* @return {Promise<any>}
|
|
||||||
*/
|
*/
|
||||||
module.exports = async (params, user, _, isSecure) => new Promise(async (res, rej) => {
|
module.exports = async (params, user, app) => new Promise(async (res, rej) => {
|
||||||
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
// Get 'name' parameter
|
// Get 'name' parameter
|
||||||
const [name, nameErr] = $(params.name).optional.nullable.string().pipe(isValidName).$;
|
const [name, nameErr] = $(params.name).optional.nullable.string().pipe(isValidName).$;
|
||||||
if (nameErr) return rej('invalid name param');
|
if (nameErr) return rej('invalid name param');
|
||||||
|
@ -35,9 +35,6 @@ import Meta from '../../../models/meta';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Show core info
|
* Show core info
|
||||||
*
|
|
||||||
* @param {any} params
|
|
||||||
* @return {Promise<any>}
|
|
||||||
*/
|
*/
|
||||||
module.exports = (params) => new Promise(async (res, rej) => {
|
module.exports = (params) => new Promise(async (res, rej) => {
|
||||||
const meta: any = (await Meta.findOne()) || {};
|
const meta: any = (await Meta.findOne()) || {};
|
||||||
|
@ -6,14 +6,8 @@ import Subscription from '../../../../models/sw-subscription';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* subscribe service worker
|
* subscribe service worker
|
||||||
*
|
|
||||||
* @param {any} params
|
|
||||||
* @param {any} user
|
|
||||||
* @param {any} _
|
|
||||||
* @param {boolean} isSecure
|
|
||||||
* @return {Promise<any>}
|
|
||||||
*/
|
*/
|
||||||
module.exports = async (params, user, _, isSecure) => new Promise(async (res, rej) => {
|
module.exports = async (params, user, app) => new Promise(async (res, rej) => {
|
||||||
// Get 'endpoint' parameter
|
// Get 'endpoint' parameter
|
||||||
const [endpoint, endpointErr] = $(params.endpoint).string().$;
|
const [endpoint, endpointErr] = $(params.endpoint).string().$;
|
||||||
if (endpointErr) return rej('invalid endpoint param');
|
if (endpointErr) return rej('invalid endpoint param');
|
||||||
|
@ -7,7 +7,6 @@ import * as bodyParser from 'body-parser';
|
|||||||
import * as cors from 'cors';
|
import * as cors from 'cors';
|
||||||
import * as multer from 'multer';
|
import * as multer from 'multer';
|
||||||
|
|
||||||
// import authenticate from './authenticate';
|
|
||||||
import endpoints from './endpoints';
|
import endpoints from './endpoints';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,12 +2,12 @@ import * as Limiter from 'ratelimiter';
|
|||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import limiterDB from '../../db/redis';
|
import limiterDB from '../../db/redis';
|
||||||
import { Endpoint } from './endpoints';
|
import { Endpoint } from './endpoints';
|
||||||
import { IAuthContext } from './authenticate';
|
|
||||||
import getAcct from '../../acct/render';
|
import getAcct from '../../acct/render';
|
||||||
|
import { IUser } from '../../models/user';
|
||||||
|
|
||||||
const log = debug('misskey:limitter');
|
const log = debug('misskey:limitter');
|
||||||
|
|
||||||
export default (endpoint: Endpoint, ctx: IAuthContext) => new Promise((ok, reject) => {
|
export default (endpoint: Endpoint, user: IUser) => new Promise((ok, reject) => {
|
||||||
const limitation = endpoint.limit;
|
const limitation = endpoint.limit;
|
||||||
|
|
||||||
const key = limitation.hasOwnProperty('key')
|
const key = limitation.hasOwnProperty('key')
|
||||||
@ -32,7 +32,7 @@ export default (endpoint: Endpoint, ctx: IAuthContext) => new Promise((ok, rejec
|
|||||||
// Short-term limit
|
// Short-term limit
|
||||||
function min() {
|
function min() {
|
||||||
const minIntervalLimiter = new Limiter({
|
const minIntervalLimiter = new Limiter({
|
||||||
id: `${ctx.user._id}:${key}:min`,
|
id: `${user._id}:${key}:min`,
|
||||||
duration: limitation.minInterval,
|
duration: limitation.minInterval,
|
||||||
max: 1,
|
max: 1,
|
||||||
db: limiterDB
|
db: limiterDB
|
||||||
@ -43,7 +43,7 @@ export default (endpoint: Endpoint, ctx: IAuthContext) => new Promise((ok, rejec
|
|||||||
return reject('ERR');
|
return reject('ERR');
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`@${getAcct(ctx.user)} ${endpoint.name} min remaining: ${info.remaining}`);
|
log(`@${getAcct(user)} ${endpoint.name} min remaining: ${info.remaining}`);
|
||||||
|
|
||||||
if (info.remaining === 0) {
|
if (info.remaining === 0) {
|
||||||
reject('BRIEF_REQUEST_INTERVAL');
|
reject('BRIEF_REQUEST_INTERVAL');
|
||||||
@ -60,7 +60,7 @@ export default (endpoint: Endpoint, ctx: IAuthContext) => new Promise((ok, rejec
|
|||||||
// Long term limit
|
// Long term limit
|
||||||
function max() {
|
function max() {
|
||||||
const limiter = new Limiter({
|
const limiter = new Limiter({
|
||||||
id: `${ctx.user._id}:${key}`,
|
id: `${user._id}:${key}`,
|
||||||
duration: limitation.duration,
|
duration: limitation.duration,
|
||||||
max: limitation.max,
|
max: limitation.max,
|
||||||
db: limiterDB
|
db: limiterDB
|
||||||
@ -71,7 +71,7 @@ export default (endpoint: Endpoint, ctx: IAuthContext) => new Promise((ok, rejec
|
|||||||
return reject('ERR');
|
return reject('ERR');
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`@${getAcct(ctx.user)} ${endpoint.name} max remaining: ${info.remaining}`);
|
log(`@${getAcct(user)} ${endpoint.name} max remaining: ${info.remaining}`);
|
||||||
|
|
||||||
if (info.remaining === 0) {
|
if (info.remaining === 0) {
|
||||||
reject('RATE_LIMIT_EXCEEDED');
|
reject('RATE_LIMIT_EXCEEDED');
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import * as express from 'express';
|
|
||||||
|
|
||||||
export default (res: express.Response, x?: any, y?: any) => {
|
|
||||||
if (x === undefined) {
|
|
||||||
res.sendStatus(204);
|
|
||||||
} else if (typeof x === 'number') {
|
|
||||||
res.status(x).send({
|
|
||||||
error: x === 500 ? 'INTERNAL_ERROR' : y
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.send(x);
|
|
||||||
}
|
|
||||||
};
|
|
@ -2,14 +2,22 @@ import * as websocket from 'websocket';
|
|||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
|
|
||||||
import User from '../../../models/user';
|
import User, { IUser } from '../../../models/user';
|
||||||
import Mute from '../../../models/mute';
|
import Mute from '../../../models/mute';
|
||||||
import { pack as packNote } from '../../../models/note';
|
import { pack as packNote } from '../../../models/note';
|
||||||
import readNotification from '../common/read-notification';
|
import readNotification from '../common/read-notification';
|
||||||
|
import call from '../call';
|
||||||
|
import { IApp } from '../../../models/app';
|
||||||
|
|
||||||
const log = debug('misskey');
|
const log = debug('misskey');
|
||||||
|
|
||||||
export default async function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any) {
|
export default async function(
|
||||||
|
request: websocket.request,
|
||||||
|
connection: websocket.connection,
|
||||||
|
subscriber: redis.RedisClient,
|
||||||
|
user: IUser,
|
||||||
|
app: IApp
|
||||||
|
) {
|
||||||
// Subscribe Home stream channel
|
// Subscribe Home stream channel
|
||||||
subscriber.subscribe(`misskey:user-stream:${user._id}`);
|
subscriber.subscribe(`misskey:user-stream:${user._id}`);
|
||||||
|
|
||||||
@ -67,7 +75,17 @@ export default async function(request: websocket.request, connection: websocket.
|
|||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case 'api':
|
case 'api':
|
||||||
// TODO
|
call(msg.endpoint, user, app, msg.data).then(res => {
|
||||||
|
connection.send(JSON.stringify({
|
||||||
|
type: `api-res:${msg.id}`,
|
||||||
|
body: { res }
|
||||||
|
}));
|
||||||
|
}).catch(e => {
|
||||||
|
connection.send(JSON.stringify({
|
||||||
|
type: `api-res:${msg.id}`,
|
||||||
|
body: { e }
|
||||||
|
}));
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'alive':
|
case 'alive':
|
||||||
|
@ -2,9 +2,6 @@ import * as http from 'http';
|
|||||||
import * as websocket from 'websocket';
|
import * as websocket from 'websocket';
|
||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import { default as User, IUser } from '../../models/user';
|
|
||||||
import AccessToken from '../../models/access-token';
|
|
||||||
import isNativeToken from './common/is-native-token';
|
|
||||||
|
|
||||||
import homeStream from './stream/home';
|
import homeStream from './stream/home';
|
||||||
import driveStream from './stream/drive';
|
import driveStream from './stream/drive';
|
||||||
@ -16,6 +13,7 @@ import serverStream from './stream/server';
|
|||||||
import requestsStream from './stream/requests';
|
import requestsStream from './stream/requests';
|
||||||
import channelStream from './stream/channel';
|
import channelStream from './stream/channel';
|
||||||
import { ParsedUrlQuery } from 'querystring';
|
import { ParsedUrlQuery } from 'querystring';
|
||||||
|
import authenticate from './authenticate';
|
||||||
|
|
||||||
module.exports = (server: http.Server) => {
|
module.exports = (server: http.Server) => {
|
||||||
/**
|
/**
|
||||||
@ -53,7 +51,7 @@ module.exports = (server: http.Server) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const q = request.resourceURL.query as ParsedUrlQuery;
|
const q = request.resourceURL.query as ParsedUrlQuery;
|
||||||
const user = await authenticate(q.i as string);
|
const [user, app] = await authenticate(q.i as string);
|
||||||
|
|
||||||
if (request.resourceURL.pathname === '/othello-game') {
|
if (request.resourceURL.pathname === '/othello-game') {
|
||||||
othelloGameStream(request, connection, subscriber, user);
|
othelloGameStream(request, connection, subscriber, user);
|
||||||
@ -75,46 +73,9 @@ module.exports = (server: http.Server) => {
|
|||||||
null;
|
null;
|
||||||
|
|
||||||
if (channel !== null) {
|
if (channel !== null) {
|
||||||
channel(request, connection, subscriber, user);
|
channel(request, connection, subscriber, user, app);
|
||||||
} else {
|
} else {
|
||||||
connection.close();
|
connection.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 接続してきたユーザーを取得します
|
|
||||||
* @param token 送信されてきたトークン
|
|
||||||
*/
|
|
||||||
function authenticate(token: string): Promise<IUser> {
|
|
||||||
if (token == null) {
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
if (isNativeToken(token)) {
|
|
||||||
// Fetch user
|
|
||||||
const user: IUser = await User
|
|
||||||
.findOne({
|
|
||||||
host: null,
|
|
||||||
'token': token
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve(user);
|
|
||||||
} else {
|
|
||||||
const accessToken = await AccessToken.findOne({
|
|
||||||
hash: token
|
|
||||||
});
|
|
||||||
|
|
||||||
if (accessToken == null) {
|
|
||||||
return reject('invalid signature');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch user
|
|
||||||
const user: IUser = await User
|
|
||||||
.findOne({ _id: accessToken.userId });
|
|
||||||
|
|
||||||
resolve(user);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user