Skip to content

Commit 185072c

Browse files
authored
Merge pull request cangzhang#6 from cangzhang/feat/oauth
2 parents a8c5897 + 44c0e92 commit 185072c

File tree

8 files changed

+193
-8
lines changed

8 files changed

+193
-8
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# coding-hbuilderx
2+
3+
## Development
4+
5+
1. start dev mode.
6+
7+
```console
8+
yarn watch
9+
```
10+
11+
2. click run plugin option in hbuilder.

package.json

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"name": "coding-hbuilderx",
3-
"description": "your extension description",
4-
"displayName": "your extension display name",
5-
"version": "0.0.0",
6-
"publisher": "your name",
3+
"description": "",
4+
"displayName": "CODING 代码仓库插件",
5+
"version": "1.0.0",
6+
"publisher": "coding",
77
"engines": {
88
"HBuilderX": "^2.7.0"
99
},
@@ -91,6 +91,25 @@
9191
"title": "CODING 合并请求详情"
9292
}
9393
]
94+
},
95+
"configuration": {
96+
"type": "object",
97+
"title": "CODING 代码仓库插件配置",
98+
"properties": {
99+
"codingPlugin.email": {
100+
"type": "string",
101+
"description": "CODING 用户邮箱"
102+
},
103+
"codingPlugin.token": {
104+
"type": "string",
105+
"description": "CODING 服务令牌,请勿擅自更改"
106+
},
107+
"codingPlugin.hbToken": {
108+
"type": "string",
109+
"description": "请勿修改"
110+
}
111+
112+
}
94113
}
95114
},
96115
"extensionDependencies": [

src/extension.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import CodingServer from './services/codingServer';
44
import ACTIONS, { dispatch } from './utils/actions';
55
import { proxyCtx } from './utils/proxy';
66
import toast from './utils/toast';
7+
import { readConfig } from './services/dcloud';
78

89
const accessToken = '7e4d9d17f87875e731d536d13635a700ddf52b12';
910
const user = {
@@ -21,6 +22,10 @@ async function activate(context: IContext) {
2122
const webviewProvider = new WebviewProvider();
2223
const repoInfo = await CodingServer.getRepoParams();
2324
console.log('repoInfo ==> ', repoInfo);
25+
const token = await readConfig(`token`);
26+
if (!token) {
27+
toast.warn(`请先登录 CODING`);
28+
}
2429

2530
const codingServer = new CodingServer(
2631
{
@@ -39,6 +44,8 @@ async function activate(context: IContext) {
3944
codingServer,
4045
depots: [],
4146
selectedDepot: null,
47+
token,
48+
repoInfo,
4249
},
4350
});
4451

src/init.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import MRTreeDataProvider from './trees/mr';
55
import toast from './utils/toast';
66
import ACTIONS, { dispatch } from './utils/actions';
77
import { IDepot, IMRItem } from './typings/common';
8+
import * as DCloudService from './services/dcloud';
89

910
const { registerCommand } = hx.commands;
1011

@@ -90,8 +91,29 @@ export function clear(context: IContext) {
9091
context.subscriptions.forEach(({ dispose }) => dispose());
9192
}
9293

94+
async function initCredentials(context: IContext) {
95+
try {
96+
let hbToken = await DCloudService.readConfig(`hbToken`);
97+
if (!hbToken) {
98+
const code = await DCloudService.grantForUserInfo();
99+
const tokenResult = await DCloudService.applyForToken(code);
100+
hbToken = tokenResult.data.access_token;
101+
}
102+
const resp = await DCloudService.fetchUser(hbToken);
103+
toast.info(`logged in as DCloud user: ${resp.data.nickname} ${resp.data.email}`);
104+
const {
105+
ctx: { codingServer, repoInfo, token },
106+
} = context;
107+
const userData = await codingServer.getUserInfo(repoInfo.team, token);
108+
toast.info(`logged in as coding user: ${userData.name} @ ${userData.team}`);
109+
} catch (err) {
110+
console.error(err);
111+
}
112+
}
113+
93114
export default function init(context: IContext) {
94115
registerCommands(context);
95116
createTreeViews(context);
96117
workspaceInit();
118+
initCredentials(context);
97119
}

src/services/codingServer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,13 @@ export default class CodingServer {
4949
const result = await axios({
5050
method: 'get',
5151
url: `https://${team}.coding.net/api/current_user`,
52-
headers: this.getHeaders(),
52+
headers: this.getHeaders(token),
5353
});
5454

55+
if (result.code) {
56+
return Promise.reject(result);
57+
}
58+
5559
return result?.data;
5660
} catch (err) {
5761
console.error(err);

src/services/dcloud.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import hx from 'hbuilderx';
2+
3+
import axios from '../utils/axios';
4+
import { ITokenResponse, IDCloudUser, ITokenType, IOAuthResponse } from '../typings/common';
5+
6+
const appSecret = `dnGxdvWuEwOO3VimZwo1IsqfESam7k`;
7+
export const appId = `crvUAM0Snz`;
8+
9+
export const applyForToken = async (code: string | null) => {
10+
try {
11+
if (!code) {
12+
throw new Error(`no code provided.`);
13+
}
14+
15+
const resp: ITokenResponse = await axios.get(`https://ide.dcloud.net.cn/dcloudOauthv2/accessToken`, {
16+
params: {
17+
code,
18+
appid: appId,
19+
app_secret: appSecret,
20+
},
21+
});
22+
23+
if (resp.ret) {
24+
return Promise.reject(resp);
25+
}
26+
27+
await setConfig(`hbToken`, resp.data.access_token);
28+
return resp;
29+
} catch (e) {
30+
return Promise.reject(e);
31+
}
32+
};
33+
34+
export const fetchUser = async (accessToken: string) => {
35+
try {
36+
const resp: IDCloudUser = await axios.get(`https://ide.dcloud.net.cn/dcloudOauthv2/userInfo`, {
37+
params: {
38+
access_token: accessToken,
39+
},
40+
});
41+
42+
if (resp.ret) {
43+
return Promise.reject(resp);
44+
}
45+
46+
if (!resp.data.email) {
47+
return Promise.reject(resp);
48+
}
49+
50+
await setConfig(`email`, resp.data.email);
51+
return resp;
52+
} catch (e) {
53+
return Promise.reject(e);
54+
}
55+
};
56+
57+
export const setConfig = async (prop: string, value: string) => {
58+
const codingPlugin = hx.workspace.getConfiguration(`codingPlugin`);
59+
try {
60+
await codingPlugin.update(prop, value);
61+
return true;
62+
} catch {
63+
return false;
64+
}
65+
};
66+
67+
export const readConfig = async (prop: string) => {
68+
const codingPlugin = hx.workspace.getConfiguration(`codingPlugin`);
69+
const token = codingPlugin.get(prop, ``);
70+
return token;
71+
};
72+
73+
export const grantForUserInfo = (): Promise<string | null> =>
74+
new Promise((resolve, reject) => {
75+
hx.authorize
76+
.login({
77+
scopes: ['basic', 'email', 'phone'],
78+
appId: appId,
79+
})
80+
.then((param: IOAuthResponse) => {
81+
const { code, error } = param;
82+
if (error || !code) {
83+
return reject(null);
84+
}
85+
86+
console.log(`hbuilder oauth code: `, code);
87+
return resolve(code);
88+
});
89+
});

src/typings/common.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,36 @@ export interface IDepot {
5656
svnEnabled: boolean;
5757
vcsType: 'git' | 'svn';
5858
}
59+
60+
export interface IOAuthResponse {
61+
code: string;
62+
error: number;
63+
}
64+
65+
export interface ITokenResponse {
66+
ret: number;
67+
desc: string;
68+
data: {
69+
access_token: string;
70+
access_token_ttl: string;
71+
refresh_token: string;
72+
refresh_token_ttl: string;
73+
};
74+
}
75+
76+
export interface IDCloudUser {
77+
ret: number;
78+
desc: string;
79+
data: {
80+
nickname: string;
81+
avatar: string;
82+
uid: string;
83+
email: string;
84+
phone: string;
85+
};
86+
}
87+
88+
export enum ITokenType {
89+
AccessToken = `accessToken`,
90+
RefreshToken = `refreshToken`,
91+
}

src/utils/toast.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import hx from 'hbuilderx';
22

3-
export const info = (msg: string, buttons?: string[]): Promise<string> => {
3+
export const info = (msg: string, buttons?: string[]) => {
44
return hx.window.showInformationMessage(msg, buttons);
55
};
66

7-
export const warn = (msg: string, buttons?: string[]): Promise<string> => {
7+
export const warn = (msg: string, buttons?: string[]) => {
88
return hx.window.showWarningMessage(msg, buttons);
99
};
1010

11-
export const error = (msg: string, buttons?: string[]): Promise<string> => {
11+
export const error = (msg: string, buttons?: string[]) => {
1212
return hx.window.showErrorMessage(msg, buttons);
1313
};
1414

0 commit comments

Comments
 (0)