remove emails from stored tenants

This commit is contained in:
Dan Percic 2023-08-08 11:28:38 +03:00
parent c851ab1394
commit 04a69f5e68
5 changed files with 76 additions and 47 deletions

View File

@ -1,11 +1,10 @@
import { inject, Injectable, signal } from '@angular/core';
import dayjs from 'dayjs';
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;
}
@ -24,7 +23,7 @@ export class TenantsService {
removeItem: localStorage.removeItem.bind(localStorage),
key: localStorage.key.bind(localStorage),
};
readonly #activeTenantId = signal<string>('');
readonly #activeTenantId = signal('');
protected readonly _serviceName: string = 'tenant-user-management';
get activeTenantId() {
@ -37,15 +36,10 @@ export class TenantsService {
return true;
}
storeTenant(emailOrUsername: string) {
if (!emailOrUsername) {
this.#logger.warn('[TENANTS] Email or username is null, skip storing');
return;
}
storeTenant() {
const storedTenants = this.getStoredTenants();
const activeTenantId = this.#activeTenantId();
const existing = storedTenants.find(s => s.email === emailOrUsername && s.tenantId === activeTenantId);
const existing = storedTenants.find(s => s.tenantId === activeTenantId);
if (existing) {
this.#logger.info('[TENANTS] Stored tenant exists: ', storedTenants);
return;
@ -56,7 +50,7 @@ export class TenantsService {
return;
}
storedTenants.push({ tenantId: activeTenantId, email: emailOrUsername, created: new Date().toISOString() });
storedTenants.push({ tenantId: activeTenantId, created: new Date().toISOString() });
this.#storageReference.setItem(STORED_TENANTS_KEY, JSON.stringify(storedTenants));
this.#logger.info('[TENANTS] Stored tenants: ', storedTenants);
}
@ -72,8 +66,8 @@ export class TenantsService {
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);
this.#logger.warn(`[TENANTS] Saved tenant ${s.tenantId} is 90 days old, delete it`);
this.removeStored(s.tenantId);
continue;
}
@ -83,17 +77,16 @@ export class TenantsService {
return validStoredTenants;
}
removeStored(email: string) {
if (!email) {
this.#logger.warn('[TENANTS] Email is null, skip storing');
removeStored(tenantId: string) {
if (!tenantId) {
this.#logger.warn('[TENANTS] Tenant Id is null, skip removing');
return;
}
const storedTenants = this.getStoredTenants();
const activeTenantId = this.#activeTenantId();
const existing = storedTenants.find(s => s.email === email && s.tenantId === activeTenantId);
const existing = storedTenants.find(s => s.tenantId === tenantId);
if (!existing) {
this.#logger.info('[TENANTS] No stored tenant for ', email);
this.#logger.info('[TENANTS] No stored tenant for ', tenantId);
return;
}

View File

@ -17,7 +17,7 @@
<div *ngIf="storedTenants.length">
<div
(click)="select(stored.tenantId, stored.email)"
(click)="select(stored.tenantId)"
*ngFor="let stored of storedTenants"
class="d-flex pointer mat-elevation-z2 card stored-tenant-card mt-10"
>
@ -25,10 +25,12 @@
<div class="card-content flex-column">
<span class="heading">{{ stored.tenantId }}</span>
<span>{{ stored.email }}</span>
</div>
<mat-icon class="card-icon upside-down" svgIcon="iqser:expand"></mat-icon>
<div class="remove" iqserStopPropagation>
<mat-icon (click)="removeStored(stored.tenantId)" svgIcon="iqser:close"></mat-icon>
</div>
</div>
</div>

View File

@ -23,6 +23,13 @@
.stored-tenant-card {
width: 450px;
height: 90px;
position: relative;
&:hover {
.remove {
display: flex;
}
}
}
.card {
@ -66,3 +73,24 @@
line-height: 29px;
font-family: 'Inter', sans-serif;
}
.remove {
display: none;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: var(--iqser-accent);
color: var(--iqser-white);
position: absolute;
right: -8px;
top: -8px;
line-height: 6px;
justify-content: center;
align-items: center;
mat-icon {
width: 6px;
height: 8px;
}
}

View File

@ -1,14 +1,14 @@
import { ChangeDetectionStrategy, Component, inject, Input } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { TenantsService } from '../services';
import { LoadingService } from '../../loading';
import { Title } from '@angular/platform-browser';
import { KeycloakService } from 'keycloak-angular';
import { NGXLogger } from 'ngx-logger';
import { LoadingService } from '../../loading';
import { getConfig } from '../../services';
import { BASE_HREF } from '../../utils';
import { getKeycloakOptions } from '../keycloak-initializer';
import { IStoredTenantId, TenantsService } from '../services';
import { KeycloakStatusService } from '../services/keycloak-status.service';
import { NGXLogger } from 'ngx-logger';
import { getConfig } from '../../services';
@Component({
templateUrl: './tenant-select.component.html',
@ -18,9 +18,8 @@ import { getConfig } from '../../services';
export class TenantSelectComponent {
protected readonly baseHref = inject(BASE_HREF);
protected readonly logger = inject(NGXLogger);
protected readonly storedTenants = inject(TenantsService)
.getStoredTenants()
.sort((a, b) => a.tenantId.localeCompare(b.tenantId));
protected readonly tenantsService = inject(TenantsService);
protected storedTenants: IStoredTenantId[] = [];
protected readonly titleService = inject(Title);
protected readonly config = getConfig();
protected readonly loadingService = inject(LoadingService);
@ -32,6 +31,10 @@ export class TenantSelectComponent {
});
@Input() isLoggedOut = false;
constructor() {
this.#loadStoredTenants();
}
updateTenantSelection() {
const tenantId = this.form.controls.tenantId.value;
if (!tenantId) {
@ -39,12 +42,10 @@ export class TenantSelectComponent {
}
this.loadingService.start();
const email = this.#getEmail(tenantId);
return this.select(tenantId, email);
return this.select(tenantId);
}
async select(tenantId: string, email?: string) {
async select(tenantId: string) {
try {
this.logger.info('[KEYCLOAK] Initializing keycloak for tenant', tenantId);
await this.keycloakService.init(getKeycloakOptions(this.baseHref, this.config, tenantId));
@ -55,15 +56,18 @@ export class TenantSelectComponent {
const url = this.keycloakService.getKeycloakInstance().createLoginUrl({
redirectUri: this.keycloakStatusService.createLoginUrl(tenantId),
idpHint: this.config.OAUTH_IDP_HINT,
loginHint: email ?? undefined,
});
this.logger.info('[KEYCLOAK] Init succeeded. Logout and redirect to', url);
return this.keycloakService.logout(url);
}
#getEmail(tenantId: string) {
const existingStored = this.storedTenants.filter(s => s.tenantId === tenantId);
return existingStored.length === 1 ? existingStored[0].email : undefined;
removeStored(tenantId: string) {
this.tenantsService.removeStored(tenantId);
this.#loadStoredTenants();
}
#loadStoredTenants() {
this.storedTenants = this.tenantsService.getStoredTenants().sort((a, b) => a.tenantId.localeCompare(b.tenantId));
}
}

View File

@ -1,20 +1,21 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDialogModule } from '@angular/material/dialog';
import { CircleButtonComponent, IconButtonComponent } from '../buttons';
import { TenantSelectComponent } from './tenant-select/tenant-select.component';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { ReactiveFormsModule } from '@angular/forms';
import { TenantIdInterceptor, TenantIdResponseInterceptor } from './services';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { MatCardModule } from '@angular/material/card';
import { RouterLink } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { CircleButtonComponent, IconButtonComponent } from '../buttons';
import { StopPropagationDirective } from '../directives';
import { LogoComponent } from '../shared';
import { SpacerComponent } from '../shared/spacer/spacer.component';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { RouterLink } from '@angular/router';
import { TenantIdInterceptor, TenantIdResponseInterceptor } from './services';
import { TenantSelectComponent } from './tenant-select/tenant-select.component';
@NgModule({
declarations: [TenantSelectComponent],
@ -33,6 +34,7 @@ import { RouterLink } from '@angular/router';
MatIconModule,
MatButtonModule,
RouterLink,
StopPropagationDirective,
],
exports: [TenantSelectComponent],
})