Bläddra i källkod

Updating angular web app

pull/61/head
Martin Stockhammer 3 år sedan
förälder
incheckning
5732208f5b
32 ändrade filer med 631 tillägg och 137 borttagningar
  1. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.spec.ts
  2. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/application.spec.ts
  3. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/application.ts
  4. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role-template.spec.ts
  5. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role-template.ts
  6. 2
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role.ts
  7. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html
  8. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.scss
  9. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.spec.ts
  10. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.ts
  11. 15
    6
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-edit/manage-users-edit.component.ts
  12. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.html
  13. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.scss
  14. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.spec.ts
  15. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.ts
  16. 99
    47
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.html
  17. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.scss
  18. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.spec.ts
  19. 259
    53
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts
  20. 26
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/role-result.ts
  21. 3
    4
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.html
  22. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.scss
  23. 0
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.spec.ts
  24. 47
    3
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts
  25. 9
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/shared.module.ts
  26. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.spec.ts
  27. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
  28. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.spec.ts
  29. 1
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts
  30. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.spec.ts
  31. 28
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts
  32. 11
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/access-token.spec.ts Visa fil

@@ -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

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/application.spec.ts Visa fil

@@ -1,3 +1,21 @@
/*
* 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 { Application } from './application';

describe('Application', () => {

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/application.ts Visa fil

@@ -1,2 +1,20 @@
/*
* 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.
*/

export class Application {
}

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role-template.spec.ts Visa fil

@@ -1,3 +1,21 @@
/*
* 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 { RoleTemplate } from './role-template';

describe('RoleTemplate', () => {

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role-template.ts Visa fil

@@ -1,3 +1,21 @@
/*
* 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.
*/

export class RoleTemplate {
id:string
name:string

+ 2
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/role.ts Visa fil

@@ -34,5 +34,7 @@ export class Role {
// Web Internal attributes
enabled: boolean = true
level:number = -1
root_path: Array<string>
assigned_origin: boolean;

}

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html Visa fil

@@ -8,7 +8,6 @@
~ 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
@@ -89,7 +88,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?.user_id}}</a> was added to the list.
User <a [routerLink]="['/security','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>

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.scss Visa fil

@@ -8,7 +8,6 @@
* 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.spec.ts Visa fil

@@ -8,7 +8,6 @@
* 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.ts Visa fil

@@ -8,7 +8,6 @@
* 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

+ 15
- 6
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-edit/manage-users-edit.component.ts Visa fil

@@ -16,11 +16,11 @@
* under the License.
*/

import {Component, OnInit} from '@angular/core';
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {UserService} from "../../../../services/user.service";
import {FormBuilder, FormControl} from "@angular/forms";
import {catchError, map, switchMap, tap} from 'rxjs/operators';
import {catchError, filter, map, switchMap, tap} from 'rxjs/operators';
import {ManageUsersBaseComponent} from "../manage-users-base.component";
import {ErrorResult} from "../../../../model/error-result";

@@ -38,6 +38,9 @@ export class ManageUsersEditComponent extends ManageUsersBaseComponent implement
editMode: boolean;
minUserIdSize = 0;

@Output()
userIdEvent: EventEmitter<string> = new EventEmitter<string>(true);

constructor(private route: ActivatedRoute, public userService: UserService, public fb: FormBuilder) {
super(userService, fb);
this.editMode=false;
@@ -46,15 +49,21 @@ export class ManageUsersEditComponent extends ManageUsersBaseComponent implement
this.editMode=true;
}
})

}

