diff --git a/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list-tab/artifact-list-tab.component.ts b/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list-tab/artifact-list-tab.component.ts index 88cc0ee36..8d837d83b 100644 --- a/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list-tab/artifact-list-tab.component.ts +++ b/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list-tab/artifact-list-tab.component.ts @@ -34,7 +34,7 @@ import { clone, CustomComparator, DEFAULT_PAGE_SIZE, DEFAULT_SUPPORTED_MIME_TYPE, - formatSize, VULNERABILITY_SCAN_STATUS + formatSize, VULNERABILITY_SCAN_STATUS, dbEncodeURIComponent } from "../../../../../../lib/utils/utils"; import { ConfirmationAcknowledgement, @@ -335,7 +335,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { } if (this.artifactDigest) { const artifactParam: NewArtifactService.GetArtifactParams = { - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), projectName: this.projectName, reference: this.artifactDigest, withImmutableStatus: true, @@ -351,7 +351,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { res.references.forEach((child, index) => { if (index >= (pageNumber - 1) * this.pageSize && index < pageNumber * this.pageSize) { let childParams: NewArtifactService.GetArtifactParams = { - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), projectName: this.projectName, reference: child.child_digest, withImmutableStatus: true, @@ -378,7 +378,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { } else { let listArtifactParams: NewArtifactService.ListArtifactsParams = { projectName: this.projectName, - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), withLabel: true, withScanOverview: true, withTag: true @@ -480,7 +480,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { this.selectedRow = this.selectedTag; let params: NewArtifactService.AddLabelParams = { projectName: this.projectName, - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), reference: this.selectedRow[0].digest, label: labelInfo.label }; @@ -517,7 +517,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { this.selectedRow = this.selectedTag; let params: NewArtifactService.RemoveLabelParams = { projectName: this.projectName, - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), reference: this.selectedRow[0].digest, labelId: labelId }; @@ -675,18 +675,18 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { onRetag() { let params: NewArtifactService.CopyArtifactParams = { projectName: this.imageNameInput.projectName.value, - repositoryName: this.imageNameInput.repoName.value, + repositoryName: dbEncodeURIComponent(this.imageNameInput.repoName.value), from: `${this.projectName}/${this.repoName}@${this.selectedRow[0].digest}`, }; this.newArtifactService.CopyArtifact(params) .pipe(finalize(() => { - this.retagDialogOpened = false; this.imageNameInput.form.reset(); })) .subscribe(response => { this.translateService.get('RETAG.MSG_SUCCESS').subscribe((res: string) => { this.errorHandlerService.info(res); }); + this.retagDialogOpened = false; }, error => { this.errorHandlerService.error(error); }); @@ -779,7 +779,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy { // } else { let params: NewArtifactService.DeleteArtifactParams = { projectName: this.projectName, - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), reference: artifact.digest }; return this.newArtifactService diff --git a/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list.component.ts b/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list.component.ts index 7485c4191..89c4b4c3c 100644 --- a/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list.component.ts +++ b/src/portal/src/app/project/repository/artifact-list-page/artifact-list/artifact-list.component.ts @@ -27,6 +27,7 @@ import { Project } from '../../../project'; import { RepositoryService as NewRepositoryService } from "../../../../../../ng-swagger-gen/services/repository.service"; +import { dbEncodeURIComponent } from '../../../../../lib/utils/utils'; const TabLinkContentMap: { [index: string]: string } = { 'repo-info': 'info', 'repo-image': 'image' @@ -117,7 +118,7 @@ export class ArtifactListComponent implements OnInit { retrieve(state?: State) { let params: NewRepositoryService.GetRepositoryParams = { projectName: this.projectName, - repositoryName: this.repoName + repositoryName: dbEncodeURIComponent(this.repoName), }; this.newRepositoryService.getRepository(params) .subscribe(response => { @@ -168,7 +169,7 @@ export class ArtifactListComponent implements OnInit { } this.onGoing = true; let params: NewRepositoryService.UpdateRepositoryParams = { - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), repository: {description: this.imageInfo}, projectName: this.projectName, }; diff --git a/src/portal/src/app/project/repository/artifact/artifact-summary.component.ts b/src/portal/src/app/project/repository/artifact/artifact-summary.component.ts index f709b158b..809354c2d 100644 --- a/src/portal/src/app/project/repository/artifact/artifact-summary.component.ts +++ b/src/portal/src/app/project/repository/artifact/artifact-summary.component.ts @@ -8,6 +8,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { AppConfigService } from "../../../services/app-config.service"; import { Project } from "../../project"; import { finalize } from "rxjs/operators"; +import { dbEncodeURIComponent } from "../../../../lib/utils/utils"; @Component({ selector: "artifact-summary", @@ -87,7 +88,7 @@ export class ArtifactSummaryComponent implements OnInit { getArtifactDetails(): void { this.loading = true; this.artifactService.getArtifact({ - repositoryName: this.repositoryName, + repositoryName: dbEncodeURIComponent(this.repositoryName), reference: this.artifactDigest, projectName: this.projectName, withLabel: true, diff --git a/src/portal/src/app/project/repository/artifact/artifact-tag/artifact-tag.component.ts b/src/portal/src/app/project/repository/artifact/artifact-tag/artifact-tag.component.ts index d6ff1b532..f301d17c6 100644 --- a/src/portal/src/app/project/repository/artifact/artifact-tag/artifact-tag.component.ts +++ b/src/portal/src/app/project/repository/artifact/artifact-tag/artifact-tag.component.ts @@ -21,7 +21,7 @@ import { UserPermissionService, USERSTATICPERMISSION } from "../../../../../lib/services"; import { ClrDatagridStateInterface } from '@clr/angular'; -import { DEFAULT_PAGE_SIZE, calculatePage } from '../../../../../lib/utils/utils'; +import { DEFAULT_PAGE_SIZE, calculatePage, dbEncodeURIComponent } from '../../../../../lib/utils/utils'; class InitTag { name = ""; @@ -74,7 +74,7 @@ export class ArtifactTagComponent implements OnInit, OnDestroy { checkTagName(name) { let listArtifactParams: ArtifactService.ListArtifactsParams = { projectName: this.projectName, - repositoryName: this.repositoryName, + repositoryName: dbEncodeURIComponent(this.repositoryName), withLabel: true, withScanOverview: true, withTag: true, @@ -111,7 +111,7 @@ export class ArtifactTagComponent implements OnInit, OnDestroy { if (pageNumber <= 0) { pageNumber = 1; } let params: ArtifactService.ListTagsParams = { projectName: this.projectName, - repositoryName: this.repositoryName, + repositoryName: dbEncodeURIComponent(this.repositoryName), reference: this.artifactDetails.digest, page: pageNumber, withSignature: true, @@ -272,6 +272,8 @@ export class ArtifactTagComponent implements OnInit, OnDestroy { existValid(name) { if (name) { this.tagNameChecker.next(name); + } else { + this.isTagNameExist = false; } } toggleTagListOpenOrClose() { diff --git a/src/portal/src/app/project/repository/repository-gridview.component.ts b/src/portal/src/app/project/repository/repository-gridview.component.ts index d9cddd414..9d96ee9ba 100644 --- a/src/portal/src/app/project/repository/repository-gridview.component.ts +++ b/src/portal/src/app/project/repository/repository-gridview.component.ts @@ -24,7 +24,7 @@ import { UserPermissionService, USERSTATICPERMISSION } from "../../../lib/services"; import { FilterComponent } from "../../../lib/components/filter/filter.component"; -import { calculatePage, clone, DEFAULT_PAGE_SIZE } from "../../../lib/utils/utils"; +import { calculatePage, clone, DEFAULT_PAGE_SIZE, dbEncodeURIComponent } from "../../../lib/utils/utils"; import { IServiceConfig, SERVICE_CONFIG } from "../../../lib/entities/service.config"; import { ErrorHandler } from "../../../lib/utils/error-handler"; import { ConfirmationButtons, ConfirmationState, ConfirmationTargets } from "../../../lib/entities/shared.const"; @@ -222,7 +222,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit, OnDestroy this.operationService.publishInfo(operMessage); return this.newRepoService .deleteRepository({ - repositoryName: repo.name, + repositoryName: dbEncodeURIComponent(repo.name), projectName: this.projectName }) .pipe(map( diff --git a/src/portal/src/app/project/repository/vulnerability-scanning/result-bar-chart.component.ts b/src/portal/src/app/project/repository/vulnerability-scanning/result-bar-chart.component.ts index 9916eaa9a..c24a3789e 100644 --- a/src/portal/src/app/project/repository/vulnerability-scanning/result-bar-chart.component.ts +++ b/src/portal/src/app/project/repository/vulnerability-scanning/result-bar-chart.component.ts @@ -14,7 +14,8 @@ import { clone, CURRENT_BASE_HREF, DEFAULT_SUPPORTED_MIME_TYPE, - VULNERABILITY_SCAN_STATUS + VULNERABILITY_SCAN_STATUS, + dbEncodeURIComponent } from "../../../../lib/utils/utils"; import { ArtifactService } from "../../../../../ng-swagger-gen/services/artifact.service"; import { Artifact } from "../../../../../ng-swagger-gen/models/artifact"; @@ -118,7 +119,7 @@ export class ResultBarChartComponent implements OnInit, OnDestroy { this.onSubmitting = true; - this.scanningService.startVulnerabilityScanning(this.projectName, this.repoName, this.artifactDigest) + this.scanningService.startVulnerabilityScanning(this.projectName, dbEncodeURIComponent(this.repoName), this.artifactDigest) .pipe(finalize(() => this.submitFinish.emit(false))) .subscribe(() => { this.onSubmitting = false; @@ -149,7 +150,7 @@ export class ResultBarChartComponent implements OnInit, OnDestroy { } this.artifactService.getArtifact({ projectName: this.projectName, - repositoryName: this.repoName, + repositoryName: dbEncodeURIComponent(this.repoName), reference: this.artifactDigest, withScanOverview: true }) diff --git a/src/portal/src/app/services/routing-resolvers/artifact-detail-routing-resolver.service.ts b/src/portal/src/app/services/routing-resolvers/artifact-detail-routing-resolver.service.ts index c00f6ceca..2b0e3834a 100644 --- a/src/portal/src/app/services/routing-resolvers/artifact-detail-routing-resolver.service.ts +++ b/src/portal/src/app/services/routing-resolvers/artifact-detail-routing-resolver.service.ts @@ -19,6 +19,7 @@ import { Artifact } from "../../../../ng-swagger-gen/models/artifact"; import { ArtifactService } from "../../../../ng-swagger-gen/services/artifact.service"; import { Project } from "../../project/project"; import { ProjectService } from "../../../lib/services"; +import { dbEncodeURIComponent } from '../../../lib/utils/utils'; @Injectable({ providedIn: 'root' @@ -38,7 +39,7 @@ export class ArtifactDetailRoutingResolverService implements Resolve { .pipe( mergeMap((project: Project) => { return forkJoin([this.artifactService.getArtifact({ - repositoryName: repositoryName, + repositoryName: dbEncodeURIComponent(repositoryName), reference: artifactDigest, projectName: project.name, withLabel: true, diff --git a/src/portal/src/lib/utils/utils.ts b/src/portal/src/lib/utils/utils.ts index 1e4a376e1..b686e7589 100644 --- a/src/portal/src/lib/utils/utils.ts +++ b/src/portal/src/lib/utils/utils.ts @@ -624,3 +624,9 @@ export function mergeDeep(target, ...sources) { } return mergeDeep(target, ...sources); } +export function dbEncodeURIComponent(url: string) { + if (typeof url === "string") { + return encodeURIComponent(encodeURIComponent(url)); + } + return ""; +} diff --git a/tests/apitests/python/test_project_quota.py b/tests/apitests/python/test_project_quota.py index 212674f8c..508ba63cb 100644 --- a/tests/apitests/python/test_project_quota.py +++ b/tests/apitests/python/test_project_quota.py @@ -59,7 +59,7 @@ class TestProjects(unittest.TestCase): self.assertEqual(quota[0].used["storage"], 2789002) #8. Delete repository(RA) by user(UA); - self.repo.delete_repoitory(project_name, image, **ADMIN_CLIENT) + self.repo.delete_repoitory(project_name, "goharbor%2Falpine", **ADMIN_CLIENT) #9. Quota should be 0 quota = self.system.get_project_quota("project", project_id, **ADMIN_CLIENT)