@@ -49,6 +49,7 @@ const routes: Routes = [ | |||
{path: 'list', component: ManageUsersListComponent}, | |||
{path: 'add', component: ManageUsersAddComponent}, | |||
{path: 'edit/:userid', component: ManageUsersEditComponent}, | |||
{path: 'edit', redirectTo:'edit/guest' }, | |||
{path: '', redirectTo:'list', pathMatch:'full'} | |||
] | |||
}, |
@@ -25,7 +25,7 @@ | |||
<a class="nav-link" routerLink="/user/users/add" routerLinkActive="active" href="#">{{'users.add.head' |translate }}</a> | |||
</li> | |||
<li class="nav-item"> | |||
<a class="nav-link" routerLink="/user/users/edit/guest" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a> | |||
<a class="nav-link" routerLink="/user/users/edit" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a> | |||
</li> | |||
</ul> | |||
@@ -26,6 +26,7 @@ import {HttpErrorResponse} from "@angular/common/http"; | |||
import {ErrorResult} from "../../../../model/error-result"; | |||
import {catchError} from "rxjs/operators"; | |||
import {of, throwError} from 'rxjs'; | |||
import {environment} from "../../../../../environments/environment"; | |||
@Component({ | |||
selector: 'app-manage-users-add', | |||
@@ -34,7 +35,7 @@ import {of, throwError} from 'rxjs'; | |||
}) | |||
export class ManageUsersAddComponent implements OnInit { | |||
minUserIdSize=8; | |||
minUserIdSize=environment.application.minUserIdLength; | |||
success:boolean=false; | |||
error:boolean=false; | |||
errorResult:ErrorResult; | |||
@@ -53,7 +54,7 @@ export class ManageUsersAddComponent implements OnInit { | |||
validator: MustMatch('password', 'confirm_password') | |||
}) | |||
constructor(private userService: UserService, private fb: FormBuilder) { | |||
constructor(public userService: UserService, public fb: FormBuilder) { | |||
} | |||
@@ -97,16 +98,16 @@ export class ManageUsersAddComponent implements OnInit { | |||
} | |||
valid(field:string) : string { | |||
valid(field:string) : string[] { | |||
let formField = this.userForm.get(field); | |||
if (formField.dirty||formField.touched) { | |||
if (formField.valid) { | |||
return 'is-valid' | |||
return ['is-valid'] | |||
} else { | |||
return 'is-invalid' | |||
return ['is-invalid'] | |||
} | |||
} else { | |||
return '' | |||
return [''] | |||
} | |||
} | |||
@@ -17,56 +17,75 @@ | |||
--> | |||
<form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()"> | |||
<div class="form-group col-md-8"> | |||
<label for="user_id">{{'users.attributes.user_id' |translate}}</label> | |||
<input type="text" class="form-control" formControlName="user_id" id="user_id" | |||
<div class="form-group row col-md-8"> | |||
<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" | |||
(change)="editMode=!editMode" | |||
> | |||
</div> | |||
</div> | |||
<div class="form-group row col-md-8"> | |||
<label class="col-md-2 col-form-label" for="user_id">{{'users.attributes.user_id' |translate}}</label> | |||
<div class="col-md-6" > | |||
<input type="text" formControlName="user_id" id="user_id" | |||
[ngClass]="valid('user_id')" | |||
placeholder="{{'users.input.user_id'|translate}}"> | |||
<small>{{'users.input.small.user_id'|translate:{'minSize':this.minUserIdSize} }}</small> | |||
value="{{editUser.user_id}}" [attr.readonly]="!editMode"> | |||
<small *ngIf="editMode">{{'users.input.small.user_id'|translate:{'minSize':this.minUserIdSize} }}</small> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<label for="full_name">{{'users.attributes.full_name' |translate}}</label> | |||
<input type="text" class="form-control" formControlName="full_name" id="full_name" | |||
[ngClass]="valid('full_name')" | |||
placeholder="{{'users.input.full_name'|translate}}"> | |||
<small>{{'users.input.small.full_name'|translate}}</small> | |||
<div class="form-group row col-md-8"> | |||
<label class="col-md-2 col-form-label" for="full_name">{{'users.attributes.full_name' |translate}}</label> | |||
<div class="col-md-6" > | |||
<input type="text" formControlName="full_name" id="full_name" | |||
[ngClass]="valid('full_name')" value="{{editUser.full_name}}" [attr.readonly]="!editMode" > | |||
<small *ngIf="editMode">{{'users.input.small.full_name'|translate}}</small> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<label for="email">{{'users.attributes.email' |translate}}</label> | |||
<input type="text" class="form-control" formControlName="email" id="email" | |||
[ngClass]="valid('email')" | |||
placeholder="{{'users.input.email'|translate}}"> | |||
<div class="form-group row col-md-8"> | |||
<label class="col-md-2 col-form-label" for="email">{{'users.attributes.email' |translate}}</label> | |||
<div class="col-md-6" > | |||
<input type="text" formControlName="email" id="email" | |||
[ngClass]="valid('email')" value="{{editUser.email}}" [attr.readonly]="!editMode"> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<label for="password">{{'users.attributes.password' |translate}}</label> | |||
<div class="form-group row col-md-8" *ngIf="editMode"> | |||
<label class="col-md-2 col-form-label" for="password">{{'users.attributes.password' |translate}}</label> | |||
<div class="col-md-6" > | |||
<input type="password" class="form-control" formControlName="password" id="password" | |||
[ngClass]="valid('password')" | |||
placeholder="{{'users.input.password'|translate}}"> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<label for="confirm_password">{{'users.attributes.confirm_password' |translate}}</label> | |||
<div class="form-group row col-md-8" *ngIf="editMode"> | |||
<label class="col-md-2 col-form-label" for="confirm_password">{{'users.attributes.confirm_password' |translate}}</label> | |||
<div class="col-md-6"> | |||
<input type="password" class="form-control" formControlName="confirm_password" id="confirm_password" | |||
[ngClass]="valid('confirm_password')" | |||
placeholder="{{'users.input.confirm_password'|translate}}"> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<div class="form-group row col-md-8"> | |||
<div class="col-md-2">Flags</div> | |||
<div class="col-md-6"> | |||
<div class="form-check"> | |||
<input class="form-check-input" type="checkbox" value="" formControlName="locked" id="locked"> | |||
<label class="form-check-label" for="locked"> | |||
<input class="form-check-input" type="checkbox" value="{{editUser.locked}}" formControlName="locked" id="locked" [attr.disabled]="editMode?null:true"> | |||
<label class="form-check-label" for="locked" > | |||
{{'users.attributes.locked'|translate}} | |||
</label> | |||
</div> | |||
<div class="form-check"> | |||
<input class="form-check-input" type="checkbox" value="" formControlName="password_change_required" | |||
id="password_change_required" checked> | |||
<input class="form-check-input" type="checkbox" value="{{editUser.password_change_required}}" formControlName="password_change_required" | |||
id="password_change_required" [attr.disabled]="editMode?null:true"> | |||
<label class="form-check-label" for="password_change_required"> | |||
{{'users.attributes.password_change_required'|translate}} | |||
</label> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="form-group col-md-8"> | |||
<div class="form-group col-md-8" *ngIf="editMode"> | |||
<button class="btn btn-primary" type="submit" | |||
[disabled]="!userForm.valid">{{'users.add.submit'|translate}}</button> | |||
[disabled]="!userForm.valid">{{'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. |
@@ -18,21 +18,40 @@ | |||
import { Component, OnInit } from '@angular/core'; | |||
import { ActivatedRoute } from '@angular/router'; | |||
import {UserService} from "../../../../services/user.service"; | |||
import {FormBuilder, Validators} from "@angular/forms"; | |||
import {ManageUsersAddComponent, MustMatch} from "../manage-users-add/manage-users-add.component"; | |||
import {environment} from "../../../../../environments/environment"; | |||
import {map, switchMap} from 'rxjs/operators'; | |||
@Component({ | |||
selector: 'app-manage-users-edit', | |||
templateUrl: './manage-users-edit.component.html', | |||
styleUrls: ['./manage-users-edit.component.scss'] | |||
}) | |||
export class ManageUsersEditComponent implements OnInit { | |||
export class ManageUsersEditComponent extends ManageUsersAddComponent implements OnInit { | |||
userid; | |||
editUser; | |||
editMode:boolean=false; | |||
constructor(private route: ActivatedRoute) { | |||
this.route.params.subscribe(params => this.userid=params.userid); | |||
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;}); | |||
} | |||
ngOnInit(): void { | |||
} | |||
valid(field: string): string[] { | |||
if (this.editMode) { | |||
let classArr = super.valid(field); | |||
return classArr.concat('form-control') | |||
} else { | |||
return ['form-control-plaintext']; | |||
} | |||
} | |||
} |
@@ -24,8 +24,7 @@ import {ErrorResult} from "../model/error-result"; | |||
import {Observable, throwError} from "rxjs"; | |||
import {Permission} from '../model/permission'; | |||
import {PagedResult} from "../model/paged-result"; | |||
import {EntityService} from "../model/entity-service"; | |||
import { User } from '../model/user'; | |||
import {User} from '../model/user'; | |||
import {catchError, map} from "rxjs/operators"; | |||
@Injectable({ | |||
@@ -37,25 +36,25 @@ export class UserService implements OnInit, OnDestroy { | |||
permissions: Permission[]; | |||
guestPermissions: Permission[]; | |||
authenticated: boolean; | |||
uiPermissionsDefault = { | |||
uiPermissionsDefault = { | |||
'menu': { | |||
'repo':{ | |||
'section':true, | |||
'browse':true, | |||
'search':true, | |||
'upload':false | |||
'repo': { | |||
'section': true, | |||
'browse': true, | |||
'search': true, | |||
'upload': false | |||
}, | |||
'admin':{ | |||
'section':false, | |||
'config':false, | |||
'status':false, | |||
'reports':false | |||
'admin': { | |||
'section': false, | |||
'config': false, | |||
'status': false, | |||
'reports': false | |||
}, | |||
'user':{ | |||
'section':false, | |||
'manage':false, | |||
'roles':false, | |||
'config':false | |||
'user': { | |||
'section': false, | |||
'manage': false, | |||
'roles': false, | |||
'config': false | |||
} | |||
} | |||
}; | |||
@@ -86,7 +85,7 @@ export class UserService implements OnInit, OnDestroy { | |||
} | |||
}, | |||
error: err => { | |||
console.log("Could not retrieve permissions "+err); | |||
console.log("Could not retrieve permissions " + err); | |||
} | |||
} | |||
this.retrievePermissionInfo().subscribe(observer); | |||
@@ -172,13 +171,14 @@ export class UserService implements OnInit, OnDestroy { | |||
resetPermissions() { | |||
this.deepCopy(this.uiPermissionsDefault, this.uiPermissions); | |||
} | |||
parsePermissions(permissions: Permission[]) { | |||
this.resetPermissions(); | |||
for ( let perm of permissions) { | |||
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=='*') { | |||
if (perm.resource.identifier == '*') { | |||
this.uiPermissions.menu.admin.section = true; | |||
this.uiPermissions.menu.admin.config = true; | |||
this.uiPermissions.menu.admin.reports = true; | |||
@@ -187,7 +187,7 @@ export class UserService implements OnInit, OnDestroy { | |||
} | |||
case "archiva-manage-users": { | |||
if (perm.resource.identifier=='*') { | |||
if (perm.resource.identifier == '*') { | |||
this.uiPermissions.menu.user.section = true; | |||
this.uiPermissions.menu.user.config = true; | |||
this.uiPermissions.menu.user.manage = true; | |||
@@ -195,7 +195,7 @@ export class UserService implements OnInit, OnDestroy { | |||
} | |||
} | |||
case "redback-configuration-edit": { | |||
if (perm.resource.identifier=='*') { | |||
if (perm.resource.identifier == '*') { | |||
this.uiPermissions.menu.user.section = true; | |||
this.uiPermissions.menu.user.config = true; | |||
} | |||
@@ -210,7 +210,7 @@ export class UserService implements OnInit, OnDestroy { | |||
private deepCopy(src: Object, dst: Object) { | |||
Object.keys(src).forEach((key, idx) => { | |||
let srcEl = src[key]; | |||
if (typeof(srcEl)=='object' ) { | |||
if (typeof (srcEl) == 'object') { | |||
let dstEl; | |||
if (!dst.hasOwnProperty(key)) { | |||
dst[key] = {} | |||
@@ -260,22 +260,35 @@ export class UserService implements OnInit, OnDestroy { | |||
this.authenticated = false; | |||
} | |||
public query(searchTerm : string, offset : number = 0, limit : number = 10, orderBy : string[] = ['user_id'], order: string = 'asc') : Observable<PagedResult<UserInfo>> { | |||
public query(searchTerm: string, offset: number = 0, limit: number = 10, orderBy: string[] = ['user_id'], order: string = 'asc'): Observable<PagedResult<UserInfo>> { | |||
console.log("getUserList " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order); | |||
if (searchTerm==null) { | |||
searchTerm="" | |||
if (searchTerm == null) { | |||
searchTerm = "" | |||
} | |||
if (orderBy==null || orderBy.length==0) { | |||
if (orderBy == null || orderBy.length == 0) { | |||
orderBy = ['user_id']; | |||
} | |||
return this.rest.executeRestCall<PagedResult<UserInfo>>("get", "redback", "users", {'q':searchTerm, 'offset':offset,'limit':limit,'orderBy':orderBy,'order':order}); | |||
return this.rest.executeRestCall<PagedResult<UserInfo>>("get", "redback", "users", { | |||
'q': searchTerm, | |||
'offset': offset, | |||
'limit': limit, | |||
'orderBy': orderBy, | |||
'order': order | |||
}); | |||
} | |||
public addUser(user : User) : Observable<string> { | |||
public addUser(user: User): Observable<string> { | |||
return this.rest.executeResponseCall<string>("post", "redback", "users", user).pipe( | |||
catchError( ( error: HttpErrorResponse) => { | |||
catchError((error: HttpErrorResponse) => { | |||
return throwError(this.rest.getTranslatedErrorResult(error)); | |||
}), map((httpResponse: HttpResponse<string>) => httpResponse.headers.get('Location'))); | |||
} | |||
public getUser(userid: string): Observable<UserInfo> { | |||
return this.rest.executeRestCall<UserInfo>("get", "redback", "users/" + userid, null).pipe( | |||
catchError((error: HttpErrorResponse) => { | |||
return throwError(this.rest.getTranslatedErrorResult(error)); | |||
}),map( (httpResponse : HttpResponse<string>) => httpResponse.headers.get('Location'))); | |||
})); | |||
} | |||
} |
@@ -28,6 +28,7 @@ export const environment = { | |||
client_id:'archiva_web_client', | |||
baseUrl: 'http://localhost:8080', | |||
restPath: '/archiva/api/v2', | |||
minUserIdLength: 8, | |||
servicePaths: { | |||
archiva:"archiva", | |||
redback:"redback", |