mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 17:12:43 +00:00
feat: add auth support (default and paia)
This commit is contained in:
committed by
Jovan Krunić
parent
046a95ba1d
commit
b5f239ea4e
75
src/app/modules/profile/page/profile-page.component.html
Normal file
75
src/app/modules/profile/page/profile-page.component.html
Normal 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>
|
||||
25
src/app/modules/profile/page/profile-page.component.scss
Normal file
25
src/app/modules/profile/page/profile-page.component.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
50
src/app/modules/profile/page/profile-page.component.spec.ts
Normal file
50
src/app/modules/profile/page/profile-page.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
105
src/app/modules/profile/page/profile-page.component.ts
Normal file
105
src/app/modules/profile/page/profile-page.component.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/app/modules/profile/profile.module.ts
Normal file
26
src/app/modules/profile/profile.module.ts
Normal 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 {}
|
||||
82
src/app/modules/profile/user.ts
Normal file
82
src/app/modules/profile/user.ts
Normal 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';
|
||||
Reference in New Issue
Block a user