org.entcore.common.share.impl.MongoDbShareService.java Source code

Java tutorial

Introduction

Here is the source code for org.entcore.common.share.impl.MongoDbShareService.java

Source

/* Copyright  "Open Digital Education", 2014
 *
 * This program is published by "Open Digital Education".
 * You must indicate the name of the software and the company in any production /contribution
 * using the software and indicate on the home page of the software industry in question,
 * "powered by Open Digital Education" with a reference to the website: https://opendigitaleducation.com/.
 *
 * This program is free software, licensed under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation, version 3 of the License.
 *
 * You can redistribute this application and/or modify it since you respect the terms of the GNU Affero General Public License.
 * If you modify the source code and then use this modified source code in your creation, you must make available the source code of your modifications.
 *
 * You should have received a copy of the GNU Affero General Public License along with the software.
 * If not, please see : <http://www.gnu.org/licenses/>. Full compliance requires reading the terms of this license and following its directives.
    
 *
 */

package org.entcore.common.share.impl;

import com.mongodb.QueryBuilder;
import fr.wseduc.mongodb.MongoDb;
import fr.wseduc.mongodb.MongoQueryBuilder;
import fr.wseduc.mongodb.MongoUpdateBuilder;
import fr.wseduc.webutils.*;
import fr.wseduc.webutils.security.SecuredAction;
import io.vertx.core.Handler;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.Message;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import static fr.wseduc.webutils.Utils.getOrElse;

public class MongoDbShareService extends GenericShareService {

    private final String collection;
    private final MongoDb mongo;

    public MongoDbShareService(EventBus eb, MongoDb mongo, String collection,
            Map<String, SecuredAction> securedActions, Map<String, List<String>> groupedActions) {
        super(eb, securedActions, groupedActions);
        this.mongo = mongo;
        this.collection = collection;
    }

    @Override
    public void shareInfos(final String userId, String resourceId, final String acceptLanguage, final String search,
            final Handler<Either<String, JsonObject>> handler) {
        if (userId == null || userId.trim().isEmpty()) {
            handler.handle(new Either.Left<String, JsonObject>("Invalid userId."));
            return;
        }
        if (resourceId == null || resourceId.trim().isEmpty()) {
            handler.handle(new Either.Left<String, JsonObject>("Invalid resourceId."));
            return;
        }
        final JsonArray actions = getResoureActions(securedActions);
        QueryBuilder query = QueryBuilder.start("_id").is(resourceId);
        JsonObject keys = new JsonObject().put("shared", 1);
        mongo.findOne(collection, MongoQueryBuilder.build(query), keys, new Handler<Message<JsonObject>>() {
            @Override
            public void handle(Message<JsonObject> event) {
                if ("ok".equals(event.body().getString("status"))) {
                    JsonArray shared = event.body().getJsonObject("result", new JsonObject()).getJsonArray("shared",
                            new fr.wseduc.webutils.collections.JsonArray());
                    JsonObject gs = new JsonObject();
                    JsonObject us = new JsonObject();
                    for (Object o : shared) {
                        if (!(o instanceof JsonObject))
                            continue;
                        JsonObject userShared = (JsonObject) o;
                        JsonArray a = new fr.wseduc.webutils.collections.JsonArray();
                        for (String attrName : userShared.fieldNames()) {
                            if ("userId".equals(attrName) || "groupId".equals(attrName)) {
                                continue;
                            }
                            if (groupedActions != null && groupedActions.containsKey(attrName)) {
                                for (String action : groupedActions.get(attrName)) {
                                    a.add(action.replaceAll("\\.", "-"));
                                }
                            } else {
                                a.add(attrName);
                            }
                        }
                        final String g = userShared.getString("groupId");
                        String u;
                        if (g != null) {
                            gs.put(g, a);
                        } else if ((u = userShared.getString("userId")) != null && !u.equals(userId)) {
                            us.put(u, a);
                        }
                    }
                    getShareInfos(userId, actions, gs, us, acceptLanguage, search, new Handler<JsonObject>() {
                        @Override
                        public void handle(JsonObject event) {
                            if (event != null && event.size() == 3) {
                                handler.handle(new Either.Right<String, JsonObject>(event));
                            } else {
                                handler.handle(
                                        new Either.Left<String, JsonObject>("Error finding shared resource."));
                            }
                        }
                    });
                } else {
                    handler.handle(new Either.Left<String, JsonObject>(
                            event.body().getString("error", "Error finding shared resource.")));
                }
            }
        });
    }

