Merge remote-tracking branch 'upstream/main' into cicd

This commit is contained in:
Luke Bennett 2021-06-15 11:04:45 +01:00
commit fc8b8a9cb6
No known key found for this signature in database
GPG key ID: A738E9C68D3BF31A
7 changed files with 64 additions and 136 deletions

View file

@ -16,7 +16,11 @@ CCash solves these issues and adds a level of abstraction, the main philosophy o
drogon depedencies (varies by OS/distro) drogon depedencies (varies by OS/distro)
``` ```
# Debian
sudo apt install libjsoncpp-dev uuid-dev openssl libssl-dev zlib1g-dev sudo apt install libjsoncpp-dev uuid-dev openssl libssl-dev zlib1g-dev
# macOS
brew install jsoncpp ossp-uuid openssl zlib
``` ```
building the project building the project
@ -62,6 +66,7 @@ Thank you to the contributors
| [Expand](https://github.com/Expand-sys) | Frontend | | [Expand](https://github.com/Expand-sys) | Frontend |
| [React](https://github.com/Reactified) | CC {API, Shops, and ATM, Logo} | | [React](https://github.com/Reactified) | CC {API, Shops, and ATM, Logo} |
| [Doggo](https://github.com/FearlessDoggo21) | Logs loading/adding Optimized, HTTP convention suggestions | | [Doggo](https://github.com/FearlessDoggo21) | Logs loading/adding Optimized, HTTP convention suggestions |
| [Luke](https://github.com/LukeeeeBennett) | Slight Doc edits |
## Features ## Features
@ -73,6 +78,7 @@ Thank you to the contributors
- **multi-threaded** - **multi-threaded**
- **parallel hashmaps** a far [superior](https://greg7mdp.github.io/parallel-hashmap/) HashMap implementation to the STD, that also benefits from multi-threaded - **parallel hashmaps** a far [superior](https://greg7mdp.github.io/parallel-hashmap/) HashMap implementation to the STD, that also benefits from multi-threaded
- **Drogon** is a very fast [web framework](https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=composite) - **Drogon** is a very fast [web framework](https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=composite)
- **xxHash** for the hashing of passwords, [graph](https://user-images.githubusercontent.com/750081/61976089-aedeab00-af9f-11e9-9239-e5375d6c080f.png)
- **Lightweight**, anecodotally I experienced 0.0% idle, <1% CPU usage on average, 7% at peak, 1000 requests in 0.85s - **Lightweight**, anecodotally I experienced 0.0% idle, <1% CPU usage on average, 7% at peak, 1000 requests in 0.85s
### Safety ### Safety

View file

@ -4,6 +4,13 @@
"address": "0.0.0.0", "address": "0.0.0.0",
"port": 80, "port": 80,
"https": false "https": false
},
{
"address": "0.0.0.0",
"port": 443,
"https": true,
"cert": "",
"key": ""
} }
] ]
} }

35
help.md
View file

