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
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ public static void registerHandlers() {
return PostResponse.unauthorized("Wrong credentials!", rq);
}
});
HttpHandler.registerPostRequestHandler("/editor", AccessLevel.ADMIN, (rq) -> {
return PostResponse.redirect("/editor", rq);
});


HttpHandler.registerPostRequestHandler("/add-students", AccessLevel.ADMIN, (rq) ->
handleBatchInsertCSV(rq, "students", ContentType.CSV, t -> {
try {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/html/admin/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ <h2>Admin Optionen</h2>
<li><a href="/manage_subjects">Fächer verwalten</a></li>
<li><a href="/manage_rooms">Räume verwalten</a></li>
<li><a href="/modules">Module verwalten</a></li>
<li><a href="/editor">HTML Editor</a></li>
</ul>
</section>
%[file_import;header=Datenimport aus Lehrerplanungstool;note=Hinweis: Stellen Sie sicher, dass das jeweilige Fach bereits existiert, und der jeweiligen Klassenstufe zugeordnet ist.;uploadUrl=/lpt-file]
Expand Down
18 changes: 18 additions & 0 deletions src/main/resources/html/admin/editor.html
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add %[site;title=HTML Editor;content=!FOLLOWS] at the beginning?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also maybe add a text field where you can put in the file name it should be saved as.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Schlaumeier5 Thanks for the review! I’ve added the template header to editor.html and registered a stub POST handler for /editor in PostRequestHandler.java as suggested.
The POST handler currently redirects back to /editor, and can be extended later with the actual save logic.
Please let me know if you’d like any adjustments or a different approach.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
%[site;title=HTML Editor;content=!FOLLOWS]

<h2>HTML Editor</h2>

<form method="post" action="/editor">

<label for="filename">File name to save as:</label><br>
<input type="text" id="filename" name="filename" placeholder="e.g. login.html" required>

<br><br>

<label for="content">HTML Content:</label><br>
<textarea name="content" rows="20" cols="80"></textarea>

<br><br>

<button type="submit">Save</button>
</form>
8 changes: 8 additions & 0 deletions src/main/resources/meta/paths/get_paths.json
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registering post handlers happens in Java code, see here:

public static void registerHandlers() {
HttpHandler.registerPostRequestHandler("/login", AccessLevel.PUBLIC, (rq) -> {
String username = prepare(rq.getString("username"), false);
// Do not sanitize / url-decode password to allow special characters like %
// This is safe as we calculate the hash value anyways
String password = rq.getString("password");
// Check login credentials in the database
if (Server.getInstance().isValidUser(username, password)) {
SessionManager manager = Server.getInstance().getWebServer().getSessionManager();
Session session = manager.getSession(rq);
manager.addSessionUser(session, username);
return PostResponse.ok("Login successful", ContentType.TEXT_PLAIN, rq, session.createSessionCookie());
} else {
return PostResponse.unauthorized("Wrong credentials!", rq);
}
});
HttpHandler.registerPostRequestHandler("/add-students", AccessLevel.ADMIN, (rq) ->
handleBatchInsertCSV(rq, "students", ContentType.CSV, t -> {
try {
return Student.generateStudentsFromCSV(t);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}, PostRequestHandler::csvResult)
);
HttpHandler.registerPostRequestHandler("/add-teachers", AccessLevel.ADMIN, (rq) ->
handleBatchInsertCSV(rq, "teachers", ContentType.CSV, t -> {
try {
return Teacher.generateTeachersFromCSV(t);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}, PostRequestHandler::csvResult)
);
HttpHandler.registerPostRequestHandler("/add-rooms", AccessLevel.ADMIN, (rq) ->
handleBatchInsertCSV(rq, "rooms", ContentType.JSON, t -> {
try {
return Room.generateRoomsFromCSV(t);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}, Arrays::toString)
);
HttpHandler.registerPostRequestHandler("/add-teacher", AccessLevel.ADMIN, (rq) -> {
String firstName = prepare(rq.getString("firstName"));
String lastName = prepare(rq.getString("lastName"));
String email = prepare(rq.getString("email"), false);
String password = Teacher.generateRandomPassword(12, (rq.getContentLength() << 4 + firstName.length() + lastName.length()) << 7 + System.currentTimeMillis() * new Random().nextInt());
Teacher teacher = Teacher.registerTeacher(firstName, lastName, email, password);
return PostResponse.ok(teacher.toString().replace("}", "") + ", \"password\": " + password + "}", ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/add-subject", AccessLevel.ADMIN, (rq) -> {
Subject.addSubject(rq.getString("name"));
return PostResponse.redirect("/manage_subjects", rq);
});
HttpHandler.registerPostRequestHandler("/add-class", AccessLevel.ADMIN, (rq) -> {
SchoolClass.addClass(rq.getString("className"), rq.getInt("grade"));
return PostResponse.redirect("/manage_subjects", rq);
});
HttpHandler.registerPostRequestHandler("/lpt-file", AccessLevel.ADMIN, (rq) -> {
String file = prepare(rq.getBodyAsString().replaceFirst("file=", "").replace("Â", ""));
Application.getInstance().readFile(file);
return PostResponse.ok("File data stored", ContentType.TEXT_PLAIN, rq);
});
HttpHandler.registerPostRequestHandler("/subject-request", AccessLevel.USER, (rq) -> {
Student student = rq.getCurrentStudent();
Subject subject = rq.getSubject();
SubjectRequest subjectRequest = rq.getSubjectRequest();
if (student != null) {
if (rq.getBoolean("remove")) {
student.removeSubjectRequest(subject, subjectRequest);
return PostResponse.ok("Removed request", ContentType.TEXT_PLAIN, rq);
} else {
student.addSubjectRequest(subject, subjectRequest);
return PostResponse.ok("Added request", ContentType.TEXT_PLAIN, rq);
}
} else {
return PostResponse.unauthorized(rq);
}
});
HttpHandler.registerPostRequestHandler("/current-topic", AccessLevel.USER, (rq) -> {
Student student = rq.getCurrentStudent();
Subject subject = rq.getSubject();
if (student == null) return PostResponse.unauthorized(rq);
Topic topic = student.getCurrentTopic(subject);
if (topic == null) return PostResponse.badRequest("No current topic for this subject.", rq);
return PostResponse.ok(topic.toJSON(), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/change-current-topic", AccessLevel.TEACHER, (rq) -> {
Student student = rq.getCurrentStudent();
if (student == null) return PostResponse.unauthorized(rq);
Subject subject = rq.getSubject();
Topic topic = rq.getTopic();
if (subject == null || topic == null) return PostResponse.badRequest("Subject or topic id not found", rq);
student.setCurrentTopic(subject, topic);
return PostResponse.ok("Current topic changed successfully", ContentType.TEXT_PLAIN, rq);
});
HttpHandler.registerPostRequestHandler("/tasks", AccessLevel.USER, (rq) -> {
return PostResponse.ok(JSONUtils.toJSON(rq.getTaskList()), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/update-room", AccessLevel.USER, (rq) -> {
Student student = rq.getCurrentStudent();
if (student == null) return PostResponse.unauthorized(rq);
Room room = rq.getRoom();
if (room == null) return PostResponse.badRequest("Room not found", rq);
student.setCurrentRoom(room);
return PostResponse.ok("Changed current room", ContentType.TEXT_PLAIN, rq);
});
HttpHandler.registerPostRequestHandler("/begin-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_IN_PROGRESS));
HttpHandler.registerPostRequestHandler("/complete-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_COMPLETED));
HttpHandler.registerPostRequestHandler("/cancel-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_NOT_STARTED));
HttpHandler.registerPostRequestHandler("/reopen-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_NOT_STARTED));
HttpHandler.registerPostRequestHandler("/lock-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_LOCKED));
HttpHandler.registerPostRequestHandler("/student-data", AccessLevel.TEACHER, PostRequestHandler::handleStudentGetData);
HttpHandler.registerPostRequestHandler("/rooms", AccessLevel.TEACHER, PostRequestHandler::handleStudentGetData);
HttpHandler.registerPostRequestHandler("/student-subjects", AccessLevel.TEACHER, PostRequestHandler::handleStudentGetData);
HttpHandler.registerPostRequestHandler("/teacher-classes", AccessLevel.ADMIN, PostRequestHandler::handleTeacherGetData);
HttpHandler.registerPostRequestHandler("/teacher-subjects", AccessLevel.ADMIN, PostRequestHandler::handleTeacherGetData);
HttpHandler.registerPostRequestHandler("/student-list", AccessLevel.TEACHER, (rq) -> {
SchoolClass schoolClass = rq.getSchoolClass();
if (schoolClass == null) return PostResponse.notFound("School class not found", rq);
if (rq.getUser().isTeacher() && !rq.getUser().asTeacher().getClassIds().contains(schoolClass.getId()))
return PostResponse.forbidden("You are not allowed to access this class's student list.", rq);
List<Student> students = schoolClass.getStudents();
return PostResponse.ok(
JSONUtils.toJSON(students, (student, builder) -> {
builder
.addProperty("id", student.getId())
.addProperty("name", student.getFirstName() + " " + student.getLastName())
.addProperty("actionRequired", student.isActionRequired())
.addProperty("graduationLevel", student.getGraduationLevel())
.addProperty("room", student.getCurrentRoom() != null ? student.getCurrentRoom().getLabel() : "None");
if (rq.getJson().containsKey("subjectId") && rq.getSubject() != null) {
Set<SubjectRequest> subjectRequests = student.getCurrentRequests(rq.getSubject());
builder.addProperty("experiment",subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXPERIMENT))
.addProperty("help", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.HELP))
.addProperty("test", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXAM))
.addProperty("partner", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.PARTNER));
}
}),
ContentType.JSON, rq
);
});
HttpHandler.registerPostRequestHandler("/get-students-by-room", AccessLevel.TEACHER, (rq) -> {
Room room = rq.getRoom();
List<Student> students = Student.getByRoom(room);
return PostResponse.ok(
JSONUtils.toJSON(students, (student, builder) -> {
builder
.addProperty("id", student.getId())
.addProperty("name", student.getFirstName() + " " + student.getLastName())
.addProperty("actionRequired", student.isActionRequired())
.addProperty("graduationLevel", student.getGraduationLevel())
.addProperty("room", student.getCurrentRoom() != null ? student.getCurrentRoom().getLabel() : "None");
if (rq.getJson().containsKey("subjectId") && rq.getSubject() != null) {
Set<SubjectRequest> subjectRequests = student.getCurrentRequests(rq.getSubject());
builder.addProperty("experiment",subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXPERIMENT))
.addProperty("help", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.HELP))
.addProperty("test", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXAM))
.addProperty("partner", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.PARTNER));
}
}),
ContentType.JSON, rq
);
});
HttpHandler.registerPostRequestHandler("/grade-list", AccessLevel.PUBLIC, (rq) -> {
return PostResponse.ok(JSONUtils.toJSON(rq.getSubject().getGrades()), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/topic-list", AccessLevel.STUDENT, (rq) -> {
return PostResponse.ok(JSONUtils.toJSON(rq.getSubject().getTopics(rq.getInt("grade"))), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/class-subjects", AccessLevel.ADMIN, (rq) -> {
SchoolClass schoolClass = rq.getSchoolClass();
if (schoolClass == null) return PostResponse.notFound("School class not found", rq);
List<Subject> subjects = schoolClass.getSubjects();
return PostResponse.ok(JSONUtils.toJSON(subjects, (subject, builder) -> {
builder.addProperty("id", subject.getId()).addProperty("name", subject.getName());
}), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/search-partner", AccessLevel.USER, (rq) -> {
SchoolClass schoolClass = rq.getSchoolClass();
Subject subject = rq.getSubject();
Topic topic = rq.getTopic();
Student student = rq.getCurrentStudent();
List<Student> students = Student.getAll().stream()
.filter((s) -> s.getSchoolClass().getGrade() == schoolClass.getGrade())
.filter((s) -> s.getCurrentTopic(subject).equals(topic)
&& s.getSelectedTasks().stream().filter((t) -> t.getTopic().equals(topic)).anyMatch((t) -> student.getSelectedTasks().contains(t))
&& s.getCurrentRequests(subject).stream().anyMatch((r) -> r == SubjectRequest.PARTNER))
.toList();
return PostResponse.ok(JSONUtils.toJSON(students, (partner, builder) -> {
builder.addProperty("id", partner.getId())
.addProperty("name", partner.getFirstName() + " " + partner.getLastName())
.addProperty("room", partner.getCurrentRoom() != null ? partner.getCurrentRoom().getLabel() : "None");
}), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/delete-subject", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Subject>() {}, PostResponse.redirect("/manage_subjects", rq), (subject) -> subject.delete())
);
HttpHandler.registerPostRequestHandler("/edit-subject", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Subject>() {}, PostResponse.redirect("/manage_subjects", rq), (subject) -> subject.edit(prepare(rq.getString("name"))))
);
HttpHandler.registerPostRequestHandler("/delete-classs", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<SchoolClass>() {}, PostResponse.redirect("/manage_classes", rq), (schoolClass) -> schoolClass.delete())
);
HttpHandler.registerPostRequestHandler("/edit-class", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<SchoolClass>() {}, PostResponse.redirect("/manage_classes", rq), (schoolClass) -> schoolClass.edit(prepare(rq.getString("name")), rq.getInt("grade")))
);
HttpHandler.registerPostRequestHandler("/add-subject-to-class", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<SchoolClass>() {}, PostResponse.redirect("/class", rq), (schoolClass) -> schoolClass.addSubject(rq.getSubject()))
);
HttpHandler.registerPostRequestHandler("/add-grade-to-subject", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Subject>() {}, PostResponse.redirect("/subject", rq), (subject) -> subject.addToGrade(rq.getInt("grade")))
);
HttpHandler.registerPostRequestHandler("/delete-grade-from-subject", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Subject>() {}, PostResponse.redirect("/subject", rq), (subject) -> subject.removeFromGrade(rq.getInt("grade")))
);
HttpHandler.registerPostRequestHandler("/delete-topics", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Subject>() {}, PostResponse.redirect("/subject", rq), (subject) -> subject.getTopics(rq.getInt("grade")).forEach((topic) -> {
try {
topic.delete();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}))
);
HttpHandler.registerPostRequestHandler("/add-class-to-teacher", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Teacher>() {}, PostResponse.redirect("/teacher", rq), (teacher) -> teacher.addClass(rq.getSchoolClass()))
);
HttpHandler.registerPostRequestHandler("/add-subject-to-teacher", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Teacher>() {}, PostResponse.redirect("/teacher", rq), (teacher) -> teacher.addSubject(rq.getSubject()))
);
HttpHandler.registerPostRequestHandler("/change-graduation-level", AccessLevel.ADMIN, (rq) ->
handleObjectAction(rq, new TypeToken<Student>() {}, PostResponse.ok("Successfully changed graduation level", ContentType.TEXT_PLAIN, rq), (student) -> student.changeGraduationLevel(rq.getInt("graduationLevel")))
);
HttpHandler.registerPostRequestHandler("/get-module", AccessLevel.USER, (rq) -> {
return PostResponse.ok(Registry.moduleRegistry().get(rq.getString("key")).toJSON(), ContentType.JSON, rq);
});
HttpHandler.registerPostRequestHandler("/toggle-module", AccessLevel.ADMIN, (rq) -> {
Registry.moduleRegistry().get(rq.getString("key")).toggle();
return PostResponse.ok("Module toggled", ContentType.TEXT_PLAIN, rq);
});
HttpHandler.registerPostRequestHandler("/toggle-module-setting", AccessLevel.ADMIN, (rq) -> {
String[] key = rq.getString("key").split(":");
Registry.moduleRegistry().get(key[0]).toggleSetting(key[1]);
return PostResponse.ok("Module setting toggled", ContentType.TEXT_PLAIN, rq);
});
HttpHandler.registerPostRequestHandler("/student-results-csv", AccessLevel.TEACHER, (rq) -> {
Student student = rq.getCurrentStudent();
if (student == null) return PostResponse.badRequest("There is no current student", rq);
return PostResponse.ok(student.getResultsCSV(), ContentType.CSV, rq);
});
HttpHandler.registerPostRequestHandler("/completed-tasks", AccessLevel.TEACHER, (rq) -> {
SchoolClass schoolClass = rq.getSchoolClass();
Subject subject = rq.getSubject();
if (schoolClass == null) return PostResponse.badRequest("No school class specified", rq);
if (subject == null) return PostResponse.badRequest("No subject specified", rq);
return PostResponse.ok(schoolClass.getCompletedTasksCSV(subject), ContentType.CSV, rq);
});
HttpHandler.registerPostRequestHandler("/class-results", AccessLevel.TEACHER, (rq) -> {
SchoolClass schoolClass = rq.getSchoolClass();
Subject subject = rq.getSubject();
if (schoolClass == null) return PostResponse.badRequest("No school class specified", rq);
if (subject == null) return PostResponse.badRequest("No subject specified", rq);
return PostResponse.ok(schoolClass.getResultsCSV(subject), ContentType.CSV, rq);
});
HttpHandler.registerPostRequestHandler("/grade-results", AccessLevel.ADMIN, (rq) -> {
int grade = rq.getInt("grade");
Subject subject = rq.getSubject();
return PostResponse.ok(SchoolClass.getResultsCSV(grade, subject), ContentType.CSV, rq);
});
}

(you can just do a stub method if you do not want to code the logic)
(registering post request handlers this way may be added in a future update, that's why there is "type": "GET")

Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@
"context": "html",
"access_level": "admin"
},
"/editor": {
"type": "GET",
"handler_type": "TemplatingFileRequestHandler",
"namespaces": ["admin"],
"context": "html",
"access_level": "admin"
},

"/teacher": {
"type": "GET",
"handler_type": "TemplatingFileRequestHandler",
Expand Down
Loading