Skip to content

Commit

Permalink
feat: support github oauth and opensumi run (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaaaash authored Mar 18, 2024
1 parent 9dba4db commit b98bf3a
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/api/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as Configuration from './configuration';
import * as Ding from './ding';
import * as GitHub from './github';
import * as Auth from './oauth';
import * as Proxy from './proxy';
import * as OpenSumiRun from './run';
import * as Static from './static';
import * as Webhook from './webhook';

Expand All @@ -12,4 +14,6 @@ export const registerBlueprint = (hono: THono) => {
Webhook.route(hono);
Static.route(hono);
Configuration.route(hono);
Auth.route(hono);
OpenSumiRun.route(hono);
};
60 changes: 60 additions & 0 deletions src/api/controllers/oauth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { GitHubKVManager } from '@/kv/github';

export function route(hono: THono) {
hono.get('/auth/callback/:id', async (c) => {
const code = c.req.query('code');
const state = c.req.query('state');
const config = await GitHubKVManager.instance().getOauthAppConfig(
c.req.param('id'),
);

if (!config) {
return c.html('error', 500);
}

const res = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: config.clientId,
client_secret: config.clientSecret,
code,
}),
})
.then((res) => res.json<{ access_token: string }>())
.catch((err) => {
console.log('request github error: ', err);
});

if (res && state) {
const [, originalUrl] = state.split('|');
// 获取 state 参数,重定向到原始页面
// 携带 access_token 参数,前端自行缓存后请求
return c.redirect(`${originalUrl}?access_token=${res.access_token}`);
}

return c.html('error', 500);
});

hono.get('/auth/github/:id', async (c) => {
const config = await GitHubKVManager.instance().getOauthAppConfig(
c.req.param('id'),
);

if (!config) {
return c.html('error', 500);
}

// 重定向到 github 登录页面
// 透传 state 参数,用于登录后重定向到原始页面
// state: originalState|originalUrl
return c.redirect(
`https://github.com/login/oauth/authorize?client_id=${
config.clientId
}&scope=read:user%20repo&state=${c.req.query('state')}`,
);
});
}
45 changes: 45 additions & 0 deletions src/api/controllers/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { html } from 'hono/html';

import Environment from '@/env';
import { OpenSumiRunKVManager } from '@/kv/run';

export function route(hono: THono) {
hono.get('/ide/:group/:project', async (c) => {
const env = Environment.instance().environment;
const version = await OpenSumiRunKVManager.instance().getCdnVersion();
const originTrial = await OpenSumiRunKVManager.instance().getTrialToken(
env,
);

const cdnBase =
env === 'prod'
? 'https://g.alicdn.com/opensumi/run'
: 'https://dev.g.alicdn.com/opensumi/run';

return c.html(
html`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>OpenSumi</title>
<link
rel="icon"
href="https://opensumi.com/favicon-32x32.png?v=844070368776e5e9503bdeccf498ee66"
/>
<script src="https://g.alicdn.com/code/lib/??react/16.14.0/umd/react.production.min.js,react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<link rel="stylesheet" href="${cdnBase}/${version}/main.css " />
</head>
<body>
<script>
const otMeta = document.createElement('meta');
otMeta.httpEquiv = 'origin-trial';
otMeta.content = '${originTrial}';
document.head.append(otMeta);
</script>
<div id="main"></div>
<script src="${cdnBase}/${version}/bundle.js"></script>
</body>
</html>`,
);
});
}
8 changes: 8 additions & 0 deletions src/kv/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export namespace DingCommon {
export namespace GitHubCommon {
export const GITHUB_SETTINGS_PREFIX = 'github/settings/';
export const GITHUB_APP_SETTINGS_PREFIX = 'github/app/settings/';
export const GITHUB_OAUTH_SETTINGS_PREFIX = 'github/oauth/settings/';
}

export namespace OpenSumiRunCommon {
export const OPENSUMI_RUN_CDN_VERSION_PREFIX = 'opensumi/run/cdn-version';

export const OPENSUMI_RUN_ORIGINAL_TRIAL_TOKEN_PREFIX =
'opensumi/run/original-trial-token';
}

export namespace Common {
Expand Down
10 changes: 9 additions & 1 deletion src/kv/github.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { GitHubCommon, KVManager } from '@/kv';

import { AppSetting, ISetting } from './types';
import { AppSetting, IGitHubOauthAppConfig, ISetting } from './types';

export class GitHubKVManager {
appSettingsKV: KVManager<AppSetting>;
settingsKV: KVManager<ISetting>;
oauthKV: KVManager<IGitHubOauthAppConfig>;

private constructor() {
this.appSettingsKV = KVManager.for<AppSetting>(
Expand All @@ -13,6 +14,9 @@ export class GitHubKVManager {
this.settingsKV = KVManager.for<ISetting>(
GitHubCommon.GITHUB_SETTINGS_PREFIX,
);
this.oauthKV = KVManager.for<IGitHubOauthAppConfig>(
GitHubCommon.GITHUB_OAUTH_SETTINGS_PREFIX,
);
}

private static _instance: GitHubKVManager;
Expand Down Expand Up @@ -45,4 +49,8 @@ export class GitHubKVManager {

return webhooks;
};

getOauthAppConfig = async (id: string) => {
return await this.oauthKV.getJSON(id);
};
}
37 changes: 37 additions & 0 deletions src/kv/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { KVManager, OpenSumiRunCommon } from '@/kv';

import { IOpenSumiRunConfig, IOpenSumiRunOriginalTrialToken } from './types';

export class OpenSumiRunKVManager {
cdnVersion: KVManager<IOpenSumiRunConfig>;

originalTrialToken: KVManager<IOpenSumiRunOriginalTrialToken>;

constructor() {
this.cdnVersion = KVManager.for<IOpenSumiRunConfig>(
OpenSumiRunCommon.OPENSUMI_RUN_CDN_VERSION_PREFIX,
);

this.originalTrialToken = KVManager.for<IOpenSumiRunOriginalTrialToken>(
OpenSumiRunCommon.OPENSUMI_RUN_ORIGINAL_TRIAL_TOKEN_PREFIX,
);
}

private static _instance: OpenSumiRunKVManager;
static instance() {
if (!this._instance) {
this._instance = new OpenSumiRunKVManager();
}
return this._instance;
}

getCdnVersion = async () => {
const cdnVersionData = await this.cdnVersion.getJSON('');
return cdnVersionData?.version || '0.0.1';
};

getTrialToken = async (env: 'local' | 'prod' | 'unittest') => {
const trialTokenData = await this.originalTrialToken.getJSON('');
return trialTokenData ? trialTokenData[env] : undefined;
};
}
15 changes: 15 additions & 0 deletions src/kv/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,18 @@ export interface IAdminInfo {
*/
tokenByScope?: Record<string, string>;
}

export interface IOpenSumiRunConfig {
version: string;
}

export interface IOpenSumiRunOriginalTrialToken {
local: string;
prod: string;
unittest: string;
}

export interface IGitHubOauthAppConfig {
clientId: string;
clientSecret: string;
}

0 comments on commit b98bf3a

Please sign in to comment.