Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 6 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import { LayoutModule } from "_layout/layout.module";
import { AppConfigService } from "app-config.service";
import { AppThemeService } from "app-theme.service";
import { SnackbarInterceptor } from "shared/interceptors/snackbar.interceptor";
import { AuthService } from "shared/services/auth/auth.service";
import { InternalStorage, SDKStorage } from "shared/services/auth/base.storage";
import { CookieBrowser } from "shared/services/auth/cookie.browser";

const appConfigInitializerFn = (appConfig: AppConfigService) => {
return () => appConfig.loadAppConfig();
Expand Down Expand Up @@ -93,11 +96,14 @@ const appThemeInitializerFn = (appTheme: AppThemeService) => {
subscriptSizing: "dynamic",
},
},
AuthService,
AppThemeService,
UserApi,
SampleApi,
Title,
MatNativeDateModule,
{ provide: InternalStorage, useClass: CookieBrowser },
{ provide: SDKStorage, useClass: CookieBrowser },
],
bootstrap: [AppComponent],
})
Expand Down
122 changes: 122 additions & 0 deletions src/app/shared/services/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Injectable, Inject } from "@angular/core";
import { InternalStorage } from "./base.storage";
import { User } from "shared/sdk";

export interface AccessTokenInterface {
id?: string;
ttl?: number;
scopes?: [string];
created?: Date;
userId?: string;
user?: User;
}

export class SDKToken implements AccessTokenInterface {
id: string = null;
ttl: number = null;
scopes: [string] = null;
created: Date = null;
userId: string = null;
user: User = null;
rememberMe: boolean = null;
constructor(data?: AccessTokenInterface) {
Object.assign(this, data);
}
}

@Injectable()
export class AuthService {
private token = new SDKToken();

protected prefix = "";

constructor(@Inject(InternalStorage) protected storage: InternalStorage) {
// TODO: Test if all this works with the new changes and removal of any types
this.token.id = this.load("id");
this.token.user = JSON.parse(this.load("user"));
this.token.userId = this.load("userId");
this.token.created = new Date(this.load("created"));
this.token.ttl = parseInt(this.load("ttl"));
this.token.rememberMe = this.load("rememberMe") === "true";
}

protected load(prop: string) {
return decodeURIComponent(this.storage.get(`${this.prefix}${prop}`));
}

protected persist(
prop: string,
value: string | User | number | Date | boolean,
expires?: Date,
): void {
try {
this.storage.set(
`${this.prefix}${prop}`,
typeof value === "object" ? JSON.stringify(value) : value,
this.token.rememberMe ? expires : null,
);
} catch (err) {
console.error("Cannot access local/session storage:", err);
}
}

public clear(): void {
Object.keys(this.token).forEach((prop: string) =>
this.storage.remove(`${this.prefix}${prop}`),
);
this.token = new SDKToken();
}

public setRememberMe(value: boolean): void {
this.token.rememberMe = value;
}

public setUser(user: User) {
this.token.user = user;
this.save();
}

public setToken(token: SDKToken): void {
this.token = Object.assign({}, this.token, token);
this.save();
}

public getToken(): SDKToken {
return <SDKToken>this.token;
}

public getAccessTokenId(): string {
return this.token.id;
}

public getCurrentUserId() {
return this.token.userId;
}

public getCurrentUserData() {
return typeof this.token.user === "string"
? JSON.parse(this.token.user)
: this.token.user;
}

public isAuthenticated() {
return !(
this.getCurrentUserId() === "" ||
this.getCurrentUserId() == null ||
this.getCurrentUserId() == "null"
);
}

public save(): boolean {
const today = new Date();
const expires = new Date(today.getTime() + this.token.ttl * 1000);
this.persist("id", this.token.id, expires);
this.persist("user", this.token.user, expires);
this.persist("userId", this.token.userId, expires);
this.persist("created", this.token.created, expires);
this.persist("ttl", this.token.ttl, expires);
this.persist("rememberMe", this.token.rememberMe, expires);

return true;
}
}
15 changes: 15 additions & 0 deletions src/app/shared/services/auth/base.storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

export class BaseStorage {
get(key: string): string | undefined {
return undefined;
}

set(key: string, value: string | number | boolean, expires?: Date): void {}

remove(key: string): void {}
}

export class InternalStorage extends BaseStorage {}

export class SDKStorage extends BaseStorage {}
47 changes: 47 additions & 0 deletions src/app/shared/services/auth/cookie.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Injectable } from "@angular/core";
export interface CookieInterface {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}

@Injectable()
export class CookieBrowser {
private cookies: CookieInterface = {};

private parse(value: string) {
try {
return JSON.parse(decodeURI(value));
} catch (e) {
return value;
}
}

get(key: string): string {
if (!this.cookies[key]) {
const cookie = window.document.cookie
.split("; ")
.filter((item) => item.split("=")[0] === key)
.pop();
if (!cookie) {
return null;
}

this.cookies[key] = this.parse(cookie.split("=").slice(1).join("="));
}

return this.cookies[key];
}

set(key: string, value: string, expires?: Date): void {
this.cookies[key] = value;
const cookie = `${key}=${encodeURI(value)}; path=/${
expires ? `; expires=${expires.toUTCString()}` : ""
}`;
window.document.cookie = cookie;
}

remove(key: string) {
document.cookie = key + "=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
delete this.cookies[key];
}
}
32 changes: 32 additions & 0 deletions src/app/shared/services/auth/storage.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Injectable } from "@angular/core";

@Injectable()
export class LocalStorageBrowser {
private parse(value: string) {
try {
return JSON.parse(value);
} catch (e) {
return value;
}
}

get(key: string) {
const data: string = localStorage.getItem(key);
return this.parse(data);
}

set(key: string, value: string): void {
localStorage.setItem(
key,
typeof value === "object" ? JSON.stringify(value) : value,
);
}

remove(key: string): void {
if (localStorage[key]) {
localStorage.removeItem(key);
} else {
console.log("Trying to remove unexisting key: ", key);
}
}
}