add some code for twitter login

This commit is contained in:
zhl 2023-06-13 10:09:53 +08:00
parent a2313ff701
commit dda8e192a1
8 changed files with 163 additions and 109 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
dist/*.js

14
.eslintrc.js Normal file
View File

@ -0,0 +1,14 @@
/** @format */
module.exports = {
parser: '@typescript-eslint/parser', //定义ESLint的解析器
extends: [
'plugin:prettier/recommended', // 使用prettier中的样式规范且如果使得ESLint会检测prettier的格式问题同样将格式问题以error的形式抛出
],
parserOptions: {ecmaVersion: 2019, sourceType: 'module'},
env: {
//指定代码的运行环境
browser: true,
node: true,
},
}

8
.gitignore copy Normal file
View File

@ -0,0 +1,8 @@
.idea
node_modules
build
dist
.DS_Store
tmp
target
boundle.log

13
.prettierrc.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
"printWidth": 120,
"semi": false, // 在语句末尾添加分号
"singleQuote": true, // 使用单引号而非双引号
"trailingComma": "all", // 在任何可能的多行中输入尾逗号
"bracketSpacing": true, // 在对象字面量声明所使用的的花括号前后({})输出空格
"jsxBracketSameLine": true, // 在多行JSX元素最后一行的末尾添加 > 而使 > 单独一行(不适用于自闭和元素)
"arrowParens": "avoid", // 为单行箭头函数的参数添加圆括号。
"requirePragma": false, // Prettier可以严格按照按照文件顶部的一些特殊的注释格式化代码
"insertPragma": false, // 顶部插入一个 @format
"tabWidth": 2,
"useTabs": false,
};

1
pm2_dev.sh Executable file
View File

@ -0,0 +1 @@
pm2 start npm --name "oauth-svr" --log-date-format "YYYY-MM-DD HH:mm:ss" -- run "dev:api"

View File

