From 767a292dbdaedeb34de5476f0c23ca25a0395e90 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 23 Nov 2017 13:25:33 +0900 Subject: #939 --- src/api/service/twitter.ts | 78 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 9 deletions(-) (limited to 'src/api/service') diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index 9fb274aacb..b5dfc2c99a 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -1,4 +1,6 @@ import * as express from 'express'; +import * as cookie from 'cookie'; +import * as uuid from 'uuid'; // import * as Twitter from 'twitter'; // const Twitter = require('twitter'); import autwh from 'autwh'; @@ -7,6 +9,7 @@ import User from '../models/user'; import serialize from '../serializers/user'; import event from '../event'; import config from '../../conf'; +import signin from '../common/signin'; module.exports = (app: express.Application) => { app.get('/disconnect/twitter', async (req, res): Promise => { @@ -30,8 +33,13 @@ module.exports = (app: express.Application) => { if (config.twitter == null) { app.get('/connect/twitter', (req, res) => { - res.send('現在Twitterへ接続できません'); + res.send('現在Twitterへ接続できません (このインスタンスではTwitterはサポートされていません)'); }); + + app.get('/signin/twitter', (req, res) => { + res.send('現在Twitterへ接続できません (このインスタンスではTwitterはサポートされていません)'); + }); + return; } @@ -41,6 +49,12 @@ module.exports = (app: express.Application) => { callbackUrl: `${config.api_url}/tw/cb` }); + const twAuthSignin = autwh({ + consumerKey: config.twitter.consumer_key, + consumerSecret: config.twitter.consumer_secret, + callbackUrl: `${config.api_url}/signin/twitter/cb` + }); + app.get('/connect/twitter', async (req, res): Promise => { if (res.locals.user == null) return res.send('plz signin'); const ctx = await twAuth.begin(); @@ -56,15 +70,15 @@ module.exports = (app: express.Application) => { const user = await User.findOneAndUpdate({ token: res.locals.user }, { - $set: { - twitter: { - access_token: result.accessToken, - access_token_secret: result.accessTokenSecret, - user_id: result.userId, - screen_name: result.screenName - } + $set: { + twitter: { + access_token: result.accessToken, + access_token_secret: result.accessTokenSecret, + user_id: result.userId, + screen_name: result.screenName } - }); + } + }); res.send(`Twitter: @${result.screenName} を、Misskey: @${user.username} に接続しました!`); @@ -75,4 +89,50 @@ module.exports = (app: express.Application) => { })); }); }); + + app.get('/signin/twitter', async (req, res): Promise => { + const ctx = await twAuthSignin.begin(); + + const sessid = uuid(); + + redis.set(sessid, JSON.stringify(ctx)); + + const expires = 1000 * 60 * 60; // 1h + res.cookie('signin_with_twitter_session_id', sessid, { + path: '/', + domain: `.${config.host}`, + secure: config.url.substr(0, 5) === 'https', + httpOnly: true, + expires: new Date(Date.now() + expires), + maxAge: expires + }); + + res.redirect(ctx.url); + }); + + app.get('/signin/twitter/cb', (req, res): any => { + // req.headers['cookie'] は常に string ですが、型定義の都合上 + // string | string[] になっているので string を明示しています + const cookies = cookie.parse((req.headers['cookie'] as string || '')); + + const sessid = cookies['signin_with_twitter_session_id']; + + if (sessid == undefined) { + res.status(400).send('invalid session'); + } + + redis.get(sessid, async (_, ctx) => { + const result = await twAuthSignin.done(JSON.parse(ctx), req.query.oauth_verifier); + + const user = await User.findOne({ + 'twitter.user_id': result.userId + }); + + if (user == null) { + res.status(404).send(`@${result.screenName}と連携しているMisskeyアカウントはありませんでした...`); + } + + signin(res, user, true); + }); + }); }; -- cgit v1.2.3-freya