You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2020/11/04 15:20:41 UTC
[archiva] 02/02: Adding permission handling to webapp
This is an automated email from the ASF dual-hosted git repository.
martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git
commit 2313e1cd86e8091bfcfe074b77e698becea8790e
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Wed Nov 4 16:20:31 2020 +0100
Adding permission handling to webapp
---
.../main/archiva-web/src/app/app.component.html | 6 +-
.../src/main/archiva-web/src/app/app.component.ts | 8 +-
.../src/main/archiva-web/src/app/app.module.ts | 2 +
.../view-permission.directive.spec.ts} | 20 +--
.../app/directives/view-permission.directive.ts | 64 +++++++++
.../main/archiva-web/src/app/model/access-token.ts | 3 +-
.../model/{access-token.ts => operation.spec.ts} | 19 ++-
.../app/model/{access-token.ts => operation.ts} | 16 +--
.../model/{access-token.ts => permission.spec.ts} | 19 ++-
.../app/model/{access-token.ts => permission.ts} | 21 +--
.../model/{access-token.ts => resource.spec.ts} | 19 ++-
.../src/app/model/{access-token.ts => resource.ts} | 15 +-
.../main/archiva-web/src/app/model/user-info.ts | 1 -
.../general/sidemenu/sidemenu.component.html | 16 ++-
.../modules/general/sidemenu/sidemenu.component.ts | 7 +-
.../src/app/services/authentication.service.ts | 55 +++++--
.../archiva-web/src/app/services/user.service.ts | 159 ++++++++++++++++++++-
17 files changed, 353 insertions(+), 97 deletions(-)
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.html
index f223be3..fd24fdc 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.html
@@ -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>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.ts
index 3dae41b..e88a6a1 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.component.ts
@@ -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));
})
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts
index aa38842..451e095 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts
@@ -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,
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.spec.ts
similarity index 70%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.spec.ts
index 6204371..9c3bb9b 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.spec.ts
@@ -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
@@ -16,11 +15,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
-}
+
+import { ViewPermissionDirective } from './view-permission.directive';
+
+describe('ViewPermissionDirective', () => {
+ it('should create an instance', () => {
+ const directive = new ViewPermissionDirective(null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.ts
new file mode 100644
index 0000000..70aeadb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.ts
@@ -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();
+ }
+ }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
index 6204371..9b3649d 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
@@ -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
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.spec.ts
similarity index 77%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.spec.ts
index 6204371..35849e2 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.spec.ts
@@ -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
@@ -16,11 +15,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
-}
+
+import { Operation } from './operation';
+
+describe('Operation', () => {
+ it('should create an instance', () => {
+ expect(new Operation()).toBeTruthy();
+ });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.ts
similarity index 77%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.ts
index 6204371..eded8ae 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/operation.ts
@@ -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
@@ -16,11 +15,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
+
+export class Operation {
+ name: string;
+ description: string;
+ descriptionKey: string;
+ permanent: boolean;
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.spec.ts
similarity index 77%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.spec.ts
index 6204371..bf2e5af 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.spec.ts
@@ -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
@@ -16,11 +15,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
-}
+
+import { Permission } from './permission';
+
+describe('Permission', () => {
+ it('should create an instance', () => {
+ expect(new Permission()).toBeTruthy();
+ });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.ts
similarity index 72%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.ts
index 6204371..53d00cf 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.ts
@@ -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
@@ -16,11 +15,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
+
+import {Operation} from "./operation";
+import {Resource} from "./resource";
+
+export class Permission {
+ name: string;
+ description: string;
+ permanent: boolean;
+ descriptionKey: string;
+ operation: Operation;
+ resource: Resource;
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.spec.ts
similarity index 77%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.spec.ts
index 6204371..10ed83c 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.spec.ts
@@ -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
@@ -16,11 +15,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
-}
+
+import { Resource } from './resource';
+
+describe('Resource', () => {
+ it('should create an instance', () => {
+ expect(new Resource()).toBeTruthy();
+ });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.ts
similarity index 77%
copy from archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
copy to archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.ts
index 6204371..f00f39f 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/resource.ts
@@ -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
@@ -16,11 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-export class AccessToken {
- access_token: string;
- refresh_token: string;
- expires_in: number;
- token_type: string;
- scope: string;
- state: string;
+
+export class Resource {
+ identifier: string;
+ permanent: boolean;
+ pattern: boolean;
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user-info.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user-info.ts
index 6356fe2..0ac142b 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user-info.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user-info.ts
@@ -28,7 +28,6 @@ export class UserInfo {
timestampAccountCreation:Date;
timestampLastLogin:Date;
timestampLastPasswordChange:Date;
- assignedRoles:string[];
readOnly:boolean;
userManagerId:string;
validationToken:string;
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.html
index 81b53df..c394e89 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.html
@@ -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"
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.ts
index a02692d..c4fa16c 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sidemenu/sidemenu.component.ts
@@ -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 {
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts
index ba4cdb1..b4a2478 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts
@@ -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();
}
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
index 3360e55..a1cc652 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
@@ -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: () => {
@@ -75,6 +133,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;
}
}