@ -1,45 +1,40 @@
import fastify, { import fastify, { FastifyError, FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
FastifyError, import helmet from '@fastify/helmet'
FastifyInstance, import { IncomingMessage, Server, ServerResponse } from 'http'
FastifyReply, import { RouterMap } from 'decorators/router'
FastifyRequest, import { mongoose } from '@typegoose/typegoose'
} from "fastify"; import logger from 'logger/logger'
import helmet from "@fastify/helmet"; import config from 'config/config'
import { IncomingMessage, Server, ServerResponse } from "http"; import { ConnectOptions } from 'mongoose'
import { RouterMap } from "decorators/router"; import { DiscordSvr } from 'services/discord.svr'
import { mongoose } from "@typegoose/typegoose";
import logger from "logger/logger";
import config from "config/config";
import { ConnectOptions } from "mongoose";
import { DiscordSvr } from "services/discord.svr";
const zReqParserPlugin = require("plugins/zReqParser"); const zReqParserPlugin = require('plugins/zReqParser')
const zTokenParserPlugin = require("plugins/zTokenParser"); const zTokenParserPlugin = require('plugins/zTokenParser')
const apiAuthPlugin = require("plugins/apiauth"); const apiAuthPlugin = require('plugins/apiauth')
const fs = require("fs"); const fs = require('fs')
const join = require("path").join; const join = require('path').join
require("./common/Extend"); require('./common/Extend')
export class ApiServer { export class ApiServer {
server: FastifyInstance<Server, IncomingMessage, ServerResponse>; server: FastifyInstance<Server, IncomingMessage, ServerResponse>
public constructor() { public constructor() {
this.server = fastify({ logger: true, trustProxy: true }); this.server = fastify({ logger: true, trustProxy: true })
this.registerPlugins(); this.registerPlugins()
console.log("version::" + process.version); console.log('version::' + process.version)
} }
private registerPlugins() { private registerPlugins() {
this.server.register(require("@fastify/formbody")); this.server.register(require('@fastify/formbody'))
this.server.register(zReqParserPlugin); this.server.register(zReqParserPlugin)
this.server.register(helmet, { this.server.register(helmet, {
hidePoweredBy: false, hidePoweredBy: false,
contentSecurityPolicy: false, contentSecurityPolicy: false,
}); })
this.server.register(zTokenParserPlugin); this.server.register(zTokenParserPlugin)
this.server.register(apiAuthPlugin, { this.server.register(apiAuthPlugin, {
secret: { secret: {
@ -47,43 +42,40 @@ export class ApiServer {
public: config.api.token_secret_public, public: config.api.token_secret_public,
}, },
expiresIn: config.api.token_expiresIn, expiresIn: config.api.token_expiresIn,
}); })
if (process.env.NODE_ENV !== "production") { if (process.env.NODE_ENV !== 'production') {
this.server.register(require("@fastify/cors"), {}); this.server.register(require('@fastify/cors'), {})
} }
this.server.register(require("@fastify/view"), { this.server.register(require('@fastify/view'), {
engine: { engine: {
ejs: require("ejs"), ejs: require('ejs'),
}, },
}); })
} }
private registerRouter() { private registerRouter() {
logger.log("register api routers"); logger.log('register api routers')
let self = this; let self = this
for (let [controller, config] of RouterMap.decoratedRouters) { for (let [controller, config] of RouterMap.decoratedRouters) {
for (let data of config.data) { for (let data of config.data) {
logger.info( logger.info(
"add router", 'add router',
data.method || "all", data.method || 'all',
data.path, data.path,
`${data.target.constructor.name}.${controller.name}()` `${data.target.constructor.name}.${controller.name}()`,
); )
// @ts-ignore // @ts-ignore
self.server[data.method || "all"]( self.server[data.method || 'all'](
data.path, data.path,
{ {
preValidation: async function ( preValidation: async function (request: FastifyRequest, reply: FastifyReply) {
request: FastifyRequest, request.roles = config.roles
reply: FastifyReply await this.apiAuth(request, reply)
) {
request.roles = config.roles;
await this.apiAuth(request, reply);
}, },
}, },
controller controller,
); )
} }
} }
} }
@ -91,20 +83,20 @@ export class ApiServer {
* controller * controller
*/ */
initControllers() { initControllers() {
logger.info("Bootstrap controllers..."); logger.info('Bootstrap controllers...')
const controllers = join(__dirname, "./controllers"); const controllers = join(__dirname, './controllers')
fs.readdirSync(controllers) fs.readdirSync(controllers)
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/)) .filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
.forEach((file: any) => { .forEach((file: any) => {
// logger.log(file); // logger.log(file);
return require(join(controllers, file)); return require(join(controllers, file))
}); })
} }
initSchedules() {} initSchedules() {}
initServcers() { initServcers() {
new DiscordSvr().init(); new DiscordSvr().init()
} }
async connectDB() { async connectDB() {
@ -113,42 +105,38 @@ export class ApiServer {
maxPoolSize: 10, maxPoolSize: 10,
keepAlive: true, keepAlive: true,
keepAliveInitialDelay: 300000, keepAliveInitialDelay: 300000,
}; }
const uri = config.db_main; const uri = config.db_main
logger.info(`connect to ${uri} ...`); logger.info(`connect to ${uri} ...`)
try { try {
// await mongoose.createConnection(uri, options) // await mongoose.createConnection(uri, options)
await mongoose.connect(uri, options); await mongoose.connect(uri, options)
logger.log("DB Connected"); logger.log('DB Connected')
} catch (err) { } catch (err) {
logger.log(`DB Connection Error: ${err.message}`); logger.log(`DB Connection Error: ${err.message}`)
} }
} }
private setErrHandler() { private setErrHandler() {
this.server.setNotFoundHandler(function ( this.server.setNotFoundHandler(function (
request: any, request: any,
reply: { send: (arg0: { errcode: number; errmsg: string }) => void } reply: { send: (arg0: { errcode: number; errmsg: string }) => void },
) { ) {
reply.send({ errcode: 404, errmsg: "page not found" }); reply.send({ errcode: 404, errmsg: 'page not found' })
}); })
this.server.setErrorHandler(function ( this.server.setErrorHandler(function (error: FastifyError, request: FastifyRequest, reply: FastifyReply) {
error: FastifyError, let statusCode = (error && error.statusCode) || 100
request: FastifyRequest,
reply: FastifyReply
) {
let statusCode = (error && error.statusCode) || 100;
if (statusCode >= 500) { if (statusCode >= 500) {
logger.error(error); logger.error(error)
} else if (statusCode >= 400) { } else if (statusCode >= 400) {
logger.info(error); logger.info(error)
} else { } else {
logger.error(error); logger.error(error)
} }
reply.code(200).send({ reply.code(200).send({
errcode: statusCode, errcode: statusCode,
errmsg: error ? error.message : "unknown error", errmsg: error ? error.message : 'unknown error',
}); })
}); })
} }
/** /**
* , * ,
@ -160,47 +148,41 @@ export class ApiServer {
* @private * @private
*/ */
private setFormatSend() { private setFormatSend() {
this.server.addHook( this.server.addHook('preSerialization', async (request: FastifyRequest, reply: FastifyReply, payload) => {
"preSerialization", reply.header('X-Powered-By', 'PHP/5.4.16')
async (request: FastifyRequest, reply: FastifyReply, payload) => { // @ts-ignore
reply.header("X-Powered-By", "PHP/5.4.16"); if (!payload.errcode) {
// @ts-ignore // @ts-ignore
if (!payload.errcode) { if (payload.direct) {
// @ts-ignore // @ts-ignore
if (payload.direct) { delete payload.direct
// @ts-ignore return payload
delete payload.direct; }
return payload; payload = {
} errcode: 0,
payload = { data: payload,
errcode: 0,
data: payload,
};
} }
return payload;
} }
); return payload
})
} }
public async start() { public async start() {
let self = this; let self = this
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
await self.connectDB(); await self.connectDB()
self.initControllers(); self.initControllers()
self.registerRouter(); self.registerRouter()
self.setErrHandler(); self.setErrHandler()
self.setFormatSend(); self.setFormatSend()
self.initSchedules(); self.initSchedules()
self.initServcers(); self.initServcers()
this.server.listen( this.server.listen({ port: config.api.port, host: config.api.host }, (err: any, address: any) => {
{ port: config.api.port, host: config.api.host }, if (err) {
(err: any, address: any) => { logger.log(err)
if (err) { process.exit(0)
logger.log(err);
process.exit(0);
}
resolve && resolve(address);
} }
); resolve && resolve(address)
}); })
})
} }
} }

View File

@ -0,0 +1,13 @@
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
class TwitterController extends BaseController {
@role(ROLE_ANON)
@router('get /twitter/redirect_uri')
async discordCallback(req, res) {
logger.info('twitter redirect: ', req.params)
return res.view('/templates/twitter_redirect.ejs')
}
}

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Discord Redirect</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
padding: 20px;
}
.form-label i {
color: green;
}
</style>
</head>
<body>
<script>
(function() {
window.close();
})();
</script>
</body>
</html>