mirror of
https://github.com/Expand-sys/CCash
synced 2025-12-17 00:22:14 +11:00
making error returns uniform
This commit is contained in:
parent
b6b1c0b78e
commit
86ab9a0e8e
7 changed files with 176 additions and 110 deletions
16
config.json
16
config.json
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"listeners": [
|
|
||||||
{
|
|
||||||
"address": "0.0.0.0",
|
|
||||||
"port": 80,
|
|
||||||
"https": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"address": "0.0.0.0",
|
|
||||||
"port": 443,
|
|
||||||
"https": true,
|
|
||||||
"cert": "",
|
|
||||||
"key": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
227
include/bank.hpp
227
include/bank.hpp
|
|
@ -2,6 +2,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include "xxhash.h"
|
#include "xxhash.h"
|
||||||
|
#include "endpoints.hpp"
|
||||||
#include "parallel-hashmap/parallel_hashmap/phmap.h"
|
#include "parallel-hashmap/parallel_hashmap/phmap.h"
|
||||||
#include "user.hpp"
|
#include "user.hpp"
|
||||||
|
|
||||||
|
|
@ -32,125 +33,189 @@ private:
|
||||||
public:
|
public:
|
||||||
std::string admin_pass;
|
std::string admin_pass;
|
||||||
|
|
||||||
bool AddUser(const std::string &name, std::string &&init_pass)
|
int_fast8_t AddUser(const std::string &name, std::string &&init_pass)
|
||||||
{
|
{
|
||||||
if (name.size() > 50)
|
if (name.size() > max_name_size)
|
||||||
{
|
{
|
||||||
return false;
|
return Endpoint::NameTooLong;
|
||||||
}
|
}
|
||||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
|
||||||
return users.try_emplace_l(
|
|
||||||
name, [](User &) {}, std::move(init_pass));
|
|
||||||
}
|
|
||||||
bool AdminAddUser(const std::string &attempt, std::string &&name, uint32_t init_bal, std::string &&init_pass)
|
|
||||||
{
|
|
||||||
if (name.size() > 50)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool state = (admin_pass == attempt);
|
|
||||||
if (state)
|
|
||||||
{
|
{
|
||||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||||
state = users.try_emplace_l(
|
if (!users.try_emplace_l(
|
||||||
name, [](User &) {}, init_bal, std::move(init_pass));
|
name, [](User &) {}, std::move(init_pass)))
|
||||||
|
{
|
||||||
|
return Endpoint::UserAlreadyExists;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int_fast8_t AdminAddUser(const std::string &attempt, std::string &&name, uint32_t init_bal, std::string &&init_pass)
|
||||||
|
{
|
||||||
|
if (name.size() > max_name_size)
|
||||||
|
{
|
||||||
|
return Endpoint::NameTooLong;
|
||||||
|
}
|
||||||
|
if (admin_pass != attempt)
|
||||||
|
{
|
||||||
|
return Endpoint::WrongAdminPassword;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||||
|
if (!users.try_emplace_l(
|
||||||
|
name, [](User &) {}, init_bal, std::move(init_pass)))
|
||||||
|
{
|
||||||
|
return Endpoint::UserAlreadyExists;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DelUser(const std::string &name, const std::string &attempt)
|
int_fast8_t DelUser(const std::string &name, const std::string &attempt)
|
||||||
{
|
{
|
||||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||||
return users.erase_if(name, [&attempt](User &u) { return (XXH3_64bits(attempt.data(), attempt.size()) == u.password); });
|
bool state = false;
|
||||||
|
if (!users.erase_if(name, [&state, &attempt](User &u) { return state = (XXH3_64bits(attempt.data(), attempt.size()) == u.password); }))
|
||||||
|
{
|
||||||
|
return Endpoint::UserNotFound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return state * Endpoint::WrongPassword;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool AdminDelUser(const std::string &name, const std::string &attempt)
|
int_fast8_t AdminDelUser(const std::string &name, const std::string &attempt)
|
||||||
{
|
{
|
||||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||||
return users.erase_if(name, [this, &attempt](const User &) { return (admin_pass == attempt); });
|
bool state = false;
|
||||||
|
if (!users.erase_if(name, [&state, this, &attempt](const User &) { return state = (admin_pass == attempt); }))
|
||||||
|
{
|
||||||
|
return Endpoint::UserNotFound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return state * Endpoint::WrongAdminPassword;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount, const std::string &attempt)
|
int_fast8_t SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount, const std::string &attempt)
|
||||||
{
|
{
|
||||||
//cant send money to self, from self or amount is 0
|
//cant send money to self, from self or amount is 0
|
||||||
if (a_name == b_name || !amount)
|
if (a_name == b_name || !amount)
|
||||||
{
|
{
|
||||||
return false;
|
return Endpoint::InvalidRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if A exists, A can afford it, and A's password matches
|
int_fast8_t state = false;
|
||||||
bool state = false;
|
|
||||||
{
|
{
|
||||||
std::shared_lock<std::shared_mutex> lock{send_funds_l}; //because SendFunds requires 3 locking operations
|
std::shared_lock<std::shared_mutex> lock{send_funds_l}; //because SendFunds requires 3 locking operations
|
||||||
users.modify_if(a_name, [&state, amount, &attempt](User &a) {
|
if (users.modify_if(a_name, [&state, amount, &attempt](User &a) {
|
||||||
if (state = (a.balance >= amount) && (a.password == XXH3_64bits(attempt.data(), attempt.size())))
|
//if A exists, A can afford it, and A's password matches
|
||||||
{
|
if (a.balance < amount)
|
||||||
a.balance -= amount;
|
{
|
||||||
}
|
state = Endpoint::InsufficientFunds;
|
||||||
});
|
}
|
||||||
|
else
|
||||||
if (state)
|
{
|
||||||
|
if (a.password != XXH3_64bits(attempt.data(), attempt.size()))
|
||||||
|
{
|
||||||
|
state = Endpoint::WrongPassword;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a.balance -= amount;
|
||||||
|
state = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
//if B doesnt exist
|
return Endpoint::UserNotFound;
|
||||||
if (!users.modify_if(b_name, [amount](User &b) {
|
}
|
||||||
b.balance += amount;
|
else
|
||||||
}))
|
{
|
||||||
|
if (!state)
|
||||||
{
|
{
|
||||||
//attempt to refund if A exist
|
return state;
|
||||||
users.modify_if(a_name, [amount](User &a) {
|
}
|
||||||
a.balance += amount;
|
else
|
||||||
});
|
{
|
||||||
return false; //because had to refund transaction
|
//if B doesnt exist
|
||||||
|
if (!users.modify_if(b_name, [amount](User &b) {
|
||||||
|
b.balance += amount;
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
//attempt to refund if A exist
|
||||||
|
users.modify_if(a_name, [amount](User &a) {
|
||||||
|
a.balance += amount;
|
||||||
|
});
|
||||||
|
return Endpoint::UserNotFound; //because had to refund transaction
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if constexpr (max_log_size)
|
||||||
|
{
|
||||||
|
Transaction temp(a_name, b_name, amount);
|
||||||
|
Transaction temp2 = temp;
|
||||||
|
users.modify_if(a_name, [&temp](User &a) {
|
||||||
|
a.log.AddTrans(std::move(temp));
|
||||||
|
});
|
||||||
|
users.modify_if(b_name, [&temp2](User &b) {
|
||||||
|
b.log.AddTrans(std::move(temp2));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if constexpr (max_log_size)
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
Transaction temp(a_name, b_name, amount);
|
|
||||||
Transaction temp2 = temp;
|
|
||||||
users.modify_if(a_name, [&temp](User &a) {
|
|
||||||
a.log.AddTrans(std::move(temp));
|
|
||||||
});
|
|
||||||
users.modify_if(b_name, [&temp2](User &b) {
|
|
||||||
b.log.AddTrans(std::move(temp2));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contains(const std::string &name) const
|
bool Contains(const std::string &name) const
|
||||||
{
|
{
|
||||||
return users.contains(name);
|
return users.contains(name);
|
||||||
}
|
}
|
||||||
bool SetBal(const std::string &name, const std::string &attempt, uint32_t amount)
|
|
||||||
{
|
|
||||||
bool state = (admin_pass == attempt);
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
users.modify_if(name, [amount](User &u) {
|
|
||||||
u.balance = amount;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
bool AdminVerifyPass(const std::string &attempt)
|
bool AdminVerifyPass(const std::string &attempt)
|
||||||
{
|
{
|
||||||
return admin_pass == attempt;
|
return (admin_pass != attempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int_fast8_t SetBal(const std::string &name, const std::string &attempt, uint32_t amount)
|
||||||
|
{
|
||||||
|
if (admin_pass != attempt)
|
||||||
|
{
|
||||||
|
return Endpoint::WrongAdminPassword;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!users.modify_if(name, [amount](User &u) {
|
||||||
|
u.balance = amount;
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return Endpoint::UserNotFound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
int_fast64_t GetBal(const std::string &name) const
|
int_fast64_t GetBal(const std::string &name) const
|
||||||
{
|
{
|
||||||
int_fast64_t res = -1;
|
int_fast64_t res = Endpoint::UserNotFound;
|
||||||
users.if_contains(name, [&res](const User &u) {
|
users.if_contains(name, [&res](const User &u) {
|
||||||
res = u.balance;
|
res = u.balance;
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t VerifyPassword(const std::string &name, const std::string &attempt) const
|
int_fast8_t VerifyPassword(const std::string &name, const std::string &attempt) const
|
||||||
{
|
{
|
||||||
int_fast8_t res = -1;
|
int_fast8_t res = Endpoint::UserNotFound;
|
||||||
users.if_contains(name, [&res, &attempt](const User &u) {
|
users.if_contains(name, [&res, &attempt](const User &u) {
|
||||||
res = u.password == XXH3_64bits(attempt.data(), attempt.size());
|
res = u.password == XXH3_64bits(attempt.data(), attempt.size());
|
||||||
});
|
});
|
||||||
|
|
@ -158,10 +223,13 @@ public:
|
||||||
}
|
}
|
||||||
int_fast8_t ChangePassword(const std::string &name, const std::string &attempt, std::string &&new_pass)
|
int_fast8_t ChangePassword(const std::string &name, const std::string &attempt, std::string &&new_pass)
|
||||||
{
|
{
|
||||||
int_fast8_t res = -1;
|
int_fast8_t res = Endpoint::UserNotFound;
|
||||||
users.modify_if(name, [&res, &attempt, &new_pass](User &u) {
|
users.modify_if(name, [&res, &attempt, &new_pass](User &u) {
|
||||||
res = (u.password == XXH3_64bits(attempt.data(), attempt.size()));
|
if (u.password != XXH3_64bits(attempt.data(), attempt.size()))
|
||||||
if (res)
|
{
|
||||||
|
res = Endpoint::WrongPassword;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
u.password = XXH3_64bits(new_pass.data(), new_pass.size());
|
u.password = XXH3_64bits(new_pass.data(), new_pass.size());
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +243,7 @@ public:
|
||||||
if (!users.if_contains(name, [&res, &attempt](const User &u) {
|
if (!users.if_contains(name, [&res, &attempt](const User &u) {
|
||||||
if (u.password != XXH3_64bits(attempt.data(), attempt.size()))
|
if (u.password != XXH3_64bits(attempt.data(), attempt.size()))
|
||||||
{
|
{
|
||||||
res = 0;
|
res = Endpoint::WrongPassword;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -191,7 +259,7 @@ public:
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
return -1;
|
return Endpoint::UserNotFound;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +286,7 @@ public:
|
||||||
if (!temp.isNull())
|
if (!temp.isNull())
|
||||||
{
|
{
|
||||||
writer->write(temp, &user_save);
|
writer->write(temp, &user_save);
|
||||||
|
throw std::invalid_argument("Saving Failed\n");
|
||||||
}
|
}
|
||||||
user_save.close();
|
user_save.close();
|
||||||
}
|
}
|
||||||
|
|
@ -254,3 +323,5 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} bank;
|
} bank;
|
||||||
|
|
||||||
|
//TODO make branchless
|
||||||
|
|
@ -68,25 +68,25 @@ public:
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.AdminAddUser(body["attempt"].asCString(), body["name"].asCString(), body["init_bal"].asUInt(), body["init_pass"].asCString()));
|
JSON(bank.AdminAddUser(body["attempt"].asCString(), body["name"].asCString(), body["init_bal"].asUInt(), body["init_pass"].asCString()));
|
||||||
}
|
}
|
||||||
void DelUser(req_args) const
|
void DelUser(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.DelUser(body["name"].asCString(), body["attempt"].asCString()));
|
JSON(bank.DelUser(name, body["attempt"].asCString()));
|
||||||
}
|
}
|
||||||
void AdminDelUser(req_args) const
|
void AdminDelUser(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.AdminDelUser(body["name"].asCString(), body["attempt"].asCString()));
|
JSON(bank.AdminDelUser(name, body["attempt"].asCString()));
|
||||||
}
|
}
|
||||||
void SendFunds(req_args) const
|
void SendFunds(req_args) const
|
||||||
{
|
{
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.SendFunds(body["a_name"].asCString(), body["b_name"].asCString(), body["amount"].asUInt(), body["attempt"].asCString()));
|
JSON(bank.SendFunds(body["a_name"].asCString(), body["b_name"].asCString(), body["amount"].asUInt(), body["attempt"].asCString()));
|
||||||
}
|
}
|
||||||
void ChangePassword(req_args) const
|
void ChangePassword(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.ChangePassword(body["name"].asCString(), body["attempt"].asCString(), body["new_pass"].asCString()));
|
JSON(bank.ChangePassword(name, body["attempt"].asCString(), body["new_pass"].asCString()));
|
||||||
}
|
}
|
||||||
void Contains(req_args, const std::string &name) const
|
void Contains(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
|
|
@ -96,10 +96,10 @@ public:
|
||||||
{
|
{
|
||||||
JSON(bank.GetBal(name));
|
JSON(bank.GetBal(name));
|
||||||
}
|
}
|
||||||
void VerifyPassword(req_args) const
|
void VerifyPassword(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
GEN_BODY
|
GEN_BODY
|
||||||
JSON(bank.VerifyPassword(body["name"].asCString(), body["attempt"].asCString()));
|
JSON(bank.VerifyPassword(name, body["attempt"].asCString()));
|
||||||
}
|
}
|
||||||
void SetBal(req_args, const std::string &name) const
|
void SetBal(req_args, const std::string &name) const
|
||||||
{
|
{
|
||||||
|
|
@ -132,17 +132,17 @@ public:
|
||||||
METHOD_ADD(BankF::AdminAddUser, "/admin/user", Post, Options);
|
METHOD_ADD(BankF::AdminAddUser, "/admin/user", Post, Options);
|
||||||
METHOD_ADD(BankF::SendFunds, "/sendfunds", Post, Options);
|
METHOD_ADD(BankF::SendFunds, "/sendfunds", Post, Options);
|
||||||
|
|
||||||
METHOD_ADD(BankF::ChangePassword, "/changepass", Patch, Options);
|
METHOD_ADD(BankF::ChangePassword, "/{name}/pass/change", Patch, Options);
|
||||||
METHOD_ADD(BankF::SetBal, "/admin/{name}/bal", Patch, Options);
|
METHOD_ADD(BankF::SetBal, "/admin/{name}/bal", Patch, Options);
|
||||||
|
|
||||||
METHOD_ADD(BankF::Help, "/help", Get, Options);
|
METHOD_ADD(BankF::Help, "/help", Get, Options);
|
||||||
METHOD_ADD(BankF::VerifyPassword, "/vpass", Post, Options);
|
METHOD_ADD(BankF::VerifyPassword, "/{name}/pass/verify", Post, Options);
|
||||||
METHOD_ADD(BankF::Contains, "/contains/{name}", Get, Options);
|
METHOD_ADD(BankF::Contains, "/contains/{name}", Get, Options);
|
||||||
METHOD_ADD(BankF::GetBal, "/{name}/bal", Get, Options);
|
METHOD_ADD(BankF::GetBal, "/{name}/bal", Get, Options);
|
||||||
METHOD_ADD(BankF::AdminVerifyPass, "/admin/vpass", Post, Options);
|
METHOD_ADD(BankF::AdminVerifyPass, "/admin/verify", Post, Options);
|
||||||
METHOD_ADD(BankF::GetLog, "/{name}/log", Post, Options);
|
METHOD_ADD(BankF::GetLog, "/{name}/log", Post, Options);
|
||||||
|
|
||||||
METHOD_ADD(BankF::DelUser, "/user", Delete, Options);
|
METHOD_ADD(BankF::DelUser, "/user/{name}", Delete, Options);
|
||||||
METHOD_ADD(BankF::AdminDelUser, "/admin/user", Delete, Options);
|
METHOD_ADD(BankF::AdminDelUser, "/admin/user/{name}", Delete, Options);
|
||||||
METHOD_LIST_END
|
METHOD_LIST_END
|
||||||
};
|
};
|
||||||
|
|
@ -3,3 +3,4 @@
|
||||||
// Setting both values to 0 does not compile logging
|
// Setting both values to 0 does not compile logging
|
||||||
constexpr unsigned max_log_size = 100;
|
constexpr unsigned max_log_size = 100;
|
||||||
constexpr unsigned pre_log_size = 10;
|
constexpr unsigned pre_log_size = 10;
|
||||||
|
constexpr unsigned max_name_size = 50;
|
||||||
12
include/endpoints.hpp
Normal file
12
include/endpoints.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
enum Endpoint
|
||||||
|
{
|
||||||
|
UserNotFound = -1,
|
||||||
|
WrongPassword = -2,
|
||||||
|
Refunded = -3,
|
||||||
|
InvalidRequest = -4,
|
||||||
|
WrongAdminPassword = -5,
|
||||||
|
NameTooLong = -6,
|
||||||
|
UserAlreadyExists = -7,
|
||||||
|
InsufficientFunds = -8,
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "log_consts.hpp"
|
#include "consts.hpp"
|
||||||
#include "transactions.hpp"
|
#include "transactions.hpp"
|
||||||
|
|
||||||
struct Log
|
struct Log
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
{
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue