Skip to content

Commit

Permalink
Merge pull request #479 from softwareconstruction240/reduce-endpoint-…
Browse files Browse the repository at this point in the history
…dependencies

Remove Server's dependency on Controller classes
  • Loading branch information
ThanGerlek authored Nov 25, 2024
2 parents 368a8fa + 33829fa commit 16eec28
Show file tree
Hide file tree
Showing 5 changed files with 433 additions and 156 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>edu.byu.cs.server.Server</mainClass>
<mainClass>Main</mainClass>
</transformer>
</transformers>
</configuration>
Expand All @@ -169,7 +169,7 @@
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>edu.byu.cs.server.Server</mainClass>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
Expand Down
103 changes: 103 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import edu.byu.cs.autograder.GradingException;
import edu.byu.cs.server.endpointprovider.EndpointProvider;
import edu.byu.cs.server.endpointprovider.EndpointProviderImpl;
import edu.byu.cs.dataAccess.DaoService;
import edu.byu.cs.dataAccess.DataAccessException;
import edu.byu.cs.properties.ApplicationProperties;
import edu.byu.cs.server.Server;
import edu.byu.cs.service.SubmissionService;
import edu.byu.cs.util.ResourceUtils;
import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

public class Main {
private static Logger LOGGER = LoggerFactory.getLogger(Main.class);

private static EndpointProvider endpointProvider = new EndpointProviderImpl();

public static void main(String[] args) {
ResourceUtils.copyResourceFiles("phases", new File(""));
setupProperties(args);

try {
DaoService.initializeSqlDAOs();
} catch (DataAccessException e) {
LOGGER.error("Error setting up database", e);
throw new RuntimeException(e);
}

new Server(endpointProvider).start(8080);

try {
SubmissionService.reRunSubmissionsInQueue();
} catch (IOException | DataAccessException | GradingException e) {
LOGGER.error("Error rerunning submissions already in queue", e);
}
}

private static void setupProperties(String[] args) {
Options options = getOptions();

Properties properties = new Properties();

CommandLineParser parser = new DefaultParser();
try {
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption("db-host")) {
properties.setProperty("db-host", cmd.getOptionValue("db-host"));
}
if (cmd.hasOption("db-port")) {
properties.setProperty("db-port", cmd.getOptionValue("db-port"));
}
if (cmd.hasOption("db-name")) {
properties.setProperty("db-name", cmd.getOptionValue("db-name"));
}
if (cmd.hasOption("db-user")) {
properties.setProperty("db-user", cmd.getOptionValue("db-user"));
}
if (cmd.hasOption("db-pass")) {
properties.setProperty("db-pass", cmd.getOptionValue("db-pass"));
}
if (cmd.hasOption("frontend-url")) {
properties.setProperty("frontend-url", cmd.getOptionValue("frontend-url"));
}
if (cmd.hasOption("cas-callback-url")) {
properties.setProperty("cas-callback-url", cmd.getOptionValue("cas-callback-url"));
}
if (cmd.hasOption("canvas-token")) {
properties.setProperty("canvas-token", cmd.getOptionValue("canvas-token"));
}
if (cmd.hasOption("use-canvas")) {
properties.setProperty("use-canvas", cmd.getOptionValue("use-canvas"));
}
if (cmd.hasOption("disable-compilation")) {
properties.setProperty("run-compilation", "false");
}
} catch (ParseException e) {
throw new RuntimeException("Error parsing command line arguments", e);
}

ApplicationProperties.loadProperties(properties);
}

private static Options getOptions() {
Options options = new Options();
options.addOption(null, "db-host", true, "Database Host");
options.addOption(null, "db-port", true, "Database Port");
options.addOption(null, "db-name", true, "Database Name");
options.addOption(null, "db-user", true, "Database User");
options.addOption(null, "db-pass", true, "Database Password");
options.addOption(null, "frontend-url", true, "Frontend URL");
options.addOption(null, "cas-callback-url", true, "CAS Callback URL");
options.addOption(null, "canvas-token", true, "Canvas Token");
options.addOption(null, "use-canvas", true, "Using Canvas");
options.addOption(null, "disable-compilation", false, "Turn off student code compilation");
return options;
}

}
207 changes: 53 additions & 154 deletions src/main/java/edu/byu/cs/server/Server.java
Original file line number Diff line number Diff line change
@@ -1,224 +1,123 @@
package edu.byu.cs.server;

