a
This commit is contained in:
parent
a1e69b84fa
commit
dca5ad1d93
15 changed files with 275 additions and 360 deletions
57
README.md
57
README.md
|
@ -1,54 +1,3 @@
|
|||
# mstats
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
|
||||
## Running the application in dev mode
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
|
||||
```shell script
|
||||
./mvnw compile quarkus:dev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
./mvnw package
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
|
||||
|
||||
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dnative
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dnative -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./target/mstats-0.0.1-SNAPSHOT-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/maven-tooling>.
|
||||
- `/api/server/heartbeat` - server heartbeat
|
||||
- `/api/plugin/{id}` - plugin info
|
||||
- `/api/plugin/find/{name}` - find a plugin id by name
|
|
@ -1,7 +1,6 @@
|
|||
package eu.m724.mstats;
|
||||
|
||||
import eu.m724.mstats.auth.AuthService;
|
||||
import eu.m724.mstats.orm.Administrator;
|
||||
import eu.m724.mstats.api.service.PluginService;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
|
@ -9,11 +8,10 @@ import jakarta.transaction.Transactional;
|
|||
|
||||
public class Startup {
|
||||
@Inject
|
||||
AuthService authService;
|
||||
PluginService pluginService;
|
||||
|
||||
@Transactional
|
||||
public void onStartup(@Observes StartupEvent event) {
|
||||
Administrator administrator = Administrator.createAdministrator();
|
||||
System.out.println(administrator.getTokenEncoded());
|
||||
pluginService.createPlugin("ploogin");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package eu.m724.mstats.api.resource;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import eu.m724.mstats.api.service.PluginService;
|
||||
import eu.m724.mstats.orm.Plugin;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Path("/api/plugin")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class PluginApiResource {
|
||||
@Inject
|
||||
PluginService pluginService;
|
||||
|
||||
@Path("/{id}")
|
||||
@GET
|
||||
public Response stats(Long id) {
|
||||
Plugin plugin = pluginService.getPlugin(id);
|
||||
if (plugin == null) {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
Map<String, Integer> servers = new HashMap<>();
|
||||
int serversTotal = 0;
|
||||
|
||||
Map<String, Integer> versions = new HashMap<>();
|
||||
for (Server server : plugin.servers) {
|
||||
String pluginVersion = server.plugins.stream().filter(p -> p.plugin.equals(plugin)).findFirst().get().version;
|
||||
serversTotal++;
|
||||
versions.put(pluginVersion, versions.getOrDefault(pluginVersion, 0) + 1);
|
||||
servers.put(server.serverVersion, servers.getOrDefault(server.serverVersion, 0) + 1);
|
||||
}
|
||||
|
||||
StatsResponse statsResponse = new StatsResponse();
|
||||
statsResponse.id = id;
|
||||
statsResponse.name = plugin.name;
|
||||
statsResponse.servers = serversTotal;
|
||||
statsResponse.serverVersions = servers.entrySet().stream().map(e -> new Version(e.getKey(), e.getValue())).toList();
|
||||
statsResponse.pluginVersions = versions.entrySet().stream().map(e -> new Version(e.getKey(), e.getValue())).toList();
|
||||
|
||||
return Response.ok(statsResponse).build();
|
||||
}
|
||||
|
||||
|
||||
@Path("/find/{name}")
|
||||
@GET
|
||||
public Response find(String name) {
|
||||
Plugin plugin = Plugin.find("name", name).firstResult();
|
||||
if (plugin == null) {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
return Response.ok(new ObjectMapper().createObjectNode().put("id", plugin.id)).build();
|
||||
|
||||
}
|
||||
|
||||
class StatsResponse {
|
||||
@JsonProperty("id")
|
||||
public Long id;
|
||||
|
||||
@JsonProperty("name")
|
||||
public String name;
|
||||
|
||||
@JsonProperty("servers")
|
||||
public int servers;
|
||||
|
||||
@JsonProperty("serverVersions")
|
||||
public List<Version> serverVersions;
|
||||
|
||||
@JsonProperty("pluginVersions")
|
||||
public List<Version> pluginVersions;
|
||||
}
|
||||
|
||||
class Version {
|
||||
public Version(String version, int servers) {
|
||||
this.version = version;
|
||||
this.servers = servers;
|
||||
}
|
||||
|
||||
@JsonProperty("version")
|
||||
public String version;
|
||||
|
||||
@JsonProperty("servers")
|
||||
public int servers;
|
||||
}
|
||||
}
|
100
src/main/java/eu/m724/mstats/api/resource/ServerApiResource.java
Normal file
100
src/main/java/eu/m724/mstats/api/resource/ServerApiResource.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
package eu.m724.mstats.api.resource;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import com.fasterxml.jackson.annotation.Nulls;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import eu.m724.mstats.api.service.ServerService;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Path("/api/server")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class ServerApiResource {
|
||||
@Inject
|
||||
ServerService serverService;
|
||||
|
||||
@Inject
|
||||
SecurityIdentity identity;
|
||||
|
||||
@Path("/heartbeat")
|
||||
@POST
|
||||
public Response heartbeat(HeartbeatRequest heartbeatRequest) {
|
||||
if (heartbeatRequest == null)
|
||||
heartbeatRequest = new HeartbeatRequest();
|
||||
|
||||
HeartbeatResponse heartbeatResponse = new HeartbeatResponse();
|
||||
Server server;
|
||||
|
||||
if (identity.isAnonymous()) {
|
||||
server = serverService.createServer();
|
||||
heartbeatResponse.token = server.getTokenEncoded();
|
||||
} else {
|
||||
server = identity.getAttribute("server");
|
||||
}
|
||||
|
||||
if (heartbeatRequest.statsVersion != 1)
|
||||
heartbeatResponse.version = 1;
|
||||
|
||||
serverService.heartbeat(server, heartbeatRequest);
|
||||
|
||||
return Response.ok(heartbeatResponse).build();
|
||||
}
|
||||
|
||||
public static class HeartbeatRequest {
|
||||
/** List of registered plugins, this is sent only on boot */
|
||||
@JsonProperty("plugins")
|
||||
public List<RunningPlugin> plugins = new ArrayList<>();
|
||||
|
||||
/** Server version like 1.21.1, this is sent only on boot */
|
||||
@JsonProperty("serverVersion")
|
||||
public String serverVersion;
|
||||
|
||||
/** Client version */
|
||||
@JsonProperty("statsVersion")
|
||||
public int statsVersion;
|
||||
|
||||
public HeartbeatRequest() {}
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class HeartbeatResponse {
|
||||
/** New token assigned to the server, usually after first request */
|
||||
@JsonProperty("token")
|
||||
@JsonSetter(nulls = Nulls.SKIP)
|
||||
public String token = null;
|
||||
|
||||
/** A message that will be displayed to server console */
|
||||
@JsonProperty("message")
|
||||
@JsonSetter(nulls = Nulls.SKIP)
|
||||
public String message = null;
|
||||
|
||||
/** Server version, used only if it doesn't match the client version */
|
||||
@JsonProperty("version")
|
||||
@JsonSetter(nulls = Nulls.SKIP)
|
||||
public Integer version = null;
|
||||
|
||||
public HeartbeatResponse() {}
|
||||
}
|
||||
|
||||
public static class RunningPlugin {
|
||||
public RunningPlugin() {}
|
||||
|
||||
@JsonProperty("id")
|
||||
public Long id;
|
||||
|
||||
@JsonProperty("version")
|
||||
public String version;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package eu.m724.mstats.resource.api;
|
||||
package eu.m724.mstats.api.service;
|
||||
|
||||
import eu.m724.mstats.orm.Plugin;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
@ -7,8 +7,8 @@ import jakarta.transaction.Transactional;
|
|||
@ApplicationScoped
|
||||
public class PluginService {
|
||||
@Transactional
|
||||
public Plugin createPlugin(String name, String description) {
|
||||
return Plugin.createPlugin(name, description);
|
||||
public Plugin createPlugin(String name) {
|
||||
return Plugin.createPlugin(name);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -29,7 +29,7 @@ public class PluginService {
|
|||
}
|
||||
|
||||
@Transactional
|
||||
public Plugin editPlugin(long id, String name, String description) {
|
||||
public Plugin editPlugin(long id, String name) {
|
||||
Plugin plugin = Plugin.findById(id);
|
||||
|
||||
if (plugin == null)
|
||||
|
@ -38,9 +38,6 @@ public class PluginService {
|
|||
if (name != null)
|
||||
plugin.name = name;
|
||||
|
||||
if (description != null)
|
||||
plugin.description = description;
|
||||
|
||||
plugin.persistAndFlush();
|
||||
return plugin;
|
||||
}
|
36
src/main/java/eu/m724/mstats/api/service/ServerService.java
Normal file
36
src/main/java/eu/m724/mstats/api/service/ServerService.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package eu.m724.mstats.api.service;
|
||||
|
||||
import eu.m724.mstats.api.resource.ServerApiResource;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ServerService {
|
||||
@Transactional
|
||||
public Server createServer() {
|
||||
return Server.createServer();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void modifyServer(Server server) {
|
||||
server.persistAndFlush();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void heartbeat(Server server, ServerApiResource.HeartbeatRequest heartbeatRequest) {
|
||||
server = Server.findById(server.id); // this is necessary for some reason
|
||||
|
||||
for (ServerApiResource.RunningPlugin plugin : heartbeatRequest.plugins) {
|
||||
server.addPlugin(plugin.id, plugin.version);
|
||||
}
|
||||
|
||||
if (heartbeatRequest.serverVersion != null)
|
||||
server.serverVersion = heartbeatRequest.serverVersion;
|
||||
|
||||
server.heartbeat = Instant.now();
|
||||
server.persistAndFlush();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package eu.m724.mstats.auth;
|
||||
|
||||
import eu.m724.mstats.orm.Administrator;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
@ -9,17 +8,9 @@ import java.util.Base64;
|
|||
|
||||
@ApplicationScoped
|
||||
public class AuthService {
|
||||
public final Base64.Decoder decoder = Base64.getDecoder();
|
||||
|
||||
@Transactional
|
||||
Administrator getAdministratorByToken(String encoded) {
|
||||
byte[] token = decoder.decode(encoded);
|
||||
return Administrator.find("token", (Object) token).firstResult();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
Server getServerByToken(String encoded) {
|
||||
byte[] token = decoder.decode(encoded);
|
||||
byte[] token = Base64.getDecoder().decode(encoded);
|
||||
return Server.find("token", (Object) token).firstResult();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package eu.m724.mstats.auth;
|
||||
|
||||
|
||||
import eu.m724.mstats.orm.Administrator;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import io.quarkus.security.identity.IdentityProviderManager;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
|
@ -16,7 +14,6 @@ import jakarta.annotation.Priority;
|
|||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Alternative;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -40,29 +37,6 @@ public class MyHttpAuthenticationMechanism implements HttpAuthenticationMechanis
|
|||
.addRole("server")
|
||||
.addAttribute("server", server)
|
||||
.build();
|
||||
} else {
|
||||
context.response()
|
||||
.setStatusCode(Response.Status.UNAUTHORIZED.getStatusCode())
|
||||
.setStatusMessage("{\"message\": \"X-Server-Token is invalid\"}");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
String adminTokenEncoded = context.request().getHeader("X-Administrator-Token");
|
||||
if (adminTokenEncoded != null) {
|
||||
Administrator administrator = authService.getAdministratorByToken(adminTokenEncoded);
|
||||
if (administrator != null) {
|
||||
return QuarkusSecurityIdentity.builder()
|
||||
.setPrincipal(new QuarkusPrincipal("Administrator " + administrator.id.toString()))
|
||||
.addRole("administrator")
|
||||
.addRoles(administrator.roles)
|
||||
.addAttribute("administrator", administrator)
|
||||
.build();
|
||||
} else {
|
||||
context.response()
|
||||
.setStatusCode(Response.Status.UNAUTHORIZED.getStatusCode())
|
||||
.setStatusMessage("{\"message\": \"X-Administrator-Token is invalid\"}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package eu.m724.mstats.orm;
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = "token"),
|
||||
indexes = @Index(columnList = "token")
|
||||
)
|
||||
public class Administrator extends PanacheEntity {
|
||||
@Column(nullable = false)
|
||||
public byte[] token;
|
||||
|
||||
public Set<String> roles;
|
||||
|
||||
public String getTokenEncoded() {
|
||||
return Base64.getEncoder().encodeToString(token);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static Administrator createAdministrator(String... roles) {
|
||||
byte[] token = new byte[32];
|
||||
ThreadLocalRandom.current().nextBytes(token);
|
||||
|
||||
Administrator administrator = new Administrator();
|
||||
administrator.token = token;
|
||||
administrator.roles = Set.of(roles);
|
||||
|
||||
administrator.persistAndFlush();
|
||||
|
||||
return administrator;
|
||||
}
|
||||
}
|
|
@ -1,37 +1,30 @@
|
|||
package eu.m724.mstats.orm;
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
indexes = @Index(columnList = "name")
|
||||
)
|
||||
public class Plugin extends PanacheEntity {
|
||||
@Column(unique = true, nullable = false)
|
||||
public String name;
|
||||
|
||||
public String description;
|
||||
|
||||
@ManyToMany
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
public List<Server> servers = new ArrayList<>();
|
||||
|
||||
@Transactional
|
||||
public static Plugin createPlugin(String name, String description) {
|
||||
public static Plugin createPlugin(String name) {
|
||||
Plugin plugin = new Plugin();
|
||||
plugin.name = name;
|
||||
plugin.description = description;
|
||||
|
||||
plugin.persistAndFlush();
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static Plugin createPlugin(String name) {
|
||||
return createPlugin(name, null);
|
||||
}
|
||||
}
|
||||
|
|
19
src/main/java/eu/m724/mstats/orm/PluginWithVersion.java
Normal file
19
src/main/java/eu/m724/mstats/orm/PluginWithVersion.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package eu.m724.mstats.orm;
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
public class PluginWithVersion extends PanacheEntity {
|
||||
public PluginWithVersion() {}
|
||||
|
||||
public PluginWithVersion(Plugin plugin, String version) {
|
||||
this.plugin = plugin;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
public Plugin plugin;
|
||||
|
||||
public String version;
|
||||
}
|
|
@ -19,13 +19,10 @@ public class Server extends PanacheEntity {
|
|||
@Column(nullable = false)
|
||||
public byte[] token;
|
||||
|
||||
/**
|
||||
* ISO 3166-1 numeric
|
||||
*/
|
||||
public int countryCode;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
public List<PluginWithVersion> plugins = new ArrayList<>();
|
||||
|
||||
@ManyToMany(cascade = CascadeType.ALL)
|
||||
public List<Plugin> plugins = new ArrayList<>();
|
||||
public String serverVersion;
|
||||
|
||||
public Instant heartbeat = Instant.now();
|
||||
|
||||
|
@ -34,13 +31,16 @@ public class Server extends PanacheEntity {
|
|||
}
|
||||
|
||||
@Transactional
|
||||
public Plugin addPlugin(long id) {
|
||||
public Plugin addPlugin(long id, String version) {
|
||||
Plugin plugin = Plugin.findById(id);
|
||||
|
||||
if (plugin == null)
|
||||
return null;
|
||||
|
||||
plugins.add(plugin);
|
||||
if (plugins.stream().anyMatch(pwv -> pwv.plugin.id == id))
|
||||
return null;
|
||||
|
||||
plugins.add(new PluginWithVersion(plugin, version));
|
||||
plugin.servers.add(this);
|
||||
|
||||
this.persistAndFlush();
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
package eu.m724.mstats.resource.api;
|
||||
|
||||
import eu.m724.mstats.auth.AuthService;
|
||||
import eu.m724.mstats.orm.Plugin;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/api/admin")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("administrator")
|
||||
public class AdminApiResource {
|
||||
@Inject
|
||||
AuthService authService;
|
||||
|
||||
@Inject
|
||||
PluginService pluginService;
|
||||
|
||||
@Inject
|
||||
SecurityIdentity identity;
|
||||
|
||||
@Path("/plugin")
|
||||
@GET
|
||||
public Response getPlugin(@QueryParam("id") long id) {
|
||||
Plugin plugin = pluginService.getPlugin(id);
|
||||
|
||||
if (plugin == null)
|
||||
return Response.ok(new JsonObject().put("id", id)).status(Response.Status.NOT_FOUND).build();
|
||||
|
||||
JsonObject response = new JsonObject()
|
||||
.put("id", plugin.id)
|
||||
.put("name", plugin.name)
|
||||
.put("description", plugin.description);
|
||||
|
||||
return Response.ok(response).build();
|
||||
}
|
||||
|
||||
@Path("/plugin")
|
||||
@PUT
|
||||
public Response createPlugin(JsonObject data) {
|
||||
String name = data.getString("name");
|
||||
String description = data.getString("description");
|
||||
|
||||
Plugin plugin = pluginService.createPlugin(name, description);
|
||||
|
||||
JsonObject response = new JsonObject()
|
||||
.put("id", plugin.id);
|
||||
|
||||
return Response.ok(response).build();
|
||||
}
|
||||
|
||||
@Path("/plugin")
|
||||
@PATCH
|
||||
public Response editPlugin(JsonObject data) {
|
||||
long id = data.getLong("id");
|
||||
String name = data.getString("name");
|
||||
String description = data.getString("description");
|
||||
|
||||
Plugin plugin = pluginService.editPlugin(id, name, description);
|
||||
|
||||
if (plugin == null)
|
||||
return Response.ok(new JsonObject().put("id", id)).status(Response.Status.NOT_FOUND).build();
|
||||
|
||||
JsonObject response = new JsonObject()
|
||||
.put("id", plugin.id);
|
||||
|
||||
return Response.ok(response).build();
|
||||
}
|
||||
|
||||
@Path("/plugin")
|
||||
@DELETE
|
||||
public Response deletePlugin(JsonObject data) {
|
||||
long id = data.getLong("id");
|
||||
|
||||
Plugin plugin = pluginService.deletePlugin(id);
|
||||
|
||||
if (plugin == null)
|
||||
return Response.ok(new JsonObject().put("id", id)).status(Response.Status.NOT_FOUND).build();
|
||||
|
||||
JsonObject response = new JsonObject()
|
||||
.put("id", plugin.id);
|
||||
|
||||
return Response.ok(response).build();
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package eu.m724.mstats.resource.api;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import eu.m724.mstats.orm.Plugin;
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Path("/api/server")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class ServerApiResource {
|
||||
@Inject
|
||||
ServerService serverService;
|
||||
|
||||
@Inject
|
||||
SecurityIdentity identity;
|
||||
|
||||
@Path("/boot")
|
||||
@POST
|
||||
public Response boot(BootRequest bootRequest) {
|
||||
BootResponse bootResponse = new BootResponse();
|
||||
Server server;
|
||||
|
||||
if (identity.isAnonymous()) {
|
||||
server = serverService.createServer();
|
||||
bootResponse.token = server.getTokenEncoded();
|
||||
} else {
|
||||
server = identity.getAttribute("server");
|
||||
}
|
||||
|
||||
List<Long> invalidIds = new ArrayList<>();
|
||||
|
||||
for (Long pluginId : bootRequest.plugins) {
|
||||
Plugin plugin = server.addPlugin(pluginId);
|
||||
if (plugin == null)
|
||||
invalidIds.add(pluginId);
|
||||
}
|
||||
|
||||
if (!invalidIds.isEmpty()) {
|
||||
bootResponse.invalidPlugins = invalidIds;
|
||||
}
|
||||
|
||||
serverService.
|
||||
|
||||
return Response.ok(bootResponse).build();
|
||||
}
|
||||
|
||||
@Path("/heartbeat")
|
||||
@POST
|
||||
@RolesAllowed("server")
|
||||
public void heartbeat() {
|
||||
|
||||
}
|
||||
|
||||
public static class BootRequest {
|
||||
@JsonProperty("plugins")
|
||||
public List<Long> plugins;
|
||||
|
||||
public BootRequest() {}
|
||||
}
|
||||
|
||||
public static class BootResponse {
|
||||
@JsonProperty("token")
|
||||
public String token;
|
||||
|
||||
@JsonProperty("invalidPlugins")
|
||||
public List<Long> invalidPlugins;
|
||||
|
||||
public BootResponse() {}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package eu.m724.mstats.resource.api;
|
||||
|
||||
import eu.m724.mstats.orm.Server;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ServerService {
|
||||
@Transactional
|
||||
public Server createServer() {
|
||||
return Server.createServer();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void modifyServer(Server server) {
|
||||
server.persistAndFlush();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void heartbeat(Server server, List<Long> plugins) {
|
||||
server.heartbeat =
|
||||
server.persistAndFlush();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue