org.entcore.blog.controllers.BlogController.java Source code

Java tutorial

Introduction

Here is the source code for org.entcore.blog.controllers.BlogController.java

Source

/*
 * Copyright  "Open Digital Education" (SAS WebServices pour lEducation?), 2014
 *
 * This program is published by "Open Digital Education" (SAS WebServices pour lEducation?).
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.entcore.blog.controllers;

import static org.entcore.common.http.response.DefaultResponseHandler.arrayResponseHandler;
import static org.entcore.common.http.response.DefaultResponseHandler.defaultResponseHandler;
import static org.entcore.common.user.UserUtils.getUserInfos;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.entcore.blog.Blog;
import org.entcore.blog.services.BlogService;
import org.entcore.blog.services.BlogTimelineService;
import org.entcore.blog.services.PostService;
import org.entcore.blog.services.impl.DefaultBlogService;
import org.entcore.blog.services.impl.DefaultBlogTimelineService;
import org.entcore.blog.services.impl.DefaultPostService;
import org.entcore.common.events.EventStore;
import org.entcore.common.events.EventStoreFactory;
import org.entcore.common.http.request.ActionsUtils;
import org.entcore.common.neo4j.Neo;
import org.entcore.common.share.ShareService;
import org.entcore.common.share.impl.MongoDbShareService;
import org.entcore.common.user.UserInfos;
import org.entcore.common.utils.StringUtils;
import org.vertx.java.core.http.RouteMatcher;

import fr.wseduc.mongodb.MongoDb;
import fr.wseduc.rs.Delete;
import fr.wseduc.rs.Get;
import fr.wseduc.rs.Post;
import fr.wseduc.rs.Put;
import fr.wseduc.security.ActionType;
import fr.wseduc.security.SecuredAction;
import fr.wseduc.webutils.Either;
import fr.wseduc.webutils.I18n;
import fr.wseduc.webutils.http.BaseController;
import fr.wseduc.webutils.http.Renders;
import fr.wseduc.webutils.request.RequestUtils;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

public class BlogController extends BaseController {

    private BlogService blog;
    private PostService postService;
    private BlogTimelineService timelineService;
    private ShareService shareService;
    private EventStore eventStore;

    private enum BlogEvent {
        ACCESS
    }

    public void init(Vertx vertx, JsonObject config, RouteMatcher rm,
            Map<String, fr.wseduc.webutils.security.SecuredAction> securedActions) {
        super.init(vertx, config, rm, securedActions);
        MongoDb mongo = MongoDb.getInstance();
        this.blog = new DefaultBlogService(mongo, config.getInteger("blog-paging-size", 30),
                config.getInteger("blog-search-word-min-size", 4));
        this.postService = new DefaultPostService(mongo, config.getInteger("post-search-word-min-size", 4),
                PostController.LIST_ACTION);
        this.timelineService = new DefaultBlogTimelineService(vertx, eb, config, new Neo(vertx, eb, log), mongo);
        final Map<String, List<String>> groupedActions = new HashMap<>();
        groupedActions.put("manager", loadManagerActions(securedActions.values()));
        this.shareService = new MongoDbShareService(eb, mongo, "blogs", securedActions, groupedActions);
        eventStore = EventStoreFactory.getFactory().getEventStore(Blog.class.getSimpleName());
    }

    @Get("")
    @SecuredAction("blog.view")
    public void blog(HttpServerRequest request) {
        renderView(request);
        eventStore.createAndStoreEvent(BlogEvent.ACCESS.name(), request);
    }

    @Get("/print/blog")
    @SecuredAction("blog.print")
    public void print(HttpServerRequest request) {
        renderView(request, new JsonObject().put("printBlogId", request.params().get("blog")), "print.html", null);
    }

    // TODO improve fields matcher and validater
    @Post("")
    @SecuredAction("blog.create")
    public void create(final HttpServerRequest request) {
        RequestUtils.bodyToJson(request, new Handler<JsonObject>() {
            public void handle(final JsonObject data) {
                getUserInfos(eb, request, new Handler<UserInfos>() {
                    @Override
                    public void handle(final UserInfos user) {
                        if (user != null) {
                            blog.create(data, user, defaultResponseHandler(request));
                        } else {
                            unauthorized(request);
                        }
                    }
                });
            }
        });
    }

    @Put("/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void update(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }
        RequestUtils.bodyToJson(request, new Handler<JsonObject>() {
            public void handle(JsonObject data) {
                blog.update(blogId, data, new Handler<Either<String, JsonObject>>() {
                    @Override
                    public void handle(Either<String, JsonObject> event) {
                        if (event.isRight()) {
                            renderJson(request, event.right().getValue());
                        } else {
                            JsonObject error = new JsonObject().put("error", event.left().getValue());
                            renderJson(request, error, 400);
                        }
                    }
                });
            }
        });
    }

    private String getBlogUri(HttpServerRequest request, String blogId) {
        return pathPrefix + "#/view/" + blogId;
    }

    @Delete("/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void delete(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }

        blog.delete(blogId, new Handler<Either<String, JsonObject>>() {
            @Override
            public void handle(Either<String, JsonObject> event) {
                if (event.isRight()) {
                    renderJson(request, event.right().getValue(), 204);
                } else {
                    JsonObject error = new JsonObject().put("error", event.left().getValue());
                    renderJson(request, error, 400);
                }
            }
        });
    }

    @Get("/:blogId")
    @SecuredAction(value = "blog.read", type = ActionType.RESOURCE)
    public void get(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }
        blog.get(blogId, defaultResponseHandler(request));
    }

    @Get("/counter/:blogId")
    @SecuredAction(value = "blog.posts.counter", type = ActionType.AUTHENTICATED)
    public void postCounter(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (StringUtils.isEmpty(blogId)) {
            badRequest(request);
            return;
        }

        getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(final UserInfos user) {
                if (user != null) {
                    postService.counter(blogId, user, new Handler<Either<String, JsonArray>>() {
                        public void handle(Either<String, JsonArray> event) {
                            if (event.isLeft()) {
                                arrayResponseHandler(request).handle(event);
                                ;
                                return;
                            }

                            final JsonArray blogs = event.right().getValue();

                            int countPublished = 0;
                            int countDraft = 0;
                            int countSubmitted = 0;
                            int countAll = 0;

                            final JsonObject result = new JsonObject();

                            for (Object blogObj : blogs) {
                                final String blogState = ((JsonObject) blogObj).getString("state");
                                if (PostService.StateType.DRAFT.name().equals(blogState)) {
                                    countDraft++;
                                } else if (PostService.StateType.PUBLISHED.name().equals(blogState)) {
                                    countPublished++;
                                } else if (PostService.StateType.SUBMITTED.name().equals(blogState)) {
                                    countSubmitted++;
                                }
                            }

                            countAll = countDraft + countPublished + countSubmitted;

                            result.put("countPublished", countPublished);
                            result.put("countDraft", countDraft);
                            result.put("countSubmitted", countSubmitted);
                            result.put("countAll", countAll);

                            Renders.renderJson(request, result);
                        }
                    });
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Get("/list/all")
    @SecuredAction("blog.list")
    public void list(final HttpServerRequest request) {
        getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(final UserInfos user) {
                if (user != null) {
                    final Integer page;

                    try {
                        page = (request.params().get("page") != null)
                                ? Integer.parseInt(request.params().get("page"))
                                : null;
                    } catch (NumberFormatException e) {
                        badRequest(request, e.getMessage());
                        return;
                    }

                    final String search = request.params().get("search");

                    blog.list(user, page, search, new Handler<Either<String, JsonArray>>() {
                        public void handle(Either<String, JsonArray> event) {
                            if (event.isLeft()) {
                                arrayResponseHandler(request).handle(event);
                                ;
                                return;
                            }

                            final JsonArray blogs = event.right().getValue();

                            if (blogs.size() < 1) {
                                renderJson(request, new JsonArray());
                                return;
                            }

                            final AtomicInteger countdown = new AtomicInteger(blogs.size());
                            final Handler<Void> finalHandler = new Handler<Void>() {
                                public void handle(Void v) {
                                    if (countdown.decrementAndGet() <= 0) {
                                        renderJson(request, blogs);
                                    }
                                }
                            };

                            for (Object blogObj : blogs) {
                                final JsonObject blog = (JsonObject) blogObj;

                                postService.list(blog.getString("_id"), PostService.StateType.PUBLISHED, user, null,
                                        2, null, new Handler<Either<String, JsonArray>>() {
                                            public void handle(Either<String, JsonArray> event) {
                                                if (event.isRight()) {
                                                    blog.put("fetchPosts", event.right().getValue());
                                                }
                                                finalHandler.handle(null);
                                            }
                                        });
                            }

                        }
                    });
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Get("/linker")
    public void listBlogsIds(final HttpServerRequest request) {
        getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(final UserInfos user) {
                if (user != null) {
                    blog.list(user, null, null, new Handler<Either<String, JsonArray>>() {
                        public void handle(Either<String, JsonArray> event) {
                            if (event.isLeft()) {
                                arrayResponseHandler(request).handle(event);
                                return;
                            }

                            final JsonArray blogs = event.right().getValue();

                            if (blogs.size() < 1) {
                                renderJson(request, new JsonArray());
                                return;
                            }

                            final AtomicInteger countdown = new AtomicInteger(blogs.size());
                            final Handler<Void> finalHandler = new Handler<Void>() {
                                public void handle(Void v) {
                                    if (countdown.decrementAndGet() <= 0) {
                                        renderJson(request, blogs);
                                    }
                                }
                            };

                            for (Object blogObj : blogs) {
                                final JsonObject blog = (JsonObject) blogObj;

                                postService.list(blog.getString("_id"), PostService.StateType.PUBLISHED, user, null,
                                        0, null, new Handler<Either<String, JsonArray>>() {
                                            public void handle(Either<String, JsonArray> event) {
                                                if (event.isRight()) {
                                                    blog.put("fetchPosts", event.right().getValue());
                                                }
                                                finalHandler.handle(null);
                                            }
                                        });
                            }

                        }
                    });
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Get("/share/json/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void shareJson(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }
        getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(UserInfos user) {
                if (user != null) {
                    shareService.shareInfos(user.getUserId(), blogId, I18n.acceptLanguage(request),
                            request.params().get("search"), defaultResponseHandler(request));
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Put("/share/json/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void shareJsonSubmit(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }
        request.setExpectMultipart(true);
        request.endHandler(new Handler<Void>() {
            @Override
            public void handle(Void v) {
                final List<String> actions = request.formAttributes().getAll("actions");
                final String groupId = request.formAttributes().get("groupId");
                final String userId = request.formAttributes().get("userId");
                if (actions == null || actions.isEmpty()) {
                    badRequest(request);
                    return;
                }
                getUserInfos(eb, request, new Handler<UserInfos>() {
                    @Override
                    public void handle(final UserInfos user) {
                        if (user != null) {
                            Handler<Either<String, JsonObject>> r = new Handler<Either<String, JsonObject>>() {
                                @Override
                                public void handle(Either<String, JsonObject> event) {
                                    if (event.isRight()) {
                                        JsonObject n = event.right().getValue().getJsonObject("notify-timeline");
                                        if (n != null) {
                                            timelineService.notifyShare(request, blogId, user,
                                                    new JsonArray().add(n), getBlogUri(request, blogId));
                                        }
                                        renderJson(request, event.right().getValue());
                                    } else {
                                        JsonObject error = new JsonObject().put("error", event.left().getValue());
                                        renderJson(request, error, 400);
                                    }
                                }
                            };
                            if (groupId != null) {
                                shareService.groupShare(user.getUserId(), groupId, blogId, actions, r);
                            } else if (userId != null) {
                                shareService.userShare(user.getUserId(), userId, blogId, actions, r);
                            } else {
                                badRequest(request);
                            }
                        } else {
                            unauthorized(request);
                        }
                    }
                });
            }
        });
    }

    @Put("/share/remove/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void removeShare(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        if (blogId == null || blogId.trim().isEmpty()) {
            badRequest(request);
            return;
        }

        request.setExpectMultipart(true);
        request.endHandler(new Handler<Void>() {
            @Override
            public void handle(Void v) {
                final List<String> actions = request.formAttributes().getAll("actions");
                final String groupId = request.formAttributes().get("groupId");
                final String userId = request.formAttributes().get("userId");
                if (groupId != null) {
                    shareService.removeGroupShare(groupId, blogId, actions, defaultResponseHandler(request));
                } else if (userId != null) {
                    shareService.removeUserShare(userId, blogId, actions, defaultResponseHandler(request));
                } else {
                    badRequest(request);
                }
            }
        });
    }

    @Put("/share/resource/:blogId")
    @SecuredAction(value = "blog.manager", type = ActionType.RESOURCE)
    public void shareResource(final HttpServerRequest request) {
        final String blogId = request.params().get("blogId");
        getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(final UserInfos user) {
                if (user != null) {
                    RequestUtils.bodyToJson(request, share -> {
                        shareService.share(user.getUserId(), blogId, share, r -> {
                            if (r.isRight()) {
                                JsonArray nta = r.right().getValue().getJsonArray("notify-timeline-array");
                                if (nta != null) {
                                    timelineService.notifyShare(request, blogId, user, nta,
                                            getBlogUri(request, blogId));
                                }
                                renderJson(request, r.right().getValue());
                            } else {
                                JsonObject error = new JsonObject().put("error", r.left().getValue());
                                renderJson(request, error, 400);
                            }
                        });
                    });
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    private List<String> loadManagerActions(Collection<fr.wseduc.webutils.security.SecuredAction> actions) {
        List<String> managerActions = new ArrayList<>();
        if (actions != null) {
            for (fr.wseduc.webutils.security.SecuredAction a : actions) {
                if (a.getName() != null && "RESOURCE".equals(a.getType())
                        && "blog.manager".equals(a.getDisplayName())) {
                    managerActions.add(a.getName().replaceAll("\\.", "-"));
                }
            }
        }
        return managerActions;
    }

    @Get("/blog/availables-workflow-actions")
    @SecuredAction(value = "blog.habilitation", type = ActionType.AUTHENTICATED)
    public void getActionsInfos(final HttpServerRequest request) {
        ActionsUtils.findWorkflowSecureActions(eb, request, this);
    }

}