mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 17:47:46 +01:00
Merge pull request #8221 from jwangyangls/addGroupInhttpMode
Add user group when http auth mode
This commit is contained in:
commit
c73fa851ff
@ -434,3 +434,8 @@ export interface HttpOptionTextInterface {
|
||||
withCredentials?: boolean;
|
||||
}
|
||||
|
||||
export interface ProjectRootInterface {
|
||||
NAME: string;
|
||||
VALUE: number;
|
||||
LABEL: string;
|
||||
}
|
||||
|
@ -84,3 +84,35 @@ export const LabelColor = [
|
||||
{ 'color': '#F52F52', 'textColor': 'black' }, { 'color': '#FF5501', 'textColor': 'black' },
|
||||
{ 'color': '#F57600', 'textColor': 'black' }, { 'color': '#FFDC0B', 'textColor': 'black' },
|
||||
];
|
||||
|
||||
export const CONFIG_AUTH_MODE = {
|
||||
HTTP_AUTH: "http_auth",
|
||||
LDAP_AUTH: "ldap_auth"
|
||||
};
|
||||
export const PROJECT_ROOTS = [
|
||||
{
|
||||
NAME: "admin",
|
||||
VALUE: 1,
|
||||
LABEL: "GROUP.PROJECT_ADMIN"
|
||||
},
|
||||
{
|
||||
NAME: "master",
|
||||
VALUE: 4,
|
||||
LABEL: "GROUP.PROJECT_MASTER"
|
||||
},
|
||||
{
|
||||
NAME: "developer",
|
||||
VALUE: 2,
|
||||
LABEL: "GROUP.DEVELOPER"
|
||||
},
|
||||
{
|
||||
NAME: "guest",
|
||||
VALUE: 3,
|
||||
LABEL: "GROUP.GUEST"
|
||||
}
|
||||
];
|
||||
|
||||
export enum GroupType {
|
||||
LDAP_TYPE = 1,
|
||||
HTTP_TYPE = 2
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import { CookieService } from 'ngx-cookie';
|
||||
import { AppConfig } from './app-config';
|
||||
import { CookieKeyOfAdmiral, HarborQueryParamKey } from './shared/shared.const';
|
||||
import { maintainUrlQueryParmas } from './shared/shared.utils';
|
||||
import { HTTP_GET_OPTIONS} from '@harbor/ui';
|
||||
import { HTTP_GET_OPTIONS , CONFIG_AUTH_MODE} from '@harbor/ui';
|
||||
import { map, catchError } from "rxjs/operators";
|
||||
import { Observable, throwError as observableThrowError } from "rxjs";
|
||||
export const systemInfoEndpoint = "/api/systeminfo";
|
||||
@ -67,7 +67,10 @@ export class AppConfigService {
|
||||
}
|
||||
|
||||
public isLdapMode(): boolean {
|
||||
return this.configurations && this.configurations.auth_mode === 'ldap_auth';
|
||||
return this.configurations && this.configurations.auth_mode === CONFIG_AUTH_MODE.LDAP_AUTH;
|
||||
}
|
||||
public isHttpAuthMode(): boolean {
|
||||
return this.configurations && this.configurations.auth_mode === CONFIG_AUTH_MODE.HTTP_AUTH;
|
||||
}
|
||||
|
||||
// Return the reconstructed admiral url
|
||||
|
@ -28,7 +28,7 @@
|
||||
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
|
||||
</a>
|
||||
<a *ngIf='isLdapMode' clrVerticalNavLink routerLink="/harbor/groups" routerLinkActive="active">
|
||||
<a *ngIf='isLdapMode || isHttpAuthMode' clrVerticalNavLink routerLink="/harbor/groups" routerLinkActive="active">
|
||||
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
|
||||
</a>
|
||||
|
@ -54,6 +54,8 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
||||
|
||||
searchSub: Subscription;
|
||||
searchCloseSub: Subscription;
|
||||
isLdapMode: boolean;
|
||||
isHttpAuthMode: boolean;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -63,6 +65,11 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
||||
private appConfigService: AppConfigService) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (this.appConfigService.isLdapMode()) {
|
||||
this.isLdapMode = true;
|
||||
} else if (this.appConfigService.isHttpAuthMode()) {
|
||||
this.isHttpAuthMode = true;
|
||||
}
|
||||
this.searchSub = this.searchTrigger.searchTriggerChan$.subscribe(searchEvt => {
|
||||
if (searchEvt && searchEvt.trim() !== "") {
|
||||
this.isSearchResultsOpened = true;
|
||||
@ -70,7 +77,7 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
this.searchCloseSub = this.searchTrigger.searchCloseChan$.subscribe(close => {
|
||||
this.isSearchResultsOpened = false;
|
||||
this.isSearchResultsOpened = false;
|
||||
});
|
||||
}
|
||||
|
||||
@ -97,11 +104,6 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
||||
return account != null && account.has_admin_role;
|
||||
}
|
||||
|
||||
public get isLdapMode(): boolean {
|
||||
let appConfig = this.appConfigService.getConfig();
|
||||
return appConfig.auth_mode === 'ldap_auth';
|
||||
}
|
||||
|
||||
public get isUserExisting(): boolean {
|
||||
let account = this.session.getCurrentUser();
|
||||
return account != null;
|
||||
|
@ -1,11 +1,12 @@
|
||||
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true" [clrModalClosable]="false">
|
||||
<h3 class="modal-title" *ngIf="mode === 'create'">{{'GROUP.IMPORT_LDAP_GROUP' | translate}}</h3>
|
||||
<h3 class="modal-title" *ngIf="mode === 'create' && isLdapMode">{{'GROUP.IMPORT_LDAP_GROUP' | translate}}</h3>
|
||||
<h3 class="modal-title" *ngIf="mode === 'create' && isHttpAuthMode">{{'GROUP.IMPORT_HTTP_GROUP' | translate}}</h3>
|
||||
<h3 class="modal-title" *ngIf="mode !== 'create'">{{'GROUP.EDIT' | translate}}</h3>
|
||||
|
||||
<div class="modal-body">
|
||||
<form class="form" #groupForm="ngForm">
|
||||
<section class="form-block">
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="isLdapMode">
|
||||
<label for="ldap_group_dn" class="required">{{ 'GROUP.GROUP_DN' | translate}}</label>
|
||||
<label for="ldap_group_dn"
|
||||
aria-haspopup="true"
|
||||
@ -22,7 +23,7 @@
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="isLdapMode">
|
||||
<label for="type">{{'GROUP.TYPE' | translate}}</label>
|
||||
<label id="type">LDAP</label>
|
||||
</div>
|
||||
|
@ -1,13 +1,15 @@
|
||||
|
||||
import {finalize} from 'rxjs/operators';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { Subscription } from "rxjs";
|
||||
import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef, OnDestroy, ViewChild } from "@angular/core";
|
||||
import { NgForm } from "@angular/forms";
|
||||
import { GroupType } from "@harbor/ui";
|
||||
|
||||
import { GroupService } from "../group.service";
|
||||
import { MessageHandlerService } from "./../../shared/message-handler/message-handler.service";
|
||||
import { SessionService } from "./../../shared/session.service";
|
||||
import { UserGroup } from "./../group";
|
||||
import { AppConfigService } from "../../app-config.service";
|
||||
|
||||
@Component({
|
||||
selector: "hbr-add-group-modal",
|
||||
@ -19,7 +21,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
||||
mode = "create";
|
||||
dnTooltip = 'TOOLTIP.ITEM_REQUIRED';
|
||||
|
||||
group: UserGroup = new UserGroup();
|
||||
group: UserGroup;
|
||||
|
||||
formChangeSubscription: Subscription;
|
||||
|
||||
@ -30,25 +32,36 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Output() dataChange = new EventEmitter();
|
||||
|
||||
isLdapMode: boolean;
|
||||
isHttpAuthMode: boolean;
|
||||
constructor(
|
||||
private session: SessionService,
|
||||
private msgHandler: MessageHandlerService,
|
||||
private appConfigService: AppConfigService,
|
||||
private groupService: GroupService,
|
||||
private cdr: ChangeDetectorRef
|
||||
) {}
|
||||
) { }
|
||||
|
||||
ngOnInit() { }
|
||||
ngOnInit() {
|
||||
if (this.appConfigService.isLdapMode()) {
|
||||
this.isLdapMode = true;
|
||||
}
|
||||
if (this.appConfigService.isHttpAuthMode()) {
|
||||
this.isHttpAuthMode = true;
|
||||
}
|
||||
this.group = new UserGroup(this.isLdapMode ? GroupType.LDAP_TYPE : GroupType.HTTP_TYPE);
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy() { }
|
||||
|
||||
public get isDNInvalid(): boolean {
|
||||
let dnControl = this.groupForm.controls['ldap_group_dn'];
|
||||
return dnControl && dnControl.invalid && (dnControl.dirty || dnControl.touched);
|
||||
return dnControl && dnControl.invalid && (dnControl.dirty || dnControl.touched);
|
||||
}
|
||||
public get isNameInvalid(): boolean {
|
||||
let dnControl = this.groupForm.controls['group_name'];
|
||||
return dnControl && dnControl.invalid && (dnControl.dirty || dnControl.touched);
|
||||
return dnControl && dnControl.invalid && (dnControl.dirty || dnControl.touched);
|
||||
}
|
||||
|
||||
public get isFormValid(): boolean {
|
||||
@ -83,7 +96,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
||||
let groupCopy = Object.assign({}, this.group);
|
||||
this.groupService
|
||||
.createGroup(groupCopy).pipe(
|
||||
finalize(() => this.close()))
|
||||
finalize(() => this.close()))
|
||||
.subscribe(
|
||||
res => {
|
||||
this.msgHandler.showSuccess("GROUP.ADD_GROUP_SUCCESS");
|
||||
@ -97,7 +110,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
||||
let groupCopy = Object.assign({}, this.group);
|
||||
this.groupService
|
||||
.editGroup(groupCopy).pipe(
|
||||
finalize(() => this.close()))
|
||||
finalize(() => this.close()))
|
||||
.subscribe(
|
||||
res => {
|
||||
this.msgHandler.showSuccess("GROUP.EDIT_GROUP_SUCCESS");
|
||||
@ -108,7 +121,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
resetGroup() {
|
||||
this.group = new UserGroup();
|
||||
this.group = new UserGroup(this.isLdapMode ? GroupType.LDAP_TYPE : GroupType.HTTP_TYPE);
|
||||
this.groupForm.reset();
|
||||
}
|
||||
}
|
||||
|
@ -15,18 +15,18 @@
|
||||
<clr-icon shape="plus" size="15"></clr-icon> {{'GROUP.ADD' | translate}}</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" (click)="editGroup()" [disabled]="!canEditGroup">
|
||||
<clr-icon shape="pencil" size="15"></clr-icon> {{'GROUP.EDIT' | translate}}</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" (click)="openDeleteConfirmationDialog()" [disabled]="!canEditGroup">
|
||||
<button type="button" class="btn btn-sm btn-secondary" (click)="openDeleteConfirmationDialog()" [disabled]="!canDeleteGroup">
|
||||
<clr-icon shape="times" size="15"></clr-icon> {{'GROUP.DELETE' | translate}}</button>
|
||||
</clr-dg-action-bar>
|
||||
|
||||
<clr-dg-column>{{'GROUP.NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'GROUP.TYPE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'GROUP.DN' | translate}}</clr-dg-column>
|
||||
<clr-dg-column *ngIf="isLdapMode">{{'GROUP.DN' | translate}}</clr-dg-column>
|
||||
|
||||
<clr-dg-row *clrDgItems="let group of groups" [clrDgItem]="group">
|
||||
<clr-dg-cell>{{group.group_name}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{groupToSring(group.group_type) | translate}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{group.ldap_group_dn}}</clr-dg-cell>
|
||||
<clr-dg-cell *ngIf="isLdapMode">{{group.ldap_group_dn}}</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
<clr-dg-pagination #pagination [clrDgPageSize]="15">
|
||||
|
@ -4,7 +4,7 @@ import { flatMap, catchError } from "rxjs/operators";
|
||||
import { SessionService } from "./../shared/session.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { Component, OnInit, ViewChild, OnDestroy } from "@angular/core";
|
||||
import { operateChanges, OperateInfo, OperationService, OperationState, errorHandler as errorHandFn } from "@harbor/ui";
|
||||
import { operateChanges, OperateInfo, OperationService, OperationState, errorHandler as errorHandFn, GroupType } from "@harbor/ui";
|
||||
|
||||
import {
|
||||
ConfirmationTargets,
|
||||
@ -19,6 +19,8 @@ import { UserGroup } from "./group";
|
||||
import { GroupService } from "./group.service";
|
||||
import { MessageHandlerService } from "../shared/message-handler/message-handler.service";
|
||||
import { throwError as observableThrowError } from "rxjs";
|
||||
import { AppConfigService } from '../app-config.service';
|
||||
|
||||
@Component({
|
||||
selector: "app-group",
|
||||
templateUrl: "./group.component.html",
|
||||
@ -35,6 +37,7 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
delSub: Subscription;
|
||||
batchOps = 'idle';
|
||||
batchInfos = new Map();
|
||||
isLdapMode: boolean;
|
||||
|
||||
@ViewChild(AddGroupModalComponent) newGroupModal: AddGroupModalComponent;
|
||||
|
||||
@ -46,10 +49,14 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
private msgHandler: MessageHandlerService,
|
||||
private session: SessionService,
|
||||
private translateService: TranslateService,
|
||||
private appConfigService: AppConfigService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.loadData();
|
||||
if (this.appConfigService.isLdapMode()) {
|
||||
this.isLdapMode = true;
|
||||
}
|
||||
this.delSub = this.operateDialogService.confirmationConfirm$.subscribe(
|
||||
message => {
|
||||
if (
|
||||
@ -150,7 +157,13 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
groupToSring(type: number) {
|
||||
if (type === 1) { return 'GROUP.LDAP_TYPE'; } else { return 'UNKNOWN'; }
|
||||
if (type === GroupType.LDAP_TYPE) {
|
||||
return 'GROUP.LDAP_TYPE';
|
||||
} else if (type === GroupType.HTTP_TYPE) {
|
||||
return 'GROUP.HTTP_TYPE';
|
||||
} else {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
|
||||
doFilter(groupName: string): void {
|
||||
@ -162,6 +175,12 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
get canEditGroup(): boolean {
|
||||
return (
|
||||
this.selectedGroups.length === 1 &&
|
||||
this.session.currentUser.has_admin_role && this.isLdapMode
|
||||
);
|
||||
}
|
||||
get canDeleteGroup(): boolean {
|
||||
return (
|
||||
this.selectedGroups.length === 1 &&
|
||||
this.session.currentUser.has_admin_role
|
||||
|
@ -4,9 +4,9 @@ export class UserGroup {
|
||||
group_type: number;
|
||||
ldap_group_dn?: string;
|
||||
|
||||
constructor() {
|
||||
constructor(groupType) {
|
||||
{
|
||||
this.group_type = 1;
|
||||
this.group_type = groupType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ export class AddGroupComponent implements OnInit {
|
||||
currentTerm = '';
|
||||
|
||||
selectedRole = 1;
|
||||
group = new UserGroup();
|
||||
group = new UserGroup(1);
|
||||
selectedGroups: UserGroup[] = [];
|
||||
groups: UserGroup[] = [];
|
||||
totalCount = 0;
|
||||
@ -89,7 +89,7 @@ export class AddGroupComponent implements OnInit {
|
||||
|
||||
resetModaldata() {
|
||||
this.createGroupMode = false;
|
||||
this.group = new UserGroup();
|
||||
this.group = new UserGroup(1);
|
||||
this.selectedRole = 1;
|
||||
this.selectedGroups = [];
|
||||
this.groups = [];
|
||||
|
@ -0,0 +1,36 @@
|
||||
<clr-modal [(clrModalOpen)]="addHttpAuthOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
||||
<h3 class="modal-title">{{'GROUP.NEW_MEMBER' | translate}}</h3>
|
||||
<inline-alert class="modal-title padding-0"></inline-alert>
|
||||
<div class="modal-body">
|
||||
<label>{{ 'GROUP.NEW_USER_INFO' | translate}}</label>
|
||||
|
||||
<form #memberForm="ngForm">
|
||||
<section class="form-block">
|
||||
<div class="form-group">
|
||||
<label for="member_name" class="col-md-4 form-group-label-override required">{{'GROUP.GROUP' | translate}} {{'GROUP.NAME' | translate}}</label>
|
||||
<label for="member_name" aria-haspopup="true" role="tooltip"
|
||||
class="tooltip tooltip-validation tooltip-sm tooltip-bottom-left">
|
||||
<input type="text" id="member_name" [(ngModel)]="member_group.group_name"
|
||||
name="member_name"
|
||||
size="20"
|
||||
minlength="3"
|
||||
#memberName="ngModel"
|
||||
required autocomplete="off">
|
||||
</label>
|
||||
<span class="spinner spinner-inline" [hidden]="!checkOnGoing"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-4 form-group-label-override">{{'GROUP.ROLE' | translate}}</label>
|
||||
<div class="radio" *ngFor="let projectRoot of projectRoots">
|
||||
<input type="radio" name="member_role" id="{{'check_root_project_' + projectRoot.NAME}}" [value]="projectRoot.VALUE" [(ngModel)]="role_id">
|
||||
<label for="{{'check_root_project_' + projectRoot.NAME}}">{{ projectRoot.LABEL | translate}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline" (click)="onCancel()">{{'BUTTON.CANCEL' | translate}}</button>
|
||||
<button type="button" class="btn btn-primary" [disabled]="!isValid" (click)="onSubmit()">{{'BUTTON.OK' | translate}}</button>
|
||||
</div>
|
||||
</clr-modal>
|
@ -0,0 +1,8 @@
|
||||
.form-group-label-override {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.padding-0 {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AddHttpAuthGroupComponent } from './add-http-auth-group.component';
|
||||
|
||||
describe('AddHttpAuthGroupComponent', () => {
|
||||
let component: AddHttpAuthGroupComponent;
|
||||
let fixture: ComponentFixture<AddHttpAuthGroupComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AddHttpAuthGroupComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddHttpAuthGroupComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,120 @@
|
||||
import { finalize } from 'rxjs/operators';
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed 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,
|
||||
Input,
|
||||
EventEmitter,
|
||||
Output,
|
||||
ViewChild,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
|
||||
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { InlineAlertComponent } from '../../../shared/inline-alert/inline-alert.component';
|
||||
import { UserService } from '../../../user/user.service';
|
||||
|
||||
|
||||
import { errorHandler as errorHandFn, PROJECT_ROOTS, ProjectRootInterface } from "@harbor/ui";
|
||||
|
||||
import { MemberService } from '../member.service';
|
||||
import { UserGroup } from "./../../../group/group";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'add-http-auth-group',
|
||||
templateUrl: './add-http-auth-group.component.html',
|
||||
styleUrls: ['./add-http-auth-group.component.scss'],
|
||||
providers: [UserService]
|
||||
})
|
||||
|
||||
export class AddHttpAuthGroupComponent implements OnInit {
|
||||
projectRoots: ProjectRootInterface[];
|
||||
member_group: UserGroup = { group_name: '', group_type: 2 };
|
||||
role_id: number;
|
||||
addHttpAuthOpened: boolean;
|
||||
|
||||
memberForm: NgForm;
|
||||
|
||||
staticBackdrop: boolean = true;
|
||||
closable: boolean = false;
|
||||
|
||||
@ViewChild('memberForm')
|
||||
currentForm: NgForm;
|
||||
|
||||
@ViewChild(InlineAlertComponent)
|
||||
inlineAlert: InlineAlertComponent;
|
||||
|
||||
@Input() projectId: number;
|
||||
@Output() added = new EventEmitter<boolean>();
|
||||
|
||||
checkOnGoing: boolean = false;
|
||||
|
||||
constructor(private memberService: MemberService,
|
||||
private translateService: TranslateService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.projectRoots = PROJECT_ROOTS;
|
||||
}
|
||||
|
||||
createGroupAsMember() {
|
||||
this.checkOnGoing = true;
|
||||
this.memberService.addGroupMember(this.projectId, this.member_group, this.role_id)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.checkOnGoing = false;
|
||||
}
|
||||
))
|
||||
.subscribe(
|
||||
res => {
|
||||
this.role_id = null;
|
||||
this.addHttpAuthOpened = false;
|
||||
this.added.emit(true);
|
||||
},
|
||||
err => {
|
||||
let errorMessageKey: string = errorHandFn(err);
|
||||
this.translateService
|
||||
.get(errorMessageKey)
|
||||
.subscribe(errorMessage => this.inlineAlert.showInlineError(errorMessage));
|
||||
this.added.emit(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
onSubmit(): void {
|
||||
this.createGroupAsMember();
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.role_id = null;
|
||||
this.addHttpAuthOpened = false;
|
||||
}
|
||||
|
||||
|
||||
openAddMemberModal(): void {
|
||||
this.currentForm.reset();
|
||||
this.addHttpAuthOpened = true;
|
||||
this.role_id = 1;
|
||||
}
|
||||
|
||||
|
||||
public get isValid(): boolean {
|
||||
return this.currentForm &&
|
||||
this.currentForm.valid &&
|
||||
!this.checkOnGoing;
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
<button class="btn btn-sm btn-secondary" (click)="openAddMemberModal()" [disabled]="!hasCreateMemberPermission">
|
||||
<span><clr-icon shape="plus" size="16"></clr-icon> {{'MEMBER.USER' | translate }}</span>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-secondary" (click)="openAddGroupModal()" [disabled]="!hasCreateMemberPermission || !isLdapMode">
|
||||
<button class="btn btn-sm btn-secondary" (click)="openAddGroupModal()" [disabled]="!hasCreateMemberPermission || !(isLdapMode || isHttpAuthMode)">
|
||||
<span><clr-icon shape="plus" size="16"></clr-icon> {{'MEMBER.LDAP_GROUP' | translate}}</span>
|
||||
</button>
|
||||
<clr-dropdown id='member-action' [clrCloseMenuOnItemClick]="false" class="btn btn-sm btn-link" clrDropdownTrigger>
|
||||
@ -53,4 +53,5 @@
|
||||
</div>
|
||||
<add-member [projectId]="projectId" [memberList]="members" (added)="addedMember($event)"></add-member>
|
||||
<add-group [projectId]="projectId" [memberList]="members" (added)="addedGroup($event)"></add-group>
|
||||
<add-http-auth-group [projectId]="projectId" (added)="addedGroup($event)"></add-http-auth-group>
|
||||
</div>
|
@ -17,8 +17,10 @@ import { Component, OnInit, ViewChild, OnDestroy, ChangeDetectionStrategy, Chang
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { Subscription, forkJoin, Observable } from "rxjs";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { operateChanges, OperateInfo, OperationService, OperationState, UserPermissionService, USERSTATICPERMISSION, ErrorHandler
|
||||
, errorHandler as errorHandFn } from "@harbor/ui";
|
||||
import {
|
||||
operateChanges, OperateInfo, OperationService, OperationState, UserPermissionService, USERSTATICPERMISSION, ErrorHandler
|
||||
, errorHandler as errorHandFn
|
||||
} from "@harbor/ui";
|
||||
|
||||
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
||||
import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from "../../shared/shared.const";
|
||||
@ -30,6 +32,7 @@ import { Project } from "../../project/project";
|
||||
import { Member } from "./member";
|
||||
import { SessionUser } from "../../shared/session-user";
|
||||
import { AddGroupComponent } from './add-group/add-group.component';
|
||||
import { AddHttpAuthGroupComponent } from './add-http-auth-group/add-http-auth-group.component';
|
||||
import { MemberService } from "./member.service";
|
||||
import { AddMemberComponent } from "./add-member/add-member.component";
|
||||
import { AppConfigService } from "../../app-config.service";
|
||||
@ -56,16 +59,18 @@ export class MemberComponent implements OnInit, OnDestroy {
|
||||
isDelete = false;
|
||||
isChangeRole = false;
|
||||
loading = false;
|
||||
isLdapMode: boolean = false;
|
||||
|
||||
isChangingRole = false;
|
||||
batchChangeRoleInfos = {};
|
||||
|
||||
isLdapMode: boolean;
|
||||
isHttpAuthMode: boolean;
|
||||
@ViewChild(AddMemberComponent)
|
||||
addMemberComponent: AddMemberComponent;
|
||||
|
||||
@ViewChild(AddGroupComponent)
|
||||
addGroupComponent: AddGroupComponent;
|
||||
@ViewChild(AddHttpAuthGroupComponent)
|
||||
addHttpAuthGroupComponent: AddHttpAuthGroupComponent;
|
||||
hasCreateMemberPermission: boolean;
|
||||
hasUpdateMemberPermission: boolean;
|
||||
hasDeleteMemberPermission: boolean;
|
||||
@ -108,13 +113,15 @@ export class MemberComponent implements OnInit, OnDestroy {
|
||||
// Get current user from registered resolver.
|
||||
this.currentUser = this.session.getCurrentUser();
|
||||
this.retrieve(this.projectId, "");
|
||||
// get member permission rule
|
||||
this.getMemberPermissionRule(this.projectId);
|
||||
if (this.appConfigService.isLdapMode()) {
|
||||
this.isLdapMode = true;
|
||||
}
|
||||
// get member permission rule
|
||||
this.getMemberPermissionRule(this.projectId);
|
||||
if (this.appConfigService.isHttpAuthMode()) {
|
||||
this.isHttpAuthMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
doSearch(searchMember: string) {
|
||||
this.searchMember = searchMember;
|
||||
this.retrieve(this.projectId, this.searchMember);
|
||||
@ -172,7 +179,11 @@ export class MemberComponent implements OnInit, OnDestroy {
|
||||
|
||||
// Add group
|
||||
openAddGroupModal() {
|
||||
this.addGroupComponent.open();
|
||||
if (this.isLdapMode) {
|
||||
this.addGroupComponent.open();
|
||||
} else {
|
||||
this.addHttpAuthGroupComponent.openAddMemberModal();
|
||||
}
|
||||
}
|
||||
addedGroup(result: boolean) {
|
||||
this.searchMember = "";
|
||||
@ -188,10 +199,10 @@ export class MemberComponent implements OnInit, OnDestroy {
|
||||
return this.memberService
|
||||
.changeMemberRole(projectId, member.id, roleId)
|
||||
.pipe(map(() => this.batchChangeRoleInfos[member.id] = 'done')
|
||||
, catchError(error => {
|
||||
this.messageHandlerService.handleError(error + ": " + member.entity_name);
|
||||
return observableThrowError(error);
|
||||
}));
|
||||
, catchError(error => {
|
||||
this.messageHandlerService.handleError(error + ": " + member.entity_name);
|
||||
return observableThrowError(error);
|
||||
}));
|
||||
};
|
||||
|
||||
// Preparation for members role change
|
||||
|
@ -38,6 +38,7 @@ import { ProjectLabelComponent } from "../project/project-label/project-label.co
|
||||
import { HelmChartModule } from './helm-chart/helm-chart.module';
|
||||
import { RobotAccountComponent } from './robot-account/robot-account.component';
|
||||
import { AddRobotComponent } from './robot-account/add-robot/add-robot.component';
|
||||
import { AddHttpAuthGroupComponent } from './member/add-http-auth-group/add-http-auth-group.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -59,7 +60,8 @@ import { AddRobotComponent } from './robot-account/add-robot/add-robot.component
|
||||
ProjectLabelComponent,
|
||||
AddGroupComponent,
|
||||
RobotAccountComponent,
|
||||
AddRobotComponent
|
||||
AddRobotComponent,
|
||||
AddHttpAuthGroupComponent
|
||||
],
|
||||
exports: [ProjectComponent, ListProjectComponent],
|
||||
providers: [ProjectRoutingResolver, MemberService, RobotService]
|
||||
|
@ -328,6 +328,7 @@
|
||||
"GROUP": "Group",
|
||||
"GROUPS": "Groups",
|
||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||
"ADD": "New Group",
|
||||
"EDIT": "Edit",
|
||||
"DELETE": "Delete",
|
||||
@ -340,8 +341,17 @@
|
||||
"ADD_GROUP_SUCCESS": "Add group success",
|
||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||
"LDAP_TYPE": "LDAP",
|
||||
"HTTP_TYPE": "HTTP",
|
||||
"OF": "of",
|
||||
"ITEMS": "items"
|
||||
"ITEMS": "items",
|
||||
"NEW_MEMBER": "New Group Member",
|
||||
"NEW_USER_INFO": "Add a group to be a member of this project with specified role",
|
||||
"ROLE": "Role",
|
||||
"SYS_ADMIN": "System Admin",
|
||||
"PROJECT_ADMIN": "Project Admin",
|
||||
"PROJECT_MASTER": "Master",
|
||||
"DEVELOPER": "Developer",
|
||||
"GUEST": "Guest"
|
||||
},
|
||||
"AUDIT_LOG": {
|
||||
"USERNAME": "Username",
|
||||
|
@ -329,6 +329,7 @@
|
||||
"GROUP": "Group",
|
||||
"GROUPS": "Groups",
|
||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||
"ADD": "Add",
|
||||
"EDIT": "Edit",
|
||||
"DELETE": "Delete",
|
||||
@ -340,8 +341,17 @@
|
||||
"ADD_GROUP_SUCCESS": "Add group success",
|
||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||
"LDAP_TYPE": "LDAP",
|
||||
"HTTP_TYPE": "HTTP",
|
||||
"OF": "of",
|
||||
"ITEMS": "items"
|
||||
"ITEMS": "items",
|
||||
"NEW_MEMBER": "New Group Member",
|
||||
"NEW_USER_INFO": "Add a group to be a member of this project with specified role",
|
||||
"ROLE": "Role",
|
||||
"SYS_ADMIN": "System Admin",
|
||||
"PROJECT_ADMIN": "Project Admin",
|
||||
"PROJECT_MASTER": "Master",
|
||||
"DEVELOPER": "Developer",
|
||||
"GUEST": "Guest"
|
||||
},
|
||||
"AUDIT_LOG": {
|
||||
"USERNAME": "Nombre de usuario",
|
||||
|
@ -321,6 +321,7 @@
|
||||
"Group": "Group",
|
||||
"GROUPS": "Groups",
|
||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||
"ADD": "Add",
|
||||
"EDIT": "Edit",
|
||||
"DELETE": "Delete",
|
||||
@ -333,8 +334,17 @@
|
||||
"ADD_GROUP_SUCCESS": "Add group success",
|
||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||
"LDAP_TYPE": "LDAP",
|
||||
"HTTP_TYPE": "HTTP",
|
||||
"OF": "of",
|
||||
"ITEMS": "items"
|
||||
"ITEMS": "items",
|
||||
"NEW_MEMBER": "New Group Member",
|
||||
"NEW_USER_INFO": "Add a group to be a member of this project with specified role",
|
||||
"ROLE": "Role",
|
||||
"SYS_ADMIN": "System Admin",
|
||||
"PROJECT_ADMIN": "Project Admin",
|
||||
"PROJECT_MASTER": "Master",
|
||||
"DEVELOPER": "Developer",
|
||||
"GUEST": "Guest"
|
||||
},
|
||||
"AUDIT_LOG": {
|
||||
"USERNAME": "Nom d'utilisateur",
|
||||
|
@ -326,6 +326,7 @@
|
||||
"GROUP": "Grupo",
|
||||
"GROUPS": "Grupos",
|
||||
"IMPORT_LDAP_GROUP": "Importar grupo do LDAP",
|
||||
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||
"ADD": "Novo Grupo",
|
||||
"EDIT": "Editar",
|
||||
"DELETE": "Remover",
|
||||
@ -338,8 +339,17 @@
|
||||
"ADD_GROUP_SUCCESS": "Grupo adicionado com sucesso",
|
||||
"EDIT_GROUP_SUCCESS": "Grupo editado com sucesso",
|
||||
"LDAP_TYPE": "LDAP",
|
||||
"HTTP_TYPE": "HTTP",
|
||||
"OF": "de",
|
||||
"ITEMS": "itens"
|
||||
"ITEMS": "itens",
|
||||
"NEW_MEMBER": "New Group Member",
|
||||
"NEW_USER_INFO": "Add a group to be a member of this project with specified role",
|
||||
"ROLE": "Role",
|
||||
"SYS_ADMIN": "System Admin",
|
||||
"PROJECT_ADMIN": "Project Admin",
|
||||
"PROJECT_MASTER": "Master",
|
||||
"DEVELOPER": "Developer",
|
||||
"GUEST": "Guest"
|
||||
},
|
||||
"AUDIT_LOG": {
|
||||
"USERNAME": "Nome do usuário",
|
||||
|
@ -327,6 +327,7 @@
|
||||
"GROUP": "组",
|
||||
"GROUPS": "组",
|
||||
"IMPORT_LDAP_GROUP": "导入LDAP组",
|
||||
"IMPORT_HTTP_GROUP": "新建HTTP组",
|
||||
"ADD": "新增",
|
||||
"EDIT": "编辑",
|
||||
"DELETE": "删除",
|
||||
@ -339,8 +340,17 @@
|
||||
"ADD_GROUP_SUCCESS": "添加组成功",
|
||||
"EDIT_GROUP_SUCCESS": "修改组成功",
|
||||
"LDAP_TYPE": "LDAP",
|
||||
"HTTP_TYPE": "HTTP",
|
||||
"OF": "共计",
|
||||
"ITEMS": "条记录"
|
||||
"ITEMS": "条记录",
|
||||
"NEW_MEMBER": "新建组成员",
|
||||
"NEW_USER_INFO": "添加一个组作为具有指定角色的此项目的成员",
|
||||
"ROLE": "权限",
|
||||
"SYS_ADMIN": "系统管理员",
|
||||
"PROJECT_ADMIN": "项目管理员",
|
||||
"PROJECT_MASTER": "维护人员",
|
||||
"DEVELOPER": "开发者",
|
||||
"GUEST": "访客"
|
||||
},
|
||||
"AUDIT_LOG": {
|
||||
"USERNAME": "用户名",
|
||||
|
Loading…
Reference in New Issue
Block a user