Skip to content

Commit 772a592

Browse files
committed
feat: refresh tree.
1 parent a21df89 commit 772a592

File tree

7 files changed

+153
-157
lines changed

7 files changed

+153
-157
lines changed

package.json

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"onCommand:codingPlugin.show",
1515
"onCommand:codingPlugin.login",
1616
"onWebviewPanel:codingPlugin",
17-
"onView:treeviewSample"
17+
"onView:treeViewSample"
1818
],
1919
"repository": {
2020
"type": "git",
@@ -37,11 +37,28 @@
3737
"command": "codingPlugin.logout",
3838
"title": "Logout coding.net",
3939
"category": "Coding plugin"
40+
},
41+
{
42+
"command": "codingPlugin.refresh",
43+
"title": "Refresh",
44+
"icon": {
45+
"light": "src/assets/refresh.light.svg",
46+
"dark": "src/assets//refresh.dark.svg"
47+
}
4048
}
4149
],
50+
"menus": {
51+
"view/title": [
52+
{
53+
"command": "codingPlugin.refresh",
54+
"when": "view == treeViewSample",
55+
"group": "navigation"
56+
}
57+
]
58+
},
4259
"viewsWelcome": [
4360
{
44-
"view": "treeviewSample",
61+
"view": "treeViewSample",
4562
"contents": "Please login first.\n[Login](command:codingPlugin.login)"
4663
}
4764
],
@@ -57,7 +74,7 @@
5774
"views": {
5875
"treeview-sample": [
5976
{
60-
"id": "treeviewSample",
77+
"id": "treeViewSample",
6178
"name": "Treeview Sample",
6279
"icon": "src/assets/coding.svg",
6380
"contextualTitle": "List"

src/assets/refresh.dark.svg

Lines changed: 1 addition & 0 deletions
Loading

src/assets/refresh.light.svg

Lines changed: 1 addition & 0 deletions
Loading

src/coding.ts

Lines changed: 0 additions & 117 deletions
This file was deleted.

src/codingServer.ts

Lines changed: 110 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,26 @@ import { nanoid } from 'nanoid';
33
import got from 'got';
44

55
import gotInstance from './common/request';
6-
import { AuthFailResult, AuthSuccessResult, CodingResponse, UserResponse } from './typings/respResult';
6+
import { AuthFailResult, AuthSuccessResult, CodingResponse } from './typings/respResult';
77
import { PromiseAdapter, promiseFromEvent, parseQuery, parseCloneUrl } from './common/utils';
88
import { GitService } from './common/gitService';
9-
import { RepoInfo, SessionData } from './typings/commonTypes';
9+
import { RepoInfo, SessionData, TokenType } from './typings/commonTypes';
10+
import { keychain } from './common/keychain';
11+
import Logger from './common/logger';
1012

1113
const AUTH_SERVER = `https://x5p7m.csb.app`;
1214
const ClientId = `ff768664c96d04235b1cc4af1e3b37a8`;
1315
const ClientSecret = `d29ebb32cab8b5f0a643b5da7dcad8d1469312c7`;
1416

17+
export const ScopeList = [
18+
`user`,
19+
`user:email`,
20+
`project`,
21+
`project:depot`,
22+
];
23+
const SCOPES = ScopeList.join(`,`);
24+
const NETWORK_ERROR = 'network error';
25+
1526
class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler {
1627
public handleUri(uri: vscode.Uri) {
1728
this.fire(uri);
@@ -25,25 +36,67 @@ const onDidManuallyProvideToken = new vscode.EventEmitter<string>();
2536
export class CodingServer {
2637
private _pendingStates = new Map<string, string[]>();
2738
private _codeExchangePromises = new Map<string, Promise<AuthSuccessResult>>();
28-
private _session: SessionData = {} as SessionData;
29-
private _repo: RepoInfo = {
30-
team: ``,
31-
project: ``,
32-
repo: ``,
33-
};
39+
private _repo: RepoInfo | undefined;
3440
private _loggedIn: boolean = false;
41+
private _session: SessionData | null = null;
3542

36-
constructor(session?: SessionData | null, repo?: RepoInfo | null) {
37-
if (session) {
38-
this._session = session;
39-
this._loggedIn = true;
40-
}
43+
constructor(repo?: RepoInfo | null) {
4144
if (repo) {
4245
this._repo = repo;
4346
}
4447
}
4548

46-
public async login(team: string, scopes: string) {
49+
public async initialize(context: vscode.ExtensionContext): Promise<void> {
50+
try {
51+
this._session = await this._readSessions();
52+
} catch (e) {
53+
// Ignore, network request failed
54+
}
55+
}
56+
57+
private async _readSessions(): Promise<SessionData | null> {
58+
const [accessToken, refreshToken] = await Promise.all([
59+
keychain.getToken(TokenType.AccessToken),
60+
keychain.getToken(TokenType.RefreshToken),
61+
]);
62+
if (accessToken && refreshToken) {
63+
try {
64+
const session = await this.getSessionData(accessToken as TokenType.AccessToken, refreshToken as TokenType.RefreshToken);
65+
return session;
66+
} catch (e) {
67+
if (e === NETWORK_ERROR) {
68+
return null;
69+
}
70+
71+
Logger.error(`Error reading sessions: ${e}`);
72+
await keychain.deleteToken(TokenType.AccessToken);
73+
}
74+
}
75+
76+
return null;
77+
}
78+
79+
public async getSessionData(accessToken: TokenType.AccessToken, refreshToken: TokenType.RefreshToken): Promise<SessionData> {
80+
try {
81+
const result = await this.getUserInfo(this._repo?.team || ``, accessToken);
82+
const { data: userInfo } = result;
83+
const ret: SessionData = {
84+
id: nanoid(),
85+
user: userInfo,
86+
accessToken,
87+
refreshToken,
88+
};
89+
90+
vscode.window.showInformationMessage(`USER ${userInfo.name} @ TEAM ${userInfo.team}`);
91+
return ret;
92+
} catch (err) {
93+
console.error(err);
94+
throw new Error(err);
95+
}
96+
}
97+
98+
99+
public async startOAuth(team: string, scopes: string) {
47100
const state = nanoid();
48101
const { name, publisher } = require('../package.json');
49102
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://${publisher}.${name}/on-did-authenticate`));
@@ -69,16 +122,35 @@ export class CodingServer {
69122
});
70123
}
71124

125+
public async login(team: string, scopes: string = SCOPES): Promise<SessionData | null> {
126+
const { access_token: accessToken, refresh_token: refreshToken } = await this.startOAuth(team, scopes);
127+
if (accessToken && refreshToken) {
128+
try {
129+
const session = await this.getSessionData(accessToken, refreshToken);
130+
this._session = session;
131+
await Promise.all([
132+
keychain.setToken(accessToken, TokenType.AccessToken),
133+
keychain.setToken(refreshToken, TokenType.RefreshToken),
134+
]);
135+
return session;
136+
} catch (e) {
137+
throw new Error(e);
138+
}
139+
}
140+
141+
return null;
142+
}
143+
72144
private _exchangeCodeForToken: (team: string, scopes: string) => PromiseAdapter<vscode.Uri, AuthSuccessResult> = (team, scopes) => async (uri, resolve, reject) => {
73145
const query = parseQuery(uri);
74146
const { code } = query;
75147

76-
const acceptedStates = this._pendingStates.get(scopes) || [];
77-
if (!acceptedStates.includes(query.state)) {
78-
console.error(`Received mismatched state`);
79-
reject({});
80-
return;
81-
}
148+
// const acceptedStates = this._pendingStates.get(scopes) || [];
149+
// if (!acceptedStates.includes(query.state)) {
150+
// console.error(`Received mismatched state`);
151+
// reject({});
152+
// return;
153+
// }
82154

83155
try {
84156
const result = await got.post(
@@ -104,7 +176,7 @@ export class CodingServer {
104176
}
105177
};
106178

107-
public async getUserInfo(team: string, token: string = this._session?.accessToken) {
179+
public async getUserInfo(team: string, token: string = this._session?.accessToken || ``) {
108180
try {
109181
const result: CodingResponse = await gotInstance.get(`https://${team}.coding.net/api/current_user`, {
110182
searchParams: {
@@ -131,9 +203,9 @@ export class CodingServer {
131203
}
132204

133205
public async getMRList(
134-
team: string = this._repo.team,
135-
project: string = this._repo.project,
136-
repo: string = this._repo.repo,
206+
team: string | undefined = this._repo?.team,
207+
project: string | undefined = this._repo?.project,
208+
repo: string | undefined = this._repo?.repo,
137209
) {
138210
try {
139211
const result = await got.get(`https://${team}.coding.net/api/user/${team}/project/${project}/depot/${repo}/git/merges/query`, {
@@ -143,7 +215,7 @@ export class CodingServer {
143215
page: 1,
144216
PageSize: 20,
145217
sortDirection: `DESC`,
146-
access_token: this._session.accessToken,
218+
access_token: this._session?.accessToken,
147219
},
148220
}).json();
149221

@@ -160,5 +232,18 @@ export class CodingServer {
160232
get session() {
161233
return this._session;
162234
}
235+
236+
public async logout() {
237+
try {
238+
await Promise.all([
239+
keychain.deleteToken(TokenType.AccessToken),
240+
keychain.deleteToken(TokenType.RefreshToken),
241+
]);
242+
this._session = null;
243+
return true;
244+
} catch (e) {
245+
throw Error(e);
246+
}
247+
}
163248
}
164249

0 commit comments

Comments
 (0)