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/14 20:38:58 UTC

[archiva] branch master updated: Finishing user operations for angular app

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 6097363  Finishing user operations for angular app
6097363 is described below

commit 609736386bfa70bd29dbaf1ca34cd08581d58f37
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Sat Nov 14 21:22:38 2020 +0100

    Finishing user operations for angular app
---
 .../main/archiva-web/src/app/app-routing.module.ts |  2 +
 .../src/app/modules/user/user.module.ts            |  4 +-
 .../manage-users-add.component.html                |  2 +-
 .../manage-users-add/manage-users-add.component.ts | 16 +---
 .../user/users/manage-users-base.component.ts      | 19 +++++
 .../manage-users-delete.component.html             | 35 +++++++++
 .../manage-users-delete.component.scss             | 18 +++++
 .../manage-users-delete.component.spec.ts          | 43 +++++++++++
 .../manage-users-delete.component.ts               | 71 +++++++++++++++++
 .../manage-users-edit.component.html               |  8 +-
 .../manage-users-edit.component.ts                 | 89 ++++++++++++++--------
 .../manage-users-list.component.html               |  5 ++
 .../src/app/services/archiva-request.service.ts    |  8 ++
 .../archiva-web/src/app/services/user.service.ts   | 10 +++
 .../src/main/archiva-web/src/assets/i18n/en.json   | 10 +++
 15 files changed, 287 insertions(+), 53 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 084b0c1..186a698 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
@@ -34,6 +34,7 @@ import {ManageUsersListComponent} from "./modules/user/users/manage-users-list/m
 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";
