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:
jwangyangls 2019-09-09 18:38:30 +08:00 committed by GitHub
commit 82eed2fb2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 147 additions and 22 deletions

View File

@ -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 {}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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