SUPPORT-9346: fix access to application pages
This commit is contained in:
parent
44681d41d3
commit
3a4a733c4b
8 changed files with 183 additions and 13 deletions
|
|
@ -0,0 +1,32 @@
|
||||||
|
package ru.micord.ervu.account_applications.controller;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import ru.micord.ervu.account_applications.security.context.SecurityContext;
|
||||||
|
import ru.micord.ervu.account_applications.service.RecruitmentService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gulnaz
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class RecruitmentController {
|
||||||
|
|
||||||
|
private final SecurityContext securityContext;
|
||||||
|
private final RecruitmentService recruitmentService;
|
||||||
|
|
||||||
|
public RecruitmentController(SecurityContext securityContext, RecruitmentService recruitmentService) {
|
||||||
|
this.securityContext = securityContext;
|
||||||
|
this.recruitmentService = recruitmentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/allowed")
|
||||||
|
public ResponseEntity<Boolean> checkAccess(HttpServletRequest request) {
|
||||||
|
Long appNumber = Long.valueOf(request.getHeader("app-number"));
|
||||||
|
boolean checkParents = Boolean.parseBoolean(request.getHeader("check-parents"));
|
||||||
|
String domainId = securityContext.getDomainId();
|
||||||
|
return ResponseEntity.ok(recruitmentService.exists(appNumber, domainId, checkParents));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,16 @@ import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.jooq.DSLContext;
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.Field;
|
||||||
|
import org.jooq.Name;
|
||||||
|
import org.jooq.Select;
|
||||||
import org.jooq.Table;
|
import org.jooq.Table;
|
||||||
import org.jooq.TableField;
|
import org.jooq.TableField;
|
||||||
import org.jooq.impl.DSL;
|
import org.jooq.impl.DSL;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.micord.ervu.account_applications.db_beans.public_.Tables;
|
import ru.micord.ervu.account_applications.db_beans.public_.Tables;
|
||||||
import ru.micord.ervu.account_applications.db_beans.public_.tables.Recruitment;
|
import ru.micord.ervu.account_applications.db_beans.public_.tables.Recruitment;
|
||||||
|
import ru.micord.ervu.account_applications.db_beans.public_.tables.UserApplicationList;
|
||||||
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentRecord;
|
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -78,6 +82,43 @@ public class RecruitmentDao extends AbstractDataDao<RecruitmentRecord> {
|
||||||
setFieldByField(Recruitment.RECRUITMENT.ACTIVE, active, Recruitment.RECRUITMENT.IDM_ID, id);
|
setFieldByField(Recruitment.RECRUITMENT.ACTIVE, active, Recruitment.RECRUITMENT.IDM_ID, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean exists(Long appNumber, String domainId, boolean checkParents) {
|
||||||
|
Recruitment orgTable = Recruitment.RECRUITMENT;
|
||||||
|
UserApplicationList appTable = UserApplicationList.USER_APPLICATION_LIST;
|
||||||
|
String parentOrg = "parent_org";
|
||||||
|
Name parentOrgName = DSL.name(parentOrg);
|
||||||
|
Table<?> parentOrgTable = DSL.table(parentOrgName);
|
||||||
|
Field<String> parentIdmId = DSL.field(DSL.name(parentOrg, orgTable.IDM_ID.getName()),
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
Field<String> parentParentId = DSL.field(DSL.name(parentOrg, orgTable.PARENT_ID.getName()),
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
Select<?> select = checkParents
|
||||||
|
? dsl.withRecursive(parentOrgName)
|
||||||
|
.as(dsl.select(orgTable.IDM_ID, orgTable.PARENT_ID)
|
||||||
|
.from(orgTable)
|
||||||
|
.where(orgTable.IDM_ID.eq(
|
||||||
|
dsl.select(orgTable.IDM_ID)
|
||||||
|
.from(orgTable)
|
||||||
|
.join(appTable).on(appTable.RECRUITMENT_ID.eq(orgTable.ID))
|
||||||
|
.where(appTable.NUMBER_APP.eq(appNumber))))
|
||||||
|
.unionAll(dsl.select(orgTable.IDM_ID, orgTable.PARENT_ID)
|
||||||
|
.from(orgTable)
|
||||||
|
.join(parentOrgTable).on(orgTable.IDM_ID.eq(parentParentId))))
|
||||||
|
.select(parentIdmId)
|
||||||
|
.from(parentOrgTable)
|
||||||
|
.where(parentIdmId.eq(domainId))
|
||||||
|
: dsl.select(orgTable.IDM_ID)
|
||||||
|
.from(orgTable)
|
||||||
|
.join(appTable)
|
||||||
|
.on(appTable.RECRUITMENT_ID.eq(orgTable.ID))
|
||||||
|
.where(appTable.NUMBER_APP.eq(appNumber)
|
||||||
|
.and(orgTable.IDM_ID.eq(domainId)));
|
||||||
|
|
||||||
|
return dsl.fetchExists(select);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Table<RecruitmentRecord> getTable() {
|
protected Table<RecruitmentRecord> getTable() {
|
||||||
return Tables.RECRUITMENT;
|
return Tables.RECRUITMENT;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
||||||
import ru.micord.ervu.account_applications.security.filter.JwtAuthenticationFilter;
|
import ru.micord.ervu.account_applications.security.filter.JwtAuthenticationFilter;
|
||||||
import ru.micord.ervu.account_applications.security.provider.ErvuJwtAuthenticationProvider;
|
import ru.micord.ervu.account_applications.security.provider.ErvuJwtAuthenticationProvider;
|
||||||
|
|
||||||
|
import static ru.micord.ervu.account_applications.security.config.SecurityConstant.CREATE_APPLICATION_AUTHORITY;
|
||||||
|
import static ru.micord.ervu.account_applications.security.config.SecurityConstant.CREATE_APPLICATION_PERMISSIONS;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
|
@ -34,6 +36,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.authorizeHttpRequests(auth -> {
|
.authorizeHttpRequests(auth -> {
|
||||||
auth.antMatchers("/version").permitAll();
|
auth.antMatchers("/version").permitAll();
|
||||||
auth.antMatchers("/session").authenticated();
|
auth.antMatchers("/session").authenticated();
|
||||||
|
auth.antMatchers(CREATE_APPLICATION_PERMISSIONS).hasAuthority(CREATE_APPLICATION_AUTHORITY);
|
||||||
|
|
||||||
if (allowedRoles != null && allowedRoles.length > 0) {
|
if (allowedRoles != null && allowedRoles.length > 0) {
|
||||||
auth.anyRequest().hasAnyAuthority(allowedRoles);
|
auth.anyRequest().hasAnyAuthority(allowedRoles);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ru.micord.ervu.account_applications.security.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gulnaz
|
||||||
|
*/
|
||||||
|
public class SecurityConstant {
|
||||||
|
public static final String CREATE_APPLICATION_AUTHORITY = "responsible_for_information_security";
|
||||||
|
|
||||||
|
public static final String[] CREATE_APPLICATION_PERMISSIONS = {
|
||||||
|
"/rpc/add_user_application/**",
|
||||||
|
"/rpc/edit_user_application/**",
|
||||||
|
"/rpc/block_user_application/**",
|
||||||
|
"/rpc/unblock_user_application/**",
|
||||||
|
"/rpc/reset_password/**"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ru.micord.ervu.account_applications.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.micord.ervu.account_applications.dao.RecruitmentDao;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gulnaz
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class RecruitmentService {
|
||||||
|
|
||||||
|
private final RecruitmentDao recruitmentDao;
|
||||||
|
|
||||||
|
public RecruitmentService(RecruitmentDao recruitmentDao) {
|
||||||
|
this.recruitmentDao = recruitmentDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(Long appNumber, String domainId, boolean checkParents) {
|
||||||
|
return recruitmentDao.exists(appNumber, domainId, checkParents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import {NgModule} from "@angular/core";
|
||||||
import {RouterModule, Routes} from "@angular/router";
|
import {RouterModule, Routes} from "@angular/router";
|
||||||
import {ConfirmExitGuard} from "@webbpm/base-package";
|
import {ConfirmExitGuard} from "@webbpm/base-package";
|
||||||
import {RolesGuard} from "./guard/RolesGuard";
|
import {RolesGuard} from "./guard/RolesGuard";
|
||||||
|
import {ErvuRole} from "./enum/ErvuRole";
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
|
|
@ -13,37 +13,58 @@ const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'add_user_application',
|
path: 'add_user_application',
|
||||||
loadChildren: 'generated-sources/page-add_user_application.module#Pageadd_user_applicationModule',
|
loadChildren: 'generated-sources/page-add_user_application.module#Pageadd_user_applicationModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
roles: [ErvuRole.CREATOR]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'edit_user_application',
|
path: 'edit_user_application',
|
||||||
loadChildren: 'generated-sources/page-edit_user_application.module#Pageedit_user_applicationModule',
|
loadChildren: 'generated-sources/page-edit_user_application.module#Pageedit_user_applicationModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
roles: [ErvuRole.CREATOR]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'block_user_application',
|
path: 'block_user_application',
|
||||||
loadChildren: 'generated-sources/page-block_user_application.module#Pageblock_user_applicationModule',
|
loadChildren: 'generated-sources/page-block_user_application.module#Pageblock_user_applicationModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
roles: [ErvuRole.CREATOR]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'reset_password',
|
path: 'reset_password',
|
||||||
loadChildren: 'generated-sources/page-reset_password.module#Pagereset_passwordModule',
|
loadChildren: 'generated-sources/page-reset_password.module#Pagereset_passwordModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
roles: [ErvuRole.CREATOR]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'process_application/:id',
|
path: 'process_application/:id',
|
||||||
loadChildren: 'generated-sources/page-process_application.module#Pageprocess_applicationModule',
|
loadChildren: 'generated-sources/page-process_application.module#Pageprocess_applicationModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
checkOrg: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'process_application_edit_user/:id',
|
path: 'process_application_edit_user/:id',
|
||||||
loadChildren: 'generated-sources/page-process_application_edit_user.module#Pageprocess_application_edit_userModule',
|
loadChildren: 'generated-sources/page-process_application_edit_user.module#Pageprocess_application_edit_userModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
checkOrg: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'unblock_user_application',
|
path: 'unblock_user_application',
|
||||||
loadChildren: 'generated-sources/page-unblock_user_application.module#Pageunblock_user_applicationModule',
|
loadChildren: 'generated-sources/page-unblock_user_application.module#Pageunblock_user_applicationModule',
|
||||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||||
|
data: {
|
||||||
|
roles: [ErvuRole.CREATOR]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
5
frontend/src/ts/modules/app/enum/ErvuRole.ts
Normal file
5
frontend/src/ts/modules/app/enum/ErvuRole.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum ErvuRole {
|
||||||
|
CREATOR = 'responsible_for_information_security',
|
||||||
|
REVIEWER = 'responsible_for_internal_control',
|
||||||
|
APPROVER = 'security_administrator'
|
||||||
|
}
|
||||||
|
|
@ -8,15 +8,17 @@ import {
|
||||||
import {Injectable} from "@angular/core";
|
import {Injectable} from "@angular/core";
|
||||||
import {AuthorizationService} from "../service/authorization.service";
|
import {AuthorizationService} from "../service/authorization.service";
|
||||||
import {TokenProvider} from "../provider/token.provider";
|
import {TokenProvider} from "../provider/token.provider";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {ErvuRole} from "../enum/ErvuRole";
|
||||||
|
|
||||||
@Injectable({providedIn: 'root'})
|
@Injectable({providedIn: 'root'})
|
||||||
export class RolesGuard implements CanActivate{
|
export class RolesGuard implements CanActivate{
|
||||||
|
|
||||||
protected readonly allowedRoles: string[] = [];
|
private allowedRoles: string[];
|
||||||
|
|
||||||
constructor(protected authService: AuthorizationService,
|
constructor(protected authService: AuthorizationService,
|
||||||
protected tokenProvider: TokenProvider,
|
protected tokenProvider: TokenProvider,
|
||||||
protected router: Router) {
|
protected router: Router, private httpClient: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async canActivate(
|
async canActivate(
|
||||||
|
|
@ -25,14 +27,21 @@ export class RolesGuard implements CanActivate{
|
||||||
if (!await this.tokenProvider.getToken()) {
|
if (!await this.tokenProvider.getToken()) {
|
||||||
return this.getUrlOnFailure()
|
return this.getUrlOnFailure()
|
||||||
}
|
}
|
||||||
|
this.allowedRoles = route.data && route.data.roles ? route.data.roles : [];
|
||||||
|
let checkOrg = route.data && route.data.checkOrg;
|
||||||
|
|
||||||
if (!this.authService.isAuthorized()) {
|
if (!this.authService.isAuthorized()) {
|
||||||
return this.authService.getCurrentSession()
|
return this.authService.getCurrentSession()
|
||||||
.then(() => this.checkRoles() ? true : this.getUrlOnFailure())
|
.then(() => {
|
||||||
|
if (checkOrg) {
|
||||||
|
return this.checkOrgByAppId(route.params.id);
|
||||||
|
}
|
||||||
|
return this.checkRoles() ? true : this.getUrlOnFailure();
|
||||||
|
})
|
||||||
.catch(() => this.getUrlOnFailure());
|
.catch(() => this.getUrlOnFailure());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return this.checkRoles();
|
return checkOrg ? this.checkOrgByAppId(route.params.id) : this.checkRoles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,4 +53,26 @@ export class RolesGuard implements CanActivate{
|
||||||
return this.allowedRoles.length === 0
|
return this.allowedRoles.length === 0
|
||||||
|| this.authService.hasAnyRole(this.allowedRoles);
|
|| this.authService.hasAnyRole(this.allowedRoles);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private checkOrgByAppId(id: string): Promise<boolean | UrlTree> {
|
||||||
|
if (this.authService.hasAnyRole([ErvuRole.CREATOR, ErvuRole.REVIEWER])) {
|
||||||
|
return this.httpClient.get("allowed", {
|
||||||
|
headers: {
|
||||||
|
'app-number': id,
|
||||||
|
'check-parents': (!this.authService.hasRole(ErvuRole.CREATOR)).toString()
|
||||||
|
},
|
||||||
|
observe: 'response'
|
||||||
|
})
|
||||||
|
.toPromise()
|
||||||
|
.then(response => {
|
||||||
|
return response.body ? true : this.getUrlOnFailure();
|
||||||
|
})
|
||||||
|
.catch(() => this.getUrlOnFailure());
|
||||||
|
}
|
||||||
|
else if (this.authService.hasRole(ErvuRole.APPROVER)) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(this.getUrlOnFailure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue