Skip to content

Instantly share code, notes, and snippets.

@alekxeyuk
Created April 5, 2024 12:07
Show Gist options
  • Save alekxeyuk/943e313cf142eaa6929ce1b1b096e02b to your computer and use it in GitHub Desktop.
Save alekxeyuk/943e313cf142eaa6929ce1b1b096e02b to your computer and use it in GitHub Desktop.
bizzarechat
#include <iostream>
#include <unordered_set>
typedef std::unordered_set<int> int_set;
enum AccessLevel : int
{
ADMIN, // Может регистрировать новых пользователей, давать роль админа или модератора другим пользователям, а также полностью останавливать чат
MODERATOR, // Может банить пользователей, создавать других модераторов, а также полностью редактировать все сообщения
BANNED, // Не может ничего, предполагается, что ни ADMIN, ни MODERATOR не станут BANNED
USER // Может писать сообщения, а также редактировать сообщения, но только свои
};
struct ResposeData {
bool Success;
std::string Response;
};
static bool set_has_id(const int& id, const int_set& set) {
const auto search_set = set.find(id);
return search_set != set.end();
}
class AccessControl {
int_set db_[4] = { int_set{}, int_set{}, int_set{}, int_set{} };
public:
bool HasRole(const int id, const AccessLevel roleName)
{
return set_has_id(id, db_[roleName]);
}
bool GrantRole(const int id, const AccessLevel roleName)
{
if (set_has_id(id, db_[roleName])) {
return false;
}
db_[roleName].insert(id);
return true;
}
bool RemoveRole(const int id, const AccessLevel roleName)
{
if (set_has_id(id, db_[roleName]))
{
const auto search_set = db_[roleName].find(id);
db_[roleName].erase(search_set);
return true;
}
return false;
}
ResposeData BanUser(int sender, int user) {
if (HasRole(sender, MODERATOR) && HasRole(user, USER)) {
return ResposeData{ GrantRole(user, BANNED), "BANNED user" };
}
return ResposeData{ false, "Cant BAN user" };
}
ResposeData UnBanUser(int sender, int user) {
if (HasRole(sender, MODERATOR) && HasRole(user, BANNED)) {
return ResposeData{ RemoveRole(user, BANNED), "UNBANNED user" };
}
return ResposeData{ false, "Cant UNBAN user" };
}
ResposeData RegisterNewUser(int sender, int newUser) {
if (HasRole(sender, ADMIN) && !HasRole(newUser, USER)) {
return ResposeData{ GrantRole(newUser, USER), "Registered new USER" };
}
return ResposeData{ false, "Cant register new USER" };
}
ResposeData GrantModeratorRole(int sender, int user) {
if ((HasRole(sender, ADMIN) || HasRole(sender, MODERATOR)) && !HasRole(user, MODERATOR) && !HasRole(user, BANNED)) {
return ResposeData{ GrantRole(user, MODERATOR), "Granted MODERATOR role" };
}
return ResposeData{ false, "Cant grant MODERATOR role" };
}
ResposeData GrantAdminRole(int sender, int user) {
if (HasRole(sender, ADMIN) && !HasRole(user, ADMIN) && !HasRole(user, BANNED)) {
return ResposeData{ GrantRole(user, ADMIN), "Granted ADMIN role" };
}
return ResposeData{ false, "Cant grant ADMIN role" };
}
};
enum ServerState {
Stopped,
Running
};
class Pausable
{
bool status = Running; // false = paused
using HasRoleFunctionType = bool(AccessControl::*)(int, AccessLevel);
HasRoleFunctionType hasRolePtr = nullptr;
AccessControl* accessControlRef = nullptr;
public:
Pausable(AccessControl& a, HasRoleFunctionType f) : accessControlRef(&a), hasRolePtr(f) {}
ResposeData StopChat(int sender) {
if (status == Running && (accessControlRef->*hasRolePtr)(sender, ADMIN)) {
status = false;
return ResposeData{ true , "chat stopped" };
}
return ResposeData{ false, "only admin can stop chat" };
}
ResposeData ResumeChat(int sender) {
if (status == Stopped && (accessControlRef->*hasRolePtr)(sender, ADMIN)) {
status = true;
return ResposeData{ true, "chat resumed" };
}
return ResposeData{ false , "only admin can start chat" };
}
};
class SystemBase : public AccessControl, public Pausable {
public:
SystemBase(int admin) : Pausable(*this, &AccessControl::HasRole) {
AccessControl::GrantRole(admin, ADMIN);
}
};
static void PrintResponse(const ResposeData& response) {
std::cout << "result: " << response.Success << "\nresponse: " << response.Response << "\n";
}
int main() {
const int USER1 = 1;
const int USER2 = 2;
const int USER3 = 3;
SystemBase chat(1);
auto responseStart3FromAdmin = chat.ResumeChat(USER1);
PrintResponse(responseStart3FromAdmin);
auto responseRegisterFromAdmin1 = chat.RegisterNewUser(USER1, USER2);
PrintResponse(responseRegisterFromAdmin1);
auto responseRegisterFromAdmin2 = chat.RegisterNewUser(USER1, USER2);
PrintResponse(responseRegisterFromAdmin2);
auto responseGrantFromAdmin = chat.GrantModeratorRole(USER1, USER2);
PrintResponse(responseGrantFromAdmin);
auto responseRegisterFromModerator = chat.RegisterNewUser(USER2, USER3);
PrintResponse(responseRegisterFromModerator);
auto responseRegisterFromAdmin3 = chat.RegisterNewUser(USER1, USER3);
PrintResponse(responseRegisterFromAdmin3);
auto responseBanFromModer = chat.BanUser(USER2, USER3);
PrintResponse(responseBanFromModer);
auto responseStopFromModer = chat.StopChat(USER2);
PrintResponse(responseStopFromModer);
auto responseStopFromAdmin = chat.StopChat(USER1);
PrintResponse(responseStopFromAdmin);
auto responseStop2FromAdmin = chat.StopChat(USER1);
PrintResponse(responseStop2FromAdmin);
auto responseStartFromAdmin = chat.ResumeChat(USER1);
PrintResponse(responseStartFromAdmin);
auto responseStart2FromAdmin = chat.ResumeChat(USER1);
PrintResponse(responseStart2FromAdmin);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment