mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 18:55:18 +01:00
Add user group when http auth mode
add the pages in project and system Signed-off-by: Yogi_Wang <yawang@vmware.com>
This commit is contained in:
parent
8fc693d843
commit
c57087574a
@ -434,3 +434,8 @@ export interface HttpOptionTextInterface {
|
|||||||
withCredentials?: boolean;
|
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': '#F52F52', 'textColor': 'black' }, { 'color': '#FF5501', 'textColor': 'black' },
|
||||||
{ 'color': '#F57600', 'textColor': 'black' }, { 'color': '#FFDC0B', '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 { AppConfig } from './app-config';
|
||||||
import { CookieKeyOfAdmiral, HarborQueryParamKey } from './shared/shared.const';
|
import { CookieKeyOfAdmiral, HarborQueryParamKey } from './shared/shared.const';
|
||||||
import { maintainUrlQueryParmas } from './shared/shared.utils';
|
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 { map, catchError } from "rxjs/operators";
|
||||||
import { Observable, throwError as observableThrowError } from "rxjs";
|
import { Observable, throwError as observableThrowError } from "rxjs";
|
||||||
export const systemInfoEndpoint = "/api/systeminfo";
|
export const systemInfoEndpoint = "/api/systeminfo";
|
||||||
@ -67,7 +67,10 @@ export class AppConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isLdapMode(): boolean {
|
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
|
// Return the reconstructed admiral url
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
|
||||||
</a>
|
</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>
|
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -54,6 +54,8 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
searchSub: Subscription;
|
searchSub: Subscription;
|
||||||
searchCloseSub: Subscription;
|
searchCloseSub: Subscription;
|
||||||
|
isLdapMode: boolean;
|
||||||
|
isHttpAuthMode: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -63,6 +65,11 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
|||||||
private appConfigService: AppConfigService) { }
|
private appConfigService: AppConfigService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
if (this.appConfigService.isLdapMode()) {
|
||||||
|
this.isLdapMode = true;
|
||||||
|
} else if (this.appConfigService.isHttpAuthMode()) {
|
||||||
|
this.isHttpAuthMode = true;
|
||||||
|
}
|
||||||
this.searchSub = this.searchTrigger.searchTriggerChan$.subscribe(searchEvt => {
|
this.searchSub = this.searchTrigger.searchTriggerChan$.subscribe(searchEvt => {
|
||||||
if (searchEvt && searchEvt.trim() !== "") {
|
if (searchEvt && searchEvt.trim() !== "") {
|
||||||
this.isSearchResultsOpened = true;
|
this.isSearchResultsOpened = true;
|
||||||
@ -70,7 +77,7 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.searchCloseSub = this.searchTrigger.searchCloseChan$.subscribe(close => {
|
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;
|
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 {
|
public get isUserExisting(): boolean {
|
||||||
let account = this.session.getCurrentUser();
|
let account = this.session.getCurrentUser();
|
||||||
return account != null;
|
return account != null;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true" [clrModalClosable]="false">
|
<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>
|
<h3 class="modal-title" *ngIf="mode !== 'create'">{{'GROUP.EDIT' | translate}}</h3>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form class="form" #groupForm="ngForm">
|
<form class="form" #groupForm="ngForm">
|
||||||
<section class="form-block">
|
<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" class="required">{{ 'GROUP.GROUP_DN' | translate}}</label>
|
||||||
<label for="ldap_group_dn"
|
<label for="ldap_group_dn"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
@ -22,7 +23,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group" *ngIf="isLdapMode">
|
||||||
<label for="type">{{'GROUP.TYPE' | translate}}</label>
|
<label for="type">{{'GROUP.TYPE' | translate}}</label>
|
||||||
<label id="type">LDAP</label>
|
<label id="type">LDAP</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
|
||||||
import {finalize} from 'rxjs/operators';
|
import { finalize } from 'rxjs/operators';
|
||||||
import { Subscription } from "rxjs";
|
import { Subscription } from "rxjs";
|
||||||
import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef, OnDestroy, ViewChild } from "@angular/core";
|
import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef, OnDestroy, ViewChild } from "@angular/core";
|
||||||
import { NgForm } from "@angular/forms";
|
import { NgForm } from "@angular/forms";
|
||||||
|
import { GroupType } from "@harbor/ui";
|
||||||
|
|
||||||
import { GroupService } from "../group.service";
|
import { GroupService } from "../group.service";
|
||||||
import { MessageHandlerService } from "./../../shared/message-handler/message-handler.service";
|
import { MessageHandlerService } from "./../../shared/message-handler/message-handler.service";
|
||||||
import { SessionService } from "./../../shared/session.service";
|
import { SessionService } from "./../../shared/session.service";
|
||||||
import { UserGroup } from "./../group";
|
import { UserGroup } from "./../group";
|
||||||
|
import { AppConfigService } from "../../app-config.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-add-group-modal",
|
selector: "hbr-add-group-modal",
|
||||||
@ -19,7 +21,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
|||||||
mode = "create";
|
mode = "create";
|
||||||
dnTooltip = 'TOOLTIP.ITEM_REQUIRED';
|
dnTooltip = 'TOOLTIP.ITEM_REQUIRED';
|
||||||
|
|
||||||
group: UserGroup = new UserGroup();
|
group: UserGroup;
|
||||||
|
|
||||||
formChangeSubscription: Subscription;
|
formChangeSubscription: Subscription;
|
||||||
|
|
||||||
@ -30,25 +32,36 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
@Output() dataChange = new EventEmitter();
|
@Output() dataChange = new EventEmitter();
|
||||||
|
|
||||||
|
isLdapMode: boolean;
|
||||||
|
isHttpAuthMode: boolean;
|
||||||
constructor(
|
constructor(
|
||||||
private session: SessionService,
|
private session: SessionService,
|
||||||
private msgHandler: MessageHandlerService,
|
private msgHandler: MessageHandlerService,
|
||||||
|
private appConfigService: AppConfigService,
|
||||||
private groupService: GroupService,
|
private groupService: GroupService,
|
||||||
private cdr: ChangeDetectorRef
|
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() { }
|
ngOnDestroy() { }
|
||||||
|
|
||||||
public get isDNInvalid(): boolean {
|
public get isDNInvalid(): boolean {
|
||||||
let dnControl = this.groupForm.controls['ldap_group_dn'];
|
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 {
|
public get isNameInvalid(): boolean {
|
||||||
let dnControl = this.groupForm.controls['group_name'];
|
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 {
|
public get isFormValid(): boolean {
|
||||||
@ -83,7 +96,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
|||||||
let groupCopy = Object.assign({}, this.group);
|
let groupCopy = Object.assign({}, this.group);
|
||||||
this.groupService
|
this.groupService
|
||||||
.createGroup(groupCopy).pipe(
|
.createGroup(groupCopy).pipe(
|
||||||
finalize(() => this.close()))
|
finalize(() => this.close()))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.msgHandler.showSuccess("GROUP.ADD_GROUP_SUCCESS");
|
this.msgHandler.showSuccess("GROUP.ADD_GROUP_SUCCESS");
|
||||||
@ -97,7 +110,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
|||||||
let groupCopy = Object.assign({}, this.group);
|
let groupCopy = Object.assign({}, this.group);
|
||||||
this.groupService
|
this.groupService
|
||||||
.editGroup(groupCopy).pipe(
|
.editGroup(groupCopy).pipe(
|
||||||
finalize(() => this.close()))
|
finalize(() => this.close()))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.msgHandler.showSuccess("GROUP.EDIT_GROUP_SUCCESS");
|
this.msgHandler.showSuccess("GROUP.EDIT_GROUP_SUCCESS");
|
||||||
@ -108,7 +121,7 @@ export class AddGroupModalComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetGroup() {
|
resetGroup() {
|
||||||
this.group = new UserGroup();
|
this.group = new UserGroup(this.isLdapMode ? GroupType.LDAP_TYPE : GroupType.HTTP_TYPE);
|
||||||
this.groupForm.reset();
|
this.groupForm.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,18 @@
|
|||||||
<clr-icon shape="plus" size="15"></clr-icon> {{'GROUP.ADD' | translate}}</button>
|
<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">
|
<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>
|
<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-icon shape="times" size="15"></clr-icon> {{'GROUP.DELETE' | translate}}</button>
|
||||||
</clr-dg-action-bar>
|
</clr-dg-action-bar>
|
||||||
|
|
||||||
<clr-dg-column>{{'GROUP.NAME' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'GROUP.NAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'GROUP.TYPE' | 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-row *clrDgItems="let group of groups" [clrDgItem]="group">
|
||||||
<clr-dg-cell>{{group.group_name}}</clr-dg-cell>
|
<clr-dg-cell>{{group.group_name}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{groupToSring(group.group_type) | translate}}</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-row>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
<clr-dg-pagination #pagination [clrDgPageSize]="15">
|
<clr-dg-pagination #pagination [clrDgPageSize]="15">
|
||||||
|
@ -4,7 +4,7 @@ import { flatMap, catchError } from "rxjs/operators";
|
|||||||
import { SessionService } from "./../shared/session.service";
|
import { SessionService } from "./../shared/session.service";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
import { Component, OnInit, ViewChild, OnDestroy } from "@angular/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 {
|
import {
|
||||||
ConfirmationTargets,
|
ConfirmationTargets,
|
||||||
@ -19,6 +19,8 @@ import { UserGroup } from "./group";
|
|||||||
import { GroupService } from "./group.service";
|
import { GroupService } from "./group.service";
|
||||||
import { MessageHandlerService } from "../shared/message-handler/message-handler.service";
|
import { MessageHandlerService } from "../shared/message-handler/message-handler.service";
|
||||||
import { throwError as observableThrowError } from "rxjs";
|
import { throwError as observableThrowError } from "rxjs";
|
||||||
|
import { AppConfigService } from '../app-config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-group",
|
selector: "app-group",
|
||||||
templateUrl: "./group.component.html",
|
templateUrl: "./group.component.html",
|
||||||
@ -35,6 +37,7 @@ export class GroupComponent implements OnInit, OnDestroy {
|
|||||||
delSub: Subscription;
|
delSub: Subscription;
|
||||||
batchOps = 'idle';
|
batchOps = 'idle';
|
||||||
batchInfos = new Map();
|
batchInfos = new Map();
|
||||||
|
isLdapMode: boolean;
|
||||||
|
|
||||||
@ViewChild(AddGroupModalComponent) newGroupModal: AddGroupModalComponent;
|
@ViewChild(AddGroupModalComponent) newGroupModal: AddGroupModalComponent;
|
||||||
|
|
||||||
@ -46,10 +49,14 @@ export class GroupComponent implements OnInit, OnDestroy {
|
|||||||
private msgHandler: MessageHandlerService,
|
private msgHandler: MessageHandlerService,
|
||||||
private session: SessionService,
|
private session: SessionService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
|
private appConfigService: AppConfigService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loadData();
|
this.loadData();
|
||||||
|
if (this.appConfigService.isLdapMode()) {
|
||||||
|
this.isLdapMode = true;
|
||||||
|
}
|
||||||
this.delSub = this.operateDialogService.confirmationConfirm$.subscribe(
|
this.delSub = this.operateDialogService.confirmationConfirm$.subscribe(
|
||||||
message => {
|
message => {
|
||||||
if (
|
if (
|
||||||
@ -150,7 +157,13 @@ export class GroupComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
groupToSring(type: number) {
|
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 {
|
doFilter(groupName: string): void {
|
||||||
@ -162,6 +175,12 @@ export class GroupComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get canEditGroup(): boolean {
|
get canEditGroup(): boolean {
|
||||||
|
return (
|
||||||
|
this.selectedGroups.length === 1 &&
|
||||||
|
this.session.currentUser.has_admin_role && this.isLdapMode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
get canDeleteGroup(): boolean {
|
||||||
return (
|
return (
|
||||||
this.selectedGroups.length === 1 &&
|
this.selectedGroups.length === 1 &&
|
||||||
this.session.currentUser.has_admin_role
|
this.session.currentUser.has_admin_role
|
||||||
|
@ -4,9 +4,9 @@ export class UserGroup {
|
|||||||
group_type: number;
|
group_type: number;
|
||||||
ldap_group_dn?: string;
|
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 = '';
|
currentTerm = '';
|
||||||
|
|
||||||
selectedRole = 1;
|
selectedRole = 1;
|
||||||
group = new UserGroup();
|
group = new UserGroup(1);
|
||||||
selectedGroups: UserGroup[] = [];
|
selectedGroups: UserGroup[] = [];
|
||||||
groups: UserGroup[] = [];
|
groups: UserGroup[] = [];
|
||||||
totalCount = 0;
|
totalCount = 0;
|
||||||
@ -89,7 +89,7 @@ export class AddGroupComponent implements OnInit {
|
|||||||
|
|
||||||
resetModaldata() {
|
resetModaldata() {
|
||||||
this.createGroupMode = false;
|
this.createGroupMode = false;
|
||||||
this.group = new UserGroup();
|
this.group = new UserGroup(1);
|
||||||
this.selectedRole = 1;
|
this.selectedRole = 1;
|
||||||
this.selectedGroups = [];
|
this.selectedGroups = [];
|
||||||
this.groups = [];
|
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">
|
<button class="btn btn-sm btn-secondary" (click)="openAddMemberModal()" [disabled]="!hasCreateMemberPermission">
|
||||||
<span><clr-icon shape="plus" size="16"></clr-icon> {{'MEMBER.USER' | translate }}</span>
|
<span><clr-icon shape="plus" size="16"></clr-icon> {{'MEMBER.USER' | translate }}</span>
|
||||||
</button>
|
</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>
|
<span><clr-icon shape="plus" size="16"></clr-icon> {{'MEMBER.LDAP_GROUP' | translate}}</span>
|
||||||
</button>
|
</button>
|
||||||
<clr-dropdown id='member-action' [clrCloseMenuOnItemClick]="false" class="btn btn-sm btn-link" clrDropdownTrigger>
|
<clr-dropdown id='member-action' [clrCloseMenuOnItemClick]="false" class="btn btn-sm btn-link" clrDropdownTrigger>
|
||||||
@ -53,4 +53,5 @@
|
|||||||
</div>
|
</div>
|
||||||
<add-member [projectId]="projectId" [memberList]="members" (added)="addedMember($event)"></add-member>
|
<add-member [projectId]="projectId" [memberList]="members" (added)="addedMember($event)"></add-member>
|
||||||
<add-group [projectId]="projectId" [memberList]="members" (added)="addedGroup($event)"></add-group>
|
<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>
|
</div>
|
@ -17,8 +17,10 @@ import { Component, OnInit, ViewChild, OnDestroy, ChangeDetectionStrategy, Chang
|
|||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { Subscription, forkJoin, Observable } from "rxjs";
|
import { Subscription, forkJoin, Observable } from "rxjs";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
import { operateChanges, OperateInfo, OperationService, OperationState, UserPermissionService, USERSTATICPERMISSION, ErrorHandler
|
import {
|
||||||
, errorHandler as errorHandFn } from "@harbor/ui";
|
operateChanges, OperateInfo, OperationService, OperationState, UserPermissionService, USERSTATICPERMISSION, ErrorHandler
|
||||||
|
, errorHandler as errorHandFn
|
||||||
|
} from "@harbor/ui";
|
||||||
|
|
||||||
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
||||||
import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from "../../shared/shared.const";
|
import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from "../../shared/shared.const";
|
||||||
@ -30,6 +32,7 @@ import { Project } from "../../project/project";
|
|||||||
import { Member } from "./member";
|
import { Member } from "./member";
|
||||||
import { SessionUser } from "../../shared/session-user";
|
import { SessionUser } from "../../shared/session-user";
|
||||||
import { AddGroupComponent } from './add-group/add-group.component';
|
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 { MemberService } from "./member.service";
|
||||||
import { AddMemberComponent } from "./add-member/add-member.component";
|
import { AddMemberComponent } from "./add-member/add-member.component";
|
||||||
import { AppConfigService } from "../../app-config.service";
|
import { AppConfigService } from "../../app-config.service";
|
||||||
@ -56,16 +59,18 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
isDelete = false;
|
isDelete = false;
|
||||||
isChangeRole = false;
|
isChangeRole = false;
|
||||||
loading = false;
|
loading = false;
|
||||||
isLdapMode: boolean = false;
|
|
||||||
|
|
||||||
isChangingRole = false;
|
isChangingRole = false;
|
||||||
batchChangeRoleInfos = {};
|
batchChangeRoleInfos = {};
|
||||||
|
isLdapMode: boolean;
|
||||||
|
isHttpAuthMode: boolean;
|
||||||
@ViewChild(AddMemberComponent)
|
@ViewChild(AddMemberComponent)
|
||||||
addMemberComponent: AddMemberComponent;
|
addMemberComponent: AddMemberComponent;
|
||||||
|
|
||||||
@ViewChild(AddGroupComponent)
|
@ViewChild(AddGroupComponent)
|
||||||
addGroupComponent: AddGroupComponent;
|
addGroupComponent: AddGroupComponent;
|
||||||
|
@ViewChild(AddHttpAuthGroupComponent)
|
||||||
|
addHttpAuthGroupComponent: AddHttpAuthGroupComponent;
|
||||||
hasCreateMemberPermission: boolean;
|
hasCreateMemberPermission: boolean;
|
||||||
hasUpdateMemberPermission: boolean;
|
hasUpdateMemberPermission: boolean;
|
||||||
hasDeleteMemberPermission: boolean;
|
hasDeleteMemberPermission: boolean;
|
||||||
@ -108,13 +113,15 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
// Get current user from registered resolver.
|
// Get current user from registered resolver.
|
||||||
this.currentUser = this.session.getCurrentUser();
|
this.currentUser = this.session.getCurrentUser();
|
||||||
this.retrieve(this.projectId, "");
|
this.retrieve(this.projectId, "");
|
||||||
|
// get member permission rule
|
||||||
|
this.getMemberPermissionRule(this.projectId);
|
||||||
if (this.appConfigService.isLdapMode()) {
|
if (this.appConfigService.isLdapMode()) {
|
||||||
this.isLdapMode = true;
|
this.isLdapMode = true;
|
||||||
}
|
}
|
||||||
// get member permission rule
|
if (this.appConfigService.isHttpAuthMode()) {
|
||||||
this.getMemberPermissionRule(this.projectId);
|
this.isHttpAuthMode = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doSearch(searchMember: string) {
|
doSearch(searchMember: string) {
|
||||||
this.searchMember = searchMember;
|
this.searchMember = searchMember;
|
||||||
this.retrieve(this.projectId, this.searchMember);
|
this.retrieve(this.projectId, this.searchMember);
|
||||||
@ -172,7 +179,11 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
// Add group
|
// Add group
|
||||||
openAddGroupModal() {
|
openAddGroupModal() {
|
||||||
this.addGroupComponent.open();
|
if (this.isLdapMode) {
|
||||||
|
this.addGroupComponent.open();
|
||||||
|
} else {
|
||||||
|
this.addHttpAuthGroupComponent.openAddMemberModal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addedGroup(result: boolean) {
|
addedGroup(result: boolean) {
|
||||||
this.searchMember = "";
|
this.searchMember = "";
|
||||||
@ -188,10 +199,10 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
return this.memberService
|
return this.memberService
|
||||||
.changeMemberRole(projectId, member.id, roleId)
|
.changeMemberRole(projectId, member.id, roleId)
|
||||||
.pipe(map(() => this.batchChangeRoleInfos[member.id] = 'done')
|
.pipe(map(() => this.batchChangeRoleInfos[member.id] = 'done')
|
||||||
, catchError(error => {
|
, catchError(error => {
|
||||||
this.messageHandlerService.handleError(error + ": " + member.entity_name);
|
this.messageHandlerService.handleError(error + ": " + member.entity_name);
|
||||||
return observableThrowError(error);
|
return observableThrowError(error);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Preparation for members role change
|
// 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 { HelmChartModule } from './helm-chart/helm-chart.module';
|
||||||
import { RobotAccountComponent } from './robot-account/robot-account.component';
|
import { RobotAccountComponent } from './robot-account/robot-account.component';
|
||||||
import { AddRobotComponent } from './robot-account/add-robot/add-robot.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({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -59,7 +60,8 @@ import { AddRobotComponent } from './robot-account/add-robot/add-robot.component
|
|||||||
ProjectLabelComponent,
|
ProjectLabelComponent,
|
||||||
AddGroupComponent,
|
AddGroupComponent,
|
||||||
RobotAccountComponent,
|
RobotAccountComponent,
|
||||||
AddRobotComponent
|
AddRobotComponent,
|
||||||
|
AddHttpAuthGroupComponent
|
||||||
],
|
],
|
||||||
exports: [ProjectComponent, ListProjectComponent],
|
exports: [ProjectComponent, ListProjectComponent],
|
||||||
providers: [ProjectRoutingResolver, MemberService, RobotService]
|
providers: [ProjectRoutingResolver, MemberService, RobotService]
|
||||||
|
@ -328,6 +328,7 @@
|
|||||||
"GROUP": "Group",
|
"GROUP": "Group",
|
||||||
"GROUPS": "Groups",
|
"GROUPS": "Groups",
|
||||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||||
|
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||||
"ADD": "New Group",
|
"ADD": "New Group",
|
||||||
"EDIT": "Edit",
|
"EDIT": "Edit",
|
||||||
"DELETE": "Delete",
|
"DELETE": "Delete",
|
||||||
@ -340,8 +341,17 @@
|
|||||||
"ADD_GROUP_SUCCESS": "Add group success",
|
"ADD_GROUP_SUCCESS": "Add group success",
|
||||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||||
"LDAP_TYPE": "LDAP",
|
"LDAP_TYPE": "LDAP",
|
||||||
|
"HTTP_TYPE": "HTTP",
|
||||||
"OF": "of",
|
"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": {
|
"AUDIT_LOG": {
|
||||||
"USERNAME": "Username",
|
"USERNAME": "Username",
|
||||||
|
@ -329,6 +329,7 @@
|
|||||||
"GROUP": "Group",
|
"GROUP": "Group",
|
||||||
"GROUPS": "Groups",
|
"GROUPS": "Groups",
|
||||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||||
|
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||||
"ADD": "Add",
|
"ADD": "Add",
|
||||||
"EDIT": "Edit",
|
"EDIT": "Edit",
|
||||||
"DELETE": "Delete",
|
"DELETE": "Delete",
|
||||||
@ -340,8 +341,17 @@
|
|||||||
"ADD_GROUP_SUCCESS": "Add group success",
|
"ADD_GROUP_SUCCESS": "Add group success",
|
||||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||||
"LDAP_TYPE": "LDAP",
|
"LDAP_TYPE": "LDAP",
|
||||||
|
"HTTP_TYPE": "HTTP",
|
||||||
"OF": "of",
|
"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": {
|
"AUDIT_LOG": {
|
||||||
"USERNAME": "Nombre de usuario",
|
"USERNAME": "Nombre de usuario",
|
||||||
|
@ -321,6 +321,7 @@
|
|||||||
"Group": "Group",
|
"Group": "Group",
|
||||||
"GROUPS": "Groups",
|
"GROUPS": "Groups",
|
||||||
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
"IMPORT_LDAP_GROUP": "Import LDAP Group",
|
||||||
|
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||||
"ADD": "Add",
|
"ADD": "Add",
|
||||||
"EDIT": "Edit",
|
"EDIT": "Edit",
|
||||||
"DELETE": "Delete",
|
"DELETE": "Delete",
|
||||||
@ -333,8 +334,17 @@
|
|||||||
"ADD_GROUP_SUCCESS": "Add group success",
|
"ADD_GROUP_SUCCESS": "Add group success",
|
||||||
"EDIT_GROUP_SUCCESS": "Edit group success",
|
"EDIT_GROUP_SUCCESS": "Edit group success",
|
||||||
"LDAP_TYPE": "LDAP",
|
"LDAP_TYPE": "LDAP",
|
||||||
|
"HTTP_TYPE": "HTTP",
|
||||||
"OF": "of",
|
"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": {
|
"AUDIT_LOG": {
|
||||||
"USERNAME": "Nom d'utilisateur",
|
"USERNAME": "Nom d'utilisateur",
|
||||||
|
@ -326,6 +326,7 @@
|
|||||||
"GROUP": "Grupo",
|
"GROUP": "Grupo",
|
||||||
"GROUPS": "Grupos",
|
"GROUPS": "Grupos",
|
||||||
"IMPORT_LDAP_GROUP": "Importar grupo do LDAP",
|
"IMPORT_LDAP_GROUP": "Importar grupo do LDAP",
|
||||||
|
"IMPORT_HTTP_GROUP": "New HTTP Group",
|
||||||
"ADD": "Novo Grupo",
|
"ADD": "Novo Grupo",
|
||||||
"EDIT": "Editar",
|
"EDIT": "Editar",
|
||||||
"DELETE": "Remover",
|
"DELETE": "Remover",
|
||||||
@ -338,8 +339,17 @@
|
|||||||
"ADD_GROUP_SUCCESS": "Grupo adicionado com sucesso",
|
"ADD_GROUP_SUCCESS": "Grupo adicionado com sucesso",
|
||||||
"EDIT_GROUP_SUCCESS": "Grupo editado com sucesso",
|
"EDIT_GROUP_SUCCESS": "Grupo editado com sucesso",
|
||||||
"LDAP_TYPE": "LDAP",
|
"LDAP_TYPE": "LDAP",
|
||||||
|
"HTTP_TYPE": "HTTP",
|
||||||
"OF": "de",
|
"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": {
|
"AUDIT_LOG": {
|
||||||
"USERNAME": "Nome do usuário",
|
"USERNAME": "Nome do usuário",
|
||||||
|
@ -327,6 +327,7 @@
|
|||||||
"GROUP": "组",
|
"GROUP": "组",
|
||||||
"GROUPS": "组",
|
"GROUPS": "组",
|
||||||
"IMPORT_LDAP_GROUP": "导入LDAP组",
|
"IMPORT_LDAP_GROUP": "导入LDAP组",
|
||||||
|
"IMPORT_HTTP_GROUP": "新建HTTP组",
|
||||||
"ADD": "新增",
|
"ADD": "新增",
|
||||||
"EDIT": "编辑",
|
"EDIT": "编辑",
|
||||||
"DELETE": "删除",
|
"DELETE": "删除",
|
||||||
@ -339,8 +340,17 @@
|
|||||||
"ADD_GROUP_SUCCESS": "添加组成功",
|
"ADD_GROUP_SUCCESS": "添加组成功",
|
||||||
"EDIT_GROUP_SUCCESS": "修改组成功",
|
"EDIT_GROUP_SUCCESS": "修改组成功",
|
||||||
"LDAP_TYPE": "LDAP",
|
"LDAP_TYPE": "LDAP",
|
||||||
|
"HTTP_TYPE": "HTTP",
|
||||||
"OF": "共计",
|
"OF": "共计",
|
||||||
"ITEMS": "条记录"
|
"ITEMS": "条记录",
|
||||||
|
"NEW_MEMBER": "新建组成员",
|
||||||
|
"NEW_USER_INFO": "添加一个组作为具有指定角色的此项目的成员",
|
||||||
|
"ROLE": "权限",
|
||||||
|
"SYS_ADMIN": "系统管理员",
|
||||||
|
"PROJECT_ADMIN": "项目管理员",
|
||||||
|
"PROJECT_MASTER": "维护人员",
|
||||||
|
"DEVELOPER": "开发者",
|
||||||
|
"GUEST": "访客"
|
||||||
},
|
},
|
||||||
"AUDIT_LOG": {
|
"AUDIT_LOG": {
|
||||||
"USERNAME": "用户名",
|
"USERNAME": "用户名",
|
||||||
|
Loading…
Reference in New Issue
Block a user