killbill-memoizeit

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SecurityResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SecurityResource.java
index b6f7b27..77d72c2 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SecurityResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SecurityResource.java
@@ -143,6 +143,18 @@ public class SecurityResource extends JaxRsResourceBase {
         return Response.status(Status.OK).build();
     }
 
+    @TimedResource
+    @GET
+    @Produces(APPLICATION_JSON)
+    @Path("/users/{username:" + ANYTHING_PATTERN + "}/roles")
+    @ApiOperation(value = "Get roles associated to a user")
+    public Response getUserRoles(@PathParam("username") final String username,
+                                 @javax.ws.rs.core.Context final HttpServletRequest request,
+                                 @javax.ws.rs.core.Context final UriInfo uriInfo) throws SecurityApiException {
+        final List<String> roles = securityApi.getUserRoles(username, context.createContext(request));
+        final UserRolesJson userRolesJson = new UserRolesJson(username, null, roles);
+        return Response.status(Status.OK).entity(userRolesJson).build();
+    }
 
     @TimedResource
     @PUT
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
index 07c8737..7dc71e7 100644
--- a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
@@ -66,7 +66,7 @@ public class DefaultUserDao implements UserDao {
                                                            password, salt.toBase64(), securityConfig.getShiroNbHashIterations()).toBase64();
 
         final DateTime createdDate = clock.getUTCNow();
-        dbi.inTransaction(new TransactionCallback<Void>() {
+        inTransactionWithExceptionHandling(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
                 final UserRolesSqlDao userRolesSqlDao = handle.attach(UserRolesSqlDao.class);
@@ -96,9 +96,9 @@ public class DefaultUserDao implements UserDao {
     }
 
     @Override
-    public void addRoleDefinition(final String role, final List<String> permissions, final String createdBy) {
+    public void addRoleDefinition(final String role, final List<String> permissions, final String createdBy)  throws SecurityApiException {
         final DateTime createdDate = clock.getUTCNow();
-        dbi.inTransaction(new TransactionCallback<Void>() {
+        inTransactionWithExceptionHandling(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
                 final RolesPermissionsSqlDao rolesPermissionsSqlDao = handle.attach(RolesPermissionsSqlDao.class);
@@ -132,7 +132,7 @@ public class DefaultUserDao implements UserDao {
         final String hashedPasswordBase64 = new SimpleHash(KillbillCredentialsMatcher.HASH_ALGORITHM_NAME,
                                                            password, salt.toBase64(), securityConfig.getShiroNbHashIterations()).toBase64();
 
-        dbi.inTransaction(new TransactionCallback<Void>() {
+        inTransactionWithExceptionHandling(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
 
@@ -150,7 +150,7 @@ public class DefaultUserDao implements UserDao {
 
     @Override
     public void updateUserRoles(final String username, final List<String> roles, final String updatedBy) throws SecurityApiException {
-        dbi.inTransaction(new TransactionCallback<Void>() {
+        inTransactionWithExceptionHandling(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
                 final DateTime updatedDate = clock.getUTCNow();
@@ -192,7 +192,7 @@ public class DefaultUserDao implements UserDao {
 
     @Override
     public void invalidateUser(final String username, final String updatedBy) throws SecurityApiException {
-        dbi.inTransaction(new TransactionCallback<Void>() {
+        inTransactionWithExceptionHandling(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
                 final DateTime updatedDate = clock.getUTCNow();
@@ -206,4 +206,24 @@ public class DefaultUserDao implements UserDao {
             }
         });
     }
+
+    private <T> T inTransactionWithExceptionHandling(final TransactionCallback<T> callback) throws SecurityApiException {
+        // Similar to EntitySqlDaoTransactionalJdbiWrapper#execute
+        try {
+            return dbi.inTransaction(callback);
+        } catch (final RuntimeException e) {
+            throwSecurityApiException(e);
+            return null;
+        }
+    }
+
+    private void throwSecurityApiException(final Throwable e) throws SecurityApiException {
+        if (e.getCause() != null && e.getCause().getClass().isAssignableFrom(SecurityApiException.class)) {
+            throw (SecurityApiException) e.getCause();
+        } else if (e.getCause() != null) {
+            throwSecurityApiException(e.getCause());
+        } else {
+            throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e);
+        }
+    }
 }
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/UserDao.java b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/UserDao.java
index bb0ab0d..142e13d 100644
--- a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/UserDao.java
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/UserDao.java
@@ -27,7 +27,7 @@ public interface UserDao {
 
     public List<UserRolesModelDao> getUserRoles(String username);
 
-    public void addRoleDefinition(String role, List<String> permissions, String createdBy);
+    public void addRoleDefinition(String role, List<String> permissions, String createdBy) throws SecurityApiException;
 
     public List<RolesPermissionsModelDao> getRoleDefinition(String role);