    @Override
    public void groupShare(final String userId, final String groupShareId, final String resourceId,
            final List<String> actions, final Handler<Either<String, JsonObject>> handler) {
        inShare(resourceId, groupShareId, true, new Handler<Boolean>() {

            @Override
            public void handle(Boolean event) {
                if (Boolean.TRUE.equals(event)) {
                    share(resourceId, groupShareId, actions, true, handler);
                } else {
                    groupShareValidation(userId, groupShareId, actions, new Handler<Either<String, JsonObject>>() {
                        @Override
                        public void handle(Either<String, JsonObject> event) {
                            if (event.isRight()) {
                                share(resourceId, groupShareId, actions, true, handler);
                            } else {
                                handler.handle(event);
                            }
                        }
                    });
                }
            }
        });
    }

    private void inShare(String resourceId, String shareId, boolean group, final Handler<Boolean> handler) {
        QueryBuilder query = QueryBuilder.start("_id").is(resourceId).put("shared")
                .elemMatch(QueryBuilder.start(group ? "groupId" : "userId").is(shareId).get());
        mongo.count(collection, MongoQueryBuilder.build(query), new Handler<Message<JsonObject>>() {
            @Override
            public void handle(Message<JsonObject> event) {
                JsonObject res = event.body();
                handler.handle(res != null && "ok".equals(res.getString("status")) && 1 == res.getInteger("count"));
            }
        });
    }

    private void share(String resourceId, final String groupShareId, final List<String> actions, boolean isGroup,
            final Handler<Either<String, JsonObject>> handler) {
        final String shareIdAttr = isGroup ? "groupId" : "userId";
        QueryBuilder query = QueryBuilder.start("_id").is(resourceId);
        JsonObject keys = new JsonObject().put("shared", 1);
        final JsonObject q = MongoQueryBuilder.build(query);
        mongo.findOne(collection, q, keys, new Handler<Message<JsonObject>>() {
            @Override
            public void handle(Message<JsonObject> event) {
                if ("ok".equals(event.body().getString("status")) && event.body().getJsonObject("result") != null) {
                    JsonArray actual = event.body().getJsonObject("result").getJsonArray("shared",
                            new fr.wseduc.webutils.collections.JsonArray());
                    boolean exist = false;
                    for (int i = 0; i < actual.size(); i++) {
                        JsonObject s = actual.getJsonObject(i);
                        String id = s.getString(shareIdAttr);
                        if (groupShareId.equals(id)) {
                            for (String action : actions) {
                                s.put(action, true);
                            }
                            if (groupedActions != null) {
                                for (Map.Entry<String, List<String>> ga : groupedActions.entrySet()) {
                                    if (actions.containsAll(ga.getValue())) {
                                        s.put(ga.getKey(), true);
                                    }
                                }
                            }
                            exist = true;
                            break;
                        }
                    }
                    final AtomicBoolean notifyTimeline = new AtomicBoolean(false);
                    if (!exist) {
                        JsonObject t = new JsonObject().put(shareIdAttr, groupShareId);
                        actual.add(t);
                        for (String action : actions) {
                            t.put(action, true);
                        }
                        if (groupedActions != null) {
                            for (Map.Entry<String, List<String>> ga : groupedActions.entrySet()) {
                                if (actions.containsAll(ga.getValue())) {
                                    t.put(ga.getKey(), true);
                                }
                            }
                        }
                        notifyTimeline.set(true);
                    }
                    MongoUpdateBuilder updateQuery = new MongoUpdateBuilder().set("shared", actual);
                    mongo.update(collection, q, updateQuery.build(), new Handler<Message<JsonObject>>() {
                        @Override
                        public void handle(Message<JsonObject> res) {
                            if (notifyTimeline.get()) {
                                JsonObject notify = new JsonObject();
                                notify.put(shareIdAttr, groupShareId);
                                res.body().put("notify-timeline", notify);
                            }
                            handler.handle(Utils.validResult(res));
                        }
                    });
                } else {
                    handler.handle(new Either.Left<String, JsonObject>("Resource not found."));
                }
            }
        });
    }

