Skip to content
Snippets Groups Projects
Verified Commit 8b43244d authored by Timm Fitschen's avatar Timm Fitschen
Browse files

WIP: acm

parent 429ddd35
No related branches found
No related tags found
2 merge requests!42Release 0.2.0,!40F dot in username
This commit is part of merge request !42. Comments created here will be created in the context of that merge request.
Showing with 844 additions and 70 deletions
...@@ -81,6 +81,7 @@ add_subdirectory(doc) ...@@ -81,6 +81,7 @@ add_subdirectory(doc)
set(PROTO_FILES set(PROTO_FILES
${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1/main.proto ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1/main.proto
${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1/main.proto ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1/main.proto
${PROJECT_SOURCE_DIR}/proto/proto/caosdb/acm/v1alpha1/main.proto
) )
set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto) set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto)
...@@ -173,6 +174,7 @@ target_link_libraries(caosdb ...@@ -173,6 +174,7 @@ target_link_libraries(caosdb
target_include_directories(caosdb PUBLIC target_include_directories(caosdb PUBLIC
$<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include> $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include> $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>
$<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_include_directories(caosdb SYSTEM PUBLIC target_include_directories(caosdb SYSTEM PUBLIC
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
# add all header files to this list # add all header files to this list
set(libcaosdb_INCL set(libcaosdb_INCL
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/acm/role.h
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.h
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/certificate_provider.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/certificate_provider.h
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/configuration.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/configuration.h
......
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* @brief PermissionRules grant or deny permissions to roles.
*
* @file caosdb/acm/permission_rule.h
* @author Timm Fitchen
* @date 2022-02-11
*/
#ifndef CAOSDB_ACM_PERMISSION_RULE_H
#define CAOSDB_ACM_PERMISSION_RULE_H
#include <unordered_set> // for unordered_set
#include <string> // for string
namespace caosdb::acm {
class PermissionRuleImpl;
class PermissionRule {
public:
PermissionRule(std::string permission, bool isGrant, bool isPriority);
explicit PermissionRule(PermissionRuleImpl *wrapped);
PermissionRule(const PermissionRule &rule);
auto operator=(const PermissionRule &rule) -> PermissionRule &;
~PermissionRule();
auto ToString() const -> std::string;
[[nodiscard]] auto IsGrant() const -> const bool;
auto SetGrant(bool isGrant) -> void;
[[nodiscard]] auto IsPriority() const -> const bool;
auto SetPriority(bool isPriority) -> void;
[[nodiscard]] auto GetPermission() const -> const std::string &;
auto operator==(const PermissionRule &other) const -> bool;
private:
PermissionRuleImpl *impl;
};
struct HashPermissionRule {
size_t operator()(const PermissionRule& rule) const {
return std::hash<std::string>()(rule.GetPermission());
}
};
using PermissionRules = std::unordered_set<PermissionRule, HashPermissionRule>;
} // namespace caosdb::acm
#endif
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* @brief Roles, together with users, and permissions are a fundamental concept
* of the access controll management of CaosDB.
*
* @file caosdb/acm/role.h
* @author Timm Fitchen
* @date 2022-02-11
*/
#ifndef CAOSDB_ACM_ROLES_H
#define CAOSDB_ACM_ROLES_H
#include "caosdb/acm/permission_rule.h" // for PermissionRule
#include <string> // for string
#include <vector> // for vector
namespace caosdb::connection {
class Connection;
}
namespace caosdb::acm {
class RoleImpl;
class Role {
public:
explicit Role(std::string name);
explicit Role(RoleImpl *wrapped);
Role(std::string name, std::string description);
Role(const Role &role);
auto operator=(const Role &role) -> Role &;
~Role();
auto ToString() const -> std::string;
[[nodiscard]] auto GetName() const -> const std::string &;
auto SetName(std::string name) -> void;
[[nodiscard]] auto GetDescription() const -> const std::string &;
auto SetDescription(std::string description) -> void;
// TODO(tf) declare and implement:
[[nodiscard]] auto GetPermissionRules() const -> const PermissionRules &;
// auto SetPermissionRules(PermissionRules rules) -> void;
// auto ClearPermissionRules() -> void;
auto Grant(std::string permission, bool priority) -> void;
// auto Deny(std::string permission, bool priority) -> void;
auto RevokeGrant(std::string permission, bool priority) -> void;
// auto RevokeDenial(std::string permission, bool priority) -> void;
friend class caosdb::connection::Connection;
private:
RoleImpl *wrapped;
};
} // namespace caosdb::acm
#endif
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
* @date 2021-05-18 * @date 2021-05-18
* @brief Configuration and setup of the connection. * @brief Configuration and setup of the connection.
*/ */
#include "caosdb/acm/role.h" // for Role
#include "caosdb/acm/v1alpha1/main.grpc.pb.h" // for AccessControlMan...
#include "caosdb/authentication.h" // for Authenticator #include "caosdb/authentication.h" // for Authenticator
#include "caosdb/configuration.h" // for ConnectionConfigura... #include "caosdb/configuration.h" // for ConnectionConfigura...
#include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransactionSe... #include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransactionSe...
...@@ -39,8 +41,11 @@ ...@@ -39,8 +41,11 @@
#include <map> // for map #include <map> // for map
#include <memory> // for shared_ptr, unique_ptr #include <memory> // for shared_ptr, unique_ptr
#include <string> // for string, basic_string #include <string> // for string, basic_string
#include <vector> // for vector
namespace caosdb::connection { namespace caosdb::connection {
using caosdb::acm::Role;
using caosdb::acm::v1alpha1::AccessControlManagementService;
using caosdb::authentication::Authenticator; using caosdb::authentication::Authenticator;
using caosdb::configuration::ConnectionConfiguration; using caosdb::configuration::ConnectionConfiguration;
using caosdb::entity::v1::EntityTransactionService; using caosdb::entity::v1::EntityTransactionService;
...@@ -89,8 +94,22 @@ public: ...@@ -89,8 +94,22 @@ public:
return this->version_info.get(); return this->version_info.get();
}; };
/**
* Create a new transaction object which uses this connection and return it.
*/
[[nodiscard]] auto CreateTransaction() const -> std::unique_ptr<Transaction>; [[nodiscard]] auto CreateTransaction() const -> std::unique_ptr<Transaction>;
/**
* List all known roles.
*/
[[nodiscard]] auto ListRoles() const -> std::vector<Role>;
[[nodiscard]] auto RetrieveSingleRole(std::string name) const -> Role;
auto CreateSingleRole(const Role &role) const -> void;
auto DeleteSingleRole(std::string name) const -> void;
private: private:
/// GRPC-Channel (HTTP/2 Connection plus Authentication). We use a shared /// GRPC-Channel (HTTP/2 Connection plus Authentication). We use a shared
/// pointer because Transaction instances also own the channel. /// pointer because Transaction instances also own the channel.
...@@ -107,6 +126,10 @@ private: ...@@ -107,6 +126,10 @@ private:
/// Service for file transmission (download and upload). We use a shared /// Service for file transmission (download and upload). We use a shared
/// pointer because Transaction instances also own this service stub. /// pointer because Transaction instances also own this service stub.
std::shared_ptr<FileTransmissionService::Stub> file_transmission_service; std::shared_ptr<FileTransmissionService::Stub> file_transmission_service;
/// Service for Access Controll Management (Role, Useraccounts, Permissions).
/// We use a unique pointer because only this connection owns and uses this
/// service.
std::unique_ptr<AccessControlManagementService::Stub> access_controll_management_service;
}; };
/** /**
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
# add all source files to this list # add all source files to this list
set(libcaosdb_SRC set(libcaosdb_SRC
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/acm/role.cpp
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/acm/role_impl.h
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/acm/permission_rule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.cpp
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/entity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/entity.cpp
${CMAKE_CURRENT_SOURCE_DIR}/caosdb/logging.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/logging.cpp
......
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "caosdb/acm/permission_rule.h"
#include "caosdb/acm/permission_rule_impl.h" // for PermissionRuleImpl
#include "caosdb/acm/v1alpha1/main.pb.h" // for ListPermissionRulesRequest
#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper
#include <utility> // for move
namespace caosdb::acm {
using caosdb::utility::ScalarProtoMessageWrapper;
using ProtoPermissionRule = caosdb::acm::v1alpha1::PermissionRule;
PermissionRuleImpl::PermissionRuleImpl() : ScalarProtoMessageWrapper<ProtoPermissionRule>() {}
PermissionRuleImpl::PermissionRuleImpl(ProtoPermissionRule *rule)
: ScalarProtoMessageWrapper<ProtoPermissionRule>(rule) {}
PermissionRuleImpl::PermissionRuleImpl(std::string permission, bool isGrant, bool isPriority)
: PermissionRuleImpl() {
this->wrapped->set_permission(std::move(permission));
this->wrapped->set_grant(isGrant);
this->wrapped->set_priority(isPriority);
}
PermissionRule::PermissionRule(std::string permission, bool isGrant, bool isPriority)
: impl(new PermissionRuleImpl(std::move(permission), isGrant, isPriority)) {}
PermissionRule::PermissionRule(const PermissionRule &rule) : impl(new PermissionRuleImpl()) {
this->impl->wrapped->CopyFrom(*(rule.impl->wrapped));
}
auto PermissionRule::operator=(const PermissionRule &rule) -> PermissionRule & {
this->impl->wrapped->CopyFrom(*(rule.impl->wrapped));
return *this;
}
PermissionRule::~PermissionRule() { delete this->impl; }
auto PermissionRule::ToString() const -> std::string { return this->impl->ToString(); }
[[nodiscard]] auto PermissionRule::IsGrant() const -> const bool {
return this->impl->wrapped->grant();
}
auto PermissionRule::SetGrant(bool isGrant) -> void { this->impl->wrapped->set_grant(isGrant); }
[[nodiscard]] auto PermissionRule::IsPriority() const -> const bool {
return this->impl->wrapped->priority();
}
auto PermissionRule::SetPriority(bool isPriority) -> void {
this->impl->wrapped->set_priority(isPriority);
}
auto PermissionRule::operator==(const PermissionRule &other) const -> bool {
return this->GetPermission() == other.GetPermission();
}
auto PermissionRule::GetPermission() const -> const std::string & {
return this->impl->wrapped->permission();
}
} // namespace caosdb::acm
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef CAOSDB_ACM_PERMISSION_RULE_IMPL_H
#define CAOSDB_ACM_PERMISSION_RULE_IMPL_H
#include "caosdb/acm/role.h"
#include "caosdb/acm/v1alpha1/main.pb.h" // for ListRolesRequest
#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper
#include <utility> // for move
namespace caosdb::acm {
using caosdb::utility::ScalarProtoMessageWrapper;
using ProtoPermissionRule = caosdb::acm::v1alpha1::PermissionRule;
/**
* PermissionRuleImpl class is designed to hide the implementation which makes direct use
* of the protobuf objects underneath from the clients of the caosdb library.
*/
class PermissionRuleImpl : public ScalarProtoMessageWrapper<ProtoPermissionRule> {
public:
/**
* Constructor. Instanciate a role from the server's responces.
*/
PermissionRuleImpl(ProtoPermissionRule *rule);
PermissionRuleImpl();
PermissionRuleImpl(std::string permission, bool isGrant, bool isPriority);
friend class PermissionRule;
};
} // namespace caosdb::acm
#endif
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "caosdb/acm/role.h"
#include "caosdb/acm/permission_rule.h" // for PermissionRule
#include "caosdb/acm/role_impl.h" // for RoleImpl
#include "caosdb/acm/v1alpha1/main.pb.h" // for ListRolesRequest
#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper
#include <utility> // for move
#include <vector> // for vector
namespace caosdb::acm {
using caosdb::utility::ScalarProtoMessageWrapper;
using ProtoRole = caosdb::acm::v1alpha1::Role;
using ProtoRolePermissions = caosdb::acm::v1alpha1::RolePermissions;
using ProtoRoleCapabilities = caosdb::acm::v1alpha1::RoleCapabilities;
using ProtoListRoleItem = caosdb::acm::v1alpha1::ListRoleItem;
RoleImpl::RoleImpl(std::string name, std::string description)
: ScalarProtoMessageWrapper<ProtoRole>() {
if (!name.empty()) {
this->wrapped->set_name(name);
}
if (!description.empty()) {
this->wrapped->set_description(description);
}
}
RoleImpl::RoleImpl(ProtoRole *role) : ScalarProtoMessageWrapper<ProtoRole>(role) {}
RoleImpl::RoleImpl(ProtoListRoleItem &role_item)
: ScalarProtoMessageWrapper<ProtoRole>(role_item.release_role()) {}
RoleImpl::RoleImpl(std::string name) : RoleImpl(std::move(name), "") {}
Role::Role(RoleImpl *wrapped) : wrapped(std::move(wrapped)) {}
Role::Role(std::string name, std::string description)
: wrapped(new RoleImpl(std::move(name), std::move(description))) {}
Role::Role(std::string name) : Role(std::move(name), {""}) {}
Role::Role(const Role &role) : Role(role.GetName(), role.GetDescription()) {}
auto Role::operator=(const Role &role) -> Role & {
this->wrapped->wrapped->CopyFrom(*(role.wrapped->wrapped));
return *this;
}
Role::~Role() { delete this->wrapped; }
auto Role::GetName() const -> const std::string & { return this->wrapped->wrapped->name(); }
auto Role::SetName(std::string name) -> void {
if (!name.empty()) {
this->wrapped->wrapped->set_name(std::move(name));
} else {
this->wrapped->wrapped->clear_name();
}
}
auto Role::GetDescription() const -> const std::string & {
return this->wrapped->wrapped->description();
}
auto Role::SetDescription(std::string description) -> void {
if (!description.empty()) {
this->wrapped->wrapped->set_description(std::move(description));
} else {
this->wrapped->wrapped->clear_description();
}
}
auto Role::ToString() const -> std::string { return this->wrapped->ToString(); }
[[nodiscard]] auto Role::GetPermissionRules() const -> const PermissionRules & {
return this->wrapped->rules;
}
auto Role::Grant(std::string permission, bool isPriority) -> void {
this->wrapped->rules.emplace(std::move(permission), true, isPriority);
}
auto Role::RevokeGrant(std::string permission, bool isPriority) -> void {
auto rule = this->wrapped->rules.begin();
while (rule != this->wrapped->rules.end()) {
if (rule->IsGrant() && rule->IsPriority() == isPriority &&
rule->GetPermission() == permission) {
this->wrapped->rules.erase(rule);
return;
} else {
rule++;
}
}
}
} // namespace caosdb::acm
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "caosdb/acm/role.h"
#include "caosdb/acm/v1alpha1/main.pb.h" // for ListRolesRequest
#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper
#include <utility> // for move
namespace caosdb::acm {
using caosdb::utility::ScalarProtoMessageWrapper;
using ProtoRole = caosdb::acm::v1alpha1::Role;
using ProtoRolePermissions = caosdb::acm::v1alpha1::RolePermissions;
using ProtoRoleCapabilities = caosdb::acm::v1alpha1::RoleCapabilities;
using ProtoListRoleItem = caosdb::acm::v1alpha1::ListRoleItem;
/**
* RoleImpl class is designed to hide the implementation which makes direct use
* of the protobuf objects underneath from the clients of the caosdb library.
*/
class RoleImpl : public ScalarProtoMessageWrapper<ProtoRole> {
public:
/**
* Constructor. Instanciate a role with the given name.
*/
explicit RoleImpl(std::string name);
/**
* Constructor. Instanciate a role with the given name and description.
*/
RoleImpl(std::string name, std::string description);
/**
* Constructor. Instanciate a role from the server's responces.
*/
RoleImpl(ProtoRole *role);
/**
* Constructor. Instanciate a role from a listRoles RPC.
*/
RoleImpl(ProtoListRoleItem &role);
friend class Role;
friend class caosdb::connection::Connection;
private:
PermissionRules rules;
};
} // namespace caosdb::acm
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
* *
*/ */
#include "caosdb/connection.h" #include "caosdb/connection.h"
#include "caosdb/acm/role_impl.h" // for RoleImpl
#include "caosdb/acm/v1alpha1/main.grpc.pb.h" // for AccessControlMan...
#include "caosdb/acm/v1alpha1/main.pb.h" // for ListRolesRequest
#include "caosdb/configuration.h" // for ConnectionConfigur... #include "caosdb/configuration.h" // for ConnectionConfigur...
#include "caosdb/exceptions.h" // for ConfigurationError #include "caosdb/exceptions.h" // for ConfigurationError
#include "caosdb/info.h" // for VersionInfo #include "caosdb/info.h" // for VersionInfo
...@@ -27,13 +30,23 @@ ...@@ -27,13 +30,23 @@
#include "caosdb/info/v1/main.pb.h" // for GetVersionInfoRequest #include "caosdb/info/v1/main.pb.h" // for GetVersionInfoRequest
#include "caosdb/transaction.h" // for Transaction #include "caosdb/transaction.h" // for Transaction
#include "caosdb/transaction_status.h" // for TransactionStatus #include "caosdb/transaction_status.h" // for TransactionStatus
#include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH...
#include <grpcpp/create_channel.h> // for CreateChannel #include <grpcpp/create_channel.h> // for CreateChannel
#include <grpcpp/impl/codegen/client_context.h> // for ClientContext #include <grpcpp/impl/codegen/client_context.h> // for ClientContext
#include <grpcpp/impl/codegen/status.h> // for Status #include <grpcpp/impl/codegen/status.h> // for Status
#include <grpcpp/impl/codegen/status_code_enum.h> // for StatusCode, UNAUTH...
#include <string> // for string, operator+ #include <string> // for string, operator+
namespace caosdb::connection { namespace caosdb::connection {
using caosdb::acm::RoleImpl;
using caosdb::acm::v1alpha1::AccessControlManagementService;
using caosdb::acm::v1alpha1::CreateSingleRoleRequest;
using caosdb::acm::v1alpha1::CreateSingleRoleResponse;
using caosdb::acm::v1alpha1::DeleteSingleRoleRequest;
using caosdb::acm::v1alpha1::DeleteSingleRoleResponse;
using caosdb::acm::v1alpha1::ListRolesRequest;
using caosdb::acm::v1alpha1::ListRolesResponse;
using caosdb::acm::v1alpha1::RetrieveSingleRoleRequest;
using caosdb::acm::v1alpha1::RetrieveSingleRoleResponse;
using caosdb::configuration::ConfigurationManager; using caosdb::configuration::ConfigurationManager;
using caosdb::configuration::ConnectionConfiguration; using caosdb::configuration::ConnectionConfiguration;
using caosdb::entity::v1::EntityTransactionService; using caosdb::entity::v1::EntityTransactionService;
...@@ -53,6 +66,8 @@ Connection::Connection(const ConnectionConfiguration &configuration) { ...@@ -53,6 +66,8 @@ Connection::Connection(const ConnectionConfiguration &configuration) {
this->entity_transaction_service = this->entity_transaction_service =
std::make_shared<EntityTransactionService::Stub>(this->channel); std::make_shared<EntityTransactionService::Stub>(this->channel);
this->file_transmission_service = std::make_shared<FileTransmissionService::Stub>(this->channel); this->file_transmission_service = std::make_shared<FileTransmissionService::Stub>(this->channel);
this->access_controll_management_service =
std::make_unique<AccessControlManagementService::Stub>(this->channel);
} }
auto Connection::RetrieveVersionInfoNoExceptions() const noexcept -> TransactionStatus { auto Connection::RetrieveVersionInfoNoExceptions() const noexcept -> TransactionStatus {
...@@ -97,6 +112,121 @@ auto Connection::RetrieveVersionInfo() const -> const VersionInfo & { ...@@ -97,6 +112,121 @@ auto Connection::RetrieveVersionInfo() const -> const VersionInfo & {
return std::make_unique<Transaction>(entity_service, file_service); return std::make_unique<Transaction>(entity_service, file_service);
} }
[[nodiscard]] auto Connection::RetrieveSingleRole(std::string name) const -> Role {
RetrieveSingleRoleRequest request;
request.set_name(name);
RetrieveSingleRoleResponse response;
grpc::ClientContext context;
const grpc::Status grpc_status =
this->access_controll_management_service->RetrieveSingleRole(&context, request, &response);
auto status = TransactionStatus::SUCCESS();
if (!grpc_status.ok()) {
switch (grpc_status.error_code()) {
case grpc::StatusCode::UNAUTHENTICATED:
status = TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
break;
case grpc::StatusCode::UNAVAILABLE:
status = TransactionStatus::CONNECTION_ERROR();
break;
default:
auto error_message = grpc_status.error_message();
status = TransactionStatus::RPC_ERROR(std::to_string(grpc_status.error_code()) + " - " +
error_message);
}
}
status.ThrowExceptionIfError();
auto *role = response.release_role();
return Role(new RoleImpl(role));
}
auto Connection::DeleteSingleRole(std::string name) const -> void {
DeleteSingleRoleRequest request;
request.set_name(name);
DeleteSingleRoleResponse response;
grpc::ClientContext context;
const grpc::Status grpc_status =
this->access_controll_management_service->DeleteSingleRole(&context, request, &response);
auto status = TransactionStatus::SUCCESS();
std::vector<Role> result;
if (!grpc_status.ok()) {
switch (grpc_status.error_code()) {
case grpc::StatusCode::UNAUTHENTICATED:
status = TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
break;
case grpc::StatusCode::UNAVAILABLE:
status = TransactionStatus::CONNECTION_ERROR();
break;
default:
auto error_message = grpc_status.error_message();
status = TransactionStatus::RPC_ERROR(std::to_string(grpc_status.error_code()) + " - " +
error_message);
}
}
status.ThrowExceptionIfError();
}
auto Connection::CreateSingleRole(const Role &role) const -> void {
CreateSingleRoleRequest request;
request.set_allocated_role(role.wrapped->wrapped);
CreateSingleRoleResponse response;
grpc::ClientContext context;
const grpc::Status grpc_status =
this->access_controll_management_service->CreateSingleRole(&context, request, &response);
auto status = TransactionStatus::SUCCESS();
std::vector<Role> result;
if (!grpc_status.ok()) {
switch (grpc_status.error_code()) {
case grpc::StatusCode::UNAUTHENTICATED:
status = TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
break;
case grpc::StatusCode::UNAVAILABLE:
status = TransactionStatus::CONNECTION_ERROR();
break;
default:
auto error_message = grpc_status.error_message();
status = TransactionStatus::RPC_ERROR(std::to_string(grpc_status.error_code()) + " - " +
error_message);
}
}
status.ThrowExceptionIfError();
}
[[nodiscard]] auto Connection::ListRoles() const -> std::vector<Role> {
const ListRolesRequest request;
ListRolesResponse response;
grpc::ClientContext context;
const grpc::Status grpc_status =
this->access_controll_management_service->ListRoles(&context, request, &response);
auto status = TransactionStatus::SUCCESS();
std::vector<Role> result;
if (!grpc_status.ok()) {
switch (grpc_status.error_code()) {
case grpc::StatusCode::UNAUTHENTICATED:
status = TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
break;
case grpc::StatusCode::UNAVAILABLE:
status = TransactionStatus::CONNECTION_ERROR();
break;
default:
auto error_message = grpc_status.error_message();
status = TransactionStatus::RPC_ERROR(std::to_string(grpc_status.error_code()) + " - " +
error_message);
}
}
status.ThrowExceptionIfError();
auto *roles = response.mutable_roles();
for (auto &role_item : *roles) {
auto *implementation = new RoleImpl(role_item);
result.emplace_back(implementation);
}
return result;
}
auto ConnectionManager::mHasConnection(const std::string &name) const -> bool { auto ConnectionManager::mHasConnection(const std::string &name) const -> bool {
auto it = connections.find(name); auto it = connections.find(name);
return it != connections.end(); return it != connections.end();
......
...@@ -29,11 +29,7 @@ ...@@ -29,11 +29,7 @@
#include "caosdb/logging.h" // for CAOSDB_LOG_TRACE #include "caosdb/logging.h" // for CAOSDB_LOG_TRACE
#include "caosdb/transaction.h" // for Transaction, ResultSet #include "caosdb/transaction.h" // for Transaction, ResultSet
#include "caosdb/transaction_status.h" // for TransactionSt... #include "caosdb/transaction_status.h" // for TransactionSt...
#include <boost/log/core/record.hpp> // for record #include <boost/program_options.hpp> // for options_description
#include <boost/log/detail/attachable_sstream_buf.hpp> // for basic_ostring...
#include <boost/log/sources/record_ostream.hpp> // for operator<<
#include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_...
#include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_...
#include <exception> // for exception #include <exception> // for exception
#include <iostream> // for operator<<, basic_ostream, basic_ost... #include <iostream> // for operator<<, basic_ostream, basic_ost...
#include <memory> // for unique_ptr, allocator, __shared_ptr_... #include <memory> // for unique_ptr, allocator, __shared_ptr_...
...@@ -41,14 +37,27 @@ ...@@ -41,14 +37,27 @@
const auto logger_name = "libcaosdb"; const auto logger_name = "libcaosdb";
auto main() -> int { using boost::program_options::bool_switch;
using boost::program_options::command_line_parser;
using boost::program_options::notify;
using boost::program_options::options_description;
using boost::program_options::parse_command_line;
using boost::program_options::positional_options_description;
using boost::program_options::store;
using boost::program_options::value;
using boost::program_options::variables_map;
using caosdb::acm::Role;
std::cout << "CaosDB C++ client (libcaosdb " << caosdb::LIBCAOSDB_VERSION_MINOR << "." auto print_version(bool print) -> void {
if (print) {
std::cout << "CaosDB C++ client (libcaosdb " << caosdb::LIBCAOSDB_VERSION_MAJOR << "."
<< caosdb::LIBCAOSDB_VERSION_MINOR << "." << caosdb::LIBCAOSDB_VERSION_PATCH << ")\n" << caosdb::LIBCAOSDB_VERSION_MINOR << "." << caosdb::LIBCAOSDB_VERSION_PATCH << ")\n"
<< "We don't miss the H of caos.\n" << "We don't miss the H of caos.\n"
<< std::endl; << std::endl;
}
}
try { auto test_connection() -> void {
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection(); const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
connection->RetrieveVersionInfoNoExceptions(); connection->RetrieveVersionInfoNoExceptions();
...@@ -57,10 +66,13 @@ auto main() -> int { ...@@ -57,10 +66,13 @@ auto main() -> int {
std::cout << "Server Version: " << v_info->GetMajor() << "." << v_info->GetMinor() << "." std::cout << "Server Version: " << v_info->GetMajor() << "." << v_info->GetMinor() << "."
<< v_info->GetPatch() << "-" << v_info->GetPreRelease() << "-" << v_info->GetBuild() << v_info->GetPatch() << "-" << v_info->GetPreRelease() << "-" << v_info->GetBuild()
<< std::endl; << std::endl;
}
// retrieve an entity auto retrieve_entity_by_id(std::string id) -> void {
std::cout << "Retrieve entity " << id << std::endl;
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
auto transaction(connection->CreateTransaction()); auto transaction(connection->CreateTransaction());
transaction->RetrieveById("21"); transaction->RetrieveById(id);
transaction->ExecuteAsynchronously(); transaction->ExecuteAsynchronously();
auto t_stat = transaction->WaitForIt(); auto t_stat = transaction->WaitForIt();
CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // " CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // "
...@@ -69,20 +81,94 @@ auto main() -> int { ...@@ -69,20 +81,94 @@ auto main() -> int {
for (const auto &entity : result_set) { for (const auto &entity : result_set) {
std::cout << entity.ToString() << std::endl; std::cout << entity.ToString() << std::endl;
} }
}
// execute a query auto execute_query(std::string query) -> void {
std::string query("FIND Property \"Prop *\""); std::cout << "Execute query:\n" << query << std::endl;
std::cout << "Trying to execute a query:\n" << query << std::endl; const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
auto q_transaction(connection->CreateTransaction()); auto q_transaction(connection->CreateTransaction());
q_transaction->Query(query); q_transaction->Query(query);
q_transaction->ExecuteAsynchronously(); q_transaction->ExecuteAsynchronously();
t_stat = q_transaction->WaitForIt(); auto t_stat = q_transaction->WaitForIt();
CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // " CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // "
<< t_stat.GetDescription(); << t_stat.GetDescription();
const auto &result_set_2 = q_transaction->GetResultSet(); const auto &result_set_2 = q_transaction->GetResultSet();
for (const auto &entity : result_set_2) { for (const auto &entity : result_set_2) {
std::cout << entity.ToString() << std::endl; std::cout << entity.ToString() << std::endl;
} }
}
auto list_roles() -> void {
std::cout << "Known roles:" << std::endl;
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
auto roles = connection->ListRoles();
for (const auto role : roles) {
std::cout << role.ToString() << std::endl;
}
}
auto retrieve_role(std::string name) {
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
auto role = connection->RetrieveSingleRole(name);
std::cout << role.ToString() << std::endl;
}
auto create_role(std::string name) {
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
Role role(name);
connection->CreateSingleRole(role);
std::cout << "OK" << std::endl;
}
auto delete_role(std::string name) {
const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
connection->DeleteSingleRole(name);
std::cout << "OK" << std::endl;
}
auto main(int argc, const char *argv[]) -> int {
try {
command_line_parser parser(argc, argv);
options_description desc{"Options"};
desc.add_options()("help,h", "Show help.")("version,V", bool_switch()->notifier(print_version),
"Print version of libcaosdb.")(
"test-connection,t", "Test the connection to the caosdb server.")(
"retrieve", value<std::string>()->notifier(retrieve_entity_by_id),
"Retrieve an entity by id and print its JSON representation.")(
"execute-query", value<std::string>()->notifier(execute_query),
"Execute a query and print the results")("list-roles", "List all known roles")(
"retrieve-role", value<std::string>()->notifier(retrieve_role), "Retrieve a role by name")(
"create-role", value<std::string>()->notifier(create_role), "Create a new role")(
"delete-role", value<std::string>()->notifier(delete_role), "Create a new role");
parser.options(desc);
// TODO(tf) add positional parameters
// positional_options_description pos_desc;
// pos_desc.add("phone", 1);
// parser.positional(pos_desc);
variables_map vm;
store(parser.run(), vm);
notify(vm);
if (vm.count("help")) {
std::cout << desc << std::endl;
} else if (vm["version"].as<bool>()) {
} else if (vm.count("test-connection")) {
test_connection();
} else if (vm.count("list-roles")) {
list_roles();
} else if (vm.count("retrieve-role")) {
} else if (vm.count("retrieve")) {
} else if (vm.count("create-role")) {
} else if (vm.count("delete-role")) {
} else if (vm.count("execute-query")) {
} else {
print_version(true);
test_connection();
}
return 0; return 0;
} catch (const caosdb::exceptions::ConfigurationError &exc) { } catch (const caosdb::exceptions::ConfigurationError &exc) {
...@@ -92,7 +178,7 @@ auto main() -> int { ...@@ -92,7 +178,7 @@ auto main() -> int {
std::cout << "Exception: " << exc.what() << std::endl; std::cout << "Exception: " << exc.what() << std::endl;
return 1; return 1;
} catch (...) { } catch (...) {
std::cout << "Some other exception." << std::endl; std::cout << "Unknown error." << std::endl;
return 2; return 2;
} }
} }
...@@ -29,6 +29,7 @@ set(test_cases ...@@ -29,6 +29,7 @@ set(test_cases
test_issues test_issues
test_list_properties test_list_properties
test_protobuf test_protobuf
test_role
test_transaction test_transaction
test_utility test_utility
test_value test_value
...@@ -41,7 +42,7 @@ set(test_cases ...@@ -41,7 +42,7 @@ set(test_cases
# special linting for tests # special linting for tests
set(_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS set(_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS
"${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-clang-analyzer-cplusplus.Move" "${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-clang-analyzer-cplusplus.Move,-clang-diagnostic-unused-result"
) )
# add special cmake functions for gtest # add special cmake functions for gtest
......
...@@ -87,4 +87,11 @@ TEST_F(test_connection, connection_manager_get_connection) { ...@@ -87,4 +87,11 @@ TEST_F(test_connection, connection_manager_get_connection) {
EXPECT_TRUE(ConnectionManager::GetConnection("local-caosdb-admin")); EXPECT_TRUE(ConnectionManager::GetConnection("local-caosdb-admin"));
} }
TEST_F(test_connection, test_list_roles) {
auto connection = ConnectionManager::GetDefaultConnection();
EXPECT_THROW_MESSAGE(auto results = connection->ListRoles(), caosdb::exceptions::ConnectionError,
"The attempt to execute this transaction was not successful because the "
"connection to the server could not be established.");
}
} // namespace caosdb::connection } // namespace caosdb::connection
/*
*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "caosdb/acm/role.h" // for Role
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiRe...
#include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ, TEST
#include <memory> // for allocator
namespace caosdb::acm {
TEST(test_role, role_name) {
auto role = Role("role1");
EXPECT_EQ(role.GetName(), "role1");
role.SetName("role2");
EXPECT_EQ(role.GetName(), "role2");
}
TEST(test_role, role_description) {
auto role1 = Role("role1", "description1");
EXPECT_EQ(role1.GetName(), "role1");
EXPECT_EQ(role1.GetDescription(), "description1");
role1.SetName("role3");
EXPECT_EQ(role1.GetDescription(), "description1");
auto role2 = Role("role2", "description1");
EXPECT_EQ(role2.GetDescription(), "description1");
EXPECT_EQ(role2.GetName(), "role2");
role2.SetDescription("description2");
EXPECT_EQ(role2.GetDescription(), "description2");
EXPECT_EQ(role2.GetName(), "role2");
}
TEST(test_role, get_permission_rules) {
auto role1 = Role("role1", "description1");
EXPECT_TRUE(role1.GetPermissionRules().empty());
role1.Grant("SOME_PERMISSION", false);
EXPECT_FALSE(role1.GetPermissionRules().empty());
role1.Grant("SOME_OTHER_PERMISSION", true);
EXPECT_FALSE(role1.GetPermissionRules().empty());
role1.RevokeGrant("SOME_PERMISSION", false);
EXPECT_FALSE(role1.GetPermissionRules().empty());
role1.RevokeGrant("SOME_OTHER_PERMISSION", true);
EXPECT_TRUE(role1.GetPermissionRules().empty());
}
} // namespace caosdb::acm
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment