From cebef4f2ddced32a298ddc5c33176708d19e407f Mon Sep 17 00:00:00 2001 From: Abba Soungui YOUNOUSS Date: Sat, 8 Nov 2025 17:02:27 +0100 Subject: [PATCH] Add target group synchronization (without member connections yet). --- .../ext/wallix/sync/TargetGroup.java | 46 ++++++++++++ .../guacamole/ext/wallix/sync/Wallix.java | 31 +++++++- .../wallix/sync/WallixConfigSynchronizer.java | 44 ++++++++++-- .../guacamole/ext/wallix/sync/db/DB.java | 70 ++++++++++++++++++- 4 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 src/main/java/cm/soungui/guacamole/ext/wallix/sync/TargetGroup.java diff --git a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/TargetGroup.java b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/TargetGroup.java new file mode 100644 index 0000000..11166d2 --- /dev/null +++ b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/TargetGroup.java @@ -0,0 +1,46 @@ +package cm.soungui.guacamole.ext.wallix.sync; + +import cm.soungui.guacamole.ext.wallix.sync.db.Entity; + +public class TargetGroup { + + private int id; + + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return getName() == null ? super.hashCode() : getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(super.equals(obj)) { + return true; + } + if (obj instanceof TargetGroup) { + TargetGroup otherObject = (TargetGroup) obj; + + boolean namesAreTheSame = otherObject.getName() != null && getName() != null && getName().equals(otherObject.getName()); + return namesAreTheSame; + } + return false; + } + +} diff --git a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java index c41fdc8..8c4b5db 100644 --- a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java +++ b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java @@ -125,7 +125,7 @@ public class Wallix { return output; } - public Set getGroups() throws Exception { + public Set getUserGroups() throws Exception { String output = get("/usergroups"); ObjectMapper objectMapper = new ObjectMapper(); @@ -188,6 +188,35 @@ public class Wallix { } } + public Set getTargetGroups() throws Exception { + String output = get("/targetgroups?fields=group_name,session"); + + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(output); + Set list = new HashSet<>(); + + jsonNode.elements().forEachRemaining((e) -> { + ObjectNode node = (ObjectNode) e; + + TargetGroup group = new TargetGroup(); + group.setName(node.findValue(Wallix.API.ATTRIBUTE_GROUP_NAME).asText()); + +// List membersList = node.findValues(Wallix.API.ATTRIBUTE_GROUP_USERS); +// if (! membersList.isEmpty()) { +// JsonNode usernames = membersList.get(0); +// usernames.forEach(userNode -> { +// User user = new User(); +// user.setName(getNameWithoutDomain(userNode.textValue())); +// group.getMembers().add(user); +// }); +// } + + list.add(group); + }); + + return list; + } + public final class API { public static final String ATTRIBUTE_USER_DISABLED = "is_disabled"; diff --git a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/WallixConfigSynchronizer.java b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/WallixConfigSynchronizer.java index 9e711f8..0c41a1c 100644 --- a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/WallixConfigSynchronizer.java +++ b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/WallixConfigSynchronizer.java @@ -28,7 +28,8 @@ public class WallixConfigSynchronizer implements Runnable { try { System.out.println("Fetching config"); synchronizeUsers(); - synchronizeGroups(); + synchronizeUserGroups(); + synchronizeTargetGroups(); Thread.sleep(sleepDuration); } catch (Exception ex) { ex.printStackTrace(); @@ -75,10 +76,10 @@ public class WallixConfigSynchronizer implements Runnable { return dbUser.isDisabled() != wallixUser.isDisabled(); } - private void synchronizeGroups() throws Exception { + private void synchronizeUserGroups() throws Exception { System.out.println("Synchronizing groups"); System.out.println("Getting Wallix groups"); - Set wallixGroups = Wallix.getInstance().getGroups(); + Set wallixGroups = Wallix.getInstance().getUserGroups(); DB db = DB.getInstance(); Set dbGroups = db.getUserGroups(); @@ -104,12 +105,45 @@ public class WallixConfigSynchronizer implements Runnable { } } } else { - System.out.println("Deleting group : " + group.getName()); - db.deleteGroup(group); + System.out.println("Deleting user group : " + group.getName()); + db.deleteUserGroup(group); } } } + private void synchronizeTargetGroups() throws Exception { + System.out.println("Synchronizing target groups"); + System.out.println("Getting Wallix target groups"); + + DB db = DB.getInstance(); + Set dbGroups = db.getTargetGroups(); + + Set wallixGroups = Wallix.getInstance().getTargetGroups(); + + for (TargetGroup group : wallixGroups) { + if (! dbGroups.contains(group)) { + System.out.println("Adding target group " + group.getName()); + db.addTargetGroup(group); + } + } + + Set newDbGroups = db.getTargetGroups(); + + for (TargetGroup group : newDbGroups) { + if (wallixGroups.contains(group)) { + for (TargetGroup wallixGroup : wallixGroups) { + if (group.equals(wallixGroup)) { +// db.updateGroupMembers(group, wallixGroup.getMembers()); + } + } + } else { + System.out.println("Deleting target group : " + group.getName()); + db.deleteTargetGroup(group); + } + } + + } + private void printWallixVersion() throws Exception { Wallix wallix = Wallix.getInstance(); System.out.println(wallix.getVersion()); diff --git a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/DB.java b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/DB.java index 8ed33e7..e64f3a1 100644 --- a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/DB.java +++ b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/DB.java @@ -14,6 +14,7 @@ import org.apache.guacamole.environment.Environment; import org.apache.guacamole.environment.LocalEnvironment; import cm.soungui.guacamole.ext.wallix.sync.Configuration; +import cm.soungui.guacamole.ext.wallix.sync.TargetGroup; import cm.soungui.guacamole.ext.wallix.sync.db.Entity.EntityType; public class DB { @@ -127,7 +128,7 @@ public class DB { return users; } - public void deleteGroup(UserGroup group) throws SQLException, GuacamoleException { + public void deleteUserGroup(UserGroup group) throws SQLException, GuacamoleException { if (group == null || group.getName() == null) { return; } @@ -139,7 +140,7 @@ public class DB { stmt.executeUpdate(); } - public UserGroup getGroup(String name) throws SQLException, GuacamoleException { + public UserGroup getUserGroup(String name) throws SQLException, GuacamoleException { DB db = DB.getInstance(); Connection connection = db.getMySQLConnection(); PreparedStatement stmt = connection @@ -348,4 +349,69 @@ public class DB { stmt.executeUpdate(); } + public void addTargetGroup(TargetGroup group) throws SQLException, GuacamoleException { + if (group == null || group.getName() == null) { + throw new NullPointerException(); + } + + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + + PreparedStatement stmt = connection + .prepareStatement("insert into guacamole_connection_group (connection_group_name, type) values (?, 'ORGANIZATIONAL')", + Statement.RETURN_GENERATED_KEYS); + stmt.setString(1, group.getName()); + stmt.executeUpdate(); + } + + public TargetGroup getTargetGroup(String name) throws SQLException, GuacamoleException { + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + PreparedStatement stmt = connection + .prepareStatement("select connection_group_id from guacamole_connection_group where type='ORGANIZATIONAL' and name=?"); + stmt.setString(1, name); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()) { + TargetGroup group = new TargetGroup(); + group.setId(rs.getInt("connection_group_id")); + group.setName(name); + + return group; + } + + return null; + } + + public Set getTargetGroups() throws GuacamoleException, SQLException { + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + ResultSet rs = connection + .prepareStatement("select g.connection_group_id, g.connection_group_name from guacamole_connection_group g where type='ORGANIZATIONAL'") + .executeQuery(); + + HashSet groups = new HashSet<>(); + while (rs.next()) { + TargetGroup group = new TargetGroup(); + group.setId(rs.getInt("connection_group_id")); + group.setName(rs.getString("connection_group_name")); + + groups.add(group); + } + + return groups; + } + + public void deleteTargetGroup(TargetGroup group) throws SQLException, GuacamoleException { + if (group == null || group.getName() == null) { + return; + } + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + PreparedStatement stmt = connection + .prepareStatement("delete from guacamole_connection_group where type='ORGANIZATIONAL' and connection_group_name=?"); + stmt.setString(1, group.getName()); + stmt.executeUpdate(); + } + }