From 3fa5e96bfe7ab5415e95bc377b65c7f5408d859a Mon Sep 17 00:00:00 2001 From: ma-silva Date: Thu, 20 Apr 2023 14:03:07 +0800 Subject: [PATCH] FEATURE: server side api --- server/app.ts | 32 +++++++++++++++++++ server/controllers/CallbackController.ts | 14 ++++++++ server/controllers/ConnectController.ts | 14 ++++++++ server/controllers/UserController.ts | 12 +++++++ .../middlewares/OauthAccessTokenMiddleware.ts | 30 +++++++++++++++++ .../OauthRequestTokenMiddleware.ts | 25 +++++++++++++++ server/services/OauthInjectedService.ts | 28 ++++++++++++++++ 7 files changed, 155 insertions(+) create mode 100644 server/app.ts create mode 100644 server/controllers/CallbackController.ts create mode 100644 server/controllers/ConnectController.ts create mode 100644 server/controllers/UserController.ts create mode 100644 server/middlewares/OauthAccessTokenMiddleware.ts create mode 100644 server/middlewares/OauthRequestTokenMiddleware.ts create mode 100644 server/services/OauthInjectedService.ts diff --git a/server/app.ts b/server/app.ts new file mode 100644 index 0000000..8cc36be --- /dev/null +++ b/server/app.ts @@ -0,0 +1,32 @@ +import 'reflect-metadata' +import 'dotenv/config' +import session from 'express-session' +import express, { Application } from 'express' +import { useExpressServer, useContainer } from 'routing-controllers' +import { Container } from 'typedi' +import path from 'path' + +const port = 8085 +const app: Application = express() +app.use(express.json()) +app.use( + session({ + secret: 'very secret', + resave: false, + saveUninitialized: true + }) +) +useContainer(Container) + +const server = useExpressServer(app, { + //routePrefix: '/api/v1', + routePrefix: '/api', + controllers: [path.join(__dirname + '/controllers/*.ts')], + middlewares: [path.join(__dirname + '/middlewares/*.ts')] +}) + +export const instance = server.listen(port) + +console.log('Server running at http://localhost:' + port) + +export default app diff --git a/server/controllers/CallbackController.ts b/server/controllers/CallbackController.ts new file mode 100644 index 0000000..56f2731 --- /dev/null +++ b/server/controllers/CallbackController.ts @@ -0,0 +1,14 @@ +import { Controller, Req, Res, Get, UseBefore } from 'routing-controllers' +import { Request, Response } from 'express' +import { Service } from 'typedi' +import OauthAccessTokenMiddleware from '../middlewares/OauthAccessTokenMiddleware' + +@Service() +@Controller() +@UseBefore(OauthAccessTokenMiddleware) +export default class CallbackController { + @Get('/callback') + callback(@Req() request: Request, @Res() response: Response): Response { + return response + } +} diff --git a/server/controllers/ConnectController.ts b/server/controllers/ConnectController.ts new file mode 100644 index 0000000..46b054f --- /dev/null +++ b/server/controllers/ConnectController.ts @@ -0,0 +1,14 @@ +import { Controller, Req, Res, Get, UseBefore } from 'routing-controllers' +import { Request, Response } from 'express' +import OauthRequestTokenMiddleware from '../middlewares/OauthRequestTokenMiddleware' +import { Service } from 'typedi' + +@Service() +@Controller() +@UseBefore(OauthRequestTokenMiddleware) +export class ConnectController { + @Get('/connect') + connect(@Req() request: Request, @Res() response: Response): Response { + return response + } +} diff --git a/server/controllers/UserController.ts b/server/controllers/UserController.ts new file mode 100644 index 0000000..d4c7551 --- /dev/null +++ b/server/controllers/UserController.ts @@ -0,0 +1,12 @@ +import { Controller, Req, Res, Get } from 'routing-controllers' +import { Request, Response } from 'express' +import { Service } from 'typedi' + +@Controller() +@Service() +export default class UserController { + @Get('/user') + getUser(@Req() request: Request, @Res() response: Response): Response { + return response.json('User list.') + } +} diff --git a/server/middlewares/OauthAccessTokenMiddleware.ts b/server/middlewares/OauthAccessTokenMiddleware.ts new file mode 100644 index 0000000..6a0602d --- /dev/null +++ b/server/middlewares/OauthAccessTokenMiddleware.ts @@ -0,0 +1,30 @@ +import { ExpressMiddlewareInterface } from 'routing-controllers' +import { Response, Request } from 'express' +import { Service } from 'typedi' +import OauthInjectedService from '../services/OauthInjectedService' + +@Service() +export default class OauthAccessTokenMiddleware implements ExpressMiddlewareInterface { + constructor(private oauthInjectedService: OauthInjectedService) {} + + use(request: Request, response: Response): any { + const oauthService = this.oauthInjectedService + const consumer = oauthService.getConsumer() + const oauthVerifier = request.query.oauth_verifier + consumer.getOAuthAccessToken( + oauthService.requestTokenKey, + oauthService.requestTokenSecret, + oauthVerifier, + (error: any, oauthTokenKey: string, oauthTokenSecret: string) => { + if (error) { + console.log(error) + response.status(500).send('Error getting OAuth access token: ' + error) + } else { + response.redirect( + process.env.VITE_HOST + '?accessKey=' + oauthTokenKey + '&secret=' + oauthTokenSecret + ) + } + } + ) + } +} diff --git a/server/middlewares/OauthRequestTokenMiddleware.ts b/server/middlewares/OauthRequestTokenMiddleware.ts new file mode 100644 index 0000000..4dc5277 --- /dev/null +++ b/server/middlewares/OauthRequestTokenMiddleware.ts @@ -0,0 +1,25 @@ +import { ExpressMiddlewareInterface } from 'routing-controllers' +import { Response, Request } from 'express' +import { Service } from 'typedi' +import OauthInjectedService from '../services/OauthInjectedService' + +@Service() +export default class OauthRequestTokenMiddleware implements ExpressMiddlewareInterface { + constructor(private oauthInjectedService: OauthInjectedService) {} + + use(request: Request, response: Response): any { + const apiHost = process.env.VITE_API_HOST + const oauthService = this.oauthInjectedService + const consumer = oauthService.getConsumer() + consumer.getOAuthRequestToken((error: any, oauthTokenKey: string, oauthTokenSecret: string) => { + if (error) { + console.error(error) + response.status(500).send('Error getting OAuth request token: ' + error) + } else { + oauthService.requestTokenKey = oauthTokenKey + oauthService.requestTokenSecret = oauthTokenSecret + response.redirect(apiHost + '/oauth/authorize?oauth_token=' + oauthTokenKey) + } + }) + } +} diff --git a/server/services/OauthInjectedService.ts b/server/services/OauthInjectedService.ts new file mode 100644 index 0000000..f691c7b --- /dev/null +++ b/server/services/OauthInjectedService.ts @@ -0,0 +1,28 @@ +import { Service } from 'typedi' +import oauth from 'oauth' + +@Service() +export default class OauthInjectedService { + public requestTokenKey: string + public requestTokenSecret: string + private oauth: oauth.OAuth + constructor() { + const apiHost = process.env.VITE_API_HOST + const consumerKey = process.env.VITE_CONSUMER_KEY + const consumerSecret = process.env.VITE_CONSUMER_SECRET + const redirectUrl = process.env.VITE_REDIRECT_URL + this.oauth = new oauth.OAuth( + apiHost + '/oauth/initiate', + apiHost + '/oauth/token', + consumerKey, + consumerSecret, + '1.0', + redirectUrl, + 'HMAC-SHA1' + ) + } + + getConsumer(): oauth.OAuth { + return this.oauth + } +}