mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 00:57:44 +01:00
Fix issues with label target 2.1 and RC
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
eb317fb8cb
commit
56083cd5c9
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -13,7 +13,8 @@
|
||||
"REMEMBER": "记住我",
|
||||
"INVALID_MSG": "用户名或者密码不正确。",
|
||||
"FORGOT_PWD": "忘记密码",
|
||||
"HEADER_LINK": "登录"
|
||||
"HEADER_LINK": "登录",
|
||||
"CORE_SERVICE_NOT_AVAILABLE": "核心服务不可用。"
|
||||
},
|
||||
"SIGN_UP": {
|
||||
"TITLE": "注册"
|
||||
|
@ -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"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user