Skip to content

Commit afde94d

Browse files
renovate[bot]rainbowdashlabsyannicklamprecht
authored
Update dependency de.chojo:cjda-util to v2.10.2+jda-5.1.0 - abandoned (#54)
* Update dependency de.chojo:cjda-util to v2.10.2+jda-5.1.0 * Migrate to javalin 6 * Patch plugins to javalin 6 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Lilly <46890129+RainbowDashLabs@users.noreply.github.com> Co-authored-by: Yannick Lamprecht <1420893+yannicklamprecht@users.noreply.github.com>
1 parent 0cfcd86 commit afde94d

13 files changed

Lines changed: 343 additions & 326 deletions

File tree

bot/build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ dependencies {
1717
implementation(project(":plugin-api"))
1818

1919
// discord
20-
implementation("de.chojo", "cjda-util", "2.9.8+jda-5.0.0") {
20+
implementation("de.chojo", "cjda-util", "2.10.3+jda-5.1.0") {
2121
exclude(module = "opus-java")
2222
}
2323
implementation(libs.javalin.bundle)
24+
implementation(libs.javalin.openapi)
25+
implementation(libs.javalin.swagger)
26+
annotationProcessor(libs.javalin.annotation)
2427
implementation("net.lingala.zip4j", "zip4j", "2.11.6")
2528

2629
// database

bot/src/main/java/de/chojo/gamejam/api/Api.java

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
import de.chojo.gamejam.server.ServerService;
1616
import io.javalin.Javalin;
1717
import io.javalin.http.Context;
18-
import io.javalin.plugin.openapi.OpenApiOptions;
19-
import io.javalin.plugin.openapi.OpenApiPlugin;
20-
import io.javalin.plugin.openapi.ui.ReDocOptions;
21-
import io.javalin.plugin.openapi.ui.SwaggerOptions;
18+
import io.javalin.http.UnauthorizedResponse;
19+
import io.javalin.openapi.plugin.OpenApiPlugin;
20+
import io.javalin.openapi.plugin.swagger.SwaggerPlugin;
2221
import net.dv8tion.jda.api.sharding.ShardManager;
2322
import org.slf4j.Logger;
2423

25-
import javax.servlet.http.HttpServletResponse;
24+
import java.util.Set;
2625
import java.util.stream.Collectors;
2726

2827
import static io.javalin.apibuilder.ApiBuilder.path;
@@ -36,6 +35,11 @@ public class Api {
3635
private final de.chojo.gamejam.data.access.Teams teams;
3736
private final ServerService serverService;
3837
private Javalin app;
38+
private final Set<String> unauthorized = Set.of(
39+
"/api/swagger",
40+
"/api/openapi.json",
41+
"/api/v1/server/plugin",
42+
"/webjars");
3943

4044
public static Api create(Configuration configuration, ShardManager shardManager, Guilds guilds, de.chojo.gamejam.data.access.Teams teams, ServerService serverService) {
4145
var api = new Api(configuration, shardManager, guilds, teams, serverService);
@@ -53,44 +57,46 @@ public Api(Configuration configuration, ShardManager shardManager, Guilds guilds
5357

5458
private void build() {
5559
app = Javalin.create(config -> {
56-
config.registerPlugin(getConfiguredOpenApiPlugin());
57-
config.accessManager((handler, ctx, routeRoles) -> {
58-
if(ctx.path().startsWith("/swagger") || ctx.path().startsWith("/redoc") || ctx.path().startsWith("/api/v1/server/plugin")){
59-
handler.handle(ctx);
60-
return;
61-
}
62-
63-
var token = ctx.req.getHeader("authorization");
64-
if (token == null) {
65-
ctx.status(HttpServletResponse.SC_UNAUTHORIZED).result("Please provide a valid token in the authorization header.");
66-
} else if (!token.equals(configuration.api().token())) {
67-
ctx.status(HttpServletResponse.SC_UNAUTHORIZED).result("Unauthorized");
68-
} else {
69-
handler.handle(ctx);
70-
}
71-
});
72-
config.requestLogger((ctx, executionTimeMs) -> {
60+
config.useVirtualThreads = true;
61+
config.requestLogger.http((ctx, executionTimeMs) -> {
7362
log.debug("{}: {} in {}ms\nHeaders:\n{}\nBody:\n{}",
7463
ctx.method(), ctx.path(), executionTimeMs,
7564
headers(ctx),
7665
ctx.body().substring(0, Math.min(100, ctx.body().length())));
7766
});
67+
config.router.apiBuilder(this::routes);
68+
config.registerPlugin(openApi());
69+
config.registerPlugin(swagger());
7870
}).start(configuration.api().host(), configuration.api().port());
7971

8072
app.exception(InterruptException.class, (exception, ctx) -> {
8173
ctx.status(exception.status()).result(exception.getMessage());
8274
});
8375

84-
app.routes(() -> {
85-
path("api/v1", () -> {
86-
var users = new Users(shardManager, guilds);
87-
users.routes();
88-
var teams = new Teams(shardManager, guilds);
89-
teams.routes();
90-
Server server = new Server(serverService, this.teams);
91-
server.routes();
92-
});
76+
app.beforeMatched(ctx -> {
77+
for (String path : unauthorized) {
78+
if(ctx.path().startsWith(path)) return;
79+
}
80+
81+
var token = ctx.req().getHeader("authorization");
82+
if (token == null) {
83+
throw new UnauthorizedResponse();
84+
} else if (!token.equals(configuration.api().token())) {
85+
throw new UnauthorizedResponse();
86+
}
87+
});
88+
}
89+
90+
private void routes() {
91+
path("api/v1", () -> {
92+
var users = new Users(shardManager, guilds);
93+
users.routes();
94+
var teams = new Teams(shardManager, guilds);
95+
teams.routes();
96+
Server server = new Server(serverService, this.teams);
97+
server.routes();
9398
});
99+
94100
}
95101

96102
private String headers(Context context) {
@@ -101,18 +107,28 @@ private String headers(Context context) {
101107
.collect(Collectors.joining("\n "));
102108
}
103109

104-
private static OpenApiPlugin getConfiguredOpenApiPlugin() {
105-
var info = new io.swagger.v3.oas.models.info.Info().version("1.0").description("User API");
106-
OpenApiOptions options = new OpenApiOptions(info)
107-
.activateAnnotationScanningFor("io.javalin.example.java")
108-
.path("/swagger-docs") // endpoint for OpenAPI json
109-
.swagger(new SwaggerOptions("/swagger-ui")) // endpoint for swagger-ui
110-
.reDoc(new ReDocOptions("/redoc")) // endpoint for redoc
111-
.defaultDocumentation(doc -> {
112-
doc.header("authorization", String.class)
113-
.result("401");
114-
});
115-
return new OpenApiPlugin(options);
110+
private OpenApiPlugin openApi() {
111+
return new OpenApiPlugin(config ->
112+
config.withDocumentationPath("/api/openapi.json")
113+
.withDefinitionConfiguration((version, definition) ->
114+
definition.withInfo(info ->
115+
info.description("Plugin Jam Bot")
116+
.license("AGPL-3.0")
117+
)
118+
.withServer(server ->
119+
server.description("Lyna Backend")
120+
.url(configuration.api().url()))
121+
.withSecurity(security ->
122+
security.withApiKeyAuth("Authorization", "Authorization"))
123+
)
124+
);
125+
}
126+
127+
private SwaggerPlugin swagger() {
128+
return new SwaggerPlugin(conf -> {
129+
conf.setUiPath("/api/swagger");
130+
conf.setDocumentationPath("/api/openapi.json");
131+
});
116132
}
117133

118134
public void shutdown() {

bot/src/main/java/de/chojo/gamejam/api/exception/Interrupt.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@
66

77
package de.chojo.gamejam.api.exception;
88

9-
import io.javalin.http.HttpCode;
9+
import io.javalin.http.HttpStatus;
1010
import org.jetbrains.annotations.Contract;
1111

1212
public final class Interrupt {
1313
private Interrupt() {
1414
}
1515

16-
public static InterruptException create(String message, HttpCode httpCode) {
16+
public static InterruptException create(String message, HttpStatus httpCode) {
1717
return new InterruptException(message, httpCode);
1818
}
1919

2020
@Contract("_ -> fail")
2121
public static InterruptException notFound(String entity) {
22-
return create(String.format("%s not found.", entity), HttpCode.NOT_FOUND);
22+
return create(String.format("%s not found.", entity), HttpStatus.NOT_FOUND);
2323
}
24+
2425
@Contract(" -> fail")
2526
public static InterruptException forbidden() {
26-
return create("Endpoint forbidden", HttpCode.FORBIDDEN);
27+
return create("Endpoint forbidden", HttpStatus.FORBIDDEN);
2728
}
2829

2930
@Contract("null,_ -> fail")
@@ -43,7 +44,7 @@ public static void assertForbidden(boolean success) throws InterruptException {
4344

4445
@Contract(" -> fail")
4546
public static InterruptException noJam() {
46-
return create("No current or upcoming jam", HttpCode.NOT_FOUND);
47+
return create("No current or upcoming jam", HttpStatus.NOT_FOUND);
4748
}
4849

4950
@Contract("true -> fail")

bot/src/main/java/de/chojo/gamejam/api/exception/InterruptException.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66

77
package de.chojo.gamejam.api.exception;
88

9-
import io.javalin.http.HttpCode;
9+
import io.javalin.http.HttpStatus;
1010

1111
public class InterruptException extends Exception {
12-
private final HttpCode status;
12+
private final HttpStatus status;
1313

14-
public InterruptException(String message, HttpCode status) {
14+
public InterruptException(String message, HttpStatus status) {
1515
super(message);
1616
this.status = status;
1717
}
1818

19-
public InterruptException(HttpCode status) {
19+
public InterruptException(HttpStatus status) {
2020
super(status.getMessage());
2121
this.status = status;
2222
}
2323

2424
public int status() {
25-
return status.getStatus();
25+
return status.getCode();
2626
}
2727
}

bot/src/main/java/de/chojo/gamejam/api/v1/Server.java

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@
1010
import de.chojo.gamejam.data.dao.guild.jams.jam.teams.Team;
1111
import de.chojo.gamejam.server.ServerService;
1212
import de.chojo.gamejam.server.TeamServer;
13-
import io.javalin.http.HttpCode;
13+
import io.javalin.http.Context;
14+
import io.javalin.http.HttpStatus;
15+
import io.javalin.openapi.HttpMethod;
16+
import io.javalin.openapi.OpenApi;
17+
import io.javalin.openapi.OpenApiParam;
18+
import io.javalin.openapi.OpenApiResponse;
19+
import org.jetbrains.annotations.NotNull;
1420
import org.slf4j.Logger;
1521

1622
import java.io.IOException;
@@ -34,48 +40,77 @@ public Server(ServerService serverService, Teams teams) {
3440

3541
public void routes() {
3642
path("server", () -> {
37-
post("plugin/{token}", ctx -> {
38-
String token = ctx.pathParam("token");
39-
Optional<Team> team = teams.byToken(token);
40-
if (team.isEmpty()) {
41-
ctx.result("Team token not found");
42-
ctx.status(HttpCode.NOT_FOUND);
43-
return;
44-
}
43+
post("plugin/{token}", this::handle);
44+
});
45+
}
4546

46-
if (!ctx.contentType().equals("application/octet-stream")) {
47-
ctx.status(HttpCode.BAD_REQUEST);
48-
ctx.result("Use Content-Type: application/octet-stream");
49-
return;
50-
}
47+
@OpenApi(path = "/api/v1/server/plugin/{token}",
48+
description = "Upload a plugin for the team",
49+
headers = {
50+
@OpenApiParam(
51+
name = "Content-Type",
52+
required = true,
53+
example = "application/octet-stream",
54+
description = "The Content-Type. Has to be application/octet-stream.")},
55+
methods = {HttpMethod.POST},
56+
pathParams = {
57+
@OpenApiParam(
58+
name = "token",
59+
description = "The token of the team",
60+
required = true)},
61+
queryParams = {
62+
@OpenApiParam(
63+
name = "restart",
64+
description = "Whether the server should restart. Default false",
65+
example = "true")},
66+
responses = {
67+
@OpenApiResponse(status = "202", description = "When the plugin was uploaded"),
68+
@OpenApiResponse(status = "400", description = "When the wrong Content-Type was defined"),
69+
@OpenApiResponse(status = "404", description = "When the provided token is invalid"),
70+
@OpenApiResponse(status = "406", description = "When the server does not exist"),
71+
@OpenApiResponse(status = "406", description = "When the server does not exist"),
72+
@OpenApiResponse(status = "500", description = "When the plugin was not applied successfully"),
73+
}
74+
)
75+
private void handle(@NotNull Context ctx) {
76+
String token = ctx.pathParam("token");
77+
Optional<Team> team = teams.byToken(token);
78+
if (team.isEmpty()) {
79+
ctx.status(HttpStatus.NOT_FOUND);
80+
return;
81+
}
5182

52-
log.info("Received plugin upload request for {}", team.get());
83+
if (!"application/octet-stream".equals(ctx.contentType())) {
84+
ctx.status(HttpStatus.BAD_REQUEST);
85+
ctx.result("Use Content-Type: application/octet-stream");
86+
return;
87+
}
5388

54-
TeamServer teamServer = serverService.get(team.get());
89+
log.info("Received plugin upload request for {}", team.get());
5590

56-
if(!teamServer.exists()){
57-
ctx.result("Server does not exist");
58-
ctx.status(HttpCode.NOT_ACCEPTABLE);
59-
return;
60-
}
61-
var pluginFile = teamServer.plugins().resolve("plugin.jar");
62-
try (var in = ctx.bodyAsInputStream()) {
63-
log.info("Writing plugin to {}", pluginFile);
64-
Files.copy(in, pluginFile, StandardCopyOption.REPLACE_EXISTING);
65-
} catch (IOException e) {
66-
log.warn("Could not write file", e);
67-
ctx.status(HttpCode.INTERNAL_SERVER_ERROR);
68-
return;
69-
}
91+
TeamServer teamServer = serverService.get(team.get());
7092

71-
ctx.status(HttpCode.ACCEPTED);
72-
String restart = ctx.queryParam("restart");
73-
if ("true".equals(restart) && teamServer.running()) {
74-
teamServer.restart();
75-
} else if (teamServer.running()) {
76-
teamServer.send("say Plugin Updated");
77-
}
78-
});
79-
});
93+
if (!teamServer.exists()) {
94+
ctx.result("Server does not exist");
95+
ctx.status(HttpStatus.NOT_ACCEPTABLE);
96+
return;
97+
}
98+
var pluginFile = teamServer.plugins().resolve("plugin.jar");
99+
try (var in = ctx.bodyInputStream()) {
100+
log.info("Writing plugin to {}", pluginFile);
101+
Files.copy(in, pluginFile, StandardCopyOption.REPLACE_EXISTING);
102+
} catch (IOException e) {
103+
log.warn("Could not write file", e);
104+
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR);
105+
return;
106+
}
107+
108+
ctx.status(HttpStatus.ACCEPTED);
109+
String restart = ctx.queryParam("restart");
110+
if ("true".equals(restart) && teamServer.running()) {
111+
teamServer.restart();
112+
} else if (teamServer.running()) {
113+
teamServer.send("say Plugin Updated");
114+
}
80115
}
81116
}

0 commit comments

Comments
 (0)