import edu.byu.cs.autograder.GradingException;
import edu.byu.cs.controller.WebSocketController;
import edu.byu.cs.dataAccess.DaoService;
import edu.byu.cs.dataAccess.DataAccessException;
import edu.byu.cs.properties.ApplicationProperties;
import edu.byu.cs.service.SubmissionService;
import edu.byu.cs.util.ResourceUtils;
import org.apache.commons.cli.*;
import edu.byu.cs.server.endpointprovider.EndpointProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import static edu.byu.cs.controller.AdminController.*;
import static edu.byu.cs.controller.AuthController.*;
import static edu.byu.cs.controller.CasController.*;
import static edu.byu.cs.controller.ConfigController.*;
import static edu.byu.cs.controller.SubmissionController.*;
import static edu.byu.cs.controller.UserController.*;
import static spark.Spark.*;

public class Server {

private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
private final EndpointProvider provider;

public Server(EndpointProvider endpointProvider) {
this.provider = endpointProvider;
}

public static int setupEndpoints(int port) {
public int start(int desiredPort) {
int chosenPort = setupEndpoints(desiredPort);
LOGGER.info("Server started on port {}", chosenPort);
return chosenPort;
}

private int setupEndpoints(int port) {
port(port);

webSocket("/ws", WebSocketController.class);
webSocketIdleTimeoutMillis(300000);

staticFiles.location("/frontend/dist");

before((request, response) -> {
response.header("Access-Control-Allow-Headers", "Authorization,Content-Type");
response.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
response.header("Access-Control-Allow-Credentials", "true");
response.header("Access-Control-Allow-Origin", ApplicationProperties.frontendUrl());
});
before(provider.beforeAll());

path("/auth", () -> {
get("/callback", callbackGet);
get("/login", loginGet);
get("/callback", provider.callbackGet());
get("/login", provider.loginGet());

// all routes after this point require authentication
post("/logout", logoutPost);
post("/logout", provider.logoutPost());
});

path("/api", () -> {
before("/*", (req, res) -> {
if (!req.requestMethod().equals("OPTIONS"))
verifyAuthenticatedMiddleware.handle(req, res);
if (!req.requestMethod().equals("OPTIONS")) provider.verifyAuthenticatedMiddleware().handle(req, res);
});

patch("/repo", repoPatch);
patch("/repo", provider.repoPatch());

get("/submit", submitGet);
post("/submit", submitPost);
get("/submit", provider.submitGet());
post("/submit", provider.submitPost());

get("/latest", latestSubmissionForMeGet);
get("/latest", provider.latestSubmissionForMeGet());

get("/submission", submissionXGet);
get("/submission/:phase", submissionXGet);
get("/submission", provider.submissionXGet());
get("/submission/:phase", provider.submissionXGet());

get("/me", meGet);
get("/me", provider.meGet());

get("/config", getConfigStudent);
get("/config", provider.getConfigStudent());

path("/admin", () -> {
before("/*", (req, res) -> {
if (!req.requestMethod().equals("OPTIONS"))
verifyAdminMiddleware.handle(req, res);
if (!req.requestMethod().equals("OPTIONS")) provider.verifyAdminMiddleware().handle(req, res);
});

patch("/repo/:netId", repoPatchAdmin);
patch("/repo/:netId", provider.repoPatchAdmin());

get("/repo/history", repoHistoryAdminGet);
get("/repo/history", provider.repoHistoryAdminGet());

get("/users", usersGet);
get("/users", provider.usersGet());

post("/submit", adminRepoSubmitPost);
post("/submit", provider.adminRepoSubmitPost());

path("/submissions", () -> {
post("/approve", approveSubmissionPost);
post("/approve", provider.approveSubmissionPost());

get("/latest", latestSubmissionsGet);
get("/latest", provider.latestSubmissionsGet());

get("/latest/:count", latestSubmissionsGet);
get("/latest/:count", provider.latestSubmissionsGet());

get("/active", submissionsActiveGet);
get("/active", provider.submissionsActiveGet());

get("/student/:netId", studentSubmissionsGet);
get("/student/:netId", provider.studentSubmissionsGet());

post("/rerun", submissionsReRunPost);
post("/rerun", provider.submissionsReRunPost());
});

get("/test_mode", testModeGet);
get("/test_mode", provider.testModeGet());

get("/analytics/commit", commitAnalyticsGet);
get("/analytics/commit", provider.commitAnalyticsGet());

get("/analytics/commit/:option", commitAnalyticsGet);
get("/analytics/commit/:option", provider.commitAnalyticsGet());

get("/honorChecker/zip/:section", honorCheckerZipGet);
get("/honorChecker/zip/:section", provider.honorCheckerZipGet());

get("/sections", sectionsGet);
get("/sections", provider.sectionsGet());

path("/config", () -> {
get("", getConfigAdmin);
get("", provider.getConfigAdmin());

post("/phases", updateLivePhases);
post("/phases/shutdown", scheduleShutdown);
post("/banner", updateBannerMessage);
post("/phases", provider.updateLivePhases());
post("/phases/shutdown", provider.scheduleShutdown());
post("/banner", provider.updateBannerMessage());

post("/courseIds", updateCourseIdsPost);
get("/courseIds", updateCourseIdsUsingCanvasGet);
post("/courseIds", provider.updateCourseIdsPost());
get("/courseIds", provider.updateCourseIdsUsingCanvasGet());

post("/penalties", updatePenalties);
post("/penalties", provider.updatePenalties());
});
});
});

// spark's notFound method does not work
get("/*", (req, res) -> {
if (req.pathInfo().equals("/ws"))
return null;

String urlParams = req.queryString();
urlParams = urlParams == null ? "" : "?" + urlParams;
res.redirect("/" + urlParams, 302);
return null;
});
init();
get("/*", provider.defaultGet());

return port();
}
after(provider.afterAll());

private static void setupProperties(String[] args) {
Options options = getOptions();

Properties properties = new Properties();

CommandLineParser parser = new DefaultParser();
try {
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption("db-host")) {
properties.setProperty("db-host", cmd.getOptionValue("db-host"));
}
if (cmd.hasOption("db-port")) {
properties.setProperty("db-port", cmd.getOptionValue("db-port"));
}
if (cmd.hasOption("db-name")) {
properties.setProperty("db-name", cmd.getOptionValue("db-name"));
}
if (cmd.hasOption("db-user")) {
properties.setProperty("db-user", cmd.getOptionValue("db-user"));
}
if (cmd.hasOption("db-pass")) {
properties.setProperty("db-pass", cmd.getOptionValue("db-pass"));
}
if (cmd.hasOption("frontend-url")) {
properties.setProperty("frontend-url", cmd.getOptionValue("frontend-url"));
}
if (cmd.hasOption("cas-callback-url")) {
properties.setProperty("cas-callback-url", cmd.getOptionValue("cas-callback-url"));
}
if (cmd.hasOption("canvas-token")) {
properties.setProperty("canvas-token", cmd.getOptionValue("canvas-token"));
}
if (cmd.hasOption("use-canvas")) {
properties.setProperty("use-canvas", cmd.getOptionValue("use-canvas"));
}
if (cmd.hasOption("disable-compilation")) {
properties.setProperty("run-compilation", "false");
}
} catch (ParseException e) {
throw new RuntimeException("Error parsing command line arguments", e);
}

ApplicationProperties.loadProperties(properties);
}

private static Options getOptions() {
Options options = new Options();
options.addOption(null, "db-host", true, "Database Host");
options.addOption(null, "db-port", true, "Database Port");
options.addOption(null, "db-name", true, "Database Name");
options.addOption(null, "db-user", true, "Database User");
options.addOption(null, "db-pass", true, "Database Password");
options.addOption(null, "frontend-url", true, "Frontend URL");
options.addOption(null, "cas-callback-url", true, "CAS Callback URL");
options.addOption(null, "canvas-token", true, "Canvas Token");
options.addOption(null, "use-canvas", true, "Using Canvas");
options.addOption(null, "disable-compilation", false, "Turn off student code compilation");
return options;
}


public static void main(String[] args) {
ResourceUtils.copyResourceFiles("phases", new File(""));
setupProperties(args);

try {
DaoService.initializeSqlDAOs();
} catch (DataAccessException e) {
LOGGER.error("Error setting up database", e);
throw new RuntimeException(e);
}

int port = setupEndpoints(8080);

LOGGER.info("Server started on port {}", port);
init();

try {
SubmissionService.reRunSubmissionsInQueue();
} catch (IOException | DataAccessException | GradingException e) {
LOGGER.error("Error rerunning submissions already in queue", e);
}
return port();
}

}
Loading

0 comments on commit 16eec28

Please sign in to comment.