mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 19:03:43 +00:00
What someone may do on the dashboard is now their GM level's permissions plus the grants on their account, minus its denies (PermissionGrants.h). A deny beats a grant; denies never apply to GM 9, and settings and permissions_manage stay GM 9 only. The account's grants are read with every request (like its GM level), so a change applies at once, and they are passed through every check: RouteUtils::Can, CanViewCharacter, the rank rules (self_* and manage_equal_rank), routes guarded by a permission, the templates' `can`, the API documentation, API access, API key scopes (a key never does more than its owner may now) and WebSocket subscriptions. New permission grants_manage (GM 9 by default) and the API to manage grants: GET /api/grants/catalog, GET /api/grants, POST /api/grants, POST /api/grants/:id/remove. Nobody grants or takes away what they don't hold themselves (a permission, every permission of a group, a command they may use, every command up to their own GM level), and only on accounts the rank rules let them manage (their own with self_moderation). Commands with a fixed level or a floor above GM 1 (/execute) can't be granted. Every change goes in the audit log (grant_permission, deny_permission, remove_grant). Also: the Showcase gate and the traffic subscription now check their permission by name. Check: grant a GM 2 account accounts_ban (it can ban, and the Ban button shows); deny a GM 8 account accounts_view (the accounts list is refused); give an expiry a minute ahead and see it stop; try to grant a permission your account doesn't have (refused); dWebTests PermissionGrantsTests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.2 KiB
C++
54 lines
2.2 KiB
C++
#ifndef __REQUIREAUTHMIDDLEWARE_H__
|
|
#define __REQUIREAUTHMIDDLEWARE_H__
|
|
|
|
#include <memory>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <string>
|
|
#include "IHTTPMiddleware.h"
|
|
|
|
/**
|
|
* RequireAuthMiddleware: Enforces authentication on protected routes
|
|
*
|
|
* Returns 401 Unauthorized if user is not authenticated
|
|
* Returns 403 Forbidden if user's GM level is below minimum required
|
|
*/
|
|
class RequireAuthMiddleware final : public IHTTPMiddleware {
|
|
public:
|
|
/**
|
|
* @param minGmLevel Minimum GM level required to access this route
|
|
* 0 = any authenticated user, higher numbers = GM-only
|
|
*/
|
|
explicit RequireAuthMiddleware(uint8_t minGmLevel = 0);
|
|
|
|
// The required level is looked up on every request (a permission that can be changed while running)
|
|
explicit RequireAuthMiddleware(std::function<uint8_t()> requiredLevel);
|
|
|
|
// A route guarded by a named permission: an API key must also have it in its scope
|
|
RequireAuthMiddleware(std::function<uint8_t()> requiredLevel, std::string permission);
|
|
~RequireAuthMiddleware() override = default;
|
|
|
|
bool Process(HTTPContext& context, HTTPReply& reply) override;
|
|
|
|
// Whether a signed-in account may use the API (requests signed in with a token in the Authorization header rather
|
|
// than the browser's cookie). Set by the dashboard from its api_access permission; unset allows everyone.
|
|
static void SetApiAccessCheck(std::function<bool(const HTTPContext& context)> check);
|
|
|
|
// Renders the page a signed-in account gets when it may not open a page (not /api/); unset replies with JSON
|
|
static void SetForbiddenPage(std::function<void(const HTTPContext& context, HTTPReply& reply)> render);
|
|
// The route only reads, although it may be a POST (DataTables and lookups send their query as a body): read-only
|
|
// API keys may use it
|
|
void SetReadsOnly() { readsOnly = true; }
|
|
|
|
// Told when an API key is refused a route for its scope or because it is read-only (for the audit log)
|
|
static void SetApiKeyDeniedHook(std::function<void(const HTTPContext& context, const std::string& reason)> hook);
|
|
std::string GetName() const override { return "RequireAuthMiddleware"; }
|
|
|
|
private:
|
|
std::function<uint8_t()> requiredLevel;
|
|
std::string permission;
|
|
bool readsOnly{};
|
|
};
|
|
|
|
#endif // !__REQUIREAUTHMIDDLEWARE_H__
|