mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
Merge pull request #7281 from jwangyangls/oidc_step3_onboard_tpl
Add the OIDC onboard page
This commit is contained in:
commit
beeb8b53d7
@ -31,7 +31,7 @@ import { ProjectConfigComponent } from './project/project-config/project-config.
|
||||
import zh from '@angular/common/locales/zh-Hans';
|
||||
import es from '@angular/common/locales/es';
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
import { DevCenterComponent } from './dev-center/dev-center.component';
|
||||
import { OidcOnboardModule } from './oidc-onboard/oidc-onboard.module';
|
||||
registerLocaleData(zh, 'zh-cn');
|
||||
registerLocaleData(es, 'es-es');
|
||||
registerLocaleData(localeFr, 'fr-fr');
|
||||
@ -60,7 +60,8 @@ export function getCurrentLanguage(translateService: TranslateService) {
|
||||
AccountModule,
|
||||
HarborRoutingModule,
|
||||
ConfigurationModule,
|
||||
DeveloperCenterModule
|
||||
DeveloperCenterModule,
|
||||
OidcOnboardModule
|
||||
],
|
||||
exports: [
|
||||
],
|
||||
|
@ -18,6 +18,7 @@ import { SystemAdminGuard } from './shared/route/system-admin-activate.service';
|
||||
import { AuthCheckGuard } from './shared/route/auth-user-activate.service';
|
||||
import { SignInGuard } from './shared/route/sign-in-guard-activate.service';
|
||||
import { MemberGuard } from './shared/route/member-guard-activate.service';
|
||||
import { OidcGuard } from './shared/route/oidc-guard-active.service';
|
||||
|
||||
import { PageNotFoundComponent } from './shared/not-found/not-found.component';
|
||||
import { HarborShellComponent } from './base/harbor-shell/harbor-shell.component';
|
||||
@ -51,6 +52,7 @@ import { ProjectRoutingResolver } from './project/project-routing-resolver.servi
|
||||
import { ListChartsComponent } from './project/helm-chart/list-charts.component';
|
||||
import { ListChartVersionsComponent } from './project/helm-chart/list-chart-versions/list-chart-versions.component';
|
||||
import { HelmChartDetailComponent } from './project/helm-chart/helm-chart-detail/chart-detail.component';
|
||||
import { OidcOnboardComponent } from './oidc-onboard/oidc-onboard.component';
|
||||
|
||||
const harborRoutes: Routes = [
|
||||
{ path: '', redirectTo: 'harbor', pathMatch: 'full' },
|
||||
@ -59,6 +61,11 @@ const harborRoutes: Routes = [
|
||||
path: 'devcenter',
|
||||
component: DevCenterComponent
|
||||
},
|
||||
{
|
||||
path: 'oidc-onboard',
|
||||
component: OidcOnboardComponent,
|
||||
canActivate: [OidcGuard, SignInGuard]
|
||||
},
|
||||
{
|
||||
path: 'harbor',
|
||||
component: HarborShellComponent,
|
||||
|
43
src/portal/src/app/oidc-onboard/oidc-onboard.component.html
Normal file
43
src/portal/src/app/oidc-onboard/oidc-onboard.component.html
Normal file
@ -0,0 +1,43 @@
|
||||
<div class="modal">
|
||||
<div class="modal-dialog" role="dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button (click)="backHarborPage()" class="close">
|
||||
<clr-icon shape="close"></clr-icon>
|
||||
</button>
|
||||
<h3 class="modal-title oidc-header-text"><span>{{'CONFIG.OIDC.OIDC_SETNAME' | translate}}</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="error-message">
|
||||
<div class="alert alert-danger" role="alert" *ngIf="errorOpen">
|
||||
<div class="alert-items">
|
||||
<div class="alert-item static">
|
||||
<div class="alert-icon-wrapper">
|
||||
<clr-icon class="alert-icon" size="24" shape="exclamation-circle"></clr-icon>
|
||||
</div>
|
||||
<span class="alert-text">{{errorMessage}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="close" aria-label="Close" (click)="emptyErrorMessage()">
|
||||
<clr-icon aria-hidden="true" size="16" shape="close"></clr-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="body-message">{{'CONFIG.OIDC.OIDC_SETNAMECONTENT' | translate}}</p>
|
||||
</div>
|
||||
<br />
|
||||
<div class="username-div">
|
||||
<label for="oidcUsername" class="required">{{'CONFIG.OIDC.OIDC_USERNAME' | translate}}</label>
|
||||
<label for="oidcUsername" role="tooltip" class="tooltip tooltip-validation tooltip-lg tooltip-top-right">
|
||||
<input name="oidcUsername" type="text" [formControl]="oidcUsername" required id="oidcUsername" size="40">
|
||||
</label>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-outline" type="button" (click)="backHarborPage()" id="cancelButton">{{'BUTTON.CANCEL' | translate }}</button>
|
||||
<button class="btn btn-primary" id="saveButton" (click)="clickSaveBtn()" [disabled]="oidcUsername.invalid"
|
||||
type="button">{{'BUTTON.SAVE' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
25
src/portal/src/app/oidc-onboard/oidc-onboard.component.scss
Normal file
25
src/portal/src/app/oidc-onboard/oidc-onboard.component.scss
Normal file
@ -0,0 +1,25 @@
|
||||
.modal {
|
||||
background-color: rgb(80, 80, 80);
|
||||
.body-message {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.modal-header {
|
||||
.close {
|
||||
margin-right: 0.2rem
|
||||
}
|
||||
}
|
||||
.username-div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 80%;
|
||||
}
|
||||
input {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
.oidc-header-text{
|
||||
color:rgb(94, 94, 94);
|
||||
}
|
||||
.close-error {
|
||||
padding-right:0;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OidcOnboardComponent } from './oidc-onboard.component';
|
||||
|
||||
describe('OidcOnboardComponent', () => {
|
||||
let component: OidcOnboardComponent;
|
||||
let fixture: ComponentFixture<OidcOnboardComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ OidcOnboardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(OidcOnboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
43
src/portal/src/app/oidc-onboard/oidc-onboard.component.ts
Normal file
43
src/portal/src/app/oidc-onboard/oidc-onboard.component.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { OidcOnboardService } from './oidc-onboard.service';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { errorHandler } from "../shared/shared.utils";
|
||||
import { CommonRoutes } from '../shared/shared.const';
|
||||
|
||||
@Component({
|
||||
selector: 'app-oidc-onboard',
|
||||
templateUrl: './oidc-onboard.component.html',
|
||||
styleUrls: ['./oidc-onboard.component.scss']
|
||||
})
|
||||
export class OidcOnboardComponent implements OnInit {
|
||||
url: string;
|
||||
errorMessage: string = '';
|
||||
oidcUsername = new FormControl('');
|
||||
errorOpen: boolean = false;
|
||||
constructor(
|
||||
private oidcOnboardService: OidcOnboardService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.route.queryParams
|
||||
.subscribe(params => {
|
||||
this.oidcUsername.setValue(params["username"] || "");
|
||||
});
|
||||
}
|
||||
clickSaveBtn(): void {
|
||||
this.oidcOnboardService.oidcSave({ username: this.oidcUsername.value }).subscribe(res => { }
|
||||
, error => {
|
||||
this.errorMessage = errorHandler(error);
|
||||
this.errorOpen = true;
|
||||
});
|
||||
}
|
||||
emptyErrorMessage() {
|
||||
this.errorOpen = false;
|
||||
}
|
||||
backHarborPage() {
|
||||
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);
|
||||
}
|
||||
}
|
29
src/portal/src/app/oidc-onboard/oidc-onboard.module.ts
Normal file
29
src/portal/src/app/oidc-onboard/oidc-onboard.module.ts
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright Project Harbor Authors
|
||||
//
|
||||
// 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 { NgModule } from '@angular/core';
|
||||
import { OidcOnboardComponent } from './oidc-onboard.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { OidcOnboardService } from './oidc-onboard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule],
|
||||
declarations: [
|
||||
OidcOnboardComponent,
|
||||
],
|
||||
providers: [OidcOnboardService],
|
||||
exports: [
|
||||
OidcOnboardComponent
|
||||
]
|
||||
})
|
||||
export class OidcOnboardModule { }
|
12
src/portal/src/app/oidc-onboard/oidc-onboard.service.spec.ts
Normal file
12
src/portal/src/app/oidc-onboard/oidc-onboard.service.spec.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OidcOnboardService } from './oidc-onboard.service';
|
||||
|
||||
describe('OidcOnboardService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: OidcOnboardService = TestBed.get(OidcOnboardService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
16
src/portal/src/app/oidc-onboard/oidc-onboard.service.ts
Normal file
16
src/portal/src/app/oidc-onboard/oidc-onboard.service.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http, URLSearchParams } from '@angular/http';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { throwError as observableThrowError, Observable } from 'rxjs';
|
||||
|
||||
|
||||
export const logEndpoint = "/c/oidc/onboard";
|
||||
|
||||
@Injectable()
|
||||
export class OidcOnboardService {
|
||||
|
||||
constructor(private http: Http) { }
|
||||
oidcSave(param): Observable<any> {
|
||||
return this.http.post(logEndpoint, param).pipe(catchError(error => observableThrowError(error)));
|
||||
}
|
||||
}
|
58
src/portal/src/app/shared/route/oidc-guard-active.service.ts
Normal file
58
src/portal/src/app/shared/route/oidc-guard-active.service.ts
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
// Copyright Project Harbor Authors
|
||||
//
|
||||
// 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 { Injectable } from '@angular/core';
|
||||
import {
|
||||
CanActivate, Router,
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot,
|
||||
CanActivateChild
|
||||
} from '@angular/router';
|
||||
import { AppConfigService } from '../../app-config.service';
|
||||
import { UserPermissionService } from "@harbor/ui";
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { CommonRoutes } from '../../shared/shared.const';
|
||||
|
||||
@Injectable()
|
||||
export class OidcGuard implements CanActivate, CanActivateChild {
|
||||
constructor(private appConfigService: AppConfigService, private router: Router, private userPermission: UserPermissionService) { }
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
|
||||
// If user has logged in, should not login again
|
||||
return new Observable((observer) => {
|
||||
// If signout appended
|
||||
let queryParams = route.queryParams;
|
||||
this.appConfigService.load()
|
||||
.subscribe(updatedConfig => {
|
||||
if (updatedConfig.auth_mode === 'oidc_auth') {
|
||||
return observer.next(true);
|
||||
} else {
|
||||
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);
|
||||
return observer.next(false);
|
||||
}
|
||||
}
|
||||
, error => {
|
||||
// Catch the error
|
||||
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);
|
||||
console.error("Failed to load bootstrap options with error: ", error);
|
||||
return observer.next(false);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
|
||||
return this.canActivate(route, state);
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ import { AuthCheckGuard } from "./route/auth-user-activate.service";
|
||||
import { SignInGuard } from "./route/sign-in-guard-activate.service";
|
||||
import { SystemAdminGuard } from "./route/system-admin-activate.service";
|
||||
import { MemberGuard } from "./route/member-guard-activate.service";
|
||||
import { OidcGuard } from "./route/oidc-guard-active.service";
|
||||
import { LeavingRepositoryRouteDeactivate } from "./route/leaving-repository-deactivate.service";
|
||||
|
||||
import { PortValidatorDirective } from "./port.directive";
|
||||
@ -140,6 +141,7 @@ const uiLibConfig: IServiceConfig = {
|
||||
SignInGuard,
|
||||
LeavingRepositoryRouteDeactivate,
|
||||
MemberGuard,
|
||||
OidcGuard,
|
||||
MessageHandlerService,
|
||||
StatisticHandler
|
||||
]
|
||||
|
@ -697,7 +697,10 @@
|
||||
"CLIENT_ID": "OIDC Client ID",
|
||||
"CLIENTSECRET": "OIDC Client Secret",
|
||||
"SCOPE": "OIDC Scope",
|
||||
"OIDCSKIPCERTVERIFY": "OIDC Verify Cert"
|
||||
"OIDCSKIPCERTVERIFY": "OIDC Verify Cert",
|
||||
"OIDC_SETNAME": "Set OIDC Username",
|
||||
"OIDC_SETNAMECONTENT": "You must create a Harbor username the first time when authenticating via a third party(OIDC).This will be used within Harbor to be associated with projects, roles, etc.",
|
||||
"OIDC_USERNAME": "Username"
|
||||
},
|
||||
"SCANNING": {
|
||||
"TRIGGER_SCAN_ALL_SUCCESS": "Trigger scan all successfully!",
|
||||
|
@ -696,7 +696,10 @@
|
||||
"CLIENT_ID": "ID de cliente OIDC",
|
||||
"CLIENTSECRET": "OIDC Client Secret",
|
||||
"SCOPE": "OIDC Ámbito",
|
||||
"OIDCSKIPCERTVERIFY": "OIDC Verify Cert"
|
||||
"OIDCSKIPCERTVERIFY": "OIDC Verify Cert",
|
||||
"OIDC_SETNAME": "Set OIDC nombre de usuario",
|
||||
"OIDC_SETNAMECONTENT": "Usted debe crear un Harbor nombre de usuario la primera vez cuando la autenticación a través de un tercero (OIDC). Esta será usada en Harbor para ser asociados con proyectos, funciones, etc.",
|
||||
"OIDC_USERNAME": "Usuario"
|
||||
},
|
||||
"SCANNING": {
|
||||
"TRIGGER_SCAN_ALL_SUCCESS": "Trigger scan all successfully!",
|
||||
|
@ -661,7 +661,10 @@
|
||||
"CLIENT_ID": "no d'identification du client OIDC",
|
||||
"CLIENTSECRET": "OIDC Client Secret",
|
||||
"SCOPE": "OIDC Scope",
|
||||
"OIDCSKIPCERTVERIFY": "OIDC vérifier cert"
|
||||
"OIDCSKIPCERTVERIFY": "OIDC vérifier cert",
|
||||
"OIDC_SETNAME": "Ensemble OIDC nom d'utilisateur",
|
||||
"OIDC_SETNAMECONTENT": "vous devez créer un Harbor identifiant la première fois lors de la vérification par une tierce partie (oidc). il sera utilisé au sein de port à être associés aux projets, des rôles, etc.",
|
||||
"OIDC_USERNAME": "d'utilisateur"
|
||||
},
|
||||
"SCANNING": {
|
||||
"TRIGGER_SCAN_ALL_SUCCESS": "Déclenchement d'analyse globale avec succès !",
|
||||
|
@ -690,7 +690,10 @@
|
||||
"CLIENT_ID": "ID de cliente OIDC",
|
||||
"CLIENTSECRET": "OIDC Client Secret",
|
||||
"SCOPE": "Escopo OIDC",
|
||||
"OIDCSKIPCERTVERIFY": "Verificar certificado OIDC"
|
||||
"OIDCSKIPCERTVERIFY": "Verificar certificado OIDC",
|
||||
"OIDC_SETNAME": "Definir o Utilizador OIDC",
|
||||
"OIDC_SETNAMECONTENT": "Você deve Criar um Nome de usuário do Porto a primeira vez que autenticar através de um terceiro (OIDC). Isto será usado Dentro de Harbor para ser associado a projetos, papéis, etc.",
|
||||
"OIDC_USERNAME": "Utilizador"
|
||||
},
|
||||
"SCANNING": {
|
||||
"TRIGGER_SCAN_ALL_SUCCESS": "Disparo de análise geral efetuado com sucesso!",
|
||||
|
@ -695,7 +695,10 @@
|
||||
"CLIENT_ID": "OIDC 客户端标识",
|
||||
"CLIENTSECRET": "OIDC 客户端密码",
|
||||
"SCOPE": "OIDC scope",
|
||||
"OIDCSKIPCERTVERIFY": "OIDC 验证证书"
|
||||
"OIDCSKIPCERTVERIFY": "OIDC 验证证书",
|
||||
"OIDC_SETNAME": "设置OIDC用户名",
|
||||
"OIDC_SETNAMECONTENT": "在通过第三方(OIDC)进行身份验证时,您必须第一次创建一个Harbor用户名。这将在端口中用于与项目、角色等关联。",
|
||||
"OIDC_USERNAME": "用户名"
|
||||
},
|
||||
"SCANNING": {
|
||||
"TRIGGER_SCAN_ALL_SUCCESS": "启动扫描所有镜像任务成功!",
|
||||
|
Loading…
Reference in New Issue
Block a user