mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-06 13:07:52 +00:00
parent
a7f65ccb35
commit
bc116247ea
@ -38,13 +38,17 @@
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.TYPE' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
|
||||
<div [ngSwitch]="idp.type">
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_AZURE_AD">
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="azure ad" />
|
||||
Microsoft
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GOOGLE">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/google.png" alt="google" />
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
Google
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITHUB">
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="github" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OIDC">
|
||||
@ -52,7 +56,7 @@
|
||||
Generic OIDC
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OAUTH">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
Generic OAuth
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_JWT">
|
||||
@ -60,16 +64,16 @@
|
||||
Generic JWT
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITLAB">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
Gitlab
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITLAB_SELF_HOSTED">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="gitlab self hosted" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab self hosted" />
|
||||
Gitlab Self Hosted
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITHUB_ES">
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="github" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub Enterprise Server
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchDefault>coming soon</div>
|
||||
|
@ -226,6 +226,8 @@ export class IdpTableComponent implements OnInit {
|
||||
public routerLinkForRow(row: Provider.AsObject): any {
|
||||
if (row.id) {
|
||||
switch (row.type) {
|
||||
case ProviderType.PROVIDER_TYPE_AZURE_AD:
|
||||
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'azure-ad', row.id];
|
||||
case ProviderType.PROVIDER_TYPE_OIDC:
|
||||
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'oidc', row.id];
|
||||
case ProviderType.PROVIDER_TYPE_GITHUB_ES:
|
||||
|
@ -18,19 +18,27 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="../../../assets/images/idp/google.png" alt="google" />
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
<div class="text-container">
|
||||
<span class="title">Google</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="item card coming-soon" matRipple>
|
||||
<span class="state coming-soon-label">{{ 'ACTIONS.COMINGSOON' | translate }}</span>
|
||||
<img class="idp-logo" src="../../../assets/images/idp/ms.svg" alt="microsoft" />
|
||||
<a
|
||||
class="item card"
|
||||
[routerLink]="
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'azure-ad', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'azure-ad', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="microsoft" />
|
||||
<div class="text-container">
|
||||
<span class="title">Microsoft</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="item card"
|
||||
@ -43,8 +51,8 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="GitHub" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="GitHub" />
|
||||
|
||||
<div class="text-container">
|
||||
<span class="title">GitHub</span>
|
||||
@ -61,8 +69,8 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="GitHub" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="GitHub" />
|
||||
|
||||
<div class="text-container">
|
||||
<span class="title">GitHub Enterprise Server</span>
|
||||
@ -70,7 +78,7 @@
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="item card coming-soon"
|
||||
class="item card"
|
||||
[routerLink]="
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'gitlab', 'create']
|
||||
@ -79,8 +87,7 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<span class="state coming-soon-label">{{ 'ACTIONS.COMINGSOON' | translate }}</span>
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
<div class="text-container">
|
||||
<span class="title">GitLab</span>
|
||||
</div>
|
||||
@ -96,7 +103,7 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
<div class="text-container">
|
||||
<span class="title">GitLab Self Hosted</span>
|
||||
</div>
|
||||
@ -130,7 +137,7 @@
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
|
||||
<div class="text-container">
|
||||
<span class="title">Generic OAuth</span>
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { ProviderAzureADComponent } from './provider-azure-ad.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ProviderAzureADComponent,
|
||||
data: { animation: 'DetailPage' },
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ProviderAzureADRoutingModule {}
|
@ -0,0 +1,108 @@
|
||||
<cnsl-create-layout
|
||||
title="{{ id ? ('IDP.DETAIL.TITLE' | translate) : ('IDP.CREATE.TITLE' | translate) }}"
|
||||
(closed)="close()"
|
||||
>
|
||||
<div class="azure-ad-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="microsoft" />
|
||||
<h1>{{ 'IDP.CREATE.AZUREAD.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<p class="desc cnsl-secondary-text">
|
||||
{{ !provider ? ('IDP.CREATE.AZUREAD.DESCRIPTION' | translate) : ('IDP.DETAIL.DESCRIPTION' | translate) }}
|
||||
</p>
|
||||
|
||||
<form [formGroup]="form" (ngSubmit)="submitForm()">
|
||||
<div class="azure-ad-content">
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="name" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="clientId" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox *ngIf="provider" [(ngModel)]="updateClientSecret" [ngModelOptions]="{ standalone: true }">{{
|
||||
'IDP.UPDATECLIENTSECRET' | translate
|
||||
}}</mat-checkbox>
|
||||
<cnsl-form-field *ngIf="!provider || (provider && updateClientSecret)" class="formfield">
|
||||
<cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="clientSecret" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<div class="optional-h-wrapper">
|
||||
<h2>{{ 'IDP.OPTIONAL' | translate }}</h2>
|
||||
<button (click)="showOptional = !showOptional" type="button" mat-icon-button>
|
||||
<mat-icon *ngIf="showOptional">keyboard_arrow_up</mat-icon
|
||||
><mat-icon *ngIf="!showOptional">keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="showOptional">
|
||||
<div class="idp-scopes">
|
||||
<div class="flex-line">
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
|
||||
|
||||
<input
|
||||
cnslInput
|
||||
[matChipInputFor]="chipScopesList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
[matChipInputAddOnBlur]="true"
|
||||
(matChipInputTokenEnd)="addScope($event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
<button class="scope-add-button" (click)="addScope($any($event))" mat-icon-button>
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<mat-chip-list #chipScopesList aria-label="scope selection">
|
||||
<mat-chip
|
||||
class="chip"
|
||||
*ngFor="let scope of scopesList?.value"
|
||||
selectable="false"
|
||||
removable
|
||||
(removed)="removeScope(scope)"
|
||||
>
|
||||
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<mat-checkbox formControlName="emailVerified">{{ 'IDP.EMAILVERIFIED' | translate }}</mat-checkbox>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.AZUREADTENANTTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="tenantType">
|
||||
<mat-option *ngFor="let type of tenantTypes" [value]="type">
|
||||
{{ 'IDP.AZUREADTENANTTYPES.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.AZUREADTENANTID' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="tenantId" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-provider-options
|
||||
[initialOptions]="provider?.config?.options"
|
||||
(optionsChanged)="options = $event"
|
||||
></cnsl-provider-options>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="azure-ad-create-actions">
|
||||
<button color="primary" mat-raised-button class="continue-button" [disabled]="form.invalid" type="submit">
|
||||
<span *ngIf="id">{{ 'ACTIONS.SAVE' | translate }}</span>
|
||||
<span *ngIf="!id">{{ 'ACTIONS.CREATE' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</cnsl-create-layout>
|
@ -0,0 +1,87 @@
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.azure-ad-create-content {
|
||||
.title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.idp-logo {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
margin-right: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.formfield {
|
||||
display: block;
|
||||
max-width: 400px;
|
||||
|
||||
.name-hint {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mat-chip-input {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.chip {
|
||||
border-radius: 0.5rem;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 450px) {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
.azure-ad-content {
|
||||
.desc {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.idp-scopes {
|
||||
padding-bottom: 0.5rem;
|
||||
|
||||
.flex-line {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
max-width: 400px;
|
||||
|
||||
.formfield {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.scope-add-button {
|
||||
margin-top: 1.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.azure-ad-create-actions {
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
|
||||
button[mat-raised-button] {
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.optional-h-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
h2 {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ProviderAzureADComponent } from './provider-azure-ad.component';
|
||||
|
||||
describe('ProviderAzureADComponent', () => {
|
||||
let component: ProviderAzureADComponent;
|
||||
let fixture: ComponentFixture<ProviderAzureADComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ProviderAzureADComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProviderAzureADComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,320 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
import {
|
||||
AddAzureADProviderRequest as AdminAddAzureADProviderRequest,
|
||||
GetProviderByIDRequest as AdminGetProviderByIDRequest,
|
||||
UpdateAzureADProviderRequest as AdminUpdateAzureADProviderRequest,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { AzureADTenant, AzureADTenantType, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import {
|
||||
AddAzureADProviderRequest as MgmtAddAzureADProviderRequest,
|
||||
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
|
||||
UpdateAzureADProviderRequest as MgmtUpdateAzureADProviderRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-provider-azure-ad',
|
||||
templateUrl: './provider-azure-ad.component.html',
|
||||
styleUrls: ['./provider-azure-ad.component.scss'],
|
||||
})
|
||||
export class ProviderAzureADComponent {
|
||||
public showOptional: boolean = false;
|
||||
public options: Options = new Options();
|
||||
public id: string | null = '';
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
private service!: ManagementService | AdminService;
|
||||
|
||||
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
|
||||
|
||||
public form!: FormGroup;
|
||||
|
||||
public loading: boolean = false;
|
||||
|
||||
public provider?: Provider.AsObject;
|
||||
public updateClientSecret: boolean = false;
|
||||
public tenantTypes = [
|
||||
AzureADTenantType.AZURE_AD_TENANT_TYPE_COMMON,
|
||||
AzureADTenantType.AZURE_AD_TENANT_TYPE_ORGANISATIONS,
|
||||
AzureADTenantType.AZURE_AD_TENANT_TYPE_CONSUMERS,
|
||||
];
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
private _location: Location,
|
||||
private breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
this.form = new FormGroup({
|
||||
name: new FormControl('', []),
|
||||
clientId: new FormControl('', [requiredValidator]),
|
||||
clientSecret: new FormControl('', [requiredValidator]),
|
||||
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
||||
tenantType: new FormControl<AzureADTenantType>(AzureADTenantType.AZURE_AD_TENANT_TYPE_COMMON),
|
||||
tenantId: new FormControl<string>(''),
|
||||
emailVerified: new FormControl(false),
|
||||
});
|
||||
|
||||
this.route.data.pipe(take(1)).subscribe((data) => {
|
||||
this.serviceType = data.serviceType;
|
||||
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
|
||||
const bread: Breadcrumb = {
|
||||
type: BreadcrumbType.ORG,
|
||||
routerLink: ['/org'],
|
||||
};
|
||||
|
||||
this.breadcrumbService.setBreadcrumb([bread]);
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
|
||||
const iamBread = new Breadcrumb({
|
||||
type: BreadcrumbType.ORG,
|
||||
name: 'Instance',
|
||||
routerLink: ['/instance'],
|
||||
});
|
||||
this.breadcrumbService.setBreadcrumb([iamBread]);
|
||||
break;
|
||||
}
|
||||
|
||||
this.id = this.route.snapshot.paramMap.get('id');
|
||||
if (this.id) {
|
||||
this.clientSecret?.setValidators([]);
|
||||
this.getData(this.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getData(id: string): void {
|
||||
const req =
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? new AdminGetProviderByIDRequest()
|
||||
: new MgmtGetProviderByIDRequest();
|
||||
req.setId(id);
|
||||
this.service
|
||||
.getProviderByID(req)
|
||||
.then((resp) => {
|
||||
this.provider = resp.idp;
|
||||
this.loading = false;
|
||||
if (this.provider?.config?.azureAd) {
|
||||
this.form.patchValue(this.provider.config.azureAd);
|
||||
this.name?.setValue(this.provider.name);
|
||||
this.tenantId?.setValue(this.provider.config.azureAd.tenant?.tenantId);
|
||||
this.tenantType?.setValue(this.provider.config.azureAd.tenant?.tenantType);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
public submitForm(): void {
|
||||
this.provider ? this.updateAzureADProvider() : this.addAzureADProvider();
|
||||
}
|
||||
|
||||
public addAzureADProvider(): void {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const req = new MgmtAddAzureADProviderRequest();
|
||||
|
||||
req.setName(this.name?.value);
|
||||
req.setClientId(this.clientId?.value);
|
||||
req.setClientSecret(this.clientSecret?.value);
|
||||
req.setEmailVerified(this.emailVerified?.value);
|
||||
|
||||
const tenant = new AzureADTenant();
|
||||
tenant.setTenantId(this.tenantId?.value);
|
||||
tenant.setTenantType(this.tenantType?.value);
|
||||
req.setTenant(tenant);
|
||||
|
||||
req.setScopesList(this.scopesList?.value);
|
||||
req.setProviderOptions(this.options);
|
||||
|
||||
this.loading = true;
|
||||
(this.service as ManagementService)
|
||||
.addAzureADProvider(req)
|
||||
.then((idp) => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } });
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.loading = false;
|
||||
});
|
||||
} else if (PolicyComponentServiceType.ADMIN) {
|
||||
const req = new AdminAddAzureADProviderRequest();
|
||||
req.setName(this.name?.value);
|
||||
req.setClientId(this.clientId?.value);
|
||||
req.setClientSecret(this.clientSecret?.value);
|
||||
req.setEmailVerified(this.emailVerified?.value);
|
||||
|
||||
const tenant = new AzureADTenant();
|
||||
tenant.setTenantId(this.tenantId?.value);
|
||||
tenant.setTenantType(this.tenantType?.value);
|
||||
req.setTenant(tenant);
|
||||
|
||||
req.setScopesList(this.scopesList?.value);
|
||||
req.setProviderOptions(this.options);
|
||||
|
||||
this.loading = true;
|
||||
(this.service as AdminService)
|
||||
.addAzureADProvider(req)
|
||||
.then((idp) => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } });
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.loading = false;
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public updateAzureADProvider(): void {
|
||||
if (this.provider) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const req = new MgmtUpdateAzureADProviderRequest();
|
||||
req.setId(this.provider.id);
|
||||
req.setName(this.name?.value);
|
||||
req.setClientId(this.clientId?.value);
|
||||
req.setEmailVerified(this.emailVerified?.value);
|
||||
|
||||
const tenant = new AzureADTenant();
|
||||
|
||||
tenant.setTenantId(this.tenantId?.value);
|
||||
tenant.setTenantType(this.tenantType?.value);
|
||||
req.setTenant(tenant);
|
||||
|
||||
req.setScopesList(this.scopesList?.value);
|
||||
req.setProviderOptions(this.options);
|
||||
|
||||
if (this.updateClientSecret) {
|
||||
req.setClientSecret(this.clientSecret?.value);
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
(this.service as ManagementService)
|
||||
.updateAzureADProvider(req)
|
||||
.then((idp) => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } });
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.loading = false;
|
||||
});
|
||||
} else if (PolicyComponentServiceType.ADMIN) {
|
||||
const req = new AdminUpdateAzureADProviderRequest();
|
||||
req.setId(this.provider.id);
|
||||
req.setName(this.name?.value);
|
||||
req.setClientId(this.clientId?.value);
|
||||
req.setEmailVerified(this.emailVerified?.value);
|
||||
|
||||
const tenant = new AzureADTenant();
|
||||
tenant.setTenantId(this.tenantId?.value);
|
||||
tenant.setTenantType(this.tenantType?.value);
|
||||
req.setTenant(tenant);
|
||||
|
||||
req.setScopesList(this.scopesList?.value);
|
||||
req.setProviderOptions(this.options);
|
||||
|
||||
if (this.updateClientSecret) {
|
||||
req.setClientSecret(this.clientSecret?.value);
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
(this.service as AdminService)
|
||||
.updateAzureADProvider(req)
|
||||
.then((idp) => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } });
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.loading = false;
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._location.back();
|
||||
}
|
||||
|
||||
public addScope(event: MatChipInputEvent): void {
|
||||
const input = event.chipInput?.inputElement;
|
||||
const value = event.value.trim();
|
||||
|
||||
if (value !== '') {
|
||||
if (this.scopesList?.value) {
|
||||
this.scopesList.value.push(value);
|
||||
if (input) {
|
||||
input.value = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public removeScope(uri: string): void {
|
||||
if (this.scopesList?.value) {
|
||||
const index = this.scopesList.value.indexOf(uri);
|
||||
|
||||
if (index !== undefined && index >= 0) {
|
||||
this.scopesList.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get name(): AbstractControl | null {
|
||||
return this.form.get('name');
|
||||
}
|
||||
|
||||
public get clientId(): AbstractControl | null {
|
||||
return this.form.get('clientId');
|
||||
}
|
||||
|
||||
public get clientSecret(): AbstractControl | null {
|
||||
return this.form.get('clientSecret');
|
||||
}
|
||||
|
||||
public get scopesList(): AbstractControl | null {
|
||||
return this.form.get('scopesList');
|
||||
}
|
||||
|
||||
public get emailVerified(): AbstractControl | null {
|
||||
return this.form.get('emailVerified');
|
||||
}
|
||||
|
||||
public get tenantId(): AbstractControl | null {
|
||||
return this.form.get('tenantId');
|
||||
}
|
||||
|
||||
public get tenantType(): AbstractControl | null {
|
||||
return this.form.get('tenantType');
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button';
|
||||
import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox';
|
||||
import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips';
|
||||
import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner';
|
||||
import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select';
|
||||
import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { CreateLayoutModule } from '../../create-layout/create-layout.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { ProviderOptionsModule } from '../../provider-options/provider-options.module';
|
||||
import { ProviderAzureADRoutingModule } from './provider-azure-ad-routing.module';
|
||||
import { ProviderAzureADComponent } from './provider-azure-ad.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ProviderAzureADComponent],
|
||||
imports: [
|
||||
ProviderAzureADRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CreateLayoutModule,
|
||||
InfoSectionModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSelectModule,
|
||||
MatIconModule,
|
||||
MatChipsModule,
|
||||
CardModule,
|
||||
MatCheckboxModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
ProviderOptionsModule,
|
||||
MatLegacyProgressSpinnerModule,
|
||||
],
|
||||
})
|
||||
export default class ProviderAzureADModule {}
|
@ -4,8 +4,8 @@
|
||||
>
|
||||
<div class="github-es-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="github" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
|
||||
<h1>{{ 'IDP.CREATE.GITHUBES.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
|
@ -4,8 +4,8 @@
|
||||
>
|
||||
<div class="github-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="github" />
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
<h1>{{ 'IDP.CREATE.GITHUB.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
>
|
||||
<div class="gitlab-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
<h1>{{ 'IDP.CREATE.GITLABSELFHOSTED.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
>
|
||||
<div class="gitlab-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
<h1>{{ 'IDP.CREATE.GITLAB.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
>
|
||||
<div class="google-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/google.png" alt="google" />
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
<h1>{{ 'IDP.CREATE.GOOGLE.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
>
|
||||
<div class="oauth-create-content">
|
||||
<div class="title-row">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
|
||||
<h1>{{ 'IDP.CREATE.OAUTH.TITLE' | translate }}</h1>
|
||||
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
|
||||
|
@ -31,6 +31,19 @@ const routes: Routes = [
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'azure-ad',
|
||||
children: [
|
||||
{
|
||||
path: 'create',
|
||||
loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'),
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'oidc',
|
||||
children: [
|
||||
|
@ -125,6 +125,19 @@ const routes: Routes = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'azure-ad',
|
||||
children: [
|
||||
{
|
||||
path: 'create',
|
||||
loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'),
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -6,6 +6,8 @@ import {
|
||||
ActivateLabelPolicyResponse,
|
||||
ActivateSMSProviderRequest,
|
||||
ActivateSMSProviderResponse,
|
||||
AddAzureADProviderRequest,
|
||||
AddAzureADProviderResponse,
|
||||
AddCustomDomainPolicyRequest,
|
||||
AddCustomOrgIAMPolicyResponse,
|
||||
AddGenericOAuthProviderRequest,
|
||||
@ -200,6 +202,8 @@ import {
|
||||
SetSecurityPolicyResponse,
|
||||
SetUpOrgRequest,
|
||||
SetUpOrgResponse,
|
||||
UpdateAzureADProviderRequest,
|
||||
UpdateAzureADProviderResponse,
|
||||
UpdateCustomDomainPolicyRequest,
|
||||
UpdateCustomDomainPolicyResponse,
|
||||
UpdateDomainPolicyRequest,
|
||||
@ -914,6 +918,14 @@ export class AdminService {
|
||||
|
||||
// idp templates
|
||||
|
||||
public addAzureADProvider(req: AddAzureADProviderRequest): Promise<AddAzureADProviderResponse.AsObject> {
|
||||
return this.grpcService.admin.addAzureADProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public updateAzureADProvider(req: UpdateAzureADProviderRequest): Promise<UpdateAzureADProviderResponse.AsObject> {
|
||||
return this.grpcService.admin.updateAzureADProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public addGoogleProvider(req: AddGoogleProviderRequest): Promise<AddGoogleProviderResponse.AsObject> {
|
||||
return this.grpcService.admin.addGoogleProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import {
|
||||
AddAPIAppResponse,
|
||||
AddAppKeyRequest,
|
||||
AddAppKeyResponse,
|
||||
AddAzureADProviderRequest,
|
||||
AddAzureADProviderResponse,
|
||||
AddCustomLabelPolicyRequest,
|
||||
AddCustomLabelPolicyResponse,
|
||||
AddCustomLockoutPolicyRequest,
|
||||
@ -423,6 +425,8 @@ import {
|
||||
UpdateAPIAppConfigResponse,
|
||||
UpdateAppRequest,
|
||||
UpdateAppResponse,
|
||||
UpdateAzureADProviderRequest,
|
||||
UpdateAzureADProviderResponse,
|
||||
UpdateCustomLabelPolicyRequest,
|
||||
UpdateCustomLabelPolicyResponse,
|
||||
UpdateCustomLockoutPolicyRequest,
|
||||
@ -873,6 +877,14 @@ export class ManagementService {
|
||||
|
||||
// idp templates
|
||||
|
||||
public addAzureADProvider(req: AddAzureADProviderRequest): Promise<AddAzureADProviderResponse.AsObject> {
|
||||
return this.grpcService.mgmt.addAzureADProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public updateAzureADProvider(req: UpdateAzureADProviderRequest): Promise<UpdateAzureADProviderResponse.AsObject> {
|
||||
return this.grpcService.mgmt.updateAzureADProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public addGoogleProvider(req: AddGoogleProviderRequest): Promise<AddGoogleProviderResponse.AsObject> {
|
||||
return this.grpcService.mgmt.addGoogleProvider(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
@ -1642,6 +1642,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Github Provider",
|
||||
"DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Github-Identitätsprovider ein."
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Microsoft Provider",
|
||||
"DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Microsoft-Identitätsprovider ein."
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1674,6 +1678,14 @@
|
||||
"1": "aktiv",
|
||||
"2": "inaktiv"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "Tenant Typ",
|
||||
"AZUREADTENANTID": "Tenant ID",
|
||||
"EMAILVERIFIED": "Email verifiziert",
|
||||
"NAMEHINT": "Wenn angegeben, wir er im Login interface angezeigt.",
|
||||
"OPTIONAL": "optional",
|
||||
"UPDATECLIENTSECRET": "Client Secret updaten",
|
||||
|
@ -1647,6 +1647,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Github Provider",
|
||||
"DESCRIPTION": "Enter the credentials for your Github Identity Provider"
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Microsoft Provider",
|
||||
"DESCRIPTION": "Enter the credentials for your Microsoft Identity Provider"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1674,6 +1678,14 @@
|
||||
"1": "active",
|
||||
"2": "inactive"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "Tenant Type",
|
||||
"AZUREADTENANTID": "Tenant ID",
|
||||
"EMAILVERIFIED": "Email verified",
|
||||
"NAMEHINT": "If specified it will be shown in the login interface.",
|
||||
"OPTIONAL": "optional",
|
||||
"UPDATECLIENTSECRET": "update client secret",
|
||||
|
@ -1646,6 +1646,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Fournisseur Github",
|
||||
"DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Github"
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Fournisseur Microsoft",
|
||||
"DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Microsoft"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1678,6 +1682,14 @@
|
||||
"1": "actif",
|
||||
"2": "inactif"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "Type de locataire",
|
||||
"AZUREADTENANTID": "ID du locataire",
|
||||
"EMAILVERIFIED": "Courriel vérifié",
|
||||
"NAMEHINT": "Si elle est spécifiée, elle sera affichée dans l'interface de connexion.",
|
||||
"OPTIONAL": "optionnel",
|
||||
"UPDATECLIENTSECRET": "mise à jour du secret client",
|
||||
|
@ -1647,6 +1647,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Github Provider",
|
||||
"DESCRIPTION": "Inserisci i dati necessari per il tuo Github provider."
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Microsoft Provider",
|
||||
"DESCRIPTION": "Inserisci i dati necessari per il tuo Microsoft provider."
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1679,6 +1683,14 @@
|
||||
"1": "attivo",
|
||||
"2": "inattivo"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "Tipo tenant",
|
||||
"AZUREADTENANTID": "tenant ID",
|
||||
"EMAILVERIFIED": "Email verificata",
|
||||
"NAMEHINT": "Se specificato, verrà mostrato nell'interfaccia di accesso.",
|
||||
"OPTIONAL": "opzionale",
|
||||
"UPDATECLIENTSECRET": "Aggiorna secret",
|
||||
|
@ -1646,6 +1646,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Github Provider",
|
||||
"DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Github"
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Microsoft Provider",
|
||||
"DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Microsoft"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1678,6 +1682,14 @@
|
||||
"1": "aktywny",
|
||||
"2": "nieaktywny"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "Rodzaj najemcy",
|
||||
"AZUREADTENANTID": "Identyfikator najemcy",
|
||||
"EMAILVERIFIED": "Email zweryfikowany",
|
||||
"NAMEHINT": "Jeśli zostanie podany, będzie widoczny w interfejsie logowania.",
|
||||
"OPTIONAL": "opcjonalnie",
|
||||
"UPDATECLIENTSECRET": "aktualizacja tajemnicy klienta",
|
||||
|
@ -1645,6 +1645,10 @@
|
||||
"GITHUB": {
|
||||
"TITLE": "Github 身份提供者",
|
||||
"DESCRIPTION": "输入您的 Github 身份提供商的凭据"
|
||||
},
|
||||
"AZUREAD": {
|
||||
"TITLE": "Microsoft 身份提供者",
|
||||
"DESCRIPTION": "输入您的 Microsoft 身份提供商的凭据"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
@ -1677,6 +1681,14 @@
|
||||
"1": "启用",
|
||||
"2": "停用"
|
||||
},
|
||||
"AZUREADTENANTTYPES": {
|
||||
"0": "Common",
|
||||
"1": "Organizations",
|
||||
"2": "Customers"
|
||||
},
|
||||
"AZUREADTENANTTYPE": "租户类型",
|
||||
"AZUREADTENANTID": "租户编号",
|
||||
"EMAILVERIFIED": "电子邮件已验证",
|
||||
"NAMEHINT": "如果指定,它将显示在登录界面。",
|
||||
"OPTIONAL": "可选",
|
||||
"UPDATECLIENTSECRET": "更新客户秘密",
|
||||
|
Loading…
x
Reference in New Issue
Block a user