org.entcore.directory.controllers.UserController.java Source code

Java tutorial

Introduction

Here is the source code for org.entcore.directory.controllers.UserController.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.directory.controllers;

import static fr.wseduc.webutils.Utils.isNotEmpty;
import static fr.wseduc.webutils.request.RequestUtils.bodyToJson;
import static org.entcore.common.http.response.DefaultResponseHandler.arrayResponseHandler;
import static org.entcore.common.http.response.DefaultResponseHandler.defaultResponseHandler;
import static org.entcore.common.http.response.DefaultResponseHandler.leftToResponse;
import static org.entcore.common.http.response.DefaultResponseHandler.notEmptyResponseHandler;
import static org.entcore.common.user.SessionAttributes.PERSON_ATTRIBUTE;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import fr.wseduc.webutils.security.SecureHttpServerRequest;
import org.entcore.common.appregistry.ApplicationUtils;
import org.entcore.common.http.filter.IgnoreCsrf;
import org.entcore.common.http.filter.ResourceFilter;
import org.entcore.common.notification.TimelineHelper;
import org.entcore.common.user.DefaultFunctions;
import org.entcore.common.user.UserInfos;
import org.entcore.common.user.UserUtils;
import org.entcore.common.validation.StringValidation;
import org.entcore.directory.pojo.Users;
import org.entcore.directory.security.*;
import org.entcore.directory.services.UserBookService;
import org.entcore.directory.services.UserService;
import org.vertx.java.core.http.RouteMatcher;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

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.http.BaseController;
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 UserController extends BaseController {

    private UserService userService;
    private UserBookService userBookService;
    private TimelineHelper notification;
    private static final int MOTTO_MAX_LENGTH = 75;

    @Override
    public void init(Vertx vertx, JsonObject config, RouteMatcher rm,
            Map<String, fr.wseduc.webutils.security.SecuredAction> securedActions) {
        super.init(vertx, config, rm, securedActions);
    }

    @Put("/user/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void update(final HttpServerRequest request) {
        bodyToJson(request, new Handler<JsonObject>() {
            @Override
            public void handle(final JsonObject body) {
                UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
                    public void handle(UserInfos user) {
                        String userId = request.params().get("userId");

                        //User name modification prevention for non-admins.
                        if (!user.getFunctions().containsKey(DefaultFunctions.SUPER_ADMIN)
                                && !user.getFunctions().containsKey(DefaultFunctions.ADMIN_LOCAL)
                                && !user.getFunctions().containsKey(DefaultFunctions.CLASS_ADMIN)) {
                            body.remove("lastName");
                            body.remove("firstName");
                        }
                        userService.update(userId, body, notEmptyResponseHandler(request));

                        UserUtils.removeSessionAttribute(eb, userId, PERSON_ATTRIBUTE, null);
                    }
                });
            }
        });
    }

    @Put("/userbook/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void updateUserBook(final HttpServerRequest request) {
        bodyToJson(request, new Handler<JsonObject>() {
            @Override
            public void handle(final JsonObject body) {
                final String userId = request.params().get("userId");
                String motto = body.getString("motto");
                if (motto != null && motto.length() > MOTTO_MAX_LENGTH) {
                    badRequest(request);
                    return;
                }
                userBookService.update(userId, body, new Handler<Either<String, JsonObject>>() {
                    @Override
                    public void handle(Either<String, JsonObject> event) {
                        if (event.isRight()) {
                            UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
                                @Override
                                public void handle(UserInfos user) {
                                    if (user != null && userId != null && userId.equals(user.getUserId())) {
                                        notifyTimeline(request, user, body);
                                    }
                                }
                            });
                            UserUtils.removeSessionAttribute(eb, userId, PERSON_ATTRIBUTE, null);
                            renderJson(request, event.right().getValue());
                        } else {
                            JsonObject error = new JsonObject().put("error", event.left().getValue());
                            renderJson(request, error, 400);
                        }
                    }
                });
            }
        });
    }

    @Get("/user/:userId")
    @ResourceFilter(UserAccessOrVisible.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void get(final HttpServerRequest request) {
        String userId = request.params().get("userId");
        boolean getManualGroups = Boolean.parseBoolean(request.params().get("manual-groups"));
        if ("true".equals(((SecureHttpServerRequest) request).getAttribute("visibleCheck"))) {
            final JsonArray filter = new JsonArray().add("activationCode").add("firstName").add("lastName")
                    .add("mobile").add("mobilePhone").add("lastLogin").add("created").add("modified").add("ine")
                    .add("email").add("emailAcademy").add("workPhone").add("homePhone").add("country")
                    .add("zipCode").add("address").add("postbox").add("city").add("otherNames").add("title");
            userService.get(userId, getManualGroups, filter, notEmptyResponseHandler(request));
        } else {
            userService.get(userId, getManualGroups, notEmptyResponseHandler(request));
        }
    }

    @Get("/userbook/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void getUserBook(final HttpServerRequest request) {
        String userId = request.params().get("userId");
        userBookService.get(userId, notEmptyResponseHandler(request));
    }

    @Put("/avatar/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void updateAvatar(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        bodyToJson(request, new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject body) {
                String p = body.getString("picture");
                if (!StringValidation.isAbsoluteDocumentUri(p)) {
                    badRequest(request);
                    return;
                }
                final JsonObject j = new JsonObject().put("picture", p);
                userBookService.update(userId, j, new Handler<Either<String, JsonObject>>() {
                    @Override
                    public void handle(Either<String, JsonObject> u) {
                        if (u.isRight()) {
                            renderJson(request, j);
                        } else {
                            leftToResponse(request, u.left());
                        }
                    }
                });
            }
        });
    }

    private void notifyTimeline(final HttpServerRequest request, final UserInfos user, final JsonObject body) {
        if (body == null) {
            return;
        }
        UserUtils.findUsersCanSeeMe(eb, request, new Handler<JsonArray>() {

            @Override
            public void handle(JsonArray users) {
                String mood = body.getString("mood");
                String motto = body.getString("motto");
                List<String> userIds = new ArrayList<>();
                for (Object o : users) {
                    JsonObject u = (JsonObject) o;
                    userIds.add(u.getString("id"));
                }
                JsonObject params = new JsonObject()
                        .put("uri", pathPrefix + "/annuaire#" + user.getUserId() + "#" + user.getType())
                        .put("username", user.getUsername()).put("motto", motto).put("moodImg", mood);
                if (mood != null && !mood.trim().isEmpty() && !mood.equals("default")) {
                    notification.notifyTimeline(request, "userbook.userbook_mood", user, userIds,
                            user.getUserId() + System.currentTimeMillis() + "mood", params);
                }
                if (motto != null && !motto.trim().isEmpty()) {
                    notification.notifyTimeline(request, "userbook.userbook_motto", user, userIds,
                            user.getUserId() + System.currentTimeMillis() + "motto", params);
                }
            }
        });
    }

    @Get("/list/isolated")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listIsolated(final HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        final List<String> expectedProfile = request.params().getAll("profile");
        userService.listIsolated(structureId, expectedProfile, arrayResponseHandler(request));
    }

    @Delete("/user")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void delete(final HttpServerRequest request) {
        List<String> users = request.params().getAll("userId");
        userService.delete(users, defaultResponseHandler(request));
    }

    @Post("/user/delete")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(TeacherOfUser.class)
    public void deleteByPost(final HttpServerRequest request) {
        bodyToJson(request, new Handler<JsonObject>() {
            @Override
            @SuppressWarnings("unchecked")
            public void handle(JsonObject event) {
                if (event != null) {
                    userService.delete(
                            event.getJsonArray("users", new fr.wseduc.webutils.collections.JsonArray()).getList(),
                            defaultResponseHandler(request));
                } else {
                    badRequest(request, "invalid.json");
                }
            }
        });
    }

    @Put("/restore/user")
    @ResourceFilter(AnyAdminOfUser.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void restore(final HttpServerRequest request) {
        List<String> users = request.params().getAll("userId");
        userService.restore(users, defaultResponseHandler(request));
    }

    @Get("/export/users")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void export(final HttpServerRequest request) {
        UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(final UserInfos user) {
                if (user != null) {
                    final String structureId = request.params().get("structureId");
                    final String classId = request.params().get("classId");
                    JsonArray types = new fr.wseduc.webutils.collections.JsonArray(
                            request.params().getAll("profile"));
                    final String filterActive = request.params().get("filterActive");
                    final String exportType = request.params().get("type") == null ? ""
                            : request.params().get("type");
                    final String format = request.params().get("format");
                    Handler<Either<String, JsonArray>> handler;
                    if (format == null) {
                        handler = arrayResponseHandler(request);
                    } else {
                        handler = new Handler<Either<String, JsonArray>>() {
                            @Override
                            public void handle(Either<String, JsonArray> r) {
                                if (r.isRight()) {
                                    processTemplate(request, new JsonObject().put("list", r.right().getValue()),
                                            "text/export" + exportType + ".id.txt", false, new Handler<String>() {
                                                @Override
                                                public void handle(final String export) {
                                                    if (export != null) {
                                                        String filename = request.params().get("filename") != null
                                                                ? request.params().get("filename")
                                                                : "export" + exportType + "." + format;
                                                        if ("xml".equals(format)) {
                                                            request.response().putHeader("Content-Type",
                                                                    "text/xml");
                                                        } else {
                                                            request.response().putHeader("Content-Type",
                                                                    "application/csv");
                                                        }
                                                        request.response().putHeader("Content-Disposition",
                                                                "attachment; filename=" + filename);
                                                        request.response().end('\ufeff' + export);
                                                    } else {
                                                        renderError(request);
                                                    }
                                                }
                                            });
                                } else {
                                    renderJson(request, new JsonObject().put("error", r.left().getValue()), 400);
                                }
                            }
                        };
                    }
                    userService.listAdmin(structureId, classId, null, types, filterActive, null, user, handler);
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Post("/user/function/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AddFunctionFilter.class)
    @IgnoreCsrf
    public void addFunction(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        bodyToJson(request, pathPrefix + "addFunction", new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject event) {
                userService.addFunction(userId, event.getString("functionCode"), event.getJsonArray("scope"),
                        event.getString("inherit", ""), r -> {
                            if (r.isRight()) {
                                final String groupId = (String) r.right().getValue().remove("groupId");
                                if (isNotEmpty(groupId)) {
                                    JsonObject j = new JsonObject().put("action", "setCommunicationRules")
                                            .put("groupId", groupId);
                                    eb.send("wse.communication", j);
                                }
                                renderJson(request, r.right().getValue());
                            } else {
                                badRequest(request, r.left().getValue());
                            }
                        });
            }
        });
    }

    @Post("/user/headteacher/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdmlOfStructures.class)
    @IgnoreCsrf
    public void addHeadTeacherManual(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        bodyToJson(request, pathPrefix + "addHeadTeacher", new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject event) {
                userService.addHeadTeacherManual(userId, event.getString("structureExternalId"),
                        event.getString("classExternalId"), defaultResponseHandler(request));
            }
        });
    }

    @Put("/user/headteacher/:userId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdmlOfStructures.class)
    public void updateHeadTeacherManual(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        bodyToJson(request, pathPrefix + "updateHeadTeacher", new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject event) {
                userService.updateHeadTeacherManual(userId, event.getString("structureExternalId"),
                        event.getString("classExternalId"), defaultResponseHandler(request));
            }
        });
    }

    @Delete("/user/function/:userId/:function")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void removeFunction(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        final String function = request.params().get("function");
        userService.removeFunction(userId, function, defaultResponseHandler(request));
    }

    @Get("/user/:userId/functions")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listFunctions(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        userService.listFunctions(userId, arrayResponseHandler(request));
    }

    @Get("/user/:userId/children")
    @ResourceFilter(UserAccessOrVisible.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listChildren(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        userService.listChildren(userId, arrayResponseHandler(request));
    }

    @Post("/user/group/:userId/:groupId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void addGroup(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        final String groupId = request.params().get("groupId");
        userService.addGroup(userId, groupId, new Handler<Either<String, JsonObject>>() {
            @Override
            public void handle(Either<String, JsonObject> res) {
                if (res.isRight()) {
                    JsonObject j = new JsonObject().put("action", "setCommunicationRules").put("groupId", groupId);
                    eb.send("wse.communication", j);
                    JsonArray a = new fr.wseduc.webutils.collections.JsonArray().add(userId);
                    ApplicationUtils.publishModifiedUserGroup(eb, a);
                    renderJson(request, res.right().getValue());
                } else {
                    renderJson(request, new JsonObject().put("error", res.left().getValue()), 400);
                }
            }
        });
    }

    @Delete("/user/group/:userId/:groupId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void removeGroup(final HttpServerRequest request) {
        final String userId = request.params().get("userId");
        final String groupId = request.params().get("groupId");
        userService.removeGroup(userId, groupId, defaultResponseHandler(request));
    }

    @Get("/user/group/:groupId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listGroup(final HttpServerRequest request) {
        final String groupId = request.params().get("groupId");
        userService.list(groupId, true, null, arrayResponseHandler(request));
    }

    @Get("/user/adml/list/:structureId")
    @SecuredAction("user.adml.list")
    public void listAdml(final HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        userService.listAdml(structureId, arrayResponseHandler(request));
    }

    @Get("/user/admin/list")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listAdmin(final HttpServerRequest request) {
        UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(UserInfos user) {
                if (user != null) {
                    final String structureId = request.params().get("structureId");
                    final String classId = request.params().get("classId");
                    final JsonArray types = new fr.wseduc.webutils.collections.JsonArray(
                            request.params().getAll("profile"));
                    final String groupId = request.params().get("groupId");
                    final String nameFilter = request.params().get("name");
                    final String filterActive = request.params().get("filterActive");

                    userService.listAdmin(structureId, classId, groupId, types, filterActive, nameFilter, user,
                            arrayResponseHandler(request));
                } else {
                    unauthorized(request);
                }
            }
        });
    }

    @Put("/user/:studentId/related/:relativeId")
    @ResourceFilter(RelativeStudentFilter.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void relativeStudent(final HttpServerRequest request) {
        final String studentId = request.params().get("studentId");
        final String relativeId = request.params().get("relativeId");
        userService.relativeStudent(relativeId, studentId, new Handler<Either<String, JsonObject>>() {
            @Override
            public void handle(Either<String, JsonObject> res) {
                if (res.isRight()) {
                    JsonArray structures = res.right().getValue().getJsonArray("structures");
                    JsonObject j = new JsonObject().put("action", "setMultipleDefaultCommunicationRules")
                            .put("schoolIds", structures);
                    eb.send("wse.communication", j);
                    JsonArray a = new fr.wseduc.webutils.collections.JsonArray().add(relativeId);
                    ApplicationUtils.publishModifiedUserGroup(eb, a);
                    if (structures == null || structures.size() == 0) {
                        notFound(request, "user.not.found");
                    } else {
                        ok(request);
                    }
                } else {
                    renderJson(request, new JsonObject().put("error", res.left().getValue()), 400);
                }
            }
        });
    }

    @Delete("/user/:studentId/related/:relativeId")
    @ResourceFilter(RelativeStudentFilter.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void unlinkRelativeStudent(final HttpServerRequest request) {
        final String studentId = request.params().get("studentId");
        final String relativeId = request.params().get("relativeId");
        userService.unlinkRelativeStudent(relativeId, studentId, defaultResponseHandler(request));
    }

    @Delete("/duplicate/ignore/:userId1/:userId2")
    @ResourceFilter(AdmlOfTwoUsers.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void ignoreDuplicate(final HttpServerRequest request) {
        final String userId1 = request.params().get("userId1");
        final String userId2 = request.params().get("userId2");
        userService.ignoreDuplicate(userId1, userId2, defaultResponseHandler(request));
    }

    @Put("/duplicate/merge/:userId1/:userId2")
    @ResourceFilter(AdmlOfTwoUsers.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void mergeDuplicate(final HttpServerRequest request) {
        final String userId1 = request.params().get("userId1");
        final String userId2 = request.params().get("userId2");
        userService.mergeDuplicate(userId1, userId2, defaultResponseHandler(request));
    }

    @Get("/duplicates")
    @ResourceFilter(AdmlOfStructures.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listDuplicates(final HttpServerRequest request) {
        final List<String> structures = request.params().getAll("structure");
        final boolean inherit = "true".equals(request.params().get("inherit"));
        userService.listDuplicates(new fr.wseduc.webutils.collections.JsonArray(structures), inherit,
                arrayResponseHandler(request));
    }

    @Get("/user/structures/list")
    @ResourceFilter(AdmlOfStructuresByUAI.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void listUserInStructuresByUAI(final HttpServerRequest request) {
        final String format = request.params().get("format");
        final List<String> structures = request.params().getAll("uai");

        JsonArray fields = new fr.wseduc.webutils.collections.JsonArray().add("externalId").add("lastName")
                .add("firstName").add("login");
        if ("true".equalsIgnoreCase(request.params().get("administrativeStructure"))) {
            fields.add("administrativeStructure");
        }
        JsonArray types = new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("type"));

        boolean isExportFull = false;
        String isExportFullParameter = request.params().get("full");
        if (null != isExportFullParameter && !isExportFullParameter.isEmpty()
                && "true".equals(isExportFullParameter)) {
            isExportFull = true;
        }

        if ("XML".equalsIgnoreCase(format)) {
            userService.listByUAI(structures, types, isExportFull, fields,
                    new Handler<Either<String, JsonArray>>() {
                        @Override
                        public void handle(Either<String, JsonArray> event) {
                            if (event.isRight()) {
                                JsonArray r = event.right().getValue();
                                ObjectMapper mapper = new ObjectMapper();
                                try {
                                    List<Users.User> users = mapper.readValue(r.encode(),
                                            new TypeReference<List<Users.User>>() {
                                            });
                                    StringWriter response = new StringWriter();
                                    JAXBContext context = JAXBContext.newInstance(Users.class);
                                    Marshaller marshaller = context.createMarshaller();
                                    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
                                    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                                    marshaller.marshal(new Users(users), response);
                                    request.response().putHeader("content-type", "application/xml");
                                    request.response().end(response.toString());
                                } catch (IOException | JAXBException e) {
                                    log.error(e.toString(), e);
                                    request.response().setStatusCode(500);
                                    request.response().end(e.getMessage());
                                }
                            } else {
                                leftToResponse(request, event.left());
                            }
                        }
                    });
        } else {
            userService.listByUAI(structures, types, isExportFull, fields, arrayResponseHandler(request));
        }
    }

    @Post("/duplicate/generate/mergeKey/:userId")
    @ResourceFilter(AdmlOfUser.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void generateMergeKeyByAdml(final HttpServerRequest request) {
        userService.generateMergeKey(request.params().get("userId"), notEmptyResponseHandler(request));
    }

    @Get("/duplicate/user/mergeKey")
    @SecuredAction("user.generate.merge.key")
    public void generateMergeKey(final HttpServerRequest request) {
        UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
            @Override
            public void handle(UserInfos event) {
                if (event != null) {
                    userService.generateMergeKey(event.getUserId(), notEmptyResponseHandler(request));
                } else {
                    unauthorized(request, "user.not.found");
                }
            }
        });
    }

    @Post("/duplicate/user/mergeByKey")
    @SecuredAction("user.merge.by.key")
    public void mergeByKey(final HttpServerRequest request) {
        RequestUtils.bodyToJson(request, new Handler<JsonObject>() {
            @Override
            public void handle(final JsonObject body) {
                UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
                    @Override
                    public void handle(UserInfos event) {
                        if (event != null) {
                            userService.mergeByKey(event.getUserId(), body, notEmptyResponseHandler(request));
                        } else {
                            unauthorized(request, "user.not.found");
                        }
                    }
                });
            }
        });
    }

    @Get("/allowLoginUpdate")
    @SecuredAction("user.allow.login.update")
    public void allowLoginUpdate(final HttpServerRequest request) {
        // This route is used to create user.allow.login.update Workflow right, nothing to do
        request.response().end();
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void setUserBookService(UserBookService userBookService) {
        this.userBookService = userBookService;
    }

    public void setNotification(TimelineHelper notification) {
        this.notification = notification;
    }

}