122 lines
4.3 KiB
TypeScript
122 lines
4.3 KiB
TypeScript
import { inject, Injectable, signal } from '@angular/core';
|
|
import { NGXLogger } from 'ngx-logger';
|
|
import { List } from '../../utils';
|
|
import dayjs from 'dayjs';
|
|
|
|
export interface IStoredTenantId {
|
|
readonly tenantId: string;
|
|
readonly email: string;
|
|
readonly created: string;
|
|
}
|
|
|
|
export type StoredTenantIds = List<IStoredTenantId>;
|
|
|
|
const STORED_TENANTS_KEY = 'red-stored-tenants';
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class TenantsService {
|
|
readonly #logger = inject(NGXLogger);
|
|
readonly #storageReference: Storage = {
|
|
length: localStorage.length,
|
|
clear: localStorage.clear.bind(localStorage),
|
|
getItem: localStorage.getItem.bind(localStorage),
|
|
setItem: localStorage.setItem.bind(localStorage),
|
|
removeItem: localStorage.removeItem.bind(localStorage),
|
|
key: localStorage.key.bind(localStorage),
|
|
};
|
|
readonly #activeTenantId = signal<string>('');
|
|
protected readonly _serviceName: string = 'tenant-user-management';
|
|
|
|
get activeTenantId() {
|
|
return this.#activeTenantId();
|
|
}
|
|
|
|
async selectTenant(tenantId: string) {
|
|
this.#mutateStorage(tenantId);
|
|
this.#setActiveTenantId(tenantId);
|
|
return true;
|
|
}
|
|
|
|
storeTenant(emailOrUsername: string) {
|
|
if (!emailOrUsername) {
|
|
this.#logger.warn('[TENANTS] Email or username is null, skip storing');
|
|
return;
|
|
}
|
|
|
|
const storedTenants = this.getStoredTenants();
|
|
const activeTenantId = this.#activeTenantId();
|
|
const existing = storedTenants.find(s => s.email === emailOrUsername && s.tenantId === activeTenantId);
|
|
if (existing) {
|
|
this.#logger.info('[TENANTS] Stored tenant exists: ', storedTenants);
|
|
return;
|
|
}
|
|
|
|
if (!activeTenantId) {
|
|
this.#logger.error('[TENANTS] Active tenant is null when storing tenants');
|
|
return;
|
|
}
|
|
|
|
storedTenants.push({ tenantId: activeTenantId, email: emailOrUsername, created: new Date().toISOString() });
|
|
this.#storageReference.setItem(STORED_TENANTS_KEY, JSON.stringify(storedTenants));
|
|
this.#logger.info('[TENANTS] Stored tenants: ', storedTenants);
|
|
}
|
|
|
|
getStoredTenants() {
|
|
const rawStoredTenants = this.#storageReference.getItem(STORED_TENANTS_KEY);
|
|
const stored = JSON.parse(rawStoredTenants ?? '[]') as StoredTenantIds;
|
|
|
|
const validStoredTenants: IStoredTenantId[] = [];
|
|
for (const s of stored) {
|
|
const date1 = dayjs(s.created);
|
|
const date2 = dayjs();
|
|
const diff = date2.diff(date1, 'days');
|
|
const is90DaysOld = diff >= 90;
|
|
if (is90DaysOld) {
|
|
this.#logger.warn(`[TENANTS] Saved tenant ${s.tenantId} - ${s.email} is 90 days old, delete it`);
|
|
this.removeStored(s.email);
|
|
continue;
|
|
}
|
|
|
|
validStoredTenants.push(s);
|
|
}
|
|
|
|
return validStoredTenants;
|
|
}
|
|
|
|
removeStored(email: string) {
|
|
if (!email) {
|
|
this.#logger.warn('[TENANTS] Email is null, skip storing');
|
|
return;
|
|
}
|
|
|
|
const storedTenants = this.getStoredTenants();
|
|
const activeTenantId = this.#activeTenantId();
|
|
const existing = storedTenants.find(s => s.email === email && s.tenantId === activeTenantId);
|
|
if (!existing) {
|
|
this.#logger.info('[TENANTS] No stored tenant for ', email);
|
|
return;
|
|
}
|
|
|
|
const serializableTenants = storedTenants.filter(s => s !== existing);
|
|
this.#storageReference.setItem(STORED_TENANTS_KEY, JSON.stringify(serializableTenants));
|
|
this.#logger.info('[TENANTS] Stored tenants at logout: ', storedTenants);
|
|
}
|
|
|
|
#setActiveTenantId(tenantId: string) {
|
|
this.#logger.info('[TENANTS] Set current tenant id: ', tenantId);
|
|
this.#activeTenantId.set(tenantId);
|
|
}
|
|
|
|
#mutateStorage(tenant: string) {
|
|
localStorage.getItem = (key: string) => {
|
|
return this.#storageReference.getItem(tenant + ':' + key);
|
|
};
|
|
localStorage.setItem = (key: string, value: string) => {
|
|
this.#storageReference.setItem(tenant + ':' + key, value);
|
|
};
|
|
localStorage.removeItem = (key: string) => {
|
|
this.#storageReference.removeItem(tenant + ':' + key);
|
|
};
|
|
}
|
|
}
|