package valandur.webapi.servlet.cmd;

import com.fasterxml.jackson.databind.JsonNode;
import io.sentry.Sentry;
import org.eclipse.jetty.http.HttpMethod;
import valandur.webapi.WebAPI;
import valandur.webapi.api.annotation.WebAPIEndpoint;
import valandur.webapi.api.annotation.WebAPIServlet;
import valandur.webapi.api.cache.command.ICachedCommand;
import valandur.webapi.api.servlet.WebAPIBaseServlet;
import valandur.webapi.command.CommandSource;
import valandur.webapi.servlet.ServletData;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@WebAPIServlet(basePath = "cmd")
public class CmdServlet extends WebAPIBaseServlet {

    public static int CMD_WAIT_TIME = 1000;

    @WebAPIEndpoint(method = HttpMethod.GET, path = "/", perm = "list")
    public void getCommands(ServletData data) {
        data.addJson("ok", true, false);
        data.addJson("commands", cacheService.getCommands(), data.getQueryParam("details").isPresent());
    }

    @WebAPIEndpoint(method = HttpMethod.GET, path = "/:cmd", perm = "one")
    public void getCommand(ServletData data, String cmdName) {
        Optional<ICachedCommand> cmd = cacheService.getCommand(cmdName);
        if (!cmd.isPresent()) {
            data.sendError(HttpServletResponse.SC_NOT_FOUND, "The command '" + cmdName + "' could not be found");
            return;
        }

        data.addJson("ok", true, false);
        data.addJson("command", cmd.get(), true);
    }

    @WebAPIEndpoint(method = HttpMethod.POST, path = "/", perm = "run")
    public void runCommands(ServletData data) {
        final JsonNode reqJson = data.getRequestBody();

        if (!reqJson.isArray()) {
            Optional<ExecuteCommandRequest> optReq = data.getRequestBody(ExecuteCommandRequest.class);
            if (!optReq.isPresent()) {
                data.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid command data: " + data.getLastParseError().getMessage());
                return;
            }

            ExecuteCommandRequest req = optReq.get();

            String cmd = req.getCommand().split(" ")[0];
            if (!permissionService.permits(data.getPermissions(), new String[]{ cmd })) {
                data.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied");
                return;
            }

            data.addJson("ok", true, false);
            data.addJson("result", runCommand(req), true);
            return;
        }

        List<Object> res = new ArrayList<>();
        Optional<ExecuteCommandRequest[]> optReqs = data.getRequestBody(ExecuteCommandRequest[].class);
        if (!optReqs.isPresent()) {
            data.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid command data: " + data.getLastParseError().getMessage());
            return;
        }

        ExecuteCommandRequest[] reqs = optReqs.get();
        for (ExecuteCommandRequest req : reqs) {
            String cmd = req.getCommand().split(" ")[0];
            if (!permissionService.permits(data.getPermissions(), new String[]{ cmd })) {
                res.add(new Exception("Not allowed"));
                continue;
            }

            res.add(runCommand(req));
        }

        data.addJson("ok", true, false);
        data.addJson("results", res, true);
    }

    private List<String> runCommand(ExecuteCommandRequest req) {
        final CommandSource src = new CommandSource(req.getName(), req.getWaitLines(), req.isHiddenInConsole());

        try {
            WebAPI.runOnMain(() -> WebAPI.executeCommand(req.getCommand(), src));

            if (req.getWaitLines() > 0 || req.getWaitTime() > 0) {
                synchronized (src) {
                    src.wait(req.getWaitTime() > 0 ? req.getWaitTime() : CMD_WAIT_TIME);
                }
            }

            return src.getLines();
        } catch (InterruptedException e) {
            e.printStackTrace();
            if (WebAPI.reportErrors()) WebAPI.sentryCapture(e);
            return null;
        }
    }
}

@@ -83,33 +83,8 @@
 de;%0A
-import io.sentry.Sentry;%0A
 impo
@@ -1650,24 +1650,216 @@
 estBody();%0A%0A
+        if (reqJson == null) %7B%0A            data.sendError(HttpServletResponse.SC_BAD_REQUEST, %22Invalid command data: %22 + data.getLastParseError().getMessage());%0A            return;%0A        %7D%0A%0A
         if (

Fix not providing a request body causing errors. Fixes #22