mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 20:26:13 +01:00
Merge pull request #9019 from jwangyangls/fix-member-permission-router-bug
Add page routing permission to prevent refresh from entering the error page
This commit is contained in:
commit
82eed2fb2b
@ -1,13 +1,13 @@
|
|||||||
// Copyright Project Harbor Authors
|
// Copyright Project Harbor Authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
@ -18,6 +18,7 @@ import { SystemAdminGuard } from './shared/route/system-admin-activate.service';
|
|||||||
import { AuthCheckGuard } from './shared/route/auth-user-activate.service';
|
import { AuthCheckGuard } from './shared/route/auth-user-activate.service';
|
||||||
import { SignInGuard } from './shared/route/sign-in-guard-activate.service';
|
import { SignInGuard } from './shared/route/sign-in-guard-activate.service';
|
||||||
import { MemberGuard } from './shared/route/member-guard-activate.service';
|
import { MemberGuard } from './shared/route/member-guard-activate.service';
|
||||||
|
import { MemberPermissionGuard } from './shared/route/member-permission-guard-activate.service';
|
||||||
import { OidcGuard } from './shared/route/oidc-guard-active.service';
|
import { OidcGuard } from './shared/route/oidc-guard-active.service';
|
||||||
|
|
||||||
import { PageNotFoundComponent } from './shared/not-found/not-found.component';
|
import { PageNotFoundComponent } from './shared/not-found/not-found.component';
|
||||||
@ -50,7 +51,7 @@ import { ProjectDetailComponent } from './project/project-detail/project-detail.
|
|||||||
import { MemberComponent } from './project/member/member.component';
|
import { MemberComponent } from './project/member/member.component';
|
||||||
import { RobotAccountComponent } from './project/robot-account/robot-account.component';
|
import { RobotAccountComponent } from './project/robot-account/robot-account.component';
|
||||||
import { WebhookComponent } from './project/webhook/webhook.component';
|
import { WebhookComponent } from './project/webhook/webhook.component';
|
||||||
import { ProjectLabelComponent } from "./project/project-label/project-label.component";
|
import { ProjectLabelComponent } from './project/project-label/project-label.component';
|
||||||
import { ProjectConfigComponent } from './project/project-config/project-config.component';
|
import { ProjectConfigComponent } from './project/project-config/project-config.component';
|
||||||
import { ProjectRoutingResolver } from './project/project-routing-resolver.service';
|
import { ProjectRoutingResolver } from './project/project-routing-resolver.service';
|
||||||
import { ListChartsComponent } from './project/helm-chart/list-charts.component';
|
import { ListChartsComponent } from './project/helm-chart/list-charts.component';
|
||||||
@ -59,8 +60,8 @@ import { HelmChartDetailComponent } from './project/helm-chart/helm-chart-detail
|
|||||||
import { OidcOnboardComponent } from './oidc-onboard/oidc-onboard.component';
|
import { OidcOnboardComponent } from './oidc-onboard/oidc-onboard.component';
|
||||||
import { LicenseComponent } from './license/license.component';
|
import { LicenseComponent } from './license/license.component';
|
||||||
import { SummaryComponent } from './project/summary/summary.component';
|
import { SummaryComponent } from './project/summary/summary.component';
|
||||||
import { TagRetentionComponent } from "./project/tag-retention/tag-retention.component";
|
import { TagRetentionComponent } from './project/tag-retention/tag-retention.component';
|
||||||
|
import { USERSTATICPERMISSION } from '@harbor/ui';
|
||||||
|
|
||||||
const harborRoutes: Routes = [
|
const harborRoutes: Routes = [
|
||||||
{ path: '', redirectTo: 'harbor', pathMatch: 'full' },
|
{ path: '', redirectTo: 'harbor', pathMatch: 'full' },
|
||||||
@ -81,7 +82,7 @@ const harborRoutes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'harbor/sign-in',
|
path: 'harbor/sign-in',
|
||||||
component: SignInComponent,
|
component: SignInComponent,
|
||||||
canActivate: [ SignInGuard]
|
canActivate: [SignInGuard]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'harbor',
|
path: 'harbor',
|
||||||
@ -117,13 +118,13 @@ const harborRoutes: Routes = [
|
|||||||
path: 'replications',
|
path: 'replications',
|
||||||
component: TotalReplicationPageComponent,
|
component: TotalReplicationPageComponent,
|
||||||
canActivate: [SystemAdminGuard],
|
canActivate: [SystemAdminGuard],
|
||||||
canActivateChild: [SystemAdminGuard],
|
canActivateChild: [SystemAdminGuard]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'replications/:id/:tasks',
|
path: 'replications/:id/:tasks',
|
||||||
component: ReplicationTasksPageComponent,
|
component: ReplicationTasksPageComponent,
|
||||||
canActivate: [SystemAdminGuard],
|
canActivate: [SystemAdminGuard],
|
||||||
canActivateChild: [SystemAdminGuard],
|
canActivateChild: [SystemAdminGuard]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tags/:id/:repo',
|
path: 'tags/:id/:repo',
|
||||||
@ -148,7 +149,7 @@ const harborRoutes: Routes = [
|
|||||||
canActivate: [MemberGuard],
|
canActivate: [MemberGuard],
|
||||||
resolve: {
|
resolve: {
|
||||||
projectResolver: ProjectRoutingResolver
|
projectResolver: ProjectRoutingResolver
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'projects/:id/helm-charts/:chart/versions',
|
path: 'projects/:id/helm-charts/:chart/versions',
|
||||||
@ -156,7 +157,7 @@ const harborRoutes: Routes = [
|
|||||||
canActivate: [MemberGuard],
|
canActivate: [MemberGuard],
|
||||||
resolve: {
|
resolve: {
|
||||||
projectResolver: ProjectRoutingResolver
|
projectResolver: ProjectRoutingResolver
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'projects/:id/helm-charts/:chart/versions/:version',
|
path: 'projects/:id/helm-charts/:chart/versions/:version',
|
||||||
@ -164,60 +165,127 @@ const harborRoutes: Routes = [
|
|||||||
canActivate: [MemberGuard],
|
canActivate: [MemberGuard],
|
||||||
resolve: {
|
resolve: {
|
||||||
projectResolver: ProjectRoutingResolver
|
projectResolver: ProjectRoutingResolver
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'projects/:id',
|
path: 'projects/:id',
|
||||||
component: ProjectDetailComponent,
|
component: ProjectDetailComponent,
|
||||||
canActivate: [MemberGuard],
|
canActivate: [MemberGuard],
|
||||||
|
canActivateChild: [MemberPermissionGuard],
|
||||||
resolve: {
|
resolve: {
|
||||||
projectResolver: ProjectRoutingResolver
|
projectResolver: ProjectRoutingResolver
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'summary',
|
path: 'summary',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.PROJECT.KEY,
|
||||||
|
action: USERSTATICPERMISSION.PROJECT.VALUE.READ
|
||||||
|
}
|
||||||
|
},
|
||||||
component: SummaryComponent
|
component: SummaryComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'repositories',
|
path: 'repositories',
|
||||||
component: RepositoryPageComponent
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.REPOSITORY.KEY,
|
||||||
|
action: USERSTATICPERMISSION.REPOSITORY.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: RepositoryPageComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'helm-charts',
|
path: 'helm-charts',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.HELM_CHART.KEY,
|
||||||
|
action: USERSTATICPERMISSION.HELM_CHART.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
component: ListChartsComponent
|
component: ListChartsComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'repositories/:repo/tags',
|
path: 'repositories/:repo/tags',
|
||||||
component: TagRepositoryComponent,
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.REPOSITORY.KEY,
|
||||||
|
action: USERSTATICPERMISSION.REPOSITORY.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: TagRepositoryComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'members',
|
path: 'members',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.MEMBER.KEY,
|
||||||
|
action: USERSTATICPERMISSION.MEMBER.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
component: MemberComponent
|
component: MemberComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'logs',
|
path: 'logs',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.LOG.KEY,
|
||||||
|
action: USERSTATICPERMISSION.LOG.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
component: AuditLogComponent
|
component: AuditLogComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'labels',
|
path: 'labels',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.LABEL.KEY,
|
||||||
|
action: USERSTATICPERMISSION.LABEL.VALUE.CREATE
|
||||||
|
}
|
||||||
|
},
|
||||||
component: ProjectLabelComponent
|
component: ProjectLabelComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'configs',
|
path: 'configs',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.CONFIGURATION.KEY,
|
||||||
|
action: USERSTATICPERMISSION.CONFIGURATION.VALUE.READ
|
||||||
|
}
|
||||||
|
},
|
||||||
component: ProjectConfigComponent
|
component: ProjectConfigComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'robot-account',
|
path: 'robot-account',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.ROBOT.KEY,
|
||||||
|
action: USERSTATICPERMISSION.ROBOT.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
component: RobotAccountComponent
|
component: RobotAccountComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tag-retention',
|
path: 'tag-retention',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.TAG_RETENTION.KEY,
|
||||||
|
action: USERSTATICPERMISSION.TAG_RETENTION.VALUE.READ
|
||||||
|
}
|
||||||
|
},
|
||||||
component: TagRetentionComponent
|
component: TagRetentionComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'webhook',
|
path: 'webhook',
|
||||||
|
data: {
|
||||||
|
permissionParam: {
|
||||||
|
resource: USERSTATICPERMISSION.WEBHOOK.KEY,
|
||||||
|
action: USERSTATICPERMISSION.WEBHOOK.VALUE.LIST
|
||||||
|
}
|
||||||
|
},
|
||||||
component: WebhookComponent
|
component: WebhookComponent
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -239,19 +307,17 @@ const harborRoutes: Routes = [
|
|||||||
path: 'registry',
|
path: 'registry',
|
||||||
component: DestinationPageComponent,
|
component: DestinationPageComponent,
|
||||||
canActivate: [SystemAdminGuard],
|
canActivate: [SystemAdminGuard],
|
||||||
canActivateChild: [SystemAdminGuard],
|
canActivateChild: [SystemAdminGuard]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: "**", component: PageNotFoundComponent }
|
{ path: '**', component: PageNotFoundComponent }
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forRoot(harborRoutes, {onSameUrlNavigation: 'reload'})
|
RouterModule.forRoot(harborRoutes, { onSameUrlNavigation: 'reload' })
|
||||||
],
|
],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
export class HarborRoutingModule {
|
export class HarborRoutingModule {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -89,6 +89,7 @@ export class ProjectDetailComponent implements OnInit {
|
|||||||
USERSTATICPERMISSION.TAG_RETENTION.KEY, USERSTATICPERMISSION.TAG_RETENTION.VALUE.READ));
|
USERSTATICPERMISSION.TAG_RETENTION.KEY, USERSTATICPERMISSION.TAG_RETENTION.VALUE.READ));
|
||||||
permissionsList.push(this.userPermissionService.getPermission(projectId,
|
permissionsList.push(this.userPermissionService.getPermission(projectId,
|
||||||
USERSTATICPERMISSION.WEBHOOK.KEY, USERSTATICPERMISSION.WEBHOOK.VALUE.LIST));
|
USERSTATICPERMISSION.WEBHOOK.KEY, USERSTATICPERMISSION.WEBHOOK.VALUE.LIST));
|
||||||
|
|
||||||
forkJoin(...permissionsList).subscribe(Rules => {
|
forkJoin(...permissionsList).subscribe(Rules => {
|
||||||
[this.hasProjectReadPermission, this.hasLogListPermission, this.hasConfigurationListPermission, this.hasMemberListPermission
|
[this.hasProjectReadPermission, this.hasLogListPermission, this.hasConfigurationListPermission, this.hasMemberListPermission
|
||||||
, this.hasLabelListPermission, this.hasRepositoryListPermission, this.hasHelmChartsListPermission, this.hasRobotListPermission
|
, this.hasLabelListPermission, this.hasRepositoryListPermission, this.hasHelmChartsListPermission, this.hasRobotListPermission
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
Router,
|
||||||
|
ActivatedRouteSnapshot,
|
||||||
|
RouterStateSnapshot,
|
||||||
|
CanActivateChild,
|
||||||
|
} from "@angular/router";
|
||||||
|
import {
|
||||||
|
UserPrivilegeServeItem,
|
||||||
|
UserPermissionService,
|
||||||
|
ErrorHandler,
|
||||||
|
CommonRoutes
|
||||||
|
} from "@harbor/ui";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MemberPermissionGuard implements CanActivate, CanActivateChild {
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private errorHandler: ErrorHandler,
|
||||||
|
private userPermission: UserPermissionService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
canActivate(
|
||||||
|
route: ActivatedRouteSnapshot,
|
||||||
|
state: RouterStateSnapshot
|
||||||
|
): Observable<boolean> | boolean {
|
||||||
|
const projectId = route.parent.params["id"];
|
||||||
|
const permission = route.data.permissionParam as UserPrivilegeServeItem;
|
||||||
|
return new Observable(observer => {
|
||||||
|
this.userPermission
|
||||||
|
.getPermission(projectId, permission.resource, permission.action)
|
||||||
|
.subscribe(
|
||||||
|
permissionRouter => {
|
||||||
|
if (!permissionRouter) {
|
||||||
|
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);
|
||||||
|
}
|
||||||
|
observer.next(permissionRouter);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);
|
||||||
|
observer.next(false);
|
||||||
|
this.errorHandler.error(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
canActivateChild(
|
||||||
|
route: ActivatedRouteSnapshot,
|
||||||
|
state: RouterStateSnapshot
|
||||||
|
): Observable<boolean> | boolean {
|
||||||
|
return this.canActivate(route, state);
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule } from "@angular/router";
|
import { RouterModule } from "@angular/router";
|
||||||
import { TranslateModule } from "@ngx-translate/core";
|
import { TranslateModule } from "@ngx-translate/core";
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||||
import { CookieService } from "ngx-cookie";
|
import { CookieService } from "ngx-cookie";
|
||||||
import {
|
import {
|
||||||
IServiceConfig,
|
IServiceConfig,
|
||||||
@ -33,6 +33,7 @@ import { AuthCheckGuard } from "./route/auth-user-activate.service";
|
|||||||
import { SignInGuard } from "./route/sign-in-guard-activate.service";
|
import { SignInGuard } from "./route/sign-in-guard-activate.service";
|
||||||
import { SystemAdminGuard } from "./route/system-admin-activate.service";
|
import { SystemAdminGuard } from "./route/system-admin-activate.service";
|
||||||
import { MemberGuard } from "./route/member-guard-activate.service";
|
import { MemberGuard } from "./route/member-guard-activate.service";
|
||||||
|
import { MemberPermissionGuard } from "./route/member-permission-guard-activate.service";
|
||||||
import { OidcGuard } from "./route/oidc-guard-active.service";
|
import { OidcGuard } from "./route/oidc-guard-active.service";
|
||||||
import { LeavingRepositoryRouteDeactivate } from "./route/leaving-repository-deactivate.service";
|
import { LeavingRepositoryRouteDeactivate } from "./route/leaving-repository-deactivate.service";
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ import { GaugeComponent } from "./gauge/gauge.component";
|
|||||||
import { ConfirmationDialogComponent } from "./confirmation-dialog/confirmation-dialog.component";
|
import { ConfirmationDialogComponent } from "./confirmation-dialog/confirmation-dialog.component";
|
||||||
import { ConfirmationDialogService } from "./confirmation-dialog/confirmation-dialog.service";
|
import { ConfirmationDialogService } from "./confirmation-dialog/confirmation-dialog.service";
|
||||||
import { MessageHandlerService } from "./message-handler/message-handler.service";
|
import { MessageHandlerService } from "./message-handler/message-handler.service";
|
||||||
import { ListChartVersionRoComponent } from './list-chart-version-ro/list-chart-version-ro.component';
|
import { ListChartVersionRoComponent } from "./list-chart-version-ro/list-chart-version-ro.component";
|
||||||
|
|
||||||
const uiLibConfig: IServiceConfig = {
|
const uiLibConfig: IServiceConfig = {
|
||||||
enablei18Support: true,
|
enablei18Support: true,
|
||||||
@ -141,6 +142,7 @@ const uiLibConfig: IServiceConfig = {
|
|||||||
SignInGuard,
|
SignInGuard,
|
||||||
LeavingRepositoryRouteDeactivate,
|
LeavingRepositoryRouteDeactivate,
|
||||||
MemberGuard,
|
MemberGuard,
|
||||||
|
MemberPermissionGuard,
|
||||||
OidcGuard,
|
OidcGuard,
|
||||||
MessageHandlerService,
|
MessageHandlerService,
|
||||||
StatisticHandler
|
StatisticHandler
|
||||||
|
Loading…
Reference in New Issue
Block a user