feat: add auth support (default and paia)

This commit is contained in:
Michel Jonathan Schmitz
2022-01-24 18:43:00 +00:00
committed by Jovan Krunić
parent 046a95ba1d
commit b5f239ea4e
85 changed files with 3626 additions and 119 deletions

View File

@@ -0,0 +1,75 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>{{ 'profile.title' | translate | titlecase }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<section>
<ion-grid>
<ion-row>
<ion-col>
<ion-card *ngIf="userInfo">
<ion-card-content>
<ion-grid>
<ion-row>
<ion-col size="3">
<ion-thumbnail>
<ion-icon name="person"></ion-icon>
</ion-thumbnail>
</ion-col>
<ion-col size="9">
<ion-row class="main-info">
<span
>{{ userInfo.givenName }}
{{ userInfo.familyName }}</span
>
</ion-row>
<ion-row class="additional-info">
<span>{{ userInfo.email }}</span>
<span
>{{
'profile.userInfo.studentId' | translate | titlecase
}}: {{ userInfo.studentId }}</span
>
</ion-row>
</ion-col>
</ion-row>
</ion-grid>
</ion-card-content>
</ion-card>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="login">
<a *ngIf="!data.default.loggedIn; else loggedIn" (click)="signIn()">{{
'profile.buttons.default.log_in' | translate | titlecase
}}</a>
<ng-template #loggedIn
><a (click)="signOut()">{{
'profile.buttons.default.log_out' | translate | titlecase
}}</a></ng-template
>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="login">
<a
*ngIf="!data.paia.loggedIn; else paiaLoggedIn"
(click)="signInPAIA()"
>{{ 'profile.buttons.paia.log_in' | translate | titlecase }}</a
>
<ng-template #paiaLoggedIn
><a (click)="signOutPAIA()">{{
'profile.buttons.paia.log_out' | translate | titlecase
}}</a></ng-template
>
</ion-col>
</ion-row>
</ion-grid>
</section>
</ion-content>

View File

@@ -0,0 +1,25 @@
:host {
ion-col.login {
text-align: center;
a {
cursor: pointer;
}
}
ion-thumbnail {
background: var(--placeholder-gray);
--size: 64px;
align-items: center;
padding: 10px;
margin: 0;
ion-icon {
width: 100%;
height: 100%;
color: white;
display: block;
}
}
ion-row.main-info {
font-weight: bold;
margin-bottom: 2px;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {HttpClientTestingModule} from '@angular/common/http/testing';
import {RouterTestingModule} from '@angular/router/testing';
import {AuthModule} from '../../auth/auth.module';
import {ProfilePageComponent} from './profile-page.component';
import {TranslateModule} from '@ngx-translate/core';
describe('ProfilePage', () => {
let component: ProfilePageComponent;
let fixture: ComponentFixture<ProfilePageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProfilePageComponent],
imports: [
HttpClientTestingModule,
RouterTestingModule,
AuthModule,
TranslateModule.forRoot(),
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProfilePageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2021-2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Component, OnDestroy, OnInit} from '@angular/core';
import {IonicUserInfoHandler} from 'ionic-appauth';
import {DefaultAuthService} from '../../auth/default-auth.service';
import {Requestor, TokenResponse} from '@openid/appauth';
import {PAIAAuthService} from '../../auth/paia/paia-auth.service';
import {SCAuthorizationProviderType, SCUserConfiguration} from '../user';
import {Subscription} from 'rxjs';
import {AuthHelperService} from '../../auth/auth-helper.service';
@Component({
selector: 'app-home',
templateUrl: './profile-page.component.html',
styleUrls: ['./profile-page.component.scss'],
})
export class ProfilePageComponent implements OnInit, OnDestroy {
data: {[key in SCAuthorizationProviderType]: {loggedIn: boolean}} = {
default: {loggedIn: false},
paia: {loggedIn: false},
};
userInfo?: SCUserConfiguration;
subscriptions: Subscription[] = [];
constructor(
private defaultAuth: DefaultAuthService,
private paiaAuth: PAIAAuthService,
private requestor: Requestor,
private authHelperService: AuthHelperService,
) {}
ngOnInit() {
this.subscriptions.push(
this.defaultAuth.token$.subscribe(_token => {
this.defaultAuth
.getValidToken()
.then(token => {
this.data.default.loggedIn = true;
this.getUserInfo(token);
})
.catch(_error => {
this.data.default.loggedIn = false;
});
}),
this.paiaAuth.token$.subscribe(_token => {
this.paiaAuth
.getValidToken()
.then(_token => {
this.data.paia.loggedIn = true;
})
.catch(_error => {
this.data.paia.loggedIn = false;
});
}),
);
}
getUserInfo(token: TokenResponse) {
const userInfoHandler = new IonicUserInfoHandler(this.requestor);
userInfoHandler
.performUserInfoRequest(this.defaultAuth.localConfiguration, token)
.then(userInfo => {
this.userInfo = this.authHelperService.getUserFromUserInfo(userInfo);
});
}
public signIn() {
this.defaultAuth.signIn();
}
signInPAIA() {
this.paiaAuth.signIn();
}
async signOut() {
await this.defaultAuth.signOut();
this.userInfo = undefined;
}
async signOutPAIA() {
await this.paiaAuth.signOut();
}
ngOnDestroy(): void {
for (const subscription of this.subscriptions) {
subscription.unsubscribe();
}
}
}

View File

@@ -0,0 +1,26 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {Routes, RouterModule} from '@angular/router';
import {IonicModule} from '@ionic/angular';
import {ProfilePageComponent} from './page/profile-page.component';
import {TranslateModule} from '@ngx-translate/core';
const routes: Routes = [
{
path: 'profile',
component: ProfilePageComponent,
},
];
@NgModule({
declarations: [ProfilePageComponent],
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild(routes),
TranslateModule,
],
})
export class ProfilePageModule {}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* TODO: Take it from the StApps Core
*/
import {SCAcademicPriceGroup} from '@openstapps/core';
/**
* A user configuration
*/
export interface SCUserConfiguration {
/**
* User's e-mail
*/
email?: string;
/**
* User's family name
*/
familyName?: string;
/**
* User's given name
*/
givenName?: string;
/**
* ID given to the user
*/
id: string;
/**
* The complete name of the user combining all the parts of the name into one
*/
name: string;
/**
* Role assigned to the user
*/
role: keyof SCAcademicPriceGroup;
/**
* Student ID given to the user
*/
studentId?: string;
}
/**
* TODO: Take it from the backend's config
*/
type mapping = {[key in keyof SCUserConfiguration]: string};
/**
* TODO: Take it from the backend's config
*/
export const userMapping: mapping = {
id: 'id',
name: 'sn',
role: 'attributes.eduPersonPrimaryAffiliation',
email: 'attributes.mailPrimaryAddress',
studentId: 'attributes.employeeNumber',
givenName: 'attributes.givenName',
familyName: 'attributes.sn',
};
/**
* TODO: Take it from the StApps Core
*/
export type SCAuthorizationProviderType = 'default' | 'paia';