feat: add fim plugin and add github oauth strategy

pull/100/head
moonrailgun 2 years ago
parent 8fc96b7918
commit b64d037b60

@ -70,6 +70,7 @@
"react-router-dom@^6.0.0": "6.11.0",
"@typegoose/typegoose": "9.3.1",
"typescript": "4.9.4",
"got": "11.8.3",
"mongodb": "4.2.1",
"mongoose@~6.0.14": "6.1.1",
"mongoose@^6.0.0": "6.1.1",

@ -1877,6 +1877,34 @@ importers:
specifier: ^4.3.6
version: 4.3.6(immer@9.0.21)(react@18.2.0)
server/plugins/com.msgbyte.fim:
dependencies:
got:
specifier: ^11.8.3
version: 11.8.3
tailchat-server-sdk:
specifier: '*'
version: link:../../packages/sdk
devDependencies:
'@types/react':
specifier: 18.0.20
version: 18.0.20
mini-star:
specifier: '*'
version: 1.3.1
server/plugins/com.msgbyte.fim/web/plugins/com.msgbyte.fim:
devDependencies:
'@types/styled-components':
specifier: ^5.1.26
version: 5.1.26
react:
specifier: 18.2.0
version: 18.2.0
styled-components:
specifier: ^5.3.6
version: 5.3.6(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)
server/plugins/com.msgbyte.getui:
dependencies:
got:

@ -0,0 +1,14 @@
const path = require('path');
module.exports = {
externalDeps: [
'react',
'react-router',
'axios',
'styled-components',
'zustand',
'zustand/middleware/immer',
],
pluginRoot: path.resolve(__dirname, './web'),
outDir: path.resolve(__dirname, '../../public'),
};

@ -0,0 +1,20 @@
import { db } from 'tailchat-server-sdk';
const { getModelForClass, prop, modelOptions, TimeStamps } = db;
@modelOptions({
options: {
customName: 'p_fim',
},
})
export class Fim extends TimeStamps implements db.Base {
_id: db.Types.ObjectId;
id: string;
}
export type FimDocument = db.DocumentType<Fim>;
const model = getModelForClass(Fim);
export type FimModel = typeof model;
export default model;

@ -0,0 +1,21 @@
{
"name": "tailchat-plugin-fim",
"version": "1.0.0",
"main": "index.js",
"author": "moonrailgun",
"description": "Unified identity authentication",
"license": "MIT",
"private": true,
"scripts": {
"build:web": "ministar buildPlugin all",
"build:web:watch": "ministar watchPlugin all"
},
"devDependencies": {
"@types/react": "18.0.20",
"mini-star": "*"
},
"dependencies": {
"got": "^11.8.3",
"tailchat-server-sdk": "*"
}
}

@ -0,0 +1,50 @@
import { TcService, TcDbService, TcPureContext } from 'tailchat-server-sdk';
import type { FimDocument, FimModel } from '../models/fim';
import { strategies } from '../strategies';
import type { StrategyType } from '../strategies/types';
/**
* Federated Identity Management
*
* Unified identity authentication
*/
interface FimService extends TcService, TcDbService<FimDocument, FimModel> {}
class FimService extends TcService {
get serviceName() {
return 'plugin:com.msgbyte.fim';
}
onInit() {
// this.registerLocalDb(require('../models/fim').default);
strategies
.filter((strategy) => strategy.checkAvailable())
.map((strategy) => {
const action = this.buildStrategyAction(strategy);
const name = strategy.name;
this.registerAction(`${name}.url`, action.url);
this.registerAction(`${name}.redirect`, action.redirect);
this.registerAuthWhitelist([`/${name}/url`, `/${name}/redirect`]);
});
}
buildStrategyAction(strategy: StrategyType) {
return {
url: async (ctx: TcPureContext) => {
return strategy.getUrl();
},
redirect: async (ctx: TcPureContext<{ code: string }>) => {
const code = ctx.params.code;
if (!code) {
throw new Error(JSON.stringify(ctx.params));
}
return strategy.getUserInfo(code);
},
};
}
}
export default FimService;

@ -0,0 +1,54 @@
import { config } from 'tailchat-server-sdk';
import type { StrategyType } from './types';
import got from 'got';
const clientInfo = {
id: process.env.FIM_GITHUB_ID,
secret: process.env.FIM_GITHUB_SECRET,
};
const authorize_uri = 'https://github.com/login/oauth/authorize';
const access_token_uri = 'https://github.com/login/oauth/access_token';
const userinfo_uri = 'https://api.github.com/user';
const redirect_uri = `${config.apiUrl}/api/plugin:com.msgbyte.fim/github/redirect`;
export const GithubStrategy: StrategyType = {
name: 'github',
checkAvailable: () => !!clientInfo.id && !!clientInfo.secret,
getUrl: () => {
return `${authorize_uri}?client_id=${clientInfo.id}&redirect_uri=${redirect_uri}`;
},
getUserInfo: async (code) => {
console.log('authorization code:', code);
const tokenResponse = await got(access_token_uri, {
method: 'POST',
searchParams: {
client_id: clientInfo.id,
client_secret: clientInfo.secret,
code: code,
},
headers: {
accept: 'application/json',
},
}).json<{ access_token: string }>();
const accessToken = tokenResponse.access_token;
console.log(`access token: ${accessToken}`);
const result = await got(userinfo_uri, {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: `token ${accessToken}`,
},
}).json<{ id: number; name: string; email: string; avatar_url: string }>();
return {
id: String(result.id),
nickname: result.name,
email: result.email,
avatar: result.avatar_url,
};
},
};

@ -0,0 +1,3 @@
import { GithubStrategy } from './github';
export const strategies = [GithubStrategy];

@ -0,0 +1,11 @@
export interface StrategyType {
name: string;
checkAvailable: () => boolean;
getUrl: () => string;
getUserInfo: (code: string) => Promise<{
id: string;
nickname: string;
email: string;
avatar: string;
}>;
}

@ -0,0 +1,9 @@
{
"label": "Federated Identity Management",
"name": "com.msgbyte.fim",
"url": "{BACKEND}/plugins/com.msgbyte.fim/index.js",
"version": "0.0.0",
"author": "moonrailgun",
"description": "Unified identity authentication",
"requireRestart": true
}

@ -0,0 +1,16 @@
{
"name": "@plugins/com.msgbyte.fim",
"main": "src/index.tsx",
"version": "0.0.0",
"description": "Unified identity authentication",
"private": true,
"scripts": {
"sync:declaration": "tailchat declaration github"
},
"dependencies": {},
"devDependencies": {
"@types/styled-components": "^5.1.26",
"react": "18.2.0",
"styled-components": "^5.3.6"
}
}

@ -0,0 +1 @@
console.log('Plugin Federated Identity Management is loaded');

@ -0,0 +1,7 @@
{
"compilerOptions": {
"esModuleInterop": true,
"jsx": "react",
"importsNotUsedAsValues": "error"
}
}

@ -0,0 +1,2 @@
declare module '@capital/common';
declare module '@capital/component';

@ -79,7 +79,7 @@ export default class ApiService extends TcService {
// window: 60 * 1000,
// // Max number of requests during window. Defaults to 30
// limit: 30,
// limit: 60,
// // Set rate limit headers to response. Defaults to false
// headers: true,

Loading…
Cancel
Save