oatpp-authkit/include/oatpp-authkit/auth/RequireRole.hpp
Uwe Schuster 495c8ddbb9 v0.2.0: IAuthBackend/IAuthPolicy/IRuntimeConfig seams + AuthInterceptor port
Ports the fewo-webapp AuthInterceptor + requireAdmin onto three abstract
interfaces so consumer apps plug in their own user store, public paths,
and runtime config without forking:

  auth/AuthPrincipal.hpp      library-owned {id, username, role} value
  auth/IAuthBackend.hpp       resolveBy{Session,ApiKey,Cert}, hasActiveUsers,
                              deleteExpiredSessions
  auth/IAuthPolicy.hpp        isPublicPath, adminRoles, readonlyRoles,
                              setupModeActive (defaults: admin/readonly,
                              no public paths, setup off)
  auth/IRuntimeConfig.hpp     bindAddress, isLoopback
  auth/AuthInterceptor.hpp    intercept() running the same 6-step ladder as
                              fewo's original (public → setup → cert DN →
                              session/API key → CSRF → readonly)
  auth/RequireRole.hpp        requireUser + requireAdmin helpers reading
                              bundle data (config-driven role sets, not
                              hard-coded 'admin')

TokenHasher is passed in so the library doesn't prescribe SHA-256 vs.
whatever. Bundle keys match fewo's existing controllers so the consumer
migration in #418 is a straightforward adapter swap.

Smoke-compiled against oatpp 1.3.0 headers.

Closes fewo-webapp#413

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 21:48:43 +02:00

55 lines
1.7 KiB
C++

#ifndef OATPP_AUTHKIT_AUTH_REQUIRE_ROLE_HPP
#define OATPP_AUTHKIT_AUTH_REQUIRE_ROLE_HPP
#include <memory>
#include <string>
#include "oatpp/web/protocol/http/Http.hpp"
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "IAuthPolicy.hpp"
namespace oatpp_authkit {
using IncomingRequest = oatpp::web::protocol::http::incoming::Request;
using Status = oatpp::web::protocol::http::Status;
/**
* @brief Pull the authenticated user into local scope inside a controller
* endpoint. Throws 401 when no principal is present in the bundle.
*
* Usage inside an ENDPOINT:
* auto me = oatpp_authkit::requireUser(request);
* // me.id, me.role, me.username
*/
inline AuthPrincipal requireUser(const std::shared_ptr<IncomingRequest>& request) {
auto id = request->getBundleData<oatpp::String>("auth_user_id");
auto role = request->getBundleData<oatpp::String>("auth_user_role");
auto username = request->getBundleData<oatpp::String>("auth_username");
OATPP_ASSERT_HTTP(id && role, Status::CODE_401, "Authentication required");
AuthPrincipal p;
p.id = std::stoi(std::string(*id));
p.role = std::string(*role);
p.username = username ? std::string(*username) : "";
return p;
}
/**
* @brief Reject the request with 403 unless the authenticated user is in
* the policy's admin role set.
*/
inline AuthPrincipal requireAdmin(const std::shared_ptr<IncomingRequest>& request,
IAuthPolicy& policy)
{
auto me = requireUser(request);
OATPP_ASSERT_HTTP(policy.adminRoles().count(me.role) > 0,
Status::CODE_403, "Admin required");
return me;
}
} // namespace oatpp_authkit
#endif