diff --git a/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/DefaultPrivilegeHandler.java b/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/DefaultPrivilegeHandler.java index 62c70c181..01aa42cfa 100644 --- a/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/DefaultPrivilegeHandler.java +++ b/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/DefaultPrivilegeHandler.java @@ -437,6 +437,83 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { } } + @Override + public void addOrUpdateUsers(Certificate certificate, List userReps) throws PrivilegeException { + + // validate user actually has this type of privilege + PrivilegeContext prvCtx = validate(certificate); + prvCtx.assertHasPrivilege(PRIVILEGE_ADD_USER); + + List toCreate = new ArrayList<>(); + List toUpdate = new ArrayList<>(); + + for (UserRep e : userReps) { + UserRep userRep = e.clone(); + + User user; + User existingUser = this.persistenceHandler.getUser(userRep.getUsername()); + + if (existingUser == null) { + + // add user + + // make sure userId is not set + if (isNotEmpty(userRep.getUserId())) { + String msg = "UserId can not be set when adding a new user!"; + throw new PrivilegeModelException(MessageFormat.format(msg, userRep.getUsername())); + } + + // set userId + userRep.setUserId(getUniqueId()); + + // first validate user + userRep.validate(); + + validateRolesExist(userRep); + + // create new user + user = createUser(userRep, new UserHistory(), null, null, false); + + // detect privilege conflicts + assertNoPrivilegeConflict(user); + + // validate this user may create such a user + prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ADD_USER, new Tuple(null, user))); + + toCreate.add(user); + logger.info("Creating new user " + user.getUsername()); + + } else { + + // update user + + if (userRep.getUserId() == null) + userRep.setUserId(existingUser.getUserId()); + + UserHistory history = existingUser.getHistory().getClone(); + byte[] passwordHash = existingUser.getPassword(); + byte[] salt = existingUser.getSalt(); + user = createUser(userRep, history, passwordHash, salt, existingUser.isPasswordChangeRequested()); + + // detect privilege conflicts + assertNoPrivilegeConflict(user); + + // validate this user may modify this user + prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_MODIFY_USER, new Tuple(existingUser, user))); + + toUpdate.add(user); + logger.info("Updating existing user " + user.getUsername()); + } + } + + // delegate to persistence handler + toCreate.forEach(user -> this.persistenceHandler.addUser(user)); + toUpdate.forEach(user -> this.persistenceHandler.replaceUser(user)); + + logger.info("Created " + toCreate.size() + " users"); + logger.info("Updated " + toUpdate.size() + " users"); + } + @Override public UserRep replaceUser(Certificate certificate, UserRep userRep, char[] password) { try { diff --git a/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/PrivilegeHandler.java b/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/PrivilegeHandler.java index 7e167a342..f242a6398 100644 --- a/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/PrivilegeHandler.java +++ b/li.strolch.privilege/src/main/java/li/strolch/privilege/handler/PrivilegeHandler.java @@ -378,6 +378,19 @@ public interface PrivilegeHandler { */ UserRep addUser(Certificate certificate, UserRep userRep, char[] password) throws PrivilegeException; + /** + * Allows the bulk adding or updating of users. If the user exists, the user's history and password is kept, + * otherwise the user is created without a password + * + * @param certificate + * the {@link Certificate} of the user which has the privilege to perform this action + * @param userReps + * the list of users to add or update + * + * @throws PrivilegeException + */ + void addOrUpdateUsers(Certificate certificate, List userReps) throws PrivilegeException; + /** *

* Updates the fields for the user with the given user. All fields on the given {@link UserRep} which are non-null diff --git a/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUserCommand.java b/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUserCommand.java index 333a12f0e..4dfec3aaa 100644 --- a/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUserCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUserCommand.java @@ -1,12 +1,14 @@ package li.strolch.service.privilege.users; +import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE; +import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.USER; + import li.strolch.model.audit.AccessType; import li.strolch.model.audit.Audit; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.privilege.handler.PrivilegeHandler; import li.strolch.privilege.model.Certificate; import li.strolch.privilege.model.UserRep; -import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants; import li.strolch.service.api.Command; import li.strolch.utils.dbc.DBC; @@ -58,9 +60,7 @@ public class PrivilegeAddUserCommand extends Command { protected void writeAudit() { tx().setSuppressAuditsForAudits(true); - this.audit = tx() - .auditFrom(AccessType.CREATE, StrolchPrivilegeConstants.PRIVILEGE, StrolchPrivilegeConstants.USER, - this.userOut.getUsername()); + this.audit = tx().auditFrom(AccessType.CREATE, PRIVILEGE, USER, this.userOut.getUsername()); tx().getAuditTrail().add(tx(), this.audit); } diff --git a/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUsersCommand.java b/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUsersCommand.java new file mode 100644 index 000000000..0fb3c5c6a --- /dev/null +++ b/li.strolch.service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddUsersCommand.java @@ -0,0 +1,60 @@ +package li.strolch.service.privilege.users; + +import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE; +import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.USER; + +import java.util.List; + +import li.strolch.model.audit.AccessType; +import li.strolch.model.audit.Audit; +import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.privilege.handler.PrivilegeHandler; +import li.strolch.privilege.model.Certificate; +import li.strolch.privilege.model.UserRep; +import li.strolch.service.api.Command; +import li.strolch.utils.dbc.DBC; + +/** + * @author Robert von Burg + */ +public class PrivilegeAddUsersCommand extends Command { + + // input + protected List usersIn; + protected Certificate cert; + + public PrivilegeAddUsersCommand(StrolchTransaction tx) { + super(tx); + } + + public void setUsersIn(List usersIn) { + this.usersIn = usersIn; + } + + public void setCert(Certificate cert) { + this.cert = cert; + } + + @Override + public void validate() { + DBC.PRE.assertNotEmpty("usersIn may not be empty!", this.usersIn); + if (this.cert == null) + this.cert = tx().getCertificate(); + } + + @Override + public void doCommand() { + PrivilegeHandler privilegeHandler = getContainer().getPrivilegeHandler().getPrivilegeHandler(); + privilegeHandler.addOrUpdateUsers(this.cert, this.usersIn); + privilegeHandler.persist(this.cert); + writeAudits(); + } + + protected void writeAudits() { + tx().setSuppressAuditsForAudits(true); + for (UserRep userRep : usersIn) { + Audit audit = tx().auditFrom(AccessType.CREATE, PRIVILEGE, USER, userRep.getUsername()); + tx().getAuditTrail().add(tx(), audit); + } + } +}