Skip to content

Commit

Permalink
Fixes permissions for newly created Source. Fixes "/permission" endpo…
Browse files Browse the repository at this point in the history
…int (OHDSI#1293)

* Fixes permissions for newly created Source. Fixes "/permission" endpoint

* Remove unused line

* Preciser role search

* Preciser role search #2

* Preciser role search OHDSI#3
  • Loading branch information
pavgra authored and wivern committed Aug 13, 2019
1 parent 554169b commit 93cb1fd
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 153 deletions.
16 changes: 16 additions & 0 deletions src/main/java/org/ohdsi/webapi/security/PermissionController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.ohdsi.webapi.security.dto.AccessRequestDTO;
import org.ohdsi.webapi.security.dto.RoleDTO;
import org.ohdsi.webapi.security.model.EntityType;
import org.ohdsi.webapi.service.UserService;
import org.ohdsi.webapi.shiro.Entities.PermissionEntity;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.springframework.core.convert.ConversionService;
Expand All @@ -18,10 +20,13 @@
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Controller
@Path(value = "/permission")
Expand All @@ -39,6 +44,17 @@ public PermissionController(PermissionService permissionService, PermissionManag
this.conversionService = conversionService;
}

@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public List<UserService.Permission> getPermissions() {

Iterable<PermissionEntity> permissionEntities = this.permissionManager.getPermissions();
return StreamSupport.stream(permissionEntities.spliterator(), false)
.map(UserService.Permission::new)
.collect(Collectors.toList());
}

@GET
@Path("/access/suggest")
@Consumes(MediaType.APPLICATION_JSON)
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/ohdsi/webapi/security/PermissionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.ohdsi.webapi.security.model.EntityPermissionSchema;
import org.ohdsi.webapi.security.model.EntityPermissionSchemaResolver;
import org.ohdsi.webapi.security.model.EntityType;
import org.ohdsi.webapi.security.model.SourcePermissionSchema;
import org.ohdsi.webapi.shiro.Entities.PermissionEntity;
import org.ohdsi.webapi.shiro.Entities.PermissionRepository;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
Expand All @@ -13,6 +14,8 @@
import org.ohdsi.webapi.shiro.Entities.RoleRepository;
import org.ohdsi.webapi.shiro.Entities.UserEntity;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.ohdsi.webapi.source.Source;
import org.ohdsi.webapi.source.SourceRepository;
import org.springframework.aop.framework.Advised;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -33,7 +36,9 @@ public class PermissionService {
private final WebApplicationContext appContext;
private final PermissionManager permissionManager;
private final EntityPermissionSchemaResolver entityPermissionSchemaResolver;
private final SourcePermissionSchema sourcePermissionSchema;
private final RoleRepository roleRepository;
private final SourceRepository sourceRepository;
private final PermissionRepository permissionRepository;
private final RolePermissionRepository rolePermissionRepository;
private final ConversionService conversionService;
Expand All @@ -44,7 +49,9 @@ public PermissionService(
WebApplicationContext appContext,
PermissionManager permissionManager,
EntityPermissionSchemaResolver entityPermissionSchemaResolver,
SourcePermissionSchema sourcePermissionSchema,
RoleRepository roleRepository,
SourceRepository sourceRepository,
PermissionRepository permissionRepository,
RolePermissionRepository rolePermissionRepository,
ConversionService conversionService
Expand All @@ -53,7 +60,9 @@ public PermissionService(
this.appContext = appContext;
this.permissionManager = permissionManager;
this.entityPermissionSchemaResolver = entityPermissionSchemaResolver;
this.sourcePermissionSchema = sourcePermissionSchema;
this.roleRepository = roleRepository;
this.sourceRepository = sourceRepository;
this.permissionRepository = permissionRepository;
this.rolePermissionRepository = rolePermissionRepository;
this.conversionService = conversionService;
Expand All @@ -63,6 +72,11 @@ public PermissionService(
private void postConstruct() {

this.repositories = new Repositories(appContext);

// Migrated from Atlas security. Is it still required?
for (Source source : sourceRepository.findAll()) {
sourcePermissionSchema.addSourceUserRole(source);
}
}

public List<RoleEntity> suggestRoles(String roleSearch) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,19 @@ public class HibernateListenerConfigurer {
private EntityManagerFactory emf;

private final EntityPermissionSchemaResolver entityPermissionSchemaResolver;
private final PermissionManager permissionManager;

public HibernateListenerConfigurer(EntityPermissionSchemaResolver entityPermissionSchemaResolver, PermissionManager permissionManager) {
public HibernateListenerConfigurer(EntityPermissionSchemaResolver entityPermissionSchemaResolver) {

this.entityPermissionSchemaResolver = entityPermissionSchemaResolver;
this.permissionManager = permissionManager;
}

@PostConstruct
protected void init() {

SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(new EntityInsertEventListener(entityPermissionSchemaResolver, permissionManager));
registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(new EntityDeleteEventListener(entityPermissionSchemaResolver, permissionManager));
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(new EntityInsertEventListener(entityPermissionSchemaResolver));
registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(new EntityDeleteEventListener(entityPermissionSchemaResolver));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@
import org.ohdsi.webapi.model.CommonEntity;
import org.ohdsi.webapi.security.model.EntityPermissionSchema;
import org.ohdsi.webapi.security.model.EntityPermissionSchemaResolver;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

import java.util.Map;

public class EntityDeleteEventListener implements PostDeleteEventListener {

private final EntityPermissionSchemaResolver entityPermissionSchemaResolver;
private final PermissionManager permissionManager;

public EntityDeleteEventListener(EntityPermissionSchemaResolver entityPermissionSchemaResolver, PermissionManager permissionManager) {
public EntityDeleteEventListener(EntityPermissionSchemaResolver entityPermissionSchemaResolver) {

this.entityPermissionSchemaResolver = entityPermissionSchemaResolver;
this.permissionManager = permissionManager;
}

@Override
Expand All @@ -30,10 +25,7 @@ public void onPostDelete(PostDeleteEvent postDeleteEvent) {
CommonEntity commonEntity = (CommonEntity) entity;
EntityPermissionSchema permissionSchema = entityPermissionSchemaResolver.getForClass(commonEntity.getClass());
if (permissionSchema != null) {
new SimpleAsyncTaskExecutor().execute(() -> {
Map<String, String> permissionTemplates = permissionSchema.getAllPermissions();
permissionManager.removePermissionsFromTemplate(permissionTemplates, commonEntity.getId().toString());
});
new SimpleAsyncTaskExecutor().execute(() -> permissionSchema.onDelete(commonEntity));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import org.ohdsi.webapi.model.CommonEntity;
import org.ohdsi.webapi.security.model.EntityPermissionSchema;
import org.ohdsi.webapi.security.model.EntityPermissionSchemaResolver;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
Expand All @@ -19,15 +17,10 @@ public class EntityInsertEventListener implements PreInsertEventListener {
private static final Logger LOG = LoggerFactory.getLogger(EntityInsertEventListener.class);

private final EntityPermissionSchemaResolver entityPermissionSchemaResolver;
private final PermissionManager permissionManager;

public EntityInsertEventListener(
EntityPermissionSchemaResolver entityPermissionSchemaResolver,
PermissionManager permissionManager
) {
public EntityInsertEventListener(EntityPermissionSchemaResolver entityPermissionSchemaResolver) {

this.entityPermissionSchemaResolver = entityPermissionSchemaResolver;
this.permissionManager = permissionManager;
}

@Override
Expand All @@ -43,21 +36,15 @@ public boolean onPreInsert(PreInsertEvent event) {
// Fails if executed within the same thread
// http://anshuiitk.blogspot.com/2010/11/hibernate-pre-database-opertaion-event.html
Future<Boolean> future = new SimpleAsyncTaskExecutor().submit(() -> {
try {
String login = permissionManager.getSubjectName();
RoleEntity role = permissionManager.getUserPersonalRole(login);
permissionManager.addPermissionsFromTemplate(role, permissionSchema.getAllPermissions(), commonEntity.getId().toString());
return true;
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
return false;
}
permissionSchema.onInsert(commonEntity);
return true;
});
try {
if (future.get()) {
return false;
}
} catch (InterruptedException | ExecutionException e) {
} catch (InterruptedException | ExecutionException ex) {
LOG.error(ex.getMessage(), ex);
}
}
throw new RuntimeException();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package org.ohdsi.webapi.security.model;

import org.ohdsi.webapi.model.CommonEntity;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -10,6 +15,9 @@ public abstract class EntityPermissionSchema {
private final Map<String, String> readPermissions;
private final Map<String, String> writePermissions;

@Autowired
protected PermissionManager permissionManager;

public EntityPermissionSchema(EntityType entityType, Map<String, String> readPermissions, Map<String, String> writePermissions) {

this.entityType = entityType;
Expand Down Expand Up @@ -39,4 +47,22 @@ public Map<String, String> getAllPermissions() {
permissions.putAll(getWritePermissions());
return permissions;
}

public void onInsert(CommonEntity commonEntity) {

addPermissionsToCurrentUserFromTemplate(commonEntity, getAllPermissions());
}

public void onDelete(CommonEntity commonEntity) {

Map<String, String> permissionTemplates = getAllPermissions();
permissionManager.removePermissionsFromTemplate(permissionTemplates, commonEntity.getId().toString());
}

protected void addPermissionsToCurrentUserFromTemplate(CommonEntity commonEntity, Map<String, String> template) {

String login = permissionManager.getSubjectName();
RoleEntity role = permissionManager.getUserPersonalRole(login);
permissionManager.addPermissionsFromTemplate(role, template, commonEntity.getId().toString());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.ohdsi.webapi.security.model;

import org.ohdsi.webapi.model.CommonEntity;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
import org.ohdsi.webapi.source.Source;
import org.springframework.stereotype.Component;

import java.util.HashMap;
Expand Down Expand Up @@ -63,4 +66,47 @@ public SourcePermissionSchema() {

super(EntityType.SOURCE, readPermissions, writePermissions);
}

@Override
public void onInsert(CommonEntity commonEntity) {

addSourceUserRole(commonEntity);
addPermissionsToCurrentUserFromTemplate(commonEntity, getWritePermissions());
}

@Override
public void onDelete(CommonEntity commonEntity) {

super.onDelete(commonEntity);
dropSourceUserRole(commonEntity);
}

public void addSourceUserRole(CommonEntity commonEntity) {

Source source = (Source) commonEntity;
final String roleName = getSourceRoleName(source.getSourceKey());
final RoleEntity role;
if (permissionManager.roleExists(roleName)) {
role = permissionManager.getSystemRoleByName(roleName);
} else {
role = permissionManager.addRole(roleName, true);
}
permissionManager.addPermissionsFromTemplate(role, getReadPermissions(), source.getSourceKey());
}

private void dropSourceUserRole(CommonEntity commonEntity) {

Source source = (Source) commonEntity;
final String roleName = getSourceRoleName(source.getSourceKey());
if (permissionManager.roleExists(roleName)) {
RoleEntity role = permissionManager.getSystemRoleByName(roleName);
permissionManager.removePermissionsFromTemplate(getReadPermissions(), source.getSourceKey());
permissionManager.removeRole(role.getId());
}
}

private String getSourceRoleName(String sourceKey) {

return String.format("Source user (%s)", sourceKey);
}
}
31 changes: 10 additions & 21 deletions src/main/java/org/ohdsi/webapi/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
*
Expand Down Expand Up @@ -119,9 +121,9 @@ public User getCurrentUser() throws Exception {
@GET
@Path("user/{userId}/permissions")
@Produces(MediaType.APPLICATION_JSON)
public ArrayList<Permission> getUsersPermissions(@PathParam("userId") Long userId) throws Exception {
public List<Permission> getUsersPermissions(@PathParam("userId") Long userId) throws Exception {
Set<PermissionEntity> permissionEntities = this.authorizer.getUserPermissions(userId);
ArrayList<Permission> permissions = convertPermissions(permissionEntities);
List<Permission> permissions = convertPermissions(permissionEntities);
Collections.sort(permissions);
return permissions;
}
Expand Down Expand Up @@ -197,9 +199,9 @@ public void removeRole(@PathParam("roleId") Long roleId) {
@GET
@Path("role/{roleId}/permissions")
@Produces(MediaType.APPLICATION_JSON)
public ArrayList<Permission> getRolePermissions(@PathParam("roleId") Long roleId) throws Exception {
public List<Permission> getRolePermissions(@PathParam("roleId") Long roleId) throws Exception {
Set<PermissionEntity> permissionEntities = this.authorizer.getRolePermissions(roleId);
ArrayList<Permission> permissions = convertPermissions(permissionEntities);
List<Permission> permissions = convertPermissions(permissionEntities);
Collections.sort(permissions);
return permissions;
}
Expand Down Expand Up @@ -258,23 +260,10 @@ public void removeUserFromRole(@PathParam("roleId") Long roleId, @PathParam("use
}
}

@GET
@Path("permission")
@Produces(MediaType.APPLICATION_JSON)
public ArrayList<Permission> getPermissions() {
Iterable<PermissionEntity> permissionEntities = this.authorizer.getPermissions();
ArrayList<Permission> permissions = convertPermissions(permissionEntities);
return permissions;
}

private ArrayList<Permission> convertPermissions(final Iterable<PermissionEntity> permissionEntities) {
ArrayList<Permission> permissions = new ArrayList<>();
for (PermissionEntity permissionEntity : permissionEntities) {
Permission permission = new Permission(permissionEntity);
permissions.add(permission);
}

return permissions;
private List<Permission> convertPermissions(final Iterable<PermissionEntity> permissionEntities) {
return StreamSupport.stream(permissionEntities.spliterator(), false)
.map(UserService.Permission::new)
.collect(Collectors.toList());
}

private ArrayList<Role> convertRoles(final Iterable<RoleEntity> roleEntities) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ public interface RoleRepository extends CrudRepository<RoleEntity, Long> {

RoleEntity findById(Long id);

RoleEntity findByName(String name);

RoleEntity findByNameAndSystemRole(String name, Boolean isSystem);

List<RoleEntity> findByNameIgnoreCaseContaining(String roleSearch);
Expand Down
Loading

0 comments on commit 93cb1fd

Please sign in to comment.