diff --git a/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java b/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java index 1047cd8..b433612 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java @@ -251,11 +251,19 @@ public void nodesAddSingle(Context ctx) throws JsonProcessingException { String name = ctx.pathParam("id"); Node node = ctx.bodyAsClass(Node.class); TemporaryNodeMergeStrategy mergeStrategy = ParamUtils.queryParamAsTemporaryNodeMergeStrategy(this.objectMapper, ctx); + boolean replace = ParamUtils.readBoolean(ctx, "replace", false); CompletableFuture> future = this.groupManager.loadGroup(name).thenCompose(opt -> { if (opt.isPresent()) { Group group = opt.get(); - group.data().add(node, mergeStrategy); + + if (replace) { + group.data().remove(node); + group.data().add(node); + } else { + group.data().add(node, mergeStrategy); + } + return this.groupManager.saveGroup(group).thenApply(v -> { this.messagingService.pushUpdate(); return group.getNodes(); diff --git a/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java b/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java index d3aa742..d8dde10 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java @@ -258,9 +258,16 @@ public void nodesAddSingle(Context ctx) throws JsonProcessingException { UUID uniqueId = pathParamAsUuid(ctx); Node node = ctx.bodyAsClass(Node.class); TemporaryNodeMergeStrategy mergeStrategy = ParamUtils.queryParamAsTemporaryNodeMergeStrategy(this.objectMapper, ctx); + boolean replace = ParamUtils.readBoolean(ctx, "replace", false); CompletableFuture> future = this.userManager.loadUser(uniqueId).thenCompose(user -> { - user.data().add(node, mergeStrategy); + if (replace) { + user.data().remove(node); + user.data().add(node); + } else { + user.data().add(node, mergeStrategy); + } + return this.userManager.saveUser(user).thenApply(v -> { this.messagingService.pushUserUpdate(user); return user.getNodes(); diff --git a/src/main/java/me/lucko/luckperms/extension/rest/util/ParamUtils.java b/src/main/java/me/lucko/luckperms/extension/rest/util/ParamUtils.java index 34d9937..6c520e9 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/util/ParamUtils.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/util/ParamUtils.java @@ -47,4 +47,18 @@ public static TemporaryNodeMergeStrategy queryParamAsTemporaryNodeMergeStrategy( return objectMapper.readValue("\"" + string + "\"", TemporaryNodeMergeStrategy.class); } } + + public static boolean readBoolean(Context ctx, String name, boolean defaultIfMissing) { + final String string = ctx.queryParam(name); + + if (string == null) { + return defaultIfMissing; + } else if (string.equals("true")) { + return true; + } else if (string.equals("false")) { + return false; + } else { + throw new IllegalArgumentException("invalid boolean '" + string + "' for query param '" + name + "'"); + } + } } diff --git a/src/main/resources/luckperms-openapi.yml b/src/main/resources/luckperms-openapi.yml index 23283c0..35eee0d 100644 --- a/src/main/resources/luckperms-openapi.yml +++ b/src/main/resources/luckperms-openapi.yml @@ -323,6 +323,7 @@ paths: operationId: add-user-node parameters: - $ref: '#/components/parameters/temporaryNodeMergeStrategy' + - $ref: '#/components/parameters/replace' responses: '200': description: Ok - returns the updated nodes @@ -862,6 +863,7 @@ paths: operationId: add-group-node parameters: - $ref: '#/components/parameters/temporaryNodeMergeStrategy' + - $ref: '#/components/parameters/replace' responses: '200': description: Ok - returns the updated nodes @@ -1848,5 +1850,12 @@ components: $ref: '#/components/schemas/TemporaryNodeMergeStrategy' required: false description: The node merge strategy + replace: + name: replace + in: query + schema: + type: boolean + required: false + description: If the node should replace an existing node with the same key (delete and add) security: - apikey: []