mirror of
https://github.com/Expand-sys/CCash
synced 2025-12-17 00:22:14 +11:00
Merge remote-tracking branch 'upstream/main' into cicd
This commit is contained in:
commit
fc8b8a9cb6
7 changed files with 64 additions and 136 deletions
|
|
@ -16,7 +16,11 @@ CCash solves these issues and adds a level of abstraction, the main philosophy o
|
|||
|
||||
drogon depedencies (varies by OS/distro)
|
||||
```
|
||||
# Debian
|
||||
sudo apt install libjsoncpp-dev uuid-dev openssl libssl-dev zlib1g-dev
|
||||
|
||||
# macOS
|
||||
brew install jsoncpp ossp-uuid openssl zlib
|
||||
```
|
||||
|
||||
building the project
|
||||
|
|
@ -62,6 +66,7 @@ Thank you to the contributors
|
|||
| [Expand](https://github.com/Expand-sys) | Frontend |
|
||||
| [React](https://github.com/Reactified) | CC {API, Shops, and ATM, Logo} |
|
||||
| [Doggo](https://github.com/FearlessDoggo21) | Logs loading/adding Optimized, HTTP convention suggestions |
|
||||
| [Luke](https://github.com/LukeeeeBennett) | Slight Doc edits |
|
||||
|
||||
|
||||
## Features
|
||||
|
|
@ -73,6 +78,7 @@ Thank you to the contributors
|
|||
- **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)
|
||||
- **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
|
||||
|
||||
### Safety
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
"address": "0.0.0.0",
|
||||
"port": 80,
|
||||
"https": false
|
||||
},
|
||||
{
|
||||
"address": "0.0.0.0",
|
||||
"port": 443,
|
||||
"https": true,
|
||||
"cert": "",
|
||||
"key": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
35
help.md
35
help.md
|
|
@ -10,28 +10,24 @@
|
|||
| -6 | InsufficientFunds |
|
||||
|
||||
# Things of Note
|
||||
|
||||
- all endpoints respond with **JSON** file type
|
||||
- "**A**" denotes requiring Authentication in the form of a header titled "**Password**"
|
||||
* all endpoints respond with **JSON** file type
|
||||
* "**A**" denotes requiring Authentication in the form of a header titled "**Password**"
|
||||
|
||||
# Usage
|
||||
|
||||
| Name | Path | Method | A | Description |
|
||||
| :------------: | :------------------------------------- | :----: | :---: | ------------------------------------------------------------------------------------------------------------ |
|
||||
| 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 (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}` |
|
||||
| VerifyPassword | BankF/{name}/pass/verify | GET | true | returns `1` if the supplied user `{name}`'s password matches the password supplied in the header |
|
||||
| Name | Path | Method | A | Description |
|
||||
| :------------: | :------------------------------------- | :----: | :---: | -------------------------------------------------------------------------------------------------- |
|
||||
| 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}` |
|
||||
| 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 |
|
||||
|
||||
# Meta Usage
|
||||
|
||||
| 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 |
|
||||
|
||||
# System Usage
|
||||
|
||||
| Name | Path | Method | A | Description |
|
||||
| :-------------: | :-------------------- | :----: | :---: | ------------------------------------------------------------------------------------- |
|
||||
| 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 |
|
||||
|
||||
# User Management
|
||||
|
||||
| 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 |
|
||||
| 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 |
|
||||
| AdminDelUser | BankF/admin/user/{name} | DELETE | true | if the password supplied in the header matches the admin password, then the user is deleted |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ enum ErrorResponse
|
|||
UserNotFound = -1,
|
||||
WrongPassword = -2,
|
||||
InvalidRequest = -3,
|
||||
WrongAdminPassword = -4,
|
||||
NameTooLong = -5,
|
||||
UserAlreadyExists = -6,
|
||||
InsufficientFunds = -7,
|
||||
NameTooLong = -4,
|
||||
UserAlreadyExists = -5,
|
||||
InsufficientFunds = -6,
|
||||
};
|
||||
|
|
@ -24,3 +24,6 @@
|
|||
- Shipping
|
||||
- High-level bank operations such as loans
|
||||
- Some trust based system for transactions similiar to Paypal
|
||||
|
||||
- a better version of one of these existing ideas
|
||||
- something completely different
|
||||
|
|
|
|||
98
src/bank.cpp
98
src/bank.cpp
|
|
@ -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};
|
||||
if (users.try_emplace_l(
|
||||
name, [](User &) {}, init_pass))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::UserAlreadyExists;
|
||||
}
|
||||
return (users.try_emplace_l(
|
||||
name, [](User &) {}, init_pass))
|
||||
? true
|
||||
: ErrorResponse::UserAlreadyExists;
|
||||
}
|
||||
}
|
||||
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};
|
||||
if (users.try_emplace_l(
|
||||
name, [](User &) {}, init_bal, std::move(init_pass)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::UserAlreadyExists;
|
||||
}
|
||||
return (users.try_emplace_l(
|
||||
name, [](User &) {}, init_bal, std::move(init_pass)))
|
||||
? true
|
||||
: ErrorResponse::UserAlreadyExists;
|
||||
}
|
||||
}
|
||||
int_fast8_t Bank::DelUser(const std::string &name, const std::string &attempt)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||
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
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::WrongPassword;
|
||||
}
|
||||
return ErrorResponse::UserNotFound;
|
||||
}
|
||||
}
|
||||
int_fast8_t Bank::AdminDelUser(const std::string &name, const std::string &attempt)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lock{size_l};
|
||||
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
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::WrongPassword;
|
||||
}
|
||||
return ErrorResponse::UserNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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 (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
|
||||
{
|
||||
if (users.contains(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::UserNotFound;
|
||||
}
|
||||
return (users.contains(name)) ? true : ErrorResponse::UserNotFound;
|
||||
}
|
||||
int_fast8_t Bank::AdminVerifyPass(const std::string &attempt)
|
||||
{
|
||||
if (admin_pass == attempt)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::WrongPassword;
|
||||
}
|
||||
return (admin_pass == attempt) ? true : ErrorResponse::WrongPassword;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (users.modify_if(name, [amount](User &u) {
|
||||
u.balance = amount;
|
||||
}))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ErrorResponse::UserNotFound;
|
||||
}
|
||||
|
||||
return (users.modify_if(name, [amount](User &u) {
|
||||
u.balance = amount;
|
||||
}))
|
||||
? true
|
||||
: ErrorResponse::UserNotFound;
|
||||
}
|
||||
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;
|
||||
users.if_contains(name, [&res, &attempt](const User &u) {
|
||||
if (u.password == XXH3_64bits(attempt.data(), attempt.size()))
|
||||
{
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ErrorResponse::WrongPassword;
|
||||
}
|
||||
res = (u.password == XXH3_64bits(attempt.data(), attempt.size())) ? true : ErrorResponse::WrongPassword;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
|
@ -234,6 +185,7 @@ int_fast8_t Bank::ChangePassword(const std::string &name, const std::string &att
|
|||
}
|
||||
else
|
||||
{
|
||||
res = true;
|
||||
u.password = XXH3_64bits(new_pass.data(), new_pass.size());
|
||||
}
|
||||
});
|
||||
|
|
|
|||
42
users.json
42
users.json
|
|
@ -1,42 +1,8 @@
|
|||
{
|
||||
"jolly" :
|
||||
"" :
|
||||
{
|
||||
"balance" : 139,
|
||||
"log" :
|
||||
[
|
||||
{
|
||||
"amount" : 100,
|
||||
"from" : "twix",
|
||||
"time" : 1623555387199,
|
||||
"to" : "jolly"
|
||||
},
|
||||
{
|
||||
"amount" : 39,
|
||||
"from" : "twix",
|
||||
"time" : 1623693328822,
|
||||
"to" : "jolly"
|
||||
}
|
||||
],
|
||||
"password" : 746744014776526199
|
||||
"balance" : 0,
|
||||
"log" : null,
|
||||
"password" : 0
|
||||
},
|
||||
"twix" :
|
||||
{
|
||||
"balance" : 9861,
|
||||
"log" :
|
||||
[
|
||||
{
|
||||
"amount" : 100,
|
||||
"from" : "twix",
|
||||
"time" : 1623555387199,
|
||||
"to" : "jolly"
|
||||
},
|
||||
{
|
||||
"amount" : 39,
|
||||
"from" : "twix",
|
||||
"time" : 1623693328822,
|
||||
"to" : "jolly"
|
||||
}
|
||||
],
|
||||
"password" : 746744014776526199
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue