diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/PolicyData.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/PolicyData.java index ef7936e684cc73496e1de8d2540efdd1d7d99a2f..9402d62bf931eca49dc377b5681cf5c11169dcf6 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/user/PolicyData.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/PolicyData.java @@ -23,4 +23,5 @@ public class PolicyData { private Boolean upnpEnabled; private Boolean rendezVous; private String defaultModerators; + private Boolean allowLookup; } diff --git a/jams-react-client/public/locales/en/translation.json b/jams-react-client/public/locales/en/translation.json index b76faa8610872a8a3b419a0c55000f6a93708441..31b43c352815812b2d56bd9985ed789e697ba97a 100644 --- a/jams-react-client/public/locales/en/translation.json +++ b/jams-react-client/public/locales/en/translation.json @@ -245,5 +245,6 @@ "auto_answer_calls_info": "If this option is enabled, incomming calls will be automaticly answered. This option can be usefull if you want for example to monitor your house or a particular room when you are away from home.", "local_lan_info": "If this option is enabled, you will be able to communicate with connected contacts on you local lan, even if your lan is disconnected from internet.", "rendezvous_info": "If this option is enabled, incomming calls will automaticly be added to a conference room.", - "rendezvous_moderators_info": "Moderators are people allowed to manage rendezvous points and conferences even if they are not hosted on their devices." + "rendezvous_moderators_info": "Moderators are people allowed to manage rendezvous points and conferences even if they are not hosted on their devices.", + "allow_jami_user_to_search_for_other_contacts": "Allow Jami user to search for other contacts" } diff --git a/jams-react-client/public/locales/fr/translation.json b/jams-react-client/public/locales/fr/translation.json index d8d6d22d37e46919187d0c5b7cd0f902315fd721..4a2e3246a3856d8577063f62cc7c965857804f91 100644 --- a/jams-react-client/public/locales/fr/translation.json +++ b/jams-react-client/public/locales/fr/translation.json @@ -245,5 +245,6 @@ "auto_answer_calls_info": "Si activé, les appels entrants seront automatiquement décrochés. Cette option peut être utile si vous souhaitez, par exemple, surveiller votre maison ou une pièce en particulier pendant votre absence", "local_lan_info": "Si activé, il sera possible de communiquer avec les personnes connectées sur votre réseau local, même si ce dernier est isolé d'internet", "rendezvous_info": "Si activé, les appels entrants sont automatiquement ajoutés à une salle de conférence", - "rendezvous_moderators_info": "Les modérateurs sont les personnes autorisées à administrer le point de rendez-vous et les conférences hébergées depuis ce compte" + "rendezvous_moderators_info": "Les modérateurs sont les personnes autorisées à administrer le point de rendez-vous et les conférences hébergées depuis ce compte", + "allow_jami_user_to_search_for_other_contacts": "Allow Jami user to search for other contacts" } diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js index 5beaa8f4d982dedd2207cfa9ae727f98cd32c6c4..4847d411dfaf3d5ec22df89572512ed4438e8160 100644 --- a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js +++ b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js @@ -146,6 +146,8 @@ export default function EditBlueprintPermissions(props) { const [proxyServer, setProxyServer] = React.useState("dhtproxy.jami.net"); const [dhtProxyListUrl, setDhtProxyListUrl] = React.useState(""); + const [allowLookup, setAllowLookup] = React.useState(true); + const [open, setOpen] = React.useState(false); const [message, setMessage] = React.useState(false); const [severity, setSeverity] = React.useState("success"); @@ -207,7 +209,8 @@ export default function EditBlueprintPermissions(props) { setTurnServerPassword(policyData["turnServerPassword"]); setProxyEnabled(policyData["proxyEnabled"]); setProxyServer(policyData["proxyServer"]); - setDhtProxyListUrl(policyData["dhtProxyListUrl"]); + setDhtProxyListUrl(); + setAllowLookup(policyData["autoAnswer"]); policyData["defaultModerators"].split("/").forEach((id) => { if(id !== "undefined" && id !== ""){ @@ -254,6 +257,7 @@ export default function EditBlueprintPermissions(props) { proxyEnabled: proxyEnabled, proxyServer: proxyServer, dhtProxyListUrl: dhtProxyListUrl, + allowLookup: allowLookup, }; if (field === "peerDiscovery") { @@ -446,11 +450,34 @@ export default function EditBlueprintPermissions(props) { </FormGroup> </Grid> <Grid item xs={12} sm={12} md={12}> + <FormLabel component="legend">Allow Lookup</FormLabel> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={allowLookup} + color="primary" + onChange={(e) => { + setAllowLookup(e.target.checked); + handleUpdatePermissions( + "allowLookup", + e.target.checked + ); + }} + name="allowLookup" + /> + } + label={i18next.t("allow_jami_user_to_search_for_other_contacts", "Allow Jami user to search for other contacts")} + /> + <CustomPopupState message={i18next.t("local_lan_info", "If this option is enabled, users will be able to search for other contacts and add them.")} /> + </FormGroup> + </Grid> + <Grid item xs={12} sm={12} md={12}> + </Grid> </Grid> </Grid> </Grid> - </Grid> </div> </CardBody> </Card> diff --git a/jams-react-client/src/views/Blueprints/Blueprints.js b/jams-react-client/src/views/Blueprints/Blueprints.js index 8aebb3b95d7bd29b309f9a72547198db4e441755..2bdddb4fadae7b5f3baeea8e5edf4a67ced86935 100644 --- a/jams-react-client/src/views/Blueprints/Blueprints.js +++ b/jams-react-client/src/views/Blueprints/Blueprints.js @@ -191,6 +191,7 @@ export default function Blueprints() { rendezVous: false, defaultModerators: "", upnpEnabled: true, + allowLookup: true, }; axios( diff --git a/jams-react-client/src/views/Users/Users.js b/jams-react-client/src/views/Users/Users.js index 52527d72043952d699565f936611bba5f0adc439..ee96a21f4409daa2bbb8f75d325ee81424a260c4 100644 --- a/jams-react-client/src/views/Users/Users.js +++ b/jams-react-client/src/views/Users/Users.js @@ -116,7 +116,7 @@ export default function Users(props) { setLoading(false); }) .catch((error) => { - console.log(error); + setLoading(false); if (error.response.status === 401) { auth.authenticated = false; history.push("/"); @@ -150,10 +150,9 @@ export default function Users(props) { } }) .catch((error) => { - console.log(error); setUsers([]); - setNoMatchFound(true); + setLoading(false); if (error.response.status === 401) { auth.authenticated = false; history.push("/"); diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java index 2bdf886074eb56ac155720b56c50af4a3453b3fc..6fa9151e344902410b338b3e1822a44af11680b3 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java @@ -22,21 +22,21 @@ */ package net.jami.jams.server.servlets.api.auth.directory; +import com.jsoniter.JsonIterator; import com.jsoniter.output.JsonStream; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import net.jami.jams.common.annotations.JsonContent; import net.jami.jams.common.authentication.AuthenticationSource; import net.jami.jams.common.authentication.AuthenticationSourceType; import net.jami.jams.common.authmodule.AuthModuleKey; import net.jami.jams.common.dao.StatementElement; import net.jami.jams.common.dao.StatementList; -import net.jami.jams.common.objects.user.AccessLevel; -import net.jami.jams.common.objects.user.User; -import net.jami.jams.common.objects.user.UserGroupMapping; -import net.jami.jams.common.objects.user.UserProfile; +import net.jami.jams.common.objects.responses.DeviceRegistrationResponse; +import net.jami.jams.common.objects.user.*; import net.jami.jams.server.servlets.api.install.CachedObjects; import org.json.JSONObject; @@ -48,6 +48,7 @@ import static net.jami.jams.server.Server.dataStore; import static net.jami.jams.server.Server.nameServer; import static net.jami.jams.server.Server.userAuthenticationModule; +@Slf4j @WebServlet("/api/auth/directory/search") public class SearchDirectoryServlet extends HttpServlet { // The search directory function does not automatically create users, this would @@ -72,6 +73,34 @@ public class SearchDirectoryServlet extends HttpServlet { ConcurrentHashMap<AuthModuleKey, AuthenticationSource> authSources = new ConcurrentHashMap<>( userAuthenticationModule.getAuthSources()); + // Check if the actual user is allowed to lookup in the directory + Group group = new Group(); + StatementList statementList1 = new StatementList(); + + statementList1.addStatement(new StatementElement("username", "=", req.getAttribute("username").toString(), "")); + if (dataStore.getUserGroupMappingsDao().getObjects(statementList1) != null && !dataStore.getUserGroupMappingsDao().getObjects(statementList1).isEmpty()) { + UserGroupMapping mapping = dataStore.getUserGroupMappingsDao().getObjects(statementList1).get(0); + statementList1 = new StatementList(); + statementList1.addStatement(new StatementElement("id", "=", mapping.getGroupId(), "")); + group = dataStore.getGroupDao().getObjects(statementList1).get(0); + } + + if (!group.isEmpty() && group.hasBlueprint()) { + StatementElement st2 = new StatementElement("name", "=", group.getBlueprint(), ""); + StatementList statementList2 = new StatementList(); + statementList2.addStatement((st2)); + try { + Policy policy = dataStore.getPolicyDao().getObjects(statementList2).get(0); + PolicyData policyData = JsonIterator.deserialize(policy.getPolicyData(),PolicyData.class); + if(!policyData.getAllowLookup()) { + resp.sendError(403, "Operation not allowed!"); + return; + } + } catch (Exception e1) { + log.warn("No policy available for user - not adding a policy component to response"); + } + } + if (authSources.size() > 1) { authSources.forEach((k, v) -> { if (k.getType() == AuthenticationSourceType.LOCAL) @@ -127,6 +156,6 @@ public class SearchDirectoryServlet extends HttpServlet { resp.getOutputStream().write((obj.toString()).getBytes()); resp.setStatus(200); } else - resp.setStatus(204, "No users were found!"); + resp.sendError(204, "No users were found!"); } } \ No newline at end of file