add rename and view code endpoints

This commit is contained in:
Ivy Collective 2025-01-16 09:12:26 -05:00
parent f9adbacf19
commit 7a08b8ca82
4 changed files with 190 additions and 11 deletions

View file

@ -19,10 +19,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import com.google.gson.JsonObject;
/**
* Utility class for directly modifiying computers.
*/
public class ComputerEditor {
private static void _setMetadata(final ComputerMetadata metadata) {
if (ComputerRegistry.getComputerById(metadata.id) != null) {
ComputerRegistry.getComputerById(metadata.id).updateMetadata(metadata);
}
ComputerRegistry.metadataStorage.storeData(metadata.id, metadata);
}
private ComputerEditor() {}
/**
@ -35,6 +43,9 @@ public class ComputerEditor {
}).stream().map(id -> ComputerRegistry.metadataStorage.getData(id)).toList();
}
/**
* Returns true if the user has permissions to access the computer
*/
public static boolean hasAccessToComputer(final UUID user, final String computer) {
ComputerMetadata metadata = ComputerRegistry.metadataStorage.getData(computer);
@ -44,4 +55,28 @@ public class ComputerEditor {
return metadata.owner == user || Arrays.asList(metadata.collaborators).contains(user);
}
public static ComputerMetadata getMetadata(final String computer) {
if (ComputerRegistry.getComputerById(computer) != null) {
return ComputerRegistry.getComputerById(computer).getMetadata();
}
return ComputerRegistry.metadataStorage.getData(computer);
}
/**
* Get the stored code for a computer
*/
public static String getCode(final String computer) {
if (ComputerRegistry.getComputerById(computer) != null) {
return ComputerRegistry.getComputerById(computer).getCode();
}
return ComputerRegistry.codeStorage.getData(computer);
}
public static void rename(final String computerId, final String name) {
JsonObject metadata = getMetadata(computerId).serialize();
metadata.addProperty("name", name);
_setMetadata(new ComputerMetadata(metadata));
}
}

View file

@ -16,16 +16,8 @@
package de.blazemcworld.blazinggames.computing.api;
import de.blazemcworld.blazinggames.computing.api.impl.RootEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthCallbackEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthConsentEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthErrorEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthLinkEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthPrepareEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthRedeemEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthTestEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthUnlinkConfirmEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.AuthUnlinkEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.computers.ComputersListEndpoint;
import de.blazemcworld.blazinggames.computing.api.impl.auth.*;
import de.blazemcworld.blazinggames.computing.api.impl.computers.*;
public enum EndpointList {
ROOT(null, new RootEndpoint()),
@ -38,7 +30,10 @@ public enum EndpointList {
AUTH_ERROR(null, new AuthErrorEndpoint()),
AUTH_UNLINK(null, new AuthUnlinkEndpoint()),
AUTH_UNLINK_CONFIRM(null, new AuthUnlinkConfirmEndpoint()),
COMPUTER_LIST("Computers", new ComputersListEndpoint());
COMPUTER_LIST("Computers", new ComputersListEndpoint()),
COMPUTER_CODE_READ("Computers", new ViewCodeEndpoint()),
;
public final String category;
public final Endpoint endpoint;

View file

@ -0,0 +1,70 @@
/*
* Copyright 2025 The Blazing Games Maintainers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.blazemcworld.blazinggames.computing.api.impl.computers;
import com.google.gson.JsonObject;
import de.blazemcworld.blazinggames.computing.ComputerEditor;
import de.blazemcworld.blazinggames.computing.api.APIDocs;
import de.blazemcworld.blazinggames.computing.api.EarlyResponse;
import de.blazemcworld.blazinggames.computing.api.Endpoint;
import de.blazemcworld.blazinggames.computing.api.EndpointResponse;
import de.blazemcworld.blazinggames.computing.api.LinkedUser;
import de.blazemcworld.blazinggames.computing.api.Permission;
import de.blazemcworld.blazinggames.computing.api.RequestContext;
import de.blazemcworld.blazinggames.computing.api.RequestMethod;
public class RenameEndpoint implements Endpoint {
@Override
public String path() {
return "/computers/rename";
}
@Override
public EndpointResponse PATCH(RequestContext context) throws EarlyResponse {
var body = context.useBodyWrapper();
LinkedUser user = context.requireAuthentication();
context.requirePermission(Permission.READ_COMPUTERS);
context.requirePermission(Permission.WRITE_COMPUTERS);
String id = context.requireClean("id", body.getString("id"));
String name = context.requireClean("name", body.getString("name"));
if (!ComputerEditor.hasAccessToComputer(user.uuid(), id)) {
return EndpointResponse.of403();
}
ComputerEditor.rename(id, name);
return EndpointResponse.of200(new JsonObject()).build();
}
@Override
public APIDocs[] docs() {
return new APIDocs[]{
APIDocs.builder()
.title("Rename computer")
.description("Set a computer's name.")
.method(RequestMethod.POST)
.addGenerics()
.removeBodyFromGenerics()
.addPermission(Permission.READ_COMPUTERS)
.addPermission(Permission.WRITE_COMPUTERS)
.addIncomingArgument("id", "The ID of the computer")
.addIncomingArgument("name", "The name of the computer")
.build()
};
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright 2025 The Blazing Games Maintainers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.blazemcworld.blazinggames.computing.api.impl.computers;
import java.util.Base64;
import com.google.gson.JsonObject;
import de.blazemcworld.blazinggames.computing.ComputerEditor;
import de.blazemcworld.blazinggames.computing.api.APIDocs;
import de.blazemcworld.blazinggames.computing.api.EarlyResponse;
import de.blazemcworld.blazinggames.computing.api.Endpoint;
import de.blazemcworld.blazinggames.computing.api.EndpointResponse;
import de.blazemcworld.blazinggames.computing.api.LinkedUser;
import de.blazemcworld.blazinggames.computing.api.Permission;
import de.blazemcworld.blazinggames.computing.api.RequestContext;
import de.blazemcworld.blazinggames.computing.api.RequestMethod;
import de.blazemcworld.blazinggames.utils.GZipToolkit;
import de.blazemcworld.blazinggames.utils.GetGson;
public class ViewCodeEndpoint implements Endpoint {
@Override
public String path() {
return "/computers/code";
}
@Override
public EndpointResponse GET(RequestContext context) throws EarlyResponse {
LinkedUser linked = context.requireAuthentication();
context.requirePermission(Permission.COMPUTER_CODE_READ);
JsonObject body = GetGson.getAsObject(context.requireBody(), EarlyResponse.of(EndpointResponse.of400("Missing query parameters")));
String id = context.requireClean("id", GetGson.getString(body, "id", EarlyResponse.of(EndpointResponse.of400("Missing id argument"))));
if (!ComputerEditor.hasAccessToComputer(linked.uuid(), id)) {
return EndpointResponse.of403();
}
JsonObject out = new JsonObject();
out.addProperty("data", Base64.getEncoder().encodeToString(GZipToolkit.compress(ComputerEditor.getCode(id))));
return EndpointResponse.of200(out).build();
}
@Override
public APIDocs[] docs() {
return new APIDocs[]{
APIDocs.builder()
.title("Read computer code")
.description("View the code of a computer. Use the WSS to edit it.")
.method(RequestMethod.GET)
.addGenerics()
.removeBodyFromGenerics()
.addPermission(Permission.COMPUTER_CODE_READ)
.addIncomingArgument(
"id",
"The ID of the computer"
)
.addOutgoingArgument(
"data",
"Base64-encoded, gzip-compressed computer code"
)
.build()
};
}
}