switch to use generic sessionmanager and storage

This commit is contained in:
J Shamsul Bahri (jibone))
2020-09-21 18:48:13 +08:00
parent 70dc0627aa
commit e2d719f502
7 changed files with 11 additions and 167 deletions
@@ -28,8 +28,8 @@ import {
import { AuthProvider, DiscoveryApi } from '../../../definitions';
import { SamlSession } from './types';
import {
SamlAuthSessionManager,
SamlAuthSessionStore,
AuthSessionStore,
StaticAuthSessionManager,
} from '../../../../lib/AuthSessionManager';
type CreateOptions = {
@@ -62,11 +62,11 @@ class SamlAuth implements SamlApi {
provider,
});
const sessionManager = new SamlAuthSessionManager<SamlSession>({
const sessionManager = new StaticAuthSessionManager<SamlSession>({
connector,
});
const authSessionStore = new SamlAuthSessionStore<SamlSession>({
const authSessionStore = new AuthSessionStore<SamlSession>({
manager: sessionManager,
storageKey: 'samlSession',
});
@@ -28,7 +28,7 @@ type Options<T> = {
/** Storage key to use to store sessions */
storageKey: string;
/** Used to get the scope of the session */
sessionScopes: SessionScopesFunc<T>;
sessionScopes?: SessionScopesFunc<T>;
/** Used to check if the session needs to be refreshed, defaults to never refresh */
sessionShouldRefresh?: SessionShouldRefreshFunc<T>;
};
@@ -1,63 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SessionManager, GetSessionOptions } from './types';
import {
SamlAuthConnector,
SamlResponse,
} from '../AuthConnector/SamlAuthConnector';
import { SessionStateTracker } from './SessionStateTracker';
type Options = {
connector: SamlAuthConnector<SamlResponse>;
};
export class SamlAuthSessionManager<T> implements SessionManager<T> {
private readonly connector: SamlAuthConnector<SamlResponse>;
private readonly stateTracker = new SessionStateTracker();
private currentSession: any | undefined; // FIXME: proper typing here?
constructor(options: Options) {
const { connector } = options;
this.connector = connector;
}
async getSession(options: GetSessionOptions): Promise<T | undefined> {
if (this.currentSession) {
return this.currentSession;
}
if (options.optional) {
return undefined;
}
this.currentSession = await this.connector.createSession();
this.stateTracker.setIsSignedIn(true);
return this.currentSession;
}
async removeSession() {
this.currentSession = undefined;
await this.connector.removeSession();
this.stateTracker.setIsSignedIn(false);
}
sessionState$() {
return this.stateTracker.sessionState$();
}
}
@@ -1,94 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SamlAuthSessionManager, GetSessionOptions } from './types';
type Options<T> = {
manager: SamlAuthSessionManager<T>;
storageKey: string;
};
export class SamlAuthSessionStore<T> implements SamlAuthSessionManager<T> {
private readonly manager: SamlAuthSessionManager<T>;
private readonly storageKey: string;
constructor(options: Options<T>) {
const { manager, storageKey } = options;
this.manager = manager;
this.storageKey = storageKey;
}
async getSession(options: GetSessionOptions): Promise<T | undefined> {
const session = this.loadSession();
if (session) {
return session!;
}
const newSession = await this.manager.getSession(options);
this.saveSession(newSession);
return newSession;
}
async removeSession() {
localStorage.removeItem(this.storageKey);
await this.manager.removeSession();
}
sessionState$() {
return this.manager.sessionState$();
}
private saveSession(session: T | undefined) {
if (session === undefined) {
localStorage.removeItem(this.storageKey);
} else {
localStorage.setItem(
this.storageKey,
JSON.stringify(session, (_key, value) => {
if (value instanceof Set) {
return {
__type: 'Set',
__value: Array.from(value),
};
}
return value;
}),
);
}
}
private loadSession(): T | undefined {
try {
const sessionJson = localStorage.getItem(this.storageKey);
if (sessionJson) {
const session = JSON.parse(sessionJson, (_key, value) => {
if (value?.__type === 'Set') {
return new Set(value.__value);
}
return value;
});
return session;
}
return undefined;
} catch (error) {
localStorage.removeItem(this.storageKey);
return undefined;
}
}
}
@@ -23,7 +23,7 @@ type Options<T> = {
/** The connector used for acting on the auth session */
connector: AuthConnector<T>;
/** Used to get the scope of the session */
sessionScopes: (session: T) => Set<string>;
sessionScopes?: (session: T) => Set<string>;
/** The default scopes that should always be present in a session, defaults to none. */
defaultScopes?: Set<string>;
};
@@ -29,7 +29,7 @@ export function hasScopes(
}
type ScopeHelperOptions<T> = {
sessionScopes: SessionScopesFunc<T>;
sessionScopes: SessionScopesFunc<T> | undefined;
defaultScopes?: Set<string>;
};
@@ -46,13 +46,16 @@ export class SessionScopeHelper<T> {
if (!scopes) {
return true;
}
if (this.options.sessionScopes === undefined) {
return true;
}
const sessionScopes = this.options.sessionScopes(session);
return hasScopes(sessionScopes, scopes);
}
getExtendedScope(session: T | undefined, scopes?: Set<string>) {
const newScope = new Set(this.options.defaultScopes);
if (session) {
if (session && this.options.sessionScopes !== undefined) {
const sessionScopes = this.options.sessionScopes(session);
for (const scope of sessionScopes) {
newScope.add(scope);
@@ -16,7 +16,5 @@
export { RefreshingAuthSessionManager } from './RefreshingAuthSessionManager';
export { StaticAuthSessionManager } from './StaticAuthSessionManager';
export { SamlAuthSessionManager } from './SamlAuthSessionManager';
export { AuthSessionStore } from './AuthSessionStore';
export { SamlAuthSessionStore } from './SamlAuthSessionStore';
export * from './types';