Compare commits

..

No commits in common. "d08dd3777ab823576117267d690f89bcf2f9b6d4" and "06187944918b9d29b87012f168f2101727b5badc" have entirely different histories.

13 changed files with 55 additions and 204 deletions

View file

@ -62,10 +62,6 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>

View file

@ -4,12 +4,23 @@ import eu.m724.mstats.api.service.PluginService;
import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.persistence.EntityExistsException;
public class Startup {
@Inject
PluginService pluginService;
public void onStartup(@Observes StartupEvent event) {
try {
pluginService.createPlugin(1, "Tweaks724");
} catch (EntityExistsException e) {
System.out.println("exists1");
}
try {
pluginService.createPlugin(2, "Giants");
} catch (EntityExistsException e) {
System.out.println("exists2");
}
}
}

View file

@ -1,92 +0,0 @@
package eu.m724.mstats.api.resource;
import com.fasterxml.jackson.annotation.JsonProperty;
import eu.m724.mstats.api.service.AdminService;
import eu.m724.mstats.orm.Plugin;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.persistence.EntityExistsException;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
@Path("/api/admin")
@RolesAllowed("admin")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class AdminApiResource {
@Inject
AdminService adminService;
@Path("/plugin")
@PUT
public Response createPlugin(CreateRequest request) {
Plugin plugin;
Response.Status status = Response.Status.OK;
try {
plugin = Plugin.createPlugin(request.name);
} catch (EntityExistsException e) {
plugin = Plugin.find("name", request.name).firstResult();
status = Response.Status.CONFLICT;
}
var response = new CreateResponse(plugin.id, plugin.name);
return Response.status(status).entity(response).build();
}
@Path("/plugin")
@DELETE
public Response deletePlugin(DeleteRequest request) {
Plugin plugin = Plugin.findById(request.id);
if (plugin == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
var response = new CreateResponse(plugin.id, plugin.name);
adminService.deletePlugin(plugin);
return Response.ok(response).build();
}
@Path("/plugins")
@GET
public Response getPlugins() {
List<Plugin> plugins = Plugin.listAll();
List<CreateResponse> responses = new ArrayList<>();
plugins.forEach(v -> responses.add(new CreateResponse(v.id, v.name)));
return Response.ok(responses).build();
}
static class DeleteRequest {
@JsonProperty("id")
public long id;
}
static class CreateRequest {
@JsonProperty("name")
public String name;
}
static class CreateResponse {
CreateResponse(long id, String name) {
this.id = id;
this.name = name;
}
@JsonProperty("id")
public long id;
@JsonProperty("name")
public String name;
}
}

View file

@ -4,10 +4,8 @@ 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.PluginVersion;
import eu.m724.mstats.orm.Server;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
@ -26,7 +24,6 @@ public class PluginApiResource {
@Path("/{id}")
@GET
@Transactional
public Response stats(Long id) {
Plugin plugin = pluginService.getPlugin(id);
if (plugin == null) {
@ -34,21 +31,16 @@ public class PluginApiResource {
}
Map<String, Integer> servers = new HashMap<>();
Map<String, Integer> versions = new HashMap<>();
int serversTotal = 0;
List<PluginVersion> pv = PluginVersion.find("plugin", plugin).list();
for (PluginVersion v : pv) {
int sv = 0;
for (Server server : v.servers) {
sv++;
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);
}
serversTotal += sv;
versions.put(v.version, sv);
}
StatsResponse statsResponse = new StatsResponse();
statsResponse.id = id;
statsResponse.name = plugin.name;

View file

@ -1,13 +0,0 @@
package eu.m724.mstats.api.service;
import eu.m724.mstats.orm.Plugin;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
@ApplicationScoped
public class AdminService {
@Transactional
public void deletePlugin(Plugin plugin) {
plugin.delete();
}
}

View file

@ -7,8 +7,8 @@ import jakarta.transaction.Transactional;
@ApplicationScoped
public class PluginService {
@Transactional
public Plugin createPlugin(String name) {
return Plugin.createPlugin(name);
public Plugin createPlugin(long id, String name) {
return Plugin.createPlugin(id, name);
}

View file

@ -3,11 +3,10 @@ package eu.m724.mstats.api.service;
import eu.m724.mstats.api.resource.ServerApiResource;
import eu.m724.mstats.orm.Plugin;
import eu.m724.mstats.orm.Server;
import io.quarkus.scheduler.Scheduled;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
@ -47,18 +46,7 @@ public class ServerService {
// TODO
}
server.lastHeartbeat = LocalDateTime.now();
server.heartbeat = Instant.now();
server.persistAndFlush();
}
@Transactional
@Scheduled(every="30m")
public void cleanUp() {
System.out.println("Cleanup running");
LocalDateTime now = LocalDateTime.now().minusHours(2);
long deleted = Server.delete("lastHeartbeat < ?1", now);
System.out.printf("Deleted %d servers\n", deleted);
}
}

View file

@ -10,11 +10,7 @@ import java.util.Base64;
public class AuthService {
@Transactional
Server getServerByToken(String encoded) {
try {
byte[] token = Base64.getDecoder().decode(encoded);
return Server.find("token", (Object) token).firstResult();
} catch (IllegalArgumentException e) {
return null;
}
}
}

View file

@ -30,13 +30,6 @@ public class MyHttpAuthenticationMechanism implements HttpAuthenticationMechanis
String serverTokenEncoded = context.request().getHeader("X-Server-Token");
if (serverTokenEncoded != null) {
if (serverTokenEncoded.equals("secure admni token")) {
return QuarkusSecurityIdentity.builder()
.setPrincipal(new QuarkusPrincipal("Administrator"))
.addRole("admin")
.build();
}
Server server = authService.getServerByToken(serverTokenEncoded);
if (server != null) {
return QuarkusSecurityIdentity.builder()

View file

@ -15,29 +15,22 @@ public class Plugin extends PanacheEntity {
@Column(unique = true, nullable = false)
public String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
public List<PluginVersion> versions = new ArrayList<>();
@ManyToMany(fetch = FetchType.EAGER)
public List<Server> servers = new ArrayList<>();
@Transactional
public static Plugin createPlugin(String name) {
public static Plugin createPlugin(long id, String name) {
if (Plugin.find("name", name).firstResultOptional().isPresent()) throw new EntityExistsException();
Plugin plugin = new Plugin();
if (id != -1) {
if (Plugin.findById(id) != null) throw new EntityExistsException();
plugin.id = id;
}
plugin.name = name;
plugin.persistAndFlush();
return plugin;
}
@Transactional
public PluginVersion getVersion(String version) {
PluginVersion pv = PluginVersion.find("plugin = ?1 and version = ?2", this, version).firstResult();
if (pv == null) {
pv = new PluginVersion(this, version);
pv.persistAndFlush();
}
return pv;
}
}

View file

@ -1,29 +0,0 @@
package eu.m724.mstats.orm;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(
uniqueConstraints = @UniqueConstraint(columnNames = { "plugin", "version" }),
indexes = @Index(columnList = "plugin_id")
)
public class PluginVersion extends PanacheEntity {
public PluginVersion() {}
public PluginVersion(Plugin plugin, String version) {
this.plugin = plugin;
this.version = version;
}
@ManyToOne
public Plugin plugin;
@ManyToMany
public List<Server> servers = new ArrayList<>();
public String version;
}

View 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;
}

View file

@ -3,9 +3,8 @@ package eu.m724.mstats.orm;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.transaction.Transactional;
import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
@ -20,13 +19,12 @@ public class Server extends PanacheEntity {
@Column(nullable = false)
public byte[] token;
@ManyToMany(mappedBy = "servers", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<PluginVersion> plugins = new ArrayList<>();
@ManyToMany(fetch = FetchType.EAGER)
public List<PluginWithVersion> plugins = new ArrayList<>();
public String serverVersion;
@CreationTimestamp
public LocalDateTime lastHeartbeat;
public Instant heartbeat = Instant.now();
public String getTokenEncoded() {
return Base64.getEncoder().encodeToString(token);
@ -42,9 +40,8 @@ public class Server extends PanacheEntity {
if (plugins.stream().anyMatch(pwv -> pwv.plugin.id == id))
return plugin;
PluginVersion pluginVersion = plugin.getVersion(version);
plugins.add(pluginVersion);
pluginVersion.servers.add(this);
plugins.add(new PluginWithVersion(plugin, version));
plugin.servers.add(this);
this.persistAndFlush();
return plugin;