private void executeCountQuery( final HttpServerRequest request, String collection, JsonObject query, final int expectedCountResult, final Handler<Boolean> handler) { request.pause(); mongo.count( collection, query, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> event) { request.resume(); JsonObject res = event.body(); handler.handle( res != null && "ok".equals(res.getString("status")) && expectedCountResult == res.getInteger("count")); } }); }
public class WorkspaceResourcesProvider implements ResourcesProvider { private MongoDb mongo = MongoDb.getInstance(); @Override public void authorize( final HttpServerRequest request, final Binding binding, final UserInfos user, final Handler<Boolean> handler) { final String serviceMethod = binding.getServiceMethod(); if (serviceMethod != null && serviceMethod.startsWith(WorkspaceService.class.getName())) { String method = serviceMethod.substring(WorkspaceService.class.getName().length() + 1); switch (method) { case "getDocument": authorizeGetDocument(request, user, binding.getServiceMethod(), handler); break; case "commentDocument": case "commentFolder": case "updateDocument": case "moveDocument": case "moveTrash": case "copyDocument": case "deleteDocument": case "restoreTrash": case "shareJson": case "shareJsonSubmit": case "removeShare": case "getRevision": case "listRevisions": authorizeDocument(request, user, binding.getServiceMethod(), handler); break; case "deleteRevision": authorizeRevisionOwner( request, user, binding.getServiceMethod(), new Handler<Boolean>() { public void handle(Boolean check) { if (check) { authorizeDocument( request, user, serviceMethod.substring(0, WorkspaceService.class.getName().length() + 1) + "updateDocument", handler); } else { authorizeDocument(request, user, binding.getServiceMethod(), handler); } } }); break; case "deleteComment": authorizeCommentOwner( request, user, binding.getServiceMethod(), new Handler<Boolean>() { public void handle(Boolean check) { if (check) { authorizeDocument( request, user, serviceMethod.substring(0, WorkspaceService.class.getName().length() + 1) + "commentDocument", handler); } else { authorizeDocument(request, user, binding.getServiceMethod(), handler); } } }); break; case "moveDocuments": case "copyDocuments": authorizeDocuments(request, user, binding.getServiceMethod(), handler); break; case "renameDocument": case "renameFolder": authorizeOwner(request, user, binding.getServiceMethod(), handler); break; default: handler.handle(false); } } else if (serviceMethod != null && serviceMethod.startsWith(QuotaController.class.getName())) { String method = serviceMethod.substring(QuotaController.class.getName().length() + 1); switch (method) { case "getQuota": isUserOrAdmin(request, user, handler); break; case "update": isAdminFromUsers(request, user, handler); break; case "getQuotaStructure": isAdmin(request, user, handler); break; case "updateDefault": case "getQuotaGlobal": isSuperAdmin(user, handler); break; case "getDefault": UserInfos.Function adminLocal = getFunction(user, handler); if (adminLocal != null) handler.handle(true); break; default: handler.handle(false); } } } private void isUserOrAdmin( HttpServerRequest request, UserInfos user, final Handler<Boolean> handler) { final String userId = request.params().get("userId"); if (user.getUserId().equals(userId)) { handler.handle(true); return; } final UserInfos.Function adminLocal = getFunction(user, handler); if (adminLocal == null) return; String query = "MATCH (s:Structure)<-[:DEPENDS]-(:ProfileGroup)<-[:IN]-(u:User {id : {userId}}) " + "WHERE s.id IN {structures} " + "RETURN count(*) > 0 as exists "; JsonObject params = new JsonObject() .putArray("structures", new JsonArray(adminLocal.getScope().toArray())) .putString("userId", userId); Neo4j.getInstance() .execute( query, params, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { JsonArray res = message.body().getArray("result"); handler.handle( "ok".equals(message.body().getString("status")) && res != null && res.size() == 1 && res.<JsonObject>get(0).getBoolean("exists", false)); } }); } private void isAdminFromUsers( HttpServerRequest request, UserInfos user, final Handler<Boolean> handler) { final UserInfos.Function adminLocal = getFunction(user, handler); if (adminLocal == null) return; RequestUtils.bodyToJson( request, new Handler<JsonObject>() { @Override public void handle(JsonObject object) { String query = "MATCH (s:Structure)<-[:DEPENDS]-(:ProfileGroup)<-[:IN]-(u:User) " + "WHERE s.id IN {structures} AND u.id IN {users} " + "RETURN count(distinct u) as nb "; final JsonArray users = object.getArray("users", new JsonArray()); JsonObject params = new JsonObject() .putArray("structures", new JsonArray(adminLocal.getScope().toArray())) .putArray("users", users); Neo4j.getInstance() .execute( query, params, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { JsonArray res = message.body().getArray("result"); handler.handle( "ok".equals(message.body().getString("status")) && res != null && res.size() == 1 && res.<JsonObject>get(0) .getInteger("nb", -1) .equals(users.size())); } }); } }); } private void isAdmin(HttpServerRequest request, UserInfos user, Handler<Boolean> handler) { UserInfos.Function adminLocal = getFunction(user, handler); if (adminLocal == null) return; String structureId = request.params().get("structureId"); handler.handle(adminLocal.getScope().contains(structureId)); } private UserInfos.Function getFunction(UserInfos user, Handler<Boolean> handler) { Map<String, UserInfos.Function> functions = user.getFunctions(); if (functions == null || functions.isEmpty()) { handler.handle(false); return null; } if (functions.containsKey(DefaultFunctions.SUPER_ADMIN)) { handler.handle(true); return null; } UserInfos.Function adminLocal = functions.get(DefaultFunctions.ADMIN_LOCAL); if (adminLocal == null || adminLocal.getScope() == null) { handler.handle(false); return null; } return adminLocal; } private void isSuperAdmin(UserInfos user, Handler<Boolean> handler) { Map<String, UserInfos.Function> functions = user.getFunctions(); if (functions == null || functions.isEmpty()) { handler.handle(false); return; } handler.handle(functions.containsKey(DefaultFunctions.SUPER_ADMIN)); } private void authorizeDocuments( HttpServerRequest request, UserInfos user, String serviceMethod, Handler<Boolean> handler) { String ids = request.params().get("ids"); if (ids != null && !ids.trim().isEmpty()) { JsonArray idsArray = new JsonArray(ids.split(",")); String query = "{ \"_id\": { \"$in\" : " + idsArray.encode() + "}, " + "\"$or\" : [{ \"owner\": \"" + user.getUserId() + "\"}, {\"shared\" : { \"$elemMatch\" : " + orSharedElementMatch(user, serviceMethod) + "}}]}"; executeCountQuery( request, DocumentDao.DOCUMENTS_COLLECTION, new JsonObject(query), idsArray.size(), handler); } else { handler.handle(false); } } private String orSharedElementMatch(UserInfos user, String serviceMethod) { String s = serviceMethod.replaceAll("\\.", "-"); StringBuilder sb = new StringBuilder(); if (user.getGroupsIds() != null) { for (String groupId : user.getGroupsIds()) { sb.append(", { \"groupId\": \"" + groupId + "\", \"" + s + "\": true }"); } } return "{ \"$or\" : [" + "{ \"userId\": \"" + user.getUserId() + "\", \"" + s + "\": true }" + sb.toString() + "]}"; } private void authorizeGetDocument( HttpServerRequest request, UserInfos user, String serviceMethod, Handler<Boolean> handler) { String id = request.params().get("id"); if (id != null && !id.trim().isEmpty()) { String query = "{ \"_id\": \"" + id + "\", \"$or\" : [{ \"owner\": \"" + user.getUserId() + "\"}, { \"protected\" : true}, { \"public\" : true}, {\"shared\" : { \"$elemMatch\" : " + orSharedElementMatch(user, serviceMethod) + "}}]}"; executeCountQuery( request, DocumentDao.DOCUMENTS_COLLECTION, new JsonObject(query), 1, handler); } else { handler.handle(false); } } private void authorizeDocument( HttpServerRequest request, UserInfos user, String serviceMethod, Handler<Boolean> handler) { String id = request.params().get("id"); if (id != null && !id.trim().isEmpty()) { String query = "{ \"_id\": \"" + id + "\", \"$or\" : [{ \"owner\": \"" + user.getUserId() + "\"}, {\"shared\" : { \"$elemMatch\" : " + orSharedElementMatch(user, serviceMethod) + "}}]}"; executeCountQuery( request, DocumentDao.DOCUMENTS_COLLECTION, new JsonObject(query), 1, handler); } else { handler.handle(false); } } private void authorizeOwner( HttpServerRequest request, UserInfos user, String serviceMethod, Handler<Boolean> handler) { String id = request.params().get("id"); if (id != null && !id.trim().isEmpty()) { String query = "{ \"_id\": \"" + id + "\", \"owner\": \"" + user.getUserId() + "\" }"; executeCountQuery( request, DocumentDao.DOCUMENTS_COLLECTION, new JsonObject(query), 1, handler); } else { handler.handle(false); } } private void authorizeRevisionOwner( HttpServerRequest request, UserInfos user, String serviceMethod, final Handler<Boolean> handler) { final String revisionId = request.params().get("revisionId"); JsonObject query = new JsonObject( "{ \"_id\": \"" + revisionId + "\", \"userId\": \"" + user.getUserId() + "\" }"); if (revisionId != null && !revisionId.trim().isEmpty()) { executeCountQuery(request, Workspace.REVISIONS_COLLECTION, query, 1, handler); } else { handler.handle(false); } } private void authorizeCommentOwner( HttpServerRequest request, UserInfos user, String serviceMethod, final Handler<Boolean> handler) { final String id = request.params().get("id"); final String commentId = request.params().get("commentId"); JsonObject query = new JsonObject( "{ \"_id\": \"" + id + "\", \"comments.id\": \"" + commentId + "\", \"comments.author\": \"" + user.getUserId() + "\" }"); if (commentId != null && !commentId.trim().isEmpty()) { executeCountQuery(request, DocumentDao.DOCUMENTS_COLLECTION, query, 1, handler); } else { handler.handle(false); } } private void executeCountQuery( final HttpServerRequest request, String collection, JsonObject query, final int expectedCountResult, final Handler<Boolean> handler) { request.pause(); mongo.count( collection, query, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> event) { request.resume(); JsonObject res = event.body(); handler.handle( res != null && "ok".equals(res.getString("status")) && expectedCountResult == res.getInteger("count")); } }); } }