Java tutorial
/* 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 fr.wseduc.rs.Delete; import fr.wseduc.rs.Get; import fr.wseduc.rs.Put; import fr.wseduc.security.ActionType; import fr.wseduc.security.SecuredAction; import fr.wseduc.webutils.Either; import fr.wseduc.webutils.email.EmailSender; import fr.wseduc.webutils.http.BaseController; import fr.wseduc.webutils.http.Renders; import fr.wseduc.webutils.request.RequestUtils; import io.vertx.core.eventbus.DeliveryOptions; import org.entcore.common.appregistry.ApplicationUtils; import org.entcore.common.http.filter.AdmlOfStructure; import org.entcore.common.http.filter.AdminFilter; import org.entcore.common.http.filter.ResourceFilter; import org.entcore.common.user.UserInfos; import org.entcore.common.user.UserUtils; import org.entcore.directory.pojo.Ent; import org.entcore.directory.security.AdminStructureFilter; import org.entcore.directory.security.AnyAdminOfUser; import org.entcore.directory.services.SchoolService; import io.vertx.core.AsyncResult; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.eventbus.Message; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import org.vertx.java.core.http.RouteMatcher; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; import static fr.wseduc.webutils.Utils.handlerToAsyncHandler; import static fr.wseduc.webutils.request.RequestUtils.bodyToJson; import static org.entcore.common.http.response.DefaultResponseHandler.*; public class StructureController extends BaseController { private SchoolService structureService; private EmailSender notifHelper; private String assetsPath = "../.."; private Map<String, String> skins = new HashMap<>(); private String node; @Override public void init(Vertx vertx, JsonObject config, RouteMatcher rm, Map<String, fr.wseduc.webutils.security.SecuredAction> securedActions) { super.init(vertx, config, rm, securedActions); node = (String) vertx.sharedData().getLocalMap("server").get("node"); if (node == null) { node = ""; } } @Put("/structure/:structureId") @SecuredAction(value = "", type = ActionType.RESOURCE) public void update(final HttpServerRequest request) { bodyToJson(request, pathPrefix + "updateStructure", new Handler<JsonObject>() { @Override public void handle(JsonObject body) { String structureId = request.params().get("structureId"); structureService.update(structureId, body, defaultResponseHandler(request)); } }); } @Put("/structure/:structureId/link/:userId") @SecuredAction(value = "", type = ActionType.RESOURCE) public void linkUser(final HttpServerRequest request) { final String structureId = request.params().get("structureId"); final String userId = request.params().get("userId"); structureService.link(structureId, userId, new Handler<Either<String, JsonObject>>() { @Override public void handle(Either<String, JsonObject> r) { if (r.isRight()) { if (r.right().getValue() != null && r.right().getValue().size() > 0) { JsonArray a = new fr.wseduc.webutils.collections.JsonArray().add(userId); ApplicationUtils.sendModifiedUserGroup(eb, a, handlerToAsyncHandler(new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { JsonObject j = new JsonObject() .put("action", "setDefaultCommunicationRules") .put("schoolId", structureId); eb.send("wse.communication", j); } })); renderJson(request, r.right().getValue(), 200); } else { notFound(request); } } else { renderJson(request, new JsonObject().put("error", r.left().getValue()), 400); } } }); } @Delete("/structure/:structureId/unlink/:userId") @SecuredAction(value = "", type = ActionType.RESOURCE) public void unlinkUser(final HttpServerRequest request) { final String userId = request.params().get("userId"); final String structureId = request.params().get("structureId"); structureService.unlink(structureId, userId, notEmptyResponseHandler(request)); } @Get("/structure/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) { structureService.listAdmin(user, arrayResponseHandler(request)); } else { unauthorized(request); } } }); } @Put("/structure/:structureId/parent/:parentStructureId") @SecuredAction("structure.define.parent") public void defineParent(final HttpServerRequest request) { final String parentStructureId = request.params().get("parentStructureId"); final String structureId = request.params().get("structureId"); structureService.defineParent(structureId, parentStructureId, notEmptyResponseHandler(request)); } @Delete("/structure/:structureId/parent/:parentStructureId") @SecuredAction("structure.remove.parent") public void removeParent(final HttpServerRequest request) { final String parentStructureId = request.params().get("parentStructureId"); final String structureId = request.params().get("structureId"); structureService.removeParent(structureId, parentStructureId, defaultResponseHandler(request)); } @Get("/structures") @SecuredAction("structure.list.all") public void listStructures(final HttpServerRequest request) { String format = request.params().get("format"); JsonArray fields = new fr.wseduc.webutils.collections.JsonArray().add("id").add("externalId").add("name") .add("UAI").add("address").add("zipCode").add("city").add("phone").add("academy"); if ("XML".equalsIgnoreCase(format)) { structureService.list(fields, new Handler<Either<String, JsonArray>>() { @Override public void handle(Either<String, JsonArray> event) { if (event.isRight()) { JsonArray r = event.right().getValue(); Ent ent = new Ent(); for (Object o : r) { if (!(o instanceof JsonObject)) continue; JsonObject j = (JsonObject) o; Ent.Etablissement etablissement = new Ent.Etablissement(); etablissement.setEtablissementId(j.getString("UAI", "")); etablissement.setEtablissementUid(j.getString("UAI", "")); etablissement.setCodePorteur(j.getString("academy", "")); etablissement.setNomCourant(j.getString("name", "")); etablissement.setAdressePlus(j.getString("address", "")); etablissement.setCodePostal(j.getString("zipCode", "")); etablissement.setVille(j.getString("city", "")); etablissement.setTelephone(j.getString("phone", "")); etablissement.setFax(""); ent.getEtablissement().add(etablissement); } try { StringWriter response = new StringWriter(); JAXBContext context = JAXBContext.newInstance(Ent.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(ent, response); request.response().putHeader("content-type", "application/xml"); request.response().end(response.toString()); } catch (JAXBException e) { log.error(e.toString(), e); request.response().setStatusCode(500); request.response().end(e.getMessage()); } } else { leftToResponse(request, event.left()); } } }); } else { structureService.list(fields, arrayResponseHandler(request)); } } @Get("/structure/:structureId/levels") @SecuredAction(value = "", type = ActionType.RESOURCE) public void getLevels(final HttpServerRequest request) { UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() { @Override public void handle(UserInfos infos) { structureService.getLevels(request.params().get("structureId"), infos, arrayResponseHandler(request)); } }); } @Get("/structure/:structureId/massMail/users") @SecuredAction(value = "", type = ActionType.RESOURCE) public void getMassmailUsers(final HttpServerRequest request) { UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() { @Override public void handle(UserInfos infos) { final JsonObject filter = new JsonObject(); final String structureId = request.params().get("structureId"); final List<String> sorts = request.params().getAll("s"); final Boolean filterMail = request.params().contains("mail") ? new Boolean(request.params().get("mail")) : null; filter.put("profiles", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("p"))) .put("levels", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("l"))) .put("classes", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("c"))) .put("sort", new fr.wseduc.webutils.collections.JsonArray(sorts)); if (request.params().contains("a")) { filter.put("activated", request.params().get("a")); } structureService.massmailUsers(structureId, filter, true, true, filterMail, infos, arrayResponseHandler(request)); } }); } @Get("/structure/:structureId/massMail/allUsers") @SecuredAction(value = "", type = ActionType.RESOURCE) public void getMassMailUsersList(final HttpServerRequest request) { UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() { @Override public void handle(UserInfos infos) { final String structureId = request.params().get("structureId"); structureService.massMailAllUsersByStructure(structureId, infos, arrayResponseHandler(request)); } }); } @Get("/structure/massMail/:userId/:type") @ResourceFilter(AnyAdminOfUser.class) @SecuredAction(value = "", type = ActionType.RESOURCE) public void performMassmailUser(final HttpServerRequest request) { final String userId = request.params().get("userId"); final String type = request.params().get("type"); final String filename = "mettre le nom de de l'utilisateur"; if (userId == null) { badRequest(request); return; } this.assetsPath = (String) vertx.sharedData().getLocalMap("server").get("assetPath"); this.skins = vertx.sharedData().getLocalMap("skins"); final String assetsPath = this.assetsPath + "/assets/themes/" + this.skins.get(Renders.getHost(request)); final String templatePath = assetsPath + "/template/directory/"; final String baseUrl = getScheme(request) + "://" + Renders.getHost(request) + "/assets/themes/" + this.skins.get(Renders.getHost(request)) + "/img/"; UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() { public void handle(final UserInfos infos) { //PDF if ("pdf".equals(type)) { structureService.massMailUser(userId, infos, new Handler<Either<String, JsonArray>>() { public void handle(Either<String, JsonArray> result) { if (result.isLeft()) { forbidden(request); return; } massMailTypePdf(request, templatePath, baseUrl, filename, result.right().getValue()); } }); } //Mail else if ("mail".equals(type)) { structureService.massMailUser(userId, infos, new Handler<Either<String, JsonArray>>() { public void handle(final Either<String, JsonArray> result) { if (result.isLeft()) { forbidden(request); return; } massMailTypeMail(request, templatePath, result.right().getValue()); } }); } else { badRequest(request); } } }); } @Get("/structure/:structureId/massMail/process/:type") @SecuredAction(value = "", type = ActionType.RESOURCE) public void performMassmail(final HttpServerRequest request) { final String structureId = request.params().get("structureId"); final String type = request.params().get("type"); final JsonObject filter = new JsonObject(); final String filename = request.params().get("filename"); final Boolean filterMail = request.params().contains("mail") ? new Boolean(request.params().get("mail")) : null; filter.put("profiles", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("p"))) .put("levels", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("l"))) .put("classes", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("c"))) .put("sort", new fr.wseduc.webutils.collections.JsonArray(request.params().getAll("s"))); if (request.params().contains("a")) { filter.put("activated", request.params().get("a")); } this.assetsPath = (String) vertx.sharedData().getLocalMap("server").get("assetPath"); this.skins = vertx.sharedData().getLocalMap("skins"); final String assetsPath = this.assetsPath + "/assets/themes/" + this.skins.get(Renders.getHost(request)); final String templatePath = assetsPath + "/template/directory/"; final String baseUrl = getScheme(request) + "://" + Renders.getHost(request) + "/assets/themes/" + this.skins.get(Renders.getHost(request)) + "/img/"; final boolean groupClasses = !filter.getJsonArray("sort").contains("classname"); UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() { public void handle(final UserInfos infos) { //PDF if ("pdf".equals(type)) { structureService.massmailUsers(structureId, filter, groupClasses, false, filterMail, infos, new Handler<Either<String, JsonArray>>() { public void handle(Either<String, JsonArray> result) { if (result.isLeft()) { forbidden(request); return; } massMailTypePdf(request, templatePath, baseUrl, filename, result.right().getValue()); } }); } //Mail else if ("mail".equals(type)) { structureService.massmailUsers(structureId, filter, true, true, filterMail, infos, new Handler<Either<String, JsonArray>>() { public void handle(final Either<String, JsonArray> result) { if (result.isLeft()) { forbidden(request); return; } massMailTypeMail(request, templatePath, result.right().getValue()); } }); } else { badRequest(request); } } }); } private void massMailTypePdf(final HttpServerRequest request, final String templatePath, final String baseUrl, final String filename, final JsonArray users) { final JsonObject templateProps = new JsonObject().put("users", users); vertx.fileSystem().readFile(templatePath + "massmail.pdf.xhtml", new Handler<AsyncResult<Buffer>>() { @Override public void handle(AsyncResult<Buffer> result) { if (!result.succeeded()) { badRequest(request); return; } StringReader reader = new StringReader(result.result().toString("UTF-8")); processTemplate(request, templateProps, "massmail.pdf.xhtml", reader, new Handler<Writer>() { public void handle(Writer writer) { String processedTemplate = ((StringWriter) writer).getBuffer().toString(); if (processedTemplate == null) { badRequest(request); return; } JsonObject actionObject = new JsonObject(); actionObject.put("content", processedTemplate.getBytes()).put("baseUrl", baseUrl); eb.send(node + "entcore.pdf.generator", actionObject, new DeliveryOptions().setSendTimeout(600000l), handlerToAsyncHandler(new Handler<Message<JsonObject>>() { public void handle(Message<JsonObject> reply) { JsonObject pdfResponse = reply.body(); if (!"ok".equals(pdfResponse.getString("status"))) { badRequest(request, pdfResponse.getString("message")); return; } byte[] pdf = pdfResponse.getBinary("content"); request.response().putHeader("Content-Type", "application/pdf"); request.response().putHeader("Content-Disposition", "attachment; filename=" + filename + ".pdf"); request.response().end(Buffer.buffer(pdf)); } })); } }); } }); } private void massMailTypeMail(final HttpServerRequest request, final String templatePath, final JsonArray users) { vertx.fileSystem().readFile(templatePath + "massmail.mail.txt", new Handler<AsyncResult<Buffer>>() { @Override public void handle(AsyncResult<Buffer> result) { if (!result.succeeded()) { badRequest(request); return; } StringReader reader = new StringReader(result.result().toString("UTF-8")); final JsonArray mailHeaders = new JsonArray().add( new JsonObject().put("name", "Content-Type").put("value", "text/html; charset=\"UTF-8\"")); for (Object userObj : users) { final JsonObject user = (JsonObject) userObj; final String userMail = user.getString("email"); if (userMail == null || userMail.trim().isEmpty()) { continue; } final String mailTitle = !user.containsKey("activationCode") || user.getString("activationCode") == null || user.getString("activationCode").trim().isEmpty() ? "directory.massmail.mail.subject.activated" : "directory.massmail.mail.subject.not.activated"; try { reader.reset(); } catch (IOException exc) { log.error("[MassMail] Error on StringReader (" + exc.toString() + ")"); } processTemplate(request, user, "massmail.mail.txt", reader, new Handler<Writer>() { public void handle(Writer writer) { String processedTemplate = ((StringWriter) writer).getBuffer().toString(); if (processedTemplate == null) { badRequest(request); return; } notifHelper.sendEmail(request, userMail, null, null, mailTitle, processedTemplate, null, true, mailHeaders, handlerToAsyncHandler(new Handler<Message<JsonObject>>() { public void handle(Message<JsonObject> event) { if ("error".equals(event.body().getString("status"))) { log.error("[MassMail] Error while sending mail (" + event.body().getString("message", "") + ")"); } } })); } }); } ok(request); } }); } @Get("/structure/:structureId/metrics") @SecuredAction(value = "", type = ActionType.RESOURCE) @ResourceFilter(AdmlOfStructure.class) public void metrics(final HttpServerRequest request) { structureService.getMetrics(request.params().get("structureId"), defaultResponseHandler(request)); } @Get("/structure/:id/sources") @ResourceFilter(AdminFilter.class) @SecuredAction(value = "", type = ActionType.RESOURCE) public void listSources(final HttpServerRequest request) { String structureId = request.params().get("id"); this.structureService.listSources(structureId, arrayResponseHandler(request)); } @Get("/structure/:id/aaffunctions") @ResourceFilter(AdminFilter.class) @SecuredAction(value = "", type = ActionType.RESOURCE) public void listAafFunctions(final HttpServerRequest request) { String structureId = request.params().get("id"); this.structureService.listAafFunctions(structureId, arrayResponseHandler(request)); } @Get("/structure/:id/quicksearch/users") @SecuredAction(type = ActionType.RESOURCE, value = "") @ResourceFilter(AdminStructureFilter.class) public void quickSearchUsers(HttpServerRequest request) { String structureId = request.params().get("id"); String input = request.params().get("input"); if (input == null || input.trim().length() == 0) { badRequest(request); return; } this.structureService.quickSearchUsers(structureId, input, arrayResponseHandler(request)); } @Get("/structure/:id/users") @SecuredAction(type = ActionType.RESOURCE, value = "") @ResourceFilter(AdminStructureFilter.class) public void userList(HttpServerRequest request) { String structureId = request.params().get("id"); this.structureService.userList(structureId, arrayResponseHandler(request)); } @Put("structure/:id/profile/block") @SecuredAction(value = "", type = ActionType.RESOURCE) @ResourceFilter(AdminStructureFilter.class) public void blockUsers(final HttpServerRequest request) { RequestUtils.bodyToJson(request, new Handler<JsonObject>() { @Override public void handle(JsonObject json) { final String structureId = request.params().get("id"); final String profile = json.getString("profile"); final boolean block = json.getBoolean("block", true); structureService.blockUsers(structureId, profile, block, new Handler<JsonObject>() { @Override public void handle(JsonObject r) { if ("ok".equals(r.getString("status"))) { request.response().end(); JsonArray usersId = r.getJsonArray("result").getJsonObject(0).getJsonArray("usersId"); for (Object userId : usersId) { UserUtils.deletePermanentSession(eb, (String) userId, null, new Handler<Boolean>() { @Override public void handle(Boolean event) { if (!event) { log.error("Error delete permanent session with userId : " + userId); } } }); UserUtils.deleteCacheSession(eb, (String) userId, new Handler<Boolean>() { @Override public void handle(Boolean event) { if (!event) { log.error("Error delete cache session with userId : " + userId); } } }); } } else { badRequest(request); } } }); } }); } public void setStructureService(SchoolService structureService) { this.structureService = structureService; } public void setNotifHelper(EmailSender notifHelper) { this.notifHelper = notifHelper; } }