Create personal info, registered services and personal-token pages
This commit is contained in:
parent
54bbc5a413
commit
59b129e284
|
@ -49,6 +49,7 @@
|
|||
"src/assets/common-assets/library-css/material.scss"
|
||||
],
|
||||
"scripts": [
|
||||
"src/assets/common-assets/js/copy.js",
|
||||
"node_modules/uikit/dist/js/uikit.min.js",
|
||||
"node_modules/uikit/dist/js/uikit-icons.min.js",
|
||||
"node_modules/jquery/dist/jquery.js"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.uk-border-circle {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
|
||||
& > img {
|
||||
max-width: 64px;
|
||||
max-height: 64px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,400 @@
|
|||
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
|
||||
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
|
||||
import {Subscription} from "rxjs";
|
||||
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
|
||||
import {User} from "../openaireLibrary/login/utils/helper.class";
|
||||
import {PersonalInfo, PersonalService} from "../services/personal.service";
|
||||
import {NotificationHandler} from "../openaireLibrary/utils/notification-handler";
|
||||
import {API, ApisService} from "../services/apis.service";
|
||||
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
|
||||
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
|
||||
import {properties} from "../../environments/environment";
|
||||
import {Stakeholder} from "../openaireLibrary/monitor/entities/stakeholder";
|
||||
import {CommunityInfo} from "../openaireLibrary/connect/community/communityInfo";
|
||||
import {UtilitiesService} from "../openaireLibrary/services/utilities.service";
|
||||
|
||||
declare var copy;
|
||||
|
||||
@Component({
|
||||
selector: `apis`,
|
||||
template: `
|
||||
<div page-content>
|
||||
<div header class="uk-section-small uk-container uk-container-small uk-flex uk-flex-right@m uk-flex-center">
|
||||
<button (click)="openEditModal()" class="uk-button uk-button-primary uk-flex uk-flex-middle">
|
||||
<icon name="add" [flex]="true"></icon>
|
||||
<span class="uk-margin-xsmall-left">New Service</span>
|
||||
</button>
|
||||
</div>
|
||||
<div inner class="uk-section-small uk-container uk-container-small">
|
||||
<div *ngIf="loading" class="uk-height-large uk-position-relative">
|
||||
<loading class="uk-position-center"></loading>
|
||||
</div>
|
||||
<div *ngIf="!loading">
|
||||
<div class="uk-alert-primary uk-alert uk-margin-top-remove uk-flex uk-flex-middle">
|
||||
<icon name="info" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">You can register up to 5 services.
|
||||
For more information please read the <a
|
||||
href="https://graph.openaire.eu/develop/authentication.html" target="_blank">OpenAIRE API Authentication documentation</a>.</span>
|
||||
</div>
|
||||
<div *ngIf="apis.length === 0"
|
||||
class="uk-margin-large-top uk-card uk-card-default uk-height-small uk-position-relative">
|
||||
<div class="uk-position-center uk-text-bold">You have not registered any service yet!</div>
|
||||
</div>
|
||||
<table *ngIf="apis.length > 0" class="uk-table uk-table-divider uk-margin-medium-top">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Client ID</th>
|
||||
<th>Creation Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let api of apis; let i=index">
|
||||
<td>{{api.service.name}}</td>
|
||||
<td>{{api.service.clientId}}</td>
|
||||
<td>{{api.service.creationDate | date: 'dd-MM-YYYY HH:mm'}}</td>
|
||||
<td>
|
||||
<span class="uk-flex uk-flex-middle">
|
||||
<icon name="edit" class="clickable" customClass="uk-text-primary"
|
||||
(click)="openEditModal(i)"></icon>
|
||||
<icon name="delete" class="clickable uk-margin-xsmall-left"
|
||||
customClass="uk-text-danger" (click)="openDeleteModal(i)"></icon>
|
||||
<icon name="info" class="clickable uk-margin-xsmall-left"
|
||||
customClass="uk-text-secondary" (click)="openInfoModal(i)"></icon>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<modal-alert #editModal (alertOutput)="save()" [large]="true"
|
||||
[okDisabled]="form?.disabled || form?.invalid || form?.pristine">
|
||||
<div *ngIf="form" class="uk-grid" uk-grid>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input placeholder="Service Name"
|
||||
[formInput]="form.get('name')"></div>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input type="logoURL" placeholder="Service URL"
|
||||
[formInput]="form.get('url')"></div>
|
||||
<div class="uk-width-1-1" input type="logoURL" placeholder="Logo URL"
|
||||
[formInput]="form.get('logoURL')">
|
||||
</div>
|
||||
<div class="uk-width-1-1">
|
||||
<label class="uk-text-bold">Security Level</label>
|
||||
<div id="security-hint" class="uk-margin">Register your service to get a client id and a client
|
||||
secret. Use the client id and secret to make your requests. <a
|
||||
href="https://graph.openaire.eu/develop/basic.html" target="_blank">Read more...</a>
|
||||
</div>
|
||||
<div class="uk-flex uk-flex-middle">
|
||||
<div class="uk-margin-small-right">
|
||||
<label><input type="radio" name="securityLevel" [disabled]="index !== -1"
|
||||
class="uk-radio" (ngModelChange)="securityChanged($event)"
|
||||
[ngModel]="advanced" [value]="false"><span
|
||||
class="uk-margin-small-left">Basic</span></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><input type="radio" name="securityLevel" [disabled]="index !== -1"
|
||||
class="uk-radio" (ngModelChange)="securityChanged($event)"
|
||||
[ngModel]="advanced" [value]="true"><span class="uk-margin-small-left">Advanced</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="advanced">
|
||||
<div class="uk-width-1-1">
|
||||
<div class="uk-flex uk-flex-between">
|
||||
<label class="uk-text-bold">Public Key</label>
|
||||
<div class="uk-flex uk-flex-middle">
|
||||
<div class="uk-margin-small-right">
|
||||
<label><input type="radio" name="keyType" class="uk-radio"
|
||||
(ngModelChange)="keyTypeChanged($event)" [ngModel]="byValue"
|
||||
[value]="true"><span
|
||||
class="uk-margin-small-left">By Value</span></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><input type="radio" name="keyType" class="uk-radio"
|
||||
(ngModelChange)="keyTypeChanged($event)" [ngModel]="byValue"
|
||||
[value]="false"><span
|
||||
class="uk-margin-small-left">By URI</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="byValue" class="uk-width-1-1" input type="textarea" [formInput]="form.get('value')"
|
||||
rows="5" placeholder="Key Value" [hint]="hint"></div>
|
||||
<div *ngIf="!byValue" class="uk-width-1-1" type="logoURL" input [formInput]="form.get('uri')"
|
||||
placeholder="Key URI"></div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</modal-alert>
|
||||
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirm()"></modal-alert>
|
||||
<modal-alert #infoModal [large]="false">
|
||||
<div *ngIf="api?.details">
|
||||
<ul class="uk-list uk-list-divider">
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Service Name</div>
|
||||
<div class="uk-width-expand uk-text-break">{{api.details.clientName}}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">
|
||||
<div class="uk-text-bold uk-flex uk-flex-middle">
|
||||
<span class="uk-margin-xsmall-right">Client Id</span>
|
||||
<a class="uk-link uk-link-reset" (click)="copyToClipboard('client-id')"><icon name="content_copy" customClass="uk-text-secondary" [flex]="true"></icon></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="client-id" class="uk-width-expand uk-text-break">{{api.details.clientId}}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Scope</div>
|
||||
<div class="uk-width-expand uk-text-break">openid</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Grant type</div>
|
||||
<div class="uk-width-expand uk-text-break">{{api.details.grantTypes.join(', ')}}</div>
|
||||
</div>
|
||||
</li>
|
||||
<ng-template [ngIf]="!api.service.keyType" [ngIfElse]="key">
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">
|
||||
<div class="uk-text-bold uk-flex uk-flex-middle">
|
||||
<span class="uk-margin-xsmall-right">Client Secret</span>
|
||||
<a class="uk-link uk-link-reset" (click)="copyToClipboard('client-secret')"><icon name="content_copy" customClass="uk-text-secondary" [flex]="true"></icon></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="client-secret" class="uk-width-expand uk-text-break">{{api.details.clientSecret}}</div>
|
||||
</div>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Authentication method</div>
|
||||
<div class="uk-width-expand uk-text-break">Client Secret Basic</div>
|
||||
</div>
|
||||
</li>
|
||||
</ng-template>
|
||||
<ng-template #key>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Authentication method</div>
|
||||
<div class="uk-width-expand uk-text-break">Asymmetrically-signed JWT assertion</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Token Endpoint Authentication Signing Algorithm</div>
|
||||
<div class="uk-width-expand uk-text-break">RSASSA using SHA-256 hash algorithm</div>
|
||||
</div>
|
||||
</li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">
|
||||
<div class="uk-text-bold uk-flex uk-flex-middle">
|
||||
<span class="uk-margin-xsmall-right">Public Key</span>
|
||||
<a class="uk-link uk-link-reset" (click)="copyToClipboard('public-key')"><icon name="content_copy" customClass="uk-text-secondary" [flex]="true"></icon></a>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="api.details.jwksUri" id="public-key" class="uk-width-expand uk-text-break">{{api.details.jwksUri}}</div>
|
||||
<div *ngIf="api.details.jwks" id="public-key" class="uk-width-expand uk-text-break">
|
||||
<pre><code class="uk-overflow-auto">{{api.details.jwks.keys[0] | json}}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
<li>
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-width-small uk-margin-xsmall-right">Creation Date</div>
|
||||
<div class="uk-width-expand uk-text-break">{{api.service.creationDate | date: 'dd-mm-YYYY hh:MM'}}</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</modal-alert>
|
||||
`,
|
||||
styleUrls: ['apis.component.less']
|
||||
})
|
||||
export class ApisComponent implements OnInit, OnDestroy {
|
||||
form: FormGroup;
|
||||
loading: boolean = true;
|
||||
subscriptions: any[] = [];
|
||||
user: User;
|
||||
apis: API[] = [];
|
||||
api: API;
|
||||
index: number = -1;
|
||||
advanced: boolean = false;
|
||||
byValue: boolean = true;
|
||||
hint = '{"kty": ..., "e": ... , "use": ... , "kid": ..., "alg": ... , "n": ...}';
|
||||
@ViewChild("editModal") editModal: AlertModal;
|
||||
@ViewChild("deleteModal") deleteModal: AlertModal;
|
||||
@ViewChild("infoModal") infoModal: AlertModal;
|
||||
|
||||
constructor(private fb: FormBuilder,
|
||||
private apisService: ApisService,
|
||||
private utilsService: UtilitiesService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private userManagementService: UserManagementService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.loading = true;
|
||||
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
|
||||
this.user = user;
|
||||
this.subscriptions.push(this.apisService.getMyServices().subscribe(apis => {
|
||||
this.apis = apis;
|
||||
this.loading = false;
|
||||
}, error => {
|
||||
console.error(error);
|
||||
this.apis = [];
|
||||
this.loading = false;
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => {
|
||||
if(subscription instanceof Subscription) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
openEditModal(index: number = -1) {
|
||||
let api = new API();
|
||||
this.index = index;
|
||||
this.editModal.okButtonLeft = false;
|
||||
if(index !== -1) {
|
||||
api = this.apis[index];
|
||||
this.editModal.alertTitle = "Edit Service";
|
||||
this.editModal.okButtonText = "Update";
|
||||
} else {
|
||||
this.editModal.alertTitle = "Create Service";
|
||||
this.editModal.okButtonText = "Create";
|
||||
}
|
||||
this.form = this.fb.group({
|
||||
name: this.fb.control(api.service.name, Validators.required),
|
||||
keyType: this.fb.control(api.service.keyType),
|
||||
logoURL: this.fb.control(api.details.logoUri, [StringUtils.urlValidator()]),
|
||||
url: this.fb.control(api.service.url, [Validators.required, StringUtils.urlValidator()]),
|
||||
uri: this.fb.control(api.details.jwksUri, [StringUtils.urlValidator()]),
|
||||
value: this.fb.control(null, [StringUtils.jsonValidator('The format should be {"kty": ..., "e": ... , "use": ... , "kid": ..., "alg": ... , "n": ...}')])
|
||||
});
|
||||
if(api.details?.jwks?.keys) {
|
||||
this.form.get('value').setValue(JSON.stringify(api.details.jwks.keys[0]));
|
||||
}
|
||||
this.advanced = !!this.form.get('keyType').getRawValue();
|
||||
this.byValue = this.advanced && this.form.get('keyType').getRawValue() === 'value';
|
||||
this.formChanges();
|
||||
this.editModal.open();
|
||||
}
|
||||
|
||||
openDeleteModal(index: number) {
|
||||
this.index = index;
|
||||
let api = this.apis[this.index];
|
||||
this.deleteModal.alertTitle = 'Delete Service';
|
||||
this.deleteModal.alertMessage = true;
|
||||
this.deleteModal.message = 'You are going to delete ' + api.service.name + '. Are you sure you want to proceed?';
|
||||
this.deleteModal.okButtonText = 'Yes';
|
||||
this.deleteModal.cancelButtonText = 'No';
|
||||
this.deleteModal.open();
|
||||
}
|
||||
|
||||
openInfoModal(index: number) {
|
||||
this.api = this.apis[index];
|
||||
this.infoModal.okButton = false;
|
||||
this.infoModal.cancelButtonText = 'Close';
|
||||
this.infoModal.alertTitle = 'Details for ' + this.api.details.clientName;
|
||||
this.infoModal.open();
|
||||
}
|
||||
|
||||
save() {
|
||||
this.loading = true;
|
||||
if(this.index === -1) {
|
||||
this.subscriptions.push(this.apisService.create(this.form.getRawValue()).subscribe(api => {
|
||||
this.apis.push(api)
|
||||
NotificationHandler.rise('Your service has been created successfully.');
|
||||
this.loading = false;
|
||||
}, error => {
|
||||
console.error(error);
|
||||
NotificationHandler.rise('An error has occurred. Please try again later.', 'danger');
|
||||
this.loading = false;
|
||||
}));
|
||||
} else {
|
||||
this.subscriptions.push(this.apisService.save(this.apis[this.index].service.id, this.form.getRawValue()).subscribe(api => {
|
||||
this.apis[this.index] = api;
|
||||
NotificationHandler.rise('Your service has been created successfully.');
|
||||
this.loading = false;
|
||||
}, error => {
|
||||
console.error(error);
|
||||
NotificationHandler.rise('An error has occurred. Please try again later.', 'danger');
|
||||
this.loading = false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
confirm() {
|
||||
this.loading = true;
|
||||
this.subscriptions.push(this.apisService.delete(this.apis[this.index].service.id).subscribe(() => {
|
||||
this.apis.splice(this.index, 1);
|
||||
NotificationHandler.rise('Your service has been created deleted.');
|
||||
this.loading = false;
|
||||
}, error => {
|
||||
console.error(error);
|
||||
NotificationHandler.rise('An error has occurred. Please try again later.', 'danger');
|
||||
this.loading = false;
|
||||
}));
|
||||
}
|
||||
|
||||
securityChanged(event) {
|
||||
this.advanced = event;
|
||||
if(this.advanced) {
|
||||
this.keyTypeChanged(true);
|
||||
} else {
|
||||
this.form.get('keyType').setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
keyTypeChanged(event) {
|
||||
this.byValue = event;
|
||||
if(this.byValue) {
|
||||
this.form.get('keyType').setValue('value');
|
||||
} else {
|
||||
this.form.get('keyType').setValue('uri');
|
||||
}
|
||||
}
|
||||
|
||||
formChanges() {
|
||||
this.subscriptions.push(this.form.get('keyType').valueChanges.subscribe(value => {
|
||||
if(value === 'value') {
|
||||
this.form.get('value').addValidators(Validators.required);
|
||||
this.form.get('uri').removeValidators(Validators.required);
|
||||
} else if(value === 'uri') {
|
||||
this.form.get('value').removeValidators(Validators.required);
|
||||
this.form.get('uri').addValidators(Validators.required);
|
||||
} else {
|
||||
this.form.get('value').removeValidators(Validators.required);
|
||||
this.form.get('uri').removeValidators(Validators.required);
|
||||
}
|
||||
this.form.get('value').updateValueAndValidity();
|
||||
this.form.get('uri').updateValueAndValidity();
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
}
|
||||
|
||||
jsonPretty(value: any) {
|
||||
return JSON.stringify(value, null, 2);
|
||||
}
|
||||
|
||||
public static getLogoUrl(api: API): string {
|
||||
return api?.details?.logoUri?api.details.logoUri:"assets/common-assets/placeholder.png";
|
||||
}
|
||||
|
||||
copyToClipboard(id: string) {
|
||||
if(copy.exec(id)) {
|
||||
NotificationHandler.rise('Copied to clipboard!');
|
||||
} else {
|
||||
NotificationHandler.rise('Unable to copy to clipboard!', 'danger');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {ApisComponent} from "./apis.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
|
||||
import {LoginGuard} from "../openaireLibrary/login/loginGuard.guard";
|
||||
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
|
||||
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
|
||||
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
|
||||
import {HasPersonalInfoGuard} from "../services/hasPersonalInfo.guard";
|
||||
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
|
||||
import {AlertModalModule} from "../openaireLibrary/utils/modal/alertModal.module";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: ApisComponent,
|
||||
canActivate: [LoginGuard, HasPersonalInfoGuard],
|
||||
canDeactivate: [PreviousRouteRecorder]
|
||||
}
|
||||
]), PageContentModule, InputModule, LoadingModule, IconsModule, AlertModalModule, FormsModule],
|
||||
declarations: [ApisComponent],
|
||||
exports: [ApisComponent]
|
||||
})
|
||||
export class ApisModule {
|
||||
|
||||
}
|
|
@ -1,10 +1,55 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {ErrorPageComponent} from "./error/errorPage.component";
|
||||
import {AdminLoginGuard} from "./openaireLibrary/login/adminLoginGuard.guard";
|
||||
|
||||
const routes: Routes = [];
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
loadChildren: () => import('./home/home.module').then(m => m.HomeModule),
|
||||
data: {hasSidebar: false}
|
||||
},
|
||||
{
|
||||
path: 'personal-info',
|
||||
loadChildren: () => import('./personal-info/personal-info.module').then(m => m.PersonalInfoModule)
|
||||
},
|
||||
{
|
||||
path: 'personal-token',
|
||||
loadChildren: () => import('./personal-token/personal-token.module').then(m => m.PersonalTokenModule)
|
||||
},
|
||||
{
|
||||
path: 'apis',
|
||||
loadChildren: () => import('./apis/apis.module').then(m => m.ApisModule)
|
||||
},
|
||||
{
|
||||
path: 'user-info',
|
||||
loadChildren: () => import('./login/libUser.module').then(m => m.LibUserModule),
|
||||
data: {hasSidebar: false}
|
||||
},
|
||||
{
|
||||
path: 'reload',
|
||||
loadChildren: () => import('./reload/libReload.module').then(m => m.LibReloadModule),
|
||||
data: {hasSidebar: false, hasHeader: false}
|
||||
},
|
||||
{
|
||||
path: 'theme',
|
||||
loadChildren: () => import('./openaireLibrary/utils/theme/theme.module').then(m => m.ThemeModule),
|
||||
canActivateChild: [AdminLoginGuard],
|
||||
data: {hasSidebar: false, hasHeader: false}
|
||||
},
|
||||
{
|
||||
path: 'error',
|
||||
pathMatch: 'full',
|
||||
component: ErrorPageComponent,
|
||||
data: {hasSidebar: false}
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
imports: [RouterModule.forRoot(routes, {
|
||||
onSameUrlNavigation: 'reload'
|
||||
})],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
export class AppRoutingModule {
|
||||
}
|
||||
|
|
|
@ -1,11 +1,114 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {EnvProperties} from "./openaireLibrary/utils/properties/env-properties";
|
||||
import {properties} from "../environments/environment";
|
||||
import {LayoutService} from "./openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
|
||||
import {SmoothScroll} from "./openaireLibrary/utils/smooth-scroll";
|
||||
import {UserManagementService} from "./openaireLibrary/services/user-management.service";
|
||||
import {Subscriber} from "rxjs";
|
||||
import {User} from "./openaireLibrary/login/utils/helper.class";
|
||||
import {MenuItem} from "./openaireLibrary/sharedComponents/menu";
|
||||
import {Header} from "./openaireLibrary/sharedComponents/navigationBar.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<div>test</div>
|
||||
<div *ngIf="loading">
|
||||
<loading [full]="true"></loading>
|
||||
</div>
|
||||
<div *ngIf="!loading">
|
||||
<div class="sidebar_main_swipe" [class.sidebar_main_active]="open && hasSidebar"
|
||||
[class.sidebar_mini]="!open && hasSidebar"
|
||||
[class.sidebar_hover]="hover">
|
||||
<div id="modal-container"></div>
|
||||
<navbar *ngIf="hasHeader" portal="client-management" [header]="menuHeader"
|
||||
[userMenuItems]=userMenuItems [menuItems]="menuItems" [user]="user"></navbar>
|
||||
<div>
|
||||
<dashboard-sidebar *ngIf="hasSidebar" [items]="sideBarItems" [backItem]="backItem"></dashboard-sidebar>
|
||||
<main>
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'client-management-portal';
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
title = 'OpenAIRE APIs Authentication';
|
||||
properties: EnvProperties = properties;
|
||||
user: User;
|
||||
loading = true;
|
||||
hasSidebar: boolean = false;
|
||||
hasHeader: boolean = true;
|
||||
sideBarItems: MenuItem[] = [];
|
||||
menuItems: MenuItem[] = [];
|
||||
backItem: MenuItem;
|
||||
menuHeader: Header = {
|
||||
route: "/",
|
||||
url: null,
|
||||
title: "OpenAIRE APIs Authentication",
|
||||
logoUrl: 'assets/common-assets/common/Logo_Horizontal.png',
|
||||
logoSmallUrl: 'assets/common-assets/common/Logo_Small.png',
|
||||
position: 'center',
|
||||
badge: false
|
||||
};
|
||||
userMenuItems: MenuItem[] = [];
|
||||
private subscriptions: any[] = [];
|
||||
|
||||
constructor(private cdr: ChangeDetectorRef,
|
||||
private smoothScroll: SmoothScroll,
|
||||
private layoutService: LayoutService,
|
||||
private userManagementService: UserManagementService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscriptions.push(this.layoutService.hasSidebar.subscribe(hasSidebar => {
|
||||
this.hasSidebar = hasSidebar;
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
this.subscriptions.push(this.layoutService.hasHeader.subscribe(hasHeader => {
|
||||
this.hasHeader = hasHeader;
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
|
||||
if (user) {
|
||||
this.user = user;
|
||||
} else if (this.user) {
|
||||
this.user = user;
|
||||
}
|
||||
this.buildMenu();
|
||||
this.layoutService.setOpen(true);
|
||||
this.loading = false;
|
||||
}));
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.subscriptions.forEach(value => {
|
||||
if (value instanceof Subscriber) {
|
||||
value.unsubscribe();
|
||||
}
|
||||
});
|
||||
this.userManagementService.clearSubscriptions();
|
||||
this.layoutService.clearSubscriptions();
|
||||
this.smoothScroll.clearSubscriptions();
|
||||
}
|
||||
|
||||
public get open() {
|
||||
return this.layoutService.open;
|
||||
}
|
||||
|
||||
public get hover() {
|
||||
return this.layoutService.hover;
|
||||
}
|
||||
|
||||
buildMenu() {
|
||||
this.backItem = new MenuItem('overview', 'Home', '', '/', false, [], [], null, {name: 'west'});
|
||||
let items: MenuItem[] = [
|
||||
new MenuItem('personal-info', 'Personal Info', '', '/personal-info', false, [], [], null, {name: 'person'}),
|
||||
new MenuItem('personal-token', 'Personal Token', '', '/personal-token', false, [], [], null, {name: 'verified_user'}),
|
||||
new MenuItem('apis', 'Registered Services', '', '/apis', false, [], [], null, {name: 'apps'}),
|
||||
];
|
||||
this.sideBarItems = items;
|
||||
this.userMenuItems = items;
|
||||
this.hasSidebar = this.hasSidebar && this.sideBarItems.length > 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,30 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import {ErrorPageComponent} from "./error/errorPage.component";
|
||||
import {ErrorModule} from "./openaireLibrary/error/error.module";
|
||||
import {SharedModule} from "./openaireLibrary/shared/shared.module";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {LoadingModule} from "./openaireLibrary/utils/loading/loading.module";
|
||||
import {SideBarModule} from "./openaireLibrary/dashboard/sharedComponents/sidebar/sideBar.module";
|
||||
import {NavigationBarModule} from "./openaireLibrary/sharedComponents/navigationBar.module";
|
||||
import {HttpClientModule} from "@angular/common/http";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
AppComponent,
|
||||
ErrorPageComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserAnimationsModule,
|
||||
LoadingModule,
|
||||
HttpClientModule,
|
||||
SideBarModule,
|
||||
BrowserModule,
|
||||
AppRoutingModule
|
||||
AppRoutingModule,
|
||||
ErrorModule,
|
||||
SharedModule,
|
||||
NavigationBarModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'openaire-error',
|
||||
template: `
|
||||
<div class="uk-section">
|
||||
<error></error>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class ErrorPageComponent {
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import {Component, OnInit} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: 'home',
|
||||
template: `
|
||||
<div class="uk-container uk-container-small uk-section uk-text-center">
|
||||
<h2>OpenAIRE APIs Authentication</h2>
|
||||
<div class="uk-margin-large-top">The OpenAIRE APIs can be accessed over HTTPS both by authenticated and unauthenticated requests. To achieve <span class="uk-text-bold">better rate limits</span> you need to make <span class="uk-text-bold">authenticated requests.</span></div>
|
||||
<div class="uk-alert uk-alert-primary uk-flex uk-flex-middle uk-margin-medium-top">
|
||||
<icon name="info" [type]="'outlined'" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">For more information please read the <a href="https://graph.openaire.eu/develop/authentication.html" target="_blank">OpenAIRE API Authentication documentation</a>.</span>
|
||||
</div>
|
||||
<div class="uk-grid uk-grid-large uk-child-width-1-2@m uk-child-width-1-1 uk-margin-large-top" uk-grid>
|
||||
<div>
|
||||
<a routerLink="personal-token" class="uk-card uk-card-default uk-card-hover uk-link-reset uk-card-body uk-flex uk-flex-column uk-flex-center">
|
||||
<h6>Personal Token</h6>
|
||||
<div>
|
||||
Get access to the OpenAIRE APIs with your personal access and refresh token.
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a routerLink="apis" class="uk-card uk-card-default uk-card-hover uk-link-reset uk-card-body uk-flex uk-flex-column uk-flex-center">
|
||||
<h6>Registered Services</h6>
|
||||
<div>
|
||||
Register your services to get access to the OpenAIRE APIs.
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
|
||||
import {HomeComponent} from "./home.component";
|
||||
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
|
||||
|
||||
@NgModule({
|
||||
declarations: [HomeComponent],
|
||||
imports: [CommonModule, RouterModule.forChild([
|
||||
{path: '', component: HomeComponent, canDeactivate: [PreviousRouteRecorder]}
|
||||
]), IconsModule],
|
||||
exports: [HomeComponent]
|
||||
})
|
||||
export class HomeModule {
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
import {OpenaireUserComponent} from './user.component';
|
||||
import {UserRoutingModule} from './user-routing.module';
|
||||
import {UserModule} from '../openaireLibrary/login/user.module';
|
||||
|
||||
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
|
||||
import {SubscribeService} from '../openaireLibrary/utils/subscribe/subscribe.service';
|
||||
import {EmailService} from "../openaireLibrary/utils/email/email.service";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule, FormsModule,
|
||||
UserRoutingModule, UserModule
|
||||
],
|
||||
providers: [PreviousRouteRecorder, SubscribeService, EmailService],
|
||||
declarations: [
|
||||
OpenaireUserComponent
|
||||
]
|
||||
})
|
||||
export class LibUserModule {
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import {OpenaireUserComponent } from './user.component';
|
||||
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{ path: '', component: OpenaireUserComponent, canDeactivate: [PreviousRouteRecorder]},
|
||||
|
||||
])
|
||||
]
|
||||
})
|
||||
export class UserRoutingModule { }
|
|
@ -0,0 +1,10 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'openaire-user',
|
||||
template: `<user></user>`
|
||||
})
|
||||
|
||||
export class OpenaireUserComponent {
|
||||
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit e6d4be54540ff1b23acb88728be9e0e9dd1ebdd1
|
||||
Subproject commit 7d2eb68914b5fc53a4e3dbf8fe22c4f67b8bff7f
|
|
@ -0,0 +1,129 @@
|
|||
import {Component, OnDestroy, OnInit} from "@angular/core";
|
||||
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
|
||||
import {Subscription} from "rxjs";
|
||||
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
|
||||
import {User} from "../openaireLibrary/login/utils/helper.class";
|
||||
import {PersonalInfo, PersonalService} from "../services/personal.service";
|
||||
import {NotificationHandler} from "../openaireLibrary/utils/notification-handler";
|
||||
import {NavigationEnd, Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: `personal-form`,
|
||||
template: `
|
||||
<div page-content>
|
||||
<div inner class="uk-section uk-container uk-container-small">
|
||||
<div *ngIf="loading" class="uk-height-viewport uk-position-relative">
|
||||
<loading class="uk-position-center"></loading>
|
||||
</div>
|
||||
<ng-container *ngIf="form">
|
||||
<div *ngIf="message" class="uk-alert uk-alert-warning uk-margin-medium-bottom uk-text-center">
|
||||
In order to visit Personal Token and Registered Services you have to fill the personal info form below. In case you already have registered services, they are still active but you cannot edit them.
|
||||
</div>
|
||||
<div class="uk-text-center uk-margin-large-bottom">
|
||||
<h3>Personal Info</h3>
|
||||
</div>
|
||||
<div class="uk-grid" uk-grid>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input [formInput]="form.get('name')"
|
||||
[placeholder]="'Name'"></div>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input [formInput]="form.get('surname')"
|
||||
[placeholder]="'Surname'"></div>
|
||||
<div class="uk-width-1-1" input [formInput]="form.get('email')" [placeholder]="'Email'"></div>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input [formInput]="form.get('affiliation')"
|
||||
[placeholder]="'Affiliation'"></div>
|
||||
<div class="uk-width-1-2@m uk-width-1-1" input [formInput]="form.get('position')"
|
||||
[placeholder]="'Position'"></div>
|
||||
</div>
|
||||
<div class="uk-flex uk-flex-right uk-margin-medium-top">
|
||||
<a class="uk-button uk-button-default uk-margin-small-right" routerLink="/">Cancel</a>
|
||||
<button class="uk-button uk-button-primary" [disabled]="form.pristine || form.invalid || form.disabled"
|
||||
[class.uk-disabled]="form.pristine || form.invalid || form.disabled" (click)="save()">Save
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class PersonalInfoComponent implements OnInit, OnDestroy {
|
||||
form: FormGroup;
|
||||
loading: boolean = true;
|
||||
subscriptions: any[] = [];
|
||||
user: User;
|
||||
info: PersonalInfo = null;
|
||||
message: boolean = false;
|
||||
|
||||
constructor(private fb: FormBuilder,
|
||||
private personalService: PersonalService,
|
||||
private userManagementService: UserManagementService,
|
||||
private router: Router) {
|
||||
this.subscriptions.push(this.router.events.subscribe(event => {
|
||||
if(event instanceof NavigationEnd) {
|
||||
const navigation = this.router.getCurrentNavigation();
|
||||
if (navigation && navigation.extras.state) {
|
||||
this.message = navigation.extras.state.message;
|
||||
} else {
|
||||
this.message = false;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscriptions.push(this.personalService.getPersonalInfo().subscribe(info => {
|
||||
this.info = info;
|
||||
this.initForm();
|
||||
this.message = false;
|
||||
}, error => {
|
||||
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
|
||||
this.user = user;
|
||||
this.initForm();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
initForm() {
|
||||
if(this.info) {
|
||||
this.form = this.fb.group({
|
||||
name: this.fb.control(this.info.name, Validators.required),
|
||||
surname: this.fb.control(this.info.surname, Validators.required),
|
||||
email: this.fb.control({value: this.info.email, disabled: true}, Validators.required),
|
||||
affiliation: this.fb.control(this.info.affiliation, Validators.required),
|
||||
position: this.fb.control(this.info.position, Validators.required),
|
||||
});
|
||||
} else {
|
||||
this.form = this.fb.group({
|
||||
name: this.fb.control(this.user.firstname, Validators.required),
|
||||
surname: this.fb.control(this.user.lastname, Validators.required),
|
||||
email: this.fb.control({value: this.user.email, disabled: true}, Validators.required),
|
||||
affiliation: this.fb.control('', Validators.required),
|
||||
position: this.fb.control('', Validators.required),
|
||||
});
|
||||
}
|
||||
this.form.markAsPristine();
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
save() {
|
||||
this.loading = true;
|
||||
this.subscriptions.push(this.personalService.savePersonalInfo(this.form.getRawValue()).subscribe(info => {
|
||||
this.info = info;
|
||||
NotificationHandler.rise('Your personal info has been saved successfully.');
|
||||
this.initForm();
|
||||
this.loading = false;
|
||||
this.message = false;
|
||||
}, error => {
|
||||
console.error(error);
|
||||
NotificationHandler.rise('An error has occurred. Please try again later.', 'danger');
|
||||
this.initForm();
|
||||
this.loading = false;
|
||||
}))
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => {
|
||||
if(subscription instanceof Subscription) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {PersonalInfoComponent} from "./personal-info.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
|
||||
import {LoginGuard} from "../openaireLibrary/login/loginGuard.guard";
|
||||
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
|
||||
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
|
||||
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule.forChild([
|
||||
{path: '', component: PersonalInfoComponent, canActivate: [LoginGuard], canDeactivate: [PreviousRouteRecorder]}
|
||||
]), PageContentModule, InputModule, LoadingModule],
|
||||
declarations: [PersonalInfoComponent],
|
||||
exports: [PersonalInfoComponent]
|
||||
})
|
||||
export class PersonalInfoModule {
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
import {Component, OnInit, ViewChild} from "@angular/core";
|
||||
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
|
||||
import {NotificationHandler} from "../openaireLibrary/utils/notification-handler";
|
||||
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
|
||||
|
||||
declare var copy;
|
||||
|
||||
@Component({
|
||||
selector: 'home',
|
||||
template: `
|
||||
<div page-content>
|
||||
<div inner class="uk-container uk-container-small uk-section">
|
||||
<div class="uk-alert uk-alert-primary uk-flex uk-flex-middle uk-margin-medium-top">
|
||||
<icon name="info" [type]="'outlined'" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">
|
||||
For further information on how to use the tokens please visit the
|
||||
<a href="https://graph.openaire.eu/develop/personalToken.html" target="_blank">OpenAIRE API Authentication documentation</a>.
|
||||
</span>
|
||||
</div>
|
||||
<div class="uk-margin-large-bottom">
|
||||
<h5 class="uk-text-primary">Your personal access token is</h5>
|
||||
<div class="clipboard-wrapper uk-width-1-1 uk-flex uk-flex-middle uk-flex-center">
|
||||
<div class="uk-width-expand">
|
||||
<pre class="uk-margin-remove-bottom uk-flex">
|
||||
<code id="accessToken" class="uk-margin-small-left uk-margin-small-top uk-margin-small-bottom">{{accessToken}}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<a class="uk-width-auto uk-margin-small-left uk-margin-xsmall-right" (click)="copyToClipboard('accessToken')">
|
||||
<icon name="content_copy"></icon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="uk-flex uk-flex-middle uk-margin-small-top">
|
||||
<icon name="info" [type]="'outlined'" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">Your access token is <span class="uk-text-bold">valid for an hour</span>.</span>
|
||||
</div>
|
||||
<div class="uk-text-warning uk-flex uk-flex-middle uk-margin-small-top">
|
||||
<icon name="warning" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">Do not share your personal access token. Send your personal access token only over HTTPS.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!showRefreshToken">
|
||||
<h5 class="uk-text-primary">Do you need a refresh token?</h5>
|
||||
<div class="uk-flex uk-flex-middle uk-margin-small-top">
|
||||
<icon name="info" [type]="'outlined'" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">OpenAIRE refresh token <span class="uk-text-bold">expires after 1 month</span> and allows you to programmatically get a new access token.</span>
|
||||
</div>
|
||||
<button (click)="openRefreshTokenModal()" class="uk-button uk-button-primary uk-margin-medium-top">Get a refresh Token</button>
|
||||
</div>
|
||||
<div *ngIf="showRefreshToken">
|
||||
<h5 class="uk-text-primary">Your refresh token is</h5>
|
||||
<div class="clipboard-wrapper uk-width-1-1 uk-flex uk-flex-middle uk-flex-center">
|
||||
<div class="uk-width-expand">
|
||||
<pre class="uk-margin-remove-bottom uk-flex">
|
||||
<code id="refreshToken" class="uk-margin-small-left uk-margin-small-top uk-margin-small-bottom">{{refreshToken}}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<a class="uk-width-auto uk-margin-small-left uk-margin-xsmall-right" (click)="copyToClipboard('refreshToken')">
|
||||
<icon name="content_copy"></icon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="uk-flex uk-flex-middle uk-margin-small-top">
|
||||
<icon name="info" [type]="'outlined'" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">OpenAIRE refresh token <span class="uk-text-bold">expires after 1 month</span> and allows you to programmatically get a new access token.</span>
|
||||
</div>
|
||||
<div class="uk-text-warning uk-flex uk-flex-middle uk-margin-small-top">
|
||||
<icon name="warning" [flex]="true"></icon>
|
||||
<span class="uk-margin-small-left">Please copy your refresh token and store it confidentially. You will not be able to retrieve it.
|
||||
Do not share your refresh token. Send your refresh token only over HTTPS.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<modal-alert #refreshTokenModal (alertOutput)="getRefreshToken()" [overflowBody]="false"></modal-alert>
|
||||
`
|
||||
})
|
||||
export class PersonalTokenComponent implements OnInit {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
showRefreshToken: boolean = false;
|
||||
subscriptions: any[] = [];
|
||||
@ViewChild("refreshTokenModal") modal: AlertModal;
|
||||
|
||||
constructor(private userManagementService: UserManagementService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
|
||||
this.accessToken = user.accessToken;
|
||||
this.refreshToken = user.refreshToken;
|
||||
}))
|
||||
}
|
||||
|
||||
getRefreshToken() {
|
||||
this.showRefreshToken = true;
|
||||
}
|
||||
|
||||
copyToClipboard(id: string) {
|
||||
if(copy.exec(id)) {
|
||||
NotificationHandler.rise('Copied to clipboard!');
|
||||
} else {
|
||||
NotificationHandler.rise('Unable to copy to clipboard!', 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
openRefreshTokenModal() {
|
||||
this.modal.alertTitle = 'Get refresh token';
|
||||
this.modal.message = 'In case you already have a refresh token, it will no longer be valid. Do you want to proceed?';
|
||||
this.modal.okButtonText = 'Get Refresh Token';
|
||||
this.modal.okButtonLeft = false;
|
||||
this.modal.open();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
|
||||
import {PersonalTokenComponent} from "./personal-token.component";
|
||||
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
|
||||
import {LoginGuard} from "../openaireLibrary/login/loginGuard.guard";
|
||||
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
|
||||
import {AlertModalModule} from "../openaireLibrary/utils/modal/alertModal.module";
|
||||
import {HasPersonalInfoGuard} from "../services/hasPersonalInfo.guard";
|
||||
|
||||
@NgModule({
|
||||
declarations: [PersonalTokenComponent],
|
||||
imports: [CommonModule, RouterModule.forChild([
|
||||
{path: '', component: PersonalTokenComponent, canActivate: [LoginGuard, HasPersonalInfoGuard], canDeactivate: [PreviousRouteRecorder]}
|
||||
]), IconsModule, PageContentModule, AlertModalModule],
|
||||
exports: [PersonalTokenComponent]
|
||||
})
|
||||
export class PersonalTokenModule {
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { NgModule} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ReloadModule } from '../openaireLibrary/reload/reload.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule, FormsModule, RouterModule, ReloadModule
|
||||
]
|
||||
})
|
||||
export class LibReloadModule { }
|
|
@ -0,0 +1,86 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {properties} from "../../environments/environment";
|
||||
import {CustomOptions} from "../openaireLibrary/services/servicesUtils/customOptions.class";
|
||||
|
||||
export class RegisteredService {
|
||||
id: number;
|
||||
clientId: string;
|
||||
creationDate: Date;
|
||||
keyType: "url" | "value" | null;
|
||||
name: string;
|
||||
owner: string;
|
||||
registrationAccessToken: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export class Details {
|
||||
clientId: string;
|
||||
clientIdIssuedAt: number;
|
||||
clientName: string;
|
||||
clientSecret: string;
|
||||
clientSecretExpiresAt: number;
|
||||
contacts: string[];
|
||||
grantTypes: string[];
|
||||
jwks: {
|
||||
keys: [
|
||||
{
|
||||
alg: string;
|
||||
e: string;
|
||||
kid: string;
|
||||
kty: string;
|
||||
n: string
|
||||
}
|
||||
];
|
||||
valid: boolean
|
||||
};
|
||||
jwksUri: string;
|
||||
logoUri: string;
|
||||
policyUri: string;
|
||||
redirectUris: string[];
|
||||
registrationAccessToken: string;
|
||||
registrationClientUri: string;
|
||||
scope: string;
|
||||
tokenEndpointAuthMethod: string;
|
||||
tokenEndpointAuthSigningAlg: string;
|
||||
}
|
||||
|
||||
export class API {
|
||||
service: RegisteredService;
|
||||
details: Details;
|
||||
|
||||
constructor() {
|
||||
this.service = new RegisteredService();
|
||||
this.details = new Details();
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ApisService {
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
|
||||
public getAll(): Observable<API[]> {
|
||||
return this.http.get<API[]>(properties.clientManagementUrl + "/apis/all", CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public getMyServices(): Observable<API[]> {
|
||||
return this.http.get<API[]>(properties.clientManagementUrl + "/apis/my-services", CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public create(form: any): Observable<API> {
|
||||
return this.http.post<API>(properties.clientManagementUrl + "/apis/save/new", form, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public save(id: number, form: any): Observable<API> {
|
||||
return this.http.post<API>(properties.clientManagementUrl + "/apis/save/" + id, form, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public delete(id: number): Observable<void> {
|
||||
return this.http.delete<void>(properties.clientManagementUrl + "/apis/delete/" + id, CustomOptions.registryOptions());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from "@angular/router";
|
||||
import {Injectable} from "@angular/core";
|
||||
import {Observable, of} from "rxjs";
|
||||
import {PersonalService} from "./personal.service";
|
||||
import {catchError, map, tap} from "rxjs/operators";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class HasPersonalInfoGuard implements CanActivate {
|
||||
|
||||
constructor(private personalService: PersonalService,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
return this.personalService.getPersonalInfo().pipe(catchError(() => of(null)), map(info => !!info), tap(hasInfo => {
|
||||
if(!hasInfo) {
|
||||
this.router.navigate(['/personal-info'], {skipLocationChange: true, state: {message: true}});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {properties} from "../../environments/environment";
|
||||
import {CustomOptions} from "../openaireLibrary/services/servicesUtils/customOptions.class";
|
||||
|
||||
export interface PersonalInfo {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
surname: string;
|
||||
affiliation: string;
|
||||
position: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PersonalService {
|
||||
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
|
||||
public getPersonalInfo() {
|
||||
return this.http.get<PersonalInfo>(properties.clientManagementUrl + '/personal/my-info', CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public savePersonalInfo(personalInfo: PersonalInfo) {
|
||||
return this.http.post<PersonalInfo>(properties.clientManagementUrl + '/personal/save', personalInfo, CustomOptions.registryOptions());
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit f15bbfa7265f170e06b256f086f2acedfa3f72e0
|
||||
Subproject commit 39cb4e56d0320975fbd08fb5e9c68b87b0c82a10
|
|
@ -1 +1 @@
|
|||
Subproject commit 468b2b008f474c88dacc52991a5231693833f1f9
|
||||
Subproject commit 1e06310b8b2b56f131754eaded615b6cf32c5848
|
|
@ -0,0 +1,14 @@
|
|||
import {EnvProperties} from '../app/openaireLibrary/utils/properties/env-properties';
|
||||
|
||||
export let properties: EnvProperties = {
|
||||
environment: 'production',
|
||||
dashboard: 'client-management-portal',
|
||||
useCache: false,
|
||||
loginUrl: "https://beta.services.openaire.eu/client-management/openid_connect_login",
|
||||
userInfoUrl: "https://beta.services.openaire.eu/client-management/userInfo",
|
||||
clientManagementUrl: "https://beta.services.openaire.eu/client-management",
|
||||
logoutUrl: "https://beta.services.openaire.eu/client-management/openid_logout",
|
||||
cookieDomain: '.openaire.eu',
|
||||
errorLink: '/error',
|
||||
};
|
||||
|
|
@ -4,9 +4,10 @@ export let properties: EnvProperties = {
|
|||
environment: 'production',
|
||||
dashboard: 'client-management-portal',
|
||||
useCache: false,
|
||||
loginUrl: "https://services.openaire.eu/login-service/openid_connect_login",
|
||||
userInfoUrl: "https://services.openaire.eu/login-service/userInfo",
|
||||
logoutUrl: "https://services.openaire.eu/login-service/openid_logout",
|
||||
loginUrl: "https://services.openaire.eu/client-management/openid_connect_login",
|
||||
userInfoUrl: "https://services.openaire.eu/client-management/userInfo",
|
||||
clientManagementUrl: "https://services.openaire.eu/client-management",
|
||||
logoutUrl: "https://services.openaire.eu/client-management/openid_logout",
|
||||
cookieDomain: '.openaire.eu',
|
||||
errorLink: '/error',
|
||||
};
|
||||
|
|
|
@ -9,9 +9,12 @@ export let properties: EnvProperties = {
|
|||
environment: 'development',
|
||||
dashboard: 'client-management-portal',
|
||||
useCache: false,
|
||||
loginUrl: "http://mpagasas.di.uoa.gr:19080/login-service/openid_connect_login",
|
||||
userInfoUrl: "http://mpagasas.di.uoa.gr:19080/login-service/userInfo",
|
||||
logoutUrl: "http://mpagasas.di.uoa.gr:19080/login-service/openid_logout",
|
||||
loginUrl: "http://mpagasas.di.uoa.gr:19580/client-management/openid_connect_login",
|
||||
userInfoUrl: "http://mpagasas.di.uoa.gr:19580/client-management/userInfo",
|
||||
clientManagementUrl: "http://mpagasas.di.uoa.gr:19580/client-management",
|
||||
logoutUrl: "http://mpagasas.di.uoa.gr:19580/client-management/openid_logout",
|
||||
cookieDomain: '.di.uoa.gr',
|
||||
errorLink: '/error',
|
||||
domain: 'http://mpagasas.di.uoa.gr:5001',
|
||||
baseLink: ''
|
||||
};
|
||||
|
|
|
@ -1 +1,12 @@
|
|||
/* You can add global styles to this file, and also import other style files */
|
||||
@import "~src/assets/openaire-theme/less/_import";
|
||||
@import "~src/assets/common-assets/less/general";
|
||||
@import "~src/assets/common-assets/less/user";
|
||||
@import "~src/assets/common-assets/less/dashboard";
|
||||
|
||||
|
||||
.uk-alert-primary {
|
||||
a, .uk-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue