Using new permissions system consequently

This commit is contained in:
WolverinDEV 2020-01-26 14:21:34 +01:00
parent d42ec40a58
commit 23a9385afe
5 changed files with 182 additions and 35 deletions

View File

@ -70,6 +70,14 @@ namespace ts {
return BasicChannel::permission_granted(data,granted_value, require_granted_value);
}
ts_always_inline bool talk_power_granted(const permission::v2::PermissionFlaggedValue& granted_value) {
return this->permission_granted(permission::i_client_needed_talk_power, granted_value, false);
}
ts_always_inline std::shared_ptr<permission::v2::PermissionManager> permissions(){ return this->_permissions; }
virtual void setPermissionManager(const std::shared_ptr<permission::v2::PermissionManager>&);
virtual void setProperties(const std::shared_ptr<Properties>&);
private:
ts_always_inline
static bool permission_granted(const permission::v2::PermissionFlaggedValue& channel_permission_value, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) {
if(!channel_permission_value.has_value || channel_permission_value.value == 0) {
@ -81,14 +89,6 @@ namespace ts {
return granted_value.value >= channel_permission_value.value;
}
ts_always_inline bool talk_power_granted(const permission::v2::PermissionFlaggedValue& granted_value) {
return this->permission_granted(permission::i_client_needed_talk_power, granted_value, false);
}
ts_always_inline std::shared_ptr<permission::v2::PermissionManager> permissions(){ return this->_permissions; }
virtual void setPermissionManager(const std::shared_ptr<permission::v2::PermissionManager>&);
virtual void setProperties(const std::shared_ptr<Properties>&);
protected:
public:
ChannelId channelId() const override;
ChannelId previousChannelId() const override;

View File

@ -15,6 +15,7 @@
#include "./misc/spin_lock.h"
#include "Definitions.h"
#include "Variable.h"
#include "spdlog/fmt/ostr.h" // must be included
#define permNotGranted (-2)
#define PERM_ID_GRANT ((ts::permission::PermissionType) (1 << 15))
@ -809,9 +810,33 @@ namespace ts {
struct PermissionFlaggedValue {
PermissionValue value = permNotGranted;
bool has_value = false;
constexpr bool has_power() const { return this->has_value && (this->value > 0 || this->value == -1); }
constexpr bool has_infinite_power() const { return this->has_value && this->value == -1; }
inline bool operator==(const PermissionFlaggedValue& other) const { return other.value == this->value && other.has_value == this->has_value; }
inline bool operator!=(const PermissionFlaggedValue& other) const { return !(*this == other); }
};
static constexpr PermissionFlaggedValue empty_permission_flagged_value{0, false};
static constexpr bool permission_granted(const PermissionFlaggedValue& required, const PermissionFlaggedValue& given, bool requires_given = true) {
if(!required.has_value) {
return !requires_given || given.has_power();
} else if(!given.has_power()) {
return false;
} else if(given.has_infinite_power()) {
return true;
} else if(required.has_infinite_power()) {
return false;
} else {
return given.value >= required.value;
}
}
static constexpr bool permission_granted(const PermissionValue& required, const PermissionFlaggedValue& given, bool requires_given = true) {
return permission_granted({required, true}, given, requires_given);
}
class PermissionManager {
public:
static constexpr size_t PERMISSIONS_BULK_BITS = 4; /* 16 permissions per block */
@ -909,6 +934,13 @@ namespace ts {
}
}
inline std::ostream& operator<<(std::ostream& os, const ts::permission::v2::PermissionFlaggedValue& c) {
if(c.has_value)
return os << c.value;
else
return os << "unset";
}
DEFINE_VARIABLE_TRANSFORM(ts::permission::PermissionType, VARTYPE_INT, std::to_string((int16_t) in), static_cast<ts::permission::PermissionType>(in.as<int16_t>()));
DEFINE_VARIABLE_TRANSFORM(ts::permission::PermissionGroup, VARTYPE_INT, std::to_string((uint16_t) in), static_cast<ts::permission::PermissionGroup>(in.as<uint16_t>()));
DEFINE_VARIABLE_TRANSFORM(ts::permission::PermissionSqlType, VARTYPE_INT, std::to_string((int8_t) in), static_cast<ts::permission::PermissionSqlType>(in.as<int8_t>()));

View File

@ -3,6 +3,7 @@
#include <string>
#include <cstddef>
#include <vector>
#include <optional>
#include "escape.h"
#include "converters/converter.h"
@ -10,6 +11,36 @@
namespace ts {
namespace impl {
inline bool value_raw_impl(const std::string_view& data, const std::string_view& key, size_t& begin, size_t* end) {
size_t index{0}, findex, max{data.size()}, key_size{key.size()};
do {
findex = data.find(key, index);
if(findex > max) return false;
/* not starting with a space so not a match */
if(findex != 0 && data[findex - 1] != ' ') {
index = findex + key_size;
continue;
}
findex += key_size;
if(findex < max) {
if(findex < max && data[findex] != '=') {
index = findex + key_size;
continue;
}
begin = findex + 1;
if(end) *end = data.find(' ', findex + 1);
return true;
} else {
begin = max;
if(end) *end = max;
return true;
}
} while(true);
}
class command_string_parser {
public:
[[nodiscard]] inline bool is_empty() const noexcept { return this->data.empty(); }
@ -22,33 +53,11 @@ namespace ts {
}
[[nodiscard]] inline std::string_view value_raw(const std::string_view& key, bool& has_been_found) const noexcept {
has_been_found = false;
size_t begin, end;
has_been_found = value_raw_impl(this->data, key, begin, &end);
if(!has_been_found) return {};
size_t index{0}, findex, max{this->data.size()}, key_size{key.size()};
do {
findex = this->data.find(key, index);
if(findex > max) return std::string_view{};
/* not starting with a space so not a match */
if(findex != 0 && this->data[findex - 1] != ' ') {
index = findex + key_size;
continue;
}
findex += key_size;
if(findex < max) {
if(findex < max && this->data[findex] != '=') {
index = findex + key_size;
continue;
}
has_been_found = true;
return this->data.substr(findex + 1, this->data.find(' ', findex + 1) - findex - 1);
} else {
has_been_found = true;
return std::string_view{};
}
} while(true);
return this->data.substr(begin, end - begin);
}
[[nodiscard]] inline std::string value(const std::string_view& key) const {
@ -121,4 +130,101 @@ namespace ts {
std::vector<command_bulk> _bulks{};
std::vector<std::string_view> flags{};
};
template <typename vector_t = std::vector<std::string>>
class command_builder_impl {
public:
explicit command_builder_impl(std::string command, size_t expected_bulk_size = 128, size_t expected_bulks = 1) : _identifier{std::move(command)}, expected_bulk_size{expected_bulk_size} {
for(size_t index = 0; index < expected_bulks; index++)
this->bulks.emplace_back(" ").reserve(expected_bulk_size);
}
inline command_builder_impl<std::vector<std::string>> as_normalized() {
return command_builder_impl<std::vector<std::string>>{this->expected_bulk_size, this->_identifier, this->bulks.begin(), this->bulks.end()};
}
inline std::string build() const {
if(this->builded.has_value())
return this->builded.value();
std::string result{};
size_t required_size{this->_identifier.size()};
for(auto& entry : this->bulks)
required_size += entry.size() + 1;
result.append(this->_identifier);
for(auto it = this->bulks.begin(); it != this->bulks.end(); it++) {
result.append(*it);
if(it + 1 != this->bulks.end())
result.append("|");
}
this->builded = result;
return result;
}
inline void reserve_bulks(size_t count) { this->bulks.reserve(count); }
inline void put(size_t index, const std::string_view& key, const std::string_view& value) {
while(this->bulks.size() <= index)
this->bulks.emplace_back(" ").reserve(expected_bulk_size);
auto& data = this->bulks[index];
size_t begin, end;
if(impl::value_raw_impl(data, key, begin, &end)) {
std::string result{};
result.reserve(data.size());
result.append(data, 0, begin - key.size() - 1); /* key incl = */
result.append(data, end + 1); /* get rid of the space */
data = result;
}
this->impl_put_unchecked(data, index, key, value);
}
template <typename T, std::enable_if_t<!(std::is_same<T, std::string_view>::value || std::is_same<T, std::string>::value), int> = 1>
inline void put(size_t index, const std::string_view& key, const T& value) {
static_assert(converter<T>::supported, "Target type isn't supported!");
static_assert(!converter<T>::supported || converter<T>::to_string, "Target type dosn't support building");
auto data = converter<T>::to_string(value);
this->put(index, key, std::string_view{data});
}
/* directly puts data without checking for duplicates */
inline void put_unchecked(size_t index, const std::string_view& key, const std::string_view& value) {
while(this->bulks.size() <= index)
this->bulks.emplace_back(" ").reserve(expected_bulk_size);
this->impl_put_unchecked(this->bulks[index], index, key, value);
}
template <typename T, std::enable_if_t<!(std::is_same<T, std::string_view>::value || std::is_same<T, std::string>::value), int> = 1>
inline void put_unchecked(size_t index, const std::string_view& key, const T& value) {
static_assert(converter<T>::supported, "Target type isn't supported!");
static_assert(!converter<T>::supported || converter<T>::to_string, "Target type dosn't support building");
auto data = converter<T>::to_string(value);
this->put_unchecked(index, key, std::string_view{data});
}
private:
command_builder_impl(size_t expected, size_t identifier, vector_t::iterator begin, vector_t::iterator end) : expected_bulk_size{expected}, _identifier{identifier}, bulks{begin, end} {}
void impl_put_unchecked(std::string& data, size_t index, const std::string_view& key, const std::string_view& value) {
auto escaped_value = ts::query::escape(std::string{value});
data.reserve(data.length() + key.size() + escaped_value.size() + 2);
data.append(key);
data.append("=");
data.append(escaped_value);
data.append(" ");
this->builded.reset();
}
const size_t expected_bulk_size;
const std::string _identifier;
mutable std::optional<std::string> builded{};
vector_t bulks{};
};
using command_builder = command_builder_impl<>;
}

View File

@ -7,6 +7,7 @@ namespace ts {
namespace cconstants {
typedef command_handler::field<tl("return_code"), std::string> return_code;
typedef command_handler::field<tl("reasonmsg"), std::string> reasonmsg;
typedef command_handler::field<tl("sid"), ServerId> server_id;
@ -17,7 +18,7 @@ namespace ts {
typedef command_handler::field<tl("cpid"), ChannelId> channel_parent_id;
typedef command_handler::field<tl("cgid"), GroupId> channel_group_id;
typedef command_handler::field<tl("cgid"), GroupId> server_group_id;
typedef command_handler::field<tl("sgid"), GroupId> server_group_id;
//FIXME
/* typedef descriptor::field<tl("permid"), permission::PermissionType> permission_id;

View File

@ -157,6 +157,14 @@ int main() {
cmd_handler->invoke(cmd);
{
ts::command_builder builder{"hello_world"};
builder.put(0, "hello", "this is hello world");
builder.put(1, "hello", "this is hello world1");
builder.put(1, "hello", "this is hello world2");
builder.put_unchecked(6, "hello", 22);
std::cout << "Result: " << builder.build() << "\n";
}
//auto v = ts::descriptor::entry::bulked::val;
return 0;
}