diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8c4a6e3..d10dc41 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,13 +1,16 @@ # .github/workflows/publish.yml - name: Publish on: release: types: [released, prereleased] + jobs: publish: name: Release build and publish runs-on: macOS-latest + permissions: + contents: read + packages: write steps: - name: Check out code uses: actions/checkout@v4 @@ -16,12 +19,19 @@ jobs: with: distribution: 'zulu' java-version: 21 - - name: Publish to MavenCentral + - name: Publish SNAPSHOT to snapshot repo + if: github.event.action == 'prereleased' + run: ./gradlew publishAllPublicationsToSnapshotsRepository --no-configuration-cache + env: + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish release to Maven Central + if: github.event.action == 'released' run: ./gradlew publishToMavenCentral --no-configuration-cache env: ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} - ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }} - + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 396e1ed..165af06 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { group = "io.github.learn-monitor" -version = "v2.0.0-SNAPSHOT-3" +version = "s2607b1-SNAPSHOT" application { mainClass.set("de.igslandstuhl.database.Application") @@ -96,4 +96,16 @@ mavenPublishing { } tasks.withType().configureEach { dependsOn(tasks.withType()) +} +publishing { + repositories { + maven { + name = "snapshots" + url = uri("https://maven.pkg.github.com/Learn-Monitor/student-database") + credentials { + username = System.getenv("GITHUB_ACTOR") ?: findProperty("gpr.user") as String? + password = System.getenv("GITHUB_TOKEN") ?: findProperty("gpr.key") as String? + } + } + } } \ No newline at end of file diff --git a/src/main/java/de/igslandstuhl/database/events/Event.java b/src/main/java/de/igslandstuhl/database/events/Event.java new file mode 100644 index 0000000..5f3497c --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/events/Event.java @@ -0,0 +1,18 @@ +package de.igslandstuhl.database.events; + +public abstract class Event { + private boolean cancelled = false; + + public abstract EventType getType(); + protected void onCancel() { + // Override this method to handle cancellation logic in subclasses + } + + public boolean isCancelled() { + return this.cancelled; + } + public void cancel() { + this.cancelled = true; + onCancel(); + } +} diff --git a/src/main/java/de/igslandstuhl/database/events/EventFilter.java b/src/main/java/de/igslandstuhl/database/events/EventFilter.java new file mode 100644 index 0000000..ef40815 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/events/EventFilter.java @@ -0,0 +1,17 @@ +package de.igslandstuhl.database.events; + +@FunctionalInterface +public interface EventFilter { + public boolean filter(T event); + @SafeVarargs + public static EventFilter linked(EventFilter... filters) { + return event -> { + for (EventFilter filter : filters) { + if (!filter.filter(event)) { + return false; + } + } + return true; + }; + } +} diff --git a/src/main/java/de/igslandstuhl/database/events/EventListener.java b/src/main/java/de/igslandstuhl/database/events/EventListener.java new file mode 100644 index 0000000..190de5f --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/events/EventListener.java @@ -0,0 +1,55 @@ +package de.igslandstuhl.database.events; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; + +import de.igslandstuhl.database.Registry; + +public abstract class EventListener { + private static final Registry, Set>> listeners = new Registry<>(); + + private final ListenerPriority priority; + + public EventListener(ListenerPriority priority) { + this.priority = priority; + } + + public abstract void onEvent(T event); + public abstract EventType getEventType(); + public EventFilter getFilter() { + return event -> true; + } + + public ListenerPriority getPriority() { + return priority; + } + public void register() { + listeners.get(getEventType()).add(this); + } + + public static void register(EventType type) { + listeners.register(type, new HashSet<>()); + } + + @SuppressWarnings("unchecked") + private static Set> getListeners(EventType type) { + return (Set>) (Set) listeners.get(type); + } + public static void fireEvent(T event) { + Set> eventListeners = getListeners(EventType.of(event)); + if (eventListeners != null) { + new LinkedList<>(eventListeners).stream() + .filter(listener -> listener.getFilter().filter(event)) + .sorted((a, b) -> a.getPriority().compareTo(b.getPriority())) + .forEach(listener -> { + if (!event.isCancelled()) { + listener.onEvent(event); + if (event.isCancelled() && listener.getPriority() == ListenerPriority.MONITOR) { + throw new IllegalStateException("Event was cancelled but a monitor listener was called."); + } + } + }); + } + } +} diff --git a/src/main/java/de/igslandstuhl/database/events/EventType.java b/src/main/java/de/igslandstuhl/database/events/EventType.java new file mode 100644 index 0000000..0e3735e --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/events/EventType.java @@ -0,0 +1,8 @@ +package de.igslandstuhl.database.events; + +public record EventType(String name) { + @SuppressWarnings("unchecked") + public static EventType of(T event) { + return (EventType) event.getType(); + } +} diff --git a/src/main/java/de/igslandstuhl/database/events/ListenerPriority.java b/src/main/java/de/igslandstuhl/database/events/ListenerPriority.java new file mode 100644 index 0000000..9d7c30c --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/events/ListenerPriority.java @@ -0,0 +1,9 @@ +package de.igslandstuhl.database.events; + +public enum ListenerPriority { + LOWEST, + LOW, + HIGH, + HIGHEST, + MONITOR +} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/AccessManager.java b/src/main/java/de/igslandstuhl/database/server/webserver/AccessManager.java deleted file mode 100644 index 53ca04a..0000000 --- a/src/main/java/de/igslandstuhl/database/server/webserver/AccessManager.java +++ /dev/null @@ -1,192 +0,0 @@ -package de.igslandstuhl.database.server.webserver; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import de.igslandstuhl.database.Registry; -import de.igslandstuhl.database.api.User; -import de.igslandstuhl.database.server.Server; -import de.igslandstuhl.database.server.resources.ResourceLocation; - -/** - * AccessManager is responsible for managing access to resources based on user roles and resource locations. - * It determines whether a user has access to a specific resource based on predefined rules. - */ -public class AccessManager { - private static final Logger LOGGER = LoggerFactory.getLogger(AccessManager.class); - private static final AccessManager INSTANCE = new AccessManager(); - public static AccessManager getInstance() { - return INSTANCE; - } - /** - * Public spaces and locations that are accessible without authentication. - * These resources can be accessed by anyone, regardless of their authentication status. - */ - private final String[] PUBLIC_SPACES; - /** - * The user space is restricted to authenticated users. - */ - private final String USER_SPACE; - /** - * The teacher space is restricted to authenticated teachers. - */ - private final String TEACHER_SPACE; - /** - * The admin space is restricted to authenticated admins. - */ - private final String ADMIN_SPACE; - /** - * Public locations that are accessible without authentication. - * These resources can be accessed by anyone, regardless of their authentication status. - */ - private final String[] PUBLIC_LOCATIONS; - /** - * User locations that are accessible only to authenticated users. - * These resources require user login for access. - */ - private final String[] USER_LOCATIONS; - /** - * Teacher locations that are accessible only to authenticated teachers. - * These resources require teacher privileges for access. - */ - private final String[] TEACHER_LOCATIONS; - /** - * Admin locations that are accessible only to authenticated admins. - * These resources require admin privileges for access. - */ - private final String[] ADMIN_LOCATIONS; - - - @SuppressWarnings("unchecked") - private AccessManager() { - LOGGER.info("Setting up AccessManager..."); - ResourceLocation metaLocation = new ResourceLocation("meta", "paths", "spaces.json"); - String userSpace = "user"; - String teacherSpace = "teacher"; - String adminSpace = "admin"; - - String[] publicSpaces = {"error", "site", "icons"}; - String[] publicLocations = {"rooms", "subjects"}; - String[] userLocations = {}; - String[] teacherLocations = {}; - String[] adminLocations = {"students", "teachers", "classes"}; - try { - LOGGER.debug("Trying to read spaces metadata..."); - Map pathData = Server.getInstance().getResourceManager().readJsonResourceAsMap(metaLocation); - List publicSpacesList = (List) pathData.get("public_spaces"); - List publicLocationsList = (List) pathData.get("public_locations"); - List userLocationsList = (List) pathData.get("user_locations"); - List teacherLocationsList = (List) pathData.get("teacher_locations"); - List adminLocationsList = (List) pathData.get("admin_locations"); - userSpace = (String) pathData.get("user_space"); - teacherSpace = (String) pathData.get("teacher_space"); - adminSpace = (String) pathData.get("admin_space"); - publicSpaces = publicSpacesList.toArray(new String[publicSpacesList.size()]); - publicLocations = publicLocationsList.toArray(new String[publicLocationsList.size()]); - userLocations = userLocationsList.toArray(new String[userLocationsList.size()]); - teacherLocations = teacherLocationsList.toArray(new String[teacherLocationsList.size()]); - adminLocations = adminLocationsList.toArray(new String[adminLocationsList.size()]); - } catch (IOException e) { - LOGGER.error("Could not read spaces metadata!", e); - } finally { - USER_SPACE = userSpace; - TEACHER_SPACE = teacherSpace; - ADMIN_SPACE = adminSpace; - PUBLIC_SPACES = publicSpaces; - PUBLIC_LOCATIONS = publicLocations; - USER_LOCATIONS = userLocations; - TEACHER_LOCATIONS = teacherLocations; - ADMIN_LOCATIONS = adminLocations; - } - - - } - - /** - * Checks if a user has access to a specific resource. - * - * @param user the username of the user, or null if not authenticated - * @param resource the ResourceLocation representing the resource to check access for - * @return true if the user has access to the resource, false otherwise - * @deprecated Use hasAccess(String user, String path) - */ - @Deprecated - public boolean hasAccess(String user, ResourceLocation resource) { - return hasAccess(User.getUser(user), resource); - } - /** - * Checks if a user has access to a specific resource. - * - * @param user the user, or null if not authenticated - * @param resource the ResourceLocation representing the resource to check access for - * @return true if the user has access to the resource, false otherwise - * @deprecated Use hasAccess(User user, String path) - */ - @Deprecated - public boolean hasAccess(User user, ResourceLocation resource) { - if (Arrays.asList(PUBLIC_SPACES).contains(resource.namespace()) || Arrays.asList(PUBLIC_LOCATIONS).contains(resource.resource())) { - return true; - } else if (user != null) { - if (resource.namespace().equals(USER_SPACE) || resource.resource().startsWith("my") && !(user == User.ANONYMOUS)) { - return true; - } else if (resource.namespace().equals(TEACHER_SPACE)) { - return user.isTeacher() || user.isAdmin(); - } else if (resource.namespace().equals(ADMIN_SPACE) || Arrays.asList(ADMIN_LOCATIONS).contains(resource.resource())) { - return user.isAdmin(); - } else { - return false; - } - } else { - return false; - } - } - /** - * Checks if a user has access to a specific access level - * @param user the user, can be null to indicate no user logged in - * @param accessLevel the access level - * @return true, if the user has access, otherwise false - */ - public boolean hasAccess(User user, AccessLevel accessLevel) { - if (accessLevel == AccessLevel.PUBLIC) { - return true; - } else if (user == null || user == User.ANONYMOUS) { - return false; - } else if (accessLevel == AccessLevel.NONE) { - return false; - } else if (accessLevel == AccessLevel.USER) { - return true; - } else if (accessLevel == AccessLevel.STUDENT) { - return user.isStudent(); - } else if (user.isStudent()) { - return false; - } else if (accessLevel == AccessLevel.TEACHER) { - return true; - } else { - return user.isAdmin(); // Must be AccessLevel.ADMIN - } - } - /** - * Checks if a user has access to a specific web path - * @param user the username of the user, can be null to indicate no user logged in - * @param path the web path - * @return true, if the user has access, otherwise false - */ - public boolean hasAccess(String user, String path) { - return hasAccess(User.getUser(user), path); - } - /** - * Checks if a user has access to a specific web path - * @param user user, can be null to indicate no user logged in - * @param path the web path - * @return true, if the user has access, otherwise false - */ - public boolean hasAccess(User user, String path) { - AccessLevel accessLevel = Registry.webPathRegistry().get(path).accessLevel(); - return hasAccess(user, accessLevel); - } -} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/WebPath.java b/src/main/java/de/igslandstuhl/database/server/webserver/WebPath.java index 075401d..062b1f9 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/WebPath.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/WebPath.java @@ -10,6 +10,7 @@ import de.igslandstuhl.database.Registry; import de.igslandstuhl.database.server.Server; import de.igslandstuhl.database.server.resources.ResourceLocation; +import de.igslandstuhl.database.server.webserver.access.AccessLevel; import de.igslandstuhl.database.server.webserver.requests.RequestType; public record WebPath(RequestType type, String handlerType, List namespaces, String context, AccessLevel accessLevel) { diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/AccessLevel.java b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessLevel.java similarity index 90% rename from src/main/java/de/igslandstuhl/database/server/webserver/AccessLevel.java rename to src/main/java/de/igslandstuhl/database/server/webserver/access/AccessLevel.java index 9119790..f18b5f3 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/AccessLevel.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessLevel.java @@ -1,4 +1,4 @@ -package de.igslandstuhl.database.server.webserver; +package de.igslandstuhl.database.server.webserver.access; import de.igslandstuhl.database.api.User; diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManager.java b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManager.java new file mode 100644 index 0000000..687605b --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManager.java @@ -0,0 +1,78 @@ +package de.igslandstuhl.database.server.webserver.access; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.igslandstuhl.database.Registry; +import de.igslandstuhl.database.api.User; +import de.igslandstuhl.database.events.EventListener; + +/** + * AccessManager is responsible for managing access to resources based on user roles and resource locations. + * It determines whether a user has access to a specific resource based on predefined rules. + */ +public class AccessManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AccessManager.class); + private static final AccessManager INSTANCE = new AccessManager(); + public static AccessManager getInstance() { + return INSTANCE; + } + + private AccessManager() { + LOGGER.info("Setting up AccessManager..."); + } + /** + * Checks if a user has access to a specific access level + * @param user the user, can be null to indicate no user logged in + * @param accessLevel the access level + * @return the access state of the user for the given access level + */ + private AccessState getAccessState(User user, AccessLevel accessLevel) { + AccessState result; + if (accessLevel == AccessLevel.PUBLIC) { + result = AccessState.PERMITTED; + } else if (user == null || user == User.ANONYMOUS) { + result = AccessState.UNAUTHORIZED; + } else if (accessLevel == AccessLevel.NONE) { + result = AccessState.RESTRICTED; + } else if (accessLevel == AccessLevel.USER) { + result = AccessState.AUTHORIZED; + } else if (accessLevel == AccessLevel.STUDENT) { + result = user.isStudent() ? AccessState.AUTHORIZED : AccessState.RESTRICTED; + } else if (user.isStudent()) { + result = AccessState.RESTRICTED; + } else if (accessLevel == AccessLevel.TEACHER) { + result = AccessState.AUTHORIZED; + } else { + result = user.isAdmin() ? AccessState.AUTHORIZED : AccessState.RESTRICTED; // Must be AccessLevel.ADMIN + } + // Fire an AccessManagerEvent to allow for external modifications of the access decision + return result; + } + /** + * Checks if a user has access to a specific web path + * @param user the username of the user, can be null to indicate no user logged in + * @param path the web path + * @return true, if the user has access, otherwise false + */ + public boolean hasAccess(String user, String path) { + return hasAccess(User.getUser(user), path); + } + /** + * Checks if a user has access to a specific web path + * @param user user, can be null to indicate no user logged in + * @param path the web path + * @return true, if the user has access, otherwise false + */ + public boolean hasAccess(User user, String path) { + AccessLevel accessLevel = Registry.webPathRegistry().get(path).accessLevel(); + AccessState result = getAccessState(user, accessLevel); + + AccessManagerEvent event = new AccessManagerEvent(result, path); + EventListener.fireEvent(event); + + result = event.getChangedAccessState().orElse(result); + + return result == AccessState.AUTHORIZED || result == AccessState.PERMITTED; + } +} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManagerEvent.java b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManagerEvent.java new file mode 100644 index 0000000..3615a0a --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessManagerEvent.java @@ -0,0 +1,53 @@ +package de.igslandstuhl.database.server.webserver.access; + +import java.util.Optional; + +import de.igslandstuhl.database.events.Event; +import de.igslandstuhl.database.events.EventType; + +public class AccessManagerEvent extends Event { + public static final EventType TYPE = new EventType<>("AccessManagerEvent"); + + private final AccessState accessState; + + private final String path; + + private Optional changedAccessState = Optional.empty(); + + public AccessManagerEvent(AccessState accessState, String path) { + this.accessState = accessState; + this.path = path; + } + + public AccessState getAccessState() { + return accessState; + } + public String getPath() { + return path; + } + public Optional getChangedAccessState() { + return changedAccessState; + } + @Override + public EventType getType() { + return TYPE; + } + + public void changeAccessState(AccessState newAccessState) { + this.changedAccessState = Optional.of(newAccessState); + this.cancel(); + } + + public static AccessManagerEvent unauthorized(String path) { + return new AccessManagerEvent(AccessState.UNAUTHORIZED, path); + } + public static AccessManagerEvent authorized(String path) { + return new AccessManagerEvent(AccessState.AUTHORIZED, path); + } + public static AccessManagerEvent restricted(String path) { + return new AccessManagerEvent(AccessState.RESTRICTED, path); + } + public static AccessManagerEvent pending(String path) { + return new AccessManagerEvent(AccessState.PENDING, path); + } +} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessState.java b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessState.java new file mode 100644 index 0000000..8ccc019 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessState.java @@ -0,0 +1,27 @@ +package de.igslandstuhl.database.server.webserver.access; + +/** + * AccessState represents the different states of access a user can have to a resource. + */ +public enum AccessState { + /** + * The user is not logged in and does not have access to the resource. + */ + UNAUTHORIZED, + /** + * The user is logged in and has access to the resource. + */ + AUTHORIZED, + /** + * The user is logged in but does not have access to the resource. + */ + RESTRICTED, + /** + * The user is logged in and has requested access to the resource. + */ + PENDING, + /** + * The user is logged in and has been granted access to the resource. + */ + PERMITTED +} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessStateFilter.java b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessStateFilter.java new file mode 100644 index 0000000..1c88008 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/server/webserver/access/AccessStateFilter.java @@ -0,0 +1,16 @@ +package de.igslandstuhl.database.server.webserver.access; + +import de.igslandstuhl.database.events.EventFilter; + +public class AccessStateFilter implements EventFilter { + private final AccessState state; + + public AccessStateFilter(AccessState state) { + this.state = state; + } + + @Override + public boolean filter(AccessManagerEvent event) { + return event.getAccessState() == state; + } +} diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/HttpHandler.java b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/HttpHandler.java index d64604b..2ab3eba 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/HttpHandler.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/HttpHandler.java @@ -5,8 +5,8 @@ import de.igslandstuhl.database.Registry; import de.igslandstuhl.database.server.Server; -import de.igslandstuhl.database.server.webserver.AccessLevel; import de.igslandstuhl.database.server.webserver.Status; +import de.igslandstuhl.database.server.webserver.access.AccessLevel; import de.igslandstuhl.database.server.webserver.requests.APIPostRequest; import de.igslandstuhl.database.server.webserver.requests.GetRequest; import de.igslandstuhl.database.server.webserver.requests.HttpRequest; diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java index 15cc8fc..594e66f 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java @@ -37,8 +37,8 @@ import de.igslandstuhl.database.plugins.config.PluginSetting; import de.igslandstuhl.database.plugins.config.ShortAnswerSetting; import de.igslandstuhl.database.server.Server; -import de.igslandstuhl.database.server.webserver.AccessLevel; import de.igslandstuhl.database.server.webserver.ContentType; +import de.igslandstuhl.database.server.webserver.access.AccessLevel; import de.igslandstuhl.database.server.webserver.requests.APIPostRequest; import de.igslandstuhl.database.server.webserver.requests.PostRequest; import de.igslandstuhl.database.server.webserver.responses.HttpResponse; diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/responses/GetResponse.java b/src/main/java/de/igslandstuhl/database/server/webserver/responses/GetResponse.java index 7189ed0..76c5ece 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/responses/GetResponse.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/responses/GetResponse.java @@ -7,10 +7,10 @@ import de.igslandstuhl.database.client.TemplatingPreprocessor; import de.igslandstuhl.database.server.Server; import de.igslandstuhl.database.server.resources.ResourceLocation; -import de.igslandstuhl.database.server.webserver.AccessManager; import de.igslandstuhl.database.server.webserver.ContentType; import de.igslandstuhl.database.server.webserver.NoWebResourceException; import de.igslandstuhl.database.server.webserver.Status; +import de.igslandstuhl.database.server.webserver.access.AccessManager; import de.igslandstuhl.database.server.webserver.handlers.HttpHandler; import de.igslandstuhl.database.server.webserver.handlers.get.PluginRequestHandler; import de.igslandstuhl.database.server.webserver.requests.HttpRequest; diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/responses/PostResponse.java b/src/main/java/de/igslandstuhl/database/server/webserver/responses/PostResponse.java index f2d373a..2181ca8 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/responses/PostResponse.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/responses/PostResponse.java @@ -8,11 +8,11 @@ import de.igslandstuhl.database.server.Server; import de.igslandstuhl.database.server.WebServer; import de.igslandstuhl.database.server.resources.ResourceLocation; -import de.igslandstuhl.database.server.webserver.AccessManager; import de.igslandstuhl.database.server.webserver.ContentType; import de.igslandstuhl.database.server.webserver.Cookie; import de.igslandstuhl.database.server.webserver.NoWebResourceException; import de.igslandstuhl.database.server.webserver.Status; +import de.igslandstuhl.database.server.webserver.access.AccessManager; import de.igslandstuhl.database.server.webserver.handlers.HttpHandler; import de.igslandstuhl.database.server.webserver.requests.HttpRequest; import de.igslandstuhl.database.server.webserver.requests.PostRequest; diff --git a/src/main/resources/meta/paths/spaces.json b/src/main/resources/meta/paths/spaces.json deleted file mode 100644 index e1f899a..0000000 --- a/src/main/resources/meta/paths/spaces.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "public_spaces": [ - "error", - "site", - "icons" - ], - "user_space": "user", - "teacher_space": "teacher", - "admin_space": "admin", - "public_locations": [ - "rooms", - "subjects" - ], - "user_locations": [], - "teacher_locations": [], - "admin_locations": [ - "students", - "teachers", - "classes", - "all-student-results" - ] -} \ No newline at end of file diff --git a/src/test/java/de/igslandstuhl/database/server/webserver/AccessManagerTest.java b/src/test/java/de/igslandstuhl/database/server/webserver/AccessManagerTest.java index 940bcc4..d9815a0 100644 --- a/src/test/java/de/igslandstuhl/database/server/webserver/AccessManagerTest.java +++ b/src/test/java/de/igslandstuhl/database/server/webserver/AccessManagerTest.java @@ -11,8 +11,7 @@ import org.junit.jupiter.api.Test; import de.igslandstuhl.database.api.User; -import de.igslandstuhl.database.server.resources.ResourceLocation; -import de.igslandstuhl.database.server.webserver.handlers.WebResourceHandler; +import de.igslandstuhl.database.server.webserver.access.AccessManager; public class AccessManagerTest { private User teacher; @@ -120,45 +119,38 @@ public String getUsername() { anonymous = User.ANONYMOUS; } @Test - public void testErrorMessageAccess() { - assertTrue(AccessManager.getInstance().hasAccess(anonymous, ResourceLocation.get("html", "error:404"))); - assertTrue(AccessManager.getInstance().hasAccess(student, ResourceLocation.get("html", "error:404"))); - assertTrue(AccessManager.getInstance().hasAccess(teacher, ResourceLocation.get("html", "error:404"))); - assertTrue(AccessManager.getInstance().hasAccess(admin, ResourceLocation.get("html", "error:404"))); - } - @Test public void testIconAccess() { - assertTrue(AccessManager.getInstance().hasAccess(anonymous, ResourceLocation.get("imgs", "icons:favicon.ico"))); - assertTrue(AccessManager.getInstance().hasAccess(student, ResourceLocation.get("imgs", "icons:favicon.ico"))); - assertTrue(AccessManager.getInstance().hasAccess(teacher, ResourceLocation.get("imgs", "icons:favicon.ico"))); - assertTrue(AccessManager.getInstance().hasAccess(admin, ResourceLocation.get("imgs", "icons:favicon.ico"))); + assertTrue(AccessManager.getInstance().hasAccess(anonymous, "/favicon.ico")); + assertTrue(AccessManager.getInstance().hasAccess(student, "/favicon.ico")); + assertTrue(AccessManager.getInstance().hasAccess(teacher, "/favicon.ico")); + assertTrue(AccessManager.getInstance().hasAccess(admin, "/favicon.ico")); } @Test public void testLoginAccess() { - assertTrue(AccessManager.getInstance().hasAccess(anonymous, ResourceLocation.get("html", "site:login"))); - assertTrue(AccessManager.getInstance().hasAccess(student, ResourceLocation.get("html", "site:login"))); - assertTrue(AccessManager.getInstance().hasAccess(teacher, ResourceLocation.get("html", "site:login"))); - assertTrue(AccessManager.getInstance().hasAccess(admin, ResourceLocation.get("html", "site:login"))); + assertTrue(AccessManager.getInstance().hasAccess(anonymous, "/login")); + assertTrue(AccessManager.getInstance().hasAccess(student, "/login")); + assertTrue(AccessManager.getInstance().hasAccess(teacher, "/login")); + assertTrue(AccessManager.getInstance().hasAccess(admin, "/login")); } @Test public void testDashboardAccess() { - assertFalse(AccessManager.getInstance().hasAccess(anonymous, WebResourceHandler.locationFromPath("/dashboard", anonymous))); - assertTrue(AccessManager.getInstance().hasAccess(student, WebResourceHandler.locationFromPath("/dashboard", student))); - assertTrue(AccessManager.getInstance().hasAccess(teacher, WebResourceHandler.locationFromPath("/dashboard", teacher))); - assertTrue(AccessManager.getInstance().hasAccess(admin, WebResourceHandler.locationFromPath("/dashboard", admin))); + assertFalse(AccessManager.getInstance().hasAccess(anonymous, "/dashboard")); + assertTrue(AccessManager.getInstance().hasAccess(student, "/dashboard")); + assertTrue(AccessManager.getInstance().hasAccess(teacher, "/dashboard")); + assertTrue(AccessManager.getInstance().hasAccess(admin, "/dashboard")); } @Test public void testStudentManagementAccess() { - assertFalse(AccessManager.getInstance().hasAccess(anonymous, WebResourceHandler.locationFromPath("/student", anonymous))); - assertFalse(AccessManager.getInstance().hasAccess(student, WebResourceHandler.locationFromPath("/student", student))); - assertTrue(AccessManager.getInstance().hasAccess(teacher, WebResourceHandler.locationFromPath("/student", teacher))); - assertTrue(AccessManager.getInstance().hasAccess(admin, WebResourceHandler.locationFromPath("/student", admin))); + assertFalse(AccessManager.getInstance().hasAccess(anonymous, "/student")); + assertFalse(AccessManager.getInstance().hasAccess(student, "/student")); + assertTrue(AccessManager.getInstance().hasAccess(teacher, "/student")); + assertTrue(AccessManager.getInstance().hasAccess(admin, "/student")); } @Test public void testTeacherManagementAccess() { - assertFalse(AccessManager.getInstance().hasAccess(anonymous, WebResourceHandler.locationFromPath("/teacher", anonymous))); - assertFalse(AccessManager.getInstance().hasAccess(student, WebResourceHandler.locationFromPath("/teacher", student))); - assertFalse(AccessManager.getInstance().hasAccess(teacher, WebResourceHandler.locationFromPath("/teacher", teacher))); - assertTrue(AccessManager.getInstance().hasAccess(admin, WebResourceHandler.locationFromPath("/teacher", admin))); + assertFalse(AccessManager.getInstance().hasAccess(anonymous, "/teacher")); + assertFalse(AccessManager.getInstance().hasAccess(student, "/teacher")); + assertFalse(AccessManager.getInstance().hasAccess(teacher, "/teacher")); + assertTrue(AccessManager.getInstance().hasAccess(admin, "/teacher")); } }