From af266e345de3e3b20a0e059d7f4589e01f10a305 Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 10 Nov 2021 19:35:02 +0100 Subject: [PATCH] Implement basic functionality for RBACUsers. --- modules/rbac/rbac_controller.cpp | 18 +++++ modules/rbac/rbac_controller.h | 6 ++ modules/rbac/rbac_rank.cpp | 8 +++ modules/rbac/rbac_rank.h | 4 ++ modules/rbac_users/rbac_user.cpp | 8 +++ modules/rbac_users/rbac_user.h | 5 ++ modules/rbac_users/rbac_user_controller.cpp | 76 +++++++++++++++++++++ modules/rbac_users/rbac_user_controller.h | 7 ++ modules/rbac_users/rbac_user_model.cpp | 46 +++++++++++++ modules/rbac_users/rbac_user_model.h | 7 ++ modules/users/user_model.cpp | 14 ++-- modules/users/user_model.h | 10 +-- 12 files changed, 201 insertions(+), 8 deletions(-) diff --git a/modules/rbac/rbac_controller.cpp b/modules/rbac/rbac_controller.cpp index 83a5e9f..d58569c 100644 --- a/modules/rbac/rbac_controller.cpp +++ b/modules/rbac/rbac_controller.cpp @@ -580,6 +580,24 @@ void RBACController::register_permissions() { register_rank_permission("Admin Panel", RBAC_PERMISSION_ADMIN_PANEL); } +Ref RBACController::get_rank(int rank_id) { + return _ranks[rank_id]; +} + +int RBACController::get_default_rank_id() { + //todo + return 0; +} + +Ref RBACController::get_default_rank() { + return _ranks[get_default_rank_id()]; +} + +bool RBACController::continue_on_missing_default_rank() { + //todo, add setting + return false; +} + RBACController *RBACController::get_singleton() { return _self; } diff --git a/modules/rbac/rbac_controller.h b/modules/rbac/rbac_controller.h index 946c95d..55be093 100644 --- a/modules/rbac/rbac_controller.h +++ b/modules/rbac/rbac_controller.h @@ -64,6 +64,12 @@ public: void initialize(); virtual void register_permissions(); + Ref get_rank(int rank_id); + int get_default_rank_id(); + Ref get_default_rank(); + + bool continue_on_missing_default_rank(); + static RBACController *get_singleton(); RBACController(); diff --git a/modules/rbac/rbac_rank.cpp b/modules/rbac/rbac_rank.cpp index fdbd065..205afda 100644 --- a/modules/rbac/rbac_rank.cpp +++ b/modules/rbac/rbac_rank.cpp @@ -1,5 +1,13 @@ #include "rbac_rank.h" +#include "core/http/request.h" + +bool RBACRank::has_permission(Request *request, const int permission) { + //todo try to find a match from the permissions array + + return (base_permissions & permission) != 0; +} + void RBACRank::sort_permissions() { for (int i = 0; i < permissions.size(); ++i) { for (int j = i + 1; j < permissions.size(); ++j) { diff --git a/modules/rbac/rbac_rank.h b/modules/rbac/rbac_rank.h index 88a2dc4..045125d 100644 --- a/modules/rbac/rbac_rank.h +++ b/modules/rbac/rbac_rank.h @@ -8,6 +8,8 @@ #include "rbac_permission.h" +class Request; + class RBACRank : public Resource { RCPP_OBJECT(RBACRank, Resource); @@ -23,6 +25,8 @@ public: Vector > permissions; + bool has_permission(Request *request, const int permission); + void sort_permissions(); RBACRank(); diff --git a/modules/rbac_users/rbac_user.cpp b/modules/rbac_users/rbac_user.cpp index 5a647a4..5fa0abb 100644 --- a/modules/rbac_users/rbac_user.cpp +++ b/modules/rbac_users/rbac_user.cpp @@ -1,5 +1,13 @@ #include "rbac_user.h" +bool RBACUser::has_permission(Request *request, const int permission) { + if (!rbac_rank.is_valid()) { + return false; + } + + return rbac_rank->has_permission(request, permission); +} + RBACUser::RBACUser() : User() { } diff --git a/modules/rbac_users/rbac_user.h b/modules/rbac_users/rbac_user.h index 6b9c627..0bfc963 100644 --- a/modules/rbac_users/rbac_user.h +++ b/modules/rbac_users/rbac_user.h @@ -4,6 +4,7 @@ #include "core/string.h" #include "modules/users/user.h" +#include "modules/rbac/rbac_rank.h" class Request; class FormValidator; @@ -12,6 +13,10 @@ class RBACUser : public User { RCPP_OBJECT(RBACUser, User); public: + Ref rbac_rank; + + bool has_permission(Request *request, const int permission); + RBACUser(); ~RBACUser(); }; diff --git a/modules/rbac_users/rbac_user_controller.cpp b/modules/rbac_users/rbac_user_controller.cpp index 9617c94..0193c44 100644 --- a/modules/rbac_users/rbac_user_controller.cpp +++ b/modules/rbac_users/rbac_user_controller.cpp @@ -1,5 +1,81 @@ #include "rbac_user_controller.h" +#include "core/http/http_session.h" +#include "core/http/request.h" + +#include "rbac_user_model.h" + +#include "modules/rbac/rbac_controller.h" +#include "modules/rbac/rbac_default_permissions.h" +#include "rbac_user.h" + +void RBACUserController::rbac_user_session_setup_middleware(Object *instance, Request *request) { + if (request->session) { + int user_id = request->session->get_int("user_id"); + + if (user_id != 0) { + + Ref u = UserModel::get_singleton()->get_user(user_id); + + if (u.is_valid()) { + request->reference_data["user"] = u; + } else { + //log + request->session->remove_int("user_id"); + } + } + } + + request->next_stage(); +} + +void RBACUserController::rbac_default_user_session_middleware(Object *instance, Request *request) { + Ref rank; + + if (request->session) { + int user_id = request->session->get_int("user_id"); + + if (user_id != 0) { + + Ref u = UserModel::get_singleton()->get_user(user_id); + + if (u.is_valid()) { + rank = u->rbac_rank; + + request->reference_data["user"] = u; + } else { + //log + request->session->remove_int("user_id"); + } + } + } + + if (!rank.is_valid()) { + rank = RBACController::get_singleton()->get_default_rank(); + + if (!rank.is_valid()) { + if (RBACController::get_singleton()->continue_on_missing_default_rank()) { + RLOG_ERR("RBACController::get_singleton()->get_default_rank() has not been set up properly!!! Continuing!"); + request->next_stage(); + } else { + RLOG_ERR("RBACController::get_singleton()->get_default_rank() has not been set up properly!!! Sending 404!"); + request->send_error(404); + } + + return; + } + } + + if (rank->has_permission(request, RBAC_PERMISSION_READ)) { + //todo implement redirect perm + + request->send_error(404); + return; + } + + request->next_stage(); +} + RBACUserController::RBACUserController() : UserController() { } diff --git a/modules/rbac_users/rbac_user_controller.h b/modules/rbac_users/rbac_user_controller.h index 6c42847..f12b1a1 100644 --- a/modules/rbac_users/rbac_user_controller.h +++ b/modules/rbac_users/rbac_user_controller.h @@ -3,10 +3,17 @@ #include "modules/users/user_controller.h" +class Request; + class RBACUserController : public UserController { RCPP_OBJECT(RBACUserController, UserController); public: + //just session setup + static void rbac_user_session_setup_middleware(Object *instance, Request *request); + //this one also handles missing read permission / redirect + static void rbac_default_user_session_middleware(Object *instance, Request *request); + RBACUserController(); ~RBACUserController(); diff --git a/modules/rbac_users/rbac_user_model.cpp b/modules/rbac_users/rbac_user_model.cpp index dac5062..f9057e3 100644 --- a/modules/rbac_users/rbac_user_model.cpp +++ b/modules/rbac_users/rbac_user_model.cpp @@ -1,5 +1,51 @@ #include "rbac_user_model.h" +#include "modules/rbac_users/rbac_user.h" + +#include "modules/rbac/rbac_controller.h" + +Ref RBACUserModel::get_user(const int id) { + Ref u = UserModel::get_user(id); + + if (u.is_valid()) { + u->rbac_rank = RBACController::get_singleton()->get_rank(u->rank); + } + + return u; +} +Ref RBACUserModel::get_user(const String &user_name_input) { + Ref u = UserModel::get_user(user_name_input); + + if (u.is_valid()) { + u->rbac_rank = RBACController::get_singleton()->get_rank(u->rank); + } + + return u; +} + +Vector > RBACUserModel::get_all() { + Vector > users = UserModel::get_all(); + + for (int i = 0; i < users.size(); ++i) { + Ref u = users[i]; + + if (u.is_valid()) { + u->rbac_rank = RBACController::get_singleton()->get_rank(u->rank); + } + } + + return users; +} + +Ref RBACUserModel::create_user() { + Ref u; + u.instance(); + + u->rank = RBACController::get_singleton()->get_default_rank_id(); + u->rbac_rank = RBACController::get_singleton()->get_rank(u->rank); + + return u; +} RBACUserModel::RBACUserModel() : UserModel() { diff --git a/modules/rbac_users/rbac_user_model.h b/modules/rbac_users/rbac_user_model.h index a8f4724..cefaf91 100644 --- a/modules/rbac_users/rbac_user_model.h +++ b/modules/rbac_users/rbac_user_model.h @@ -7,6 +7,13 @@ class RBACUserModel : public UserModel { RCPP_OBJECT(RBACUserModel, UserModel); public: + Ref get_user(const int id); + Ref get_user(const String &user_name_input); + + Vector > get_all(); + + Ref create_user(); + RBACUserModel(); ~RBACUserModel(); diff --git a/modules/users/user_model.cpp b/modules/users/user_model.cpp index d93b48a..7324b75 100644 --- a/modules/users/user_model.cpp +++ b/modules/users/user_model.cpp @@ -29,7 +29,7 @@ Ref UserModel::get_user(const int id) { } Ref user; - user.instance(); + user = create_user(); user->id = id; user->name_user_input = r->get_cell(0); @@ -64,7 +64,7 @@ Ref UserModel::get_user(const String &user_name_input) { } Ref user; - user.instance(); + user = create_user(); user->id = r->get_cell_int(0); user->name_user_input = user_name_input; @@ -138,8 +138,7 @@ Vector > UserModel::get_all() { Ref r = b->run(); while (r->next_row()) { - Ref user; - user.instance(); + Ref user = create_user(); user->id = r->get_cell_int(0); user->name_user_input = r->get_cell(1); @@ -158,6 +157,13 @@ Vector > UserModel::get_all() { return users; } +Ref UserModel::create_user() { + Ref u; + u.instance(); + + return u; +} + bool UserModel::is_username_taken(const String &user_name_input) { Ref b = DatabaseManager::get_singleton()->ddb->get_query_builder(); diff --git a/modules/users/user_model.h b/modules/users/user_model.h index a5caee7..8503c36 100644 --- a/modules/users/user_model.h +++ b/modules/users/user_model.h @@ -12,11 +12,13 @@ class UserModel : public Object { RCPP_OBJECT(UserModel, Object); public: - Ref get_user(const int id); - Ref get_user(const String &user_name_input); - void save_user(Ref &user); + virtual Ref get_user(const int id); + virtual Ref get_user(const String &user_name_input); + virtual void save_user(Ref &user); - Vector > get_all(); + virtual Vector > get_all(); + + virtual Ref create_user(); bool is_username_taken(const String &user_name_input); bool is_email_taken(const String &email_input);