Fix issues with label target 2.1 and RC

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
AllForNothing 2020-08-19 12:37:37 +08:00
parent eb317fb8cb
commit 56083cd5c9
15 changed files with 95 additions and 52 deletions

View File

@ -402,6 +402,7 @@
<clr-checkbox-wrapper>
<input type="checkbox" clrCheckbox name="oidcAutoOnboard" id="oidcAutoOnboard"
[disabled]="disabled(currentConfig.oidc_auto_onboard)"
(change)="changeAutoOnBoard()"
[(ngModel)]="currentConfig.oidc_auto_onboard.value" />
</clr-checkbox-wrapper>
</clr-checkbox-container>
@ -414,9 +415,9 @@
</clr-tooltip-content>
</clr-tooltip>
</label>
<input clrInput name="oidcUserClaim" type="text" #oidcUserClaimInput="ngModel"
<input autocomplete="off" clrInput name="oidcUserClaim" type="text" #oidcUserClaimInput="ngModel"
[(ngModel)]="currentConfig.oidc_user_claim.value" id="oidcUserClaim" size="40"
[disabled]="disabled(currentConfig.oidc_user_claim)" pattern="^[a-zA-Z0-9_-]*$">
[disabled]="!currentConfig.oidc_auto_onboard.value || disabled(currentConfig.oidc_user_claim)" pattern="^[a-zA-Z0-9_-]*$">
</clr-input-container>
<div class="oidc-tip">{{ 'CONFIG.OIDC.OIDC_REDIREC_URL' | translate}}
<span>{{redirectUrl}}/c/oidc/callback</span>
@ -431,4 +432,4 @@
<button type="button" id="ping-test" class="btn btn-outline" (click)="pingTestServer()" *ngIf="showTestingServerBtn"
[disabled]="!isConfigValidForTesting()">{{(showLdap?'BUTTON.TEST_LDAP':'BUTTON.TEST_OIDC') | translate}}</button>
<span id="forTestingLDAP" class="spinner spinner-inline" [hidden]="hideTestingSpinner"></span>
</div>
</div>

View File

@ -263,5 +263,9 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
console.error('Nothing changed');
}
}
changeAutoOnBoard() {
if (!this.currentConfig.oidc_auto_onboard.value) {
this.currentConfig.oidc_user_claim.value = null;
}
}
}

View File

@ -80,33 +80,6 @@
<clr-dg-cell>{{ instance.endpoint }}</clr-dg-cell>
<clr-dg-cell class="no-wrapper">
<span>{{ instance.vendor }}</span>
<clr-signpost *ngIf="providerMap[instance.vendor]">
<clr-signpost-content *clrIfOpen>
<div>
<span>
<img (error)="showDefaultIcon($event, instance.vendor)" class="height-24" [src]="providerMap[instance.vendor].icon">
</span>
</div>
<div class="margin-top-5px">
<span>{{'DISTRIBUTION.NAME' | translate}}:</span>
<span class="ml-1">{{providerMap[instance.vendor].name}}</span>
</div>
<div class="margin-top-5px">
<span class="no-wrapper">
<span>{{'DISTRIBUTION.MAINTAINER' | translate}}:</span>
<span class="ml-1">{{providerMap[instance.vendor].maintainers?.join(',')}}</span>
</span>
</div>
<div class="margin-top-5px">
<span>{{'DISTRIBUTION.SOURCE' | translate}}:</span>
<a target="_blank" href="{{providerMap[instance.vendor].source}}" class="ml-1">{{providerMap[instance.vendor].source}}</a>
</div>
<div class="margin-top-5px">
<span>{{'DISTRIBUTION.VERSION' | translate}}:</span>
<span class="ml-1">{{providerMap[instance.vendor].version}}</span>
</div>
</clr-signpost-content>
</clr-signpost>
</clr-dg-cell>
<clr-dg-cell>
<span *ngIf="!instance.hasCheckHealth;else elseBlockLoading" class="spinner spinner-inline ml-2"></span>

View File

@ -7,7 +7,7 @@
<clr-icon shape="download"></clr-icon>
{{'CONFIG.REGISTRY_CERTIFICATE' | translate | uppercase}}
</a>
<hbr-push-image-button class="push-image-button" *ngIf="hasCreateRepositoryPermission" [registryUrl]="registryUrl" [projectName]="projectName"></hbr-push-image-button>
<hbr-push-image-button class="push-image-button" *ngIf="hasCreateRepositoryPermission && !isProxyCacheProject" [registryUrl]="registryUrl" [projectName]="projectName"></hbr-push-image-button>
<hbr-filter [withDivider]="true" filterPlaceholder="{{'REPOSITORY.FILTER_FOR_REPOSITORIES' | translate}}" [currentValue]="lastFilteredRepoName"></hbr-filter>
<span class="card-btn" (click)="showCard(true)" (mouseenter) ="mouseEnter('card') " (mouseleave) ="mouseLeave('card')">
<clr-icon [ngClass]="{'is-highlight': isCardView || isHovering('card') }" shape="view-cards"></clr-icon>

