Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/de/igslandstuhl/database/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import de.igslandstuhl.database.holidays.Holiday;
import de.igslandstuhl.database.server.Server;
import de.igslandstuhl.database.server.commands.Command;
import de.igslandstuhl.database.server.webserver.PostRequestHandler;
import de.igslandstuhl.database.utils.CommandLineUtils;

/**
Expand Down Expand Up @@ -94,6 +95,7 @@ public static void main(String[] args) throws Exception {
Server.getInstance().getConnection().createTables();

Holiday.setupCurrentSchoolYear();
PostRequestHandler.registerHandlers();

if (getInstance().runsWebServer()) {
Server.getInstance().getWebServer().start();
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/de/igslandstuhl/database/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,23 @@
import java.util.stream.Stream;

import de.igslandstuhl.database.server.commands.Command;
import de.igslandstuhl.database.server.webserver.requests.APIPostRequest;
import de.igslandstuhl.database.server.webserver.requests.GetRequest;
import de.igslandstuhl.database.server.webserver.requests.HttpHandler;

public class Registry<K, V> implements Closeable {
private static final Registry<String,Command> COMMAND_REGISTRY = new Registry<>();
private static final Registry<String,HttpHandler<APIPostRequest>> POST_HANDLER_REGISTRY = new Registry<>();
private static final Registry<String,HttpHandler<GetRequest>> GET_HANDLER_REGISTRY = new Registry<>();
public static Registry<String,Command> commandRegistry() {
return COMMAND_REGISTRY;
}
public static Registry<String, HttpHandler<APIPostRequest>> postRequestHandlerRegistry() {
return POST_HANDLER_REGISTRY;
}
public static Registry<String, HttpHandler<GetRequest>> getRequestHandlerRegistry() {
return GET_HANDLER_REGISTRY;
}

private final Map<K,V> objects = new HashMap<>();

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/de/igslandstuhl/database/api/APIObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package de.igslandstuhl.database.api;

public interface APIObject {
public String toJSON();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.igslandstuhl.database.api;

public enum GraduationLevel {
public enum GraduationLevel implements APIObject {
LEVEL0 (0, "Neustarter"),
LEVEL1 (1, "Starter"),
LEVEL2 (2, "Durchstarter"),
Expand Down Expand Up @@ -46,4 +46,9 @@ public static GraduationLevel of(int level) {
public static GraduationLevel initialValue() {
return LEVEL1;
}

@Override
public String toJSON() {
return String.valueOf(level);
}
}
6 changes: 5 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* Represents a room in the system.
* Each room has a label and a minimum level required for students to access it.
*/
public class Room {
public class Room implements APIObject {
private static final String[] SQL_FIELDS = {"label", "minimum_level"};
/**
* A map to store all rooms, keyed by their label.
Expand Down Expand Up @@ -229,5 +229,9 @@ public boolean equals(Object obj) {
return false;
return true;
}
@Override
public String toJSON() {
return "{\"label\": \""+label+ "\", \"minimumLevel\": \"" + minimumLevel + "\"}";
}

}
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/SchoolClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* Represents a school class with its associated subjects and students.
* Provides methods to fetch subjects and students from the database.
*/
public class SchoolClass {
public class SchoolClass implements APIObject {
/**
* SQL fields for the SchoolClass table.
* Used for database queries to retrieve class information.
Expand Down Expand Up @@ -321,5 +321,10 @@ public boolean equals(Object obj) {
return false;
return true;
}

@Override
public String toJSON() {
return "{\"id\": " + id + ", \"label\": \"" + label + "\", \"grade\": " + grade + "}";
}

}
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/SchoolYear.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Represents a school year with its associated properties and methods to manage it.
* Provides functionality to retrieve, add, and update school years in the database.
*/
public class SchoolYear {
public class SchoolYear implements APIObject {
/**
* SQL fields for the SchoolYear table.
* Used for database queries to retrieve school year information.
Expand Down Expand Up @@ -240,4 +240,9 @@ public boolean equals(Object obj) {
return false;
return true;
}

@Override
public String toJSON() {
return "{\"id\":" + id + ",\"label\":\"" + label + "\",\"weekCount\":" + weekCount + ",\"currentWeek\":" + currentWeek + "}";
}
}
10 changes: 10 additions & 0 deletions src/main/java/de/igslandstuhl/database/api/SpecialTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ public String toString() {
'}';
}

@Override
public String toJSON() {
return "{" +
"\"id\":" + getId() +
", \"name\": \"" + getName() + '"' +
", \"ratio\":" + ratio +
", \"subject\": \"" + subject.getName() + '"' +
'}';
}

/**
* Creates a SpecialTask object from SQL query result fields.
* This method is used to convert the result of a database query into a SpecialTask object.
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/de/igslandstuhl/database/api/Student.java
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ public Set<SubjectRequest> getCurrentRequests(Subject subject) {
* Adds a subject request for this student.
* @param subjectId the subject ID
* @param type the request type
* @deprecated Use addSubjectRequest(Subject, SubjectRequest) instead
*/
public void addSubjectRequest(int subjectId, String type) {
currentRequests.computeIfPresent(subjectId, (key, value) -> {
Expand All @@ -397,17 +398,34 @@ public void addSubjectRequest(int subjectId, String type) {
});
currentRequests.computeIfAbsent(subjectId, key -> new HashSet<>()).add(SubjectRequest.fromGermanTranslation(type));
}
/**
* Adds a subject request for this student.
* @param subject the corresponding subject
* @param subjectRequest the request
*/
public void addSubjectRequest(Subject subject, SubjectRequest subjectRequest) {
addSubjectRequest(subject.getId(), subjectRequest.getGermanTranslation());
}
/**
* Removes a subject request for this student.
* @param subjectId the subject ID
* @param type the request type to remove
* @deprecated Use removeSubjectRequest(Subject, SubjectRequest) instead
*/
public void removeSubjectRequest(int subjectId, String type) {
currentRequests.computeIfPresent(subjectId, (key, value) -> {
value.remove(SubjectRequest.fromGermanTranslation(type));
return value;
});
}
/**
* Removes a subject request from this student.
* @param subject the corresponding subject
* @param subjectRequest the request
*/
public void removeSubjectRequest(Subject subject, SubjectRequest subjectRequest) {
removeSubjectRequest(subject.getId(), subjectRequest.getGermanTranslation());
}

public void beginTask(Task task) throws SQLException {
if (task == null) {
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/Subject.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Represents a subject in the student database.
* Subjects can be added to grades and have associated topics.
*/
public class Subject {
public class Subject implements APIObject {
/**
* A map to cache subjects by their unique identifier.
* This helps avoid repeated database queries for the same subject.
Expand Down Expand Up @@ -282,5 +282,10 @@ public boolean equals(Object obj) {
return false;
return true;
}

@Override
public String toJSON() {
return "{\"id\": " + id + ", \"name\": \"" + name + "\"}";
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.igslandstuhl.database.api;

public enum SubjectRequest {
public enum SubjectRequest implements APIObject {
HELP ("hilfe"),
PARTNER ("partner"),
EXPERIMENT ("betreuung"),
Expand All @@ -23,4 +23,9 @@ public static SubjectRequest fromGermanTranslation(String translation) {
}
throw new IllegalArgumentException("No matching SubjectRequest for translation: " + translation);
}

@Override
public String toJSON() {
return '"' + germanTranslation + '"';
}
}
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Represents a task in the student database.
* Tasks are associated with topics and have different levels of difficulty.
*/
public class Task {
public class Task implements APIObject {
public static final int STATUS_NOT_STARTED = 0;
public static final int STATUS_IN_PROGRESS = 1;
public static final int STATUS_COMPLETED = 2;
Expand Down Expand Up @@ -285,5 +285,10 @@ public static Task fromSerialized(Topic topic, String serialized) throws SQLExce
TaskLevel level = TaskLevel.get(Integer.parseInt(parts[1]));
return addTask(topic, name, level);
}

@Override
public String toJSON() {
return "{\"id\": " + id + ", \"topic\": " + topic + ", \"name\": \"" + name + "\", \"niveau\": " + niveau + ", \"number\": \"" + getNumber() + "\", \"ratio\": " + getRatio() + "}";
}

}
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/TaskLevel.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Each level has a specific ratio that indicates the proportion of the progress
* that can be achieved at that level.
*/
public enum TaskLevel {
public enum TaskLevel implements APIObject {
LEVEL1 (1, "Niveau 1"),
LEVEL2 (2, "Niveau 2"),
LEVEL3 (3, "Niveau 3"),
Expand Down Expand Up @@ -73,4 +73,9 @@ public double getRatio() {
public String toString() {
return this == SPECIAL ? "Special" : String.valueOf(number);
}

@Override
public String toJSON() {
return this == SPECIAL ? "\"Special\"" : String.valueOf(number);
}
}
7 changes: 6 additions & 1 deletion src/main/java/de/igslandstuhl/database/api/Topic.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* Represents a topic in the student database.
* Topics are associated with subjects and contain tasks of varying difficulty levels.
*/
public class Topic {
public class Topic implements APIObject {
/**
* SQL fields for the Topic table.
* Used for database queries to retrieve topic information.
Expand Down Expand Up @@ -300,6 +300,11 @@ public String toString() {
return "{\"id\":" + id + ", \"name\": \"" + name + "\", \"subject\": " + subject + ", \"ratio\": " + ratio + ", \"grade\": " + grade
+ ", \"tasks\": " + getTaskIds() + ", \"number\": " + number + "}";
}
@Override
public String toJSON() {
return "{\"id\":" + id + ", \"name\": \"" + name + "\", \"subject\": " + subject + ", \"ratio\": " + ratio + ", \"grade\": " + grade
+ ", \"tasks\": " + getTaskIds() + ", \"number\": " + number + "}";
}
/**
* Adds a new topic to the database.
* This method executes a secure SQL process to insert a new topic with the provided parameters.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/igslandstuhl/database/api/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* Abstract class representing a user in the system.
* This class provides methods to check user roles, retrieve password hashes, and convert user data to JSON format.
*/
public abstract class User {
public abstract class User implements APIObject {
public static final User ANONYMOUS = new User() {
@Override
public boolean isTeacher() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.igslandstuhl.database.api.results;

public class GenerationResult<T> {
public abstract class GenerationResult<T> {
private final T entity;
private final String password;

Expand All @@ -16,4 +16,6 @@ public T getEntity() {
public String getPassword() {
return password;
}

public abstract String toCSVRow();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ public StudentGenerationResult(Student student, String password) {
public Student getStudent() {
return getEntity();
}
@Override
public String toCSVRow() {
return new StringBuilder().append(this.getStudent().getId()).append(",")
.append(this.getStudent().getFirstName()).append(",")
.append(this.getStudent().getLastName()).append(",")
.append(this.getStudent().getEmail()).append(",")
.append(this.getPassword()).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,13 @@ public String getLastName() {
public String getEmail() {
return getTeacher().getEmail();
}

@Override
public String toCSVRow() {
return new StringBuilder().append(this.getId()).append(",")
.append(this.getFirstName()).append(",")
.append(this.getLastName()).append(",")
.append(this.getEmail()).append(",")
.append(this.getPassword()).toString();
}
}
11 changes: 6 additions & 5 deletions src/main/java/de/igslandstuhl/database/server/WebServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import de.igslandstuhl.database.server.webserver.GetRequest;
import de.igslandstuhl.database.server.webserver.GetResponse;
import de.igslandstuhl.database.server.webserver.HttpHeader;
import de.igslandstuhl.database.server.webserver.PostRequest;
import de.igslandstuhl.database.server.webserver.PostRequestHandler;
import de.igslandstuhl.database.server.webserver.PostResponse;
import de.igslandstuhl.database.server.webserver.SessionManager;
import de.igslandstuhl.database.server.webserver.requests.GetRequest;
import de.igslandstuhl.database.server.webserver.requests.PostRequest;
import de.igslandstuhl.database.server.webserver.responses.GetResponse;
import de.igslandstuhl.database.server.webserver.responses.HttpResponse;
import de.igslandstuhl.database.server.webserver.responses.PostResponse;

/**
* A simple HTTPS web server that handles various requests related to student data.
Expand Down Expand Up @@ -152,7 +153,7 @@ void handlePost(String headerString, InputStream in, PrintStream out) throws IOE
body = URLDecoder.decode(raw, bodyCharset.name());
}
PostRequest parsedRequest = new PostRequest(postHeader, body, clientIp, secure);
PostResponse response = Server.getInstance().getWebServer().getSessionManager().validateSession(parsedRequest) ? PostRequestHandler.getInstance().handlePostRequest(parsedRequest) : PostResponse.forbidden("Forbidden: session manipulation or ratelimit", parsedRequest);
HttpResponse response = Server.getInstance().getWebServer().getSessionManager().validateSession(parsedRequest) ? PostRequestHandler.getInstance().handlePostRequest(parsedRequest) : PostResponse.forbidden("Forbidden: session manipulation or ratelimit", parsedRequest);
response.respond(out);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.igslandstuhl.database.server.webserver;

import de.igslandstuhl.database.api.User;

public enum AccessLevel {
PUBLIC, USER, STUDENT, TEACHER, ADMIN, NONE;

public boolean hasAccess(User user) {
if (this == PUBLIC) return true;
else if (user == null || user == User.ANONYMOUS) return false;
else if (this == USER || this == STUDENT) return true;
else if (user.isStudent()) return false;
else if (this == TEACHER) return true;
else if (user.isTeacher()) return false;
else return this == ADMIN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public enum ContentType {
JAVASCRIPT ("text/javascript"),
CSS ("text/css"),
PNG ("image/png"),
JSON ("text/json")
JSON ("text/json"),
CSV ("text/csv")
;
/**
* The name of the content type, used in HTTP headers.
Expand Down
Loading
Loading