Skip to content

Commit

Permalink
enhance RBAC access control
Browse files Browse the repository at this point in the history
  • Loading branch information
shenqinb-star committed Nov 30, 2023
1 parent 01e0661 commit 7206176
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.server.ResponseStatusException;

import io.boomerang.model.FlowSettings;
import io.boomerang.mongo.entity.FlowUserEntity;
import io.boomerang.mongo.model.UserType;
import io.boomerang.service.UserIdentityService;
import io.boomerang.security.service.UserValidationService;
import io.boomerang.service.crud.ConfigurationService;

@RestController
Expand All @@ -23,28 +22,26 @@ public class ConfigurationController {
private ConfigurationService configurationService;

@Autowired
UserIdentityService service;
private UserValidationService userValidationService;

@GetMapping(value = "")
public List<FlowSettings> getAppConfiguration() {
validateUser();
validateUser();
return configurationService.getAllSettings();
}

@PutMapping(value = "")
public List<FlowSettings> updateSettings(@RequestBody List<FlowSettings> settings) {
validateUser();
validateUser();
return configurationService.updateSettings(settings);
}

protected void validateUser() {

FlowUserEntity userEntity = service.getCurrentUser();
if (userEntity == null || (!userEntity.getType().equals(UserType.admin)
&& !userEntity.getType().equals(UserType.operator))) {

throw new HttpClientErrorException(HttpStatus.FORBIDDEN);
}
try {
userValidationService.validateUserAdminOrOperator();
} catch (ResponseStatusException e) {
throw new HttpClientErrorException(e.getStatus());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ public interface UserValidationService {

void validateUserForTeam(String teamId);

void validateUserForWorkflow(String workflowId);

void validateUserAdminOrOperator();

void validateUserAccessForWorkflow(WorkflowScope scope, String flowTeamId, String flowOwnerUserId, boolean editable);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package io.boomerang.security.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import io.boomerang.client.model.Team;
import io.boomerang.model.FlowTeam;
import io.boomerang.model.TemplateScope;
import io.boomerang.mongo.entity.FlowUserEntity;
import io.boomerang.mongo.entity.TeamEntity;
import io.boomerang.mongo.entity.WorkflowEntity;
import io.boomerang.mongo.model.UserType;
import io.boomerang.mongo.model.WorkflowScope;
import io.boomerang.mongo.service.FlowWorkflowService;
import io.boomerang.security.service.UserValidationService;
import io.boomerang.service.UserIdentityService;
import io.boomerang.service.crud.TeamService;
Expand All @@ -30,34 +25,22 @@ public class UserValidationServiceImpl implements UserValidationService {
@Autowired
private UserIdentityService userIdentityService;

@Autowired
private FlowWorkflowService workflowRepository;

@Override
public void validateUserForTeam(String teamId) {
FlowUserEntity user = userIdentityService.getCurrentUser();
FlowTeam team = teamService.getTeamByIdDetailed(teamId);
List<String> userIds = new ArrayList<>();
if (team.getUsers() != null) {
for (FlowUserEntity teamUser : team.getUsers()) {
userIds.add(teamUser.getId());
}
}
List<String> userTeamIds = new ArrayList<>();
if (user.getTeams() != null) {
for (Team userTeam : user.getTeams()) {
userTeamIds.add(userTeam.getId());
}
}
if (user.getType() != UserType.admin && user.getType() != UserType.operator
&& !userIds.contains(user.getId()) && !userTeamIds.contains(team.getHigherLevelGroupId())) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
if(user == null) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
this.validateAccessForTeamScope(user, teamId, false);
}

@Override
public void validateUserAccessForWorkflow(WorkflowScope scope, String flowTeamId, String flowOwnerUserId, boolean editable) {
FlowUserEntity user = userIdentityService.getCurrentUser();
if(user == null) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}

if(scope == WorkflowScope.user) {
this.validateAccessForUserScope(user, flowOwnerUserId);
} else if(scope == WorkflowScope.team) {
Expand All @@ -70,56 +53,20 @@ public void validateUserAccessForWorkflow(WorkflowScope scope, String flowTeamId
@Override
public void validateUserAccessForTaskTemplate(TemplateScope scope, String taskTeamId, boolean editable) {
FlowUserEntity user = userIdentityService.getCurrentUser();
if(user == null) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
if(scope == TemplateScope.team) {
this.validateAccessForTeamScope(user, taskTeamId, editable);
} else {
this.validateAccessForSystemScope(user);
}
}

@Override
public void validateUserForWorkflow(String workflowId) {
FlowUserEntity user = userIdentityService.getCurrentUser();
WorkflowEntity workflow = workflowRepository.getWorkflow(workflowId);
WorkflowScope scope = workflow.getScope();
if (workflow.getScope() == WorkflowScope.team) {

FlowTeam team = teamService.getTeamByIdDetailed(workflow.getFlowTeamId());

List<String> userIds = new ArrayList<>();
if (team.getUsers() != null) {
for (FlowUserEntity teamUser : team.getUsers()) {
userIds.add(teamUser.getId());
}
}

List<String> userTeamIds = new ArrayList<>();
if (user.getTeams() != null) {
for (Team userTeam : user.getTeams()) {
userTeamIds.add(userTeam.getId());
}
}
if (user.getType() != UserType.admin && user.getType() != UserType.operator
&& !userIds.contains(user.getId())
&& !userTeamIds.contains(team.getHigherLevelGroupId())) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}

if (scope == WorkflowScope.user && !user.getId().equals(workflow.getOwnerUserId())) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}

if (scope == WorkflowScope.system && user.getType() != UserType.admin
&& user.getType() != UserType.operator) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}

@Override
public void validateUserAdminOrOperator() {
FlowUserEntity user = userIdentityService.getCurrentUser();
if (!isPlatformAdminOrOperator(user)) {
if (user == null || !isPlatformAdminOrOperator(user)) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}
Expand Down Expand Up @@ -156,12 +103,15 @@ private void validateAccessForSystemScope(FlowUserEntity user) {
}

private void validateTeamLevelRoles(TeamEntity team, boolean editable) {
if(!editable) {
return;
}
if(team.getUserRoles() == null || team.getUserRoles().isEmpty()) {
// skip if team user roles is not enabled
return;
}

if(editable && !team.getUserRoles().contains("operator")) {
if(!team.getUserRoles().contains("operator")) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}
Expand Down
23 changes: 12 additions & 11 deletions src/main/java/io/boomerang/service/crud/TeamServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.server.ResponseStatusException;

import com.google.inject.internal.util.Lists;
import com.google.inject.internal.util.Maps;
Expand Down Expand Up @@ -50,12 +50,12 @@
import io.boomerang.mongo.model.Settings;
import io.boomerang.mongo.model.Storage;
import io.boomerang.mongo.model.TaskStatus;
import io.boomerang.mongo.model.UserType;
import io.boomerang.mongo.service.FlowSettingsService;
import io.boomerang.mongo.service.FlowTeamService;
import io.boomerang.mongo.service.FlowUserService;
import io.boomerang.mongo.service.FlowWorkflowActivityService;
import io.boomerang.mongo.service.FlowWorkflowService;
import io.boomerang.security.service.UserValidationService;
import io.boomerang.service.UserIdentityService;
import static io.boomerang.util.DataAdapterUtil.*;

Expand Down Expand Up @@ -106,7 +106,10 @@ public class TeamServiceImpl implements TeamService {

@Autowired
private WorkflowVersionService workflowVersionService;


@Autowired
private UserValidationService userValidationService;

private FlowTeam createFlowTeam(TeamEntity team) {
FlowTeam flowTeam = new FlowTeam();
BeanUtils.copyProperties(team, flowTeam);
Expand Down Expand Up @@ -902,14 +905,12 @@ public Quotas updateTeamQuotas(String teamId, Quotas quotas) {
return flowTeamService.save(team).getQuotas();
}

protected void validateUser() {

FlowUserEntity userEntity = userIdentiyService.getCurrentUser();
if (userEntity == null || (!userEntity.getType().equals(UserType.admin)
&& !userEntity.getType().equals(UserType.operator))) {

throw new HttpClientErrorException(HttpStatus.FORBIDDEN);
}
private void validateUser() {
try {
userValidationService.validateUserAdminOrOperator();
} catch (ResponseStatusException e) {
throw new HttpClientErrorException(e.getStatus());
}
}

@Override
Expand Down

0 comments on commit 7206176

Please sign in to comment.