@@ -29,7 +29,7 @@ | |||
<div class="collapse navbar-collapse" id="navbarsDefault"> | |||
<div class="navbar-nav ml-auto"> | |||
<span *ngIf="auth.loggedIn" class="navbar-text border-right pr-2 mr-2"> | |||
<span *ngIf="auth.authenticated" class="navbar-text border-right pr-2 mr-2"> | |||
{{user.userInfo.fullName}} | |||
</span> | |||
<ul class="navbar-nav"> | |||
@@ -38,12 +38,12 @@ | |||
<i class="fas fa-home mr-1"></i>{{ 'menu.home' |translate }} | |||
</a> | |||
</li> | |||
<li *ngIf="!auth.loggedIn" class="nav-item active"> | |||
<li *ngIf="!auth.authenticated" class="nav-item active"> | |||
<a class="nav-link" routerLink="/login" data-toggle="modal" data-target="#loginModal"> | |||
<i class="fas fa-user mr-1"></i>{{'menu.login' | translate}} | |||
</a> | |||
</li> | |||
<li *ngIf="auth.loggedIn" class="nav-item active"> | |||
<li *ngIf="auth.authenticated" class="nav-item active"> | |||
<a class="nav-link" routerLink="/logout" (click)="auth.logout()"> | |||
<i class="fas fa-user mr-1"></i>{{'menu.logout' | translate}} | |||
</a> |
@@ -62,17 +62,17 @@ export class AppComponent implements OnInit, OnDestroy{ | |||
ngOnInit(): void { | |||
let lang = this.user.userInfo.language; | |||
if (lang==null) { | |||
this.translate.use('en'); | |||
if (this.user.userInfo!=null && this.user.userInfo.language!=null ) { | |||
this.translate.use(this.user.userInfo.language); | |||
} else { | |||
this.translate.use(lang); | |||
this.translate.use('en'); | |||
} | |||
// Subscribe to login event in authenticator to switch the language | |||
this.auth.LoginEvent.subscribe(userInfo => { | |||
if (userInfo.language != null) { | |||
this.switchLang(userInfo.language); | |||
} | |||
// console.log("Permissions: " + JSON.stringify(this.user.permissions)); | |||
}) | |||
} |
@@ -31,6 +31,7 @@ import { NotFoundComponent } from './modules/general/not-found/not-found.compone | |||
import { SidemenuComponent } from './modules/general/sidemenu/sidemenu.component'; | |||
import {FormsModule, ReactiveFormsModule} from "@angular/forms"; | |||
import { LoginComponent } from './modules/general/login/login.component'; | |||
import { ViewPermissionDirective } from './directives/view-permission.directive'; | |||
@NgModule({ | |||
declarations: [ | |||
@@ -41,6 +42,7 @@ import { LoginComponent } from './modules/general/login/login.component'; | |||
NotFoundComponent, | |||
SidemenuComponent, | |||
LoginComponent, | |||
ViewPermissionDirective, | |||
], | |||
imports: [ | |||
BrowserModule, |
@@ -0,0 +1,26 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { ViewPermissionDirective } from './view-permission.directive'; | |||
describe('ViewPermissionDirective', () => { | |||
it('should create an instance', () => { | |||
const directive = new ViewPermissionDirective(null, null); | |||
expect(directive).toBeTruthy(); | |||
}); | |||
}); |
@@ -0,0 +1,64 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import {Directive, ElementRef, Input, OnChanges, OnInit, Renderer2, SimpleChanges} from '@angular/core'; | |||
/** | |||
* This directive can be used to render based on permissions | |||
*/ | |||
@Directive({ | |||
selector: '[appViewPermission]' | |||
}) | |||
export class ViewPermissionDirective implements OnInit, OnChanges { | |||
@Input('appViewPermission') permission: boolean; | |||
constructor(private renderer: Renderer2, private el: ElementRef) { | |||
} | |||
ngOnInit(): void { | |||
// console.log("Init appViewPermission " + this.permission + " " + typeof (this.permission)); | |||
// this.togglePermission(); | |||
} | |||
private togglePermission() { | |||
if (this.permission) { | |||
this.removeClass("d-none"); | |||
} else { | |||
this.addClass("d-none"); | |||
} | |||
} | |||
addClass(className: string) { | |||
// make sure you declare classname in your main style.css | |||
this.renderer.addClass(this.el.nativeElement, className); | |||
} | |||
removeClass(className: string) { | |||
this.renderer.removeClass(this.el.nativeElement, className); | |||
} | |||
ngOnChanges(changes: SimpleChanges): void { | |||
if (changes.permission != null && | |||
(changes.permission.firstChange || changes.permission.currentValue != changes.permission.previousValue)) { | |||
// console.debug("Changed " + JSON.stringify(changes)); | |||
this.togglePermission(); | |||
} | |||
} | |||
} |
@@ -7,8 +7,7 @@ | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
@@ -0,0 +1,25 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { Operation } from './operation'; | |||
describe('Operation', () => { | |||
it('should create an instance', () => { | |||
expect(new Operation()).toBeTruthy(); | |||
}); | |||
}); |
@@ -0,0 +1,24 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
export class Operation { | |||
name: string; | |||
description: string; | |||
descriptionKey: string; | |||
permanent: boolean; | |||
} |
@@ -0,0 +1,25 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { Permission } from './permission'; | |||
describe('Permission', () => { | |||
it('should create an instance', () => { | |||
expect(new Permission()).toBeTruthy(); | |||
}); | |||
}); |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import {Operation} from "./operation"; | |||
import {Resource} from "./resource"; | |||
export class Permission { | |||
name: string; | |||
description: string; | |||
permanent: boolean; | |||
descriptionKey: string; | |||
operation: Operation; | |||
resource: Resource; | |||
} |
@@ -0,0 +1,25 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { Resource } from './resource'; | |||
describe('Resource', () => { | |||
it('should create an instance', () => { | |||
expect(new Resource()).toBeTruthy(); | |||
}); | |||
}); |
@@ -0,0 +1,23 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you under the Apache License, Version 2.0 (the | |||
* "License"); you may not use this file except in compliance | |||
* with the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* Unless required by applicable law or agreed to in writing, | |||
* software distributed under the License is distributed on an | |||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
export class Resource { | |||
identifier: string; | |||
permanent: boolean; | |||
pattern: boolean; | |||
} |
@@ -28,7 +28,6 @@ export class UserInfo { | |||
timestampAccountCreation:Date; | |||
timestampLastLogin:Date; | |||
timestampLastPasswordChange:Date; | |||
assignedRoles:string[]; | |||
readOnly:boolean; | |||
userManagerId:string; | |||
validationToken:string; |
@@ -18,19 +18,22 @@ | |||
--> | |||
<nav class="nav flex-column nav-pills " role="tablist" aria-orientation="vertical"> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Artifacts</a> | |||
<div [appViewPermission]="perms.menu.repo.section"> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" >Artifacts</a> | |||
<a class="nav-link active my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-search" aria-selected="true">Search</a> | |||
role="tab" aria-controls="v-pills-search" aria-selected="true" >Search</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Browse</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Upload Artifact</a> | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false" | |||
[appViewPermission]="perms.menu.repo.upload">Upload Artifact</a> | |||
</div> | |||
<div [appViewPermission]="perms.menu.admin.section"> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Administration</a> | |||
role="tab" aria-controls="v-pills-home" aria-selected="false" >Administration</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Repository Groups</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
@@ -51,6 +54,8 @@ | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">UI Configuration</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Reports</a> | |||
</div> | |||
<div [appViewPermission]="perms.menu.user.section"> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Users</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
@@ -59,6 +64,7 @@ | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Roles</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Users Runtime Configuration</a> | |||
</div> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Documentation</a> | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" |
@@ -17,6 +17,7 @@ | |||
* under the License. | |||
*/ | |||
import { Component, OnInit } from '@angular/core'; | |||
import {UserService} from "../../../services/user.service"; | |||
@Component({ | |||
selector: 'app-sidemenu', | |||
@@ -25,7 +26,11 @@ import { Component, OnInit } from '@angular/core'; | |||
}) | |||
export class SidemenuComponent implements OnInit { | |||
constructor() { } | |||
perms; | |||
constructor(private user: UserService) { | |||
this.perms = user.uiPermissions; | |||
} | |||
ngOnInit(): void { | |||
} |
@@ -33,17 +33,22 @@ import {UserInfo} from "../model/user-info"; | |||
providedIn: 'root' | |||
}) | |||
export class AuthenticationService { | |||
loggedIn: boolean; | |||
authenticated: boolean; | |||
/** | |||
* The LoginEvent is emitted, when a successful login happened. And the corresponding user info was retrieved. | |||
*/ | |||
public LoginEvent: EventEmitter<UserInfo> = new EventEmitter<UserInfo>(); | |||
/** | |||
* The LogoutEvent is emitted, when the user has been logged out. | |||
*/ | |||
public LogoutEvent: EventEmitter<any> = new EventEmitter<any>(); | |||
constructor(private rest: ArchivaRequestService, | |||
private userService: UserService) { | |||
this.loggedIn = false; | |||
this.authenticated = false; | |||
this.restoreLoginData(); | |||
} | |||
@@ -55,12 +60,34 @@ export class AuthenticationService { | |||
let expDate = new Date(expirationDate); | |||
let currentDate = new Date(); | |||
if (currentDate < expDate) { | |||
this.loggedIn = true | |||
let observer = this.userService.retrieveUserInfo(); | |||
observer.subscribe(userInfo => | |||
this.LoginEvent.emit(userInfo) | |||
observer.subscribe({ | |||
next: (userInfo: UserInfo) => { | |||
if (userInfo != null) { | |||
let permObserver = this.userService.retrievePermissionInfo(); | |||
permObserver.subscribe({ | |||
next: () => { | |||
this.authenticated = true; | |||
this.LoginEvent.emit(userInfo) | |||
}, | |||
error: (err) => { | |||
console.debug("Error retrieving perms: " + JSON.stringify(err)); | |||
} | |||
} | |||
) | |||
} | |||
}, | |||
error: (err: HttpErrorResponse) => { | |||
console.debug("Error retrieving user info: " + JSON.stringify(err)); | |||
this.logout(); | |||
} | |||
} | |||
); | |||
} else { | |||
this.logout(); | |||
} | |||
} else { | |||
this.logout(); | |||
} | |||
} | |||
@@ -94,9 +121,16 @@ export class AuthenticationService { | |||
localStorage.setItem("token_expire", dt.toISOString()); | |||
} | |||
let userObserver = this.userService.retrieveUserInfo(); | |||
this.loggedIn = true; | |||
userObserver.subscribe(userInfo => | |||
this.LoginEvent.emit(userInfo)); | |||
this.authenticated = true; | |||
userObserver.subscribe(userInfo => { | |||
if (userInfo != null) { | |||
let permObserver = this.userService.retrievePermissionInfo(); | |||
permObserver.subscribe((perms) => { | |||
this.LoginEvent.emit(userInfo); | |||
} | |||
) | |||
} | |||
}); | |||
resultHandler("OK"); | |||
}, | |||
error: (err: HttpErrorResponse) => { | |||
@@ -104,7 +138,7 @@ export class AuthenticationService { | |||
let result = err.error as ErrorResult | |||
if (result.errorMessages != null) { | |||
for (let msg of result.errorMessages) { | |||
console.error('Observer got an error: ' + msg.errorKey) | |||
console.debug('Observer got an error: ' + msg.errorKey) | |||
} | |||
resultHandler("ERROR", result.errorMessages); | |||
} else { | |||
@@ -125,8 +159,9 @@ export class AuthenticationService { | |||
localStorage.removeItem("access_token"); | |||
localStorage.removeItem("refresh_token"); | |||
localStorage.removeItem("token_expire"); | |||
this.loggedIn = false; | |||
this.authenticated = false; | |||
this.userService.resetUser(); | |||
this.rest.resetToken(); | |||
this.LogoutEvent.emit(); | |||
} | |||
} |
@@ -16,23 +16,77 @@ | |||
* under the License. | |||
*/ | |||
import {Injectable} from '@angular/core'; | |||
import {Injectable, OnDestroy, OnInit} from '@angular/core'; | |||
import {ArchivaRequestService} from "./archiva-request.service"; | |||
import {UserInfo} from '../model/user-info'; | |||
import {HttpErrorResponse} from "@angular/common/http"; | |||
import {ErrorResult} from "../model/error-result"; | |||
import {Observable} from "rxjs"; | |||
import {Permission} from '../model/permission'; | |||
@Injectable({ | |||
providedIn: 'root' | |||
}) | |||
export class UserService { | |||
export class UserService implements OnInit, OnDestroy { | |||
userInfo: UserInfo; | |||
permissions: Permission[]; | |||
guestPermissions: Permission[]; | |||
authenticated: boolean; | |||
uiPermissionsDefault = { | |||
'menu': { | |||
'repo':{ | |||
'section':true, | |||
'browse':true, | |||
'search':true, | |||
'upload':false | |||
}, | |||
'admin':{ | |||
'section':false, | |||
'config':false, | |||
'status':false, | |||
'reports':false | |||
}, | |||
'user':{ | |||
'section':false, | |||
'manage':false, | |||
'roles':false, | |||
'config':false | |||
} | |||
} | |||
}; | |||
uiPermissions; | |||
constructor(private rest: ArchivaRequestService) { | |||
this.userInfo = new UserInfo() | |||
this.userInfo = new UserInfo(); | |||
this.uiPermissions = {}; | |||
this.deepCopy(this.uiPermissionsDefault, this.uiPermissions); | |||
} | |||
ngOnDestroy(): void { | |||
this.resetUser(); | |||
} | |||
ngOnInit(): void { | |||
this.userInfo.user_id = "guest"; | |||
this.loadPersistedUserInfo(); | |||
this.authenticated = false; | |||
this.deepCopy(this.uiPermissionsDefault, this.uiPermissions); | |||
if (this.guestPermissions == null) { | |||
let observer = { | |||
next: (permList: Permission[]) => { | |||
this.guestPermissions = permList; | |||
if (!this.authenticated) { | |||
this.permissions = this.guestPermissions; | |||
this.parsePermissions(this.permissions); | |||
} | |||
}, | |||
error: err => { | |||
console.log("Could not retrieve permissions "+err); | |||
} | |||
} | |||
this.retrievePermissionInfo().subscribe(observer); | |||
} | |||
} | |||
/** | |||
@@ -53,16 +107,20 @@ export class UserService { | |||
this.loadPersistedUserInfo(); | |||
} | |||
this.persistUserInfo(); | |||
this.authenticated = true; | |||
resultObserver.next(this.userInfo); | |||
}, | |||
error: (err: HttpErrorResponse) => { | |||
console.log("Error " + (JSON.stringify(err))); | |||
let result = err.error as ErrorResult | |||
if (result.errorMessages != null) { | |||
if (result != null && result.errorMessages != null) { | |||
for (let msg of result.errorMessages) { | |||
console.error('Observer got an error: ' + msg.errorKey) | |||
} | |||
} else if (err.message != null) { | |||
console.error("Bad response from user info call: " + err.message); | |||
} | |||
this.authenticated = false; | |||
resultObserver.error(); | |||
}, | |||
complete: () => { | |||
@@ -74,6 +132,96 @@ export class UserService { | |||
}); | |||
} | |||
/** | |||
* Retrieves the permission list from the REST service | |||
*/ | |||
public retrievePermissionInfo(): Observable<Permission[]> { | |||
return new Observable<Permission[]>((resultObserver) => { | |||
let userName = this.authenticated ? "me" : "guest"; | |||
let infoObserver = this.rest.executeRestCall<Permission[]>("get", "redback", "users/" + userName + "/permissions", null); | |||
let permissionObserver = { | |||
next: (x: Permission[]) => { | |||
this.permissions = x; | |||
this.parsePermissions(x); | |||
resultObserver.next(this.permissions); | |||
}, | |||
error: (err: HttpErrorResponse) => { | |||
console.log("Error " + (JSON.stringify(err))); | |||
let result = err.error as ErrorResult | |||
if (result.errorMessages != null) { | |||
for (let msg of result.errorMessages) { | |||
console.debug('Observer got an error: ' + msg.errorKey) | |||
} | |||
} | |||
this.resetPermissions(); | |||
resultObserver.error(err); | |||
}, | |||
complete: () => { | |||
resultObserver.complete(); | |||
} | |||
}; | |||
infoObserver.subscribe(permissionObserver); | |||
}); | |||
} | |||
resetPermissions() { | |||
this.deepCopy(this.uiPermissionsDefault, this.uiPermissions); | |||
} | |||
parsePermissions(permissions: Permission[]) { | |||
this.resetPermissions(); | |||
for ( let perm of permissions) { | |||
// console.debug("Checking permission for op: " + perm.operation.name); | |||
switch (perm.operation.name) { | |||
case "archiva-manage-configuration": { | |||
if (perm.resource.identifier=='*') { | |||
this.uiPermissions.menu.admin.section = true; | |||
this.uiPermissions.menu.admin.config = true; | |||
this.uiPermissions.menu.admin.reports = true; | |||
this.uiPermissions.menu.admin.status = true; | |||
} | |||
} | |||
case "archiva-manage-users": { | |||
if (perm.resource.identifier=='*') { | |||
this.uiPermissions.menu.user.section = true; | |||
this.uiPermissions.menu.user.config = true; | |||
this.uiPermissions.menu.user.manage = true; | |||
this.uiPermissions.menu.user.roles = true; | |||
} | |||
} | |||
case "redback-configuration-edit": { | |||
if (perm.resource.identifier=='*') { | |||
this.uiPermissions.menu.user.section = true; | |||
this.uiPermissions.menu.user.config = true; | |||
} | |||
} | |||
case "archiva-upload-file": { | |||
this.uiPermissions.menu.repo.upload = true; | |||
} | |||
} | |||
} | |||
console.log("New permissions: " + JSON.stringify(this.uiPermissions)); | |||
} | |||
private deepCopy(src: Object, dst: Object) { | |||
Object.keys(src).forEach((key, idx) => { | |||
let srcEl = src[key]; | |||
if (typeof(srcEl)=='object' ) { | |||
let dstEl; | |||
if (!dst.hasOwnProperty(key)) { | |||
dst[key] = {} | |||
} | |||
dstEl = dst[key]; | |||
this.deepCopy(srcEl, dstEl); | |||
} else { | |||
// console.debug("setting " + key + " = " + srcEl); | |||
dst[key] = srcEl; | |||
} | |||
}); | |||
} | |||
/** | |||
* Stores user information persistent. Not the complete UserInfo object, only properties, that | |||
* are needed. | |||
@@ -104,6 +252,9 @@ export class UserService { | |||
*/ | |||
resetUser() { | |||
this.userInfo = new UserInfo(); | |||
this.userInfo.user_id = "guest"; | |||
this.resetPermissions(); | |||
this.authenticated = false; | |||
} | |||
} |