Skip to content

Commit b60e59f

Browse files
mariusodejcbe-odezban-odejuniorode
authored
Feat wb 3801 adapt legacy visibles (#613)
* chore: prepare develop-b2school version * feat(communication): MOZO-206, new search visible API for messaging * feat: MOZO-206 light version of search visibles * feat: WB-3801, adapt legacy visible result to new api format * feat: WB-3801, fix after merge --------- Co-authored-by: Jean-Christophe <jean-christophe.benoit@opendigitaleducation.com> Co-authored-by: Zakaria BANI <zakaria.bani@edifice.io> Co-authored-by: Junior BERNARD <junior.bernard@opendigitaleducation.com>
1 parent cadb351 commit b60e59f

File tree

14 files changed

+944
-70
lines changed

14 files changed

+944
-70
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.entcore.common.conversation;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
8+
@JsonInclude(JsonInclude.Include.NON_NULL)
9+
@JsonIgnoreProperties(ignoreUnknown = true)
10+
public class LegacySearchVisibleRequest {
11+
private final String userId;
12+
private final String search;
13+
private final String language;
14+
private final String parentMessageId;
15+
16+
@JsonCreator
17+
public LegacySearchVisibleRequest(@JsonProperty("userId") final String userId,
18+
@JsonProperty("search") final String search,
19+
@JsonProperty("language") final String language,
20+
@JsonProperty("parentMessageId") final String parentMessageId) {
21+
this.userId = userId;
22+
this.search = search;
23+
this.language = language;
24+
this.parentMessageId = parentMessageId;
25+
}
26+
27+
public String getUserId() {
28+
return userId;
29+
}
30+
31+
public String getSearch() {
32+
return search;
33+
}
34+
35+
public String getLanguage() {
36+
return language;
37+
}
38+
39+
public String getParentMessageId() {
40+
return parentMessageId;
41+
}
42+
}

common/src/main/java/org/entcore/common/user/UserUtils.java

+118-7
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,10 @@
2020
package org.entcore.common.user;
2121

2222
import com.fasterxml.jackson.databind.ObjectMapper;
23-
2423
import fr.wseduc.mongodb.MongoDb;
2524
import fr.wseduc.webutils.I18n;
2625
import fr.wseduc.webutils.Utils;
27-
import static fr.wseduc.webutils.Utils.getOrElse;
28-
import static fr.wseduc.webutils.Utils.handlerToAsyncHandler;
29-
import static fr.wseduc.webutils.Utils.isEmpty;
30-
import static fr.wseduc.webutils.Utils.isNotEmpty;
3126
import fr.wseduc.webutils.http.Renders;
32-
import static fr.wseduc.webutils.http.Renders.unauthorized;
3327
import fr.wseduc.webutils.request.CookieHelper;
3428
import fr.wseduc.webutils.security.JWT;
3529
import fr.wseduc.webutils.security.SecureHttpServerRequest;
@@ -49,7 +43,6 @@
4943
import io.vertx.core.json.JsonObject;
5044
import io.vertx.core.logging.Logger;
5145
import io.vertx.core.logging.LoggerFactory;
52-
import static org.entcore.common.http.filter.AppOAuthResourceProvider.getTokenId;
5346

5447
import io.vertx.core.shareddata.LocalMap;
5548
import org.entcore.common.neo4j.Neo4j;
@@ -58,6 +51,9 @@
5851
import org.entcore.common.utils.StringUtils;
5952

6053
import java.io.IOException;
54+
import java.util.Arrays;
55+
import java.util.Collections;
56+
import java.util.Comparator;
6157
import java.util.HashMap;
6258
import java.util.HashSet;
6359
import java.util.List;
@@ -66,6 +62,13 @@
6662
import java.util.Set;
6763
import java.util.stream.Collectors;
6864

65+
import static fr.wseduc.webutils.Utils.getOrElse;
66+
import static fr.wseduc.webutils.Utils.handlerToAsyncHandler;
67+
import static fr.wseduc.webutils.Utils.isEmpty;
68+
import static fr.wseduc.webutils.Utils.isNotEmpty;
69+
import static fr.wseduc.webutils.http.Renders.unauthorized;
70+
import static org.entcore.common.http.filter.AppOAuthResourceProvider.getTokenId;
71+
6972
public class UserUtils {
7073

7174
private static final Vertx vertx = Vertx.currentContext().owner();
@@ -235,6 +238,7 @@ public static void findVisibles(EventBus eb, String userId, String customReturn,
235238
public void handle(AsyncResult<Message<JsonArray>> res) {
236239
if (res.succeeded()) {
237240
JsonArray r = res.result().body();
241+
log.info("UserUtils.findVisibles - r.size = " + r.size()); // TODO JBER : exposer métrique
238242
if (acceptLanguage != null) {
239243
translateGroupsNames(r, acceptLanguage);
240244
}
@@ -348,6 +352,106 @@ private static void formatPositions(JsonObject dbResult) {
348352
dbResult.put("positions", positions);
349353
}
350354

355+
public static JsonArray mapObjectToContact(final String profile, final JsonArray shareBookmarks, final JsonArray visible, final String acceptLanguage) {
356+
final List<String> usedInAll = Arrays.asList("TO", "CC", "CCI");
357+
final List<String> usedInCCI = Collections.singletonList("CCI");
358+
359+
/*
360+
final JsonArray sb = new JsonArray();
361+
if (shareBookmarks != null) {
362+
for (String id: shareBookmarks.fieldNames()) {
363+
final JsonArray value = shareBookmarks.getJsonArray(id);
364+
if (value == null || value.size() < 2) {
365+
continue;
366+
}
367+
final JsonObject r = new fr.wseduc.webutils.collections.JsonObject();
368+
r.put("id", id);
369+
r.put("displayName", value.remove(0));
370+
r.put("type", "ShareBookmark");
371+
sb.add(r);
372+
}
373+
}
374+
375+
final JsonArray res = !sb.isEmpty() ? sortShareBookmarksByName(sb) : new JsonArray();
376+
*/
377+
378+
final JsonArray res = new JsonArray();
379+
for (Object o: shareBookmarks) {
380+
if (!(o instanceof JsonObject)) continue;
381+
JsonObject j = (JsonObject) o;
382+
j.put("type", "ShareBookmark");
383+
j.put("usedIn", usedInAll);
384+
res.add(j);
385+
}
386+
387+
for (Object o: visible) {
388+
if (!(o instanceof JsonObject)) continue;
389+
JsonObject j = (JsonObject) o;
390+
if (j.getString("name") != null) {
391+
j.remove("profile");
392+
j.remove("children");
393+
j.remove("classrooms");
394+
j.remove("disciplines");
395+
j.remove("functions");
396+
j.remove("relatives");
397+
398+
Object gt = j.remove("groupType");
399+
Object gp = j.remove("groupProfile");
400+
if (gt instanceof Iterable) {
401+
for (Object gti: (Iterable) gt) {
402+
if (gti != null && !"Group".equals(gti) && gti.toString().endsWith("Group")) {
403+
j.put("groupType", gti);
404+
if ("ProfileGroup".equals(gti)) {
405+
j.put("profile", gp);
406+
}
407+
break;
408+
}
409+
}
410+
}
411+
412+
UserUtils.groupDisplayName(j, acceptLanguage);
413+
j.put("displayName", j.getString("name"));
414+
415+
if ("ManualGroup".equals(j.getString("groupType")) && "BroadcastGroup".equals(j.getString("subType"))) {
416+
j.put("type", "BroadcastGroup");
417+
j.put("usedIn", usedInCCI);
418+
} else {
419+
j.put("type", "Group");
420+
j.put("usedIn", usedInAll);
421+
}
422+
} else {
423+
j.put("type", "User");
424+
j.put("usedIn", usedInAll);
425+
j.remove("groupProfile");
426+
j.remove("groupType");
427+
j.remove("nbUsers");
428+
if (profile.equals("Student")) {
429+
j.remove("relatives");
430+
}
431+
}
432+
433+
j.remove("name");
434+
j.remove("groupDisplayName");
435+
j.remove("sortDisplayName");
436+
j.remove("sortWeight");
437+
j.remove("subjects");
438+
j.remove("subType");
439+
j.remove("sorted_children_names");
440+
j.remove("sorted_functions");
441+
j.remove("sorted_disciplines");
442+
443+
res.add(j);
444+
}
445+
return res;
446+
}
447+
448+
private static JsonArray sortShareBookmarksByName(JsonArray sb) {
449+
List<JsonObject> list = sb.getList();
450+
list.sort(Comparator.comparing(o -> o.getString("displayName")));
451+
452+
return new JsonArray(list);
453+
}
454+
351455
public static void findUsersCanSeeMe(final EventBus eb, HttpServerRequest request,
352456
final Handler<JsonArray> handler) {
353457
JsonObject m = new JsonObject()
@@ -667,6 +771,13 @@ public void handle(JsonObject session) {
667771
});
668772
}
669773

774+
/**
775+
* Fetch the user's session information and return an unauthorized response if the user has no session. Therefore,
776+
* <b>there is no need to handle a failure of the returned Future</b>.
777+
* @param eb Event bus to be used to fetch the user's session
778+
* @param request Caller's request
779+
* @return The user's session information
780+
*/
670781
public static Future<UserInfos> getAuthenticatedUserInfos(EventBus eb, HttpServerRequest request) {
671782
final Promise<UserInfos> promise = Promise.promise();
672783
getSession(eb, request, session -> {

communication/src/main/java/org/entcore/communication/Communication.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void start(final Promise<Void> startPromise) throws Exception {
3535
TimelineHelper helper = new TimelineHelper(vertx, vertx.eventBus(), config);
3636
CommunicationController communicationController = new CommunicationController();
3737

38-
communicationController.setCommunicationService(new DefaultCommunicationService(helper, config.getJsonArray("discoverVisibleExpectedProfile", new JsonArray())));
38+
communicationController.setCommunicationService(new DefaultCommunicationService(vertx, helper, config));
3939

4040
addController(communicationController);
4141
setDefaultResourceFilter(new CommunicationFilter());

communication/src/main/java/org/entcore/communication/controllers/CommunicationController.java

+27-1
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,31 @@
3232
import fr.wseduc.webutils.http.BaseController;
3333
import fr.wseduc.webutils.http.Renders;
3434
import fr.wseduc.webutils.request.RequestUtils;
35+
import io.vertx.core.CompositeFuture;
3536
import io.vertx.core.Handler;
37+
import io.vertx.core.Promise;
3638
import io.vertx.core.eventbus.Message;
3739
import io.vertx.core.http.HttpServerRequest;
40+
import io.vertx.core.json.Json;
3841
import io.vertx.core.json.JsonArray;
3942
import io.vertx.core.json.JsonObject;
4043
import org.entcore.common.http.filter.AdminFilter;
4144
import org.entcore.common.http.filter.ResourceFilter;
45+
import org.entcore.common.neo4j.Neo4j;
4246
import org.entcore.common.user.UserUtils;
47+
import org.entcore.common.utils.StringUtils;
4348
import org.entcore.common.validation.StringValidation;
4449
import org.entcore.communication.filters.CommunicationDiscoverVisibleFilter;
4550
import org.entcore.communication.services.CommunicationService;
4651
import org.entcore.communication.services.impl.DefaultCommunicationService;
4752

4853
import java.util.List;
4954

55+
import static fr.wseduc.webutils.Utils.getOrElse;
5056
import static fr.wseduc.webutils.Utils.isNotEmpty;
5157
import static org.entcore.common.http.response.DefaultResponseHandler.*;
58+
import static org.entcore.common.neo4j.Neo4jResult.fullNodeMergeHandler;
59+
import static org.entcore.common.neo4j.Neo4jResult.validResultHandler;
5260

5361
public class CommunicationController extends BaseController {
5462

@@ -269,7 +277,7 @@ public void searchVisible(HttpServerRequest request) {
269277
"visibles.displayName as displayName, visibles.groupDisplayName as groupDisplayName, " +
270278
"HEAD(visibles.profiles) as profile, subjects" + nbUsers + groupTypes;
271279
communicationService.visibleUsers(user.getUserId(), null, expectedTypes, true, true, false,
272-
preFilter, customReturn, params, user.getType(), visibles -> {
280+
preFilter, customReturn, params, user.getType(), false, visibles -> {
273281
if (visibles.isRight()) {
274282
renderJson(request,
275283
UserUtils.translateAndGroupVisible(visibles.right().getValue(),
@@ -875,4 +883,22 @@ public void addDiscoverVisibleGroupUsers(HttpServerRequest request) {
875883
});
876884
}
877885

886+
/**
887+
* Search entities (users, groups) visible by the requester.
888+
* This endpoint can serve 2 different types of results based on the configuration :
889+
* - the old format that used to be served by the module conversation
890+
* - the new format which returns more data
891+
* @param request Caller's HTTP request
892+
*/
893+
@Get("/visible/search")
894+
@SecuredAction(value = "", type = ActionType.AUTHENTICATED)
895+
public void searchVisibleContacts(HttpServerRequest request) {
896+
UserUtils.getAuthenticatedUserInfos(eb, request)
897+
.onSuccess(userInfos -> {
898+
final String query = request.params().get("query");
899+
communicationService.searchVisibles(userInfos, query, I18n.acceptLanguage(request))
900+
.onSuccess(visibles -> renderJson(request, visibles))
901+
.onFailure(th -> renderError(request, new JsonObject().put("error", th.getMessage())));
902+
});
903+
}
878904
}

communication/src/main/java/org/entcore/communication/services/CommunicationService.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import fr.wseduc.webutils.Either;
2323

24+
import io.vertx.core.Future;
2425
import io.vertx.core.Handler;
2526
import io.vertx.core.http.HttpServerRequest;
2627
import io.vertx.core.json.JsonArray;
@@ -106,11 +107,12 @@ void applyDefaultRules(JsonArray structureIds, final Integer transactionId, fina
106107
void removeRules(String structureId, Handler<Either<String, JsonObject>> handler);
107108

108109
void visibleUsers(String userId, String structureId, JsonArray expectedTypes, boolean itSelf, boolean myGroup,
109-
boolean profile, String preFilter, String customReturn, JsonObject additionnalParams,
110+
boolean profile, String preFilter, String customReturn, JsonObject additionalParams,
110111
Handler<Either<String, JsonArray>> handler);
111112

112113
void visibleUsers(String userId, String structureId, JsonArray expectedTypes, boolean itSelf, boolean myGroup,
113-
boolean profile, String preFilter, String customReturn, JsonObject additionnalParams, String userProfile,
114+
boolean profile, String preFilter, String customReturn, JsonObject additionalParams, String userProfile,
115+
boolean reverseUnion,
114116
Handler<Either<String, JsonArray>> handler);
115117

116118
void usersCanSeeMe(String userId, final Handler<Either<String, JsonArray>> handler);
@@ -167,5 +169,15 @@ void visibleManualGroups(String userId, String customReturn, JsonObject addition
167169
void addDiscoverVisibleGroupUsers(UserInfos user, String groupId, JsonObject body, HttpServerRequest request, Handler<Either<String, JsonObject>> handler);
168170

169171
void getDiscoverVisibleAcceptedProfile(Handler<Either<String, JsonArray>> handler);
172+
173+
174+
/**
175+
* Search visible users.
176+
* @param user Requester
177+
* @param search Keyword to filter the search results
178+
* @param language User's language
179+
*/
180+
Future<JsonArray> searchVisibles(UserInfos user, String search, String language);
181+
170182
}
171183

0 commit comments

Comments
 (0)