feat(console): GitHub identity provider template (#5403)

Github idp template for console
This commit is contained in:
Max Peintner 2023-03-13 11:01:09 +01:00 committed by GitHub
parent eb4f7c5d7c
commit f55877eb70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 657 additions and 23 deletions

View File

@ -42,6 +42,11 @@
<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 Google
</div> </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" />
GitHub
</div>
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OIDC"> <div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OIDC">
<mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" /> <mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" />
Generic OIDC Generic OIDC

View File

@ -234,6 +234,8 @@ export class IdpTableComponent implements OnInit {
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'jwt', row.id]; return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'jwt', row.id];
case ProviderType.PROVIDER_TYPE_GOOGLE: case ProviderType.PROVIDER_TYPE_GOOGLE:
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'google', row.id]; return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'google', row.id];
case ProviderType.PROVIDER_TYPE_GITHUB:
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'github', row.id];
} }
} }
} }

View File

@ -32,15 +32,24 @@
</div> </div>
</div> </div>
<div class="item card coming-soon" matRipple> <a
<span class="state coming-soon-label">{{ 'ACTIONS.COMINGSOON' | translate }}</span> class="item card"
matRipple
[routerLink]="
serviceType === PolicyComponentServiceType.ADMIN
? ['/instance', 'provider', 'github', 'create']
: serviceType === PolicyComponentServiceType.MGMT
? ['/org', 'provider', 'github', 'create']
: []
"
>
<img class="idp-logo dark" src="../../../assets/images/idp/github-dark.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" /> <img class="idp-logo light" src="../../../assets/images/idp/github.svg" alt="GitHub" />
<div class="text-container"> <div class="text-container">
<span class="title">GitHub</span> <span class="title">GitHub</span>
</div> </div>
</div> </a>
<div class="item card coming-soon" matRipple> <div class="item card coming-soon" matRipple>
<span class="state coming-soon-label">{{ 'ACTIONS.COMINGSOON' | translate }}</span> <span class="state coming-soon-label">{{ 'ACTIONS.COMINGSOON' | translate }}</span>

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProviderGithubComponent } from './provider-github.component';
const routes: Routes = [
{
path: '',
component: ProviderGithubComponent,
data: { animation: 'DetailPage' },
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ProviderGithubRoutingModule {}

View File

@ -0,0 +1,94 @@
<cnsl-create-layout
title="{{ id ? ('IDP.DETAIL.TITLE' | translate) : ('IDP.CREATE.TITLE' | translate) }}"
(closed)="close()"
>
<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" />
<h1>{{ 'IDP.CREATE.GITHUB.TITLE' | translate }}</h1>
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
</div>
<p class="desc cnsl-secondary-text">
{{ !provider ? ('IDP.CREATE.GITHUB.DESCRIPTION' | translate) : ('IDP.DETAIL.DESCRIPTION' | translate) }}
</p>
<form [formGroup]="form" (ngSubmit)="submitForm()">
<div class="github-content">
<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>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
<span class="name-hint cnsl-secondary-text" cnslHint>{{ 'IDP.NAMEHINT' | translate }}</span>
</cnsl-form-field>
<cnsl-provider-options
[initialOptions]="provider?.config?.options"
(optionsChanged)="options = $event"
></cnsl-provider-options>
</div>
</div>
<div class="github-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>

View File

@ -0,0 +1,99 @@
.desc {
font-size: 14px;
}
@mixin provider-github-theme($theme) {
$is-dark-theme: map-get($theme, is-dark);
.github-create-content {
.title-row {
display: flex;
align-items: center;
.idp-logo {
height: 36px;
width: 36px;
margin-right: 1rem;
flex-shrink: 0;
&.dark {
display: if($is-dark-theme, block, none);
}
&.light {
display: if($is-dark-theme, none, block);
}
}
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;
}
}
.github-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;
}
}
}
}
}
}
.github-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;
}
}

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ProviderGithubComponent } from './provider-github.component';
describe('ProviderGithubComponent', () => {
let component: ProviderGithubComponent;
let fixture: ComponentFixture<ProviderGithubComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ProviderGithubComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProviderGithubComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,267 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component, Injector, Type } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
import { ActivatedRoute } from '@angular/router';
import { take } from 'rxjs';
import {
AddGitHubProviderRequest as AdminAddGithubProviderRequest,
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGitHubProviderRequest as AdminUpdateGithubProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGitHubProviderRequest as MgmtAddGithubProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
UpdateGitHubProviderRequest as MgmtUpdateGithubProviderRequest,
} 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 { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
@Component({
selector: 'cnsl-provider-github',
templateUrl: './provider-github.component.html',
styleUrls: ['./provider-github.component.scss'],
})
export class ProviderGithubComponent {
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;
constructor(
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('', [Validators.required]),
clientSecret: new FormControl('', [Validators.required]),
scopesList: new FormControl(['openid', 'profile', 'email'], []),
});
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?.github) {
this.form.patchValue(this.provider.config.github);
this.name?.setValue(this.provider.name);
}
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
}
public submitForm(): void {
this.provider ? this.updateGithubProvider() : this.addGithubProvider();
}
public addGithubProvider(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new MgmtAddGithubProviderRequest();
req.setName(this.name?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
req.setProviderOptions(this.options);
this.loading = true;
(this.service as ManagementService)
.addGitHubProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.close();
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
} else if (PolicyComponentServiceType.ADMIN) {
const req = new AdminAddGithubProviderRequest();
req.setName(this.name?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
req.setProviderOptions(this.options);
this.loading = true;
(this.service as AdminService)
.addGitHubProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.close();
}, 2000);
})
.catch((error) => {
this.loading = false;
this.toast.showError(error);
});
}
}
public updateGithubProvider(): void {
if (this.provider) {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new MgmtUpdateGithubProviderRequest();
req.setId(this.provider.id);
req.setName(this.name?.value);
req.setClientId(this.clientId?.value);
req.setScopesList(this.scopesList?.value);
req.setProviderOptions(this.options);
if (this.updateClientSecret) {
req.setClientSecret(this.clientSecret?.value);
}
this.loading = true;
(this.service as ManagementService)
.updateGitHubProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.close();
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
} else if (PolicyComponentServiceType.ADMIN) {
const req = new AdminUpdateGithubProviderRequest();
req.setId(this.provider.id);
req.setName(this.name?.value);
req.setClientId(this.clientId?.value);
req.setScopesList(this.scopesList?.value);
req.setProviderOptions(this.options);
if (this.updateClientSecret) {
req.setClientSecret(this.clientSecret?.value);
}
this.loading = true;
(this.service as AdminService)
.updateGitHubProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.close();
}, 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');
}
}

