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/13 15:55:57 UTC

[archiva] branch master updated: Adding generic error handling

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


The following commit(s) were added to refs/heads/master by this push:
     new 4a72e6f  Adding generic error handling
4a72e6f is described below

commit 4a72e6f0dbb712a2aa43f8755a5cdfe24295e124
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Fri Nov 13 16:39:08 2020 +0100

    Adding generic error handling
---
 .../main/archiva-web/src/app/app-routing.module.ts | 11 +++-
 .../main/archiva-web/src/app/app.component.html    | 19 +++++++
 .../src/main/archiva-web/src/app/app.component.ts  | 47 ++++++++++++++++--
 .../src/main/archiva-web/src/app/app.module.ts     |  5 +-
 .../src/app/modules/core/core.module.ts            | 32 ++++++++++++
 .../modules/core/errors/error-handler.module.ts    | 37 ++++++++++++++
 .../modules/core/errors/global-error-handler.ts    | 32 ++++++++++++
 .../modules/core/errors/http-error-interceptor.ts  | 58 ++++++++++++++++++++++
 .../services/error/error-dialog.service.spec.ts    | 34 +++++++++++++
 .../src/app/services/error/error-dialog.service.ts | 55 ++++++++++++++++++++
 .../src/app/services/routing-guard.service.spec.ts | 34 +++++++++++++
 .../src/app/services/routing-guard.service.ts      | 57 +++++++++++++++++++++
 .../src/main/archiva-web/src/assets/i18n/en.json   | 10 ++++
 13 files changed, 425 insertions(+), 6 deletions(-)

diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app-routing.module.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app-routing.module.ts
index f4699f8..15fcbd7 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app-routing.module.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app-routing.module.ts
@@ -33,6 +33,12 @@ import {SecurityConfigurationComponent} from "./modules/user/security-configurat
 import {ManageUsersListComponent} from "./modules/user/users/manage-users-list/manage-users-list.component";
 import {ManageUsersAddComponent} from "./modules/user/users/manage-users-add/manage-users-add.component";
 import {ManageUsersEditComponent} from "./modules/user/users/manage-users-edit/manage-users-edit.component";
