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:39 UTC

[archiva] branch master updated (fb2a7fd -> 2313e1c)

This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git.


    from fb2a7fd  Additional angular code
     new e597490  changing test pwd
     new 2313e1c  Adding permission handling to webapp

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../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}             |   7 +-
 .../app/directives/view-permission.directive.ts    |  64 +++++++++
 .../main/archiva-web/src/app/model/access-token.ts |   3 +-
 .../model/{user-info.spec.ts => operation.spec.ts} |   6 +-
 .../app/model/{error-message.ts => operation.ts}   |   9 +-
 .../{user-info.spec.ts => permission.spec.ts}      |   6 +-
 .../main/archiva-web/src/app/model/permission.ts}  |  21 ++-
 .../model/{user-info.spec.ts => resource.spec.ts}  |   6 +-
 .../app/model/{error-message.ts => resource.ts}    |   8 +-
 .../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 ++++++++++++++++++++-
 .../test/resources/auto-admin-creation.properties  |   2 +-
 18 files changed, 324 insertions(+), 62 deletions(-)
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/{model/error-message.spec.ts => directives/view-permission.directive.spec.ts} (80%)
 create mode 100644 archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/view-permission.directive.ts
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/{user-info.spec.ts => operation.spec.ts} (88%)
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/{error-message.ts => operation.ts} (87%)
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/{user-info.spec.ts => permission.spec.ts} (87%)
 copy archiva-modules/{archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/ArtifactType.java => archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/permission.ts} (76%)
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/{user-info.spec.ts => resource.spec.ts} (88%)
 copy archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/{error-message.ts => resource.ts} (89%)


[archiva] 01/02: changing test pwd

Posted by ma...@apache.org.
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 e597490140888fced3be9db12a6eb854ce990404
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Wed Nov 4 16:19:52 2020 +0100

    changing test pwd
---
 .../archiva-webapp/src/test/resources/auto-admin-creation.properties    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/resources/auto-admin-creation.properties b/archiva-modules/archiva-web/archiva-webapp/src/test/resources/auto-admin-creation.properties
index 7c8c581..78bdfc7 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/test/resources/auto-admin-creation.properties
+++ b/archiva-modules/archiva-web/archiva-webapp/src/test/resources/auto-admin-creation.properties
@@ -19,4 +19,4 @@
 
 redback.admin.fullname=Archiva Admin
 redback.admin.email=admin@toto.com
-redback.admin.password=admin123
\ No newline at end of file
+redback.admin.password=admin456
\ No newline at end of file


[archiva] 02/02: Adding permission handling to webapp

Posted by ma...@apache.org.
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;
     }
 
 }