Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/177493 create user store #1568

Merged
merged 5 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
10 changes: 5 additions & 5 deletions src/app/base/core.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoggerTestingModule } from 'ngx-logger/testing';

import { Injector, PLATFORM_ID } from '@angular/core';
import { Injector, PLATFORM_ID, signal } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { REQUEST, RESPONSE } from '../../express.tokens';

import { EmptyMockComponent, SERVER_REQUEST, SERVER_RESPONSE } from '@tests/app.mocks';

import { AppInjector, CoreModule } from '@modules/core';
import { AuthenticationStore, StoresModule } from '@modules/stores';
import { CtxStore, StoresModule } from '@modules/stores';

import { CoreComponent } from './core.component';

Expand Down Expand Up @@ -108,7 +108,7 @@ describe('App/Base/CoreComponent running CLIENT side', () => {
let router: Router;
let routerSpy: jest.SpyInstance;

let authenticationStore: AuthenticationStore;
let ctx: CtxStore;

let component: CoreComponent;
let fixture: ComponentFixture<CoreComponent>;
Expand All @@ -131,7 +131,7 @@ describe('App/Base/CoreComponent running CLIENT side', () => {
router = TestBed.inject(Router);
routerSpy = jest.spyOn(router, 'navigate');

authenticationStore = TestBed.inject(AuthenticationStore);
ctx = TestBed.inject(CtxStore);
});

it('should create the component', () => {
Expand Down Expand Up @@ -231,7 +231,7 @@ describe('App/Base/CoreComponent running CLIENT side', () => {
// }));

it(`should run userUrlBasePath()`, () => {
authenticationStore.userUrlBasePath = () => 'innovator';
ctx.user.userUrlBasePath = signal('innovator');

fixture = TestBed.createComponent(CoreComponent);
component = fixture.componentInstance;
Expand Down
14 changes: 3 additions & 11 deletions src/app/base/core.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { REQUEST, RESPONSE } from '../../express.tokens';
import { AppInjector } from '@modules/core/injectors/app-injector';

import { EnvironmentVariablesStore } from '@modules/core/stores/environment-variables.store';
import { AuthenticationStore } from '@modules/stores/authentication/authentication.store';

import { AlertType, LinkType, MappedObjectType } from '@modules/core/interfaces/base.interfaces';
import { URLS } from './constants';
Expand Down Expand Up @@ -50,10 +49,6 @@ export class CoreComponent implements OnDestroy {
URLS: typeof URLS;
};

protected stores: {
authentication: AuthenticationStore;
};

protected ctx: CtxStore;

protected subscriptions: Subscription[] = [];
Expand Down Expand Up @@ -91,10 +86,6 @@ export class CoreComponent implements OnDestroy {
URLS: URLS
};

this.stores = {
authentication: injector.get(AuthenticationStore)
};

this.ctx = injector.get(CtxStore);

this.ctx.layout.setCurrentUrl(this.location.path());
Expand Down Expand Up @@ -190,7 +181,7 @@ export class CoreComponent implements OnDestroy {

// If no url is provided, use the previous url or default to the dashboard to avoid getting out of the app.
if (!urlOrCallback) {
urlOrCallback = this.ctx.layout.previousUrl() ?? `/${this.stores.authentication.userUrlBasePath()}/dashboard`;
urlOrCallback = this.ctx.layout.previousUrl() ?? `/${this.ctx.user.userUrlBasePath()}/dashboard`;
}

this.ctx.layout.update({ backLink: { label, callback: urlOrCallback, hiddenLabel } });
Expand Down Expand Up @@ -264,8 +255,9 @@ export class CoreComponent implements OnDestroy {
// }
// }

// TODO: this could return a signal or be a computed from the store
userUrlBasePath(): string {
return this.stores.authentication.userUrlBasePath();
return this.ctx.user.userUrlBasePath();
}

redirectTo(url: string, queryParams: MappedObjectType = {}): void {
Expand Down
20 changes: 10 additions & 10 deletions src/app/base/core.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { LoggerTestingModule } from 'ngx-logger/testing';

import { Injector } from '@angular/core';
import { Injector, signal } from '@angular/core';

import { AppInjector, CoreModule } from '@modules/core';
import { AuthenticationStore, StoresModule } from '@modules/stores';
import { CtxStore, StoresModule } from '@modules/stores';

import { UserRoleEnum } from './enums';

import { CoreService } from './core.service';

describe('App/Base/CoreService', () => {
let authenticationStore: AuthenticationStore;
let ctx: CtxStore;

let service: CoreService;

Expand All @@ -24,7 +24,7 @@ describe('App/Base/CoreService', () => {

AppInjector.setInjector(TestBed.inject(Injector));

authenticationStore = TestBed.inject(AuthenticationStore);
ctx = TestBed.inject(CtxStore);

service = TestBed.inject(CoreService);
});
Expand All @@ -34,28 +34,28 @@ describe('App/Base/CoreService', () => {
});

it(`should run apiUserBasePath() as Admin`, () => {
authenticationStore.getUserType = () => UserRoleEnum.ADMIN;
ctx.user.getUserType = signal(UserRoleEnum.ADMIN);
expect(service.apiUserBasePath()).toBe('user-admin');
});
it(`should run apiUserBasePath() as NA`, () => {
authenticationStore.getUserType = () => UserRoleEnum.ASSESSMENT;
ctx.user.getUserType = signal(UserRoleEnum.ASSESSMENT);
expect(service.apiUserBasePath()).toBe('assessments');
});
it(`should run apiUserBasePath() as Accessor`, () => {
authenticationStore.getUserType = () => UserRoleEnum.ACCESSOR;
ctx.user.getUserType = signal(UserRoleEnum.ACCESSOR);
expect(service.apiUserBasePath()).toBe('accessors');
});
it(`should run apiUserBasePath() as Innovator`, () => {
authenticationStore.getUserType = () => UserRoleEnum.INNOVATOR;
ctx.user.getUserType = signal(UserRoleEnum.INNOVATOR);
expect(service.apiUserBasePath()).toBe('innovators');
});
it(`should run apiUserBasePath() as nothing`, () => {
authenticationStore.getUserType = () => undefined;
ctx.user.getUserType = signal(undefined);
expect(service.apiUserBasePath()).toBe('');
});

it(`should run userUrlBasePath()`, () => {
authenticationStore.userUrlBasePath = () => 'innovator';
ctx.user.userUrlBasePath = signal('innovator');

expect(service.userUrlBasePath()).toBe('innovator');
});
Expand Down
17 changes: 4 additions & 13 deletions src/app/base/core.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import { NGXLogger } from 'ngx-logger';
import { AppInjector } from '@modules/core/injectors/app-injector';

import { EnvironmentVariablesStore } from '@modules/core/stores/environment-variables.store';
import { AuthenticationStore } from '@modules/stores/authentication/authentication.store';
import { UserRoleEnum } from '@modules/stores/authentication/authentication.enums';
import { ContextLayoutType, CtxStore } from '@modules/stores';
import { ContextLayoutType, CtxStore, UserRoleEnum } from '@modules/stores';

@Injectable()
export class CoreService {
Expand All @@ -18,10 +16,6 @@ export class CoreService {
protected translateService: TranslateService;
protected logger: NGXLogger;

protected stores: {
authentication: AuthenticationStore;
};

protected ctx: CtxStore;

protected APP_URL: string;
Expand All @@ -38,10 +32,6 @@ export class CoreService {
this.translateService = injector.get(TranslateService);
this.logger = injector.get(NGXLogger);

this.stores = {
authentication: injector.get(AuthenticationStore)
};

this.ctx = injector.get(CtxStore);
this.APP_URL = this.envVariablesStore.APP_URL;
this.API_URL = this.envVariablesStore.API_URL;
Expand All @@ -60,7 +50,7 @@ export class CoreService {
}

apiUserBasePath(): string {
switch (this.stores.authentication.getUserType()) {
switch (this.ctx.user.getUserType()) {
case UserRoleEnum.ADMIN:
return 'user-admin';
case UserRoleEnum.ASSESSMENT:
Expand All @@ -75,8 +65,9 @@ export class CoreService {
}
}

// TODO: could return a computed from the store
userUrlBasePath(): string {
return this.stores.authentication.userUrlBasePath();
return this.ctx.user.userUrlBasePath();
}

translate(translation: string, params?: object): string {
Expand Down
11 changes: 2 additions & 9 deletions src/app/base/enums.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
// Authentication store.
export {
UserRoleEnum,
InnovatorOrganisationRoleEnum,
AccessorOrganisationRoleEnum
} from '@modules/stores/authentication/authentication.enums';

// Authentication store.
export { TermsOfUseTypeEnum } from '@modules/stores/authentication/authentication.enums';
// Stores
export { UserRoleEnum, TermsOfUseTypeEnum } from '@modules/stores';

// Environment store.
export {
Expand Down
38 changes: 18 additions & 20 deletions src/modules/core/guards/authentication-redirection.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { ActivatedRouteSnapshot, RouterModule, RouterStateSnapshot } from '@angu
import { EmptyMockComponent } from '@tests/app.mocks';

import { CoreModule } from '@modules/core';
import { AuthenticationStore, StoresModule } from '@modules/stores';
import { CtxStore, StoresModule } from '@modules/stores';

import { UserRoleEnum } from '@app/base/enums';

import { PLATFORM_ID } from '@angular/core';
import { PLATFORM_ID, signal } from '@angular/core';
import { AuthenticationRedirectionGuard } from './authentication-redirection.guard';

describe('Core/Guards/AuthenticationRedirectionGuard', () => {
let authenticationStore: AuthenticationStore;
let ctx: CtxStore;

let guard: AuthenticationRedirectionGuard;

Expand All @@ -37,7 +37,7 @@ describe('Core/Guards/AuthenticationRedirectionGuard', () => {
providers: [{ provide: PLATFORM_ID, useValue: 'browser' }]
});

authenticationStore = TestBed.inject(AuthenticationStore);
ctx = TestBed.inject(CtxStore);

guard = TestBed.inject(AuthenticationRedirectionGuard);

Expand All @@ -49,16 +49,16 @@ describe('Core/Guards/AuthenticationRedirectionGuard', () => {
routeConfig: { path: 'terms-of-use' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.INNOVATOR;
authenticationStore.isTermsOfUseAccepted = () => false;
ctx.user.getUserType = signal(UserRoleEnum.INNOVATOR);
ctx.user.isTermsOfUseAccepted = signal(false);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});

it('should deny access and redirect when user type is empty or path is empty', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => undefined;
ctx.user.getUserType = signal(undefined);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});

Expand All @@ -67,31 +67,31 @@ describe('Core/Guards/AuthenticationRedirectionGuard', () => {
routeConfig: { path: 'dashboard' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ASSESSMENT;
ctx.user.getUserType = signal(UserRoleEnum.ASSESSMENT);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is ACCESSOR', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'dashboard' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ACCESSOR;
ctx.user.getUserType = signal(UserRoleEnum.ACCESSOR);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is INNOVATOR', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'dashboard' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.INNOVATOR;
ctx.user.getUserType = signal(UserRoleEnum.INNOVATOR);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is ADMIN', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'dashboard' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ADMIN;
ctx.user.getUserType = signal(UserRoleEnum.ADMIN);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});

Expand All @@ -100,31 +100,31 @@ describe('Core/Guards/AuthenticationRedirectionGuard', () => {
routeConfig: { path: 'innovator' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ASSESSMENT;
ctx.user.getUserType = signal(UserRoleEnum.ASSESSMENT);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is ACCESSOR', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'innovator' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ACCESSOR;
ctx.user.getUserType = signal(UserRoleEnum.ACCESSOR);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is INNOVATOR', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'accessor' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.INNOVATOR;
ctx.user.getUserType = signal(UserRoleEnum.INNOVATOR);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});
it('should deny access and redirect when user type is ADMIN', () => {
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
routeConfig: { path: 'innovator' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.ADMIN;
ctx.user.getUserType = signal(UserRoleEnum.ADMIN);
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(false);
});

Expand All @@ -133,11 +133,9 @@ describe('Core/Guards/AuthenticationRedirectionGuard', () => {
routeConfig: { path: 'innovator' },
queryParams: { dismissNotification: undefined }
};
authenticationStore.getUserType = () => UserRoleEnum.INNOVATOR;
authenticationStore.isTermsOfUseAccepted = () => true;
authenticationStore.getUserContextInfo = () => {
return { id: 'userId', roleId: 'id', type: UserRoleEnum.INNOVATOR };
};
ctx.user.getUserType = signal(UserRoleEnum.INNOVATOR);
ctx.user.isTermsOfUseAccepted = signal(true);
ctx.user.getUserContext = signal({ id: 'userId', roleId: 'id', type: UserRoleEnum.INNOVATOR });
expect(guard.canActivate(activatedRouteSnapshotMock as any, routerStateSnapshopMock as any)).toBe(true);
});
});
Loading