Skip to content

Commit daf6262

Browse files
committed
WIP(tree): mr list.
1 parent 79ecb15 commit daf6262

File tree

12 files changed

+171
-275
lines changed

12 files changed

+171
-275
lines changed

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"version": "0.0.1",
55
"publisher": "alcheung",
66
"license": "MIT",
7-
"enableProposedApi": true,
87
"engines": {
98
"vscode": "^1.47.0"
109
},
@@ -34,13 +33,19 @@
3433
"title": "Login coding.net",
3534
"category": "Coding plugin"
3635
}
37-
],
36+
],
37+
"viewsWelcome": [
38+
{
39+
"view": "treeviewSample",
40+
"contents": "Please login first.\n[Login](command:codingPlugin.login)"
41+
}
42+
],
3843
"viewsContainers": {
3944
"activitybar": [
4045
{
4146
"id": "treeview-sample",
4247
"title": "Treeview Sample",
43-
"icon": "src/assets/coding.svg"
48+
"icon": "src/assets/coding.svg"
4449
}
4550
]
4651
},

src/coding.ts

Lines changed: 42 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,9 @@ import * as vscode from 'vscode';
22
import { nanoid } from 'nanoid';
33

44
import { keychain } from './common/keychain';
5-
import Logger from './common/logger'
5+
import Logger from './common/logger';
66
import { CodingServer } from './codingServer';
7-
import { RepoInfo } from './typings/types';
8-
9-
interface SessionData {
10-
id: string;
11-
account?: {
12-
label?: string;
13-
displayName?: string;
14-
id: string;
15-
}
16-
scopes: string[];
17-
accessToken: string;
18-
}
7+
import { RepoInfo, SessionData, TokenType } from './typings/commonTypes';
198

