mirror of
https://github.com/goharbor/harbor.git
synced 2025-01-11 10:27:58 +01:00
fix issue about no warn when deleting repository which contains signed tags, 3022
This commit is contained in:
parent
78e1f8c8ce
commit
160593a86a
@ -23,7 +23,7 @@ export const REPOSITORY_STACKVIEW_TEMPLATE: string = `
|
||||
<clr-dg-cell>{{r.name}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{r.tags_count}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{r.pull_count}}</clr-dg-cell>
|
||||
<hbr-tag *clrIfExpanded ngProjectAs="clr-dg-row-detail" (tagClickEvent)="watchTagClickEvt($event)" class="sub-grid-custom" [repoName]="r.name" [registryUrl]="registryUrl" [withNotary]="withNotary" [withClair]="withClair" [hasSignedIn]="hasSignedIn" [hasProjectAdminRole]="hasProjectAdminRole" [projectId]="projectId" [isEmbedded]="true"></hbr-tag>
|
||||
<hbr-tag *clrIfExpanded ngProjectAs="clr-dg-row-detail" (tagClickEvent)="watchTagClickEvt($event)" (signatureOutput)="saveSignatures($event)" class="sub-grid-custom" [repoName]="r.name" [registryUrl]="registryUrl" [withNotary]="withNotary" [withClair]="withClair" [hasSignedIn]="hasSignedIn" [hasProjectAdminRole]="hasProjectAdminRole" [projectId]="projectId" [isEmbedded]="true"></hbr-tag>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
<span *ngIf="showDBStatusWarning" class="db-status-warning">
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
ViewChild,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
EventEmitter
|
||||
EventEmitter, OnChanges, SimpleChanges
|
||||
} from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Comparator } from 'clarity-angular';
|
||||
@ -41,6 +41,7 @@ import {
|
||||
doFiltering,
|
||||
doSorting
|
||||
} from '../utils';
|
||||
import {TagService} from '../service/index';
|
||||
|
||||
@Component({
|
||||
selector: 'hbr-repository-stackview',
|
||||
@ -48,7 +49,8 @@ import {
|
||||
styles: [REPOSITORY_STACKVIEW_STYLES],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class RepositoryStackviewComponent implements OnInit {
|
||||
export class RepositoryStackviewComponent implements OnChanges, OnInit {
|
||||
signedCon: {[key: string]: any | string[]} = {};
|
||||
|
||||
@Input() projectId: number;
|
||||
@Input() projectName: string = "unknown";
|
||||
@ -80,6 +82,8 @@ export class RepositoryStackviewComponent implements OnInit {
|
||||
private translateService: TranslateService,
|
||||
private repositoryService: RepositoryService,
|
||||
private systemInfoService: SystemInfoService,
|
||||
private translate: TranslateService,
|
||||
private tagService: TagService,
|
||||
private ref: ChangeDetectorRef) { }
|
||||
|
||||
public get registryUrl(): string {
|
||||
@ -122,15 +126,24 @@ export class RepositoryStackviewComponent implements OnInit {
|
||||
}
|
||||
this.translateService.get('REPOSITORY.DELETED_REPO_SUCCESS')
|
||||
.subscribe(res => this.errorHandler.info(res));
|
||||
}).catch(error => this.errorHandler.error(error));
|
||||
}).catch(error => {
|
||||
if (error.status === "412"){
|
||||
this.translateService.get('REPOSITORY.TAGS_SIGNED')
|
||||
.subscribe(res => this.errorHandler.info(res));
|
||||
return;
|
||||
}
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes['projectId']) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.projectId) {
|
||||
this.errorHandler.error('Project ID cannot be unset.');
|
||||
return;
|
||||
}
|
||||
//Get system info for tag views
|
||||
toPromise<SystemInfo>(this.systemInfoService.getSystemInfo())
|
||||
.then(systemInfo => this.systemInfo = systemInfo)
|
||||
@ -153,15 +166,67 @@ export class RepositoryStackviewComponent implements OnInit {
|
||||
this.clrLoad(st);
|
||||
}
|
||||
|
||||
saveSignatures(event: {[key: string]: string[]}): void {
|
||||
Object.assign(this.signedCon, event);
|
||||
}
|
||||
|
||||
deleteRepo(repoName: string) {
|
||||
let message = new ConfirmationMessage(
|
||||
'REPOSITORY.DELETION_TITLE_REPO',
|
||||
'REPOSITORY.DELETION_SUMMARY_REPO',
|
||||
repoName,
|
||||
repoName,
|
||||
ConfirmationTargets.REPOSITORY,
|
||||
ConfirmationButtons.DELETE_CANCEL);
|
||||
this.confirmationDialog.open(message);
|
||||
// get children tags data
|
||||
|
||||
let signature: string = '';
|
||||
if (this.signedCon[repoName]) {
|
||||
if (this.signedCon[repoName].length === 0) {
|
||||
this.confirmationDialogSet('DELETION_TITLE_REPO', signature, repoName, 'REPOSITORY.DELETION_SUMMARY_REPO', ConfirmationButtons.DELETE_CANCEL);
|
||||
return;
|
||||
}
|
||||
signature = this.signedCon[repoName].join(',');
|
||||
this.confirmationDialogSet('DELETION_TITLE_REPO_SIGNED', signature, repoName, 'REPOSITORY.DELETION_SUMMARY_REPO_SIGNED', ConfirmationButtons.CLOSE);
|
||||
} else {
|
||||
this.getTagInfo(repoName).then(() => {
|
||||
if (this.signedCon[repoName].length) {
|
||||
signature = this.signedCon[repoName].join(',');
|
||||
this.confirmationDialogSet('DELETION_TITLE_REPO_SIGNED', signature, repoName, 'REPOSITORY.DELETION_SUMMARY_REPO_SIGNED', ConfirmationButtons.CLOSE);
|
||||
} else {
|
||||
this.confirmationDialogSet('DELETION_TITLE_REPO', signature, repoName, 'REPOSITORY.DELETION_SUMMARY_REPO', ConfirmationButtons.DELETE_CANCEL);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
getTagInfo(repoName: string): Promise<void> {
|
||||
// this.signedNameArr = [];
|
||||
this.signedCon[repoName] = [];
|
||||
return toPromise<Tag[]>(this.tagService
|
||||
.getTags(repoName))
|
||||
.then(items => {
|
||||
items.forEach((t: Tag) => {
|
||||
if (t.signature !== null) {
|
||||
this.signedCon[repoName].push(t.name);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
|
||||
confirmationDialogSet(summaryTitle: string, signature: string, repoName: string, summaryKey: string, button: ConfirmationButtons): void {
|
||||
this.translate.get(summaryKey,
|
||||
{
|
||||
repoName: repoName,
|
||||
signedImages: signature,
|
||||
})
|
||||
.subscribe((res: string) => {
|
||||
summaryKey = res;
|
||||
let message = new ConfirmationMessage(
|
||||
summaryTitle,
|
||||
summaryKey,
|
||||
repoName,
|
||||
repoName,
|
||||
ConfirmationTargets.REPOSITORY,
|
||||
button);
|
||||
this.confirmationDialog.open(message);
|
||||
|
||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
||||
setTimeout(() => clearInterval(hnd), 5000);
|
||||
});
|
||||
}
|
||||
|
||||
refresh() {
|
||||
@ -194,6 +259,7 @@ export class RepositoryStackviewComponent implements OnInit {
|
||||
this.totalCount = repo.metadata.xTotalCount;
|
||||
this.repositories = repo.data;
|
||||
|
||||
this.signedCon = {};
|
||||
//Do filtering and sorting
|
||||
this.repositories = doFiltering<RepositoryItem>(this.repositories, state);
|
||||
this.repositories = doSorting<RepositoryItem>(this.repositories, state);
|
||||
@ -231,4 +297,5 @@ export class RepositoryStackviewComponent implements OnInit {
|
||||
|
||||
return st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,10 +71,11 @@ export class TagComponent implements OnInit {
|
||||
|
||||
@Output() refreshRepo = new EventEmitter<boolean>();
|
||||
@Output() tagClickEvent = new EventEmitter<TagClickEvent>();
|
||||
@Output() signatureOutput = new EventEmitter<any>();
|
||||
|
||||
|
||||
tags: Tag[];
|
||||
|
||||
|
||||
showTagManifestOpened: boolean;
|
||||
manifestInfoTitle: string;
|
||||
digestId: string;
|
||||
@ -136,6 +137,7 @@ export class TagComponent implements OnInit {
|
||||
|
||||
retrieve() {
|
||||
this.tags = [];
|
||||
let signatures: string[] = [] ;
|
||||
this.loading = true;
|
||||
|
||||
toPromise<Tag[]>(this.tagService
|
||||
@ -151,11 +153,17 @@ export class TagComponent implements OnInit {
|
||||
components: {
|
||||
total: 0,
|
||||
summary: []
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
this.tags = items;
|
||||
}
|
||||
};
|
||||
}
|
||||
if (t.signature !== null) {
|
||||
signatures.push(t.name);
|
||||
}
|
||||
});
|
||||
this.tags = items;
|
||||
let signedName: {[key: string]: string[]} = {};
|
||||
signedName[this.repoName] = signatures;
|
||||
this.signatureOutput.emit(signedName);
|
||||
this.loading = false;
|
||||
if (this.tags && this.tags.length === 0) {
|
||||
this.refreshRepo.emit(true);
|
||||
|
@ -321,6 +321,8 @@
|
||||
"MY_REPOSITORY": "My Repository",
|
||||
"PUBLIC_REPOSITORY": "Public Repository",
|
||||
"DELETION_TITLE_REPO": "Confirm Repository Deletion",
|
||||
"DELETION_TITLE_REPO_SIGNED": "Repository cannot be deleted",
|
||||
"DELETION_SUMMARY_REPO_SIGNED": "Repository '{{repoName}}' cannot be deleted because the following signed images existing.\n{{signedImages}} \nYou should unsign all the signed images before deleting the repository!",
|
||||
"DELETION_SUMMARY_REPO": "Do you want to delete repository {{param}}?",
|
||||
"DELETION_TITLE_TAG": "Confirm Tag Deletion",
|
||||
"DELETION_SUMMARY_TAG": "Do you want to delete tag {{param}}?",
|
||||
|
@ -322,6 +322,8 @@
|
||||
"MY_REPOSITORY": "Mi Repositorio",
|
||||
"PUBLIC_REPOSITORY": "Repositorio Público",
|
||||
"DELETION_TITLE_REPO": "Confirmar Eliminación de Repositorio",
|
||||
"DELETION_TITLE_REPO_SIGNED": "Repository cannot be deleted",
|
||||
"DELETION_SUMMARY_REPO_SIGNED": "Repository '{{repoName}}' cannot be deleted because the following signed images existing.\n{{signedImages}} \nYou should unsign all the signed images before deleting the repository!",
|
||||
"DELETION_SUMMARY_REPO": "¿Quiere eliminar el repositorio {{param}}?",
|
||||
"DELETION_TITLE_TAG": "Confirmación de Eliminación de Etiqueta",
|
||||
"DELETION_SUMMARY_TAG": "¿Quiere eliminar la etiqueta {{param}}?",
|
||||
|
@ -321,6 +321,8 @@
|
||||
"MY_REPOSITORY": "我的仓库",
|
||||
"PUBLIC_REPOSITORY": "公共仓库",
|
||||
"DELETION_TITLE_REPO": "删除镜像仓库确认",
|
||||
"DELETION_TITLE_REPO_SIGNED": "仓库不能被删除",
|
||||
"DELETION_SUMMARY_REPO_SIGNED": "镜像仓库 '{{repoName}}' 不能被删除,因为存在以下签名镜像.\n{{signedImages}} \n在删除镜像仓库前需先删除所有的签名镜像",
|
||||
"DELETION_SUMMARY_REPO": "确认删除镜像仓库 {{param}}?",
|
||||
"DELETION_TITLE_TAG": "删除镜像标签确认",
|
||||
"DELETION_SUMMARY_TAG": "确认删除镜像标签 {{param}}?",
|
||||
|
Loading…
Reference in New Issue
Block a user