View File

@ -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 { ProviderGithubRoutingModule } from './provider-github-routing.module';
import { ProviderGithubComponent } from './provider-github.component';
@NgModule({
declarations: [ProviderGithubComponent],
imports: [
ProviderGithubRoutingModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
CreateLayoutModule,
InfoSectionModule,
InputModule,
MatButtonModule,
MatSelectModule,
MatIconModule,
MatChipsModule,
CardModule,
MatCheckboxModule,
MatTooltipModule,
TranslateModule,
ProviderOptionsModule,
MatLegacyProgressSpinnerModule,
],
})
export default class ProviderGithubModule {}

View File

@ -3,7 +3,7 @@ import { Location } from '@angular/common';
import { Component, Injector, Type } from '@angular/core'; import { Component, Injector, Type } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms'; import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips'; import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { take } from 'rxjs'; import { take } from 'rxjs';
import { import {
AddGoogleProviderRequest as AdminAddGoogleProviderRequest, AddGoogleProviderRequest as AdminAddGoogleProviderRequest,
@ -45,7 +45,6 @@ export class ProviderGoogleComponent {
public updateClientSecret: boolean = false; public updateClientSecret: boolean = false;
constructor( constructor(
private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
private toast: ToastService, private toast: ToastService,
private injector: Injector, private injector: Injector,
@ -135,7 +134,7 @@ export class ProviderGoogleComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -156,7 +155,7 @@ export class ProviderGoogleComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -186,7 +185,7 @@ export class ProviderGoogleComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -211,7 +210,7 @@ export class ProviderGoogleComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {

View File

@ -2,7 +2,7 @@ import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { Component, Injector, Type } from '@angular/core'; import { Component, Injector, Type } from '@angular/core';
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { import {
AddJWTProviderRequest as AdminAddJWTProviderRequest, AddJWTProviderRequest as AdminAddJWTProviderRequest,
@ -42,7 +42,6 @@ export class ProviderJWTComponent {
public provider?: Provider.AsObject; public provider?: Provider.AsObject;
constructor( constructor(
private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
private toast: ToastService, private toast: ToastService,
private injector: Injector, private injector: Injector,
@ -134,7 +133,7 @@ export class ProviderJWTComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -157,7 +156,7 @@ export class ProviderJWTComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -185,7 +184,7 @@ export class ProviderJWTComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -208,7 +207,7 @@ export class ProviderJWTComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {

View File

@ -3,7 +3,7 @@ import { Location } from '@angular/common';
import { Component, Injector, Type } from '@angular/core'; import { Component, Injector, Type } from '@angular/core';
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips'; import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { take } from 'rxjs'; import { take } from 'rxjs';
import { import {
AddGenericOIDCProviderRequest as AdminAddGenericOIDCProviderRequest, AddGenericOIDCProviderRequest as AdminAddGenericOIDCProviderRequest,
@ -44,7 +44,6 @@ export class ProviderOIDCComponent {
public provider?: Provider.AsObject; public provider?: Provider.AsObject;
constructor( constructor(
private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
private toast: ToastService, private toast: ToastService,
private injector: Injector, private injector: Injector,
@ -136,7 +135,7 @@ export class ProviderOIDCComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -157,7 +156,7 @@ export class ProviderOIDCComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -184,7 +183,7 @@ export class ProviderOIDCComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {
@ -206,7 +205,7 @@ export class ProviderOIDCComponent {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } }); this.close();
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {

View File

@ -83,6 +83,19 @@ const routes: Routes = [
}, },
], ],
}, },
{
path: 'github',
children: [
{
path: 'create',
loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'),
},
{
path: ':id',
loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'),
},
],
},
], ],
}, },
]; ];

View File

@ -71,6 +71,19 @@ const routes: Routes = [
}, },
], ],
}, },
{
path: 'github',
children: [
{
path: 'create',
loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'),
},
{
path: ':id',
loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'),
},
],
},
], ],
}, },
{ {

View File

@ -12,6 +12,8 @@ import {
AddGenericOAuthProviderResponse, AddGenericOAuthProviderResponse,
AddGenericOIDCProviderRequest, AddGenericOIDCProviderRequest,
AddGenericOIDCProviderResponse, AddGenericOIDCProviderResponse,
AddGitHubProviderRequest,
AddGitHubProviderResponse,
AddGoogleProviderRequest, AddGoogleProviderRequest,
AddGoogleProviderResponse, AddGoogleProviderResponse,
AddIAMMemberRequest, AddIAMMemberRequest,
@ -200,6 +202,8 @@ import {
UpdateGenericOAuthProviderResponse, UpdateGenericOAuthProviderResponse,
UpdateGenericOIDCProviderRequest, UpdateGenericOIDCProviderRequest,
UpdateGenericOIDCProviderResponse, UpdateGenericOIDCProviderResponse,
UpdateGitHubProviderRequest,
UpdateGitHubProviderResponse,
UpdateGoogleProviderRequest, UpdateGoogleProviderRequest,
UpdateGoogleProviderResponse, UpdateGoogleProviderResponse,
UpdateIAMMemberRequest, UpdateIAMMemberRequest,
@ -906,6 +910,14 @@ export class AdminService {
return this.grpcService.admin.updateGoogleProvider(req, null).then((resp) => resp.toObject()); return this.grpcService.admin.updateGoogleProvider(req, null).then((resp) => resp.toObject());
} }
public addGitHubProvider(req: AddGitHubProviderRequest): Promise<AddGitHubProviderResponse.AsObject> {
return this.grpcService.admin.addGitHubProvider(req, null).then((resp) => resp.toObject());
}
public updateGitHubProvider(req: UpdateGitHubProviderRequest): Promise<UpdateGitHubProviderResponse.AsObject> {
return this.grpcService.admin.updateGitHubProvider(req, null).then((resp) => resp.toObject());
}
public addGenericOIDCProvider(req: AddGenericOIDCProviderRequest): Promise<AddGenericOIDCProviderResponse.AsObject> { public addGenericOIDCProvider(req: AddGenericOIDCProviderRequest): Promise<AddGenericOIDCProviderResponse.AsObject> {
return this.grpcService.admin.addGenericOIDCProvider(req, null).then((resp) => resp.toObject()); return this.grpcService.admin.addGenericOIDCProvider(req, null).then((resp) => resp.toObject());
} }

View File

@ -33,6 +33,8 @@ import {
AddGenericOAuthProviderResponse, AddGenericOAuthProviderResponse,
AddGenericOIDCProviderRequest, AddGenericOIDCProviderRequest,
AddGenericOIDCProviderResponse, AddGenericOIDCProviderResponse,
AddGitHubProviderRequest,
AddGitHubProviderResponse,
AddGoogleProviderRequest, AddGoogleProviderRequest,
AddGoogleProviderResponse, AddGoogleProviderResponse,
AddHumanUserRequest, AddHumanUserRequest,
@ -433,6 +435,8 @@ import {
UpdateGenericOAuthProviderResponse, UpdateGenericOAuthProviderResponse,
UpdateGenericOIDCProviderRequest, UpdateGenericOIDCProviderRequest,
UpdateGenericOIDCProviderResponse, UpdateGenericOIDCProviderResponse,
UpdateGitHubProviderRequest,
UpdateGitHubProviderResponse,
UpdateGoogleProviderRequest, UpdateGoogleProviderRequest,
UpdateGoogleProviderResponse, UpdateGoogleProviderResponse,
UpdateHumanEmailRequest, UpdateHumanEmailRequest,
@ -865,6 +869,14 @@ export class ManagementService {
return this.grpcService.mgmt.updateGoogleProvider(req, null).then((resp) => resp.toObject()); return this.grpcService.mgmt.updateGoogleProvider(req, null).then((resp) => resp.toObject());
} }
public addGitHubProvider(req: AddGitHubProviderRequest): Promise<AddGitHubProviderResponse.AsObject> {
return this.grpcService.mgmt.addGitHubProvider(req, null).then((resp) => resp.toObject());
}
public updateGitHubProvider(req: UpdateGitHubProviderRequest): Promise<UpdateGitHubProviderResponse.AsObject> {
return this.grpcService.mgmt.updateGitHubProvider(req, null).then((resp) => resp.toObject());
}
public addGenericOIDCProvider(req: AddGenericOIDCProviderRequest): Promise<AddGenericOIDCProviderResponse.AsObject> { public addGenericOIDCProvider(req: AddGenericOIDCProviderRequest): Promise<AddGenericOIDCProviderResponse.AsObject> {
return this.grpcService.mgmt.addGenericOIDCProvider(req, null).then((resp) => resp.toObject()); return this.grpcService.mgmt.addGenericOIDCProvider(req, null).then((resp) => resp.toObject());
} }

View File

@ -1629,6 +1629,10 @@
"GOOGLE": { "GOOGLE": {
"TITLE": "Google Provider", "TITLE": "Google Provider",
"DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Google-Identitätsprovider ein." "DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Google-Identitätsprovider ein."
},
"GITHUB": {
"TITLE": "Github Provider",
"DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Github-Identitätsprovider ein."
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -1634,6 +1634,10 @@
"GOOGLE": { "GOOGLE": {
"TITLE": "Google Provider", "TITLE": "Google Provider",
"DESCRIPTION": "Enter the credentials for your Google Identity Provider" "DESCRIPTION": "Enter the credentials for your Google Identity Provider"
},
"GITHUB": {
"TITLE": "Github Provider",
"DESCRIPTION": "Enter the credentials for your Github Identity Provider"
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -1633,6 +1633,10 @@
"GOOGLE": { "GOOGLE": {
"TITLE": "Fournisseur Google", "TITLE": "Fournisseur Google",
"DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Google" "DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Google"
},
"GITHUB": {
"TITLE": "Fournisseur Github",
"DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Github"
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -1634,6 +1634,10 @@
"GOOGLE": { "GOOGLE": {
"TITLE": "Google Provider", "TITLE": "Google Provider",
"DESCRIPTION": "Inserisci i dati necessari per il tuo Google provider." "DESCRIPTION": "Inserisci i dati necessari per il tuo Google provider."
},
"GITHUB": {
"TITLE": "Github Provider",
"DESCRIPTION": "Inserisci i dati necessari per il tuo Github provider."
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -1633,6 +1633,10 @@
"GOOGLE": { "GOOGLE": {
"TITLE": "Google Provider", "TITLE": "Google Provider",
"DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Google" "DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Google"
},
"GITHUB": {
"TITLE": "Github Provider",
"DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Github"
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -1630,8 +1630,12 @@
"DESCRIPTION": "输入你的JWT供应商所需的数据。" "DESCRIPTION": "输入你的JWT供应商所需的数据。"
}, },
"GOOGLE": { "GOOGLE": {
"TITLE": "谷歌供应商", "TITLE": "Google 身份提供者",
"DESCRIPTION": "输入你的谷歌身份提供者的凭证" "DESCRIPTION": "输入您的 Google 身份提供商的凭据"
},
"GITHUB": {
"TITLE": "Github 身份提供者",
"DESCRIPTION": "输入您的 Github 身份提供商的凭据"
} }
}, },
"DETAIL": { "DETAIL": {

View File

@ -25,6 +25,7 @@
@import 'src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component'; @import 'src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component';
@import 'src/app/pages/projects/apps/app-detail/app-detail.component'; @import 'src/app/pages/projects/apps/app-detail/app-detail.component';
@import 'src/app/pages/projects/apps/redirect-uris/redirect-uris.component'; @import 'src/app/pages/projects/apps/redirect-uris/redirect-uris.component';
@import 'src/app/modules/providers/provider-github/provider-github.component';
@import 'src/app/modules/filter-events/filter-events.component'; @import 'src/app/modules/filter-events/filter-events.component';
@import 'src/app/modules/top-view/top-view.component'; @import 'src/app/modules/top-view/top-view.component';
@import 'src/app/pages/projects/projects.component'; @import 'src/app/pages/projects/projects.component';
@ -89,6 +90,7 @@
@include table-theme($theme); @include table-theme($theme);
@include detail-layout-theme($theme); @include detail-layout-theme($theme);
@include app-card-theme($theme); @include app-card-theme($theme);
@include provider-github-theme($theme);
@include login-policy-mfas-theme($theme); @include login-policy-mfas-theme($theme);
@include changes-theme($theme); @include changes-theme($theme);
@include home-theme($theme); @include home-theme($theme);