209
export const ScopeList = [
2110
`user`,
@@ -29,7 +18,7 @@ const NETWORK_ERROR = 'network error';
2918
export const onDidChangeSessions = new vscode.EventEmitter<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent>();
3019

3120
export class CodingAuthenticationProvider {
32-
private _sessions: vscode.AuthenticationSession[] = [];
21+
private _session: SessionData | null = null;
3322
private _codingServer = new CodingServer();
3423
private _repo: RepoInfo = {
3524
team: ``,
@@ -45,141 +34,66 @@ export class CodingAuthenticationProvider {
4534

4635
public async initialize(context: vscode.ExtensionContext): Promise<void> {
4736
try {
48-
this._sessions = await this._readSessions();
49-
} catch (e) {
50-
// Ignore, network request failed
51-
}
52-
53-
context.subscriptions.push(vscode.authentication.onDidChangePassword(() => this._checkForUpdates()));
54-
}
55-
56-
private async _checkForUpdates() {
57-
let storedSessions: vscode.AuthenticationSession[];
58-
try {
59-
storedSessions = await this._readSessions();
37+
this._session = await this._readSessions();
6038
} catch (e) {
6139
// Ignore, network request failed
62-
return;
63-
}
64-
65-
const added: string[] = [];
66-
const removed: string[] = [];
67-
68-
storedSessions.forEach(session => {
69-
const matchesExisting = this._sessions.some(s => s.id === session.id);
70-
// Another window added a session to the keychain, add it to our state as well
71-
if (!matchesExisting) {
72-
Logger.info('Adding session found in keychain');
73-
this._sessions.push(session);
74-
added.push(session.id);
75-
}
76-
});
77-
78-
this._sessions.map(session => {
79-
const matchesExisting = storedSessions.some(s => s.id === session.id);
80-
// Another window has logged out, remove from our state
81-
if (!matchesExisting) {
82-
Logger.info('Removing session no longer found in keychain');
83-
const sessionIndex = this._sessions.findIndex(s => s.id === session.id);
84-
if (sessionIndex > -1) {
85-
this._sessions.splice(sessionIndex, 1);
86-
}
87-
88-
removed.push(session.id);
89-
}
90-
});
91-
92-
if (added.length || removed.length) {
93-
onDidChangeSessions.fire({ added, removed, changed: [] });
9440
}
9541
}
9642

97-
private async _readSessions(): Promise<vscode.AuthenticationSession[]> {
98-
const storedSessions = await keychain.getToken() || await keychain.tryMigrate();
99-
if (storedSessions) {
43+
private async _readSessions(): Promise<SessionData | null> {
44+
const [accessToken, refreshToken] = await Promise.all([
45+
keychain.getToken(TokenType.AccessToken),
46+
keychain.getToken(TokenType.RefreshToken),
47+
]);
48+
if (accessToken && refreshToken) {
10049
try {
101-
const sessionData: SessionData[] = JSON.parse(storedSessions);
102-
const sessionPromises = sessionData.map(async (session: SessionData): Promise<vscode.AuthenticationSession> => {
103-
const needsUserInfo = !session.account;
104-
let userInfo: { id: string, accountName: string };
105-
if (needsUserInfo) {
106-
userInfo = await this._codingServer.getUserInfo(this._repo.team, session.accessToken);
107-
}
108-
109-
return {
110-
id: session.id,
111-
account: {
112-
label: session.account
113-
? session.account.label || session.account.displayName!
114-
: userInfo!.accountName,
115-
id: session.account?.id ?? userInfo!.id
116-
},
117-
scopes: session.scopes,
118-
accessToken: session.accessToken
119-
};
120-
});
121-
122-
return Promise.all(sessionPromises);
50+
const session = await this.getSessionData(accessToken as TokenType.AccessToken, refreshToken as TokenType.RefreshToken);
51+
return session;
12352
} catch (e) {
12453
if (e === NETWORK_ERROR) {
125-
return [];
54+
return null;
12655
}
12756

12857
Logger.error(`Error reading sessions: ${e}`);
129-
await keychain.deleteToken();
58+
await keychain.deleteToken(TokenType.AccessToken);
13059
}
13160
}
13261

133-
return [];
134-
}
135-
136-
private async _tokenToSession(token: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
137-
const userInfo = await this._codingServer.getUserInfo(this._repo.team, token);
138-
139-
return {
140-
id: nanoid(),
141-
accessToken: token,
142-
account: {
143-
label: userInfo.name,
144-
id: userInfo.global_key,
145-
},
146-
scopes,
147-
};
62+
return null;
14863
}
14964

150-
public async login(team: string, scopes: string = SCOPES): Promise<vscode.AuthenticationSession> {
151-
const { access_token: token } = await this._codingServer.login(team, scopes);
152-
const session = await this._tokenToSession(token, scopes.split(' '));
153-
await this._setToken(session);
154-
return session;
155-
}
156-
157-
private async _storeSessions(): Promise<void> {
158-
await keychain.setToken(JSON.stringify(this._sessions));
65+
public async getSessionData(accessToken: TokenType.AccessToken, refreshToken: TokenType.RefreshToken): Promise<SessionData | null> {
66+
try {
67+
const { data: userInfo } = await this._codingServer.getUserInfo(this._repo.team, accessToken);
68+
const ret: SessionData = {
69+
id: nanoid(),
70+
user: userInfo,
71+
accessToken,
72+
refreshToken,
73+
};
74+
75+
vscode.window.showInformationMessage(`USER ${userInfo.name} @ TEAM ${userInfo.team}`);
76+
return ret;
77+
} catch (err) {
78+
return null;
79+
}
15980
}
16081

161-
private async _setToken(session: vscode.AuthenticationSession): Promise<void> {
162-
const sessionIndex = this._sessions.findIndex(s => s.id === session.id);
163-
if (sessionIndex > -1) {
164-
this._sessions.splice(sessionIndex, 1, session);
165-
} else {
166-
this._sessions.push(session);
82+
public async login(team: string, scopes: string = SCOPES): Promise<SessionData | null> {
83+
const { access_token: accessToken, refresh_token: refreshToken } = await this._codingServer.login(team, scopes);
84+
if (accessToken && refreshToken) {
85+
const session = await this.getSessionData(accessToken, refreshToken);
86+
await Promise.all([
87+
keychain.setToken(accessToken, TokenType.AccessToken),
88+
keychain.setToken(refreshToken, TokenType.RefreshToken),
89+
]);
90+
return session;
16791
}
16892

169-
await this._storeSessions();
93+
return null;
17094
}
17195

172-
// @ts-ignore
173-
get sessions(): vscode.AuthenticationSession[] {
174-
return this._sessions;
175-
}
176-
177-
public async logout(id: string) {
178-
const sessionIndex = this._sessions.findIndex(session => session.id === id);
179-
if (sessionIndex > -1) {
180-
this._sessions.splice(sessionIndex, 1);
181-
}
182-
183-
await this._storeSessions();
96+
get session() {
97+
return this._session;
18498
}
18599
}

src/codingServer.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as vscode from 'vscode';
2-
import { nanoid } from 'nanoid'
2+
import { nanoid } from 'nanoid';
33
import got from 'got';
44

5-
import { AuthFailResult, AuthSuccessResult, UserResponse } from './typings/ResponseResult';
5+
import { AuthFailResult, AuthSuccessResult, UserResponse } from './typings/respResult';
66
import { PromiseAdapter, promiseFromEvent, parseQuery, parseCloneUrl } from './common/utils';
77
import { GitService } from './common/gitService';
8-
import { RepoInfo } from './typings/types';
8+
import { RepoInfo, SessionData } from './typings/commonTypes';
99

1010
const AUTH_SERVER = `http://127.0.0.1:5000`;
1111
const ClientId = `ff768664c96d04235b1cc4af1e3b37a8`;
@@ -24,16 +24,18 @@ const onDidManuallyProvideToken = new vscode.EventEmitter<string>();
2424
export class CodingServer {
2525
private _pendingStates = new Map<string, string[]>();
2626
private _codeExchangePromises = new Map<string, Promise<AuthSuccessResult>>();
27-
private _accessToken: string = ``;
27+
private _session: SessionData = {} as SessionData;
2828
private _repo: RepoInfo = {
2929
team: ``,
3030
project: ``,
3131
repo: ``,
3232
};
33+
private _loggedIn: boolean = false;
3334

34-
constructor(sessions?: vscode.AuthenticationSession[], repo?: RepoInfo | null) {
35-
if (sessions?.length) {
36-
this._accessToken = sessions[sessions.length - 1].accessToken;
35+
constructor(session?: SessionData | null, repo?: RepoInfo | null) {
36+
if (session) {
37+
this._session = session;
38+
this._loggedIn = true;
3739
}
3840
if (repo) {
3941
this._repo = repo;
@@ -86,11 +88,12 @@ export class CodingServer {
8688
client_id: ClientId,
8789
client_secret: ClientSecret,
8890
grant_type: `authorization_code`,
89-
}
90-
}
91+
},
92+
},
9193
).json();
9294

9395
if ((result as AuthFailResult).code) {
96+
this._loggedIn = false;
9497
reject({} as AuthSuccessResult);
9598
} else {
9699
resolve(result as AuthSuccessResult);
@@ -100,12 +103,12 @@ export class CodingServer {
100103
}
101104
};
102105

103-
public async getUserInfo(team: string, token: string = this._accessToken) {
106+
public async getUserInfo(team: string, token: string = this._session?.accessToken) {
104107
try {
105-
const result: UserResponse = await got.get(`https://${team}.coding.net/api/me`, {
108+
const result: UserResponse = await got.get(`https://${team}.coding.net/api/current_user`, {
106109
searchParams: {
107110
access_token: token,
108-
}
111+
},
109112
}).json();
110113
return result;
111114
} catch (err) {
@@ -137,16 +140,24 @@ export class CodingServer {
137140
status: `all`,
138141
sort: `action_at`,
139142
page: 1,
140-
PageSize: 15,
143+
PageSize: 20,
141144
sortDirection: `DESC`,
142-
access_token: this._accessToken,
143-
}
145+
access_token: this._session.accessToken,
146+
},
144147
}).json();
145148

146149
return result;
147150
} catch (err) {
148-
return err
151+
return err;
149152
}
150153
}
154+
155+
get loggedIn() {
156+
return this._loggedIn;
157+
}
158+
159+
get session() {
160+
return this._session;
161+
}
151162
}
152163

0 commit comments

Comments
 (0)