refresh token on expire added

This commit is contained in:
Lucio Lelii 2023-03-08 17:13:03 +01:00
parent 0c60c05f45
commit 839e4ef118
13 changed files with 150 additions and 126 deletions

View File

@ -1,22 +1,23 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { EventType } from '@angular/router';
import { resolve } from 'dns';
import { KeycloakService } from 'keycloak-angular';
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
@Injectable({
providedIn: 'root'
})
export class D4sAuthService {
redirectUrl: string = 'd4sworkspace://org.gcube.workspace/'; //'http://localhost:8100/'; //
redirectUrl: string = 'http://localhost:8100/'; //'d4sworkspace://org.gcube.workspace/'; //
umaUrl : string = " https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token";
umaUrl: string = " https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token";
audience: string = '%2Fgcube';
config: any = undefined;
uma : UmaToken | undefined ;
uma: UmaToken | undefined;
constructor(private keycloak: KeycloakService, private httpClient: HttpClient) {
}
@ -29,9 +30,7 @@ export class D4sAuthService {
}
if (!this.isAuthorized())
throw("error authorizing");
await this.entitlement(this.audience).then( res => this.uma = res);
throw ("error authorizing");
}
isAuthorized(): boolean {
@ -40,43 +39,65 @@ export class D4sAuthService {
else
return auth;
}
getSecureHeader(): string{
return "Bearer "+this.uma?.access_token;
parseJwt(token: string) {
var base64Url = token.split('.')[1]
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
}).join(''))
return JSON.parse(jsonPayload);
}
async getSecureHeader(): Promise<string> {
var mustUpdate = false;
if (this.keycloak.isTokenExpired(30)) {
await this.keycloak.updateToken();
mustUpdate = true;
console.log("token refreshed");
}
if (mustUpdate || !this.uma)
this.uma = await this.entitlement(this.audience);
return "Bearer " + this.uma.access_token;
}
entitlement(resourceServerId: any): Promise<UmaToken> {
return new Promise((resolve, reject) => {
const keycloak = this.keycloak.getKeycloakInstance();
var params = "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket"
const audience = encodeURIComponent(resourceServerId)
params += "&audience=" + audience;
console.log("params "+params);
this.httpClient.post<UmaToken>(this.umaUrl, params , { headers: {
"Content-type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + this.keycloak.getKeycloakInstance().token
} }).subscribe(
console.log("params " + params);
this.httpClient.post<UmaToken>(this.umaUrl, params, {
headers: {
"Content-type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + this.keycloak.getKeycloakInstance().token
}
}).subscribe(
{
error: (err) => reject("error getting uma token "+err),
next: (res:UmaToken) => resolve(res)
}
error: (err) => reject("error getting uma token " + err),
next: (res: UmaToken) => resolve(res)
}
);
});
}
}
class UmaToken{
class UmaToken {
constructor(public upgraded :boolean,
public access_token:string,
constructor(public upgraded: boolean,
public access_token: string,
public expires_in: number,
public refresh_expires_in: number,
public refresh_token: string,
public token_type: string,
public not_before_policy:number){}
public not_before_policy: number) { }
}

View File

@ -13,7 +13,7 @@ export abstract class Action {
return undefined;
}
abstract actionHandler(data: any, storagehub: StoragehubService): Observable<any>;
abstract actionHandler(data: any, storagehub: StoragehubService): any;
abstract getName(): string;

View File

@ -17,19 +17,19 @@ export class CopyAction extends Action {
notClickableIds: [item.item.id],
notSelectableIds: [item.item.parentId],
onSelected: (destinationItem: WSItem) => {
this.actionHandler({ item: item, destinationItem: destinationItem }, storagehub).subscribe(
this.actionHandler({ item: item, destinationItem: destinationItem }, storagehub).then( (obs) => obs.subscribe(
() => {
reload();
notify(`${item.getTitle()} copied`);
}
)
))
}
}
};
}
actionHandler(data: { item: WSItem, destinationItem: WSItem }, storagehub: StoragehubService): Observable<any> {
actionHandler(data: { item: WSItem, destinationItem: WSItem }, storagehub: StoragehubService){
return storagehub.copyItem(data.destinationItem.item.id, data.item.item.id, data.item.item.name);
}

View File

@ -6,46 +6,46 @@ import { Action } from "./action";
export class CreateFolderAction extends Action {
override getAlertOptions(item: WSItem, storagehub: StoragehubService, reload: Function): AlertOptions {
var title = item.getTitle();
var options: AlertOptions = {
header: 'Create folder',
message: 'Please specify the name of the new folder',
inputs: [
{
name: 'name',
type: 'text',
placeholder: 'new folder'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'Create',
handler: (data) => {
this.actionHandler({wsitem: item, name: data.name}, storagehub).subscribe(
() => reload()
);
}
}
]
};
return options;
override getAlertOptions(item: WSItem, storagehub: StoragehubService, reload: Function): AlertOptions {
var title = item.getTitle();
var options: AlertOptions = {
header: 'Create folder',
message: 'Please specify the name of the new folder',
inputs: [
{
name: 'name',
type: 'text',
placeholder: 'new folder'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'Create',
handler: (data) => {
this.actionHandler({ wsitem: item, name: data.name }, storagehub).then((obs) => obs.subscribe(
() => reload()
)
);
}
}
]
};
return options;
}
actionHandler(data: {wsitem: WSItem, name : string}, storagehub: StoragehubService): Observable<any> {
return storagehub.createFolder(data.wsitem.item.id, data.name, "");
}
}
actionHandler(data: { wsitem: WSItem, name: string }, storagehub: StoragehubService) {
return storagehub.createFolder(data.wsitem.item.id, data.name, "");
}
getName(): string {
return "Create Folder";
}
getActionType(): string | undefined {
return undefined;
}
getName(): string {
return "Create Folder";
}
getActionType(): string | undefined {
return undefined;
}
}

View File

@ -17,16 +17,16 @@ export class DeleteAction extends Action {
{
text: 'Yes',
handler: () => {
this.actionHandler(item, storagehub).subscribe(
this.actionHandler(item, storagehub).then((obs) => obs.subscribe(
() => reload()
);
));
}
}]
};
return options;
}
actionHandler(data: WSItem, storagehub: StoragehubService): Observable<any> {
actionHandler(data: WSItem, storagehub: StoragehubService) {
return storagehub.deleteItem(data.item.id);
}

View File

@ -17,19 +17,19 @@ export class MoveAction extends Action {
notClickableIds: [item.item.id],
notSelectableIds: [item.item.parentId],
onSelected: (destinationItem:WSItem) =>{
this.actionHandler({item: item, destinationItem: destinationItem}, storagehub).subscribe(
this.actionHandler({item: item, destinationItem: destinationItem}, storagehub).then( (obs) => obs.subscribe(
() => {
reload();
notify(`${item.getTitle()} moved`);
}
)
))
}
}
};
}
actionHandler(data: {item: WSItem, destinationItem : WSItem}, storagehub: StoragehubService): Observable<any> {
actionHandler(data: {item: WSItem, destinationItem : WSItem}, storagehub: StoragehubService) {
return storagehub.moveItem(data.destinationItem.item.id, data.item.item.id);
}

View File

@ -26,9 +26,9 @@ export class RenameAction extends Action {
{
text: 'Rename',
handler: (data) => {
this.actionHandler({item: item, newName: data.name}, storagehub).subscribe(
this.actionHandler({item: item, newName: data.name}, storagehub).then( (obs) => obs.subscribe(
() => reload()
);
));
}
}
]
@ -36,7 +36,7 @@ export class RenameAction extends Action {
return options;
}
actionHandler(data: {item: WSItem, newName : string}, storagehub: StoragehubService): Observable<any> {
actionHandler(data: {item: WSItem, newName : string}, storagehub: StoragehubService) {
return storagehub.renameItem(data.item.item.id, data.newName);
}

View File

@ -76,7 +76,7 @@ export class ShowFolderComponent implements OnInit {
loadDocuments() {
this.filteredItems = undefined;
if (this.parentItem) {
this.storagehub.getChildren(this.parentItem.item.id).subscribe(
this.storagehub.getChildren(this.parentItem.item.id).then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = []
const tmpFiltered$: WSItem[] = []
@ -90,6 +90,7 @@ export class ShowFolderComponent implements OnInit {
this._items = tmpItems$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
this.filteredItems = tmpFiltered$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
})
)
}
}
@ -160,12 +161,13 @@ export class ShowFolderComponent implements OnInit {
if (selected && this.parentItem) {
this.underUploadItem = [selected.name];
const upload$ = this.storagehub.uploadFile(this.parentItem.item.id, selected.name, selected);
upload$.subscribe({
upload$.then( (obs) => obs.subscribe({
next: () => this.loadDocuments(),
error: () => this.underUploadItem = [],
complete: () => this.underUploadItem = []
});
})
);
}
}

View File

@ -18,17 +18,17 @@ export class StoragehubService {
}
getWsRoot() {
async getWsRoot() {
const getWsURL = `${shURL}?exclude=hl:accounting`;
const bearer = this.auth.getSecureHeader();
const bearer = await this.auth.getSecureHeader();
return this.http.get<ItemWrapper>(getWsURL, {headers: {"Authorization": bearer }, observe: 'body', responseType: 'json'}).pipe(
map(value => value.item),
catchError(this.error)
);
}
getTrashRoot(): Observable<Item> {
const bearer = this.auth.getSecureHeader();
async getTrashRoot(): Promise<Observable<Item>> {
const bearer = await this.auth.getSecureHeader();
const getTrashURL = `${shURL}/trash/?exclude=hl:accounting`;
return this.http.get<ItemWrapper>(getTrashURL, {headers: {"Authorization": bearer }, observe: "body", responseType: "json"}).pipe(
map(value => value.item),
@ -36,8 +36,8 @@ export class StoragehubService {
);
}
getVres(): Observable<Item[]> {
const bearer = this.auth.getSecureHeader();
async getVres(): Promise<Observable<Item[]>> {
const bearer = await this.auth.getSecureHeader();
const getVresURL = `${shURL}/vrefolders/?exclude=hl:accounting`;
return this.http.get<ItemList>(getVresURL, {headers: {"Authorization": bearer }, observe: 'body', responseType: 'json'}).pipe(
map(value => value.itemlist),
@ -45,8 +45,8 @@ export class StoragehubService {
);
}
getItem(id: string): Observable<Item> {
const bearer = this.auth.getSecureHeader();
async getItem(id: string): Promise<Observable<Item>> {
const bearer = await this.auth.getSecureHeader();
const getWsURL = `${shURL}/items/${id}?exclude=hl:accounting`;
return this.http.get<ItemWrapper>(getWsURL, {headers: {"Authorization": bearer }, observe: 'body', responseType: 'json'}).pipe(
map(value => value.item),
@ -54,8 +54,8 @@ export class StoragehubService {
);
}
getChildren(id:string, onlyFolder?:boolean): Observable<Item[]>{
const bearer = this.auth.getSecureHeader();
async getChildren(id:string, onlyFolder?:boolean): Promise<Observable<Item[]>>{
const bearer = await this.auth.getSecureHeader();
let getWsURL = `${shURL}/items/${id}/children?exclude=hl:accounting`;
if (onlyFolder)
getWsURL += '&onlyType=nthl:workspaceItem';
@ -65,8 +65,8 @@ export class StoragehubService {
);
}
getAnchestor(id:string): Observable<Item[]>{
const bearer = this.auth.getSecureHeader();
async getAnchestor(id:string): Promise<Observable<Item[]>>{
const bearer = await this.auth.getSecureHeader();
let getWsURL = `${shURL}/items/${id}/ancherstors?exclude=hl:accounting`;
console.log("ws children "+getWsURL);
return this.http.get<ItemList>(getWsURL, {headers: {"Authorization": bearer }, observe: 'body', responseType: 'json'}).pipe(
@ -75,8 +75,8 @@ export class StoragehubService {
);
}
uploadFile(parentId: string, name: string, file: File){
const bearer = this.auth.getSecureHeader();
async uploadFile(parentId: string, name: string, file: File){
const bearer = await this.auth.getSecureHeader();
let uploadURL = `${shURL}/items/${parentId}/create/FILE`;
const formData = new FormData();
formData.append("name", name);
@ -87,8 +87,8 @@ export class StoragehubService {
);
}
createFolder(parentId: string, name: string, description: string) : Observable<any> {
const bearer = this.auth.getSecureHeader();
async createFolder(parentId: string, name: string, description: string) {
const bearer = await this.auth.getSecureHeader();
let createFolderURL = `${shURL}/items/${parentId}/create/FOLDER`;
const formData = new FormData();
let body = `name=${name}&description=${description}`;
@ -97,16 +97,16 @@ export class StoragehubService {
);
}
deleteItem(itemId: string) : Observable<any> {
const bearer = this.auth.getSecureHeader();
async deleteItem(itemId: string) : Promise<Observable<any>> {
const bearer = await this.auth.getSecureHeader();
let deleteItemUrl = `${shURL}/items/${itemId}`;
return this.http.delete( deleteItemUrl).pipe(
catchError(this.error)
);
}
renameItem(itemId: string, newName: string) : Observable<any> {
const bearer = this.auth.getSecureHeader();
async renameItem(itemId: string, newName: string) {
const bearer = await this.auth.getSecureHeader();
let renameItemUrl = `${shURL}/items/${itemId}/rename`;
let body = `newName=${newName}`;
return this.http.put(renameItemUrl,body,{observe: 'body', responseType: 'text' ,headers: { 'Content-Type' : 'application/x-www-form-urlencoded', "Authorization": bearer }}).pipe(
@ -114,8 +114,8 @@ export class StoragehubService {
);
}
copyItem(destinationId: string, itemId: string, name:string) : Observable<any> {
const bearer = this.auth.getSecureHeader();
async copyItem(destinationId: string, itemId: string, name:string) {
const bearer = await this.auth.getSecureHeader();
let copyItemUrl = `${shURL}/items/${itemId}/copy`;
let body = `destinationId=${destinationId}&fileName=${name}`;
return this.http.put(copyItemUrl,body,{observe: 'body', responseType: 'text' ,headers: { 'Content-Type' : 'application/x-www-form-urlencoded', "Authorization": bearer }}).pipe(
@ -123,8 +123,8 @@ export class StoragehubService {
);
}
moveItem(destinationId: string, itemId: string) : Observable<any> {
const bearer = this.auth.getSecureHeader();
async moveItem(destinationId: string, itemId: string) {
const bearer = await this.auth.getSecureHeader();
let copyItemUrl = `${shURL}/items/${itemId}/move`;
let body = `destinationId=${destinationId}`;
return this.http.put(copyItemUrl,body,{observe: 'body', responseType: 'text' ,headers: { 'Content-Type' : 'application/x-www-form-urlencoded', "Authorization": bearer }}).pipe(

View File

@ -20,19 +20,19 @@ export class TrashPage implements OnInit {
ngOnInit() {
this.storagehub.getTrashRoot().subscribe(
this.storagehub.getTrashRoot().then((obs) => obs.subscribe(
(res) => this.onSuccess(res)
);
));
}
private onSuccess(res: Item) {
this.storagehub.getChildren(res.id, false).subscribe(
this.storagehub.getChildren(res.id, false).then((obs) => obs.subscribe(
(res) => {
const tmpItems$ : WSItem[] = []
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
)
))
}
public getValues(): WSItem[] {

View File

@ -34,20 +34,20 @@ export class VresPage implements OnInit {
this.root = !folderId;
if (!tmpItem) {
if (!folderId)
this.storagehub.getVres().subscribe(
this.storagehub.getVres().then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
);
));
else //folder is not cached
this.storagehub.getItem(folderId).subscribe(
this.storagehub.getItem(folderId).then( (obs) => obs.subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
));
} else {
this.item = tmpItem;
@ -58,13 +58,13 @@ export class VresPage implements OnInit {
private onSuccess(item: Item) {
this.storagehub.getChildren(item.id, false).subscribe(
this.storagehub.getChildren(item.id, false).then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
)
))
}
public getValues(): WSItem[] | undefined {

View File

@ -41,25 +41,26 @@ export class WsViewerComponent implements OnInit {
loadDocuments() {
if (this.currentItem) {
this.storagehub.getChildren(this.currentItem.item.id).subscribe(
this.storagehub.getChildren(this.currentItem.item.id).then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.items = tmpItems$.sort(Sorting.getSortFunction(SortName.FolderFirst, SortType.Asc));
})
);
} else
this.storagehub.getWsRoot().subscribe(
this.storagehub.getWsRoot().then( (obs) => obs.subscribe(
(res) => this.addVresToWs(new WSItem(res))
);
));
}
addVresToWs(wsRoot: WSItem) {
this.storagehub.getVres().subscribe(
this.storagehub.getVres().then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = [wsRoot]
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.items = tmpItems$;
})
}));
}
isCurrentItemSelectable(){

View File

@ -36,19 +36,19 @@ export class WsPage implements OnInit {
this.root = !folderId;
if (!tmpItem) {
if (!folderId)
this.storagehub.getWsRoot().subscribe(
this.storagehub.getWsRoot().then( (obs) => obs.subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
));
else //folder is not cached
this.storagehub.getItem(folderId).subscribe(
this.storagehub.getItem(folderId).then( (obs) => obs.subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
));
} else {
this.item = tmpItem;
this.onSuccess(tmpItem.item);
@ -58,13 +58,13 @@ export class WsPage implements OnInit {
private onSuccess(item: Item) {
this.storagehub.getChildren(item.id, false).subscribe(
this.storagehub.getChildren(item.id, false).then( (obs) => obs.subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
)
))
}
public getValues(): WSItem[] | undefined {