feat(authorization): Implemented guards to avoid unauthorized access. (TV-515)

Squashed commit of the following:

commit 86aa3af3f54be4ef5bfb99baece6654a7fba204f
Merge: f3258e8 1e45fb5
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Thu Sep 9 05:42:46 2021 +0200

    Merge branch 'develop' into feature/TV-515-authorization-flow

commit f3258e8c6e3d51f21ec619e09c82b2d0f581bde9
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 16:43:44 2021 +0200

    Fixed tests

commit 91bfea1baa297f34769a33972fd61481dfa31197
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 15:55:13 2021 +0200

    Removed unused pages

commit d4a92fbde9d6255d8406abc23fe1479658035787
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 15:51:25 2021 +0200

    Updated some styling

commit dc75656ff96ff0358a2dd0a8b090b4b4938b8323
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 15:35:04 2021 +0200

    Refactured guards by separating organizations into its own guard

commit 24f3a0a2d821930bd682b854f98e1c9816ece08c
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 15:33:53 2021 +0200

    Readded search on employees

commit f1890b104c48d6dd6e263b730dbdafbc2a6fbf0f
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 14:59:24 2021 +0200

    Added RoleGuard to pages needing a guard

commit ef4b37e3dcc8fe26eef1bb813cfb35727ba691be
Merge: 07bca2a b06436a
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 14:06:34 2021 +0200

    Merge branch 'develop' into feature/TV-515-authorization-flow

commit 07bca2a84d0ec970188c284ba4b950312cec57cb
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Sep 8 13:26:50 2021 +0200

    Added check for navigation
This commit is contained in:
Erik Tiekstra
2021-09-09 06:13:17 +02:00
parent 1e45fb5da5
commit c984912a87
49 changed files with 266 additions and 263 deletions

View File

@@ -71,7 +71,7 @@
}
&__edit-button {
@include msfa-button('secondary');
@include msfa__button('secondary');
}
&__authorization-icon {

View File

@@ -140,7 +140,7 @@
(afOnPrimaryClick)="onFormSubmitted(true)"
(afOnSecondaryClick)="abortFormSubmit()"
(afOnInactive)="abortFormSubmit()"
afHeading="Är du säker"
afHeading="Är du säker?"
afHeadingLevel="h2"
afPrimaryButtonText="Ja, spara ändå"
afSecondaryButtonText="Nej, gå tillbaka"

View File

@@ -47,7 +47,7 @@
}
&__link-btn {
@include msfa-button('secondary');
@include msfa__button('secondary');
}
&__choose-all-utforande-verksamheter {

View File

@@ -20,11 +20,11 @@
<h2>Personallista</h2>
<form class="employees__search-wrapper" (ngSubmit)="setSearchFilter()">
<!-- <digi-form-input-search
af-label="Sök personal"
af-label-description="Sök på namn"
<digi-form-input-search
af-label="Sök personalens namn"
(afOnInput)="setSearchValue($event)"
></digi-form-input-search> -->
></digi-form-input-search>
<digi-form-checkbox
class="employees__only-employees-without-authorization"
af-label="Visa endast personal utan behörigheter"

View File

@@ -12,6 +12,7 @@
&__search-wrapper {
display: flex;
flex-direction: column;
gap: $digi--layout--gutter--l;
max-width: var(--digi--typography--text--max-width);
margin-bottom: $digi--layout--gutter--xl;
}

View File

@@ -1,3 +0,0 @@
<msfa-layout>
<section class="messages">Meddelanden funkar!</section>
</msfa-layout>

View File

@@ -1,29 +0,0 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { LayoutComponent } from '@msfa-shared/components/layout/layout.component';
import { MessagesComponent } from './messages.component';
describe('MessagesComponent', () => {
let component: MessagesComponent;
let fixture: ComponentFixture<MessagesComponent>;
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [MessagesComponent, LayoutComponent],
imports: [RouterTestingModule, HttpClientTestingModule],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(MessagesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,9 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'msfa-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MessagesComponent {}

View File

@@ -1,11 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { MessagesComponent } from './messages.component';
@NgModule({
declarations: [MessagesComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: MessagesComponent }]), LayoutModule],
})
export class MessagesModule {}

View File

@@ -1,9 +1,29 @@
<msfa-layout>
<digi-typography>
<section class="my-account">
<h1>Mitt konto</h1>
<header class="my-account__header">
<h1>Mitt konto</h1>
<a class="my-account__logout" routerLink="/logga-ut">
<msfa-icon [icon]="IconType.LOGOUT"></msfa-icon>
Logga ut
</a>
</header>
<digi-ng-link-internal afText="Logga ut" afRoute="/logga-ut"></digi-ng-link-internal>
<main *ngIf="user$ | async as user; else loadingRef">
<p>Här kan du se dina uppgifter.</p>
<h2>Mina roller</h2>
<ul class="my-account__roles">
<li class="my-account__role" *ngFor="let role of user.roles">
<digi-icon-check-circle class="msfa__digi-icon my-account__authorization-icon"></digi-icon-check-circle>
{{role.name}}
</li>
</ul>
</main>
</section>
</digi-typography>
</msfa-layout>
<ng-template #loadingRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar kontoinformation"></digi-ng-skeleton-base>
</ng-template>

View File

@@ -0,0 +1,32 @@
@import 'mixins/buttons';
@import 'mixins/list';
@import 'variables/gutters';
.my-account {
&__header {
display: flex;
justify-content: space-between;
align-items: center;
}
&__logout {
@include msfa__button('secondary');
}
&__roles {
@include msfa__reset-list;
display: flex;
flex-direction: column;
gap: $digi--layout--gutter--s;
}
&__role {
display: flex;
align-items: center;
gap: $digi--layout--gutter--s;
}
&__authorization-icon {
color: var(--digi--ui--color--border--success);
}
}

View File

@@ -1,5 +1,7 @@
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { MyAccountComponent } from './my-account.component';
describe('MyAccountComponent', () => {
@@ -9,8 +11,9 @@ describe('MyAccountComponent', () => {
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [MyAccountComponent],
imports: [HttpClientTestingModule, RouterTestingModule],
}).compileComponents();
})
);

