diff --git a/src/portal/lib/src/shared/shared.const.ts b/src/portal/lib/src/shared/shared.const.ts index a74ed9b16..84a22b8b7 100644 --- a/src/portal/lib/src/shared/shared.const.ts +++ b/src/portal/lib/src/shared/shared.const.ts @@ -93,7 +93,9 @@ export const LabelColor = [ export const CONFIG_AUTH_MODE = { HTTP_AUTH: "http_auth", - LDAP_AUTH: "ldap_auth" + LDAP_AUTH: "ldap_auth", + OIDC_AUTH: "oidc_auth", + UAA_AUTH: "uaa_auth" }; export const PROJECT_ROOTS = [ { diff --git a/src/portal/src/app/config/auth/config-auth.component.html b/src/portal/src/app/config/auth/config-auth.component.html index e055e7212..0371c13bf 100644 --- a/src/portal/src/app/config/auth/config-auth.component.html +++ b/src/portal/src/app/config/auth/config-auth.component.html @@ -423,7 +423,7 @@ [disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE' | translate}} - - + + diff --git a/src/portal/src/app/config/auth/config-auth.component.ts b/src/portal/src/app/config/auth/config-auth.component.ts index d05e2c770..a096a8a23 100644 --- a/src/portal/src/app/config/auth/config-auth.component.ts +++ b/src/portal/src/app/config/auth/config-auth.component.ts @@ -15,7 +15,8 @@ import { Component, Input, ViewChild, SimpleChanges, OnChanges, OnInit, Output, import { NgForm } from '@angular/forms'; import { Subscription } from "rxjs"; -import { Configuration, clone, isEmpty, getChanges, StringValueItem, BoolValueItem, SystemInfoService, ErrorHandler } from '@harbor/ui'; +import { Configuration, clone, isEmpty, getChanges, StringValueItem, BoolValueItem, SystemInfoService, ErrorHandler + , CONFIG_AUTH_MODE } from '@harbor/ui'; import { MessageHandlerService } from '../../shared/message-handler/message-handler.service'; import { ConfirmMessageHandler } from '../config.msg.utils'; import { AppConfigService } from '../../app-config.service'; @@ -30,7 +31,7 @@ const fakePass = 'aWpLOSYkIzJTTU4wMDkx'; }) export class ConfigurationAuthComponent implements OnChanges, OnInit { changeSub: Subscription; - testingLDAPOnGoing = false; + testingOnGoing = false; onGoing = false; redirectUrl: string; // tslint:disable-next-line:no-input-rename @@ -72,24 +73,26 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit { public get showLdap(): boolean { return this.currentConfig && this.currentConfig.auth_mode && - this.currentConfig.auth_mode.value === 'ldap_auth'; + this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.LDAP_AUTH; } public get showUAA(): boolean { - return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === 'uaa_auth'; + return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.UAA_AUTH; } public get showOIDC(): boolean { - return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === 'oidc_auth'; + return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.OIDC_AUTH; } public get showHttpAuth(): boolean { - return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === 'http_auth'; + return this.currentConfig && this.currentConfig.auth_mode && this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.HTTP_AUTH; } public get showSelfReg(): boolean { if (!this.currentConfig || !this.currentConfig.auth_mode) { return true; } else { - return this.currentConfig.auth_mode.value !== 'ldap_auth' && this.currentConfig.auth_mode.value !== 'uaa_auth' - && this.currentConfig.auth_mode.value !== 'http_auth' && this.currentConfig.auth_mode.value !== 'oidc_auth'; + return this.currentConfig.auth_mode.value !== CONFIG_AUTH_MODE.LDAP_AUTH + && this.currentConfig.auth_mode.value !== CONFIG_AUTH_MODE.UAA_AUTH + && this.currentConfig.auth_mode.value !== CONFIG_AUTH_MODE.HTTP_AUTH + && this.currentConfig.auth_mode.value !== CONFIG_AUTH_MODE.OIDC_AUTH; } } @@ -105,52 +108,74 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit { this.currentConfig.ldap_verify_cert.value = $event; } - public testLDAPServer(): void { - if (this.testingLDAPOnGoing) { + public pingTestServer(): void { + if (this.testingOnGoing) { return; // Should not come here } - let ldapSettings = {}; - for (let prop in this.currentConfig) { - if (prop.startsWith('ldap_')) { - ldapSettings[prop] = this.currentConfig[prop].value; - } - } + let settings = {}; + if (this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.LDAP_AUTH) { - let allChanges = this.getChanges(); - let ldapSearchPwd = allChanges['ldap_search_password']; - if (ldapSearchPwd) { - ldapSettings['ldap_search_password'] = ldapSearchPwd; - } else { - delete ldapSettings['ldap_search_password']; - } - - // Fix: Confirm ldap scope is number - ldapSettings['ldap_scope'] = +ldapSettings['ldap_scope']; - - this.testingLDAPOnGoing = true; - this.configService.testLDAPServer(ldapSettings) - .subscribe(respone => { - this.testingLDAPOnGoing = false; - this.msgHandler.showSuccess('CONFIG.TEST_LDAP_SUCCESS'); - }, error => { - this.testingLDAPOnGoing = false; - let err = error.error; - if (!err || !err.trim()) { - err = 'UNKNOWN'; + for (let prop in this.currentConfig) { + if (prop.startsWith('ldap_')) { + settings[prop] = this.currentConfig[prop].value; } - this.msgHandler.showError('CONFIG.TEST_LDAP_FAILED', { 'param': err }); - }); + } + + let allChanges = this.getChanges(); + this.testingOnGoing = true; + // set password for ldap + let ldapSearchPwd = allChanges['ldap_search_password']; + if (ldapSearchPwd) { + settings['ldap_search_password'] = ldapSearchPwd; + } else { + delete settings['ldap_search_password']; + } + + // Fix: Confirm ldap scope is number + settings['ldap_scope'] = +settings['ldap_scope']; + + this.configService.testLDAPServer(settings) + .subscribe(respone => { + this.testingOnGoing = false; + this.msgHandler.showSuccess('CONFIG.TEST_LDAP_SUCCESS'); + }, error => { + this.testingOnGoing = false; + let err = error.error; + if (!err || !err.trim()) { + err = 'UNKNOWN'; + } + this.msgHandler.showError('CONFIG.TEST_LDAP_FAILED', { 'param': err }); + }); + } else { + for (let prop in this.currentConfig) { + if (prop === 'oidc_endpoint') { + settings['url'] = this.currentConfig[prop].value; + } else if (prop === 'oidc_verify_cert') { + settings['verify_cert'] = this.currentConfig[prop].value; + } + } + this.configService.testOIDCServer(settings) + .subscribe(respone => { + this.testingOnGoing = false; + this.msgHandler.showSuccess('CONFIG.TEST_OIDC_SUCCESS'); + }, error => { + this.testingOnGoing = false; + this.errorHandler.error(error); + }); + } + } - public get showLdapServerBtn(): boolean { + public get showTestingServerBtn(): boolean { return this.currentConfig.auth_mode && - this.currentConfig.auth_mode.value === 'ldap_auth'; + (this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.LDAP_AUTH + || this.currentConfig.auth_mode.value === CONFIG_AUTH_MODE.OIDC_AUTH); } - public isLDAPConfigValid(): boolean { + public isConfigValidForTesting(): boolean { return this.isValid() && - !this.testingLDAPOnGoing; + !this.testingOnGoing; } public getChanges() { @@ -171,8 +196,8 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit { return changes; } - public get hideLDAPTestingSpinner(): boolean { - return !this.testingLDAPOnGoing || !this.showLdapServerBtn; + public get hideTestingSpinner(): boolean { + return !this.testingOnGoing || !this.showTestingServerBtn; } disabled(prop: any): boolean { @@ -182,7 +207,8 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit { handleOnChange($event: any): void { if ($event && $event.target && $event.target["value"]) { let authMode = $event.target["value"]; - if (authMode === 'ldap_auth' || authMode === 'uaa_auth' || authMode === 'http_auth' || authMode === 'oidc_auth') { + if (authMode === CONFIG_AUTH_MODE.LDAP_AUTH || authMode === CONFIG_AUTH_MODE.UAA_AUTH || authMode === CONFIG_AUTH_MODE.HTTP_AUTH + || authMode === CONFIG_AUTH_MODE.OIDC_AUTH) { if (this.currentConfig.self_registration.value) { this.currentConfig.self_registration.value = false; // unselect } diff --git a/src/portal/src/app/config/config.service.ts b/src/portal/src/app/config/config.service.ts index fd10c2756..3197c5006 100644 --- a/src/portal/src/app/config/config.service.ts +++ b/src/portal/src/app/config/config.service.ts @@ -22,6 +22,7 @@ import { Configuration, HTTP_GET_OPTIONS, HTTP_JSON_OPTIONS } from '@harbor/ui'; const configEndpoint = "/api/configurations"; const emailEndpoint = "/api/email/ping"; const ldapEndpoint = "/api/ldap/ping"; +const oidcEndpoint = "/api/system/oidc/ping"; @Injectable() export class ConfigurationService { @@ -51,4 +52,8 @@ export class ConfigurationService { .pipe(map(response => response) , catchError(error => observableThrowError(error))); } + public testOIDCServer(oidcSettings: any): Observable { + return this.http.post(oidcEndpoint, JSON.stringify(oidcSettings), HTTP_JSON_OPTIONS) + .pipe(catchError(error => observableThrowError(error))); + } } diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 93bb2c978..54bdacc87 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -31,6 +31,7 @@ "TEST_MAIL": "TEST MAIL SERVER", "CLOSE": "CLOSE", "TEST_LDAP": "TEST LDAP SERVER", + "TEST_OIDC": "TEST OIDC SERVER", "MORE_INFO": "More info...", "YES": "YES", "NO": "NO", @@ -813,7 +814,8 @@ "TEST_MAIL_FAILED": "Failed to verify mail server with error: {{param}}.", "TEST_LDAP_FAILED": "Failed to verify LDAP server with error: {{param}}.", "LEAVING_CONFIRMATION_TITLE": "Confirm to leave", - "LEAVING_CONFIRMATION_SUMMARY": "Changes have not been saved yet. Do you want to leave current page?" + "LEAVING_CONFIRMATION_SUMMARY": "Changes have not been saved yet. Do you want to leave current page?", + "TEST_OIDC_SUCCESS": "Connection to OIDC server is verified." }, "PAGE_NOT_FOUND": { "MAIN_TITLE": "Page not found", diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index e3a9c2e62..9ada37c03 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -31,6 +31,7 @@ "TEST_MAIL": "COMPROBAR SERVIDOR DE CORREO", "CLOSE": "CERRAR", "TEST_LDAP": "COMPROBAR SERVIDOR LDAP", + "TEST_OIDC": "TEST OIDC SERVER", "MORE_INFO": "Más información...", "YES": "SI", "NO": "NO", @@ -813,7 +814,8 @@ "TEST_MAIL_FAILED": "Fallo al verificar el servidor de correo con el error: {{param}}.", "TEST_LDAP_FAILED": "Fallo al verificar el servidor LDAP con el error: {{param}}.", "LEAVING_CONFIRMATION_TITLE": "Confirme la salida", - "LEAVING_CONFIRMATION_SUMMARY": "Los cambios no han sido guardados aún. ¿Quiere abandonar la página actual?" + "LEAVING_CONFIRMATION_SUMMARY": "Los cambios no han sido guardados aún. ¿Quiere abandonar la página actual?", + "TEST_OIDC_SUCCESS": "Connection to OIDC server is verified." }, "PAGE_NOT_FOUND": { "MAIN_TITLE": "Página no encontrada", diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index b0e6fc08b..68f27320b 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -31,6 +31,7 @@ "TEST_MAIL": "TESTER LE SERVEUR MAIL", "CLOSE": "FERMER", "TEST_LDAP": "TESTER LE SERVEUR LDAP", + "TEST_OIDC": "TEST OIDC SERVER", "MORE_INFO": "Plus d'informations...", "YES": "OUI", "NO": "NON", @@ -787,7 +788,8 @@ "TEST_MAIL_FAILED": "Echec de la vérification du serveur de mail avec erreurs : {{param}}.", "TEST_LDAP_FAILED": "Echec de la vérification du serveur LDAP avec erreurs : {{param}}.", "LEAVING_CONFIRMATION_TITLE": "Confirmer pour quitter", - "LEAVING_CONFIRMATION_SUMMARY": "Les modifications n'ont pas encore été enregistrées. Voulez-vous quitter la page actuelle ?" + "LEAVING_CONFIRMATION_SUMMARY": "Les modifications n'ont pas encore été enregistrées. Voulez-vous quitter la page actuelle ?", + "TEST_OIDC_SUCCESS": "Connection to OIDC server is verified." }, "PAGE_NOT_FOUND": { "MAIN_TITLE": "Page introuvable", diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index adbb68718..e15273b35 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -31,6 +31,7 @@ "TEST_MAIL": "TESTAR SERVIDOR DE EMAIL", "CLOSE": "FECHAR", "TEST_LDAP": "TESTAR SERVIDOR DE LDAP", + "TEST_OIDC": "TEST OIDC SERVER", "MORE_INFO": "Mais informações...", "YES": "SIM", "NO": "NÃO", @@ -807,7 +808,8 @@ "TEST_MAIL_FAILED": "Falha ao verificar servidor de Email com erro: {{param}}.", "TEST_LDAP_FAILED": "Falha ao verificar servidor de LDAP com erro: {{param}}.", "LEAVING_CONFIRMATION_TITLE": "Confirme para sair", - "LEAVING_CONFIRMATION_SUMMARY": "As alterações ainda não foram salvas. Você deseja sair da página atual?" + "LEAVING_CONFIRMATION_SUMMARY": "As alterações ainda não foram salvas. Você deseja sair da página atual?", + "TEST_OIDC_SUCCESS": "Connection to OIDC server is verified." }, "PAGE_NOT_FOUND": { "MAIN_TITLE": "Página não encontrada", diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index a1940bb8c..4c1fae9a4 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -31,6 +31,7 @@ "TEST_MAIL": "测试邮件服务器", "CLOSE": "关闭", "TEST_LDAP": "测试LDAP服务器", + "TEST_OIDC": "测试OIDC服务器", "MORE_INFO": "更多信息...", "YES": "是", "NO": "否", @@ -812,7 +813,8 @@ "TEST_MAIL_FAILED": "验证邮件服务器失败,错误: {{param}}。", "TEST_LDAP_FAILED": "验证LDAP服务器失败,错误: {{param}}。", "LEAVING_CONFIRMATION_TITLE": "确定离开", - "LEAVING_CONFIRMATION_SUMMARY": "有未保存的配置更改, 确认离开当前页面?" + "LEAVING_CONFIRMATION_SUMMARY": "有未保存的配置更改, 确认离开当前页面?", + "TEST_OIDC_SUCCESS": "OIDC服务器的连通正常。" }, "PAGE_NOT_FOUND": { "MAIN_TITLE": "页面不存在",