From 6fa30df4d77d22c996f5607ce0c23f9520e9ac05 Mon Sep 17 00:00:00 2001 From: Abba Soungui YOUNOUSS Date: Tue, 4 Nov 2025 21:01:26 +0100 Subject: [PATCH] Add user creation and update in Guacamole database. --- .../guacamole/ext/wallix/sync/Wallix.java | 40 ++++++ .../wallix/sync/WallixConfigSynchronizer.java | 40 ++++++ .../guacamole/ext/wallix/sync/db/DB.java | 119 ++++++++++++++++-- .../guacamole/ext/wallix/sync/db/User.java | 40 ++++++ 4 files changed, 230 insertions(+), 9 deletions(-) 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 a288589..e7e648c 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 @@ -149,8 +149,48 @@ public class Wallix { return list; } + public Set getUsers() throws Exception { + String output = get("/users?fields=user_name,display_name,is_disabled"); + + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(output); + Set list = new HashSet<>(); + + jsonNode.elements().forEachRemaining((e) -> { + ObjectNode node = (ObjectNode) e; + + User user = new User(); + String formattedName = getNameWithoutDomain(node.findValue(Wallix.API.ATTRIBUTE_USER_NAME).asText()); + user.setName(formattedName); + user.setFullName(node.findValue(Wallix.API.ATTRIBUTE_USER_FULL_NAME).asText()); + user.setDisabled(node.findValue(Wallix.API.ATTRIBUTE_USER_DISABLED).asBoolean()); + + list.add(user); + }); + + return list; + } + + public static String getNameWithoutDomain(String name) { + if (name == null) { + return null; + } + String[] words = name.split("\\\\"); + if (words.length > 1) { + return words[1]; + } else { + return name; + } + } + public final class API { + public static final String ATTRIBUTE_USER_DISABLED = "is_disabled"; + + public static final String ATTRIBUTE_USER_FULL_NAME = "display_name"; + + public static final String ATTRIBUTE_USER_NAME = "user_name"; + public static final String ATTRIBUTE_GROUP_NAME = "group_name"; public static final String ATTRIBUTE_GROUP_USERS = "users"; 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 b386dde..92292a2 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 @@ -7,6 +7,7 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.environment.LocalEnvironment; import cm.soungui.guacamole.ext.wallix.sync.db.DB; +import cm.soungui.guacamole.ext.wallix.sync.db.User; import cm.soungui.guacamole.ext.wallix.sync.db.UserGroup; public class WallixConfigSynchronizer implements Runnable { @@ -26,6 +27,7 @@ public class WallixConfigSynchronizer implements Runnable { while (true) { try { System.out.println("Fetching config"); + synchronizeUsers(); synchronizeGroups(); Thread.sleep(sleepDuration); } catch (Exception ex) { @@ -34,6 +36,44 @@ public class WallixConfigSynchronizer implements Runnable { } } + private void synchronizeUsers() throws Exception { + System.out.println("Synchronizing groups"); + System.out.println("Getting Wallix groups"); + Set wallixUsers = Wallix.getInstance().getUsers(); + DB db = DB.getInstance(); + wallixUsers.forEach(wallixUser -> { + try { + User dbUser = db.getUser(wallixUser.getName()); + if (dbUser == null) { + System.out.println("Adding user " + wallixUser.getName()); + db.addUser(wallixUser); + } else if (userNeedUpdate(dbUser, wallixUser)) { + System.out.println("Updating user " + wallixUser.getName() + " - " + dbUser + " - " + dbUser.getName() + " - " + + dbUser.getId()); + db.updateUser(wallixUser); + } + } catch (SQLException | GuacamoleException e) { + System.err.println(e.getMessage()); + } + }); + } + + private boolean userNeedUpdate(User dbUser, User wallixUser) { + if (wallixUser == null || dbUser == null) { + throw new NullPointerException("Null user provided"); + } + if (dbUser.getName() == null) { + return true; + } + if (dbUser.getFullName() == null) { + String fullName = wallixUser.getFullName(); + if (fullName != null && ! fullName.isEmpty()) { + return true; + } + } + return dbUser.isDisabled() != wallixUser.isDisabled(); + } + private void synchronizeGroups() throws Exception { System.out.println("Synchronizing groups"); System.out.println("Getting Wallix groups"); 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 c24a38d..c465c81 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 @@ -23,6 +23,8 @@ public class DB { private Connection mysqlConnection; + private final static String DB_ORGANIZATION = "Wallix"; + public Connection getMySQLConnection() throws GuacamoleException { try { if (mysqlConnection == null) { @@ -77,6 +79,53 @@ public class DB { return groups; } + + public User getUser(String name) throws GuacamoleException, SQLException { + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + PreparedStatement stmt = connection + .prepareStatement("select e.entity_id,u.user_id,e.name,e.type,u.full_name,u.disabled, u.organization from guacamole_entity e, guacamole_user u where e.entity_id=u.entity_id and e.name=? and u.organization=?"); + stmt.setString(1, name); + stmt.setString(2, DB_ORGANIZATION); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()) { + User user = new User(); + user.setId(rs.getInt("entity_id")); + user.setUserId(rs.getInt("user_id")); + user.setName(rs.getString("name")); + user.setFullName(rs.getString("full_name")); + user.setDisabled(rs.getBoolean("disabled")); + user.setOrganization(rs.getString("organization")); + + return user; + } + + return null; + } + + public Set getUsers() throws GuacamoleException, SQLException { + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + ResultSet rs = connection + .prepareStatement("select e.entity_id,u.user_id,e.name,e.type,u.full_name,u.disabled, from guacamole_entity e, guacamole_user u where e.entity_id=u.entity_id and u.organization='" + DB_ORGANIZATION + "'") + .executeQuery(); + + HashSet users = new HashSet<>(); + while (rs.next()) { + User user = new User(); + user.setId(rs.getInt("entity_id")); + user.setUserId(rs.getInt("user_id")); + user.setName(rs.getString("name")); + user.setFullName(rs.getString("full_name")); + user.setDisabled(rs.getBoolean("disabled")); + user.setOrganization(rs.getString("organization")); + + users.add(user); + } + + return users; + } public void deleteGroup(UserGroup group) throws SQLException, GuacamoleException { if (group == null || group.getName() == null) { @@ -90,10 +139,6 @@ public class DB { stmt.executeUpdate(); } - public User getUser(String name) throws SQLException, GuacamoleException { - return (User) getEntity(Entity.EntityType.USER, name); - } - public UserGroup getGroup(String name) throws SQLException, GuacamoleException { return (UserGroup) getEntity(Entity.EntityType.GROUP, name); } @@ -107,12 +152,12 @@ public class DB { Connection connection = db.getMySQLConnection(); PreparedStatement stmt = connection .prepareStatement("select entity_id,name from guacamole_entity where type=? and name=?"); - stmt.setString(1, type.toString()); + stmt.setString(1, type == EntityType.USER ? "USER" : "USER_GROUP"); stmt.setString(2, name); ResultSet rs = stmt.executeQuery(); while (rs.next()) { - Entity entity = new Entity(); + Entity entity = type == EntityType.USER ? new User() : new UserGroup(); entity.setId(rs.getInt("entity_id")); entity.setName(rs.getString("name")); @@ -194,10 +239,9 @@ public class DB { connection.setAutoCommit(false); PreparedStatement stmtAddEntity = connection - .prepareStatement("insert into guacamole_entity (entity_id, name, type) values (?, ?, 'USER_GROUP')", + .prepareStatement("insert into guacamole_entity (name, type) values (?, 'USER_GROUP')", Statement.RETURN_GENERATED_KEYS); - stmtAddEntity.setInt(1, group.getGroupId()); - stmtAddEntity.setString(2, group.getName()); + stmtAddEntity.setString(1, group.getName()); stmtAddEntity.executeUpdate(); ResultSet rs = stmtAddEntity.getGeneratedKeys(); @@ -215,4 +259,61 @@ public class DB { connection.setAutoCommit(true); } + public void addUser(User user) throws SQLException, GuacamoleException { + if (user == null || user.getName() == null) { + throw new NullPointerException(); + } + + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + + connection.setAutoCommit(false); + + PreparedStatement stmtAddEntity; + PreparedStatement stmtAddUser; + try { + stmtAddEntity = connection + .prepareStatement("insert into guacamole_entity (name, type) values (?, 'USER')", + Statement.RETURN_GENERATED_KEYS); + stmtAddEntity.setString(1, user.getName()); + stmtAddEntity.executeUpdate(); + + ResultSet rs = stmtAddEntity.getGeneratedKeys(); + rs.next(); + + stmtAddUser = connection + .prepareStatement("insert into guacamole_user (entity_id, full_name, disabled, password_hash, password_date, organization) values (?, ?, ?, UNHEX(SHA2(UUID(), 256)), CURRENT_TIMESTAMP(), ?)"); + stmtAddUser.setInt(1, rs.getInt(1)); + stmtAddUser.setString(2, user.getFullName()); + stmtAddUser.setBoolean(3, user.isDisabled()); + stmtAddUser.setString(4, DB_ORGANIZATION); + stmtAddUser.executeUpdate(); + + connection.commit(); + stmtAddEntity.close(); + stmtAddUser.close(); + } catch (SQLException e) { + connection.rollback(); + throw e; + } + + connection.setAutoCommit(true); + } + + public void updateUser(User wallixUser) throws GuacamoleException, SQLException { + if (wallixUser == null || wallixUser.getName() == null) { + throw new NullPointerException(); + } + + DB db = DB.getInstance(); + Connection connection = db.getMySQLConnection(); + PreparedStatement stmt = connection + .prepareStatement("update guacamole_user set full_name=?, disabled=? where user_id=? and organization=?"); + stmt.setString(1, wallixUser.getFullName()); + stmt.setBoolean(2, wallixUser.isDisabled()); + stmt.setInt(3, wallixUser.getUserId()); + stmt.setString(4, DB_ORGANIZATION); + stmt.executeUpdate(); + } + } diff --git a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/User.java b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/User.java index 86aec91..1441d09 100644 --- a/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/User.java +++ b/src/main/java/cm/soungui/guacamole/ext/wallix/sync/db/User.java @@ -2,6 +2,14 @@ package cm.soungui.guacamole.ext.wallix.sync.db; public class User extends Entity { + private int userId; + + private String fullName; + + private boolean disabled = false; + + private String organization; + @Override public EntityType getType() { return EntityType.USER; @@ -12,4 +20,36 @@ public class User extends Entity { super.setType(type); } + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public boolean isDisabled() { + return disabled; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + public String getOrganization() { + return organization; + } + + public void setOrganization(String organization) { + this.organization = organization; + } + }