View File

@@ -1,4 +1,8 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconType } from '@msfa-enums/icon-type.enum';
import { User } from '@msfa-models/user.model';
import { UserService } from '@msfa-services/api/user.service';
import { Observable } from 'rxjs';
@Component({
selector: 'msfa-my-account',
@@ -6,4 +10,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
styleUrls: ['./my-account.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyAccountComponent {}
export class MyAccountComponent {
user$: Observable<User> = this.userService.user$;
readonly IconType = IconType;
constructor(private userService: UserService) {}
}

View File

@@ -1,7 +1,8 @@
import { DigiNgLinkInternalModule } from '@af/digi-ng/_link/link-internal';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { IconModule } from '@msfa-shared/components/icon/icon.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { MyAccountComponent } from './my-account.component';
@@ -12,7 +13,8 @@ import { MyAccountComponent } from './my-account.component';
CommonModule,
RouterModule.forChild([{ path: '', component: MyAccountComponent }]),
LayoutModule,
DigiNgLinkInternalModule,
IconModule,
DigiNgSkeletonBaseModule,
],
})
export class MyAccountModule {}

View File

@@ -5,7 +5,7 @@ import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
import { Organization } from '@msfa-models/organization.model';
import { UserService } from '@msfa-services/api/user.service';
import { Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
@Component({
selector: 'msfa-organization-picker',
@@ -14,9 +14,8 @@ import { filter, map } from 'rxjs/operators';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OrganizationPickerComponent extends UnsubscribeDirective {
organizations$: Observable<Organization[]> = this.userService.user$.pipe(
filter(user => !!(user && user.organizations?.length)),
map(({ organizations }) => organizations)
organizations$: Observable<Organization[]> = this.userService.organizations$.pipe(
filter(organizations => !!organizations?.length)
);
constructor(

View File

@@ -1,3 +0,0 @@
<msfa-layout>
<section class="settings">Inställningar funkar!</section>
</msfa-layout>

View File

@@ -1,29 +0,0 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { LayoutComponent } from '@msfa-shared/components/layout/layout.component';
import { SettingsComponent } from './settings.component';
describe('SettingsComponent', () => {
let component: SettingsComponent;
let fixture: ComponentFixture<SettingsComponent>;
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [SettingsComponent, LayoutComponent],
imports: [RouterTestingModule, HttpClientTestingModule],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(SettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,9 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'msfa-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SettingsComponent {}

View File

@@ -1,11 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { SettingsComponent } from './settings.component';
@NgModule({
declarations: [SettingsComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: SettingsComponent }]), LayoutModule],
})
export class SettingsModule {}

View File

@@ -1,3 +0,0 @@
<msfa-layout>
<section class="statistics">Statistik funkar!</section>
</msfa-layout>

View File

@@ -1,29 +0,0 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { LayoutComponent } from '@msfa-shared/components/layout/layout.component';
import { StatisticsComponent } from './statistics.component';
describe('StatisticsComponent', () => {
let component: StatisticsComponent;
let fixture: ComponentFixture<StatisticsComponent>;
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [StatisticsComponent, LayoutComponent],
imports: [RouterTestingModule, HttpClientTestingModule],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(StatisticsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,9 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'msfa-statistics',
templateUrl: './statistics.component.html',
styleUrls: ['./statistics.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StatisticsComponent {}

View File

@@ -1,11 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { StatisticsComponent } from './statistics.component';
@NgModule({
declarations: [StatisticsComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: StatisticsComponent }]), LayoutModule],
})
export class StatisticsModule {}