// Copyright 2023 Memgraph Ltd. // // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // this file except in compliance with the License. You may obtain a copy of the License at https://memgraph.com/legal. // // #pragma once #include #include #include #include namespace memgraph::auth { // These permissions must have values that are applicable for usage in a // bitmask. // clang-format off enum class Permission : uint64_t { MATCH = 1, CREATE = 1U << 1U, MERGE = 1U << 2U, DELETE = 1U << 3U, SET = 1U << 4U, REMOVE = 1U << 5U, INDEX = 1U << 6U, STATS = 1U << 7U, CONSTRAINT = 1U << 8U, DUMP = 1U << 9U, REPLICATION = 1U << 10U, DURABILITY = 1U << 11U, READ_FILE = 1U << 12U, FREE_MEMORY = 1U << 13U, TRIGGER = 1U << 14U, CONFIG = 1U << 15U, AUTH = 1U << 16U, STREAM = 1U << 17U, MODULE_READ = 1U << 18U, MODULE_WRITE = 1U << 19U, WEBSOCKET = 1U << 20U, TRANSACTION_MANAGEMENT = 1U << 21U }; // clang-format on #ifdef MG_ENTERPRISE // clang-format off enum class FineGrainedPermission : uint64_t { NOTHING = 0, READ = 1, UPDATE = 1U << 1U, CREATE_DELETE = 1U << 2U }; // clang-format on constexpr inline uint64_t operator|(FineGrainedPermission lhs, FineGrainedPermission rhs) { return static_cast(lhs) | static_cast(rhs); } constexpr inline uint64_t operator|(uint64_t lhs, FineGrainedPermission rhs) { return lhs | static_cast(rhs); } constexpr inline uint64_t operator&(uint64_t lhs, FineGrainedPermission rhs) { return (lhs & static_cast(rhs)) != 0; } constexpr uint64_t kLabelPermissionAll = memgraph::auth::FineGrainedPermission::CREATE_DELETE | memgraph::auth::FineGrainedPermission::UPDATE | memgraph::auth::FineGrainedPermission::READ; constexpr uint64_t kLabelPermissionMax = static_cast(memgraph::auth::FineGrainedPermission::CREATE_DELETE); constexpr uint64_t kLabelPermissionMin = static_cast(memgraph::auth::FineGrainedPermission::READ); #endif // Function that converts a permission to its string representation. std::string PermissionToString(Permission permission); // Class that indicates what permission level the user/role has. enum class PermissionLevel : uint8_t { GRANT, NEUTRAL, DENY }; // Function that converts a permission level to its string representation. std::string PermissionLevelToString(PermissionLevel level); #ifdef MG_ENTERPRISE // Function that converts a label permission level to its string representation. std::string FineGrainedPermissionToString(FineGrainedPermission level); // Constructs a label permission from a permission FineGrainedPermission PermissionToFineGrainedPermission(uint64_t permission); #endif class Permissions final { public: explicit Permissions(uint64_t grants = 0, uint64_t denies = 0); Permissions(const Permissions &) = default; Permissions &operator=(const Permissions &) = default; Permissions(Permissions &&) noexcept = default; Permissions &operator=(Permissions &&) noexcept = default; ~Permissions() = default; PermissionLevel Has(Permission permission) const; void Grant(Permission permission); void Revoke(Permission permission); void Deny(Permission permission); std::vector GetGrants() const; std::vector GetDenies() const; nlohmann::json Serialize() const; /// @throw AuthException if unable to deserialize. static Permissions Deserialize(const nlohmann::json &data); uint64_t grants() const; uint64_t denies() const; private: uint64_t grants_{0}; uint64_t denies_{0}; }; bool operator==(const Permissions &first, const Permissions &second); bool operator!=(const Permissions &first, const Permissions &second); #ifdef MG_ENTERPRISE class FineGrainedAccessPermissions final { public: explicit FineGrainedAccessPermissions(const std::unordered_map &permissions = {}, const std::optional &global_permission = std::nullopt); FineGrainedAccessPermissions(const FineGrainedAccessPermissions &) = default; FineGrainedAccessPermissions &operator=(const FineGrainedAccessPermissions &) = default; FineGrainedAccessPermissions(FineGrainedAccessPermissions &&) = default; FineGrainedAccessPermissions &operator=(FineGrainedAccessPermissions &&) = default; ~FineGrainedAccessPermissions() = default; PermissionLevel Has(const std::string &permission, FineGrainedPermission fine_grained_permission) const; void Grant(const std::string &permission, FineGrainedPermission fine_grained_permission); void Revoke(const std::string &permission); nlohmann::json Serialize() const; /// @throw AuthException if unable to deserialize. static FineGrainedAccessPermissions Deserialize(const nlohmann::json &data); const std::unordered_map &GetPermissions() const; const std::optional &GetGlobalPermission() const; private: std::unordered_map permissions_{}; std::optional global_permission_; static uint64_t CalculateGrant(FineGrainedPermission fine_grained_permission); }; bool operator==(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second); bool operator!=(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second); class FineGrainedAccessHandler final { public: explicit FineGrainedAccessHandler(FineGrainedAccessPermissions labelPermissions = FineGrainedAccessPermissions(), FineGrainedAccessPermissions edgeTypePermissions = FineGrainedAccessPermissions()); FineGrainedAccessHandler(const FineGrainedAccessHandler &) = default; FineGrainedAccessHandler &operator=(const FineGrainedAccessHandler &) = default; FineGrainedAccessHandler(FineGrainedAccessHandler &&) noexcept = default; FineGrainedAccessHandler &operator=(FineGrainedAccessHandler &&) noexcept = default; ~FineGrainedAccessHandler() = default; const FineGrainedAccessPermissions &label_permissions() const; FineGrainedAccessPermissions &label_permissions(); const FineGrainedAccessPermissions &edge_type_permissions() const; FineGrainedAccessPermissions &edge_type_permissions(); nlohmann::json Serialize() const; /// @throw AuthException if unable to deserialize. static FineGrainedAccessHandler Deserialize(const nlohmann::json &data); friend bool operator==(const FineGrainedAccessHandler &first, const FineGrainedAccessHandler &second); private: FineGrainedAccessPermissions label_permissions_; FineGrainedAccessPermissions edge_type_permissions_; }; bool operator==(const FineGrainedAccessHandler &first, const FineGrainedAccessHandler &second); #endif class Role final { public: explicit Role(const std::string &rolename); Role(const std::string &rolename, const Permissions &permissions); #ifdef MG_ENTERPRISE Role(const std::string &rolename, const Permissions &permissions, FineGrainedAccessHandler fine_grained_access_handler); #endif Role(const Role &) = default; Role &operator=(const Role &) = default; Role(Role &&) noexcept = default; Role &operator=(Role &&) noexcept = default; ~Role() = default; const std::string &rolename() const; const Permissions &permissions() const; Permissions &permissions(); #ifdef MG_ENTERPRISE const FineGrainedAccessHandler &fine_grained_access_handler() const; FineGrainedAccessHandler &fine_grained_access_handler(); const FineGrainedAccessPermissions &GetFineGrainedAccessLabelPermissions() const; const FineGrainedAccessPermissions &GetFineGrainedAccessEdgeTypePermissions() const; #endif nlohmann::json Serialize() const; /// @throw AuthException if unable to deserialize. static Role Deserialize(const nlohmann::json &data); friend bool operator==(const Role &first, const Role &second); private: std::string rolename_; Permissions permissions_; #ifdef MG_ENTERPRISE FineGrainedAccessHandler fine_grained_access_handler_; #endif }; bool operator==(const Role &first, const Role &second); // TODO (mferencevic): Implement password expiry. class User final { public: User(); explicit User(const std::string &username); User(const std::string &username, const std::string &password_hash, const Permissions &permissions); #ifdef MG_ENTERPRISE User(const std::string &username, const std::string &password_hash, const Permissions &permissions, FineGrainedAccessHandler fine_grained_access_handler); #endif User(const User &) = default; User &operator=(const User &) = default; User(User &&) noexcept = default; User &operator=(User &&) noexcept = default; ~User() = default; /// @throw AuthException if unable to verify the password. bool CheckPassword(const std::string &password); /// @throw AuthException if unable to set the password. void UpdatePassword(const std::optional &password = std::nullopt); void SetRole(const Role &role); void ClearRole(); Permissions GetPermissions() const; #ifdef MG_ENTERPRISE FineGrainedAccessPermissions GetFineGrainedAccessLabelPermissions() const; FineGrainedAccessPermissions GetFineGrainedAccessEdgeTypePermissions() const; const FineGrainedAccessHandler &fine_grained_access_handler() const; FineGrainedAccessHandler &fine_grained_access_handler(); #endif const std::string &username() const; const Permissions &permissions() const; Permissions &permissions(); const Role *role() const; nlohmann::json Serialize() const; /// @throw AuthException if unable to deserialize. static User Deserialize(const nlohmann::json &data); friend bool operator==(const User &first, const User &second); private: std::string username_; std::string password_hash_; Permissions permissions_; #ifdef MG_ENTERPRISE FineGrainedAccessHandler fine_grained_access_handler_; #endif std::optional role_; }; bool operator==(const User &first, const User &second); #ifdef MG_ENTERPRISE FineGrainedAccessPermissions Merge(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second); #endif } // namespace memgraph::auth