From fc7906cae9dee8e1ff7cadcd45179df1c7307b4f Mon Sep 17 00:00:00 2001 From: Larbi Gharib <larbi.gharib@savoirfairelinux.com> Date: Fri, 4 Dec 2020 10:51:16 -0500 Subject: [PATCH] Groupename to groupId Change-Id: I63bec131410ba30e8d9eef573e9e7e4eba264e86 --- .../java/net/jami/datastore/dao/GroupDao.java | 18 +- .../datastore/dao/UserGroupMappingsDao.java | 29 +- .../jami/datastore/dao/UserProfileDao.java | 6 +- .../net/jami/datastore/main/DataStore.java | 33 --- .../db/migration/V27__UserGroupMappings.sql | 6 + .../resources/db/migration/V35__Group.sql | 2 + .../db/migration/V17__UserGroupMappings.sql | 2 +- .../db/migration/V27__UserGroupMappings.sql | 6 + .../resources/db/migration/V35__Group.sql | 2 + .../jami/jams/common/objects/user/Group.java | 19 +- .../common/objects/user/UserGroupMapping.java | 24 +- .../jams/common/objects/user/UserProfile.java | 8 - .../public/locales/en/translation.json | 3 +- .../public/locales/fr/translation.json | 3 +- .../src/assets/img/favicon_jami.png | Bin 0 -> 88137 bytes .../src/components/Drawer/Drawer.js | 2 +- jams-react-client/src/globalUrls.js | 18 +- jams-react-client/src/index.js | 2 +- .../src/routes/BlueprintRoute.js | 2 +- .../src/routes/BlueprintsRoute.js | 2 +- jams-react-client/src/routes/GroupRoute.js | 7 +- jams-react-client/src/routes/GroupsRoute.js | 5 +- jams-react-client/src/routes/SettingsRoute.js | 2 +- .../src/views/Groups/EditGroup.js | 266 +++++++++++------- jams-react-client/src/views/Groups/Groups.js | 188 +++++-------- .../views/UserProfile/DisplayUserProfile.js | 146 ++++++---- .../core/workflows/AddUserToGroupFlow.java | 70 ----- .../core/workflows/RegisterDeviceFlow.java | 55 ++-- .../directory/DirectoryEntryServlet.java | 3 +- .../api/admin/group/AddGroupServlet.java | 42 +++ .../api/admin/group/GroupProfileServlet.java | 78 ----- .../api/admin/group/GroupServlet.java | 172 +++-------- .../api/admin/group/GroupsServlet.java | 46 +++ .../api/admin/group/UserGroupServlet.java | 123 ++++++++ .../api/admin/users/UserGroupsServlet.java | 59 ++++ .../api/auth/user/UserProfileServlet.java | 1 - 36 files changed, 761 insertions(+), 689 deletions(-) create mode 100644 datastore/src/main/resources/db/migration/V27__UserGroupMappings.sql create mode 100644 datastore/src/main/resources/db/migration/V35__Group.sql create mode 100644 datastore/src/test/resources/db/migration/V27__UserGroupMappings.sql create mode 100644 datastore/src/test/resources/db/migration/V35__Group.sql create mode 100644 jams-react-client/src/assets/img/favicon_jami.png delete mode 100644 jams-server/src/main/java/net/jami/jams/server/core/workflows/AddUserToGroupFlow.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/AddGroupServlet.java delete mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupProfileServlet.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java diff --git a/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java b/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java index e33bc036..045136c8 100644 --- a/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java +++ b/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java @@ -22,7 +22,7 @@ public class GroupDao extends AbstractDao<Group>{ SQLConnection connection = DataStore.connectionPool.getConnection(); try{ PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO groups " + - "(name, blueprint) VALUES (?, ?)"); + "(id, name, blueprint) VALUES (?, ?, ?)"); ps = object.getInsert(ps); return ps.executeUpdate() != 0; } @@ -38,17 +38,17 @@ public class GroupDao extends AbstractDao<Group>{ @Override public boolean updateObject(StatementList update, StatementList constraints) { - String name = update.getStatements().get(0).getValue(); - String blueprint = update.getStatements().get(1).getValue(); - String oldName = constraints.getStatements().get(0).getValue(); + String id = update.getStatements().get(0).getValue(); + String name = update.getStatements().get(1).getValue(); + String blueprint = update.getStatements().get(2).getValue(); SQLConnection connection = DataStore.connectionPool.getConnection(); try{ - PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE groups SET name = ?, blueprint = ? WHERE name = ?"); + PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE groups SET name = ?, blueprint = ? WHERE id = ?"); ps.setString(1, name); ps.setString(2, blueprint); - ps.setString(3, oldName); + ps.setString(3, id); return ps.executeUpdate() != 0; } catch (SQLException e){ @@ -63,12 +63,12 @@ public class GroupDao extends AbstractDao<Group>{ @Override public boolean deleteObject(StatementList constraints) { - String name = constraints.getStatements().get(0).getValue(); + String id = constraints.getStatements().get(0).getValue(); SQLConnection connection = DataStore.connectionPool.getConnection(); try { - PreparedStatement ps = connection.getConnection().prepareStatement("DELETE FROM groups WHERE name = ?"); - ps.setString(1, name); + PreparedStatement ps = connection.getConnection().prepareStatement("DELETE FROM groups WHERE id = ?"); + ps.setString(1, id); return ps.executeUpdate() != 0; } catch (SQLException e){ log.error("An error has occurred while trying to delete a group: " + e.toString()); diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java index 9e576cf8..c58b31aa 100644 --- a/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java +++ b/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java @@ -7,6 +7,7 @@ import net.jami.jams.common.dao.connectivity.SQLConnection; import net.jami.jams.common.objects.user.UserGroupMapping; import java.sql.PreparedStatement; +import java.sql.SQLException; @Slf4j public class UserGroupMappingsDao extends AbstractDao<UserGroupMapping>{ @@ -22,7 +23,7 @@ public class UserGroupMappingsDao extends AbstractDao<UserGroupMapping>{ SQLConnection connection = DataStore.connectionPool.getConnection(); try { PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO usergroupmappings " + - "(username, groups)" + " VALUES " + "(?,?)"); + "(username, groupId)" + " VALUES " + "(?,?)"); ps = object.getInsert(ps); return ps.executeUpdate() != 0; } catch (Exception e) { @@ -34,22 +35,30 @@ public class UserGroupMappingsDao extends AbstractDao<UserGroupMapping>{ } @Override - public boolean updateObject(StatementList update, StatementList constraints) { + public boolean deleteObject(StatementList constraints) { - String groups = update.getStatements().get(0).getValue(); String username = constraints.getStatements().get(0).getValue(); - + String groupId = constraints.getStatements().get(1).getValue(); SQLConnection connection = DataStore.connectionPool.getConnection(); + try { - PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE usergroupmappings SET groups = ? WHERE username = ?"); - ps.setString(1, groups); - ps.setString(2, username); - return ps.executeUpdate() != 0; - } catch (Exception e) { - log.error("An error has occurred while trying to update a user profile: " + e.toString()); + if(username.equals("*")){ + PreparedStatement ps = connection.getConnection().prepareStatement("DELETE FROM usergroupmappings WHERE groupId = ?"); + ps.setString(1, groupId); + return ps.executeUpdate() != 0; + } + else { + PreparedStatement ps = connection.getConnection().prepareStatement("DELETE FROM usergroupmappings WHERE username = ? AND groupId = ?"); + ps.setString(1, username); + ps.setString(2, groupId); + return ps.executeUpdate() != 0; + } + } catch (SQLException e){ + log.error("An error has occurred while trying to delete a group member: " + e.toString()); return false; } finally { DataStore.connectionPool.returnConnection(connection); } } + } diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java index 56d06de6..7fa7a52e 100644 --- a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java +++ b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java @@ -46,8 +46,8 @@ public class UserProfileDao extends AbstractDao<UserProfile> { SQLConnection connection = DataStore.connectionPool.getConnection(); try { PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO local_directory " + - "(username, firstName, lastName, email, profilePicture, organization, phoneNumber, phoneNumberExtension, faxNumber, mobileNumber, groupMemberships)" + - " VALUES " + "(?,?,?,?,?,?,?,?,?,?,?)"); + "(username, firstName, lastName, email, profilePicture, organization, phoneNumber, phoneNumberExtension, faxNumber, mobileNumber)" + + " VALUES " + "(?,?,?,?,?,?,?,?,?,?)"); ps = object.getInsert(ps); return ps.executeUpdate() != 0; } catch (Exception e) { @@ -63,7 +63,7 @@ public class UserProfileDao extends AbstractDao<UserProfile> { SQLConnection connection = DataStore.connectionPool.getConnection(); try { - PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE local_directory SET firstname = ?, lastName = ?, email = ?, profilePicture = ?, organization = ?, phoneNumber = ?, phoneNumberExtension = ?, faxNumber = ?, mobileNumber = ?, groupMemberships = ? WHERE username = ?"); + PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE local_directory SET firstname = ?, lastName = ?, email = ?, profilePicture = ?, organization = ?, phoneNumber = ?, phoneNumberExtension = ?, faxNumber = ?, mobileNumber = ? WHERE username = ?"); for (int i = 1; i < update.getStatements().size(); i++) { ps.setString(i, update.getStatements().get(i).getValue()); } diff --git a/datastore/src/main/java/net/jami/datastore/main/DataStore.java b/datastore/src/main/java/net/jami/datastore/main/DataStore.java index 15cb8c23..ae4c229c 100644 --- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java +++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java @@ -144,27 +144,6 @@ public class DataStore implements AuthenticationSource { return userProfileDao.storeObject(userProfile); } - public boolean updateUserGroupMappings (UserProfile userProfile) { - StatementList statementList = new StatementList(); - statementList.addStatement(new StatementElement("username", "=", userProfile.getUsername(), "")); - if (getUserGroupMappingsDao().getObjects(statementList) != null && !getUserGroupMappingsDao().getObjects(statementList).isEmpty()) { - UserGroupMapping mapping = getUserGroupMappingsDao().getObjects(statementList).get(0); - List<String> list = new ArrayList<>(); - if (mapping.getUsername().equals(userProfile.getUsername())) { - String[] splits = mapping.getGroups().split(","); - - for (int i = 0; i < splits.length; i++) - list.add(splits[i]); - } - if (!list.isEmpty()) - userProfile.setGroupMemberships(list); - - return (updateUserProfile(userProfile)); - } - - return true; - } - public boolean updateUserProfile(UserProfile userProfile){ StatementList update = new StatementList(); @@ -178,18 +157,6 @@ public class DataStore implements AuthenticationSource { update.addStatement(new StatementElement("phoneNumberExtension","=",userProfile.getPhoneNumberExtension(),"")); update.addStatement(new StatementElement("faxNumber","=",userProfile.getFaxNumber(),"")); update.addStatement(new StatementElement("mobileNumber","=",userProfile.getMobileNumber(),"")); - if (userProfile.getGroupMemberships() != null && !userProfile.getGroupMemberships().isEmpty()) { - String groups = ""; - for (String s: userProfile.getGroupMemberships()) { - if (groups.equals("")) - groups = s; - else - groups = groups.concat("," + s); - } - update.addStatement(new StatementElement("groupMemberships","=", groups ,"")); - } else - update.addStatement(new StatementElement("groupMemberships","=", "" ,"")); - return userProfileDao.updateObject(update, null); } diff --git a/datastore/src/main/resources/db/migration/V27__UserGroupMappings.sql b/datastore/src/main/resources/db/migration/V27__UserGroupMappings.sql new file mode 100644 index 00000000..f8567a23 --- /dev/null +++ b/datastore/src/main/resources/db/migration/V27__UserGroupMappings.sql @@ -0,0 +1,6 @@ +ALTER TABLE usergroupmappings DROP PRIMARY KEY; +ALTER TABLE usergroupmappings ADD COLUMN GROUPID varchar(36); +UPDATE usergroupmappings SET GROUPID = groups; +ALTER TABLE usergroupmappings DROP COLUMN groups; +ALTER TABLE usergroupmappings ADD id int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1); +ALTER TABLE usergroupmappings ADD PRIMARY KEY (id); \ No newline at end of file diff --git a/datastore/src/main/resources/db/migration/V35__Group.sql b/datastore/src/main/resources/db/migration/V35__Group.sql new file mode 100644 index 00000000..a8ca7fb4 --- /dev/null +++ b/datastore/src/main/resources/db/migration/V35__Group.sql @@ -0,0 +1,2 @@ +ALTER TABLE groups DROP PRIMARY KEY; +ALTER TABLE groups ADD ID varchar(36) PRIMARY KEY not null default ''; \ No newline at end of file diff --git a/datastore/src/test/resources/db/migration/V17__UserGroupMappings.sql b/datastore/src/test/resources/db/migration/V17__UserGroupMappings.sql index d9b8deb1..2bcd6e18 100644 --- a/datastore/src/test/resources/db/migration/V17__UserGroupMappings.sql +++ b/datastore/src/test/resources/db/migration/V17__UserGroupMappings.sql @@ -1,3 +1,3 @@ CREATE TABLE usergroupmappings (username varchar(255), -groupMemberships CLOB, +groups varchar(5000), PRIMARY KEY (username)); \ No newline at end of file diff --git a/datastore/src/test/resources/db/migration/V27__UserGroupMappings.sql b/datastore/src/test/resources/db/migration/V27__UserGroupMappings.sql new file mode 100644 index 00000000..f8567a23 --- /dev/null +++ b/datastore/src/test/resources/db/migration/V27__UserGroupMappings.sql @@ -0,0 +1,6 @@ +ALTER TABLE usergroupmappings DROP PRIMARY KEY; +ALTER TABLE usergroupmappings ADD COLUMN GROUPID varchar(36); +UPDATE usergroupmappings SET GROUPID = groups; +ALTER TABLE usergroupmappings DROP COLUMN groups; +ALTER TABLE usergroupmappings ADD id int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1); +ALTER TABLE usergroupmappings ADD PRIMARY KEY (id); \ No newline at end of file diff --git a/datastore/src/test/resources/db/migration/V35__Group.sql b/datastore/src/test/resources/db/migration/V35__Group.sql new file mode 100644 index 00000000..a8ca7fb4 --- /dev/null +++ b/datastore/src/test/resources/db/migration/V35__Group.sql @@ -0,0 +1,2 @@ +ALTER TABLE groups DROP PRIMARY KEY; +ALTER TABLE groups ADD ID varchar(36) PRIMARY KEY not null default ''; \ No newline at end of file diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/Group.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/Group.java index 0bd5a5d8..a77b95c1 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/user/Group.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/Group.java @@ -17,20 +17,21 @@ import java.util.List; @Getter @Setter public class Group implements DatabaseObject { + private String id; private String name; private String blueprint; - private List<String> groupMembers; public Group(ResultSet rs) throws SQLException { + this.id = rs.getString("id"); this.name = rs.getString("name"); this.blueprint = rs.getString("blueprint"); - this.groupMembers = new ArrayList<>(); } @Override public PreparedStatement getInsert(PreparedStatement ps) throws SQLException { - ps.setString(1, name); - ps.setString(2, blueprint); + ps.setString(1, id); + ps.setString(2, name); + ps.setString(3, blueprint); return ps; } @@ -43,4 +44,14 @@ public class Group implements DatabaseObject { public PreparedStatement getUpdate(PreparedStatement ps) throws Exception { return null; } + + public boolean isEmpty() { + if(this.id == null && this.name == null) return true; + return false; + } + + public boolean hasBlueprint() { + if(this.blueprint == null || this.blueprint.equals("")) return false; + return true; + } } diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserGroupMapping.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserGroupMapping.java index 46f477a9..2925ebd6 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserGroupMapping.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserGroupMapping.java @@ -16,35 +16,17 @@ import java.sql.ResultSet; public class UserGroupMapping implements DatabaseObject { private String username; - private String groups; + private String groupId; public UserGroupMapping(ResultSet rs) throws Exception { this.username = rs.getString("username"); - this.groups = rs.getString("groups"); - } - - public void addGroup(String s) { - if (this.groups.equals("")) - this.groups = s; - else - this.groups = this.groups.concat("," + s); - } - - public void removeGroup(String s) { - if (this.groups.contains(s) ) { - if (this.groups.contains(",")) { - this.groups = this.groups.replace(s + ",", ""); - this.groups = this.groups.replace("," + s, ""); - } - else - this.groups = ""; - } + this.groupId = rs.getString("groupId"); } @Override public PreparedStatement getInsert(PreparedStatement ps) throws Exception { ps.setString(1, username); - ps.setString(2, groups); + ps.setString(2, groupId); return ps; } diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java index b9a67de1..23e56b57 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java @@ -75,7 +75,6 @@ public class UserProfile implements DatabaseObject { private String faxNumber; private String mobileNumber; private String id; - private List<String> groupMemberships; public UserProfile(ResultSet rs) throws Exception { this.username = rs.getString("username"); @@ -88,7 +87,6 @@ public class UserProfile implements DatabaseObject { this.phoneNumberExtension = rs.getString("phoneNumberExtension"); this.faxNumber = rs.getString("faxNumber"); this.mobileNumber = rs.getString("mobileNumber"); - this.groupMemberships = new ArrayList<>(Arrays.asList(rs.getString("groupMemberships").split(","))); } @JsonIgnore @@ -130,10 +128,6 @@ public class UserProfile implements DatabaseObject { ps.setString(8, phoneNumberExtension); ps.setString(9, faxNumber); ps.setString(10, mobileNumber); - if (!groupMemberships.isEmpty()) - ps.setString(11, JsonStream.serialize(groupMemberships)); - else - ps.setString(11, ""); return ps; } @@ -176,8 +170,6 @@ public class UserProfile implements DatabaseObject { this.faxNumber = ""; if (this.mobileNumber == null) this.mobileNumber = ""; - if (this.groupMemberships == null) - this.groupMemberships = new ArrayList<>(); } } diff --git a/jams-react-client/public/locales/en/translation.json b/jams-react-client/public/locales/en/translation.json index 9ef108ce..0ca38add 100644 --- a/jams-react-client/public/locales/en/translation.json +++ b/jams-react-client/public/locales/en/translation.json @@ -235,5 +235,6 @@ "add_user_to_group": "Add user to group ...", "add_user_to_a_group": "Add user to a group", "remove_from_group": "Remove from group", - "myprofile": "My profile" + "myprofile": "My profile", + "select_blueprint": "Select a blueprint" } diff --git a/jams-react-client/public/locales/fr/translation.json b/jams-react-client/public/locales/fr/translation.json index 5aad0bef..9e037d6e 100644 --- a/jams-react-client/public/locales/fr/translation.json +++ b/jams-react-client/public/locales/fr/translation.json @@ -235,5 +235,6 @@ "add_user_to_group": "Ajouter un utilisateur au groupe...", "add_user_to_a_group": "Ajouter l'utilisateur à un groupe", "remove_from_group": "Retirer du groupe", - "myprofile": "Mon profil" + "myprofile": "My profile", + "select_blueprint": "Select a blueprint" } diff --git a/jams-react-client/src/assets/img/favicon_jami.png b/jams-react-client/src/assets/img/favicon_jami.png new file mode 100644 index 0000000000000000000000000000000000000000..794f3628e2eb68df1f8c287ee4ed9f37e73fb9c0 GIT binary patch literal 88137 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�T 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 Rsz``SPs>oVM#C=Re*n4&DMtVR literal 0 HcmV?d00001 diff --git a/jams-react-client/src/components/Drawer/Drawer.js b/jams-react-client/src/components/Drawer/Drawer.js index 267c939a..6cb43848 100644 --- a/jams-react-client/src/components/Drawer/Drawer.js +++ b/jams-react-client/src/components/Drawer/Drawer.js @@ -77,7 +77,7 @@ export default function TemporaryDrawer(props) { button key={target.name} onClick={() => { - props.addElementToTarget(target.name); + props.addElementToTarget(target); props.setOpenDrawer(false); }} > diff --git a/jams-react-client/src/globalUrls.js b/jams-react-client/src/globalUrls.js index 85565dc0..9d7f89c4 100644 --- a/jams-react-client/src/globalUrls.js +++ b/jams-react-client/src/globalUrls.js @@ -17,9 +17,11 @@ const api_path_delete_auth_user_revoke = "/api/auth/user"; const api_path_delete_admin_device_revoke = "/api/admin/device"; const api_path_delete_auth_device_revoke = "/api/auth/device"; const api_path_rename_device = "/api/auth/device"; -const api_path_get_list_group = "/api/admin/group"; -const api_path_delete_group = "/api/admin/group"; -const api_path_put_update_group = "/api/admin/group"; +const api_path_get_list_group = "/api/admin/groups"; +const api_path_post_create_group = "/api/admin/group"; +const api_path_delete_group = "/api/admin/group/"; +const api_path_put_update_group = "/api/admin/group/"; +const api_path_get_group = "/api/admin/group/"; const api_path_get_server_status = "/api/info"; const api_path_get_post_configuration_auth_service = "/api/configuration/authservice"; @@ -31,7 +33,6 @@ const api_path_get_subscription_status = "/api/admin/subscription"; const api_path_get_directories = "/api/auth/directories"; const api_path_get_needs_update = "/api/admin/update"; const api_path_get_start_update = "/api/admin/update"; -const api_path_post_create_group = "/api/admin/group"; const api_path_post_create_user = "/api/admin/user"; const api_path_put_update_user = "/api/admin/user"; const api_path_get_auth_user = "/api/auth/user"; @@ -50,6 +51,10 @@ const api_path_blueprints = "/api/admin/policy"; const api_path_get_user_profile = "/api/auth/userprofile/"; const api_path_get_ns_name_from_addr = "/api/nameserver/addr/"; const api_path_get_ns_addr_from_name = "/api/nameserver/name/"; +const api_path_get_group_members = "/api/admin/group/members/"; +const api_path_post_group_member = "/api/admin/group/members/"; +const api_path_delete_group_member = "/api/admin/group/members/"; +const api_path_get_admin_user_groups = "/api/admin/user/groups/"; module.exports = { uri, @@ -98,8 +103,13 @@ module.exports = { api_path_get_list_group, api_path_post_create_group, api_path_put_update_group, + api_path_get_group, api_path_blueprints, api_path_get_user_profile, api_path_get_ns_name_from_addr, api_path_get_ns_addr_from_name, + api_path_get_group_members, + api_path_post_group_member, + api_path_delete_group_member, + api_path_get_admin_user_groups }; diff --git a/jams-react-client/src/index.js b/jams-react-client/src/index.js index 587dbcdf..117ab849 100644 --- a/jams-react-client/src/index.js +++ b/jams-react-client/src/index.js @@ -52,7 +52,7 @@ auth.isServerInstalled(() => { <ProtectedRoute path="/user/:username" component={UserRoute} /> <ProtectedRoute path="/createuser" component={CreateUserRoute} /> <ProtectedRoute path="/groups" component={GroupsRoute} /> - {/* <ProtectedRoute path="/group/:groupname" component={GroupRoute} /> */} + <ProtectedRoute path="/group/:groupid" component={GroupRoute} /> <ProtectedRoute path="/blueprints" component={BlueprintsRoute} /> <ProtectedRoute path="/blueprint/:blueprintname" component={BlueprintRoute} /> <ProtectedRoute path="/settings" component={SettingsRoute} /> diff --git a/jams-react-client/src/routes/BlueprintRoute.js b/jams-react-client/src/routes/BlueprintRoute.js index 182d9901..d9f87304 100644 --- a/jams-react-client/src/routes/BlueprintRoute.js +++ b/jams-react-client/src/routes/BlueprintRoute.js @@ -3,7 +3,7 @@ import React from "react"; import BaseLayout from "layouts/BaseLayout.js"; import Blueprint from "views/Blueprint/Blueprint"; -export default function UsersRoute (props) { +export default function BlueprintRoute (props) { return ( <BaseLayout component={<Blueprint blueprintName={props.match.params.blueprintname} />} /> ) diff --git a/jams-react-client/src/routes/BlueprintsRoute.js b/jams-react-client/src/routes/BlueprintsRoute.js index cd765700..35037ee6 100644 --- a/jams-react-client/src/routes/BlueprintsRoute.js +++ b/jams-react-client/src/routes/BlueprintsRoute.js @@ -4,7 +4,7 @@ import Blueprints from "views/Blueprints/Blueprints.js"; import ListLayout from "layouts/ListLayout.js"; -export default function UsersRoute () { +export default function BlueprintsRoute () { return ( <ListLayout component={<Blueprints />} /> ) diff --git a/jams-react-client/src/routes/GroupRoute.js b/jams-react-client/src/routes/GroupRoute.js index 4fe4eb49..d33110e1 100644 --- a/jams-react-client/src/routes/GroupRoute.js +++ b/jams-react-client/src/routes/GroupRoute.js @@ -1,11 +1,10 @@ import React from "react"; +import ListLayout from "layouts/ListLayout.js"; import EditGroup from "views/Groups/EditGroup.js"; -import BaseLayout from "layouts/BaseLayout.js"; - -export default function UsersRoute (props) { +export default function GroupRoute (props) { return ( - <BaseLayout component={<EditGroup groupName={props.match.params.groupname} />} /> + <ListLayout component={<EditGroup groupid={props.match.params.groupid} />} /> ) } \ No newline at end of file diff --git a/jams-react-client/src/routes/GroupsRoute.js b/jams-react-client/src/routes/GroupsRoute.js index ea731f5c..db4bc713 100644 --- a/jams-react-client/src/routes/GroupsRoute.js +++ b/jams-react-client/src/routes/GroupsRoute.js @@ -1,10 +1,9 @@ import React from "react"; -import Groups from "views/Groups/Groups.js"; - import ListLayout from "layouts/ListLayout.js"; +import Groups from "views/Groups/Groups.js"; -export default function UsersRoute () { +export default function GroupsRoute () { return ( <ListLayout component={<Groups />} /> ) diff --git a/jams-react-client/src/routes/SettingsRoute.js b/jams-react-client/src/routes/SettingsRoute.js index 60fd2a61..c645ee93 100644 --- a/jams-react-client/src/routes/SettingsRoute.js +++ b/jams-react-client/src/routes/SettingsRoute.js @@ -4,7 +4,7 @@ import Settings from "views/Settings/Settings.js"; import BaseLayout from "layouts/BaseLayout.js"; -export default function UsersRoute (props) { +export default function SettingsRoute (props) { return ( <BaseLayout component={<Settings />} /> ) diff --git a/jams-react-client/src/views/Groups/EditGroup.js b/jams-react-client/src/views/Groups/EditGroup.js index e84c6899..4c0ddf6c 100644 --- a/jams-react-client/src/views/Groups/EditGroup.js +++ b/jams-react-client/src/views/Groups/EditGroup.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback } from "react"; import { Link, useHistory } from "react-router-dom"; import classnames from "classnames"; @@ -23,6 +23,8 @@ import TableHead from '@material-ui/core/TableHead'; import TableRow from "@material-ui/core/TableRow"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; +import InputLabel from "@material-ui/core/InputLabel"; + import Select from "@material-ui/core/Select"; @@ -37,9 +39,14 @@ import axios from "axios" import configApiCall from "../../api" import { api_path_get_list_group, + api_path_get_group, api_path_put_update_group, api_path_get_user_directory_search, - api_path_get_user_profile + api_path_get_user_profile, + api_path_blueprints, + api_path_get_group_members, + api_path_post_group_member, + api_path_delete_group_member } from "../../globalUrls" import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; @@ -55,6 +62,8 @@ import i18next from "i18next"; import auth from "auth.js"; +import { debounce } from "lodash"; + const useStyles = makeStyles((theme) => ({ ...devicesStyle, ...dashboardStyle, @@ -95,6 +104,9 @@ const useStyles = makeStyles((theme) => ({ maxHeight: '60vh', minWidth: '80vh', maxWidth: '80vh' + }, + inputBottomMargin: { + marginBottom: "1rem" } })); @@ -102,11 +114,16 @@ export default function EditGroup(props) { const classes = useStyles(); const history = useHistory(); - const [name, setName] = React.useState(props.groupName); - const [newName, setNewName] = React.useState(props.groupName); - const [blueprint, setBlueprint] = React.useState(null); + const [name, setName] = React.useState(""); + const [newName, setNewName] = React.useState(""); + const [blueprints, setBlueprints] = React.useState([]); + const [selectedBlueprint, setSelectedBlueprint] = React.useState({ + value: 0, + label: "No blueprint", + }); const [groupMembers, setGroupMembers] = React.useState([]); const [openDrawer, setOpenDrawer] = React.useState(false); + const [groupNameExits, setGroupNameExits] = React.useState(false); const [users, setUsers] = React.useState([]); const getUserInfo = username => new Promise((resolve, reject) => { @@ -126,89 +143,91 @@ export default function EditGroup(props) { }); }) - const getUsersInformation = userNames => { - userNames.forEach((username)=> { - getUserInfo(username).then((userInfo) => setGroupMembers(groupMembers.push(userInfo))) - }) - } - const getGroup = () => { - axios(configApiCall(api_path_get_list_group+"?groupName="+props.groupName, 'GET', null, null)).then((response) => { - let groups=response.data; - if(groups.length > 1){ - groups.map((group) => { - if(group.name === props.groupName){ - props.getBlueprintsOptions().forEach((blueprintOption) => { - if(blueprintOption.label === group["blueprint"]){ - console.log("Group option value : " + blueprintOption.value); - setBlueprint(blueprintOption.value); - } - }) - - getUserInfo(group["groupMembers"]).then((userInfo) => { - let newGroupMembers = groupMembers; - newGroupMembers.push(userInfo); - setGroupMembers(newGroupMembers); -  }) - } + axios(configApiCall(api_path_get_group + props.groupid, 'GET', null, null)).then((response) => { + let group = response.data; + + axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) + .then((response) => { + setBlueprints(response.data); + let index = 0; + response.data.map((blueprint) => { + if(blueprint.name == group["blueprint"]) + setSelectedBlueprint({ value: index, label: blueprint.name }); + index += 1; + }); + }) + .catch((error) => { + console.log(error); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 500) { + setBlueprints([]); + } + }); + + axios(configApiCall(api_path_get_group_members + props.groupid, 'GET', null, null)).then((response) => { + let members = response.data; + members.forEach((member) => { + getUserInfo(member.username).then((userInfo) => { + let newGroupMembers = groupMembers; + newGroupMembers.push(userInfo); + setGroupMembers(newGroupMembers); + + //This state update is added to force the groupMembers to displayed on first page loading + setOpenDrawer(true); + setOpenDrawer(false); +  }) }) - } - else{ - if(groups.name === props.groupName){ - props.getBlueprintsOptions().forEach((blueprintOption) => { - if(blueprintOption.label === groups["blueprint"]){ - setBlueprint(blueprintOption.value) - } - }) - groups["groupMembers"].forEach((username)=> { - getUserInfo(username).then((userInfo) => { - let newGroupMembers = groupMembers; - newGroupMembers.push(userInfo); - setGroupMembers(newGroupMembers); -  }) - }) - + }).catch((error) => { + if (error.response.status === 404) { + setGroupMembers([]); } - } + else + console.log(error); + }) + + + setName(group.name); + setNewName(group.name); }).catch((error) => { - console.log("Error fetching group members of: " + props.groupName + " " + error) + console.log("Error fetching group members of: " + props.name + " " + error) }) } - const getGroupsOptions = () => { - let blueprintsOptions = [] - let index = 0 - if(props.blueprints.length === 0) - blueprintsOptions.push({value: index, label: "No blueprint found"}) + const getBlueprintsOptions = (inputs) => { + let blueprintsOptions = []; + let index = 0; + if (blueprints.length === 0) + blueprintsOptions.push({ value: index, label: "No blueprint found" }); else { - props.blueprints.map((blueprintElement) => { - blueprintsOptions.push({value: index, label: blueprintElement.name}); - index += 1 - }) + blueprints.map((blueprint) => { + blueprintsOptions.push({ value: index, label: blueprint.name }); + index += 1; + }); } - return blueprintsOptions - } + return blueprintsOptions; + }; - const blueprintsOptionsItems = tool.buildSelectMenuItems(getGroupsOptions()); + const blueprintsOptionsItems = tool.buildSelectMenuItems(getBlueprintsOptions(blueprints)); React.useEffect(()=>{ getGroup(); searchUsers(); }, []) - const handleUpdateGroup = (blueprintValue) => { + const updateGroup = (blueprintValue) => { - let url = ''; - if(blueprintValue == null){ - url = api_path_put_update_group+"?groupName="+props.groupName+"&newName="+name+"&blueprintName=&groupMembers="; - }else{ - url = api_path_put_update_group+"?groupName="+props.groupName+"&newName="+name+"&blueprintName="+props.getBlueprintsOptions()[blueprintValue].label+"&groupMembers="; + let data = { + "name": newName, + "blueprint": blueprintValue ? blueprintValue : selectedBlueprint.label } - axios(configApiCall(url, 'PUT', null, null)).then((response) => { - setNewName(name); - setBlueprint(blueprintValue); + axios(configApiCall(api_path_put_update_group + props.groupid, 'PUT', data, null)).then((response) => { + setName(newName); }).catch((error) => { console.log("Error updating group: " + error) }) @@ -245,29 +264,83 @@ export default function EditGroup(props) { }); }; - const updateUserInGroup = (user) => { - let url = ''; - if(blueprint == null){ - url = api_path_put_update_group+"?groupName="+props.groupName+"&newName="+props.groupName+"&blueprintName=&groupMembers="+[user.username,]; - }else{ - url = api_path_put_update_group+"?groupName="+props.groupName+"&newName="+props.groupName+"&blueprintName="+props.getBlueprintsOptions()[blueprint].label+"&groupMembers="+[user.username,]; + const addUserInGroup = (user) => { + let data = { + "username": user.username } + axios(configApiCall(api_path_post_group_member + props.groupid, 'POST', data, null)).then((response) => { + let newGroupMembers = groupMembers; + newGroupMembers.push(user); + setGroupMembers(newGroupMembers); - axios(configApiCall(url, 'PUT', null, null)).then((response) => { + //This state update is added to force the groupMembers to refreshed displayed + setOpenDrawer(true); + setOpenDrawer(false); + }).catch((error) => { + if (error.response.status === 409) { + alert(`${user.username} is already part of ${name}`); + } + else + console.log("Error updating group: " + error) + }) + } + + const deleteUserFromGroup = (user) => { + let data = { + "username": user.username + } + axios(configApiCall(api_path_delete_group_member + props.groupid, 'DELETE', data, null)).then((response) => { let newGroupMembers = groupMembers; - if(newGroupMembers.includes(user)) newGroupMembers.splice(newGroupMembers.indexOf(user), 1); - else newGroupMembers.push(user); + newGroupMembers.splice(newGroupMembers.indexOf(user), 1); setGroupMembers(newGroupMembers); + + //This state update is added to force the groupMembers to refreshed displayed + setOpenDrawer(true); + setOpenDrawer(false); }).catch((error) => { console.log("Error updating group: " + error) }) } - const handleBlueprintsChange = (blueprintValue) => { - setBlueprint(blueprintValue) - handleUpdateGroup(blueprintValue) + const handleBlueprintsChange = (e) => { + updateGroup(getBlueprintsOptions()[e.target.value].label !== "No blueprint found" ? getBlueprintsOptions()[e.target.value].label : ""); + setSelectedBlueprint(getBlueprintsOptions()[e.target.value]); } + const initCheckGroupNameExists = useCallback( + debounce( + (searchGroupNameValue) => + handleCheckGroupNameExists(searchGroupNameValue), + 500 + ), + [] + ); + + + const handleCheckGroupNameExists = (searchGroupNameValue) => { + + axios( + configApiCall( + api_path_get_list_group + "?groupName=" + searchGroupNameValue, + "GET", + null, + null + ) + ) + .then((response) => { + setGroupNameExits(false); + response.data.forEach((group) => { + if(searchGroupNameValue === group.name){ + setGroupNameExits(true); + } + }); + }) + .catch((error) => { + console.log(error); + setGroupNameExits(false); + }); + }; + const tableCellClasses = classnames(classes.tableCell); return( @@ -279,7 +352,7 @@ export default function EditGroup(props) { placeholder={i18next.t("add_user_to_group", "Add user to group ...")} searchTargets={searchUsers} targets={users} - addElementToTarget={updateUserInGroup} + addElementToTarget={addUserInGroup} targetName={name} type="user" /> @@ -290,50 +363,51 @@ export default function EditGroup(props) { <CardIcon color="info"> <EditIcon /> </CardIcon> - <p className={classes.cardCategory}>{i18next.t("edit_group", "Edit group")}</p> - <h3 className={classes.cardTitle}>{newName}</h3> + <p className={classes.cardCategory}>{i18next.t("edit_group", "Edit group")}</p> + <h3 className={classes.cardTitle}>{name}</h3> </CardHeader> <CardBody profile> <div className={classes.root}> <Grid container spacing={2}> <Grid item xs={12} sm={12} md={12}> - <FormControl className={classes.margin} size="medium" error={props.groupNameExits}> + <FormControl className={classes.margin} size="medium" error={groupNameExits}> <Input id="name" - placeholder={props.groupName} + placeholder={name} startAdornment={ <InputAdornment position="start"> <PeopleOutlineIcon /> </InputAdornment> } endAdornment={ - <IconButton color="primary" aria-label="upload picture" component="span" + <IconButton color="primary" aria-label="update name" component="span" onClick={() => { - handleUpdateGroup(blueprint); + updateGroup(); }} - disabled={props.groupNameExits} + disabled={groupNameExits || name == newName} > <SaveIcon /> </IconButton> } onChange={e => { - setName(e.target.value); - props.initCheckGroupNameExists(e.target.value) + setNewName(e.target.value); + initCheckGroupNameExists(e.target.value) }} /> </FormControl> </Grid> <Grid item xs={12} sm={12} md={12}> + <InputLabel className={classes.inputBottomMargin} htmlFor="blueprint">{i18next.t("select_blueprint", "Select a blueprint")}</InputLabel> <FormControl className={classes.margin} fullWidth> <Select labelId="demo-simple-select-label" fullWidth - value={blueprint} - onChange={(e) => handleBlueprintsChange(e.target.value)} + value={selectedBlueprint.value} + onChange={handleBlueprintsChange} variant="outlined" children={blueprintsOptionsItems} - disabled={props.blueprints.length === 0} - /> + disabled={blueprints.length === 0} + /> </FormControl> </Grid> </Grid> @@ -342,7 +416,7 @@ export default function EditGroup(props) { </Card> </GridItem> <GridItem xs={12} sm={12} md={12}> - <Button color="primary" onClick={() => {setOpenDrawer(true)}}><AddCircleOutlineIcon /> {i18next.t("add_user_to", "Add user to")} {props.groupName}</Button> + <Button color="primary" onClick={() => {setOpenDrawer(true)}}><AddCircleOutlineIcon /> {i18next.t("add_user_to", "Add user to")} {name}</Button> <Table className={classes.table}> <TableHead> <TableRow> @@ -379,7 +453,7 @@ export default function EditGroup(props) { <Link to={`/user/${user.username}`}>{user.lastName}</Link> </TableCell> <TableCell align="right" className={classes.tableActions}> - <Button color="primary" onClick={() => updateUserInGroup(user)}>{i18next.t("remove_user", "Remove user")}</Button> + <Button color="primary" onClick={() => deleteUserFromGroup(user)}>{i18next.t("remove_user", "Remove user")}</Button> </TableCell> </TableRow> )} diff --git a/jams-react-client/src/views/Groups/Groups.js b/jams-react-client/src/views/Groups/Groups.js index a26eb1b3..aba42d2c 100644 --- a/jams-react-client/src/views/Groups/Groups.js +++ b/jams-react-client/src/views/Groups/Groups.js @@ -1,5 +1,5 @@ import React, { useEffect, useState, useCallback } from "react"; -import { useHistory } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; // @material-ui/core components import { makeStyles } from "@material-ui/core/styles"; import InputLabel from "@material-ui/core/InputLabel"; @@ -32,6 +32,7 @@ import { api_path_get_list_group, api_path_delete_group, api_path_blueprints, + api_path_get_group_members } from "globalUrls"; import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline"; @@ -86,6 +87,9 @@ const styles = { }, whiteButtonText: { color: "white", + }, + inputBottomMargin: { + marginBottom: "1rem" } }; @@ -95,9 +99,8 @@ export default function Groups() { const classes = useStyles(); const history = useHistory(); const [groups, setGroups] = React.useState([]); - const [selectedGroupName, setSelectedGroupName] = React.useState(""); const [loading, setLoading] = React.useState(false); - const [zeroGroup, setZeroGroup] = React.useState(true); + const [zeroGroup, setZeroGroup] = React.useState(false); const [progress, setProgress] = React.useState(0); const [searchValue, setSearchValue] = React.useState(null); @@ -107,31 +110,34 @@ export default function Groups() { const [groupName, setGroupName] = React.useState(""); const [groupNameExits, setGroupNameExits] = React.useState(false); - const [removedGroup, setRemovedGroup] = React.useState(); + const [removedGroup, setRemovedGroup] = React.useState({ + "id": 0, + "name": "groupeName" + }); const [openRemoveDialog, setOpenRemoveDialog] = React.useState(); const [disableCreate, setDisableCreate] = React.useState(true); - const handleRemoveGroup = (groupRemovedName) => { - setRemovedGroup(groupRemovedName); + const handleRemoveGroup = (group) => { + setRemovedGroup(group); setOpenRemoveDialog(true); }; const removeGroup = () => { axios( configApiCall( - api_path_delete_group + "?groupName=" + removedGroup, + api_path_delete_group + removedGroup.id, "DELETE", null, null ) ) .then((response) => { - console.log("Successfully deleted " + removedGroup); + console.log("Successfully deleted " + removedGroup.name); setOpenRemoveDialog(false); }) .catch((error) => { - console.log("Could not delete " + removedGroup + " " + error); + console.log("Could not delete " + removedGroup.name + " " + error); setOpenRemoveDialog(false); }); @@ -152,6 +158,24 @@ export default function Groups() { return blueprintsOptions; }; + const getBlueprints = () => { + axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) + .then((response) => { + setBlueprints(response.data); + setSelectedBlueprint(getBlueprintsOptions()[0]); + }) + .catch((error) => { + console.log(error); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 500) { + setBlueprints([]); + } + }); + } + useEffect(() => { setLoading(true); const timer = setInterval(() => { @@ -165,30 +189,26 @@ export default function Groups() { }, 500); axios( - configApiCall(api_path_get_list_group + "?groupName=*", "GET", null, null) + configApiCall(api_path_get_list_group, "GET", null, null) ) .then((response) => { let allGroups = response.data; - if (allGroups.length === 0) setZeroGroup(true); - else { - setZeroGroup(false); - } - setGroups(allGroups); - axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) - .then((response) => { - setBlueprints(response.data); - setSelectedBlueprint(getBlueprintsOptions()[0]); + + allGroups.forEach((group)=> { + axios(configApiCall(api_path_get_group_members + group.id, 'GET', null, null)).then((response) => { + group["groupMembersLength"] = response.data.length; + }).catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 404) { + group["groupMembersLength"] = 0; + } + }); }) - .catch((error) => { - console.log(error); - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/"); - } - if (error.response.status === 500) { - setBlueprints([]); - } - }); + setGroups(allGroups); + getBlueprints(); setLoading(false); }) .catch((error) => { @@ -197,20 +217,16 @@ export default function Groups() { auth.authenticated = false; history.push("/"); } + if (error.response.status === 404){ + getBlueprints(); + setZeroGroup(true); + } }); return () => { clearInterval(timer); }; }, [openCreate, openRemoveDialog, history]); - const [selectedGroup, setSelectedGroup] = useState(false); - - const redirectToGroup = (e, name) => { - e.preventDefault(); - setSelectedGroup(true); - setSelectedGroupName(name); - }; - const handleCheckGroupNameExists = (searchGroupNameValue) => { setDisableCreate(true); axios( @@ -222,8 +238,15 @@ export default function Groups() { ) ) .then((response) => { - setDisableCreate(true); - setGroupNameExits(true); + let allGroups = response.data; + setDisableCreate(false); + setGroupNameExits(false); + allGroups.forEach((group) => { + if(searchGroupNameValue === group.name){ + setDisableCreate(true); + setGroupNameExits(true); + } + }); }) .catch((error) => { console.log(error); @@ -262,15 +285,15 @@ export default function Groups() { null ) ) - .then(() => { + .then((response) => { console.log("Successfully created " + groupName); setOpenCreate(false); + history.push(`/group/${response.data.id}`); }) .catch((error) => { - console.log("Error creating group: " + error); + alert("Error creating group: " + error); setOpenCreate(false); }); - history.push(`/group/${groupName}`); }; const blueprintsOptionsItems = tool.buildSelectMenuItems( @@ -294,22 +317,8 @@ export default function Groups() { </h4> </div> ); - } else if (selectedGroup && auth.hasAdminScope()) { - return ( - <div> - <EditGroup - groupName={selectedGroupName} - initCheckGroupNameExists={initCheckGroupNameExists} - groupNameExits={groupNameExits} - blueprintsOptionsItems={blueprintsOptionsItems} - handleBlueprintsChange={handleBlueprintsChange} - getBlueprintsOptions={getBlueprintsOptions} - blueprints={blueprints} - disableCreate={disableCreate} - /> - </div> - ); - } else { + } + else { return ( <div> <Dialog @@ -351,6 +360,7 @@ export default function Groups() { )} </Grid> <Grid item xs={12} sm={12} md={12}> + <InputLabel className={classes.inputBottomMargin} htmlFor="blueprint">{i18next.t("select_blueprint", "Select a blueprint")}</InputLabel> <Select labelId="demo-simple-select-label" fullWidth @@ -387,7 +397,7 @@ export default function Groups() { <DialogTitle id="alert-dialog-title">{i18next.t("remove_group", "Remove group")}</DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> - {i18next.t("are_you_sure_you_want_to_delete", "Are you sure you want to delete")} <strong>{removedGroup}</strong> ? + {i18next.t("are_you_sure_you_want_to_delete", "Are you sure you want to delete")} <strong>{removedGroup.name}</strong> ? </DialogContentText> </DialogContent> <DialogActions> @@ -428,7 +438,7 @@ export default function Groups() { )} {!zeroGroup && <Search />} <div className={classes.loading}> - {loading && ( + {!zeroGroup && loading && ( <LinearProgress variant="determinate" value={progress} /> )} </div> @@ -438,7 +448,7 @@ export default function Groups() { <div className={classes.groupsNotFound}> <InfoIcon /> <p style={{ marginLeft: "10px" }}>{i18next.t("no_groups_found", "No groups Found")}</p> </div> - ) : groups.length >= 1 ? ( + ) : ( groups .filter((data) => { if (searchValue === null) { @@ -458,10 +468,7 @@ export default function Groups() { xl={2} key={group.name}> <Card profile> - <a - href="#" - onClick={(e) => redirectToGroup(e, group.name)} - > + <Link to={`/group/${group.id}`}> <CardBody profile> <h3 className={classes.cardTitle}>{group.name}</h3> <ul> @@ -471,7 +478,7 @@ export default function Groups() { style={{ marginRight: "10px" }} /> <strong style={{ marginRight: "5px" }}> - {group.groupMembers.length} + {group.groupMembersLength} </strong> {i18next.t("users", "users")} </li> @@ -487,12 +494,12 @@ export default function Groups() { </li> </ul> </CardBody> - </a> + </Link> <CardFooter> <IconButton color="secondary" onClick={() => { - handleRemoveGroup(group.name); + handleRemoveGroup(group); }} > <DeleteOutlineIcon /> @@ -501,51 +508,6 @@ export default function Groups() { </Card> </GridItem> )) - ) : ( - <GridItem xs={12} sm={12} md={2} key={groups.name}> - <Card profile> - - <a href="#" onClick={(e) => redirectToGroup(e, groups.name)}> - <CardBody profile> - <h3 className={classes.cardTitle}>{groups.name}</h3> - <ul> - <li> - <PersonIcon - fontSize="small" - style={{ marginRight: "10px" }} - /> - <strong style={{ marginRight: "5px" }}> - {typeof groups.groupMembers !== "undefined" - ? groups.groupMembers - : 0} - </strong> - {i18next.t("users", "users")} - </li> - <li> - <MailOutlineIcon - fontSize="small" - style={{ marginRight: "10px" }} - /> - <strong style={{ marginRight: "5px" }}> - {i18next.t("blueprint", "Blueprint")} - </strong> - {selectedBlueprint.label} - </li> - </ul> - </CardBody> - </a> - <CardFooter> - <IconButton - color="secondary" - onClick={() => { - handleRemoveGroup(groups.name); - }} - > - <DeleteOutlineIcon /> - </IconButton> - </CardFooter> - </Card> - </GridItem> )} </GridContainer> </div> diff --git a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js index d115c82c..d5bcfa31 100644 --- a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js +++ b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js @@ -1,5 +1,5 @@ import React, { useEffect } from "react"; -import { useHistory } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; import classnames from "classnames"; // @material-ui/core components @@ -58,7 +58,10 @@ import { api_path_get_user_profile, api_path_delete_admin_user_revoke, api_path_get_list_group, - api_path_put_update_group, + api_path_get_group, + api_path_post_group_member, + api_path_get_admin_user_groups, + api_path_delete_group_member } from "globalUrls"; import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; @@ -249,50 +252,49 @@ export default function DisplayUserProfile(props) { }); } - const updateUserInGroup = (group) => { + const removeUserFromGroup = (group) => { + + let data = { + "username": props.username + } + axios( configApiCall( - api_path_get_list_group + "?groupName=" + group, - "GET", - null, + api_path_delete_group_member + group.groupId, + "DELETE", + data, null ) ).then((response)=>{ - - let url = ""; - let oldGroup = response.data.name; - if (response.data.blueprint == null) { - url = - api_path_put_update_group + - "?groupName=" + - response.data.name + - "&newName=" + - response.data.name + - "&blueprintName=&groupMembers=" + - [props.username]; - } else { - url = - api_path_put_update_group + - "?groupName=" + - response.data.name + - "&newName=" + - response.data.name + - "&blueprintName=" + - response.data.blueprint + - "&groupMembers=" + - [props.username]; - } - - axios(configApiCall(url, "PUT", null, null)) - .then(() => { - let newGroupMemberships = groupMemberships; - if(newGroupMemberships.includes(oldGroup)) newGroupMemberships.splice(newGroupMemberships.indexOf(oldGroup), 1); - else newGroupMemberships.push(oldGroup); - setGroupMemberships(newGroupMemberships); - }) - .catch((error) => { - console.log("Error updating group: " + error); - }); + let newGroupMemberships = groupMemberships; + newGroupMemberships.splice(newGroupMemberships.indexOf(group), 1); + setGroupMemberships(newGroupMemberships); + }).catch((error)=>{console.log(error)}) + + }; + + const addUserToGroup = (group) => { + + let data = { + "username": props.username + } + + axios( + configApiCall( + api_path_post_group_member + group.id, + "POST", + data, + null + ) + ).then((response)=>{ + let newGroupMemberships = groupMemberships; + newGroupMemberships.push( + { + "groupId": group.id, + "name": group.name + } + ); + setGroupMemberships(newGroupMemberships); }).catch((error)=>{console.log(error)}) }; @@ -329,10 +331,28 @@ export default function DisplayUserProfile(props) { ) .then((response) => { setUser(response.data); - if(response.data.groupMemberships.length === 1 && response.data.groupMemberships[0] === "") { - setGroupMemberships([]); - } - else setGroupMemberships(response.data.groupMemberships) + axios(configApiCall(api_path_get_admin_user_groups + props.username, + "GET", + null, + null + )).then((userGroups) => { + let userGroupsData = userGroups.data; + userGroupsData.forEach((group) => { + axios(configApiCall(api_path_get_group + group.groupId, 'GET', null, null)).then((groupInfo) =>{ + group["name"] = groupInfo.data.name; + }); + }); + setGroupMemberships(userGroupsData); + }).catch((error) => { + console.log(error); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 404) { + setGroupMemberships([]); + } + }) searchGroups("*") setLoading(false); }) @@ -367,10 +387,28 @@ export default function DisplayUserProfile(props) { ) .then((response) => { setUser(response.data); - if(response.data.groupMemberships.length === 1 && response.data.groupMemberships[0] === "") { - setGroupMemberships([]); - } - else setGroupMemberships(response.data.groupMemberships) + axios(configApiCall(api_path_get_admin_user_groups + props.username, + "GET", + null, + null + )).then((userGroups) => { + let userGroupsData = userGroups.data; + userGroupsData.forEach((group) => { + axios(configApiCall(api_path_get_group + group.groupId, 'GET', null, null)).then((groupInfo) =>{ + group["name"] = groupInfo.data.name; + }); + }); + setGroupMemberships(userGroupsData); + }).catch((error) => { + console.log(error); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 404) { + setGroupMemberships([]); + } + }) setLoading(false); }) .catch((error) => { @@ -497,7 +535,7 @@ export default function DisplayUserProfile(props) { placeholder={i18next.t("add_user_to_group", "Add user to group ...")} searchTargets={searchGroups} targets={groups} - addElementToTarget={updateUserInGroup} + addElementToTarget={addUserToGroup} targetName={props.username} type="group" /> @@ -668,13 +706,15 @@ export default function DisplayUserProfile(props) { </TableRow> </TableHead> <TableBody> - {groupMemberships !== [""] && groupMemberships.map(group => + {groupMemberships !== [] && groupMemberships.map(group => <TableRow key={group} className={classes.tableRow}> <TableCell className={tableCellClasses}> - {group} + <Link to={`/group/${group.groupId}`}> + {group.name} + </Link> </TableCell> <TableCell align="right" className={classes.tableActions}> - <Button color="primary" onClick={() => updateUserInGroup(group)}>{i18next.t("remove_from_group", "Remove from group")}</Button> + <Button color="primary" onClick={() => removeUserFromGroup(group)}>{i18next.t("remove_from_group", "Remove from group")}</Button> </TableCell> </TableRow> ) } diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/AddUserToGroupFlow.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/AddUserToGroupFlow.java deleted file mode 100644 index 00f57cbf..00000000 --- a/jams-server/src/main/java/net/jami/jams/server/core/workflows/AddUserToGroupFlow.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.jami.jams.server.core.workflows; - -import lombok.extern.slf4j.Slf4j; -import net.jami.jams.common.dao.StatementElement; -import net.jami.jams.common.dao.StatementList; -import net.jami.jams.common.objects.user.UserGroupMapping; -import net.jami.jams.common.objects.user.UserProfile; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static net.jami.jams.server.Server.dataStore; -import static net.jami.jams.server.Server.userAuthenticationModule; - -@Slf4j -public class AddUserToGroupFlow { - - public static void addUserToGroup(String groupName, String username) { - userAuthenticationModule.getAuthSources().forEach((k, v) -> { - UserProfile profile = v.getUserProfile(username); - List<UserProfile> groupProfiles = v.searchUserProfiles(username, "LOGON_NAME", Optional.empty()); - if (!groupProfiles.isEmpty()) { - UserGroupMapping mapping = null; - StatementList statementList = new StatementList(); - statementList.addStatement(new StatementElement("username", "=", username, "")); - if (dataStore.getUserGroupMappingsDao().getObjects(statementList).isEmpty()) { - // if the mapping doesn't exist, create it and add the group directly. - - try { - mapping = new UserGroupMapping(); - } catch (Exception e) { - e.printStackTrace(); - } - mapping.setUsername(username); - mapping.setGroups(""); - mapping.addGroup(groupName); - dataStore.getUserGroupMappingsDao().storeObject(mapping); - - } else { - // otherwise, update the object. - - mapping = dataStore.getUserGroupMappingsDao().getObjects(statementList).get(0); - if (!mapping.getGroups().contains(groupName)) { - mapping.addGroup(groupName); - String newGroups = mapping.getGroups(); - - StatementList update = new StatementList(); - StatementElement st0 = new StatementElement("groups", "=", newGroups, ""); - update.addStatement(st0); - StatementList constraint = new StatementList(); - StatementElement st1 = new StatementElement("username", "=", username, ""); - constraint.addStatement(st1); - dataStore.getUserGroupMappingsDao().updateObject(update, constraint); - } - } - - if (profile != null) { - if (profile.getGroupMemberships() == null) - profile.setGroupMemberships(new ArrayList<>()); - - if (!profile.getGroupMemberships().contains(groupName)) - profile.getGroupMemberships().add(groupName); - - dataStore.updateUserProfile(profile); - } - } - }); - } -} diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java index 81f22b94..8bb441d8 100644 --- a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java +++ b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java @@ -32,6 +32,8 @@ import net.jami.jams.common.objects.requests.DeviceRegistrationRequest; import net.jami.jams.common.objects.responses.DeviceRegistrationResponse; import net.jami.jams.common.objects.user.*; import net.jami.jams.dht.DeviceReceiptGenerator; +import net.jami.jams.common.objects.user.Group; + import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -70,57 +72,40 @@ public class RegisterDeviceFlow { } dataStore.getDeviceDao().storeObject(device); + Group group = new Group(); + statementList = new StatementList(); statementList.addStatement(new StatementElement("username", "=", username, "")); if (dataStore.getUserGroupMappingsDao().getObjects(statementList) != null && !dataStore.getUserGroupMappingsDao().getObjects(statementList).isEmpty()) { UserGroupMapping mapping = dataStore.getUserGroupMappingsDao().getObjects(statementList).get(0); - List<String> list = new ArrayList<>(); - if (mapping.getUsername().equals(userProfile.getUsername())) { - String[] splits = mapping.getGroups().split(","); - - for (int i = 0; i < splits.length; i++) - list.add(splits[i]); - } - if (!list.isEmpty()) - userProfile.setGroupMemberships(list); + statementList = new StatementList(); + statementList.addStatement(new StatementElement("id", "=", mapping.getGroupId(), "")); + group = dataStore.getGroupDao().getObjects(statementList).get(0); } - // Now we build this response out. DeviceRegistrationResponse response = new DeviceRegistrationResponse(); - if (userProfile.getGroupMemberships() != null) { - userProfile.getGroupMemberships().forEach(e -> { - if (!e.equals("")) { - StatementElement st = new StatementElement("name", "=", e, ""); - StatementList statementList1 = new StatementList(); - statementList1.addStatement(st); - - Group group = dataStore.getGroupDao().getObjects(statementList1).get(0); - String policyName = group.getBlueprint(); - if (group != null && policyName != null) { - StatementElement st2 = new StatementElement("name", "=", policyName, ""); - StatementList statementList2 = new StatementList(); - statementList2.addStatement((st2)); - try { - Policy policy = dataStore.getPolicyDao().getObjects(statementList2).get(0); - response.setPolicyData(policy.getPolicyData()); - } catch (Exception e1) { - log.warn("No policy available for user - not adding a policy component to response"); - } - } - } - }); + 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); + response.setPolicyData(policy.getPolicyData()); + } catch (Exception e1) { + log.warn("No policy available for user - not adding a policy component to response"); + } } - // We need to set the device receipt.... + // Device receipt String[] devReceipt = DeviceReceiptGenerator.generateReceipt(user.getPrivateKey(), user.getCertificate().getPublicKey(), device.getCertificate().getPublicKey(), user.getEthAddress()); response.setDeviceReceipt(devReceipt[0]); response.setReceiptSignature(devReceipt[1]); response.setDisplayName(userProfile.getFirstName() + " " + userProfile.getLastName()); - // We need to set + response.setNameServer(nameServer.getURI()); if (userProfile.getProfilePicture() != null) response.setUserPhoto(userProfile.getProfilePicture()); - // Finally we set the certificate chain. + // Chain certificate response.setCertificateChain(new X509Certificate[] { certificateAuthority.getCA(), user.getCertificate(), device.getCertificate() }); return response; diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java index 472680da..33c6804f 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java @@ -78,7 +78,6 @@ public class DirectoryEntryServlet extends HttpServlet { userProfile.setFaxNumber(obj.get("faxNumber").toString()); userProfile.setMobileNumber(obj.get("mobileNumber").toString()); userProfile.setId(obj.get("jamiId").toString()); - userProfile.setGroupMemberships(new ArrayList<>()); userAuthenticationModule.getAuthSources().get(new AuthModuleKey(realm, AuthenticationSourceType.LOCAL)) .setUserProfile(userProfile); @@ -112,7 +111,7 @@ public class DirectoryEntryServlet extends HttpServlet { if (callingUser.getAccessLevel() == AccessLevel.ADMIN || (callingUser.getAccessLevel() == AccessLevel.USER && callingUser.getUsername().equals(targetUser.getUsername()))) { select = new StatementList(); select.addStatement(new StatementElement("username", "=", userProfile.getUsername(), "")); - if (dataStore.updateUserProfile(userProfile) && dataStore.updateUserGroupMappings(userProfile)) + if (dataStore.updateUserProfile(userProfile)) resp.setStatus(200); else resp.sendError(500, "Could not update the users's profile information"); diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/AddGroupServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/AddGroupServlet.java new file mode 100644 index 00000000..c29f498a --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/AddGroupServlet.java @@ -0,0 +1,42 @@ +package net.jami.jams.server.servlets.api.admin.group; + +import com.google.gson.JsonObject; +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.annotations.ScopedServletMethod; +import net.jami.jams.common.objects.user.AccessLevel; +import net.jami.jams.common.objects.user.Group; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.UUID; + +import static net.jami.jams.server.Server.dataStore; + +@WebServlet("/api/admin/group") +@Slf4j +public class AddGroupServlet extends HttpServlet { + + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + Group group = new Group(); + UUID uuid = UUID.randomUUID(); + group.setId(uuid.toString()); + group.setName(req.getParameter("name")); + group.setBlueprint(req.getParameter("blueprintName")); + if (dataStore.getGroupDao().storeObject(group)) { + JsonObject data = new JsonObject(); + data.addProperty("id", uuid.toString()); + resp.getOutputStream().write(data.toString().getBytes()); + resp.setStatus(200); + } + else + resp.sendError(500, "Could not create a group successfully!"); + } +} \ No newline at end of file diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupProfileServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupProfileServlet.java deleted file mode 100644 index b78615b4..00000000 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupProfileServlet.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.jami.jams.server.servlets.api.admin.group; - -import com.jsoniter.output.JsonStream; -import jakarta.servlet.ServletException; -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.annotations.ScopedServletMethod; -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.Group; -import net.jami.jams.common.objects.user.UserProfile; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static net.jami.jams.server.Server.dataStore; - -@WebServlet("/api/admin/group/*") -@Slf4j -public class GroupProfileServlet extends HttpServlet { - - - @Override - @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) - @JsonContent - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - List<Group> groups = new ArrayList<>(); - Group singleGroup = null; - String groupName = req.getPathInfo().replace("/",""); - - if (!groupName.equals("*")) { - StatementList statementList = new StatementList(); - StatementElement st = new StatementElement("name", "=", groupName, ""); - - statementList.addStatement(st); - if (!dataStore.getGroupDao().getObjects(statementList).isEmpty()) - singleGroup = dataStore.getGroupDao().getObjects(statementList).get(0); - } else { - groups = dataStore.getGroupDao().getObjects(null); - } - - if (singleGroup != null) { - Group finalSingleGroup = singleGroup; - List<UserProfile> profiles = dataStore.getUserProfileDao().getObjects(null).stream().filter(profile -> - profile.getGroupMemberships().contains(finalSingleGroup.getName())).collect(Collectors.toList()); - - profiles.forEach(profile -> - finalSingleGroup.getGroupMembers().add(profile.getUsername())); - - resp.getOutputStream().write(JsonStream.serialize(finalSingleGroup).getBytes()); - resp.setStatus(200); - } - if (!groups.isEmpty()) { - List<UserProfile> profiles = dataStore.getUserProfileDao().getObjects(null); - for (Group group: groups) { - for (UserProfile p: profiles) { - if (p.getGroupMemberships().contains(group.getName())) - group.getGroupMembers().add(p.getUsername()); - } - } - - resp.getOutputStream().write(JsonStream.serialize(groups).getBytes()); - resp.setStatus(200); - } - else { - log.info("No existing groups were found."); - resp.setStatus(200); - } - } -} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java index 77d0d0e4..88cf7bc1 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java @@ -13,66 +13,41 @@ 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.Group; -import net.jami.jams.common.objects.user.UserGroupMapping; import net.jami.jams.common.objects.user.UserProfile; -import net.jami.jams.server.core.workflows.AddUserToGroupFlow; +import org.json.JSONObject; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import static net.jami.jams.server.Server.dataStore; -import static net.jami.jams.server.Server.userAuthenticationModule; -@WebServlet("/api/admin/group") +@WebServlet("/api/admin/group/*") @Slf4j public class GroupServlet extends HttpServlet { + @Override @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) @JsonContent protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - List<Group> groups = new ArrayList<>(); Group singleGroup = null; + String id = req.getPathInfo().replace("/",""); - if (!req.getParameter("groupName").equals("*")) { - StatementList statementList = new StatementList(); - StatementElement st = new StatementElement("name", "=", req.getParameter("groupName"), ""); + StatementList statementList = new StatementList(); + StatementElement st = new StatementElement("id", "=", id, ""); - statementList.addStatement(st); + statementList.addStatement(st); + if (!dataStore.getGroupDao().getObjects(statementList).isEmpty()) singleGroup = dataStore.getGroupDao().getObjects(statementList).get(0); - } else { - groups = dataStore.getGroupDao().getObjects(null); - } if (singleGroup != null) { - Group finalSingleGroup = singleGroup; - List<UserProfile> profiles = dataStore.getUserProfileDao().getObjects(null).stream().filter(profile -> - profile.getGroupMemberships().contains(finalSingleGroup.getName())).collect(Collectors.toList()); - - profiles.forEach(profile -> - finalSingleGroup.getGroupMembers().add(profile.getUsername())); - - resp.getOutputStream().write(JsonStream.serialize(finalSingleGroup).getBytes()); - resp.setStatus(200); - } - if (!groups.isEmpty()) { - List<UserProfile> profiles = dataStore.getUserProfileDao().getObjects(null); - for (Group group: groups) { - for (UserProfile p: profiles) { - if (p.getGroupMemberships().contains(group.getName())) - group.getGroupMembers().add(p.getUsername()); - } - } - - resp.getOutputStream().write(JsonStream.serialize(groups).getBytes()); + resp.getOutputStream().write(JsonStream.serialize(singleGroup).getBytes()); resp.setStatus(200); } else { - log.info("No existing groups were found."); - resp.setStatus(200); + log.info("No group with this id was found!" ); + resp.setStatus(404); } } @@ -80,125 +55,54 @@ public class GroupServlet extends HttpServlet { @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) @JsonContent protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String name = req.getParameter("groupName"); - String newName = req.getParameter("newName"); - String blueprint = req.getParameter("blueprintName"); - StatementList statementList = new StatementList(); - StatementElement st = new StatementElement("name", "=", name, ""); - statementList.addStatement(st); - Group targetGroup = dataStore.getGroupDao().getObjects(statementList).get(0); - List<UserProfile> profiles = dataStore.getUserProfileDao().getObjects(null).stream().filter(profile -> - profile.getGroupMemberships().contains(targetGroup.getName())).collect(Collectors.toList()); - - profiles.forEach(profile -> - targetGroup.getGroupMembers().add(profile.getUsername())); - - String groupMembers = req.getParameter("groupMembers"); - - // if the username sent isn't already part of the group members, then we add it - if (!targetGroup.getGroupMembers().contains(groupMembers)) { - AddUserToGroupFlow.addUserToGroup(name, req.getParameter("groupMembers")); - } else { - // otherwise remove the group from the user's memberships. - statementList = new StatementList(); - st = new StatementElement("username", "=", groupMembers, ""); - statementList.addStatement(st); - - UserProfile targetProfile = dataStore.getUserProfileDao().getObjects(statementList).get(0); - UserGroupMapping mapping = dataStore.getUserGroupMappingsDao().getObjects(statementList).get(0); - mapping.removeGroup(name); - - StatementList update = new StatementList(); - StatementElement st0 = new StatementElement("groups", "=", mapping.getGroups(), ""); - update.addStatement(st0); - StatementList constraint = new StatementList(); - StatementElement st1 = new StatementElement("username", "=", mapping.getUsername(), ""); - constraint.addStatement(st1); - - // update user mappings - dataStore.getUserGroupMappingsDao().updateObject(update, constraint); - - List<String> groups = targetProfile.getGroupMemberships(); - groups.remove(name); - // TODO: LDAP/AD handling - dataStore.updateUserProfile(targetProfile); - } + String id = req.getPathInfo().replace("/",""); - StatementList update = new StatementList(); - StatementElement st0; + final JSONObject obj = new JSONObject(req.getReader().lines().collect(Collectors.joining(System.lineSeparator()))); - if (newName != null) - st0 = new StatementElement("name", "=", newName, ""); - else - st0 = new StatementElement("name", "=", name, ""); + String name = obj.getString("name"); + String blueprint = obj.getString("blueprint"); - StatementElement st1 = new StatementElement("blueprint", "=", blueprint, ""); + StatementList update = new StatementList(); + + StatementElement st0 = new StatementElement("id", "=", id, ""); update.addStatement(st0); + + StatementElement st1 = new StatementElement("name", "=", name, ""); update.addStatement(st1); + + StatementElement st2 = new StatementElement("blueprint", "=", blueprint, ""); + update.addStatement(st2); + StatementList constraint = new StatementList(); - StatementElement st2 = new StatementElement("name", "=", name, ""); - constraint.addStatement(st2); if (dataStore.getGroupDao().updateObject(update, constraint)) resp.setStatus(200); - else resp.sendError(500, "could not update the group's name!"); - } - - @Override - @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) - @JsonContent - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - Group group = new Group(); - group.setName(req.getParameter("name")); - group.setBlueprint(req.getParameter("blueprintName")); - group.setGroupMembers(new ArrayList<String>()); - if (dataStore.getGroupDao().storeObject(group)) - resp.setStatus(200); - else - resp.sendError(500, "Could not create a group successfully!"); + else resp.sendError(500, "Could not update group!"); } @Override @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) @JsonContent protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String id = req.getPathInfo().replace("/",""); + + StatementElement statementElement = new StatementElement("id", "=", id, ""); - StatementElement statementElement = new StatementElement("name", "=", req.getParameter("groupName"), ""); StatementList constraint = new StatementList(); constraint.addStatement(statementElement); if (dataStore.getGroupDao().deleteObject(constraint)) { - // if deletion was successful, cascade the deletion onto the users - List<UserProfile> validProfiles = dataStore.getUserProfileDao().getObjects(null).stream().filter(profile -> - profile.getGroupMemberships().remove(req.getParameter("groupName"))).collect(Collectors.toList()); - - validProfiles.parallelStream().forEach(profile -> { - - StatementList statementList = new StatementList(); - StatementElement st = new StatementElement("username", "=", profile.getUsername(), ""); - statementList.addStatement(st); - - UserGroupMapping mapping = dataStore.getUserGroupMappingsDao().getObjects(statementList).get(0); - mapping.removeGroup(req.getParameter("groupName")); - - StatementList update = new StatementList(); - StatementElement st0 = new StatementElement("groups", "=", mapping.getGroups(), ""); - update.addStatement(st0); - StatementList constraint2 = new StatementList(); - StatementElement st1 = new StatementElement("username", "=", mapping.getUsername(), ""); - constraint2.addStatement(st1); - - // update user mappings - dataStore.getUserGroupMappingsDao().updateObject(update, constraint2); - - // then update the profile itself - dataStore.updateUserProfile(profile); - }); - - - resp.setStatus(200); + StatementElement statementElement1 = new StatementElement("username", "=", "*", ""); + StatementElement statementElement2 = new StatementElement("groupId", "=", id, ""); + StatementList constraintMapping = new StatementList(); + constraintMapping.addStatement(statementElement1); + constraintMapping.addStatement(statementElement2); + if (dataStore.getUserGroupMappingsDao().deleteObject(constraintMapping)) + resp.setStatus(200); + else + resp.sendError(500, "Could not delete the group mappings successfully!"); } else { resp.sendError(500, "Could not delete the group successfully!"); } } -} \ No newline at end of file +} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java new file mode 100644 index 00000000..6fe101f2 --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java @@ -0,0 +1,46 @@ +package net.jami.jams.server.servlets.api.admin.group; + +import com.google.gson.JsonObject; +import com.jsoniter.output.JsonStream; +import jakarta.servlet.ServletException; +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.annotations.ScopedServletMethod; +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.Group; +import net.jami.jams.common.objects.user.UserProfile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static net.jami.jams.server.Server.dataStore; + +@WebServlet("/api/admin/groups") +@Slf4j +public class GroupsServlet extends HttpServlet { + + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + List<Group> groups = dataStore.getGroupDao().getObjects(null); + + if (!groups.isEmpty()) { + resp.getOutputStream().write(JsonStream.serialize(groups).getBytes()); + resp.setStatus(200); + } + else { + resp.setStatus(404); + } + } +} \ No newline at end of file diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java new file mode 100644 index 00000000..82666f4d --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java @@ -0,0 +1,123 @@ +package net.jami.jams.server.servlets.api.admin.group; + +import com.google.gson.JsonObject; +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.annotations.ScopedServletMethod; +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.UserGroupMapping; +import org.json.JSONObject; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static net.jami.jams.server.Server.dataStore; + +@WebServlet("/api/admin/group/members/*") +@Slf4j +public class UserGroupServlet extends HttpServlet { + /** + * @apiVersion 1.0.0 + * @api {get} /api/admin/group/[groupId]/members/ Get JAMS groups members + * @apiName getGroupMembers + * @apiGroup Group + * + * @apiSuccess (200) {body} Array of usernames + * @apiSuccessExample {json} Success-Response: + * { + * "usernames": ["user1", "user2", "user3"] + * } + * @apiError (404) {null} null could not find members for this groups + */ + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String groupId = req.getPathInfo().replace("/",""); + + StatementList statementList = new StatementList(); + StatementElement st = new StatementElement("groupId", "=", groupId, ""); + + statementList.addStatement(st); + + List<UserGroupMapping> result = dataStore.getUserGroupMappingsDao().getObjects(statementList); + + if (result.isEmpty()) + resp.sendError(404, "No users found for this group!"); + else { + resp.getOutputStream().write(JsonStream.serialize(result).getBytes()); + resp.setStatus(200); + } + } + + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String groupId = req.getPathInfo().replace("/",""); + + final JSONObject obj = new JSONObject(req.getReader().lines().collect(Collectors.joining(System.lineSeparator()))); + + String username = obj.getString("username"); + + StatementList statementList = new StatementList(); + statementList.addStatement(new StatementElement("groupId", "=", groupId, "AND")); + statementList.addStatement(new StatementElement("username", "=", username, "")); + + if (!dataStore.getUserGroupMappingsDao().getObjects(statementList).isEmpty()) { + resp.sendError( 409, "The user already part of the group!"); + return; + } + + UserGroupMapping mapping = new UserGroupMapping(); + + mapping.setGroupId(groupId); + mapping.setUsername(username); + + if (dataStore.getUserGroupMappingsDao().storeObject(mapping)) { + resp.setStatus(200); + } + else + resp.sendError(500, "Could not add user to group!"); + + } + + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String groupId = req.getPathInfo().replace("/",""); + + final JSONObject obj = new JSONObject(req.getReader().lines().collect(Collectors.joining(System.lineSeparator()))); + + String username = obj.getString("username"); + + + StatementElement statementElement1 = new StatementElement("username", "=", username, "AND"); + StatementElement statementElement2 = new StatementElement("groupId", "=", groupId, ""); + + StatementList constraint = new StatementList(); + constraint.addStatement(statementElement1); + constraint.addStatement(statementElement2); + if (dataStore.getUserGroupMappingsDao().deleteObject(constraint)) { + resp.setStatus(200); + } + else { + resp.sendError(500, "Could not delete mapping between user and group!"); + } + } +} \ No newline at end of file diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java new file mode 100644 index 00000000..696eb145 --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java @@ -0,0 +1,59 @@ +package net.jami.jams.server.servlets.api.admin.users; + +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.annotations.ScopedServletMethod; +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.UserGroupMapping; + +import java.io.IOException; +import java.util.List; + +import static net.jami.jams.server.Server.dataStore; + +@WebServlet("/api/admin/user/groups/*") +@Slf4j +public class UserGroupsServlet extends HttpServlet { + + /** + * @apiVersion 1.0.0 + * @api {get} /api/admin/user/[username]/groups/ Get JAMS user groups + * @apiName getUserGroups + * @apiGroup User + * + * @apiSuccess (200) {body} User json user object representation + * @apiSuccessExample {json} Success-Response: + * { + * "groups": ["a5085350-3348-11eb-adc1-0242ac120002", "abde9b76-3348-11eb-adc1-0242ac120002"] + * } + * @apiError (404) {null} null could not find groups for this user + */ + @Override + @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) + @JsonContent + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String username = req.getPathInfo().replace("/",""); + + StatementList statementList = new StatementList(); + StatementElement st = new StatementElement("username", "=", username, ""); + + statementList.addStatement(st); + + List<UserGroupMapping> result = dataStore.getUserGroupMappingsDao().getObjects(statementList); + + if (result.isEmpty()) + resp.sendError(404, "No groups found for this user!"); + else { + resp.getOutputStream().write(JsonStream.serialize(result).getBytes()); + resp.setStatus(200); + } + } +} \ No newline at end of file diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserProfileServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserProfileServlet.java index 7705069e..fc28c2bf 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserProfileServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserProfileServlet.java @@ -51,7 +51,6 @@ public class UserProfileServlet extends HttpServlet { if (v.getUserProfile(username) != null) profile[0] = v.getUserProfile(username); }); - dataStore.updateUserGroupMappings(profile[0]); if (profile[0] != null) { resp.getOutputStream().write(JsonStream.serialize(profile[0]).getBytes()); -- GitLab