+import {ManageUsersDeleteComponent} from "./modules/user/users/manage-users-delete/manage-users-delete.component";
 
 /**
  * You can use Guard (RoutingGuardService) for permission checking. The service needs data with one parameter 'perm',
@@ -57,6 +58,7 @@ const routes: Routes = [
           {path: 'add', component: ManageUsersAddComponent},
           {path: 'edit/:userid', component: ManageUsersEditComponent},
           {path: 'edit', redirectTo:'edit/guest' },
+          {path: 'delete/:userid', component: ManageUsersDeleteComponent},
           {path: '', redirectTo:'list', pathMatch:'full'}
         ]
       },
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/user.module.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/user.module.ts
index 1ca65cc..9897c1f 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/user.module.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/user.module.ts
@@ -24,6 +24,7 @@ import {ManageUsersAddComponent} from "./users/manage-users-add/manage-users-add
 import {ManageUsersEditComponent} from "./users/manage-users-edit/manage-users-edit.component";
 import {SharedModule} from "../shared/shared.module";
 import {FormsModule, ReactiveFormsModule} from "@angular/forms";
+import { ManageUsersDeleteComponent } from './users/manage-users-delete/manage-users-delete.component';
 
 
 
@@ -32,7 +33,8 @@ import {FormsModule, ReactiveFormsModule} from "@angular/forms";
       ManageUsersComponent,
       ManageUsersListComponent,
       ManageUsersAddComponent,
-      ManageUsersEditComponent
+      ManageUsersEditComponent,
+      ManageUsersDeleteComponent
   ],
   exports: [
     ManageUsersComponent,
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
index 13b764c..4f95595 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
@@ -89,7 +89,7 @@
                 [attr.disabled]="userForm.valid?null:true">{{'users.add.submit'|translate}}</button>
     </div>
     <div *ngIf="success" class="alert alert-success" role="alert">
-        User <a [routerLink]="['user','users','edit',result?.user_id]">{{result?.userid}}</a> was added to the list.
+        User <a [routerLink]="['/user','users','edit',result?.user_id]">{{result?.user_id}}</a> was added to the list.
     </div>
     <div *ngIf="error" class="alert alert-danger" role="alert" >
         <h4 class="alert-heading">{{'users.add.errortitle'|translate}}</h4>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
index d77f598..6588813 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
@@ -68,26 +68,12 @@ export class ManageUsersAddComponent extends ManageUsersBaseComponent implements
                 this.result = user;
                 this.success = true;
                 this.error = false;
+                this.userForm.reset(this.formInitialValues);
             });
         }
     }
 
-    getAllErrors(formGroup: FormGroup, errors: string[] = []) : string[] {
-        Object.keys(formGroup.controls).forEach(field => {
-            const control = formGroup.get(field);
-            if (control instanceof FormControl && control.errors != null) {
-                let keys = Object.keys(control.errors).map(errorKey=>field+'.'+errorKey);
-                errors = errors.concat(keys);
-            } else if (control instanceof FormGroup) {
-                errors = errors.concat(this.getAllErrors(control));
-            }
-        });
-        return errors;
-    }
 
-    getAttributeErrors(control:string):string[] {
-        return Object.keys(this.userForm.get(control).errors);
-    }
 
 
 
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-base.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-base.component.ts
index c6ea8a9..42a27e8 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-base.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-base.component.ts
@@ -43,6 +43,7 @@ export class ManageUsersBaseComponent {
     errorResult: ErrorResult;
     result: UserInfo;
     user: string;
+    formInitialValues;
 
     userForm = this.fb.group({
         user_id: ['', [Validators.required, Validators.minLength(this.minUserIdSize), whitespaceValidator()], this.userUidExistsValidator()],
@@ -58,6 +59,7 @@ export class ManageUsersBaseComponent {
     })
 
     constructor(public userService: UserService, public fb: FormBuilder) {
+        this.formInitialValues=this.userForm.value
     }
 
 
@@ -117,6 +119,23 @@ export class ManageUsersBaseComponent {
             return forbidden ? {forbiddenName: {value: control.value}} : null;
         };
     }
+
+    getAllErrors(formGroup: FormGroup, errors: string[] = []) : string[] {
+        Object.keys(formGroup.controls).forEach(field => {
+            const control = formGroup.get(field);
+            if (control instanceof FormControl && control.errors != null) {
+                let keys = Object.keys(control.errors).map(errorKey=>field+'.'+errorKey);
+                errors = errors.concat(keys);
+            } else if (control instanceof FormGroup) {
+                errors = errors.concat(this.getAllErrors(control));
+            }
+        });
+        return errors;
+    }
+
+    getAttributeErrors(control:string):string[] {
+        return Object.keys(this.userForm.get(control).errors);
+    }
 }
 
 export function whitespaceValidator(): ValidatorFn {
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.html
new file mode 100644
index 0000000..23e4177
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.html
@@ -0,0 +1,35 @@
+<!--
+  ~ 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.
+  -->
+
+<ng-template #userdelete let-modal>
+    <div class="modal-header">
+        <h5 class="modal-title alert" id="modal-basic-title">{{'users.delete.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-warning">
+            <p [innerHTML]="'users.delete.modal.text'|translate:{'user_id':user_id}"></p>
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button type="button" class="btn btn-danger" (click)="modal.close('YES')">{{'form.button.yes'|translate}}</button>
+        <button type="button" class="btn btn-secondary" (click)="modal.close('NO')">{{'form.button.no'|translate}}</button>
+    </div>
+</ng-template>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.scss b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.scss
new file mode 100644
index 0000000..343c3b1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.scss
@@ -0,0 +1,18 @@
+/*!
+ * 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.
+ */
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.spec.ts
new file mode 100644
index 0000000..d51fdaa
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * 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 { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ManageUsersDeleteComponent } from './manage-users-delete.component';
+
+describe('ManageUsersDeleteComponent', () => {
+  let component: ManageUsersDeleteComponent;
+  let fixture: ComponentFixture<ManageUsersDeleteComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ManageUsersDeleteComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ManageUsersDeleteComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.ts
new file mode 100644
index 0000000..fcfc438
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-delete/manage-users-delete.component.ts
@@ -0,0 +1,71 @@
+/*
+ * 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 {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
+import {ActivatedRoute, Router} from "@angular/router";
+import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
+import {UserService} from "../../../../services/user.service";
+
+@Component({
+  selector: 'app-manage-users-delete',
+  templateUrl: './manage-users-delete.component.html',
+  styleUrls: ['./manage-users-delete.component.scss']
+})
+export class ManageUsersDeleteComponent implements OnInit, AfterViewInit {
+
+  @ViewChild('userdelete') askModal;
+
+  user_id: string;
+
+  constructor(private route: ActivatedRoute, private modal: NgbModal,
+              private userService: UserService, private router : Router) {
+    this.route.params.subscribe((params)=>{
+      if (params.userid) {
+        this.user_id = params.userid;
+      }
+    })
+  }
+
+  ngOnInit(): void {
+
+  }
+
+  private runModal() {
+    if (this.user_id!=null && this.user_id!='') {
+      let modalInstance = this.modal.open(this.askModal).result.then((result) => {
+        console.log("Result: " + result);
+        let userId = this.user_id;
+        if (result=='YES' && userId!=null && userId!='') {
+          let deleted = this.userService.deleteUser(userId).subscribe();
+          if (deleted) {
+            this.router.navigate(['/user','users','list']);
+          }
+        }
+      }, (reason) => {
+        console.log("Reason: " + reason);
+      });
+    }
+  }
+
+  ngAfterViewInit(): void {
+    if (this.user_id!=null) {
+      this.runModal();
+    }
+  }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.html
index 8fa520d..ba8becf 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.html
@@ -20,7 +20,7 @@
     <div class="form-group row col-md-8" *ngIf="!editUser.permanent">
         <div class="col-md-1">Edit <span class="fas fa-edit"></span></div>
         <div class="col-md-6">
-            <input class="form-check-input" type="checkbox" [value]="editMode"
+            <input class="form-check-input" type="checkbox" [value]="editMode" [checked]="editMode"
                    (change)="editMode=!editMode"
             >
         </div>
@@ -121,9 +121,9 @@
                 [disabled]="userForm.invalid || !userForm.dirty">{{'users.edit.submit'|translate}}</button>
     </div>
     <div *ngIf="success" class="alert alert-success" role="alert">
-        User <a [routerLink]="['user','users','edit',userid]">{{userid}}</a> was added to the list.
+        User has been updated.
     </div>
-    <div *ngIf="editMode && error" class="alert alert-danger" role="alert">
+    <div *ngIf="error" class="alert alert-danger" role="alert">
         <h4 class="alert-heading">Errors</h4>
         <ng-container *ngFor="let message of errorResult?.error_messages; first as isFirst">
             <hr *ngIf="!isFirst">
@@ -131,7 +131,7 @@
         </ng-container>
     </div>
     <div *ngIf="editMode && userForm.invalid" class="alert alert-danger" role="alert" >
-        <h4 class="alert-heading">Errors</h4>
+        <h4 class="alert-heading">Validation Errors</h4>
         <ng-container *ngFor="let message of getAllErrors(userForm); first as isFirst" >
             <hr *ngIf="!isFirst">
             <p>{{message}}</p>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.ts
index f7eead0..288b552 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-edit/manage-users-edit.component.ts
@@ -16,53 +16,78 @@
  * under the License.
  */
 
-import { Component, OnInit } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
 import {UserService} from "../../../../services/user.service";
 import {FormBuilder, FormControl} from "@angular/forms";
-import {map, switchMap} from 'rxjs/operators';
+import {catchError, map, switchMap, tap} from 'rxjs/operators';
 import {ManageUsersBaseComponent} from "../manage-users-base.component";
+import {ErrorResult} from "../../../../model/error-result";
 
 @Component({
-  selector: 'app-manage-users-edit',
-  templateUrl: './manage-users-edit.component.html',
-  styleUrls: ['./manage-users-edit.component.scss']
+    selector: 'app-manage-users-edit',
+    templateUrl: './manage-users-edit.component.html',
+    styleUrls: ['./manage-users-edit.component.scss']
 })
 export class ManageUsersEditComponent extends ManageUsersBaseComponent implements OnInit {
 
-  editProperties = ['user_id', 'full_name', 'email', 'locked', 'password_change_required',
-    'password', 'confirm_password', 'validated'];
-  editUser;
-  originUser;
-  editMode:boolean=false;
-  minUserIdSize=0;
+    editProperties = ['user_id', 'full_name', 'email', 'locked', 'password_change_required',
+        'password', 'confirm_password', 'validated'];
+    editUser;
+    originUser;
+    editMode: boolean;
+    minUserIdSize = 0;
 
-  constructor(private route: ActivatedRoute, public userService: UserService, public fb: FormBuilder) {
-    super(userService, fb);
-    this.editUser = this.route.params.pipe(map (params => params.userid ),  switchMap(userid => userService.getUser(userid))  ).subscribe(user => {
-      this.editUser = user;
-      this.originUser = user;
-      this.copyToForm(this.editProperties, this.editUser);});
-  }
+    constructor(private route: ActivatedRoute, public userService: UserService, public fb: FormBuilder) {
+        super(userService, fb);
+        this.editMode=false;
+        this.route.queryParams.subscribe((params)=>{
+          if (params.editmode) {
+            this.editMode=true;
+          }
+        })
+        this.editUser = this.route.params.pipe(
+            map(params => params.userid), switchMap(userid => userService.getUser(userid))).subscribe(user => {
+            this.editUser = user;
+            this.originUser = user;
+            this.copyToForm(this.editProperties, this.editUser);
+        });
+    }
 
-  ngOnInit(): void {
-    this.userForm.setControl('user_id', new FormControl());
-  }
+    ngOnInit(): void {
+      // This resets the validators of the base class
+      this.userForm.get('user_id').clearValidators();
+      this.userForm.get('user_id').clearAsyncValidators();
+    }
 
-  valid(field: string): string[] {
-    if (this.editMode) {
-      let classArr  = super.valid(field);
-      return classArr.concat('form-control')
-    } else {
-      return ['form-control-plaintext'];
+    valid(field: string): string[] {
+        if (this.editMode) {
+            let classArr = super.valid(field);
+            return classArr.concat('form-control')
+        } else {
+            return ['form-control-plaintext'];
+        }
     }
-  }
 
 
-  onSubmit() {
-    this.copyFromForm(this.editProperties)
+    onSubmit() {
+        let user = this.copyFromForm(this.editProperties);
+        this.userService.updateUser(user).pipe(
+            catchError((err: ErrorResult) => {
+                this.error = true;
+                this.success = false;
+                this.errorResult = err;
+                return [];
+            })
+        ).subscribe(userInfo=>{
+            this.error=false;
+            this.success=true;
+            this.errorResult=null;
+            this.result = userInfo;
+            this.editMode = false;
+        });
 
-  }
+    }
 
 
 }
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
index 960e16d..f8763f2 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
@@ -39,6 +39,7 @@
             <app-th-sorted [fieldArray]="['last_login']" contentText="users.attributes.last_login"></app-th-sorted>
             <app-th-sorted [fieldArray]="['created']" contentText="users.attributes.created" ></app-th-sorted>
             <app-th-sorted [fieldArray]="['last_password_change']" contentText="users.attributes.last_password_change"></app-th-sorted>
+            <th>Action</th>
         </tr>
         </thead>
         <tbody>
@@ -55,6 +56,10 @@
             <td>{{user.timestamp_last_login | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
             <td>{{user.timestamp_account_creation | date : 'yyyy-MM-ddTHH:mm:ss'}}</td>
             <td>{{user.timestamp_last_password_change| date : 'yyyy-MM-ddTHH:mm:ss'}}</td>
+            <td><ng-container *ngIf="!user.permanent"><a  [routerLink]="['..','edit', user.user_id]" [queryParams]="{editmode:true}" ><span class="fas fa-edit"></span></a>
+                &nbsp;&nbsp; <a *ngIf="!user.permanent" [routerLink]="['..','delete',user.user_id]"><span class="fas fa-user-minus"></span></a>
+            </ng-container>
+            </td>
         </tr>
         </tbody>
     </table>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
index 2f1e993..52a55e6 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
@@ -54,6 +54,10 @@ export class ArchivaRequestService {
             return this.http.head<R>(httpArgs.url, httpArgs.options);
         } else if (lType == "post") {
             return this.http.post<R>(httpArgs.url, input, httpArgs.options);
+        } else if (lType == "delete") {
+            return this.http.delete<R>(httpArgs.url, httpArgs.options);
+        } else if (lType == "put") {
+            return this.http.put<R>(httpArgs.url, input, httpArgs.options);
         }
     }
 
@@ -91,6 +95,10 @@ export class ArchivaRequestService {
             return this.http.head<HttpResponse<R>>(httpArgs.url, httpArgs.options);
         } else if (lType == 'post') {
             return this.http.post<HttpResponse<R>>(httpArgs.url, input, httpArgs.options);
+        } else if (lType=='delete') {
+            return this.http.delete<HttpResponse<R>>(httpArgs.url, httpArgs.options);
+        } else if (lType=='put') {
+            return this.http.put<HttpResponse<R>>(httpArgs.url, input, httpArgs.options);
         }
     }
 
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 f6eccab..3354acf 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
@@ -329,6 +329,16 @@ export class UserService implements OnInit, OnDestroy {
             }));
     }
 
+    public deleteUser(user_id:string): Observable<boolean> {
+        return this.rest.executeResponseCall<boolean>("delete", "redback", "users/" + user_id, null).pipe(
+            catchError((error: HttpErrorResponse) => {
+                return throwError(this.rest.getTranslatedErrorResult(error));
+            }),
+            map((response) => {
+                return response.status == 200;
+            }));
+    }
+
     public userExists(userid:string): Observable<boolean> {
         console.log("Checking user " + userid);
         return this.rest.executeResponseCall<string>("head", "redback", "users/" + userid, null).pipe(
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 a94ad54..d3c0c41 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
@@ -107,6 +107,12 @@
       "small": {
         "password": "If the password field is empty, it will not be updated."
       }
+    },
+    "delete": {
+      "modal": {
+        "title": "Delete User",
+        "text": "Are you sure? <br/> Do you want to delete the user <strong>{user_id}</strong>?"
+      }
     }
   },
   "search": {
@@ -120,6 +126,10 @@
       "required": "Value is empty. This is required.",
       "containsWhitespace": "Value must not contain whitespace.",
       "userexists": "This user exists already."
+    },
+    "button": {
+      "yes": "Yes",
+      "no": "No"
     }
   },
   "password": {