@ -10,28 +10,24 @@
| -6 | InsufficientFunds | | -6 | InsufficientFunds |
# Things of Note # Things of Note
* all endpoints respond with **JSON** file type
- all endpoints respond with **JSON** file type * "**A**" denotes requiring Authentication in the form of a header titled "**Password**"
- "**A**" denotes requiring Authentication in the form of a header titled "**Password**"
# Usage # Usage
| Name | Path | Method | A | Description |
| Name | Path | Method | A | Description | | :------------: | :------------------------------------- | :----: | :---: | -------------------------------------------------------------------------------------------------- |
| :------------: | :------------------------------------- | :----: | :---: | ------------------------------------------------------------------------------------------------------------ | | GetBal | BankF/{name}/bal | GET | false | returns the balance of a given user `{name}` |
| GetBal | BankF/{name}/bal | GET | false | returns the balance of a given user `{name}` | | GetLog | BankF/{name}/log | GET | true | returns a list of last `n` number of transactions (a configurable amount) of a given user `{name}` |
| GetLog | BankF/{name}/log | GET | true | returns a list of last `n` number of transactions (configurable in CCash webserver) of a given user `{name}` | | SendFunds | BankF/{name}/send/{to}?amount={amount} | POST | true | sends `{amount}` from user `{name}` to user `{to}` |
| SendFunds | BankF/{name}/send/{to}?amount={amount} | POST | true | sends `{amount}` from user `{name}` to user `{to}` | | VerifyPassword | BankF/{name}/pass/verify | GET | true | returns `1` if the supplied user `{name}`'s password matches the password supplied in the header |
| VerifyPassword | BankF/{name}/pass/verify | GET | true | returns `1` if the supplied user `{name}`'s password matches the password supplied in the header |
# Meta Usage # Meta Usage
| Name | Path | Method | A | Description | | Name | Path | Method | A | Description |
| :------------: | :------------------------------------- | :----: | :---: | ---------------------------------------------------------------------------------------------------------------------------------------- | | :------------: | :------------------------------------- | :----: | :---: | ---------------------------------------------------------------------------------------------------------------------------------------- |
| ChangePassword | BankF/{name}/pass/change | PATCH | true | if the password supplied in the header matches the user `{name}`'s password, the user's password is changed to the one given as the body | | ChangePassword | BankF/{name}/pass/change | PATCH | true | if the password supplied in the header matches the user `{name}`'s password, the user's password is changed to the one given in the body |
| SetBal | BankF/admin/{name}/bal?amount={amount} | PATCH | true | sets the balance of a give user `{name}` if the supplied password matches the admin password | | SetBal | BankF/admin/{name}/bal?amount={amount} | PATCH | true | sets the balance of a give user `{name}` if the supplied password matches the admin password |
# System Usage # System Usage
| Name | Path | Method | A | Description | | Name | Path | Method | A | Description |
| :-------------: | :-------------------- | :----: | :---: | ------------------------------------------------------------------------------------- | | :-------------: | :-------------------- | :----: | :---: | ------------------------------------------------------------------------------------- |
| Help | BankF/help | GET | false | the page you're looking at right now! | | Help | BankF/help | GET | false | the page you're looking at right now! |
@ -41,10 +37,9 @@
| AdminVerifyPass | BankF/admin/verify | GET | true | returns `1` if the password supplied in the header matches the admin password | | AdminVerifyPass | BankF/admin/verify | GET | true | returns `1` if the password supplied in the header matches the admin password |
# User Management # User Management
| Name | Path | Method | A | Description |
| Name | Path | Method | A | Description | | :----------: | :------------------------------------------ | :----: | :---: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| :----------: | :------------------------------------------ | :----: | :---: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | AddUser | BankF/user/{name} | POST | true | registers a user with the name `{name}`, balance of 0 and a password of the password supplied in the header |
| AddUser | BankF/user/{name} | POST | true | registers a user with the name `{name}`, balance of 0 and a password of the password supplied in the header | | AdminAddUser | BankF/admin/user/{name}?init_bal={init_bal} | POST | true | if the password supplied in the header matches the admin password, then it registers a user with the name `{name}`, balance of `init_bal` and a password supplied by the body of the request |
| AdminAddUser | BankF/admin/user/{name}?init_bal={init_bal} | POST | true | if the password supplied in the header matches the admin password, then it registers a user with the name `{name}`, balance of `init_bal` and a password that is supplied as the body of the request | | DelUser | BankF/user/{name} | DELETE | true | if the password supplied in the header matches the user `{name}`'s password, then the user is deleted |
| DelUser | BankF/user/{name} | DELETE | true | if the password supplied in the header matches the user `{name}`'s password, then the user is deleted | | AdminDelUser | BankF/admin/user/{name} | DELETE | true | if the password supplied in the header matches the admin password, then the user is deleted |
| AdminDelUser | BankF/admin/user/{name} | DELETE | true | if the password supplied in the header matches the admin password, then the user is deleted |

View file

@ -4,8 +4,7 @@ enum ErrorResponse
UserNotFound = -1, UserNotFound = -1,
WrongPassword = -2, WrongPassword = -2,
InvalidRequest = -3, InvalidRequest = -3,
WrongAdminPassword = -4, NameTooLong = -4,
NameTooLong = -5, UserAlreadyExists = -5,
UserAlreadyExists = -6, InsufficientFunds = -6,
InsufficientFunds = -7,
}; };

View file

@ -24,3 +24,6 @@
- Shipping - Shipping
- High-level bank operations such as loans - High-level bank operations such as loans
- Some trust based system for transactions similiar to Paypal - Some trust based system for transactions similiar to Paypal
- a better version of one of these existing ideas
- something completely different

View file