View File

@ -93,6 +93,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit, OnDestroy
@ViewChild(FilterComponent, {static: true})
filterComponent: FilterComponent;
searchSub: Subscription;
isProxyCacheProject: boolean = false;
constructor(@Inject(SERVICE_CONFIG) private configInfo: IServiceConfig,
private errorHandlerService: ErrorHandler,
@ -139,6 +140,9 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit, OnDestroy
let pro: Project = <Project>resolverData['projectResolver'];
this.hasProjectAdminRole = pro.has_project_admin_role;
this.projectName = pro.name;
if (pro.registry_id) {
this.isProxyCacheProject = true;
}
}
this.hasSignedIn = this.session.getCurrentUser() !== null;
// Get system info for tag views

View File

@ -29,7 +29,8 @@
</clr-checkbox-wrapper>
</div>
<div [class.visibility-hidden]="!isError" class="error active">
{{ 'SIGN_IN.INVALID_MSG' | translate }}
<span *ngIf="isCoreServiceAvailable">{{ 'SIGN_IN.INVALID_MSG' | translate }}</span>
<span *ngIf="!isCoreServiceAvailable">{{ 'SIGN_IN.CORE_SERVICE_NOT_AVAILABLE' | translate }}</span>
</div>
<button [disabled]="isOnGoing || !isValid" type="submit" class="btn btn-primary" (click)="signIn()" id="log_in">{{ 'BUTTON.LOG_IN' | translate }}</button>
<a href="javascript:void(0)" class="signup" (click)="signUp()" *ngIf="selfSignUp">{{ 'BUTTON.SIGN_UP_LINK' | translate }}</a>
@ -44,4 +45,4 @@
</div>
</clr-main-container>
<sign-up #signupDialog (userCreation)="handleUserCreation($event)"></sign-up>
<about-dialog></about-dialog>
<about-dialog></about-dialog>

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, getTestBed, inject, TestBed } from '@angular/core/testing';
import { SignInComponent } from './sign-in.component';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { RouterTestingModule } from '@angular/router/testing';
@ -10,11 +10,18 @@ import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { ClarityModule } from "@clr/angular";
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { of } from "rxjs";
import { throwError as observableThrowError } from 'rxjs/internal/observable/throwError';
import { HttpErrorResponse } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('SignInComponent', () => {
let component: SignInComponent;
let fixture: ComponentFixture<SignInComponent>;
const mockedSessionService = {
signIn() {
return of(true);
}
};
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
@ -22,12 +29,13 @@ describe('SignInComponent', () => {
RouterTestingModule,
ClarityModule,
FormsModule,
ReactiveFormsModule
ReactiveFormsModule,
HttpClientTestingModule
],
declarations: [SignInComponent],
providers: [
TranslateService,
{ provide: SessionService, useValue: null },
{ provide: SessionService, useValue: mockedSessionService},
{
provide: AppConfigService, useValue: {
load: function () {
@ -68,4 +76,44 @@ describe('SignInComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should show core service is not available', async () => {
expect(component).toBeTruthy();
const sessionService = TestBed.get<SessionService>(SessionService);
const spy: jasmine.Spy = spyOn(sessionService, "signIn").and.returnValue(observableThrowError( new HttpErrorResponse({
error: 'test 501 error',
status: 501
})));
signIn();
fixture.detectChanges();
await fixture.whenStable();
expect(spy.calls.count()).toEqual(1);
const errorSpan: HTMLSpanElement = fixture.nativeElement.querySelector(".error>span");
expect(errorSpan.innerText).toEqual('SIGN_IN.CORE_SERVICE_NOT_AVAILABLE');
});
it('should show invalid username or password', async () => {
expect(component).toBeTruthy();
const sessionService = TestBed.get<SessionService>(SessionService);
const spy: jasmine.Spy = spyOn(sessionService, "signIn").and.returnValue(observableThrowError( new HttpErrorResponse({
error: 'test 404 error',
status: 404,
statusText: 'Not Found'
})));
signIn();
fixture.detectChanges();
await fixture.whenStable();
expect(spy.calls.count()).toEqual(1);
const errorSpan: HTMLSpanElement = fixture.nativeElement.querySelector(".error>span");
expect(errorSpan.innerText).toEqual('SIGN_IN.INVALID_MSG');
});
function signIn() {
const nameInput: HTMLInputElement = fixture.nativeElement.querySelector("#login_username");
nameInput.value = "admin";
nameInput.dispatchEvent(new Event('input'));
const passwordInput: HTMLInputElement = fixture.nativeElement.querySelector("#login_password");
passwordInput.value = "Harbor12345";
passwordInput.dispatchEvent(new Event('input'));
const signButton: HTMLAnchorElement = fixture.nativeElement.querySelector("#log_in");
signButton.click();
}
});

View File

@ -66,7 +66,7 @@ export class SignInComponent implements AfterViewChecked, OnInit {
principal: "",
password: ""
};
isCoreServiceAvailable: boolean = true;
constructor(
private router: Router,
private session: SessionService,
@ -254,6 +254,7 @@ export class SignInComponent implements AfterViewChecked, OnInit {
} else {
this.router.navigateByUrl(this.redirectUrl);
}
this.isCoreServiceAvailable = true;
}, error => {
// 403 oidc login no body;
if (this.isOidcLoginMode && error && error.status === 403) {
@ -265,6 +266,10 @@ export class SignInComponent implements AfterViewChecked, OnInit {
return;
} catch (error) { }
}
// core service is not available for error code 5xx
if (error && /5[0-9][0-9]/.test(error.status)) {
this.isCoreServiceAvailable = false;
}
this.handleError(error);
});
}

View File

@ -13,7 +13,8 @@
"REMEMBER": "Remember me",
"INVALID_MSG": "Invalid user name or password.",
"FORGOT_PWD": "Forgot password",
"HEADER_LINK": "Sign In"
"HEADER_LINK": "Sign In",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "Sign Up"
@ -247,7 +248,7 @@
"QUOTA_UNLIMIT_TIP": "For unlimited quota enter '-1'.",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},

View File

@ -13,7 +13,8 @@
"REMEMBER": "Recordarme",
"INVALID_MSG": "Nombre o contraseña no válidos.",
"FORGOT_PWD": "Olvidé mi contraseña",
"HEADER_LINK": "Identificarse"
"HEADER_LINK": "Identificarse",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "Registrarse"
@ -248,7 +249,7 @@
"QUOTA_UNLIMIT_TIP": "For unlimited quota enter '-1'.",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},

View File

@ -13,7 +13,8 @@
"REMEMBER": "Se souvenir de moi",
"INVALID_MSG": "Nom d'utilisateur ou mot de passe invalide.",
"FORGOT_PWD": "Mot de passe oublié",
"HEADER_LINK": "S'identifier"
"HEADER_LINK": "S'identifier",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "S'inscrire"
@ -241,7 +242,7 @@
"QUOTA_UNLIMIT_TIP": "For unlimited quota enter '-1'.",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},

