Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions src/authentication/providers.ts → src/authentication/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { authentication, type AuthenticationProviderAuthenticationSessionsChange
import type ExtensionCore from "../core/extension";
import { GlobalStorageKeys } from "../utils/constants";
import { AuthenticationProviderId } from "./enum/providers";
import type { IPatAuthenticationProvider } from "./interfaces/pat";
import { type IAuthenticationProvider } from "./interfaces/provider";
import DiscloudPatAuthenticationProvider from "./pat/provider";
import type { IAuthenticationProvider } from "./interfaces/provider";
import DiscloudPatAuthenticationProvider from "./providers/pat";

export default class AuthenticationProviderContainer implements IAuthenticationProvider {
export default class AuthenticationProviderAdapter implements IAuthenticationProvider {
constructor(
readonly core: ExtensionCore,
) {
const providerIds = Object.values(AuthenticationProviderId);

for (let i = 0; i < providerIds.length; i++) {
const providerId = providerIds[i];

core.context.subscriptions.push(
authentication.registerAuthenticationProvider(
providerId,
Expand All @@ -29,37 +29,38 @@ export default class AuthenticationProviderContainer implements IAuthenticationP
core.context.subscriptions.push(this._emitter);
}

protected readonly _pat: IPatAuthenticationProvider;
declare protected readonly _pat: IAuthenticationProvider;

protected readonly _emitter = new EventEmitter<AuthenticationProviderAuthenticationSessionsChangeEvent>();
/** @override {@link AuthenticationSession} */
/** @override {@link AuthenticationProvider} */
get onDidChangeSessions() { return this._emitter.event; }

protected get _globalStorage() { return this.core.globalStorage; }

protected _getCurrentAuthenticationProviderId() {
return this.core.globalStorage.get<AuthenticationProviderId>(GlobalStorageKeys.currentAutenticationProviderId);
return this._globalStorage.get<AuthenticationProviderId>(GlobalStorageKeys.currentAutenticationProviderId);
}

protected _getCurrentSessionId() {
return this.core.globalStorage.get<string>(GlobalStorageKeys.currentSessionId);
return this._globalStorage.get<string>(GlobalStorageKeys.currentSessionId);
}

protected _getCurrentSessionAccount(): AuthenticationSessionAccountInformation | undefined {
const sessionId = this._getCurrentSessionId();
if (!sessionId) return;
return this.core.globalStorage.get(sessionId);
if (sessionId) return this._globalStorage.get(sessionId);
}

/** @override {@link AuthenticationSession} */
/** @override {@link AuthenticationProvider} */
createSession(scopes: readonly string[], options: AuthenticationProviderSessionOptions): Thenable<AuthenticationSession> {
return this._pat.createSession(scopes, options);
}

/** @override {@link AuthenticationSession} */
/** @override {@link AuthenticationProvider} */
getSessions(scopes: readonly string[] | undefined, options: AuthenticationProviderSessionOptions): Thenable<AuthenticationSession[]> {
return this._pat.getSessions(scopes, options);
}

/** @override {@link AuthenticationSession} */
/** @override {@link AuthenticationProvider} */
removeSession(sessionId: string): Thenable<void> {
return this._pat.removeSession(sessionId);
}
Expand Down
3 changes: 0 additions & 3 deletions src/authentication/interfaces/pat.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import { GlobalStorageKeys } from "../../utils/constants";
import { AuthenticationProviderId } from "../enum/providers";
import BaseAuthenticationError from "../errors/base";
import UnauthorizedError from "../errors/unauthorized";
import { type IPatAuthenticationProvider } from "../interfaces/pat";
import type { IAuthenticationProvider } from "../interfaces/provider";
import DiscloudAuthenticationSession from "../session";

const providerId = AuthenticationProviderId.discloud;
const defaultSessionAccount: AuthenticationSessionAccountInformation = {
const _providerId = AuthenticationProviderId.discloud;
const _defaultSessionAccount: AuthenticationSessionAccountInformation = {
id: "Unknown Discloud User ID",
label: "Unknown Discloud User",
};

export default class DiscloudPatAuthenticationProvider implements IPatAuthenticationProvider {
export default class DiscloudPatAuthenticationProvider implements IAuthenticationProvider {
constructor(
protected readonly emitter: EventEmitter<AuthenticationProviderAuthenticationSessionsChangeEvent>,
protected readonly secrets: SecretStorage,
Expand All @@ -25,12 +25,12 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica

get onDidChangeSessions() { return this.emitter.event; }

get #sessionIdList() {
#getSessionIdList() {
return this.storage.get<string[]>(GlobalStorageKeys.sessionIdList, []);
}

get #sessionIdSet() {
return new Set(this.#sessionIdList);
#getSessionIdSet() {
return new Set(this.#getSessionIdList());
}

protected _fire(data: Partial<AuthenticationProviderAuthenticationSessionsChangeEvent>): void;
Expand All @@ -41,7 +41,7 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
/** @override {@link AuthenticationProvider} */
createSession(scopes: readonly string[], options: AuthenticationProviderSessionOptions): Thenable<AuthenticationSession>;
async createSession(_scopes: readonly string[], _options: AuthenticationProviderSessionOptions) {
const sessionIdSet = this.#sessionIdSet;
const sessionIdSet = this.#getSessionIdSet();

const currentTokens = new Set<string>();
for (const sessionId of sessionIdSet) {
Expand Down Expand Up @@ -74,39 +74,41 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
const body = await response.json().catch(() => null) as RESTGetApiUserResult | null;

const account: AuthenticationSessionAccountInformation = {
id: body?.user.userID ?? defaultSessionAccount.id,
label:
body?.user.username ?? body?.user.userID ?? defaultSessionAccount.label,
id: body?.user.userID ?? _defaultSessionAccount.id,
label: body?.user.username ?? body?.user.userID ?? _defaultSessionAccount.label,
};

const promises = [];

const newSessionId = `${providerId}.${account.id}`;
const newSessionId = `${_providerId}.${account.id}`;

const oldSessionId = this.storage.get<string>(GlobalStorageKeys.currentSessionId);

if (oldSessionId !== newSessionId) {
sessionIdSet.add(newSessionId);

if (oldSessionId) {
sessionIdSet.delete(oldSessionId);

promises.push(
this.storage.update(oldSessionId, undefined),
this.secrets.delete(oldSessionId),
);
}

sessionIdSet.add(newSessionId);

promises.push(
this.storage.update(GlobalStorageKeys.sessionIdList, Array.from(sessionIdSet)),
this.storage.update(GlobalStorageKeys.currentSessionId, newSessionId),
);
}

await Promise.all(promises.concat(
this.storage.update(GlobalStorageKeys.currentAutenticationProviderId, providerId),
promises.push(
this.storage.update(GlobalStorageKeys.currentAutenticationProviderId, _providerId),
this.storage.update(newSessionId, account),
this.secrets.store(newSessionId, input),
));
);

await Promise.all(promises);

const newSession = new DiscloudAuthenticationSession(newSessionId, input, account);

Expand All @@ -118,10 +120,10 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
/** @override {@link AuthenticationProvider} */
getSessions(scopes: readonly string[] | undefined, options: AuthenticationProviderSessionOptions): Thenable<AuthenticationSession[]>;
async getSessions(_scopes: readonly string[] | undefined, options: AuthenticationProviderSessionOptions) {
const sessionIdList = this.#sessionIdList;
const sessionIdList = this.#getSessionIdList();
const sessionIdSet = new Set(sessionIdList);

const sessions: DiscloudAuthenticationSession[] = [];
const sessions: AuthenticationSession[] = [];

for (const sessionId of sessionIdSet) {
const secret = await this.secrets.get(sessionId);
Expand All @@ -131,7 +133,7 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
}

const account: AuthenticationSessionAccountInformation =
this.storage.get(sessionId) ?? defaultSessionAccount;
this.storage.get(sessionId) ?? _defaultSessionAccount;

if (options.account && options.account.id !== account.id) continue;

Expand All @@ -153,13 +155,13 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
if (!secret) return;

const account: AuthenticationSessionAccountInformation =
this.storage.get(sessionId) ?? defaultSessionAccount;
this.storage.get(sessionId) ?? _defaultSessionAccount;

const session = new DiscloudAuthenticationSession(sessionId, secret, account);

const currentSessionId = this.storage.get<string>(GlobalStorageKeys.currentSessionId);

const sessionIdSet = this.#sessionIdSet;
const sessionIdSet = this.#getSessionIdSet();
sessionIdSet.delete(sessionId);

const promises: Thenable<void>[] = [
Expand All @@ -186,7 +188,7 @@ export default class DiscloudPatAuthenticationProvider implements IPatAuthentica
}

getSession(account?: AuthenticationSessionAccountInformation) {
return authentication.getSession(providerId, [], { account, silent: true });
return authentication.getSession(_providerId, [], { account, silent: true });
}

async hasSession() {
Expand Down
6 changes: 3 additions & 3 deletions src/core/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { normalize } from "path";
import { commands, type Disposable, type ExtensionContext, type LogOutputChannel, type SecretStorage, window, workspace } from "vscode";
import { type ExtensionContextId } from "../@enum";
import type { Events, IGlobalStateStorage, TaskData } from "../@types";
import AuthenticationProviderContainer from "../authentication/providers";
import AuthenticationProviderAdapter from "../authentication/adapter";
import { commandsRegister } from "../commands";
import { loadEvents } from "../events";
import DiscloudLogOutputChannel from "../output/LogOutputChannel";
Expand Down Expand Up @@ -41,7 +41,7 @@ export default class ExtensionCore extends EventEmitter<Events> implements Dispo
this.workspaceStorage = new StateStorage(context.workspaceState);
this.secrets = new SecretStorageImpl(context.secrets);

this.auth = new AuthenticationProviderContainer(this);
this.auth = new AuthenticationProviderAdapter(this);

this.statusBar = new DiscloudStatusBarItem(this);

Expand All @@ -58,7 +58,7 @@ export default class ExtensionCore extends EventEmitter<Events> implements Dispo
this.userTree = new UserTreeDataProvider(this);
}

declare readonly auth: AuthenticationProviderContainer;
declare readonly auth: AuthenticationProviderAdapter;
declare readonly secrets: SecretStorage;
declare readonly globalStorage: StateStorage & IGlobalStateStorage;
declare readonly workspaceStorage: StateStorage;
Expand Down
20 changes: 10 additions & 10 deletions src/storage/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export default class StateStorage implements vscode.Memento {
protected readonly state: vscode.Memento,
) { }

keys() {
return this.state.keys();
delete(key: string) {
return this.state.update(key, undefined);
}

get<T>(key: string): T | undefined;
Expand All @@ -15,6 +15,14 @@ export default class StateStorage implements vscode.Memento {
return this.state.get<T>(key, defaultValue!);
}

keys() {
return this.state.keys();
}

update<T>(key: string, value: T) {
return this.state.update(key, value);
}

/**
* Store the current value and return the previous value.
* if it does not contain a saved value, the current value will be returned
Expand All @@ -31,12 +39,4 @@ export default class StateStorage implements vscode.Memento {
if (typeof cached === typeof currentValue) return cached;
return currentValue;
}

update<T>(key: string, value: T) {
return this.state.update(key, value);
}

delete(key: string) {
return this.state.update(key, undefined);
}
}
Loading