@ -8,15 +8,10 @@ int_fast8_t Bank::AddUser(const std::string &name, const std::string &init_pass)
} }
{ {
std::shared_lock<std::shared_mutex> lock{size_l}; std::shared_lock<std::shared_mutex> lock{size_l};
if (users.try_emplace_l( return (users.try_emplace_l(
name, [](User &) {}, init_pass)) name, [](User &) {}, init_pass))
{ ? true
return true; : ErrorResponse::UserAlreadyExists;
}
else
{
return ErrorResponse::UserAlreadyExists;
}
} }
} }
int_fast8_t Bank::AdminAddUser(const std::string &attempt, std::string &&name, uint32_t init_bal, std::string &&init_pass) int_fast8_t Bank::AdminAddUser(const std::string &attempt, std::string &&name, uint32_t init_bal, std::string &&init_pass)
@ -31,55 +26,36 @@ int_fast8_t Bank::AdminAddUser(const std::string &attempt, std::string &&name, u
} }
{ {
std::shared_lock<std::shared_mutex> lock{size_l}; std::shared_lock<std::shared_mutex> lock{size_l};
if (users.try_emplace_l( return (users.try_emplace_l(
name, [](User &) {}, init_bal, std::move(init_pass))) name, [](User &) {}, init_bal, std::move(init_pass)))
{ ? true
return true; : ErrorResponse::UserAlreadyExists;
}
else
{
return ErrorResponse::UserAlreadyExists;
}
} }
} }
int_fast8_t Bank::DelUser(const std::string &name, const std::string &attempt) int_fast8_t Bank::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};
bool state = false; bool state = false;
if (!users.erase_if(name, [&state, &attempt](User &u) { return state = (XXH3_64bits(attempt.data(), attempt.size()) == u.password); })) if (users.erase_if(name, [&state, &attempt](User &u) { return state = (XXH3_64bits(attempt.data(), attempt.size()) == u.password); }))
{ {
return ErrorResponse::UserNotFound; return (state) ? true : ErrorResponse::WrongPassword;
} }
else else
{ {
if (state) return ErrorResponse::UserNotFound;
{
return true;
}
else
{
return ErrorResponse::WrongPassword;
}
} }
} }
int_fast8_t Bank::AdminDelUser(const std::string &name, const std::string &attempt) int_fast8_t Bank::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};
bool state = false; bool state = false;
if (!users.erase_if(name, [this, &state, &attempt](const User &) { return state = (admin_pass == attempt); })) if (users.erase_if(name, [this, &state, &attempt](const User &) { return state = (admin_pass == attempt); }))
{ {
return ErrorResponse::UserNotFound; return (state) ? true : ErrorResponse::WrongPassword;
} }
else else
{ {
if (state) return ErrorResponse::UserNotFound;
{
return true;
}
else
{
return ErrorResponse::WrongPassword;
}
} }
} }
@ -119,7 +95,7 @@ int_fast8_t Bank::SendFunds(const std::string &a_name, const std::string &b_name
} }
})) }))
{ {
if (state) if (state > 0)
{ {
//if B does exist //if B does exist
if (users.modify_if(b_name, [amount](User &b) { if (users.modify_if(b_name, [amount](User &b) {
@ -162,25 +138,11 @@ int_fast8_t Bank::SendFunds(const std::string &a_name, const std::string &b_name
int_fast8_t Bank::Contains(const std::string &name) const int_fast8_t Bank::Contains(const std::string &name) const
{ {
if (users.contains(name)) return (users.contains(name)) ? true : ErrorResponse::UserNotFound;
{
return true;
}
else
{
return ErrorResponse::UserNotFound;
}
} }
int_fast8_t Bank::AdminVerifyPass(const std::string &attempt) int_fast8_t Bank::AdminVerifyPass(const std::string &attempt)
{ {
if (admin_pass == attempt) return (admin_pass == attempt) ? true : ErrorResponse::WrongPassword;
{
return true;
}
else
{
return ErrorResponse::WrongPassword;
}
} }
int_fast8_t Bank::SetBal(const std::string &name, const std::string &attempt, uint32_t amount) int_fast8_t Bank::SetBal(const std::string &name, const std::string &attempt, uint32_t amount)
@ -189,16 +151,12 @@ int_fast8_t Bank::SetBal(const std::string &name, const std::string &attempt, ui
{ {
return ErrorResponse::WrongPassword; return ErrorResponse::WrongPassword;
} }
if (users.modify_if(name, [amount](User &u) {
u.balance = amount; return (users.modify_if(name, [amount](User &u) {
})) u.balance = amount;
{ }))
return true; ? true
} : ErrorResponse::UserNotFound;
else
{
return ErrorResponse::UserNotFound;
}
} }
int_fast64_t Bank::GetBal(const std::string &name) const int_fast64_t Bank::GetBal(const std::string &name) const
{ {
@ -213,14 +171,7 @@ int_fast8_t Bank::VerifyPassword(const std::string &name, const std::string &att
{ {
int_fast8_t res = ErrorResponse::UserNotFound; int_fast8_t res = ErrorResponse::UserNotFound;
users.if_contains(name, [&res, &attempt](const User &u) { users.if_contains(name, [&res, &attempt](const User &u) {
if (u.password == XXH3_64bits(attempt.data(), attempt.size())) res = (u.password == XXH3_64bits(attempt.data(), attempt.size())) ? true : ErrorResponse::WrongPassword;
{
res = true;
}
else
{
res = ErrorResponse::WrongPassword;
}
}); });
return res; return res;
} }
@ -234,6 +185,7 @@ int_fast8_t Bank::ChangePassword(const std::string &name, const std::string &att
} }
else else
{ {
res = true;
u.password = XXH3_64bits(new_pass.data(), new_pass.size()); u.password = XXH3_64bits(new_pass.data(), new_pass.size());
} }
}); });

View file

@ -1,42 +1,8 @@
{ {
"jolly" : "" :
{ {
"balance" : 139, "balance" : 0,
"log" : "log" : null,
[ "password" : 0
{
"amount" : 100,
"from" : "twix",
"time" : 1623555387199,
"to" : "jolly"
},
{
"amount" : 39,
"from" : "twix",
"time" : 1623693328822,
"to" : "jolly"
}
],
"password" : 746744014776526199
}, },
"twix" : }
{
"balance" : 9861,
"log" :
[
{
"amount" : 100,
"from" : "twix",
"time" : 1623555387199,
"to" : "jolly"
},
{
"amount" : 39,
"from" : "twix",
"time" : 1623693328822,
"to" : "jolly"
}
],
"password" : 746744014776526199
}
}