import {SearchComponent} from './modules/repo/search/search.component';
import {BrowseComponent} from "./modules/repo/browse/browse.component";
import {UploadComponent} from "./modules/repo/upload/upload.component";
-import {ManageRolesComponent} from "./modules/user/manage-roles/manage-roles.component";
+import {ManageRolesComponent} from "./modules/security/manage-roles/manage-roles.component";
import {RoutingGuardService as Guard} from "./services/routing-guard.service";
-import {SecurityConfigurationComponent} from "./modules/user/security-configuration/security-configuration.component";
+import {SecurityConfigurationComponent} from "./modules/security/security-configuration/security-configuration.component";
/**
* You can use Guard (RoutingGuardService) for permission checking. The service needs data with one parameter 'perm',
},
{
- path: 'user', component: HomeComponent,canActivate:[Guard],data:{perm: 'menu.user.section'},
+ path: 'security', component: HomeComponent,canActivate:[Guard],data:{perm: 'menu.user.section'},
children: [
- {path: 'users', loadChildren: () => import('./modules/user/user.module').then(m => m.UserModule)},
+ {path: 'users', loadChildren: () => import('./modules/security/user.module').then(m => m.UserModule)},
{path: 'roles', component: ManageRolesComponent},
{path: 'config', component: SecurityConfigurationComponent},
]
import {SearchComponent} from './modules/repo/search/search.component';
import {BrowseComponent} from './modules/repo/browse/browse.component';
import {UploadComponent} from './modules/repo/upload/upload.component';
-import {SecurityConfigurationComponent} from './modules/user/security-configuration/security-configuration.component';
+import {SecurityConfigurationComponent} from './modules/security/security-configuration/security-configuration.component';
import {CoreModule} from "./modules/core/core.module";
import {httpTranslateLoader, SharedModule} from "./modules/shared/shared.module";
import {TranslateCompiler, TranslateLoader, TranslateModule} from "@ngx-translate/core";
--- /dev/null
+import { Application } from './application';
+
+describe('Application', () => {
+ it('should create an instance', () => {
+ expect(new Application()).toBeTruthy();
+ });
+});
--- /dev/null
+export class Application {
+}
--- /dev/null
+import { RoleTemplate } from './role-template';
+
+describe('RoleTemplate', () => {
+ it('should create an instance', () => {
+ expect(new RoleTemplate()).toBeTruthy();
+ });
+});
--- /dev/null
+export class RoleTemplate {
+ id:string
+ name:string
+ description:string
+ application_id:string
+ assignable:boolean
+ permanent:boolean
+
+}
--- /dev/null
+/*
+ * 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 { RoleTree } from './role-tree';
+
+describe('RoleTree', () => {
+ it('should create an instance', () => {
+ expect(new RoleTree()).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 './role';
+import {Application} from "@app/model/application";
+
+export class RoleTree {
+ userid: string
+ applications: Map<string, Application>
+ root_roles: Array<Role>
+}
--- /dev/null
+/*
+ * 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 './role';
+
+describe('Role', () => {
+ it('should create an instance', () => {
+ expect(new Role()).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 Role {
+ id: string
+ name: string
+ description: string
+ assignable: boolean
+ permanent: boolean
+ child: boolean
+ assigned: boolean
+ template_instance: boolean
+ application_id:string
+ model_id:string
+ resource:string
+
+ children: Array<Role>
+
+ // Web Internal attributes
+ enabled: boolean = true
+ level:number = -1
+
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<p>manage-roles works!</p>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { ManageRolesComponent } from './manage-roles.component';
+
+describe('ManageRolesComponent', () => {
+ let component: ManageRolesComponent;
+ let fixture: ComponentFixture<ManageRolesComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageRolesComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageRolesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-manage-roles',
+ templateUrl: './manage-roles.component.html',
+ styleUrls: ['./manage-roles.component.scss']
+})
+export class ManageRolesComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<p>security-configuration works!</p>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { SecurityConfigurationComponent } from './security-configuration.component';
+
+describe('SecurityConfigurationComponent', () => {
+ let component: SecurityConfigurationComponent;
+ let fixture: ComponentFixture<SecurityConfigurationComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ SecurityConfigurationComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SecurityConfigurationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-security-configuration',
+ templateUrl: './security-configuration.component.html',
+ styleUrls: ['./security-configuration.component.scss']
+})
+export class SecurityConfigurationComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
--- /dev/null
+/*
+ * 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 { Routes, RouterModule } from '@angular/router';
+import { ManageUsersComponent } from './users/manage-users/manage-users.component';
+import { ManageUsersListComponent } from './users/manage-users-list/manage-users-list.component';
+import { ManageUsersAddComponent } from './users/manage-users-add/manage-users-add.component';
+import { ManageUsersEditComponent } from './users/manage-users-edit/manage-users-edit.component';
+import { ManageUsersDeleteComponent } from './users/manage-users-delete/manage-users-delete.component';
+import {ManageUsersRolesComponent} from "./users/manage-users-roles/manage-users-roles.component";
+import {RoutingGuardService as Guard} from "@app/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: ManageUsersComponent,canActivate:[Guard],
+ data: { perm: 'menu.user.manage' },
+ children: [
+ {path: 'list', component: ManageUsersListComponent},
+ {path: 'add', component: ManageUsersAddComponent},
+ {path: 'edit/:userid', component: ManageUsersEditComponent},
+ {path: 'edit', redirectTo:'edit/guest' },
+ {path: 'delete/:userid', component: ManageUsersDeleteComponent},
+ {path: 'roles', component:ManageUsersRolesComponent},
+ {path: 'roles/:userid', component:ManageUsersRolesComponent},
+ {path: '', redirectTo:'list',pathMatch:'full'}
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [],
+ declarations: []
+})
+export class UserRoutingModule { }
+
--- /dev/null
+/*
+ * 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 {ManageUsersComponent} from "./users/manage-users/manage-users.component";
+import {ManageUsersListComponent} from "./users/manage-users-list/manage-users-list.component";
+import {ManageUsersAddComponent} from "./users/manage-users-add/manage-users-add.component";
+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';
+import {UserRoutingModule} from "./user-routing.module";
+import { ManageUsersRolesComponent } from './users/manage-users-roles/manage-users-roles.component';
+import {RoutingGuardService} from "../../services/routing-guard.service";
+
+
+@NgModule({
+ declarations: [
+ ManageUsersComponent,
+ ManageUsersListComponent,
+ ManageUsersAddComponent,
+ ManageUsersEditComponent,
+ ManageUsersDeleteComponent,
+ ManageUsersRolesComponent
+ ],
+ exports: [
+ ManageUsersComponent,
+ ManageUsersListComponent,
+ ManageUsersAddComponent,
+ ManageUsersEditComponent
+ ],
+ imports: [
+ CommonModule,
+ SharedModule,
+ FormsModule,
+ ReactiveFormsModule,
+ UserRoutingModule
+ ]
+})
+export class UserModule {
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<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"
+ [ngClass]="valid('user_id')"
+ placeholder="{{'users.input.user_id'|translate}}">
+ <small>{{'users.input.small.user_id'|translate:{'minSize':this.minUserIdSize} }}</small>
+ <div *ngIf="userForm.get('user_id').invalid" class="invalid-feedback">
+ <div *ngIf="userForm.get('user_id').errors.required">
+ {{'form.error.required'|translate}}
+ </div>
+ <div *ngIf="userForm.get('user_id').errors.containsWhitespace">
+ {{'form.error.containsWhitespace'|translate}}
+ </div>
+ <div *ngIf="userForm.get('user_id').errors.userexists">
+ {{'form.error.userexists'|translate}}
+ </div>
+ </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>
+ <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>
+ <div class="form-group col-md-8">
+ <label for="password">{{'users.attributes.password' |translate}}</label>
+ <input type="password" class="form-control" formControlName="password" id="password"
+ [ngClass]="valid('password')"
+ placeholder="{{'users.input.password'|translate}}">
+ </div>
+ <div class="form-group col-md-8">
+ <label for="confirm_password">{{'users.attributes.confirm_password' |translate}}</label>
+ <input type="password" class="form-control" formControlName="confirm_password" id="confirm_password"
+ [ngClass]="valid('confirm_password')"
+ placeholder="{{'users.input.confirm_password'|translate}}">
+ </div>
+ <div class="form-group col-md-8">
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" formControlName="locked" id="locked">
+ <label class="form-check-label" for="locked">
+ {{'users.attributes.locked'|translate}}
+ </label>
+ </div>
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" formControlName="password_change_required"
+ id="password_change_required" checked>
+ <label class="form-check-label" for="password_change_required">
+ {{'users.attributes.password_change_required'|translate}}
+ </label>
+ </div>
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" formControlName="validated"
+ id="validated" checked>
+ <label class="form-check-label" for="validated">
+ {{'users.attributes.validated'|translate}}
+ </label>
+ </div>
+ </div>
+ <div class="form-group col-md-8">
+ <button class="btn btn-primary" type="submit"
+ [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.
+ </div>
+ <div *ngIf="error" class="alert alert-danger" role="alert" >
+ <h4 class="alert-heading">{{'users.add.errortitle'|translate}}</h4>
+ <ng-container *ngFor="let message of errorResult?.error_messages; first as isFirst" >
+ <hr *ngIf="!isFirst">
+ <p>{{message.message}}</p>
+ </ng-container>
+ </div>
+
+
+</form>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { ManageUsersAddComponent } from './manage-users-add.component';
+
+describe('ManageUsersAddComponent', () => {
+ let component: ManageUsersAddComponent;
+ let fixture: ComponentFixture<ManageUsersAddComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageUsersAddComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageUsersAddComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 {Component, OnInit} from '@angular/core';
+import {AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn} from '@angular/forms';
+import {UserService} from "../../../../services/user.service";
+import {ErrorResult} from "../../../../model/error-result";
+import {catchError} from "rxjs/operators";
+import {UserInfo} from "../../../../model/user-info";
+import {ManageUsersBaseComponent} from "../manage-users-base.component";
+
+@Component({
+ selector: 'app-manage-users-add',
+ templateUrl: './manage-users-add.component.html',
+ styleUrls: ['./manage-users-add.component.scss']
+})
+export class ManageUsersAddComponent extends ManageUsersBaseComponent implements OnInit {
+
+ constructor(userService: UserService, fb: FormBuilder) {
+ super(userService, fb);
+
+ }
+
+ ngOnInit(): void {
+ }
+
+ onSubmit() {
+ // Process checkout data here
+ this.result = null;
+ if (this.userForm.valid) {
+ let user = this.copyFromForm(this.editProperties);
+ console.info('Adding user ' + user);
+ this.userService.addUser(user).pipe(catchError((error: ErrorResult) => {
+ // console.log("Error " + error + " - " + typeof (error) + " - " + JSON.stringify(error));
+ if (error.status == 422) {
+ // console.warn("Validation error");
+ let pwdErrors = {};
+ for (let message of error.error_messages) {
+ if (message.error_key.startsWith('user.password.violation')) {
+ pwdErrors[message.error_key] = message.message;
+ }
+ }
+ this.userForm.get('password').setErrors(pwdErrors);
+
+ }
+ this.errorResult = error;
+ this.success = false;
+ this.error = true;
+ return [];
+ // return throwError(error);
+ })).subscribe((user: UserInfo) => {
+ this.result = user;
+ this.success = true;
+ this.error = false;
+ this.userForm.reset(this.formInitialValues);
+ });
+ }
+ }
+
+
+
+
+
+}
+
+
+
--- /dev/null
+/*
+ * 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 {environment} from "../../../../environments/environment";
+import {ErrorResult} from "../../../model/error-result";
+import {UserInfo} from "../../../model/user-info";
+import {
+ AbstractControl,
+ FormControl,
+ ValidatorFn,
+ Validators,
+ FormBuilder,
+ ValidationErrors,
+ FormGroup
+} from "@angular/forms";
+import {User} from "../../../model/user";
+import {of, timer} from "rxjs";
+import {catchError, map, switchMap} from "rxjs/operators";
+import { UserService } from 'src/app/services/user.service';
+
+export class ManageUsersBaseComponent {
+
+ editProperties = ['user_id', 'full_name', 'email', 'locked', 'password_change_required',
+ 'password', 'confirm_password', 'validated'];
+ minUserIdSize = environment.application.minUserIdLength;
+ success: boolean = false;
+ error: boolean = false;
+ errorResult: ErrorResult;
+ result: UserInfo;
+ user: string;
+ formInitialValues;
+
+ userForm = this.fb.group({
+ user_id: ['', [Validators.required, Validators.minLength(this.minUserIdSize), whitespaceValidator()], this.userUidExistsValidator()],
+ full_name: ['', Validators.required],
+ email: ['', [Validators.required, Validators.email]],
+ locked: [false],
+ password_change_required: [true],
+ password: [''],
+ confirm_password: [''],
+ validated: [true]
+ }, {
+ validator: MustMatch('password', 'confirm_password')
+ })
+
+ constructor(public userService: UserService, public fb: FormBuilder) {
+ this.formInitialValues=this.userForm.value
+ }
+
+
+ public copyFromForm(properties: string[]): User {
+ let user: any = new User();
+ for (let prop of properties) {
+ user[prop] = this.userForm.get(prop).value;
+ }
+ console.log("User " + user);
+ return user;
+ }
+
+ public copyToForm(properties: string[], user: User): void {
+ let propMap = {};
+ for (let prop of properties) {
+ let propValue = user[prop] == null ? '' : user[prop];
+ propMap[prop] = propValue;
+ }
+ this.userForm.patchValue(propMap);
+ console.log("User " + user);
+ }
+
+
+ valid(field: string): string[] {
+ let formField = this.userForm.get(field);
+ if (formField.dirty || formField.touched) {
+ if (formField.valid) {
+ return ['is-valid']
+ } else {
+ return ['is-invalid']
+ }
+ } else {
+ return ['']
+ }
+ }
+
+ /**
+ * Async validator with debounce time
+ * @constructor
+ */
+ userUidExistsValidator() {
+
+ return (ctrl: FormControl) => {
+ // debounceTimer() does not work here, as the observable is created with each keystroke
+ // but angular does unsubscribe on previous started async observables.
+ return timer(500).pipe(
+ switchMap((userid) => this.userService.userExists(ctrl.value)),
+ catchError(() => of(null)),
+ map(exists => (exists ? {userexists: true} : null))
+ );
+ }
+ }
+
+ forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
+ return (control: AbstractControl): { [key: string]: any } | null => {
+ const forbidden = nameRe.test(control.value);
+ 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 {
+ return (control: AbstractControl): ValidationErrors | null => {
+ const hasWhitespace = /\s/g.test(control.value);
+ return hasWhitespace ? {containsWhitespace: {value: control.value}} : null;
+ };
+}
+export function MustMatch(controlName: string, matchingControlName: string) : ValidatorFn {
+ return (formGroup: FormGroup): ValidationErrors | null => {
+ const control = formGroup.controls[controlName];
+ const matchingControl = formGroup.controls[matchingControlName];
+
+ if (matchingControl.errors && !matchingControl.errors.mustMatch) {
+ // return if another validator has already found an error on the matchingControl
+ return;
+ }
+
+ // set error on matchingControl if validation fails
+ if (control.value !== matchingControl.value) {
+ matchingControl.setErrors({mustMatch: true});
+ } else {
+ matchingControl.setErrors(null);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<!--
+ ~ 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">×</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>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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();
+ });
+});
--- /dev/null
+/*
+ * 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(['/security','users','list']);
+ }
+ } else if (result=='NO') {
+ this.router.navigate(['/security','users','list']);
+ }
+ }, (reason) => {
+ console.log("Reason: " + reason);
+ });
+ }
+ }
+
+ ngAfterViewInit(): void {
+ if (this.user_id!=null) {
+ this.runModal();
+ }
+ }
+
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()">
+ <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" [checked]="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')"
+ [attr.readonly]="true">
+ </div>
+ </div>
+ <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')" [attr.readonly]="editMode?null:true">
+ <small *ngIf="editMode">{{'users.input.small.full_name'|translate}}</small>
+ </div>
+ </div>
+ <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?null:true">
+ </div>
+ </div>
+ <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}}">
+ <small>{{'users.edit.small.password'|translate}}</small>
+ </div>
+ </div>
+ <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 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" 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"
+ 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 class="form-check">
+ <input class="form-check-input" type="checkbox"
+ formControlName="validated"
+ id="validated" [attr.disabled]="editMode?null:true">
+ <label class="form-check-label" for="validated">
+ {{'users.attributes.validated'|translate}}
+ </label>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row col-md-8">
+ <label class="col-md-2 col-form-label" for="created">{{'users.attributes.created' |translate}}</label>
+ <div class="col-md-6">
+ <input type="text" id="created" class="form-control-plaintext"
+ value="{{editUser.timestamp_account_creation|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
+ </div>
+ </div>
+ <div class="form-group row col-md-8">
+ <label class="col-md-2 col-form-label" for="last_login">{{'users.attributes.last_login' |translate}}</label>
+ <div class="col-md-6">
+ <input type="text" id="last_login" class="form-control-plaintext"
+ value="{{editUser.timestamp_last_login|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
+ </div>
+ </div>
+ <div class="form-group row col-md-8">
+ <label class="col-md-2 col-form-label" for="email">{{'users.attributes.last_password_change' |translate}}</label>
+ <div class="col-md-6">
+ <input type="text" id="last_password_change" class="form-control-plaintext"
+ value="{{editUser.timestamp_last_password_change|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
+ </div>
+ </div>
+
+ <div class="form-group col-md-8" *ngIf="editMode">
+ <button class="btn btn-primary" type="submit"
+ [disabled]="userForm.invalid || !userForm.dirty">{{'users.edit.submit'|translate}}</button>
+ </div>
+ <div *ngIf="success" class="alert alert-success" role="alert">
+ User has been updated.
+ </div>
+ <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">
+ <p>{{message.message}}</p>
+ </ng-container>
+ </div>
+ <div *ngIf="editMode && userForm.invalid" class="alert alert-danger" role="alert" >
+ <h4 class="alert-heading">Validation Errors</h4>
+ <ng-container *ngFor="let message of getAllErrors(userForm); first as isFirst" >
+ <hr *ngIf="!isFirst">
+ <p>{{message}}</p>
+ </ng-container>
+ </div>
+
+
+</form>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { ManageUsersEditComponent } from './manage-users-edit.component';
+
+describe('ManageUsersEditComponent', () => {
+ let component: ManageUsersEditComponent;
+ let fixture: ComponentFixture<ManageUsersEditComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageUsersEditComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageUsersEditComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 {Component, OnInit} 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 {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']
+})
+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;
+ minUserIdSize = 0;
+
+ 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 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'];
+ }
+ }
+
+
+ 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;
+ });
+
+ }
+
+
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<app-paginated-entities [service]="service" pageSize="5" [(sortField)]="sortField" [(sortOrder)]="sortOrder"
+ #parent>
+
+ <table class="table table-striped table-bordered">
+ <thead class="thead-light">
+ <tr sorted [sortFieldEmitter]="parent.sortFieldChange" [sortOrderEmitter]="parent.sortOrderChange"
+ [toggleObserver]="parent">
+ <app-th-sorted [fieldArray]="['user_id']" contentText="users.attributes.user_id"></app-th-sorted>
+ <app-th-sorted [fieldArray]="['full_name']" contentText="users.attributes.full_name" ></app-th-sorted>
+ <app-th-sorted [fieldArray]="['email']" contentText="users.attributes.email" ></app-th-sorted>
+ <app-th-sorted [fieldArray]="['validated','user_id']">
+ <span class="fas fa-check" placement="top"
+ [ngbTooltip]="heads.validated" [attr.aria-label]="heads.validated"></span>
+ </app-th-sorted>
+ <app-th-sorted [fieldArray]="['locked','user_id']"><span class="fas fa-lock" placement="top"
+ [ngbTooltip]="heads.locked" [attr.aria-label]="heads.locked"></span></app-th-sorted>
+ <app-th-sorted [fieldArray]="['password_change_required','user_id']"><span class="fa fa-chevron-circle-right" placement="top"
+ [ngbTooltip]="heads.password_change_required" [attr.aria-label]="heads.password_change_required"></span>
+ </app-th-sorted>
+ <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>
+ <tr *ngFor="let user of parent.items$ | async" [ngClass]="(user.permanent||user.readOnly)?'table-secondary':''">
+ <td><span data-toggle="tooltip" placement="left" ngbTooltip="{{user.id}}">{{user.user_id}}</span></td>
+ <td>{{user.full_name}}</td>
+ <td>{{user.email}}</td>
+ <td><span class="far" [attr.aria-valuetext]="user.validated"
+ [ngClass]="user.validated?'fa-check-circle':'fa-circle'"></span></td>
+ <td><span class="far" [attr.aria-valuetext]="user.locked"
+ [ngClass]="user.locked?'fa-check-circle':'fa-circle'"></span></td>
+ <td><span class="far" [attr.aria-valuetext]="user.password_change_required"
+ [ngClass]="user.password_change_required?'fa-check-circle':'fa-circle'"></span></td>
+ <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}" [attr.title]="'users.edit.head' |translate"><span class="fas fa-edit"></span></a>
+ <a [routerLink]="['..','delete',user.user_id]" [attr.title]="'users.delete.head'|translate"><span class="fas fa-user-minus"></span></a>
+ <a [routerLink]="['..','roles',user.user_id]" [attr.title]="'users.roles.head'|translate"><span class="fas fa-user-tag" ></span></a>
+ </ng-container>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+</app-paginated-entities>
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { ManageUsersListComponent } from './manage-users-list.component';
+
+describe('ManageUsersListComponent', () => {
+ let component: ManageUsersListComponent;
+ let fixture: ComponentFixture<ManageUsersListComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageUsersListComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageUsersListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 {Component, OnInit, Input, OnDestroy} from '@angular/core';
+import {TranslateService} from "@ngx-translate/core";
+import {UserService} from "../../../../services/user.service";
+import {UserInfo} from "../../../../model/user-info";
+import {EntityService} from "../../../../model/entity-service";
+import {Observable, of} from "rxjs";
+import {PagedResult} from "../../../../model/paged-result";
+
+@Component({
+ selector: 'app-manage-users-list',
+ templateUrl: './manage-users-list.component.html',
+ styleUrls: ['./manage-users-list.component.scss']
+})
+export class ManageUsersListComponent implements OnInit {
+
+ @Input() heads: any;
+ service : EntityService<UserInfo>;
+ sortField = ["user_id"];
+ sortOrder = "asc";
+
+
+ constructor(private translator: TranslateService, private userService : UserService) {
+ this.service = function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string) : Observable<PagedResult<UserInfo>> {
+ console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
+ return userService.query(searchTerm, offset, limit, orderBy, order);
+ }
+
+ }
+
+ ngOnInit(): void {
+ this.heads = {};
+ // We need to wait for the translator initialization and use the init key as step in.
+ this.translator.get('init').subscribe(() => {
+ // Only table headings for small columns that use icons
+ for (let suffix of ['validated', 'locked', 'password_change_required']) {
+ this.heads[suffix] = this.translator.instant('users.attributes.' + suffix);
+ }
+ });
+ }
+
+
+ changeSortOrder(order:string) {
+ if (this.sortOrder!=order) {
+ this.sortOrder = order;
+ }
+ }
+
+ private compareArrays(a1: string[], a2: string[]) {
+ let i = a1.length;
+ while (i--) {
+ if (a1[i] !== a2[i]) return false;
+ }
+ return true
+ }
+
+ sortCheck(fieldArray:string[]) {
+ return this.compareArrays(this.sortField, fieldArray);
+ }
+
+ isAscending() : boolean {
+ return this.sortOrder == "asc";
+ }
+
+
+
+
+
+
+
+
+
+}
--- /dev/null
+<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)"
+ >
+ </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>
+ </td>
+ </tr>
+ </tbody>
+
+</table>
--- /dev/null
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ManageUsersRolesComponent } from './manage-users-roles.component';
+
+describe('ManageUsersRolesComponent', () => {
+ let component: ManageUsersRolesComponent;
+ let fixture: ComponentFixture<ManageUsersRolesComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageUsersRolesComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageUsersRolesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, OnInit } 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 {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 {Util} from "@app/modules/shared/shared.module";
+
+@Component({
+ selector: 'app-manage-users-roles',
+ templateUrl: './manage-users-roles.component.html',
+ styleUrls: ['./manage-users-roles.component.scss']
+})
+export class ManageUsersRolesComponent implements OnInit {
+
+ baseRoles : Array<Role>
+ guest: Role
+ registered: Role
+ // Map of (resource, [roles])
+ templateRoleInstances: Map<string, Array<Role>>
+ templateRoles$: Observable<RoleTemplate[]>;
+
+ 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);
+ });
+
+ }
+
+ ngOnInit(): void {
+ 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);
+ }
+ 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);
+ }
+ this.templateRoleInstances = templateMap;
+ }
+
+ private recurseRoleTree(role:Role, roles : Array<Role>, level:number) : Array<Role> {
+ if (role.id=='guest') {
+ this.guest = role;
+ } else if (role.id=='registered-user') {
+ this.registered = role;
+ }
+ role.enabled=true;
+ let newLevel;
+ if (!role.template_instance && 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;
+ }
+
+ private recurseTemplates(role:Role, roles : Map<string, Array<Role>>, level:number) : Map<string, Array<Role>> {
+ role.enabled=true;
+ if (role.template_instance && role.assignable) {
+ role.level=level
+ let roleList = roles.get(role.resource)
+ if (roleList==null) {
+ roleList = []
+ }
+ roleList.push(role);
+ roles.set(role.resource, roleList);
+ }
+ for(let childRole of role.children) {
+ roles = this.recurseTemplates(childRole, roles, level+1);
+ }
+ return roles;
+ }
+
+ getRoleContent(role:Role) : string {
+ let level = role.level
+ let result = "";
+ for(let _i=0; _i<level; _i++) {
+ result = result + " <i class='fas fa-angle-double-right'></i> ";
+ }
+ if (role.child) {
+ return result + role.name;
+ } else {
+ return "<strong>"+result+role.name+"</strong>"
+ }
+ }
+
+ changeBaseAssignment(role : Role, event) {
+ let cLevel=-1
+ let assignStatus;
+ if (role.id==this.guest.id) {
+ if (role.assigned) {
+ for (let cRole of this.baseRoles) {
+ if (cRole.id != this.guest.id) {
+ cRole.assigned = false;
+ cRole.enabled=true;
+ }
+ }
+ role.enabled = false;
+ }
+ } else {
+ this.guest.enabled = true;
+ for (let cRole of this.baseRoles) {
+ if (cRole.id == role.id) {
+ console.log("Value: " + cRole.assigned);
+ cLevel = cRole.level;
+ assignStatus = cRole.assigned;
+ if (assignStatus) {
+ this.guest.assigned = false;
+ } else {
+ if (!this.baseRoles.find(role=>role.assigned)) {
+ this.guest.assigned=true;
+ }
+ }
+ } else {
+ console.log("Level " + cLevel);
+ if (cLevel >= 0 && cLevel < cRole.level) {
+ if (assignStatus) {
+ cRole.assigned = true;
+ cRole.enabled = false;
+ } else {
+ cRole.enabled = true;
+ }
+ } else if (cLevel >= 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ 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:Array<Role>) : Role {
+ return roles.find(role=>role.model_id==template.id)
+ }
+}
--- /dev/null
+<!--
+ ~ 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.
+ -->
+
+<ul class="nav nav-tabs">
+ <li class="nav-item">
+ <a class="nav-link" routerLink="/security/users/list" routerLinkActive="active" href="#">{{'users.list.head' | translate}}</a>
+ </li>
+ <li class="nav-item">
+ <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>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" routerLink="/security/users/roles" routerLinkActive="active" href="#">{{'users.roles.head' |translate }}</a>
+ </li>
+</ul>
+
+<router-outlet ></router-outlet>
\ No newline at end of file
--- /dev/null
+/*!
+ * 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.
+ */
+
--- /dev/null
+/*
+ * 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 { ManageUsersComponent } from './manage-users.component';
+
+describe('ManageUsersComponent', () => {
+ let component: ManageUsersComponent;
+ let fixture: ComponentFixture<ManageUsersComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ManageUsersComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ManageUsersComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+/*
+ * 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 { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-manage-users',
+ templateUrl: './manage-users.component.html',
+ styleUrls: ['./manage-users.component.scss']
+})
+export class ManageUsersComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
* under the License.
*/
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
import {PaginatedEntitiesComponent} from "./paginated-entities/paginated-entities.component";
import {SortedTableHeaderComponent} from "./sorted-table-header/sorted-table-header.component";
import {SortedTableHeaderRowComponent} from "./sorted-table-header-row/sorted-table-header-row.component";
import {RouterModule} from "@angular/router";
-
@NgModule({
- declarations: [
- PaginatedEntitiesComponent,
- SortedTableHeaderComponent,
- SortedTableHeaderRowComponent
- ],
- exports: [
- CommonModule,
- RouterModule,
- TranslateModule,
- NgbPaginationModule,
- NgbTooltipModule,
- PaginatedEntitiesComponent,
- SortedTableHeaderComponent,
- SortedTableHeaderRowComponent
- ],
- imports: [
- CommonModule,
- RouterModule,
- NgbPaginationModule,
- NgbTooltipModule,
- TranslateModule.forChild({
- compiler: {
- provide: TranslateCompiler,
- useClass: TranslateMessageFormatCompiler
- },
- loader: {
- provide: TranslateLoader,
- useFactory: httpTranslateLoader,
- deps: [HttpClient]
- }
- }),
- ]
+ declarations: [
+ PaginatedEntitiesComponent,
+ SortedTableHeaderComponent,
+ SortedTableHeaderRowComponent
+ ],
+ exports: [
+ CommonModule,
+ RouterModule,
+ TranslateModule,
+ NgbPaginationModule,
+ NgbTooltipModule,
+ PaginatedEntitiesComponent,
+ SortedTableHeaderComponent,
+ SortedTableHeaderRowComponent
+ ],
+ imports: [
+ CommonModule,
+ RouterModule,
+ NgbPaginationModule,
+ NgbTooltipModule,
+ TranslateModule.forChild({
+ compiler: {
+ provide: TranslateCompiler,
+ useClass: TranslateMessageFormatCompiler
+ },
+ loader: {
+ provide: TranslateLoader,
+ useFactory: httpTranslateLoader,
+ deps: [HttpClient]
+ }
+ }),
+ ]
})
-export class SharedModule { }
+export class SharedModule {
+}
+
export function httpTranslateLoader(http: HttpClient) {
- return new TranslateHttpLoader(http);
+ return new TranslateHttpLoader(http);
+}
+
+export const Util = {
+ deepCopy(src: Object, dst: Object) {
+ Object.keys(src).forEach((key, idx) => {
+ let srcEl = src[key];
+ if (typeof (srcEl) == 'object') {
+ let dstEl;
+ if (!dst.hasOwnProperty(key)) {
+ dst[key] = {}
+ }
+ dstEl = dst[key];
+ this.deepCopy(srcEl, dstEl);
+ } else {
+ // console.debug("setting " + key + " = " + srcEl);
+ dst[key] = srcEl;
+ }
+ });
+ }
}
\ No newline at end of file
<div class="nav flex-column nav-pills" [appViewPermission]="perms.menu.user.section">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill"
role="tab" aria-controls="v-pills-home" aria-selected="false">{{'sidemenu.user.section'|translate}}</a>
- <a class="nav-link my-0 py-0" id="users-manage" routerLink="/user/users" routerLinkActive="active" data-toggle="pill"
+ <a class="nav-link my-0 py-0" id="users-manage" routerLink="/security/users" routerLinkActive="active" data-toggle="pill"
role="tab" aria-controls="v-pills-browse" aria-selected="false">{{'sidemenu.user.users'|translate}}</a>
- <a class="nav-link my-0 py-0" id="users-roles" routerLink="/user/roles" routerLinkActive="active" data-toggle="pill"
+ <a class="nav-link my-0 py-0" id="users-roles" routerLink="/security/roles" routerLinkActive="active" data-toggle="pill"
role="tab" aria-controls="v-pills-browse" aria-selected="false">{{'sidemenu.user.roles'|translate}}</a>
- <a class="nav-link my-0 py-0" id="users-configuration" routerLink="/user/config" routerLinkActive="active" data-toggle="pill"
+ <a class="nav-link my-0 py-0" id="users-configuration" routerLink="/security/config" routerLinkActive="active" data-toggle="pill"
role="tab" aria-controls="v-pills-browse" aria-selected="false">{{'sidemenu.user.config'|translate}}</a>
</div>
<div class="nav flex-column nav-pills" >
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<p>manage-roles works!</p>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { ManageRolesComponent } from './manage-roles.component';
-
-describe('ManageRolesComponent', () => {
- let component: ManageRolesComponent;
- let fixture: ComponentFixture<ManageRolesComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ ManageRolesComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ManageRolesComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-manage-roles',
- templateUrl: './manage-roles.component.html',
- styleUrls: ['./manage-roles.component.scss']
-})
-export class ManageRolesComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
-}
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<p>security-configuration works!</p>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { SecurityConfigurationComponent } from './security-configuration.component';
-
-describe('SecurityConfigurationComponent', () => {
- let component: SecurityConfigurationComponent;
- let fixture: ComponentFixture<SecurityConfigurationComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ SecurityConfigurationComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(SecurityConfigurationComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-security-configuration',
- templateUrl: './security-configuration.component.html',
- styleUrls: ['./security-configuration.component.scss']
-})
-export class SecurityConfigurationComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
-}
+++ /dev/null
-/*
- * 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 { Routes, RouterModule } from '@angular/router';
-import { ManageUsersComponent } from './users/manage-users/manage-users.component';
-import { ManageUsersListComponent } from './users/manage-users-list/manage-users-list.component';
-import { ManageUsersAddComponent } from './users/manage-users-add/manage-users-add.component';
-import { ManageUsersEditComponent } from './users/manage-users-edit/manage-users-edit.component';
-import { ManageUsersDeleteComponent } from './users/manage-users-delete/manage-users-delete.component';
-import {SharedModule} from "../shared/shared.module";
-import {TranslateModule} from "@ngx-translate/core";
-
-
-/**
- * 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: ManageUsersComponent,
- children: [
- {path: 'list', component: ManageUsersListComponent},
- {path: 'add', component: ManageUsersAddComponent},
- {path: 'edit/:userid', component: ManageUsersEditComponent},
- {path: 'edit', redirectTo:'edit/guest' },
- {path: 'delete/:userid', component: ManageUsersDeleteComponent},
- ]
- }
-];
-
-@NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [],
- declarations: []
-})
-export class UserRoutingModule { }
-
+++ /dev/null
-/*
- * 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 {ManageUsersComponent} from "./users/manage-users/manage-users.component";
-import {ManageUsersListComponent} from "./users/manage-users-list/manage-users-list.component";
-import {ManageUsersAddComponent} from "./users/manage-users-add/manage-users-add.component";
-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';
-import {UserRoutingModule} from "./user-routing.module";
-import {TranslateLoader, TranslateModule } from '@ngx-translate/core';
-import { HttpClient } from '@angular/common/http';
-
-
-@NgModule({
- declarations: [
- ManageUsersComponent,
- ManageUsersListComponent,
- ManageUsersAddComponent,
- ManageUsersEditComponent,
- ManageUsersDeleteComponent
- ],
- exports: [
- ManageUsersComponent,
- ManageUsersListComponent,
- ManageUsersAddComponent,
- ManageUsersEditComponent
- ],
- imports: [
- CommonModule,
- SharedModule,
- FormsModule,
- ReactiveFormsModule,
- UserRoutingModule
- ]
-})
-export class UserModule {
-}
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<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"
- [ngClass]="valid('user_id')"
- placeholder="{{'users.input.user_id'|translate}}">
- <small>{{'users.input.small.user_id'|translate:{'minSize':this.minUserIdSize} }}</small>
- <div *ngIf="userForm.get('user_id').invalid" class="invalid-feedback">
- <div *ngIf="userForm.get('user_id').errors.required">
- {{'form.error.required'|translate}}
- </div>
- <div *ngIf="userForm.get('user_id').errors.containsWhitespace">
- {{'form.error.containsWhitespace'|translate}}
- </div>
- <div *ngIf="userForm.get('user_id').errors.userexists">
- {{'form.error.userexists'|translate}}
- </div>
- </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>
- <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>
- <div class="form-group col-md-8">
- <label for="password">{{'users.attributes.password' |translate}}</label>
- <input type="password" class="form-control" formControlName="password" id="password"
- [ngClass]="valid('password')"
- placeholder="{{'users.input.password'|translate}}">
- </div>
- <div class="form-group col-md-8">
- <label for="confirm_password">{{'users.attributes.confirm_password' |translate}}</label>
- <input type="password" class="form-control" formControlName="confirm_password" id="confirm_password"
- [ngClass]="valid('confirm_password')"
- placeholder="{{'users.input.confirm_password'|translate}}">
- </div>
- <div class="form-group col-md-8">
- <div class="form-check">
- <input class="form-check-input" type="checkbox" formControlName="locked" id="locked">
- <label class="form-check-label" for="locked">
- {{'users.attributes.locked'|translate}}
- </label>
- </div>
- <div class="form-check">
- <input class="form-check-input" type="checkbox" formControlName="password_change_required"
- id="password_change_required" checked>
- <label class="form-check-label" for="password_change_required">
- {{'users.attributes.password_change_required'|translate}}
- </label>
- </div>
- <div class="form-check">
- <input class="form-check-input" type="checkbox" formControlName="validated"
- id="validated" checked>
- <label class="form-check-label" for="validated">
- {{'users.attributes.validated'|translate}}
- </label>
- </div>
- </div>
- <div class="form-group col-md-8">
- <button class="btn btn-primary" type="submit"
- [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.
- </div>
- <div *ngIf="error" class="alert alert-danger" role="alert" >
- <h4 class="alert-heading">{{'users.add.errortitle'|translate}}</h4>
- <ng-container *ngFor="let message of errorResult?.error_messages; first as isFirst" >
- <hr *ngIf="!isFirst">
- <p>{{message.message}}</p>
- </ng-container>
- </div>
-
-
-</form>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { ManageUsersAddComponent } from './manage-users-add.component';
-
-describe('ManageUsersAddComponent', () => {
- let component: ManageUsersAddComponent;
- let fixture: ComponentFixture<ManageUsersAddComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ ManageUsersAddComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ManageUsersAddComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 {Component, OnInit} from '@angular/core';
-import {AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn} from '@angular/forms';
-import {UserService} from "../../../../services/user.service";
-import {ErrorResult} from "../../../../model/error-result";
-import {catchError} from "rxjs/operators";
-import {UserInfo} from "../../../../model/user-info";
-import {ManageUsersBaseComponent} from "../manage-users-base.component";
-
-@Component({
- selector: 'app-manage-users-add',
- templateUrl: './manage-users-add.component.html',
- styleUrls: ['./manage-users-add.component.scss']
-})
-export class ManageUsersAddComponent extends ManageUsersBaseComponent implements OnInit {
-
- constructor(userService: UserService, fb: FormBuilder) {
- super(userService, fb);
-
- }
-
- ngOnInit(): void {
- }
-
- onSubmit() {
- // Process checkout data here
- this.result = null;
- if (this.userForm.valid) {
- let user = this.copyFromForm(this.editProperties);
- console.info('Adding user ' + user);
- this.userService.addUser(user).pipe(catchError((error: ErrorResult) => {
- // console.log("Error " + error + " - " + typeof (error) + " - " + JSON.stringify(error));
- if (error.status == 422) {
- // console.warn("Validation error");
- let pwdErrors = {};
- for (let message of error.error_messages) {
- if (message.error_key.startsWith('user.password.violation')) {
- pwdErrors[message.error_key] = message.message;
- }
- }
- this.userForm.get('password').setErrors(pwdErrors);
-
- }
- this.errorResult = error;
- this.success = false;
- this.error = true;
- return [];
- // return throwError(error);
- })).subscribe((user: UserInfo) => {
- this.result = user;
- this.success = true;
- this.error = false;
- this.userForm.reset(this.formInitialValues);
- });
- }
- }
-
-
-
-
-
-}
-
-
-
+++ /dev/null
-/*
- * 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 {environment} from "../../../../environments/environment";
-import {ErrorResult} from "../../../model/error-result";
-import {UserInfo} from "../../../model/user-info";
-import {
- AbstractControl,
- FormControl,
- ValidatorFn,
- Validators,
- FormBuilder,
- ValidationErrors,
- FormGroup
-} from "@angular/forms";
-import {User} from "../../../model/user";
-import {of, timer} from "rxjs";
-import {catchError, map, switchMap} from "rxjs/operators";
-import { UserService } from 'src/app/services/user.service';
-
-export class ManageUsersBaseComponent {
-
- editProperties = ['user_id', 'full_name', 'email', 'locked', 'password_change_required',
- 'password', 'confirm_password', 'validated'];
- minUserIdSize = environment.application.minUserIdLength;
- success: boolean = false;
- error: boolean = false;
- errorResult: ErrorResult;
- result: UserInfo;
- user: string;
- formInitialValues;
-
- userForm = this.fb.group({
- user_id: ['', [Validators.required, Validators.minLength(this.minUserIdSize), whitespaceValidator()], this.userUidExistsValidator()],
- full_name: ['', Validators.required],
- email: ['', [Validators.required, Validators.email]],
- locked: [false],
- password_change_required: [true],
- password: [''],
- confirm_password: [''],
- validated: [true]
- }, {
- validator: MustMatch('password', 'confirm_password')
- })
-
- constructor(public userService: UserService, public fb: FormBuilder) {
- this.formInitialValues=this.userForm.value
- }
-
-
- public copyFromForm(properties: string[]): User {
- let user: any = new User();
- for (let prop of properties) {
- user[prop] = this.userForm.get(prop).value;
- }
- console.log("User " + user);
- return user;
- }
-
- public copyToForm(properties: string[], user: User): void {
- let propMap = {};
- for (let prop of properties) {
- let propValue = user[prop] == null ? '' : user[prop];
- propMap[prop] = propValue;
- }
- this.userForm.patchValue(propMap);
- console.log("User " + user);
- }
-
-
- valid(field: string): string[] {
- let formField = this.userForm.get(field);
- if (formField.dirty || formField.touched) {
- if (formField.valid) {
- return ['is-valid']
- } else {
- return ['is-invalid']
- }
- } else {
- return ['']
- }
- }
-
- /**
- * Async validator with debounce time
- * @constructor
- */
- userUidExistsValidator() {
-
- return (ctrl: FormControl) => {
- // debounceTimer() does not work here, as the observable is created with each keystroke
- // but angular does unsubscribe on previous started async observables.
- return timer(500).pipe(
- switchMap((userid) => this.userService.userExists(ctrl.value)),
- catchError(() => of(null)),
- map(exists => (exists ? {userexists: true} : null))
- );
- }
- }
-
- forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
- return (control: AbstractControl): { [key: string]: any } | null => {
- const forbidden = nameRe.test(control.value);
- 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 {
- return (control: AbstractControl): ValidationErrors | null => {
- const hasWhitespace = /\s/g.test(control.value);
- return hasWhitespace ? {containsWhitespace: {value: control.value}} : null;
- };
-}
-export function MustMatch(controlName: string, matchingControlName: string) : ValidatorFn {
- return (formGroup: FormGroup): ValidationErrors | null => {
- const control = formGroup.controls[controlName];
- const matchingControl = formGroup.controls[matchingControlName];
-
- if (matchingControl.errors && !matchingControl.errors.mustMatch) {
- // return if another validator has already found an error on the matchingControl
- return;
- }
-
- // set error on matchingControl if validation fails
- if (control.value !== matchingControl.value) {
- matchingControl.setErrors({mustMatch: true});
- } else {
- matchingControl.setErrors(null);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-<!--
- ~ 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">×</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>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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();
- });
-});
+++ /dev/null
-/*
- * 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();
- }
- }
-
-}
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()">
- <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" [checked]="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')"
- [attr.readonly]="true">
- </div>
- </div>
- <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')" [attr.readonly]="editMode?null:true">
- <small *ngIf="editMode">{{'users.input.small.full_name'|translate}}</small>
- </div>
- </div>
- <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?null:true">
- </div>
- </div>
- <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}}">
- <small>{{'users.edit.small.password'|translate}}</small>
- </div>
- </div>
- <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 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" 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"
- 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 class="form-check">
- <input class="form-check-input" type="checkbox"
- formControlName="validated"
- id="validated" [attr.disabled]="editMode?null:true">
- <label class="form-check-label" for="validated">
- {{'users.attributes.validated'|translate}}
- </label>
- </div>
- </div>
- </div>
- <div class="form-group row col-md-8">
- <label class="col-md-2 col-form-label" for="created">{{'users.attributes.created' |translate}}</label>
- <div class="col-md-6">
- <input type="text" id="created" class="form-control-plaintext"
- value="{{editUser.timestamp_account_creation|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
- </div>
- </div>
- <div class="form-group row col-md-8">
- <label class="col-md-2 col-form-label" for="last_login">{{'users.attributes.last_login' |translate}}</label>
- <div class="col-md-6">
- <input type="text" id="last_login" class="form-control-plaintext"
- value="{{editUser.timestamp_last_login|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
- </div>
- </div>
- <div class="form-group row col-md-8">
- <label class="col-md-2 col-form-label" for="email">{{'users.attributes.last_password_change' |translate}}</label>
- <div class="col-md-6">
- <input type="text" id="last_password_change" class="form-control-plaintext"
- value="{{editUser.timestamp_last_password_change|date:'yyyy-MM-ddTHH:mm:ss'}}" [attr.readonly]="true">
- </div>
- </div>
-
- <div class="form-group col-md-8" *ngIf="editMode">
- <button class="btn btn-primary" type="submit"
- [disabled]="userForm.invalid || !userForm.dirty">{{'users.edit.submit'|translate}}</button>
- </div>
- <div *ngIf="success" class="alert alert-success" role="alert">
- User has been updated.
- </div>
- <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">
- <p>{{message.message}}</p>
- </ng-container>
- </div>
- <div *ngIf="editMode && userForm.invalid" class="alert alert-danger" role="alert" >
- <h4 class="alert-heading">Validation Errors</h4>
- <ng-container *ngFor="let message of getAllErrors(userForm); first as isFirst" >
- <hr *ngIf="!isFirst">
- <p>{{message}}</p>
- </ng-container>
- </div>
-
-
-</form>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { ManageUsersEditComponent } from './manage-users-edit.component';
-
-describe('ManageUsersEditComponent', () => {
- let component: ManageUsersEditComponent;
- let fixture: ComponentFixture<ManageUsersEditComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ ManageUsersEditComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ManageUsersEditComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 {Component, OnInit} 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 {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']
-})
-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;
- minUserIdSize = 0;
-
- 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 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'];
- }
- }
-
-
- 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;
- });
-
- }
-
-
-}
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<app-paginated-entities [service]="service" pageSize="5" [(sortField)]="sortField" [(sortOrder)]="sortOrder"
- #parent>
-
- <table class="table table-striped table-bordered">
- <thead class="thead-light">
- <tr sorted [sortFieldEmitter]="parent.sortFieldChange" [sortOrderEmitter]="parent.sortOrderChange"
- [toggleObserver]="parent">
- <app-th-sorted [fieldArray]="['user_id']" contentText="users.attributes.user_id"></app-th-sorted>
- <app-th-sorted [fieldArray]="['full_name']" contentText="users.attributes.full_name" ></app-th-sorted>
- <app-th-sorted [fieldArray]="['email']" contentText="users.attributes.email" ></app-th-sorted>
- <app-th-sorted [fieldArray]="['validated','user_id']">
- <span class="fas fa-check" placement="top"
- [ngbTooltip]="heads.validated" [attr.aria-label]="heads.validated"></span>
- </app-th-sorted>
- <app-th-sorted [fieldArray]="['locked','user_id']"><span class="fas fa-lock" placement="top"
- [ngbTooltip]="heads.locked" [attr.aria-label]="heads.locked"></span></app-th-sorted>
- <app-th-sorted [fieldArray]="['password_change_required','user_id']"><span class="fa fa-chevron-circle-right" placement="top"
- [ngbTooltip]="heads.password_change_required" [attr.aria-label]="heads.password_change_required"></span>
- </app-th-sorted>
- <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>
- <tr *ngFor="let user of parent.items$ | async" [ngClass]="(user.permanent||user.readOnly)?'table-secondary':''">
- <td><span data-toggle="tooltip" placement="left" ngbTooltip="{{user.id}}">{{user.user_id}}</span></td>
- <td>{{user.full_name}}</td>
- <td>{{user.email}}</td>
- <td><span class="far" [attr.aria-valuetext]="user.validated"
- [ngClass]="user.validated?'fa-check-circle':'fa-circle'"></span></td>
- <td><span class="far" [attr.aria-valuetext]="user.locked"
- [ngClass]="user.locked?'fa-check-circle':'fa-circle'"></span></td>
- <td><span class="far" [attr.aria-valuetext]="user.password_change_required"
- [ngClass]="user.password_change_required?'fa-check-circle':'fa-circle'"></span></td>
- <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>
- <a *ngIf="!user.permanent" [routerLink]="['..','delete',user.user_id]"><span class="fas fa-user-minus"></span></a>
- </ng-container>
- </td>
- </tr>
- </tbody>
- </table>
-
-</app-paginated-entities>
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { ManageUsersListComponent } from './manage-users-list.component';
-
-describe('ManageUsersListComponent', () => {
- let component: ManageUsersListComponent;
- let fixture: ComponentFixture<ManageUsersListComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ ManageUsersListComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ManageUsersListComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 {Component, OnInit, Input, OnDestroy} from '@angular/core';
-import {TranslateService} from "@ngx-translate/core";
-import {UserService} from "../../../../services/user.service";
-import {UserInfo} from "../../../../model/user-info";
-import {EntityService} from "../../../../model/entity-service";
-import {Observable, of} from "rxjs";
-import {PagedResult} from "../../../../model/paged-result";
-
-@Component({
- selector: 'app-manage-users-list',
- templateUrl: './manage-users-list.component.html',
- styleUrls: ['./manage-users-list.component.scss']
-})
-export class ManageUsersListComponent implements OnInit {
-
- @Input() heads: any;
- service : EntityService<UserInfo>;
- sortField = ["user_id"];
- sortOrder = "asc";
-
-
- constructor(private translator: TranslateService, private userService : UserService) {
- this.service = function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string) : Observable<PagedResult<UserInfo>> {
- console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
- return userService.query(searchTerm, offset, limit, orderBy, order);
- }
-
- }
-
- ngOnInit(): void {
- this.heads = {};
- // We need to wait for the translator initialization and use the init key as step in.
- this.translator.get('init').subscribe(() => {
- // Only table headings for small columns that use icons
- for (let suffix of ['validated', 'locked', 'password_change_required']) {
- this.heads[suffix] = this.translator.instant('users.attributes.' + suffix);
- }
- });
- }
-
-
- changeSortOrder(order:string) {
- if (this.sortOrder!=order) {
- this.sortOrder = order;
- }
- }
-
- private compareArrays(a1: string[], a2: string[]) {
- let i = a1.length;
- while (i--) {
- if (a1[i] !== a2[i]) return false;
- }
- return true
- }
-
- sortCheck(fieldArray:string[]) {
- return this.compareArrays(this.sortField, fieldArray);
- }
-
- isAscending() : boolean {
- return this.sortOrder == "asc";
- }
-
-
-
-
-
-
-
-
-
-}
+++ /dev/null
-<!--
- ~ 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.
- -->
-
-<ul class="nav nav-tabs">
- <li class="nav-item">
- <a class="nav-link" routerLink="/user/users/list" routerLinkActive="active" href="#">{{'users.list.head' | translate}}</a>
- </li>
- <li class="nav-item">
- <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" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a>
- </li>
-</ul>
-
-<router-outlet ></router-outlet>
\ No newline at end of file
+++ /dev/null
-/*!
- * 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.
- */
-
+++ /dev/null
-/*
- * 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 { ManageUsersComponent } from './manage-users.component';
-
-describe('ManageUsersComponent', () => {
- let component: ManageUsersComponent;
- let fixture: ComponentFixture<ManageUsersComponent>;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ ManageUsersComponent ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ManageUsersComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+++ /dev/null
-/*
- * 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 { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-manage-users',
- templateUrl: './manage-users.component.html',
- styleUrls: ['./manage-users.component.scss']
-})
-export class ManageUsersComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
-}
--- /dev/null
+import { TestBed } from '@angular/core/testing';
+
+import { RoleService } from './role.service';
+
+describe('RoleService', () => {
+ let service: RoleService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(RoleService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
--- /dev/null
+import { Injectable } from '@angular/core';
+import {ArchivaRequestService} from "@app/services/archiva-request.service";
+import {RoleTemplate} from "@app/model/role-template";
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class RoleService {
+
+ constructor(private rest: ArchivaRequestService) { }
+
+ public getTemplates() : Observable<RoleTemplate[]> {
+ return this.rest.executeRestCall("get", "redback", "roles/templates", null);
+ }
+
+}
*/
import {Injectable, OnDestroy, OnInit} from '@angular/core';
-import {ArchivaRequestService} from "./archiva-request.service";
-import {UserInfo} from '../model/user-info';
+import {ArchivaRequestService} from "@app/services/archiva-request.service";
+import {UserInfo} from '@app/model/user-info';
import {HttpErrorResponse, HttpResponse} from "@angular/common/http";
-import {ErrorResult} from "../model/error-result";
+import {ErrorResult} from "@app/model/error-result";
import {Observable, throwError} from "rxjs";
-import {Permission} from '../model/permission';
-import {PagedResult} from "../model/paged-result";
-import {User} from '../model/user';
+import {Permission} from '@app/model/permission';
+import {PagedResult} from "@app/model/paged-result";
+import {User} from '@app/model/user';
import {catchError, map} from "rxjs/operators";
+import {RoleTree} from "@app/model/role-tree";
@Injectable({
providedIn: 'root'
})
);
- // return new Observable<Permission[]>((resultObserver) => {
- // let permissionObserver = {
- // next: (x: Permission[]) => {
- // this.permissions = x;
- // this.parsePermissions(x);
- // resultObserver.next(this.permissions);
- // },
- // error: (err: HttpErrorResponse) => {
- // console.log("Error " + (JSON.stringify(err)));
- // let result = err.error as ErrorResult
- // if (result.error_messages != null) {
- // for (let msg of result.error_messages) {
- // console.debug('Observer got an error: ' + msg.error_key)
- // }
- // }
- // this.resetPermissions();
- // resultObserver.error(err);
- // },
- // complete: () => {
- // resultObserver.complete();
- // }
- // };
- // infoObserver.subscribe(permissionObserver);
- //
- // });
}
resetPermissions() {
}), map((httpResponse: HttpResponse<string>) => httpResponse.status == 200));
}
+ public userRoleTree(userid:String): Observable<RoleTree> {
+ return this.rest.executeResponseCall<RoleTree>("get", "redback","users/"+userid+"/roletree", null).pipe(
+ catchError((error: HttpErrorResponse)=>{
+ if (error.status==404) {
+ console.error("User not found: " + userid);
+ return [];
+ } else {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }
+ })
+ ).pipe(map((httpResponse:HttpResponse<RoleTree>)=>httpResponse.body))
+ }
+
}
}
},
"delete": {
+ "head":"Delete User",
"modal": {
"title": "Delete User",
"text": "Are you sure? <br/> Do you want to delete the user <strong>{user_id}</strong>?"
}
+ },
+ "roles": {
+ "head": "Edit Roles"
}
},
"search": {
"lib": [
"es2018",
"dom"
- ]
+ ],
+ "paths": {
+ "@app/*": ["src/app/*"],
+ "@app/model/*":["src/app/model/*"],
+ "@app/services/*": ["src/app/services/*"],
+ }
}
}