activity-oauth-svr/src/controllers/twitter.controller.ts
2024-04-23 10:32:23 +08:00

110 lines
4.0 KiB
TypeScript

import { ZError } from 'common/ZError'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
import { AuthRecord } from 'modules/AuthRecord'
import {
exchangeTwitterCodeForToken,
getOAuthAccessTokenWith,
getOAuthRequestToken,
getTwitterUserInfo,
} from 'services/twitter.svr'
import { parseOauthState } from 'utils/net.util'
class TwitterController extends BaseController {
@role(ROLE_ANON)
@router('get /twitter/redirect_uri')
async twitterRedirect(req, res) {
// logger.info('twitter redirect: ', req.params)
const { code, state } = req.params
if (code && state) {
const stateArr = parseOauthState(state)
const address = stateArr[0].toLowerCase()
const record = await AuthRecord.insertOrUpdate(
{ address, platform: 4 },
{ address, platform: 4, $inc: { version: 1 } },
)
const vcode = stateArr[1] || stateArr[0]
const tokenResponse = await exchangeTwitterCodeForToken(code, vcode)
record.accessToken = tokenResponse.access_token
record.refreshToken = tokenResponse.refresh_token
record.scope = tokenResponse.scope
record.tokenType = tokenResponse.token_type
record.expiresIn = (Date.now() / 1000 + tokenResponse.expires_in || 0) | 0
await record.save()
if (tokenResponse && tokenResponse.access_token) {
const uinfo = await getTwitterUserInfo(tokenResponse.access_token)
if (!uinfo.data) {
logger.info('twitter user info: ', JSON.stringify(uinfo))
}
record.nickname = uinfo.data?.name
record.username = uinfo.data?.username
record.openId = uinfo.data?.id
if (uinfo.data?.profile_image_url) {
record.avatar = uinfo.data?.profile_image_url.replace('_normal', '')
}
await record.save()
}
if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
}
if (state) {
const stateArr = parseOauthState(state)
if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
}
return res.view('/templates/twitter_redirect.ejs')
}
@role(ROLE_ANON)
@router('get /twitter/oauth/:address')
async twitterOauth(req, res) {
let method = 'authenticate'
let { address } = req.params
if (!address) {
throw new ZError(10, 'address needed')
}
address = address.toLowerCase()
// @ts-ignore
const { oauthRequestToken, oauthRequestTokenSecret } = await getOAuthRequestToken()
logger.info(
`twitter request token::oauthRequestToken:${oauthRequestToken},oauthRequestTokenSecret:${oauthRequestTokenSecret}`,
)
req.session.oauthRequestToken = oauthRequestToken
req.session.oauthRequestTokenSecret = oauthRequestTokenSecret
req.session.address = address
const authorizationUrl = `https://api.twitter.com/oauth/${method}?oauth_token=${oauthRequestToken}`
logger.info('redirecting:', authorizationUrl)
res.redirect(authorizationUrl)
}
// for twitter oauth v1.0
@role(ROLE_ANON)
@router('get /twitter/callback')
async twitterOauth1Callback(req, res) {
const { address, oauthRequestToken, oauthRequestTokenSecret } = req.session
logger.info('request.query', req.query)
const { oauth_verifier: oauthVerifier } = req.query
const { oauthAccessToken, oauthAccessTokenSecret, results } = await getOAuthAccessTokenWith({
oauthRequestToken,
oauthRequestTokenSecret,
oauthVerifier,
})
const { user_id: userId /*, screen_name */ } = results
logger.info('userId:', userId)
const record = await AuthRecord.insertOrUpdate(
{ address, platform: 4 },
{ address, platform: 4, $inc: { version: 1 } },
)
record.nickname = results.screen_name
record.username = results.screen_name
record.openId = results.user_id
record.accessToken = oauthAccessToken
record.refreshToken = oauthAccessTokenSecret
record.tokenType = 'oauth1'
await record.save()
return res.view('/templates/twitter_redirect.ejs')
}
}