feat(login): Added auth-guard to avoid unauthorized access
Squashed commit of the following:
commit c8f20f6ff0dee2257a4191d8e6771ed2fc364326
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 12:04:40 2021 +0200
Removed current from currentUser and currentToken/currentExpiration
commit fef6b046861efe8cfacb5b5b1e9dbb86bff42336
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 10:42:27 2021 +0200
Fixed some tests
commit f357546d3a61ad66d804a7cb36807985c8435974
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 09:41:47 2021 +0200
Fixed linting
commit 85fdbaed8d922bec235e4987cc34464c1419a093
Merge: c93dd92 c06452d
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 09:29:55 2021 +0200
Merged develop and resolved conflicts
commit c93dd925b06a0b8a0361a687165e9c3954e2050b
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 07:43:57 2021 +0200
Moved some components to shared folder
commit aa1cc2b6240236149b0367363d4175fbdacf94dc
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Jun 30 07:32:28 2021 +0200
Removed comments and some unused code
commit 7b83eb9d9d368b7466189ab3588fa91697db49c0
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Tue Jun 29 14:56:02 2021 +0200
Login-flow now works locally and against API
commit dab5a76f2b6e24447d85e237233053a3f23b1b39
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Tue Jun 29 12:50:24 2021 +0200
Adjusted login-functionality to use a guard
This commit is contained in:
@@ -104,8 +104,8 @@
|
|||||||
"browserTarget": "dafa-web:build:production"
|
"browserTarget": "dafa-web:build:production"
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
"proxyConfig": "./config/proxy.conf.api.json",
|
"browserTarget": "dafa-web:build:api",
|
||||||
"browserTarget": "dafa-web:build:api"
|
"proxyConfig": "./config/proxy.conf.api.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,56 +1,60 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
|
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
|
||||||
import { environment } from '@dafa-environment';
|
import { environment } from '@dafa-environment';
|
||||||
|
import { AuthGuard } from '@dafa-guards/auth.guard';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
data: { title: '' },
|
data: { title: '' },
|
||||||
loadChildren: () => import('./pages/start/start.module').then(m => m.StartModule),
|
loadChildren: () => import('./pages/start/start.module').then(m => m.StartModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'administration',
|
path: 'administration',
|
||||||
data: { title: 'Administration' },
|
data: { title: 'Administration' },
|
||||||
loadChildren: () => import('./pages/administration/administration.module').then(m => m.AdministrationModule),
|
loadChildren: () => import('./pages/administration/administration.module').then(m => m.AdministrationModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'deltagare',
|
path: 'deltagare',
|
||||||
data: { title: 'Deltagare' },
|
data: { title: 'Deltagare' },
|
||||||
loadChildren: () => import('./pages/participants/participants.module').then(m => m.ParticipantsModule),
|
loadChildren: () => import('./pages/participants/participants.module').then(m => m.ParticipantsModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'avrop',
|
path: 'avrop',
|
||||||
data: { title: 'Avrop' },
|
data: { title: 'Avrop' },
|
||||||
loadChildren: () => import('./pages/avrop/avrop.module').then(m => m.AvropModule),
|
loadChildren: () => import('./pages/avrop/avrop.module').then(m => m.AvropModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'meddelanden',
|
path: 'meddelanden',
|
||||||
data: { title: 'Meddelanden' },
|
data: { title: 'Meddelanden' },
|
||||||
loadChildren: () => import('./pages/messages/messages.module').then(m => m.MessagesModule),
|
loadChildren: () => import('./pages/messages/messages.module').then(m => m.MessagesModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'statistik',
|
path: 'statistik',
|
||||||
data: { title: 'Statistik' },
|
data: { title: 'Statistik' },
|
||||||
loadChildren: () => import('./pages/statistics/statistics.module').then(m => m.StatisticsModule),
|
loadChildren: () => import('./pages/statistics/statistics.module').then(m => m.StatisticsModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'installningar',
|
path: 'installningar',
|
||||||
data: { title: 'Inställningar' },
|
data: { title: 'Inställningar' },
|
||||||
loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsModule),
|
loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'releases',
|
path: 'releases',
|
||||||
data: { title: 'Releases' },
|
data: { title: 'Releases' },
|
||||||
loadChildren: () => import('./pages/releases/releases.module').then(m => m.ReleasesModule),
|
loadChildren: () => import('./pages/releases/releases.module').then(m => m.ReleasesModule),
|
||||||
},
|
canActivate: [AuthGuard],
|
||||||
{
|
|
||||||
path: 'ciam-landing',
|
|
||||||
data: { title: 'Ciam landing page' },
|
|
||||||
loadChildren: () => import('./pages/ciam-landing/ciam-landing.module').then(m => m.CiamLandingModule),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'logout',
|
path: 'logout',
|
||||||
data: { title: 'Ciam landing page' },
|
data: { title: 'Logga ut' },
|
||||||
loadChildren: () => import('./pages/logout/logout.module').then(m => m.LogoutModule),
|
loadChildren: () => import('./pages/logout/logout.module').then(m => m.LogoutModule),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -67,6 +71,7 @@ routes.push({
|
|||||||
path: '**',
|
path: '**',
|
||||||
data: { title: 'Sidan hittas inte' },
|
data: { title: 'Sidan hittas inte' },
|
||||||
loadChildren: () => import('./pages/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule),
|
loadChildren: () => import('./pages/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule),
|
||||||
|
canActivate: [AuthGuard],
|
||||||
});
|
});
|
||||||
|
|
||||||
const options: ExtraOptions = {
|
const options: ExtraOptions = {
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
||||||
|
<dafa-toast-list></dafa-toast-list>
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { NavigationModule } from './components/navigation/navigation.module';
|
|
||||||
import { SidebarModule } from './components/sidebar/sidebar.module';
|
|
||||||
import { SkipToContentModule } from './components/skip-to-content/skip-to-content.module';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
imports: [RouterTestingModule, HttpClientTestingModule, SkipToContentModule, NavigationModule, SidebarModule],
|
imports: [RouterTestingModule, HttpClientTestingModule],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|||||||
styleUrls: ['./app.component.scss'],
|
styleUrls: ['./app.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,42 +1,24 @@
|
|||||||
import { DigiNgNavigationBreadcrumbsModule } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
|
|
||||||
import { ErrorHandler, NgModule } from '@angular/core';
|
import { ErrorHandler, NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { RouterModule } from '@angular/router';
|
import { AuthGuard } from '@dafa-guards/auth.guard';
|
||||||
import { CustomErrorHandler } from '@dafa-interceptors/custom-error-handler.module';
|
import { CustomErrorHandler } from '@dafa-interceptors/custom-error-handler.module';
|
||||||
import { MarkdownModule } from 'ngx-markdown';
|
import { AuthInterceptor } from '@dafa-services/api/auth.interceptor';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { FooterModule } from './components/footer/footer.module';
|
|
||||||
import { NavigationModule } from './components/navigation/navigation.module';
|
|
||||||
import { SidebarModule } from './components/sidebar/sidebar.module';
|
|
||||||
import { SkipToContentModule } from './components/skip-to-content/skip-to-content.module';
|
|
||||||
import { ToastListModule } from './components/toast-list/toast-list.module';
|
import { ToastListModule } from './components/toast-list/toast-list.module';
|
||||||
import { AuthInterceptor } from '@dafa-services/api/auth.interceptor';
|
|
||||||
import { AvropModule } from './pages/avrop/avrop.module';
|
import { AvropModule } from './pages/avrop/avrop.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
imports: [
|
imports: [BrowserModule, HttpClientModule, AppRoutingModule, ToastListModule, AvropModule],
|
||||||
BrowserModule,
|
|
||||||
HttpClientModule,
|
|
||||||
AppRoutingModule,
|
|
||||||
RouterModule,
|
|
||||||
SkipToContentModule,
|
|
||||||
NavigationModule,
|
|
||||||
SidebarModule,
|
|
||||||
ToastListModule,
|
|
||||||
FooterModule,
|
|
||||||
MarkdownModule.forRoot({ loader: HttpClient }),
|
|
||||||
DigiNgNavigationBreadcrumbsModule,
|
|
||||||
AvropModule,
|
|
||||||
],
|
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: ErrorHandler,
|
provide: ErrorHandler,
|
||||||
useClass: CustomErrorHandler,
|
useClass: CustomErrorHandler,
|
||||||
},
|
},
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
|
||||||
|
AuthGuard,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { LoggedInShellComponent } from './logged-in-shell.component';
|
|
||||||
import { SkipToContentModule } from '../skip-to-content/skip-to-content.module';
|
|
||||||
import { NavigationModule } from '../navigation/navigation.module';
|
|
||||||
import { SidebarModule } from '../sidebar/sidebar.module';
|
|
||||||
import { DigiNgNavigationBreadcrumbsModule } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
|
||||||
import { FooterModule } from '../footer/footer.module';
|
|
||||||
import { ToastListModule } from '../toast-list/toast-list.module';
|
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
RouterModule,
|
|
||||||
CommonModule,
|
|
||||||
SkipToContentModule,
|
|
||||||
NavigationModule,
|
|
||||||
SidebarModule,
|
|
||||||
DigiNgNavigationBreadcrumbsModule,
|
|
||||||
FooterModule,
|
|
||||||
ToastListModule,
|
|
||||||
],
|
|
||||||
declarations: [LoggedInShellComponent],
|
|
||||||
exports: [LoggedInShellComponent],
|
|
||||||
})
|
|
||||||
export class LoggedInShellModule {}
|
|
||||||
@@ -1,15 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
export interface AuthenticationResult {
|
export interface AuthenticationResult {
|
||||||
idToken: string;
|
idToken: string;
|
||||||
expiresIn: number;
|
expiresIn: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthenticationApiResponse {
|
export interface AuthenticationApiResponse {
|
||||||
data: AuthenticationApiResponseData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AuthenticationApiResponseData {
|
|
||||||
id: string;
|
id: string;
|
||||||
access_token: string;
|
access_token: string;
|
||||||
scope: string;
|
scope: string;
|
||||||
@@ -18,12 +12,10 @@ export interface AuthenticationApiResponseData {
|
|||||||
expires_in: number;
|
expires_in: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapAuthApiResponseToAuthenticationResult(data: AuthenticationApiResponseData): AuthenticationResult {
|
export function mapAuthApiResponseToAuthenticationResult(data: AuthenticationApiResponse): AuthenticationResult {
|
||||||
const {
|
const { id_token, expires_in } = data;
|
||||||
id_token,
|
|
||||||
expires_in } = data;
|
|
||||||
return {
|
return {
|
||||||
idToken: id_token,
|
idToken: id_token,
|
||||||
expiresIn: expires_in
|
expiresIn: expires_in,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
30
apps/dafa-web/src/app/guards/auth.guard.ts
Normal file
30
apps/dafa-web/src/app/guards/auth.guard.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||||
|
import { environment } from '@dafa-environment';
|
||||||
|
import { AuthenticationService } from '@dafa-services/api/authentication.service';
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthGuard implements CanActivate {
|
||||||
|
constructor(private authenticationService: AuthenticationService, private router: Router) {}
|
||||||
|
|
||||||
|
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
|
||||||
|
return this.authenticationService.isLoggedIn$.pipe(
|
||||||
|
switchMap(loggedIn => {
|
||||||
|
if (loggedIn) {
|
||||||
|
return of(true);
|
||||||
|
} else if (route.queryParams.code) {
|
||||||
|
return this.authenticationService.login$(route.queryParams.code).pipe(map(result => !!result));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environment.environment === 'local') {
|
||||||
|
void this.router.navigateByUrl(environment.loginUrl);
|
||||||
|
} else {
|
||||||
|
document.location.href = `${environment.loginUrl}&client_id=${environment.clientId}&redirect_uri=${environment.redirectUri}`;
|
||||||
|
}
|
||||||
|
return of(false);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="employee-card">
|
<section class="employee-card">
|
||||||
<digi-typography *ngIf="detailedEmployeeData$ | async as detailedEmployeeData; else loadingRef">
|
<digi-typography *ngIf="detailedEmployeeData$ | async as detailedEmployeeData; else loadingRef">
|
||||||
<div class="employee-card__editcontainer">
|
<div class="employee-card__editcontainer">
|
||||||
@@ -90,4 +90,4 @@
|
|||||||
<span class="dafa__a11y-sr-only">Info saknas</span>
|
<span class="dafa__a11y-sr-only">Info saknas</span>
|
||||||
</dd>
|
</dd>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { HideTextModule } from '@dafa-shared/components/hide-text/hide-text.module';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { LocalDatePipeModule } from '@dafa-shared/pipes/local-date/local-date.module';
|
import { LocalDatePipeModule } from '@dafa-shared/pipes/local-date/local-date.module';
|
||||||
import { EmployeeCardComponent } from './employee-card.component';
|
import { EmployeeCardComponent } from './employee-card.component';
|
||||||
import { LoggedInShellModule } from '../../../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
import { HideTextModule } from '@dafa-shared/components/hide-text/hide-text.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -14,11 +14,11 @@ import { HideTextModule } from '@dafa-shared/components/hide-text/hide-text.modu
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: EmployeeCardComponent }]),
|
RouterModule.forChild([{ path: '', component: EmployeeCardComponent }]),
|
||||||
|
LayoutModule,
|
||||||
DigiNgSkeletonBaseModule,
|
DigiNgSkeletonBaseModule,
|
||||||
DigiNgLayoutExpansionPanelModule,
|
DigiNgLayoutExpansionPanelModule,
|
||||||
LocalDatePipeModule,
|
LocalDatePipeModule,
|
||||||
HideTextModule,
|
HideTextModule,
|
||||||
LoggedInShellModule
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class EmployeeCardModule {}
|
export class EmployeeCardModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="employee-form">
|
<section class="employee-form">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h1>Skapa nytt konto</h1>
|
<h1>Skapa nytt konto</h1>
|
||||||
@@ -87,8 +87,10 @@
|
|||||||
</digi-typography>
|
</digi-typography>
|
||||||
|
|
||||||
<ul class="employee-form__authorizations">
|
<ul class="employee-form__authorizations">
|
||||||
<li *ngFor="let authorization of authorizations; let first = first"
|
<li
|
||||||
class="employee-form__authorization-item">
|
*ngFor="let authorization of authorizations; let first = first"
|
||||||
|
class="employee-form__authorization-item"
|
||||||
|
>
|
||||||
<digi-form-checkbox
|
<digi-form-checkbox
|
||||||
class="employee-form__digi-checkbox"
|
class="employee-form__digi-checkbox"
|
||||||
[afId]="(first && 'employee-form-authorizations') || undefined"
|
[afId]="(first && 'employee-form-authorizations') || undefined"
|
||||||
@@ -99,9 +101,13 @@
|
|||||||
[afChecked]="authorizationsControl.value.includes(authorization)"
|
[afChecked]="authorizationsControl.value.includes(authorization)"
|
||||||
(afOnChange)="toggleAuthorization(authorization, $event.detail.target.checked)"
|
(afOnChange)="toggleAuthorization(authorization, $event.detail.target.checked)"
|
||||||
></digi-form-checkbox>
|
></digi-form-checkbox>
|
||||||
<digi-button af-variation="secondary" [afAriaLabel]="'Läs mer om ' + authorization.name"
|
<digi-button
|
||||||
af-size="s" class="employee-form__read-more"
|
af-variation="secondary"
|
||||||
(afOnClick)="openDialog(true, authorization.name)">
|
[afAriaLabel]="'Läs mer om ' + authorization.name"
|
||||||
|
af-size="s"
|
||||||
|
class="employee-form__read-more"
|
||||||
|
(afOnClick)="openDialog(true, authorization.name)"
|
||||||
|
>
|
||||||
Läs mer
|
Läs mer
|
||||||
</digi-button>
|
</digi-button>
|
||||||
</li>
|
</li>
|
||||||
@@ -117,7 +123,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="employee-form__footer">
|
<div class="employee-form__footer">
|
||||||
<digi-button af-type="reset" af-variation="secondary" (afOnClick)="resetForm($event.detail)">Avbryt</digi-button>
|
<digi-button af-type="reset" af-variation="secondary" (afOnClick)="resetForm($event.detail)"
|
||||||
|
>Avbryt</digi-button
|
||||||
|
>
|
||||||
<digi-button af-type="submit">Registrera konto</digi-button>
|
<digi-button af-type="submit">Registrera konto</digi-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -128,17 +136,15 @@
|
|||||||
(afOnPrimaryClick)="openDialog(false)"
|
(afOnPrimaryClick)="openDialog(false)"
|
||||||
[afHeading]="modalAuthInfo.name"
|
[afHeading]="modalAuthInfo.name"
|
||||||
afHeadingLevel="h3"
|
afHeadingLevel="h3"
|
||||||
afPrimaryButtonText="Stäng">
|
afPrimaryButtonText="Stäng"
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
Behörigheten passar personer som arbetar nära deltagare.
|
Behörigheten passar personer som arbetar nära deltagare. Behörigheten kan användas av exempelvis handledare,
|
||||||
Behörigheten kan användas av exempelvis handledare, coacher, studie- och yrkesvägledare,
|
coacher, studie- och yrkesvägledare, lärare eller annan roll som behöver kunna se information om deltager,
|
||||||
lärare eller annan roll som behöver kunna se information om deltager, kontakta deltagare,
|
kontakta deltagare, planera aktiviteter med deltagre och hantera rapporter för deltagre.
|
||||||
planera aktiviteter med deltagre och hantera rapporter för deltagre.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>Behörigheten ger tillgång till och utföra aktiviteter i följande funktioner i systemet:</p>
|
||||||
Behörigheten ger tillgång till och utföra aktiviteter i följande funktioner i systemet:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
- Deltagarlista <br />
|
- Deltagarlista <br />
|
||||||
@@ -155,4 +161,4 @@
|
|||||||
</digi-ng-dialog>
|
</digi-ng-dialog>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||||
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
|
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
|
||||||
import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
||||||
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
||||||
@@ -8,10 +9,9 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { LocalDatePipeModule } from '@dafa-shared/pipes/local-date/local-date.module';
|
import { LocalDatePipeModule } from '@dafa-shared/pipes/local-date/local-date.module';
|
||||||
import { EmployeeFormComponent } from './employee-form.component';
|
import { EmployeeFormComponent } from './employee-form.component';
|
||||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
|
||||||
import { LoggedInShellModule } from '../../../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -19,6 +19,7 @@ import { LoggedInShellModule } from '../../../../components/logged-in-shell/logg
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: EmployeeFormComponent }]),
|
RouterModule.forChild([{ path: '', component: EmployeeFormComponent }]),
|
||||||
|
LayoutModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
LocalDatePipeModule,
|
LocalDatePipeModule,
|
||||||
DigiNgFormInputModule,
|
DigiNgFormInputModule,
|
||||||
@@ -28,7 +29,6 @@ import { LoggedInShellModule } from '../../../../components/logged-in-shell/logg
|
|||||||
DigiNgPopoverModule,
|
DigiNgPopoverModule,
|
||||||
DigiNgFormCheckboxModule,
|
DigiNgFormCheckboxModule,
|
||||||
DigiNgDialogModule,
|
DigiNgDialogModule,
|
||||||
LoggedInShellModule
|
],
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class EmployeeFormModule {}
|
export class EmployeeFormModule {}
|
||||||
|
|||||||
@@ -4,9 +4,13 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" class="employees-list__column-head" *ngFor="let column of columnHeaders">
|
<th scope="col" class="employees-list__column-head" *ngFor="let column of columnHeaders">
|
||||||
<button class="employees-list__sort-button" [id]="'sort-button-' + column" (click)="handleSort(column.key)">
|
<button
|
||||||
|
class="employees-list__sort-button"
|
||||||
|
[attr.id]="'sort-button-' + column.key"
|
||||||
|
(click)="handleSort(column.key)"
|
||||||
|
>
|
||||||
{{column.label}}
|
{{column.label}}
|
||||||
<ng-container *ngIf="sort.key === column">
|
<ng-container *ngIf="sort.key === column.key">
|
||||||
<digi-icon-caret-up
|
<digi-icon-caret-up
|
||||||
class="employees-list__sort-icon"
|
class="employees-list__sort-icon"
|
||||||
*ngIf="sort.order === orderType.ASC"
|
*ngIf="sort.order === orderType.ASC"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="employees">
|
<section class="employees">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h1>Personal</h1>
|
<h1>Personal</h1>
|
||||||
@@ -37,4 +37,4 @@
|
|||||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
|
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</section>
|
</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { EmployeesListModule } from './components/employees-list/employees-list.module';
|
import { EmployeesListModule } from './components/employees-list/employees-list.module';
|
||||||
import { EmployeesComponent } from './employees.component';
|
import { EmployeesComponent } from './employees.component';
|
||||||
import { LoggedInShellModule } from '../../../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -15,12 +15,12 @@ import { LoggedInShellModule } from '../../../../components/logged-in-shell/logg
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: EmployeesComponent }]),
|
RouterModule.forChild([{ path: '', component: EmployeesComponent }]),
|
||||||
|
LayoutModule,
|
||||||
DigiNgLinkInternalModule,
|
DigiNgLinkInternalModule,
|
||||||
DigiNgSkeletonBaseModule,
|
DigiNgSkeletonBaseModule,
|
||||||
EmployeesListModule,
|
EmployeesListModule,
|
||||||
DigiNgLinkButtonModule,
|
DigiNgLinkButtonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
LoggedInShellModule
|
],
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class EmployeesModule {}
|
export class EmployeesModule {}
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="call-off" *ngIf="currentStep$ | async; let currentStep; else loadingRef">
|
<section class="call-off" *ngIf="currentStep$ | async; let currentStep; else: loadingRef">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h2>Välj deltagare att tilldela</h2>
|
<h2>Välj deltagare att tilldela</h2>
|
||||||
<p>Steg {{ currentStep }} av {{ steps }}:</p>
|
<p>Steg {{ currentStep }} av {{ steps }}:</p>
|
||||||
</digi-typography>
|
</digi-typography>
|
||||||
<digi-ng-progress-progressbar
|
<digi-ng-progress-progressbar [afSteps]="steps" afAriaLabel="An aria label" [afActiveStep]="currentStep">
|
||||||
[afSteps]="steps"
|
|
||||||
afAriaLabel="An aria label"
|
|
||||||
[afActiveStep]="currentStep">
|
|
||||||
</digi-ng-progress-progressbar>
|
</digi-ng-progress-progressbar>
|
||||||
|
|
||||||
<div class="" style="height:300px; padding: 30px 0;">
|
<div class="" style="height: 300px; padding: 30px 0">
|
||||||
<ng-container *ngIf="currentStep == 4">
|
<ng-container *ngIf="currentStep == 4">
|
||||||
<h2>Avropet är sparat</h2>
|
<h2>Avropet är sparat</h2>
|
||||||
<digi-button
|
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="goToStep1()">
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="goToStep1()">
|
|
||||||
Tillbaka till nya deltagare
|
Tillbaka till nya deltagare
|
||||||
</digi-button>
|
</digi-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -39,64 +33,58 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="currentStep == 1">
|
<ng-container *ngIf="currentStep == 1">
|
||||||
<digi-button
|
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="lockSelectedDeltagare()">
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="lockSelectedDeltagare()">
|
|
||||||
Lås deltagare
|
Lås deltagare
|
||||||
</digi-button>
|
</digi-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="currentStep == 2">
|
<ng-container *ngIf="currentStep == 2">
|
||||||
<h2>Välj handledare</h2>
|
<h2>Välj handledare</h2>
|
||||||
<ng-container *ngIf="selectableHandledareList$ | async; let selectableHandledareList; else loadingRefSmall">
|
<ng-container *ngIf="selectableHandledareList$ | async; let selectableHandledareList; else: loadingRefSmall">
|
||||||
<select [value]="(selectedHandledare$ | async)?.id ? (selectedHandledare$ | async)?.id : ''" (change)="changeHandledare($event)">
|
<select
|
||||||
|
[value]="(selectedHandledare$ | async)?.id ? (selectedHandledare$ | async)?.id : ''"
|
||||||
|
(change)="changeHandledare($event)"
|
||||||
|
>
|
||||||
<option disabled value="">Välj handledare</option>
|
<option disabled value="">Välj handledare</option>
|
||||||
|
|
||||||
<option
|
<option *ngFor="let selectableHandledare of selectableHandledareList" [value]="selectableHandledare?.id">
|
||||||
*ngFor="let selectableHandledare of selectableHandledareList"
|
{{ selectableHandledare?.fullName }}
|
||||||
[value]="selectableHandledare?.id"
|
</option>
|
||||||
>{{selectableHandledare?.fullName}}</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<span *ngIf="selectableHandledareList.length === 0">Inga handledare har behörighet till alla markerade deltagare</span>
|
<span *ngIf="selectableHandledareList.length === 0"
|
||||||
|
>Inga handledare har behörighet till alla markerade deltagare</span
|
||||||
|
>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
<br><br>
|
<digi-button
|
||||||
<digi-button af-variation="secondary"
|
af-variation="secondary"
|
||||||
af-size="m"
|
af-size="m"
|
||||||
class="employee-form__read-more"
|
class="employee-form__read-more"
|
||||||
(afOnClick)="unlockSelectedDeltagare()">
|
(afOnClick)="unlockSelectedDeltagare()"
|
||||||
|
>
|
||||||
Tillbaka
|
Tillbaka
|
||||||
</digi-button>
|
</digi-button>
|
||||||
<digi-button
|
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="confirmHandledare()">
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="confirmHandledare()">
|
|
||||||
Tilldela
|
Tilldela
|
||||||
</digi-button>
|
</digi-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div *ngIf="currentStep == 3">
|
<div *ngIf="currentStep == 3">
|
||||||
<br><br>
|
<br /><br />
|
||||||
<digi-button af-variation="secondary"
|
<digi-button
|
||||||
|
af-variation="secondary"
|
||||||
af-size="m"
|
af-size="m"
|
||||||
class="employee-form__read-more"
|
class="employee-form__read-more"
|
||||||
(afOnClick)="unconfirmHandledare()">
|
(afOnClick)="unconfirmHandledare()"
|
||||||
|
>
|
||||||
Tillbaka
|
Tillbaka
|
||||||
</digi-button>
|
</digi-button>
|
||||||
<digi-button
|
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="save()"> Spara avrop </digi-button>
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="save()">
|
|
||||||
Spara avrop
|
|
||||||
</digi-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</dafa-logged-in-shell>
|
|
||||||
|
|
||||||
|
|
||||||
<ng-template #loadingRef>
|
<ng-template #loadingRef>
|
||||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
|
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
|
||||||
@@ -106,5 +94,5 @@
|
|||||||
<digi-icon-spinner af-title="Laddar innehåll"></digi-icon-spinner>
|
<digi-icon-spinner af-title="Laddar innehåll"></digi-icon-spinner>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
<hr />
|
||||||
<hr>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
|
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
|
||||||
|
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { AvropComponent } from './avrop.component';
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
|
|
||||||
import { AvropFiltersComponent } from './avrop-filters/avrop-filters.component';
|
import { AvropFiltersComponent } from './avrop-filters/avrop-filters.component';
|
||||||
import { AvropTableComponent } from './avrop-table/avrop-table.component';
|
|
||||||
import { AvropTableRowComponent } from './avrop-table/avrop-table-row/avrop-table-row.component';
|
|
||||||
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
|
||||||
import { TemporaryFilterComponent } from './avrop-filters/temporary-filter/temporary-filter.component';
|
import { TemporaryFilterComponent } from './avrop-filters/temporary-filter/temporary-filter.component';
|
||||||
|
import { AvropTableRowComponent } from './avrop-table/avrop-table-row/avrop-table-row.component';
|
||||||
|
import { AvropTableComponent } from './avrop-table/avrop-table.component';
|
||||||
|
import { AvropComponent } from './avrop.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [AvropComponent, AvropFiltersComponent, AvropTableComponent, AvropTableRowComponent, TemporaryFilterComponent],
|
declarations: [
|
||||||
|
AvropComponent,
|
||||||
|
AvropFiltersComponent,
|
||||||
|
AvropTableComponent,
|
||||||
|
AvropTableRowComponent,
|
||||||
|
TemporaryFilterComponent,
|
||||||
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: AvropComponent }]),
|
RouterModule.forChild([{ path: '', component: AvropComponent }]),
|
||||||
LoggedInShellModule,
|
LayoutModule,
|
||||||
DigiNgProgressProgressbarModule,
|
DigiNgProgressProgressbarModule,
|
||||||
DigiNgSkeletonBaseModule,
|
DigiNgSkeletonBaseModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<digi-typography>
|
|
||||||
<section class="releases">
|
|
||||||
<h1>Ciam landing</h1>
|
|
||||||
|
|
||||||
<p>Redirecting to /......</p>
|
|
||||||
</section>
|
|
||||||
</digi-typography>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { first, map, switchMap } from 'rxjs/operators';
|
|
||||||
import { AuthenticationService } from '@dafa-services/api/authentication.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'dafa-ciam-landing',
|
|
||||||
templateUrl: './ciam-landing.component.html',
|
|
||||||
styleUrls: ['./ciam-landing.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class CiamLandingComponent implements OnInit {
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private authenticationService: AuthenticationService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.route.queryParams
|
|
||||||
.pipe(
|
|
||||||
first(),
|
|
||||||
map(({ code }) => {
|
|
||||||
if (!code) {
|
|
||||||
throw new Error('Expected CIAM to return "code" in queryparams.');
|
|
||||||
}
|
|
||||||
return code as string;
|
|
||||||
}),
|
|
||||||
switchMap(code => {
|
|
||||||
return this.authenticationService.login$(code);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(() => {
|
|
||||||
void this.router.navigateByUrl('/');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
import { CiamLandingComponent } from './ciam-landing.component';
|
|
||||||
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
declarations: [CiamLandingComponent],
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
RouterModule.forChild([{ path: '', component: CiamLandingComponent }]),
|
|
||||||
DigiNgButtonModule
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class CiamLandingModule {}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { LogoutComponent } from './logout.component';
|
import { LogoutComponent } from './logout.component';
|
||||||
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
<dafa-layout>
|
||||||
<dafa-logged-in-shell>
|
|
||||||
<section class="messages">Meddelanden funkar!</section>
|
<section class="messages">Meddelanden funkar!</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { MessagesComponent } from './messages.component';
|
import { MessagesComponent } from './messages.component';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [MessagesComponent],
|
declarations: [MessagesComponent],
|
||||||
imports: [CommonModule, RouterModule.forChild([{ path: '', component: MessagesComponent }]), LoggedInShellModule]
|
imports: [CommonModule, RouterModule.forChild([{ path: '', component: MessagesComponent }]), LayoutModule],
|
||||||
})
|
})
|
||||||
export class MessagesModule {}
|
export class MessagesModule {}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<digi-typography>
|
<digi-typography>
|
||||||
<section class="login__wrapper">
|
<section class="mock-login">
|
||||||
<h1>Mock login</h1>
|
<h1>Mock login</h1>
|
||||||
<p>Simulera att man loggar in och blir redirectad till /ciam-landing med en Authorization-code som sedan används för att hämta authentication-token:</p>
|
<p>
|
||||||
<digi-ng-button [routerLink]="'/ciam-landing'" [queryParams]="{code: 'auth_code_from_CIAM_with_all_permissions'}">
|
Simulera att man loggar in och blir redirectad till startsidan med en Authorization-code som sedan används för att
|
||||||
|
hämta authentication-token:
|
||||||
|
</p>
|
||||||
|
<digi-ng-button routerLink="/" [queryParams]="{ code: 'auth_code_from_CIAM_with_all_permissions' }">
|
||||||
Logga in med fullständiga rättigheter
|
Logga in med fullständiga rättigheter
|
||||||
</digi-ng-button>
|
</digi-ng-button>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
.login__wrapper {
|
.mock-login {
|
||||||
margin: 5rem;
|
margin: 5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MockLoginComponent } from './mock-login.component';
|
import { MockLoginComponent } from './mock-login.component';
|
||||||
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<section class="page-not-found">
|
<section class="page-not-found">
|
||||||
<h1>Oj då! Vi kan inte hitta sidan.</h1>
|
<h1>Oj då! Vi kan inte hitta sidan.</h1>
|
||||||
@@ -9,4 +9,4 @@
|
|||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
</digi-typography>
|
</digi-typography>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { PageNotFoundComponent } from './page-not-found.component';
|
import { PageNotFoundComponent } from './page-not-found.component';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [PageNotFoundComponent],
|
declarations: [PageNotFoundComponent],
|
||||||
imports: [CommonModule, RouterModule.forChild([{ path: '', component: PageNotFoundComponent }]), LoggedInShellModule]
|
imports: [CommonModule, RouterModule.forChild([{ path: '', component: PageNotFoundComponent }]), LayoutModule],
|
||||||
})
|
})
|
||||||
export class PageNotFoundModule {}
|
export class PageNotFoundModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="participant-card">
|
<section class="participant-card">
|
||||||
<digi-typography *ngIf="detailedParticipantData$ | async as detailedParticipantData; else loadingRef">
|
<digi-typography *ngIf="detailedParticipantData$ | async as detailedParticipantData; else loadingRef">
|
||||||
<header class="participant-card__header">
|
<header class="participant-card__header">
|
||||||
@@ -54,4 +54,4 @@
|
|||||||
<span class="dafa__a11y-sr-only">Info saknas</span>
|
<span class="dafa__a11y-sr-only">Info saknas</span>
|
||||||
</dd>
|
</dd>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { BackLinkModule } from '@dafa-shared/components/back-link/back-link.module';
|
import { BackLinkModule } from '@dafa-shared/components/back-link/back-link.module';
|
||||||
import { IconModule } from '@dafa-shared/components/icon/icon.module';
|
import { IconModule } from '@dafa-shared/components/icon/icon.module';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { ParticipantCardComponent } from './participant-card.component';
|
import { ParticipantCardComponent } from './participant-card.component';
|
||||||
import { LoggedInShellModule } from '../../../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -13,7 +13,7 @@ import { LoggedInShellModule } from '../../../../components/logged-in-shell/logg
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: ParticipantCardComponent }]),
|
RouterModule.forChild([{ path: '', component: ParticipantCardComponent }]),
|
||||||
LoggedInShellModule,
|
LayoutModule,
|
||||||
DigiNgLinkInternalModule,
|
DigiNgLinkInternalModule,
|
||||||
IconModule,
|
IconModule,
|
||||||
BackLinkModule,
|
BackLinkModule,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="participants">
|
<section class="participants">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h1>Mina deltagare</h1>
|
<h1>Mina deltagare</h1>
|
||||||
@@ -41,4 +41,4 @@
|
|||||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar deltagare"></digi-ng-skeleton-base>
|
<digi-ng-skeleton-base [afCount]="3" afText="Laddar deltagare"></digi-ng-skeleton-base>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</section>
|
</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { ParticipantsListModule } from './components/participants-list/participants-list.module';
|
import { ParticipantsListModule } from './components/participants-list/participants-list.module';
|
||||||
import { ParticipantsRoutingModule } from './participants-routing.module';
|
import { ParticipantsRoutingModule } from './participants-routing.module';
|
||||||
import { ParticipantsComponent } from './participants.component';
|
import { ParticipantsComponent } from './participants.component';
|
||||||
@@ -12,11 +12,11 @@ import { ParticipantsComponent } from './participants.component';
|
|||||||
declarations: [ParticipantsComponent],
|
declarations: [ParticipantsComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
LayoutModule,
|
||||||
ParticipantsRoutingModule,
|
ParticipantsRoutingModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
DigiNgSkeletonBaseModule,
|
DigiNgSkeletonBaseModule,
|
||||||
ParticipantsListModule,
|
ParticipantsListModule,
|
||||||
LoggedInShellModule,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ParticipantsModule {}
|
export class ParticipantsModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<section class="releases">
|
<section class="releases">
|
||||||
<h1>Releaser</h1>
|
<h1>Releaser</h1>
|
||||||
@@ -9,4 +9,4 @@
|
|||||||
<markdown src="assets/CHANGELOG.md"></markdown>
|
<markdown src="assets/CHANGELOG.md"></markdown>
|
||||||
</section>
|
</section>
|
||||||
</digi-typography>
|
</digi-typography>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { MarkdownModule } from 'ngx-markdown';
|
import { MarkdownModule } from 'ngx-markdown';
|
||||||
import { ReleasesComponent } from './releases.component';
|
import { ReleasesComponent } from './releases.component';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -12,7 +12,7 @@ import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
MarkdownModule.forChild(),
|
MarkdownModule.forChild(),
|
||||||
RouterModule.forChild([{ path: '', component: ReleasesComponent }]),
|
RouterModule.forChild([{ path: '', component: ReleasesComponent }]),
|
||||||
LoggedInShellModule
|
LayoutModule,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class ReleasesModule {}
|
export class ReleasesModule {}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="settings">Inställningar funkar!</section>
|
<section class="settings">Inställningar funkar!</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { SettingsComponent } from './settings.component';
|
import { SettingsComponent } from './settings.component';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [SettingsComponent],
|
declarations: [SettingsComponent],
|
||||||
imports: [CommonModule, RouterModule.forChild([{ path: '', component: SettingsComponent }]), LoggedInShellModule]
|
imports: [CommonModule, RouterModule.forChild([{ path: '', component: SettingsComponent }]), LayoutModule],
|
||||||
})
|
})
|
||||||
export class SettingsModule {}
|
export class SettingsModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="start">
|
<section class="start">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h1>Välkommen till Mina Sidor FA</h1>
|
<h1>Välkommen till Mina Sidor FA</h1>
|
||||||
@@ -33,4 +33,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import { DigiNgCardModule } from '@af/digi-ng/_card/card';
|
||||||
|
import { DigiNgLinkInternalModule } from '@af/digi-ng/_link/link-internal';
|
||||||
|
import { DigiNgNotificationAlertModule } from '@af/digi-ng/_notification/notification-alert';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { StartComponent } from './start.component';
|
import { StartComponent } from './start.component';
|
||||||
import { DigiNgCardModule } from '@af/digi-ng/_card/card';
|
|
||||||
import { DigiNgNotificationAlertModule } from '@af/digi-ng/_notification/notification-alert';
|
|
||||||
import { DigiNgLinkInternalModule } from '@af/digi-ng/_link/link-internal';
|
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -13,10 +13,10 @@ import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: StartComponent }]),
|
RouterModule.forChild([{ path: '', component: StartComponent }]),
|
||||||
|
LayoutModule,
|
||||||
DigiNgCardModule,
|
DigiNgCardModule,
|
||||||
DigiNgNotificationAlertModule,
|
DigiNgNotificationAlertModule,
|
||||||
DigiNgLinkInternalModule,
|
DigiNgLinkInternalModule,
|
||||||
LoggedInShellModule
|
],
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class StartModule {}
|
export class StartModule {}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<dafa-logged-in-shell>
|
<dafa-layout>
|
||||||
<section class="statistics">Statistik funkar!</section>
|
<section class="statistics">Statistik funkar!</section>
|
||||||
</dafa-logged-in-shell>
|
</dafa-layout>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
|
||||||
import { StatisticsComponent } from './statistics.component';
|
import { StatisticsComponent } from './statistics.component';
|
||||||
import { LoggedInShellModule } from '../../components/logged-in-shell/logged-in-shell.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [StatisticsComponent],
|
declarations: [StatisticsComponent],
|
||||||
imports: [CommonModule, RouterModule.forChild([{ path: '', component: StatisticsComponent }]), LoggedInShellModule]
|
imports: [CommonModule, RouterModule.forChild([{ path: '', component: StatisticsComponent }]), LayoutModule],
|
||||||
})
|
})
|
||||||
export class StatisticsModule {}
|
export class StatisticsModule {}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AuthenticationService } from './authentication.service';
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
import { AuthenticationService } from './authentication.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthInterceptor implements HttpInterceptor {
|
export class AuthInterceptor implements HttpInterceptor {
|
||||||
constructor(private auth: AuthenticationService) {}
|
constructor(private auth: AuthenticationService) {}
|
||||||
|
|
||||||
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||||
const idToken = this.auth.getAuthorizationToken();
|
const idToken = this.auth.currentAuthorizationToken;
|
||||||
|
|
||||||
if (idToken) {
|
if (idToken) {
|
||||||
const cloned = req.clone({
|
const cloned = req.clone({
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { environment } from '@dafa-environment';
|
import { environment } from '@dafa-environment';
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { map, tap } from 'rxjs/operators';
|
|
||||||
import {
|
import {
|
||||||
AuthenticationApiResponse,
|
AuthenticationApiResponse,
|
||||||
AuthenticationResult,
|
AuthenticationResult,
|
||||||
mapAuthApiResponseToAuthenticationResult,
|
mapAuthApiResponseToAuthenticationResult,
|
||||||
} from '@dafa-models/authentication.model';
|
} from '@dafa-models/authentication.model';
|
||||||
import { add, isBefore } from 'date-fns';
|
import { add, isBefore } from 'date-fns';
|
||||||
|
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||||
|
import { map, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
const API_HEADERS = { headers: environment.api.headers };
|
const API_HEADERS = { headers: environment.api.headers };
|
||||||
|
|
||||||
@@ -16,14 +16,29 @@ const API_HEADERS = { headers: environment.api.headers };
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AuthenticationService {
|
export class AuthenticationService {
|
||||||
private static _authTokenApiUrl(code: string): string {
|
private _token$ = new BehaviorSubject<string>(null);
|
||||||
return `${environment.api.url}/get-token?code=${code}`;
|
private _expiration$ = new BehaviorSubject<number>(null);
|
||||||
|
|
||||||
|
isLoggedIn$: Observable<boolean> = combineLatest([this._token$, this._expiration$]).pipe(
|
||||||
|
map(([token, expiration]) => {
|
||||||
|
if (token && expiration) {
|
||||||
|
return isBefore(new Date(), expiration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _setSession(authenticationResult: AuthenticationResult): void {
|
return false;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
private static _authTokenApiUrl(code: string): string {
|
||||||
|
return `${environment.api.url}/auth/token?accessCode=${code}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setSession(authenticationResult: AuthenticationResult): void {
|
||||||
const expiresAt = add(new Date(), { seconds: authenticationResult.expiresIn });
|
const expiresAt = add(new Date(), { seconds: authenticationResult.expiresIn });
|
||||||
|
|
||||||
|
this._token$.next(authenticationResult.idToken);
|
||||||
localStorage.setItem('id_token', authenticationResult.idToken);
|
localStorage.setItem('id_token', authenticationResult.idToken);
|
||||||
|
this._expiration$.next(expiresAt.valueOf());
|
||||||
localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
|
localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,31 +46,37 @@ export class AuthenticationService {
|
|||||||
return this.httpClient
|
return this.httpClient
|
||||||
.get<AuthenticationApiResponse>(AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam), API_HEADERS)
|
.get<AuthenticationApiResponse>(AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam), API_HEADERS)
|
||||||
.pipe(
|
.pipe(
|
||||||
map(response => mapAuthApiResponseToAuthenticationResult(response.data)),
|
map(response => mapAuthApiResponseToAuthenticationResult(response)),
|
||||||
tap(authenticationResult => {
|
tap(authenticationResult => {
|
||||||
AuthenticationService._setSession(authenticationResult);
|
this._setSession(authenticationResult);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoggedIn(): boolean {
|
private _getLocalStorageData(): { id_token: string; expires_at: number } {
|
||||||
return isBefore(new Date(), this.getExpiration());
|
const id_token = localStorage.getItem('id_token');
|
||||||
}
|
|
||||||
|
|
||||||
isLoggedOut(): boolean {
|
|
||||||
return !this.isLoggedIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
getAuthorizationToken(): string {
|
|
||||||
return localStorage.getItem('id_token');
|
|
||||||
}
|
|
||||||
|
|
||||||
getExpiration(): number {
|
|
||||||
const expiration = localStorage.getItem('expires_at');
|
const expiration = localStorage.getItem('expires_at');
|
||||||
return JSON.parse(expiration) as number;
|
|
||||||
|
return id_token && expiration
|
||||||
|
? {
|
||||||
|
id_token,
|
||||||
|
expires_at: +JSON.parse(expiration),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) {}
|
get currentAuthorizationToken(): string {
|
||||||
|
return this._token$.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private httpClient: HttpClient) {
|
||||||
|
const localStorageData = this._getLocalStorageData();
|
||||||
|
|
||||||
|
if (localStorageData) {
|
||||||
|
this._token$.next(localStorageData.id_token);
|
||||||
|
this._expiration$.next(localStorageData.expires_at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
localStorage.removeItem('id_token');
|
localStorage.removeItem('id_token');
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ const API_HEADERS = { headers: environment.api.headers };
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class UserService {
|
export class UserService {
|
||||||
private _userApiUrl = `${environment.api.url}/currentUser`;
|
private _userApiUrl = `${environment.api.url}/auth`;
|
||||||
public currentUser$: Observable<User> = this.httpClient
|
public user$: Observable<User> = this.httpClient
|
||||||
.get<UserApiResponse>(this._userApiUrl, API_HEADERS)
|
.get<UserApiResponse>(this._userApiUrl, API_HEADERS)
|
||||||
.pipe(map(response => mapUserApiResponseToUser(response.data)));
|
.pipe(map(response => mapUserApiResponseToUser(response.data)));
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="navigation__list dafa__hide-on-print">
|
<ul class="navigation__list dafa__hide-on-print">
|
||||||
<li class="navigation__item navigation__item--user" *ngIf="currentUser">
|
<li class="navigation__item navigation__item--user">
|
||||||
<span class="navigation__text">{{ currentUser.fullName }}</span>
|
<span *ngIf="user" class="navigation__text">{{ user.fullName }}</span>
|
||||||
<dafa-icon [icon]="iconType.USER" size="l"></dafa-icon>
|
<dafa-icon [icon]="iconType.USER" size="l"></dafa-icon>
|
||||||
</li>
|
</li>
|
||||||
<li class="navigation__item">
|
<li class="navigation__item">
|
||||||
@@ -21,16 +21,5 @@
|
|||||||
<span class="dafa__a11y-sr-only">Inställningar</span>
|
<span class="dafa__a11y-sr-only">Inställningar</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- <li class="navigation__item">
|
|
||||||
<a
|
|
||||||
class="navigation__link"
|
|
||||||
[routerLink]="['/']"
|
|
||||||
[routerLinkActive]="['navigation__link--active']"
|
|
||||||
[routerLinkActiveOptions]="{ exact: true }"
|
|
||||||
>
|
|
||||||
<dafa-icon [icon]="iconType.HOME" size="l"></dafa-icon>
|
|
||||||
<span class="navigation__text">Startsida</span>
|
|
||||||
</a>
|
|
||||||
</li> -->
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,6 +9,6 @@ import { User } from '@dafa-models/user.model';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class NavigationComponent {
|
export class NavigationComponent {
|
||||||
@Input() currentUser: User;
|
@Input() user: User;
|
||||||
iconType = IconType;
|
iconType = IconType;
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<div class="dafa">
|
<div class="dafa" *ngIf="isLoggedIn$ | async">
|
||||||
<dafa-skip-to-content mainContentId="dafa-main-content"></dafa-skip-to-content>
|
<dafa-skip-to-content mainContentId="dafa-main-content"></dafa-skip-to-content>
|
||||||
|
|
||||||
<header class="dafa__header">
|
<header class="dafa__header">
|
||||||
<dafa-navigation *ngIf="isLoggedIn" [currentUser]="currentUser$ | async"></dafa-navigation>
|
<dafa-navigation [user]="user$ | async"></dafa-navigation>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<dafa-sidebar class="dafa__sidebar"></dafa-sidebar>
|
<dafa-sidebar class="dafa__sidebar"></dafa-sidebar>
|
||||||
@@ -13,9 +13,7 @@
|
|||||||
></digi-ng-navigation-breadcrumbs>
|
></digi-ng-navigation-breadcrumbs>
|
||||||
|
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<dafa-footer class="dafa__footer"></dafa-footer>
|
<dafa-footer class="dafa__footer"></dafa-footer>
|
||||||
</div>
|
</div>
|
||||||
<dafa-toast-list></dafa-toast-list>
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { LayoutComponent } from './Layout.component';
|
||||||
|
|
||||||
|
describe('LayoutComponent', () => {
|
||||||
|
let component: LayoutComponent;
|
||||||
|
let fixture: ComponentFixture<LayoutComponent>;
|
||||||
|
|
||||||
|
beforeEach(
|
||||||
|
waitForAsync(() => {
|
||||||
|
void TestBed.configureTestingModule({
|
||||||
|
declarations: [LayoutComponent],
|
||||||
|
imports: [RouterTestingModule, HttpClientTestingModule],
|
||||||
|
}).compileComponents();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LayoutComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,47 +1,54 @@
|
|||||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
||||||
import { NavigationBreadcrumbsItem } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
import { NavigationBreadcrumbsItem } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
import { User } from '@dafa-models/user.model';
|
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||||
import { NavigationEnd, Router } from '@angular/router';
|
|
||||||
import { UserService } from '@dafa-services/api/user.service';
|
|
||||||
import { filter } from 'rxjs/operators';
|
|
||||||
import { mapPathsToBreadcrumbs } from '@dafa-utils/map-paths-to-breadcrumbs.util';
|
|
||||||
import { UnsubscribeDirective } from '@dafa-directives/unsubscribe.directive';
|
import { UnsubscribeDirective } from '@dafa-directives/unsubscribe.directive';
|
||||||
|
import { User } from '@dafa-models/user.model';
|
||||||
import { AuthenticationService } from '@dafa-services/api/authentication.service';
|
import { AuthenticationService } from '@dafa-services/api/authentication.service';
|
||||||
import { environment } from '@dafa-environment';
|
import { UserService } from '@dafa-services/api/user.service';
|
||||||
|
import { mapPathsToBreadcrumbs } from '@dafa-utils/map-paths-to-breadcrumbs.util';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { filter, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dafa-logged-in-shell',
|
selector: 'dafa-layout',
|
||||||
templateUrl: './logged-in-shell.component.html',
|
templateUrl: './layout.component.html',
|
||||||
styleUrls: ['./logged-in-shell.component.scss'],
|
styleUrls: ['./layout.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class LoggedInShellComponent extends UnsubscribeDirective {
|
export class LayoutComponent extends UnsubscribeDirective {
|
||||||
private startBreadcrumb: NavigationBreadcrumbsItem = {
|
private startBreadcrumb: NavigationBreadcrumbsItem = {
|
||||||
text: 'Start',
|
text: 'Start',
|
||||||
routerLink: '/',
|
routerLink: '/',
|
||||||
};
|
};
|
||||||
private _breadcrumbsItems$ = new BehaviorSubject<NavigationBreadcrumbsItem[]>([this.startBreadcrumb]);
|
private _breadcrumbsItems$ = new BehaviorSubject<NavigationBreadcrumbsItem[]>([this.startBreadcrumb]);
|
||||||
public currentUser$: Observable<User> = this.userService.currentUser$;
|
isLoggedIn$: Observable<boolean> = this.authService.isLoggedIn$;
|
||||||
|
user$: Observable<User> = this.isLoggedIn$.pipe(
|
||||||
|
filter(loggedIn => !!loggedIn),
|
||||||
|
switchMap(() => this.userService.user$)
|
||||||
|
);
|
||||||
|
|
||||||
get breadcrumbsItems(): NavigationBreadcrumbsItem[] {
|
get breadcrumbsItems(): NavigationBreadcrumbsItem[] {
|
||||||
return this._breadcrumbsItems$.getValue();
|
return this._breadcrumbsItems$.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isLoggedIn(): boolean {
|
constructor(
|
||||||
return this.authService.isLoggedIn();
|
private router: Router,
|
||||||
}
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private authService: AuthenticationService,
|
||||||
constructor(private router: Router, private authService: AuthenticationService, private userService: UserService) {
|
private userService: UserService
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (this.authService.isLoggedOut()) {
|
|
||||||
void this.router.navigateByUrl(environment.loginUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.unsubscribeOnDestroy(
|
super.unsubscribeOnDestroy(
|
||||||
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
|
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
|
||||||
const urlTree = this.router.parseUrl(this.router.url);
|
const urlTree = this.router.parseUrl(this.router.url);
|
||||||
|
if (urlTree.queryParams.code) {
|
||||||
|
void this.router.navigate([], {
|
||||||
|
relativeTo: this.activatedRoute,
|
||||||
|
queryParams: { code: null },
|
||||||
|
queryParamsHandling: 'merge',
|
||||||
|
replaceUrl: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
urlTree.queryParams = {};
|
urlTree.queryParams = {};
|
||||||
const paths = urlTree
|
const paths = urlTree
|
||||||
.toString()
|
.toString()
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { DigiNgNavigationBreadcrumbsModule } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { MarkdownModule } from 'ngx-markdown';
|
||||||
|
import { FooterModule } from './components/footer/footer.module';
|
||||||
|
import { NavigationModule } from './components/navigation/navigation.module';
|
||||||
|
import { SidebarModule } from './components/sidebar/sidebar.module';
|
||||||
|
import { SkipToContentModule } from './components/skip-to-content/skip-to-content.module';
|
||||||
|
import { LayoutComponent } from './layout.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [LayoutComponent],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterModule,
|
||||||
|
SkipToContentModule,
|
||||||
|
NavigationModule,
|
||||||
|
SidebarModule,
|
||||||
|
FooterModule,
|
||||||
|
MarkdownModule.forRoot({ loader: HttpClient }),
|
||||||
|
DigiNgNavigationBreadcrumbsModule,
|
||||||
|
],
|
||||||
|
exports: [LayoutComponent],
|
||||||
|
})
|
||||||
|
export class LayoutModule {}
|
||||||
11
apps/dafa-web/src/environments/environment.api.ts
Normal file
11
apps/dafa-web/src/environments/environment.api.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export const environment = {
|
||||||
|
environment: 'api',
|
||||||
|
clientId: '5d08c2e4-763e-42f6-b858-24e4773bb83d',
|
||||||
|
redirectUri: 'http://localhost:4200',
|
||||||
|
loginUrl: 'https://ciam-test.arbetsformedlingen.se:8443/uas/oauth2/authorization?response_type=code&scope=openid',
|
||||||
|
production: false,
|
||||||
|
api: {
|
||||||
|
url: '/api',
|
||||||
|
headers: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
export const environment = {
|
|
||||||
loginUrl:
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
'https://ciam-test.arbetsformedlingen.se:8443/uas/oauth2/authorization?response_type=code&scope=openid&redirect_uri=https://localhost:4200/ciam-landing&client_id=5d08c2e4-763e-42f6-b858-24e4773bb83d',
|
|
||||||
production: false,
|
|
||||||
api: {
|
|
||||||
url: '/api',
|
|
||||||
headers: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
export const environment = {
|
|
||||||
production: false,
|
|
||||||
api: {
|
|
||||||
meet: 'https://dafa-utv.tocp.arbetsformedlingen.se/prweb/api/meettest/v1',
|
|
||||||
default: 'https://dafa-utv.tocp.arbetsformedlingen.se/prweb/api/v1/data',
|
|
||||||
url: '/api',
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Basic dGVzdHVzZXIxOmRhZmFAMTIz', // user: testuser1, password: dafa@123
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
loginUrl: 'mock-login',
|
environment: 'local',
|
||||||
|
clientId: '',
|
||||||
|
redirectUri: '',
|
||||||
|
loginUrl: '/mock-login',
|
||||||
production: false,
|
production: false,
|
||||||
api: {
|
api: {
|
||||||
url: '/api',
|
url: '/api',
|
||||||
|
|||||||
7
config/proxy.conf.api.json
Normal file
7
config/proxy.conf.api.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"/api": {
|
||||||
|
"target": "http://mina-sidor-fa-test-api.tocp.arbetsformedlingen.se",
|
||||||
|
"secure": false,
|
||||||
|
"changeOrigin": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"/api": {
|
|
||||||
"target": "http://localhost:6001",
|
|
||||||
"secure": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,17 +15,18 @@ server.use(
|
|||||||
'/employee*': '/employees$1',
|
'/employee*': '/employees$1',
|
||||||
'/participants': '/participants?_embed=employees',
|
'/participants': '/participants?_embed=employees',
|
||||||
'/participant/:id': '/participants/:id?_embed=employees',
|
'/participant/:id': '/participants/:id?_embed=employees',
|
||||||
|
'/auth': '/currentUser',
|
||||||
'*page=*': '$1_page=$2',
|
'*page=*': '$1_page=$2',
|
||||||
'*limit=*': '$1_limit=$2',
|
'*limit=*': '$1_limit=$2',
|
||||||
'*sort=*': '$1_sort=$2',
|
'*sort=*': '$1_sort=$2',
|
||||||
'*order=*': '$1_order=$2',
|
'*order=*': '$1_order=$2',
|
||||||
'/get-token?code=auth_code_from_CIAM_with_all_permissions': '/getTokenFullAccess',
|
'/auth/token?accessCode=auth_code_from_CIAM_with_all_permissions': '/getTokenFullAccess',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
router.render = (req, res) => {
|
router.render = (req, res) => {
|
||||||
// all paths except getToken requires Authorization header.
|
// all paths except getTokenFullAccess requires Authorization header.
|
||||||
if (!req._parsedUrl.pathname.includes('getToken') && !req.headers.authorization) {
|
if (!req._parsedUrl.pathname.includes('getTokenFullAccess') && !req.headers.authorization) {
|
||||||
return res.status(401).jsonp({ error: 'No valid access-token' });
|
return res.status(401).jsonp({ error: 'No valid access-token' });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,10 +37,14 @@ router.render = (req, res) => {
|
|||||||
req.body.createdAt = Date.now();
|
req.body.createdAt = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req._parsedUrl.pathname.includes('getTokenFullAccess')) {
|
||||||
|
res.jsonp(res.locals.data);
|
||||||
|
} else {
|
||||||
res.jsonp({
|
res.jsonp({
|
||||||
data: res.locals.data,
|
data: res.locals.data,
|
||||||
...appendMetaData(params, res),
|
...appendMetaData(params, res),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
server.use(router);
|
server.use(router);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@dafa-assets/*": ["apps/dafa-web/src/assets/*"],
|
"@dafa-assets/*": ["apps/dafa-web/src/assets/*"],
|
||||||
"@dafa-shared/*": ["apps/dafa-web/src/app/shared/*"],
|
"@dafa-shared/*": ["apps/dafa-web/src/app/shared/*"],
|
||||||
"@dafa-models/*": ["apps/dafa-web/src/app/data/models/*"],
|
"@dafa-models/*": ["apps/dafa-web/src/app/data/models/*"],
|
||||||
|
"@dafa-guards/*": ["apps/dafa-web/src/app/guards/*"],
|
||||||
"@dafa-constants/*": ["apps/dafa-web/src/app/data/constants/*"],
|
"@dafa-constants/*": ["apps/dafa-web/src/app/data/constants/*"],
|
||||||
"@dafa-directives/*": ["apps/dafa-web/src/app/directives/*"],
|
"@dafa-directives/*": ["apps/dafa-web/src/app/directives/*"],
|
||||||
"@dafa-enums/*": ["apps/dafa-web/src/app/data/enums/*"],
|
"@dafa-enums/*": ["apps/dafa-web/src/app/data/enums/*"],
|
||||||
|
|||||||
Reference in New Issue
Block a user