ngOnInit(): void {
this.editUser = this.route.params.pipe(
map(params => params.userid), switchMap(userid => userService.getUser(userid))).subscribe(user => {
map(params => params.userid),
filter(userid=>userid!=null),
tap(userid=>{
this.userIdEvent.emit(userid)
}),
switchMap(userid => this.userService.getUser(userid))).subscribe(user => {
this.editUser = user;
this.originUser = user;
this.copyToForm(this.editProperties, this.editUser);
});
}

ngOnInit(): void {
// This resets the validators of the base class
this.userForm.get('user_id').clearValidators();
this.userForm.get('user_id').clearAsyncValidators();

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.html Visa fil

@@ -8,7 +8,6 @@
~ 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.scss Visa fil

@@ -8,7 +8,6 @@
* 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.spec.ts Visa fil

@@ -8,7 +8,6 @@
* 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-list/manage-users-list.component.ts Visa fil

@@ -8,7 +8,6 @@
* 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

+ 99
- 47
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.html Visa fil

@@ -1,50 +1,102 @@
<h3>Roles</h3>
<table class="table">
<thead class="thead-light">
<tr class="d-flex">
<th class="col-3">Role</th>
<th class="col-2">Scope</th>
<th class="col-1">Assign</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let baseRole of baseRoles" class="d-flex">
<td class="col-3" [innerHTML]="getRoleContent(baseRole)"></td>
<td class="col-2">
{{baseRole.application_id}}
</td>
<td class="col-1">
<div class="form-check form-check-inline"><input class="form-check-input" type="checkbox"
[attr.disabled]="baseRole.enabled?null:true"
[attr.id]="baseRole.id"
[(ngModel)]="baseRole.assigned"
(change)="changeBaseAssignment(baseRole, $event)"
>


<!--
~ 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.
-->

<div class="row">

<div class="row col-md-6">
<h4 class="col-md-2 mt-3">{{'users.roles.base_roles'|translate}} </h4>
<h4 class="col-md-2 offset-md-4 mt-3"><span class="badge badge-primary">{{userid}}</span></h4>
</div>
<ng-container *ngIf="roles$|async as myRoles">
<table class="table col-md-12">
<thead class="thead-light">
<tr class="d-flex">
<th class="col-3">{{'users.roles.table.role'|translate}}</th>
<th class="col-2">{{'users.roles.table.scope'|translate}}</th>
<th class="col-1">{{'users.roles.table.assign'|translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let baseRoleItem of myRoles.baseRoles|keyvalue" class="d-flex">
<td class="col-3" [innerHTML]="getRoleContent(baseRoleItem.value)"></td>
<td class="col-2">
{{baseRoleItem.value.application_id}}
</td>
<td class="col-1">
<div class="form-check form-check-inline"><input class="form-check-input" type="checkbox"
[attr.disabled]="baseRoleItem.value.enabled?null:true"
[attr.id]="baseRoleItem.key"
[(ngModel)]="baseRoleItem.value.assigned"
(change)="changeBaseAssignment(baseRoleItem.value, $event)"
>
</div>
</td>
</tr>
</tbody>
</table>


<h4>{{'users.roles.template_roles'|translate}}</h4>
<table class="table">
<thead class="thead-light">
<tr class="d-flex">
<th scope="row" class="col-1">{{'users.roles.table.repository'|translate}}</th>
<th scope="col" class="col-1"
*ngFor="let templateRole of templateRoles$ | async">{{templateRole.name}}</th>
</tr>
</thead>
<tbody>
<tr class="d-flex" *ngFor="let res of myRoles.templateRoleInstances | keyvalue">
<td class="table-secondary col-1">{{res.key}}</td>
<td class="col-1 text-center" *ngFor="let templateRole of templateRoles$ | async">
<div class="form-check form-check-inline"
*ngIf="getInstanceContent(templateRole, res.value) as role">
<input class="form-check-input"
[attr.disabled]="role.enabled?null:true"
type="checkbox" [attr.id]="role.id"
[(ngModel)]="role.assigned" (ngModelChange)="changeTemplateAssignment(role, $event)"/>
</div>
</td>
</tr>
</tbody>

</table>

<div class="form-group col-md-12 mt-3 ">
<button class="btn btn-primary" type="submit"
(click)="saveAssignments()">{{'form.button.save'|translate}}</button>
</div>

<ng-container *ngIf="saved">
<div *ngIf="success" class="alert alert-success" role="alert">
Roles have been assigned
</div>
</td>
</tr>
</tbody>
</table>


<h3>Repository Roles</h3>
<table class="table">
<thead class="thead-light">
<tr class="d-flex">
<th scope="row" class="col-1">Repository</th>
<th scope="col" class="col-1" *ngFor="let templateRole of templateRoles$ | async">{{templateRole.name}}</th>
</tr>
</thead>
<tbody>
<tr class="d-flex" *ngFor="let res of templateRoleInstances | keyvalue" >
<td class="table-secondary col-1">{{res.key}}</td>
<td class="col-1 text-center" *ngFor="let templateRole of templateRoles$ | async">
<div class="form-check form-check-inline" *ngIf="getInstanceContent(templateRole, res.value) as role">
<input class="form-check-input" type="checkbox" [attr.id]="role.id"
[(ngModel)]="role.assigned" (ngModelChange)="changeInstAssignment(role, $event)"/>
<div *ngIf="!success" class="alert alert-danger" role="alert">
<h4 class="alert-heading">Errors</h4>
<ng-container *ngFor="let message of errors.error_messages; first as isFirst">
<hr *ngIf="!isFirst">
<p>{{message.message}}</p>
</ng-container>
</div>
</td>
</tr>
</tbody>
</ng-container>

</ng-container>

</table>
</div>

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.scss Visa fil

@@ -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.
*/


+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.spec.ts Visa fil

@@ -1,3 +1,21 @@
/*
* 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 { ManageUsersRolesComponent } from './manage-users-roles.component';

+ 259
- 53
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts Visa fil

@@ -1,54 +1,125 @@
import { Component, OnInit } from '@angular/core';
/*
* 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, EventEmitter, OnInit, Output} from '@angular/core';
import { Role } from '@app/model/role';
import {UserService} from "@app/services/user.service";
import {ActivatedRoute} from "@angular/router";
import {filter, map, switchMap} from "rxjs/operators";
import {catchError, filter, map, multicast, share, switchMap, tap} from "rxjs/operators";
import {RoleTree} from "@app/model/role-tree";
import {RoleService} from "@app/services/role.service";
import {RoleTemplate} from "@app/model/role-template";
import {Observable} from "rxjs";
import {Observable, of} from "rxjs";
import {Util} from "@app/modules/shared/shared.module";
import { RoleResult } from './role-result';
import {fromArray} from "rxjs/internal/observable/fromArray";
import {ErrorResult} from "@app/model/error-result";
import {HttpResponse} from "@angular/common/http";

@Component({
selector: 'app-manage-users-roles',
templateUrl: './manage-users-roles.component.html',
styleUrls: ['./manage-users-roles.component.scss']
})
export class ManageUsersRolesComponent implements OnInit {
export class ManageUsersRolesComponent implements OnInit, AfterViewInit {

baseRoles : Array<Role>
roles$ : Observable<RoleResult>
currentRoles: RoleResult
guest: Role
registered: Role
// Map of (resource, [roles])
templateRoleInstances: Map<string, Array<Role>>
templateRoles$: Observable<RoleTemplate[]>;
userid: string;
success:boolean=true;
errors: ErrorResult[]=[];
saved:boolean=false;

constructor(private route : ActivatedRoute, private userService : UserService, private roleService : RoleService) {
this.route.params.pipe(
map(params => params.userid), filter(userid => userid!=null), switchMap(userid => userService.userRoleTree(userid))).subscribe(roleTree => {
this.parseRoleTree(roleTree);
});
@Output()
userIdEvent: EventEmitter<string> = new EventEmitter<string>(true);

constructor(private route : ActivatedRoute, private userService : UserService, private roleService : RoleService) {
}

ngOnInit(): void {
this.roles$ = this.route.params.pipe(
map(params => params.userid), filter(userid => userid != null),
tap(userid => this.userid = userid),
tap(userid=>{
this.userIdEvent.emit(userid)
}),
switchMap(userid => {
return this.userService.userRoleTree(userid)
}),
map(roleTree=>this.parseRoleTree(roleTree)),
// This is to avoid multiple userService.userRoleTree() calls for template and base roles
share()
);
this.templateRoles$ = this.roleService.getTemplates();
}

private parseRoleTree(roleTree:RoleTree): void {
let roleTable = [];
for(let rootRole of roleTree.root_roles) {
roleTable = this.recurseRoleTree(rootRole, roleTable, 0);
private parseRoleTree(roleTree:RoleTree): RoleResult {
let roleResult = new RoleResult();
let rootRoles = roleTree.root_roles;
rootRoles.sort((a, b)=>{
if (b.id=='guest') {
return 1;
} else if (b.id=='registered-user') {
return 1;
} else {
return -1;
}
})
for (let rootRole of rootRoles) {
this.recurseTree(rootRole, roleResult, 0, null);
}
return roleResult;
}

private recurseTree(role:Role,roleResult:RoleResult, level:number, parent: Role) : void {
let newLevel=level;
if (parent!=null) {
if (role.root_path==null) {
role.root_path = (parent.root_path == null ? [] : parent.root_path.slice());
}
role.root_path.push(parent.id)
}
this.baseRoles = roleTable;
let templateMap : Map<string,Array<Role>> = new Map<string, Array<Role>>();
for (let rootRole of roleTree.root_roles) {
templateMap = this.recurseTemplates(rootRole, templateMap, 0);
role.assigned_origin = role.assigned;
if (role.template_instance) {
newLevel = this.parseTemplateRole(role,roleResult.templateRoleInstances,newLevel)
} else {
newLevel = this.parseBaseRole(role, roleResult.baseRoles, newLevel)
}
for(let childRole of role.children) {
let recurseChild = childRole;
if (childRole.template_instance) {
if (roleResult.templateRoleInstances.has(childRole.resource) && roleResult.templateRoleInstances.get(childRole.resource).has(childRole.model_id)) {
recurseChild = roleResult.templateRoleInstances.get(childRole.resource).get(childRole.model_id)
}
} else {
let existingBaseRole = roleResult.baseRoles.find(role => role.id == childRole.id)
if (existingBaseRole != null) {
recurseChild = existingBaseRole;
}
}
this.recurseTree(recurseChild, roleResult, newLevel, role);
}
this.templateRoleInstances = templateMap;
}

private recurseRoleTree(role:Role, roles : Array<Role>, level:number) : Array<Role> {
private parseBaseRole(role:Role, roles : Array<Role>, level:number) : number {
if (role.id=='guest') {
this.guest = role;
} else if (role.id=='registered-user') {
@@ -56,34 +127,32 @@ export class ManageUsersRolesComponent implements OnInit {
}
role.enabled=true;
let newLevel;
if (!role.template_instance && role.assignable) {
if (role.assignable) {
role.level=level
roles.push(role);
newLevel = level+1;
} else {
newLevel = level;
}
for(let childRole of role.children) {
roles = this.recurseRoleTree(childRole, roles, newLevel);
}
return roles;
return newLevel;
}

private recurseTemplates(role:Role, roles : Map<string, Array<Role>>, level:number) : Map<string, Array<Role>> {
private parseTemplateRole(role:Role, roles : Map<string, Map<string, Role>>, level:number) : number {
let newLevel=level;
role.enabled=true;
if (role.template_instance && role.assignable) {
if (role.assignable) {
role.level=level
let roleList = roles.get(role.resource)
if (roleList==null) {
roleList = []
let modelRoleMap = roles.get(role.resource)
if (modelRoleMap==null) {
modelRoleMap = new Map<string, Role>();
}
roleList.push(role);
roles.set(role.resource, roleList);
}
for(let childRole of role.children) {
roles = this.recurseTemplates(childRole, roles, level+1);
modelRoleMap.set(role.model_id, role);
roles.set(role.resource, modelRoleMap);
newLevel = level + 1;
} else {
newLevel = level;
}
return roles;
return newLevel;
}

getRoleContent(role:Role) : string {
@@ -101,55 +170,192 @@ export class ManageUsersRolesComponent implements OnInit {

changeBaseAssignment(role : Role, event) {
let cLevel=-1
let assignStatus;
let assignStatus
// Guest is special and exclusive
if (role.id==this.guest.id) {
if (role.assigned) {
for (let cRole of this.baseRoles) {
this.currentRoles.baseRoles.forEach((cRole:Role)=> {
if (cRole.id != this.guest.id) {
cRole.assigned = false;
cRole.enabled=true;
}
}

})
role.enabled = false;
this.currentRoles.templateRoleInstances.forEach((value, key)=>{
value.forEach((templateInstance, modelId) => {
templateInstance.assigned = false;
templateInstance.enabled = true;

});
})
}
} else {
this.guest.enabled = true;
for (let cRole of this.baseRoles) {
this.currentRoles.baseRoles.forEach((cRole)=> {
if (cRole.id == role.id) {
console.log("Value: " + cRole.assigned);
cLevel = cRole.level;
assignStatus = cRole.assigned;
if (assignStatus) {
this.guest.assigned = false;
this.guest.enabled = true;
} else {
if (!this.baseRoles.find(role=>role.assigned)) {
if (!this.isAnyAssigned()) {
this.guest.assigned=true;
this.guest.enabled = false;
}
}
} else {
console.log("Level " + cLevel);
if (cLevel >= 0 && cLevel < cRole.level) {
if (cLevel >= 0 && cLevel < cRole.level && cRole.root_path.find(pRoleId => pRoleId==role.id)) {
if (assignStatus) {
cRole.assigned = true;
cRole.enabled = false;
} else {
cRole.enabled = true;
cRole.assigned=cRole.assigned_origin
}
} else if (cLevel >= 0) {
break;
return;
}
}
})
this.currentRoles.templateRoleInstances.forEach((value, key)=>{
value.forEach((templateInstance, modelId) => {
if(templateInstance.root_path.find(roleId => roleId==role.id)) {
if (role.assigned) {
templateInstance.assigned = true;
templateInstance.enabled = false
} else {
templateInstance.enabled = true;
templateInstance.assigned=templateInstance.assigned_origin
}
}
}
)
})
}
}

isAnyAssigned() : boolean {
if (Array.from(this.currentRoles.baseRoles.values()).find(role=>role.assigned)!=null) {
return true;
}
return Array.from(this.currentRoles.templateRoleInstances.values()).map((roleMap: Map<string, Role>) => Array.from(roleMap.values()))
.find(values=>values.find(role=>role.assigned))!=null
}




changeTemplateAssignment(role : Role, event) {
if (role.assigned) {
if (this.guest.assigned) {
this.guest.assigned = false;
this.guest.enabled = true;
}
if (!this.registered.assigned) {
this.registered.assigned=true;
}
} else {
if (!this.isAnyAssigned()) {
this.guest.assigned=true;
this.guest.enabled = false;
}

}
}

changeInstAssignment(role : Role, event) {
console.log("Change " + role.id);
console.log("Assignment changed "+JSON.stringify(event));
console.log("Event target "+event.target);
getInstanceContent(template:RoleTemplate, roles:Map<string,Role>) : Role {
return roles.get(template.id)
}

saveAssignments() {
this.saved=false;
this.success=true;
this.errors = [];
let assignmentMap : Map<string, Role> = new Map(this.currentRoles.baseRoles.filter(role => role.assigned != role.assigned_origin).map(role => [role.id, role]));
let assignments : Array<Role> = []
let unassignments : Array<Role> = []
assignmentMap.forEach((role, roleId)=>{
if (role.level>0) {
for(let parentId of role.root_path) {
if (assignmentMap.has(parentId) && assignmentMap.get(parentId).assigned) {
return;
}
}
}
if (role.assigned) {
assignments.push(role);
} else {
unassignments.push(role);
}
})
this.currentRoles.templateRoleInstances.forEach((templMap, resource)=> {
templMap.forEach((role, modelId)=> {
if (role.assigned!=role.assigned_origin) {
if (role.level>0) {
for(let parentId of role.root_path) {
if (assignmentMap.has(parentId) && assignmentMap.get(parentId).assigned) {
return;
}
}
}
if (role.assigned) {
assignments.push(role);
} else {
unassignments.push(role);
}
}
})
}
)
fromArray(assignments).pipe(switchMap((role) => this.roleService.assignRole(role.id, this.userid)),
catchError((err: ErrorResult, caught) => {
this.success = false;
this.errors.push(err);
return [];
}
)
).subscribe((result:HttpResponse<Role>)=> {
this.updateRole(result.body, true);
this.saved=true;
}
);
fromArray(unassignments).pipe(switchMap((role) => this.roleService.unAssignRole(role.id, this.userid)),
catchError((err: ErrorResult, caught) => {
this.success = false;
this.errors.push(err);
return [];
}
)
).subscribe(result=>{
this.updateRole(result.body,false);
this.saved=true;
});
this.saved=true;
}

private updateRole(role:Role, assignment:boolean) : void {
if (role!=null) {
if (role.template_instance) {
this.currentRoles.templateRoleInstances.forEach((templMap, resource)=>{
templMap.forEach((tmplRole, modelId)=> {
if (tmplRole.id == role.id) {
Util.deepCopy(role, tmplRole, false);
tmplRole.assigned = assignment;
}
}
)
})
} else {
let target = this.currentRoles.baseRoles.find(baseRole => baseRole.id == role.id);
Util.deepCopy(role, target, false);
target.assigned = assignment;
}
}
}

getInstanceContent(template:RoleTemplate, roles:Array<Role>) : Role {
return roles.find(role=>role.model_id==template.id)
ngAfterViewInit(): void {
this.roles$.subscribe(roleResult => this.currentRoles = roleResult);
}
}

+ 26
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/role-result.ts Visa fil

@@ -0,0 +1,26 @@
/*
* 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 {Role} from "@app/model/role";

export class RoleResult {
// Map of (roleId, Role)
baseRoles: Array<Role> = [];
// Map of (resource, [(modelId, role), ...])
templateRoleInstances: Map<string, Map<string, Role>> = new Map<string, Map<string, Role>>();
}

+ 3
- 4
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.html Visa fil

@@ -8,7 +8,6 @@
~ 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
@@ -25,11 +24,11 @@
<a class="nav-link" routerLink="/security/users/add" routerLinkActive="active" href="#">{{'users.add.head' |translate }}</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/security/users/edit" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a>
<a class="nav-link" routerLink="/security/users/edit{{userId$|async}}" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/security/users/roles" routerLinkActive="active" href="#">{{'users.roles.head' |translate }}</a>
<a class="nav-link" routerLink="/security/users/roles{{userId$|async}}" routerLinkActive="active" href="#">{{'users.roles.head' |translate }}</a>
</li>
</ul>

<router-outlet ></router-outlet>
<router-outlet (activate)="onChildActivate($event)" ></router-outlet>

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.scss Visa fil

@@ -8,7 +8,6 @@
* 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

+ 0
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.spec.ts Visa fil

@@ -8,7 +8,6 @@
* 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

+ 47
- 3
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts Visa fil

@@ -8,7 +8,6 @@
* 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
@@ -17,7 +16,12 @@
* under the License.
*/

import { Component, OnInit } from '@angular/core';
import {AfterViewInit, Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from "@angular/router";
import {iif, Observable, of, pipe, merge, combineLatest} from "rxjs";
import {combineAll, filter, map, mergeMap, share, switchMap, tap} from 'rxjs/operators';
import {flatMap} from "rxjs/internal/operators";
import {fromArray} from "rxjs/internal/observable/fromArray";

@Component({
selector: 'app-manage-users',
@@ -26,9 +30,49 @@ import { Component, OnInit } from '@angular/core';
})
export class ManageUsersComponent implements OnInit {

constructor() { }
userId$:Observable<string>

constructor(private route : ActivatedRoute) {
}

ngOnInit(): void {
}



onChildActivate(componentReference) {
// console.log("Activating "+componentReference+" - "+JSON.stringify(componentReference,getCircularReplacer()))
if (componentReference.userIdEvent!=null) {
let componentEmit : Observable<string> = componentReference.userIdEvent.pipe(
tap(userid=>console.log("Event "+componentReference.class+" "+userid)),
map((userid: string) => this.getSubPath(userid)));
if (this.userId$!=null) {
this.userId$ = merge(this.userId$, componentEmit)
} else {
this.userId$ = componentEmit;
}
}
}

getSubPath(userid:string) {
if (userid!=null && userid.length>0) {
return '/' + userid;
} else {
return '';
}
}

}

const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};

+ 9
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/shared.module.ts Visa fil

@@ -71,7 +71,7 @@ export function httpTranslateLoader(http: HttpClient) {
}

export const Util = {
deepCopy(src: Object, dst: Object) {
deepCopy(src: Object, dst: Object, overwriteWithEmptyString:boolean=true) {
Object.keys(src).forEach((key, idx) => {
let srcEl = src[key];
if (typeof (srcEl) == 'object') {
@@ -81,6 +81,14 @@ export const Util = {
}
dstEl = dst[key];
this.deepCopy(srcEl, dstEl);
} else if (typeof(srcEl)=='string') {
if (overwriteWithEmptyString) {
dst[key]=srcEl
} else {
if ((srcEl as string).length>0) {
dst[key]=srcEl
}
}
} else {
// console.debug("setting " + key + " = " + srcEl);
dst[key] = srcEl;

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.spec.ts Visa fil

@@ -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

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts Visa fil

@@ -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

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.spec.ts Visa fil

@@ -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

+ 1
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/authentication.service.ts Visa fil

@@ -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

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.spec.ts Visa fil

@@ -1,3 +1,21 @@
/*
* 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 { RoleService } from './role.service';

+ 28
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts Visa fil

@@ -1,7 +1,27 @@
/*
* 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 {ArchivaRequestService} from "@app/services/archiva-request.service";
import {RoleTemplate} from "@app/model/role-template";
import { Observable } from 'rxjs';
import { Role } from '@app/model/role';
import {HttpResponse} from "@angular/common/http";

@Injectable({
providedIn: 'root'
@@ -14,4 +34,12 @@ export class RoleService {
return this.rest.executeRestCall("get", "redback", "roles/templates", null);
}

public assignRole(roleId, userId) : Observable<HttpResponse<Role>> {
return this.rest.executeResponseCall<Role>("put", "redback", "roles/" + roleId + "/user/" + userId, null);
}

public unAssignRole(roleId, userId) : Observable<HttpResponse<Role>> {
return this.rest.executeResponseCall<Role>("delete", "redback", "roles/" + roleId + "/user/" + userId, null);
}

}

+ 11
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json Visa fil

@@ -116,7 +116,15 @@
}
},
"roles": {
"head": "Edit Roles"
"head": "Edit Roles",
"base_roles": "Roles",
"template_roles": "Repository Roles",
"table": {
"role": "Role",
"scope": "Scope",
"assign": "Assign",
"repository": "Repository"
}
}
},
"search": {
@@ -133,7 +141,8 @@
},
"button": {
"yes": "Yes",
"no": "No"
"no": "No",
"save": "Save Changes"
}
},
"password": {

Laddar…
Avbryt
Spara