Merge remote-tracking branch 'origin/develop' into feature/SUPPORT-9363
# Conflicts: # backend/src/main/java/ru/micord/ervu/account_applications/security/config/SecurityConfig.java
This commit is contained in:
commit
ae5181e9f2
8 changed files with 184 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 org.jooq.DSLContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.impl.DSL;
|
||||
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.Recruitment;
|
||||
import ru.micord.ervu.account_applications.db_beans.public_.tables.UserApplicationList;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
protected Table<RecruitmentRecord> getTable() {
|
||||
return Tables.RECRUITMENT;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
|||
import ru.micord.ervu.account_applications.security.filter.JwtAuthenticationFilter;
|
||||
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
|
||||
@EnableWebSecurity
|
||||
|
|
@ -30,7 +32,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
.authorizeHttpRequests(auth -> {
|
||||
auth.antMatchers("/version").permitAll();
|
||||
auth.antMatchers("/session").authenticated();
|
||||
auth.antMatchers(CREATE_APPLICATION_PERMISSIONS).hasAuthority(CREATE_APPLICATION_AUTHORITY);
|
||||
auth.anyRequest().authenticated();
|
||||
|
||||
})
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
|
|
|
|||
|
|
@ -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 {ConfirmExitGuard} from "@webbpm/base-package";
|
||||
import {RolesGuard} from "./guard/RolesGuard";
|
||||
|
||||
import {ErvuRole} from "./enum/ErvuRole";
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
|
|
@ -13,37 +13,58 @@ const appRoutes: Routes = [
|
|||
{
|
||||
path: 'add_user_application',
|
||||
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',
|
||||
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',
|
||||
loadChildren: 'generated-sources/page-block_user_application.module#Pageblock_user_applicationModule',
|
||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
||||
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||
data: {
|
||||
roles: [ErvuRole.CREATOR]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'reset_password',
|
||||
loadChildren: 'generated-sources/page-reset_password.module#Pagereset_passwordModule',
|
||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
||||
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||
data: {
|
||||
roles: [ErvuRole.CREATOR]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'process_application/:id',
|
||||
loadChildren: 'generated-sources/page-process_application.module#Pageprocess_applicationModule',
|
||||
canActivate: [ConfirmExitGuard, RolesGuard]
|
||||
canActivate: [ConfirmExitGuard, RolesGuard],
|
||||
data: {
|
||||
checkOrg: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'process_application_edit_user/:id',
|
||||
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',
|
||||
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 {AuthorizationService} from "../service/authorization.service";
|
||||
import {TokenProvider} from "../provider/token.provider";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {ErvuRole} from "../enum/ErvuRole";
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class RolesGuard implements CanActivate{
|
||||
|
||||
protected readonly allowedRoles: string[] = [];
|
||||
private allowedRoles: string[];
|
||||
|
||||
constructor(protected authService: AuthorizationService,
|
||||
protected tokenProvider: TokenProvider,
|
||||
protected router: Router) {
|
||||
protected router: Router, private httpClient: HttpClient) {
|
||||
}
|
||||
|
||||
async canActivate(
|
||||
|
|
@ -25,14 +27,21 @@ export class RolesGuard implements CanActivate{
|
|||
if (!await this.tokenProvider.getToken()) {
|
||||
return this.getUrlOnFailure()
|
||||
}
|
||||
this.allowedRoles = route.data && route.data.roles ? route.data.roles : [];
|
||||
let checkOrg = route.data && route.data.checkOrg;
|
||||
|
||||
if (!this.authService.isAuthorized()) {
|
||||
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());
|
||||
}
|
||||
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
|
||||
|| 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