View File

@ -13,7 +13,8 @@
"REMEMBER": "Lembrar-se de mim",
"INVALID_MSG": "Usuário ou senha inválidos",
"FORGOT_PWD": "Esqueci a senha",
"HEADER_LINK": "Logar-se"
"HEADER_LINK": "Logar-se",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "Registrar-se"
@ -245,7 +246,7 @@
"QUOTA_UNLIMIT_TIP": "For unlimited quota enter '-1'.",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},

View File

@ -13,7 +13,8 @@
"REMEMBER": "Beni Hatırla",
"INVALID_MSG": "Geçersiz kullanıcı adı veya şifre.",
"FORGOT_PWD": "Parolamı Unuttum",
"HEADER_LINK": "Oturum aç"
"HEADER_LINK": "Oturum aç",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "Kayıt ol"
@ -247,7 +248,7 @@
"QUOTA_UNLIMIT_TIP": "Bu kotayı sınırsız istiyorsanız, lütfen -1 girin.",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},

View File

@ -13,7 +13,8 @@
"REMEMBER": "记住我",
"INVALID_MSG": "用户名或者密码不正确。",
"FORGOT_PWD": "忘记密码",
"HEADER_LINK": "登录"
"HEADER_LINK": "登录",
"CORE_SERVICE_NOT_AVAILABLE": "核心服务不可用。"
},
"SIGN_UP": {
"TITLE": "注册"

View File

@ -13,7 +13,8 @@
"REMEMBER": "記住我",
"INVALID_MSG": "用戶名或者密碼不正確。",
"FORGOT_PWD": "忘記密碼",
"HEADER_LINK": "登錄"
"HEADER_LINK": "登錄",
"CORE_SERVICE_NOT_AVAILABLE": "Core service is not available."
},
"SIGN_UP": {
"TITLE": "註冊"
@ -244,7 +245,7 @@
"QUOTA_UNLIMIT_TIP": "如果你想要對存儲不設置上限,請輸入-1。",
"TYPE": "Type",
"PROXY_CACHE": "Proxy Cache",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular namespace within a target registry. Harbor can only act a proxy for DockerHub and Harbor registries.",
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub and Harbor registries.",
"ENDPOINT": "Endpoint",
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
},