+import {RoutingGuardService as Guard} from "./services/routing-guard.service";
+
+/**
+ * You can use Guard (RoutingGuardService) for permission checking. The service needs data with one parameter 'perm',
+ * that gives the path of the uiPermission map of the user service.
+ */
 
 const routes: Routes = [
   { path: '', component: HomeComponent,
@@ -42,9 +48,10 @@ const routes: Routes = [
     {path:'repo/upload', component: UploadComponent},
     {path:'', redirectTo:'repo/search', pathMatch:'full'},
   ]},
-  { path: 'user', component: HomeComponent,
+  { path: 'user', component: HomeComponent,canActivate:[Guard],data:{perm: 'menu.user.section'},
     children: [
-      { path: 'users', component: ManageUsersComponent,
+      { path: 'users', component: ManageUsersComponent,canActivate:[Guard],
+        data: { perm: 'menu.user.manage' },
         children: [
           {path: 'list', component: ManageUsersListComponent},
           {path: 'add', component: ManageUsersAddComponent},
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 7525842..e1d9bb0 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
@@ -16,6 +16,25 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
+<ng-template #alertcontainer let-modal>
+    <div class="modal-header alert alert-danger">
+        <h5 class="modal-title alert" id="modal-basic-title">{{'error.modal.title'|translate}}</h5>
+        <button type="button" class="close alert" aria-label="{{'modal.close'|translate}}" (click)="modal.dismiss('Cross click')">
+            <span aria-hidden="true">&times;</span>
+        </button>
+    </div>
+    <div class="modal-body">
+        <div class="alert alert-danger">
+        <p>{{'error.modal.info'|translate}}</p>
+        </div>
+        <div *ngFor="let message of errorMessages" class="alert alert-secondary">
+            <p>{{message.message}}</p>
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button type="button" class="btn btn-danger" (click)="modal.close('Save click')">{{'modal.close'|translate}}</button>
+    </div>
+</ng-template>
 <div class="app d-flex flex-column">
     <header>
         <nav class="navbar navbar-expand-md fixed-top navbar-light " style="background-color: #c6cbd2;">
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 e88a6a1..01a1423 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
@@ -16,29 +16,45 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import {Component, OnDestroy, OnInit} from '@angular/core';
+import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild, ViewChildren} from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import { AuthenticationService } from "./services/authentication.service";
 import {UserService} from "./services/user.service";
+import {ErrorDialogService} from "./services/error/error-dialog.service";
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
+import {ErrorMessage} from "./model/error-message";
 
 @Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.scss']
 })
-export class AppComponent implements OnInit, OnDestroy{
+export class AppComponent implements OnInit, OnDestroy {
   title = 'archiva-web';
   version = 'Angular version 10.0.2';
 
+  @ViewChild('alertcontainer') errorAlert;
+  private alertUnsubscribe = new Subject();
+  private errorOpen=false;
+  errorMessages: Array<ErrorMessage> = new Array<ErrorMessage>();
+
+
   constructor(
       public translate: TranslateService,
       public auth: AuthenticationService,
-      public user: UserService
+      public user: UserService,
+      public error: ErrorDialogService,
+      private modalService: NgbModal
   ) {
+
     translate.addLangs(['en', 'de']);
     translate.setDefaultLang('en');
+    this.initializeErrors();
   }
 
+
   switchLang(lang: string) {
     this.translate.use(lang);
     this.user.userInfo.language = lang;
@@ -58,6 +74,8 @@ export class AppComponent implements OnInit, OnDestroy{
 
   ngOnDestroy(): void {
     this.auth.LoginEvent.unsubscribe();
+    this.alertUnsubscribe.next();
+    this.alertUnsubscribe.complete();
   }
 
 
@@ -76,4 +94,27 @@ export class AppComponent implements OnInit, OnDestroy{
     })
 
   }
+
+
+  private initializeErrors()
+  {
+    this
+        .error
+        .getErrors()
+        .pipe(takeUntil(this.alertUnsubscribe))
+        .subscribe((errorMsg) =>
+        {
+          this.errorMessages.push(errorMsg);
+          if (!this.errorOpen) {
+            this.errorOpen=true;
+            this.modalService.open(this.errorAlert).result.then((result) => {
+              this.errorOpen=false;
+              this.errorMessages.length = 0;
+            }, (reason) => {
+              this.errorOpen=false;
+              this.errorMessages.length = 0;
+            });
+          }
+        });
+  }
 }
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 bd46271..d07e42f 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
@@ -47,6 +47,8 @@ import { PaginatedEntitiesComponent } from './modules/general/paginated-entities
 import { SortedTableHeaderComponent } from './modules/general/sorted-table-header/sorted-table-header.component';
 import { SortedTableHeaderRowComponent } from './modules/general/sorted-table-header-row/sorted-table-header-row.component';
 import { ManageUsersEditComponent } from './modules/user/users/manage-users-edit/manage-users-edit.component';
+import {ErrorHandlerModule} from "./modules/core/errors/error-handler.module";
+import {CoreModule} from "./modules/core/core.module";
 
 
 @NgModule({
@@ -91,7 +93,8 @@ import { ManageUsersEditComponent } from './modules/user/users/manage-users-edit
       }
     }),
       NgbPaginationModule,
-      NgbTooltipModule
+      NgbTooltipModule,
+      CoreModule
   ],
   providers: [
     { provide: MESSAGE_FORMAT_CONFIG, useValue: { locales: ['en', 'de'] }}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/core.module.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/core.module.ts
new file mode 100644
index 0000000..28309c2
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/core.module.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import {ErrorHandlerModule} from "./errors/error-handler.module";
+
+
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+      ErrorHandlerModule
+  ]
+})
+export class CoreModule { }
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/error-handler.module.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/error-handler.module.ts
new file mode 100644
index 0000000..12e16de
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/error-handler.module.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 { NgModule, ErrorHandler } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { GlobalErrorHandler } from './global-error-handler';
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { HttpErrorInterceptor } from './http-error-interceptor';
+
+
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+  ],
+  providers: [
+    { provide: ErrorHandler, useClass: GlobalErrorHandler },
+    { provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
+    ]
+})
+export class ErrorHandlerModule { }
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/global-error-handler.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/global-error-handler.ts
new file mode 100644
index 0000000..a4478c7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/global-error-handler.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 {ErrorHandler, Injectable} from "@angular/core";
+
+@Injectable()
+export class GlobalErrorHandler implements ErrorHandler{
+    handleError(error: any): void {
+        try {
+            console.log("GlobalErrorHandler catched: " + error + " - " + typeof (error));
+            console.log("JSON "+JSON.stringify(error));
+        } catch (e) {
+            console.error("Could not log: " + e);
+            //
+        };
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/http-error-interceptor.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/http-error-interceptor.ts
new file mode 100644
index 0000000..a4ebbd5
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/core/errors/http-error-interceptor.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 {
+    HttpHandler,
+    HttpRequest,
+    HttpEvent,
+    HttpErrorResponse,
+    HttpInterceptor
+} from "@angular/common/http";
+import { Observable, throwError } from "rxjs";
+import { catchError, finalize } from "rxjs/operators";
+import { Injectable } from "@angular/core";
+import {ErrorDialogService} from "../../../services/error/error-dialog.service";
+
+/**
+ * Checks for generic HTTP errors and adds messages to the error service.
+ */
+@Injectable()
+export class HttpErrorInterceptor implements HttpInterceptor {
+    constructor(private errorService: ErrorDialogService) {}
+
+    intercept(
+        request: HttpRequest<any>,
+        next: HttpHandler
+    ): Observable<HttpEvent<any>> {
+        return next.handle(request).pipe(
+            catchError((error: HttpErrorResponse) => {
+                console.error("Error from HTTP error interceptor", error);
+                if (error.status==0 && error.statusText=="Unknown Error") {
+                    console.log("Unknown error");
+                    this.errorService.addError('error.http.unknownError');
+                } else if (error.status==403) {
+                    console.log("Permission error "+error.message);
+                    this.errorService.addError('error.http.permissionDenied');
+                }
+                return throwError(error);
+            }),
+            finalize(() => {
+            })
+        ) as Observable<HttpEvent<any>>;
+    }
+}
\ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.spec.ts
new file mode 100644
index 0000000..51cf063
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.spec.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 { TestBed } from '@angular/core/testing';
+
+import { ErrorDialogService } from './error-dialog.service';
+
+describe('ErrorDialogService', () => {
+  let service: ErrorDialogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(ErrorDialogService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.ts
new file mode 100644
index 0000000..e312709
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/error/error-dialog.service.ts
@@ -0,0 +1,55 @@
+/*
+ * 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 {Injectable} from '@angular/core';
+import {ErrorMessage} from "../../model/error-message";
+import { Router } from '@angular/router';
+import { Subject } from 'rxjs';
+import {TranslateService} from "@ngx-translate/core";
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ErrorDialogService {
+
+  private errors= new Subject<ErrorMessage>();
+  private opened = false;
+
+  constructor(private router : Router, private translate : TranslateService) {}
+
+
+  public addError(messageKey:string, args?:string[]) {
+    let msg = new ErrorMessage();
+    msg.error_key = messageKey;
+    msg.args = args;
+    if (msg.message==null||msg.message=='') {
+      msg.message = this.translate.instant(msg.error_key, msg.args);
+    }
+    this.errors.next(msg);
+  }
+
+
+  public getErrors = () =>
+      this.errors.asObservable();
+
+
+  public showError() {
+
+    this.router.navigate(['error'],  { queryParams:{'dialog':true} } );
+  }
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.spec.ts
new file mode 100644
index 0000000..9545ac3
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.spec.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 { TestBed } from '@angular/core/testing';
+
+import { RoutingGuardService } from './routing-guard.service';
+
+describe('RoutingGuardService', () => {
+  let service: RoutingGuardService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(RoutingGuardService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.ts
new file mode 100644
index 0000000..0e7a079
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/routing-guard.service.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { Injectable } from '@angular/core';
+import {UserService} from "./user.service";
+import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
+
+/**
+ * Guard for the routes, that checks permissions by querying the uiPermission map of the UserService.
+ * The guard checks the data in the routing definition for a 'perm' entry and uses this as path for the
+ * uiPermission map.
+ */
+@Injectable({
+  providedIn: 'root'
+})
+export class RoutingGuardService implements CanActivate {
+
+  constructor(private userService:UserService, public router: Router) {
+
+  }
+
+  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+    const permString = route.data.perm;
+    if (permString==null || permString=='') {
+      console.error("Guard active, but permissions not set for route " + state.url);
+      return false;
+    }
+    let perm = this.userService.uiPermissions;
+    for (let permPath of permString.split(/\./)) {
+      perm = perm[permPath];
+      if (perm==null) {
+        perm=false;
+        break;
+      }
+    }
+    console.debug("Permission for " + state.url + ": " + perm);
+    if (!perm) {
+      this.router.navigate(['']);
+    }
+    return perm;
+  }
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
index aaffa09..a94ad54 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
@@ -16,6 +16,16 @@
     "about": "About",
     "contact": "Contact"
   },
+  "error": {
+    "modal": {
+      "title": "Application Error",
+      "info":"The backend does not answer as expected. Please check, if your archiva service is running. See detail messages below."
+    },
+    "http": {
+      "unknownError": "We got a bad response from the backend REST service. Maybe the connection is broken, or the service is down. Please check your network to the backend service and the archiva.log for any errors.",
+      "permissionDenied": "You are not allowed to access the data from the backend service. Try to login again and/or check your permissions."
+    }
+  },
   "sidemenu": {
     "repo": {
       "section": "Artifacts",