    @Override
    public void userShare(final String userId, final String userShareId, final String resourceId,
            final List<String> actions, final Handler<Either<String, JsonObject>> handler) {
        inShare(resourceId, userShareId, false, new Handler<Boolean>() {

            @Override
            public void handle(Boolean event) {
                if (Boolean.TRUE.equals(event)) {
                    share(resourceId, userShareId, actions, false, handler);
                } else {
                    userShareValidation(userId, userShareId, actions, new Handler<Either<String, JsonObject>>() {
                        @Override
                        public void handle(Either<String, JsonObject> event) {
                            if (event.isRight()) {
                                share(resourceId, userShareId, actions, false, handler);
                            } else {
                                handler.handle(event);
                            }
                        }
                    });
                }
            }
        });
    }

    @Override
    public void removeGroupShare(String groupId, String resourceId, List<String> actions,
            Handler<Either<String, JsonObject>> handler) {
        removeShare(resourceId, groupId, actions, true, handler);
    }

    @Override
    public void removeUserShare(String userId, String resourceId, List<String> actions,
            Handler<Either<String, JsonObject>> handler) {
        removeShare(resourceId, userId, actions, false, handler);
    }

    @Override
    public void share(String userId, String resourceId, JsonObject share,
            Handler<Either<String, JsonObject>> handler) {
        shareValidation(resourceId, userId, share, res -> {
            if (res.isRight()) {
                final JsonObject query = new JsonObject().put("_id", resourceId);
                final JsonObject update = new JsonObject().put("$set",
                        new JsonObject().put("shared", res.right().getValue().getJsonArray("shared")));
                final JsonObject keys = new JsonObject().put("shared", 1);
                mongo.findAndModify(collection, query, update, null, keys, mongoRes -> {
                    if ("ok".equals(mongoRes.body().getString("status"))) {
                        JsonArray oldShared = getOrElse(mongoRes.body().getJsonObject("result"), new JsonObject())
                                .getJsonArray("shared");
                        JsonArray members = res.right().getValue().getJsonArray("notify-members");
                        getNotifyMembers(handler, oldShared, members,
                                (m -> getOrElse(((JsonObject) m).getString("groupId"),
                                        ((JsonObject) m).getString("userId"))));
                    } else {
                        handler.handle(new Either.Left<>(mongoRes.body().getString("message")));
                    }
                });
            } else {
                handler.handle(res);
            }
        });
    }

    private void removeShare(String resourceId, final String shareId, List<String> removeActions, boolean isGroup,
            final Handler<Either<String, JsonObject>> handler) {
        final String shareIdAttr = isGroup ? "groupId" : "userId";
        final List<String> actions = findRemoveActions(removeActions);
        QueryBuilder query = QueryBuilder.start("_id").is(resourceId);
        JsonObject keys = new JsonObject().put("shared", 1);
        final JsonObject q = MongoQueryBuilder.build(query);
        mongo.findOne(collection, q, keys, new Handler<Message<JsonObject>>() {
            @Override
            public void handle(Message<JsonObject> event) {
                if ("ok".equals(event.body().getString("status")) && event.body().getJsonObject("result") != null) {
                    JsonArray actual = event.body().getJsonObject("result").getJsonArray("shared",
                            new fr.wseduc.webutils.collections.JsonArray());
                    JsonArray shared = new fr.wseduc.webutils.collections.JsonArray();
                    for (int i = 0; i < actual.size(); i++) {
                        JsonObject s = actual.getJsonObject(i);
                        String id = s.getString(shareIdAttr);
                        if (shareId.equals(id)) {
                            if (actions != null) {
                                for (String action : actions) {
                                    s.remove(action);
                                }
                                if (s.size() > 1) {
                                    shared.add(s);
                                }
                            }
                        } else {
                            shared.add(s);
                        }
                    }
                    MongoUpdateBuilder updateQuery = new MongoUpdateBuilder().set("shared", shared);
                    mongo.update(collection, q, updateQuery.build(), new Handler<Message<JsonObject>>() {
                        @Override
                        public void handle(Message<JsonObject> res) {
                            handler.handle(Utils.validResult(res));
                        }
                    });
                } else {
                    handler.handle(new Either.Left<String, JsonObject>("Resource not found."));
                }
            }
        });
    }

    @Override
    protected void prepareSharedArray(String resourceId, String type, JsonArray shared, String attr,
            Set<String> actions) {
        JsonObject el = new JsonObject().put(type, attr);
        for (String action : actions) {
            el.put(action, true);
        }
        shared.add(el);
    }

}