diff --git a/README.md b/README.md index 5860f17..f50cdc2 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ building the project ``` git clone --recurse-submodule https://github.com/EntireTwix/CCash/ +cd CCash mkdir build cd build cmake .. @@ -48,35 +49,8 @@ sudo ./bank ## Connected Services -Go to `{ip}/BankF/help` to see the bank's methods (also found in help.html). Using the Bank's API allows (you/others) to (make/use) connected services that utilize the bank, a couple ideas are -### Implemented: - -- [Web Frontend](https://github.com/Expand-sys/ccashfrontend) - ![image](https://user-images.githubusercontent.com/31377881/121337724-afe9fe80-c8d1-11eb-8851-23ec5e74cd26.png) -- [CC Frontend](https://github.com/Reactified/rpm/blob/main/packages/ccash-wallet) - - ![image](https://user-images.githubusercontent.com/31377881/121338034-fb041180-c8d1-11eb-8640-b18c141eb980.png) -- [CC Shop](https://github.com/Reactified/rpm/tree/main/packages/ccash-shop) - ![image](https://user-images.githubusercontent.com/31377881/120050327-de163700-bfd1-11eb-9d5a-f75c003e867c.png) - ![image](https://user-images.githubusercontent.com/31377881/120050367-09992180-bfd2-11eb-9a22-449d73c196cf.png) -- [CC ATM](https://github.com/Reactified/misc/tree/main/lua/ccash-bank) an ATM for economies allowing for an initial exchange to start up - ![image](https://user-images.githubusercontent.com/31377881/121277361-4d6b1100-c885-11eb-87c8-cfebcf58da4f.png) -- [CC API](https://github.com/Reactified/rpm/blob/main/packages/ccash-api/api.lua) - -### In-Dev: - -- [a Market](https://github.com/STBoyden/market-api-2.0) -- [Python API](https://github.com/fearlessdoggo21/ccashpythonclient) - -### Ideas: - -- Gambling -- Shipping -- High-level bank operations such as loans -- Some trust based system for transactions similiar to Paypal - -`**WARNING** : abruptly killing the program will result in data loss, use Close() method to close safely` +Go to `{ip}/BankF/help` to see the bank's methods (also found in releases as help.html). Using the Bank's API allows (you/others) to (make/use) connected services that utilize the bank, a couple ideas can be found [here](services.md) ## FAQ **Q:** how is money initially injected into the economy @@ -85,6 +59,7 @@ Go to `{ip}/BankF/help` to see the bank's methods (also found in help.html). Usi ## [Contributions](https://github.com/EntireTwix/CCash/graphs/contributors) Thank you to the contributors + | Name | Work | | :--- | --- | | [Expand](https://github.com/Expand-sys) | Frontend | diff --git a/help.html b/help.html index 15acbe4..a233d6e 100644 --- a/help.html +++ b/help.html @@ -1,85 +1,198 @@ - -

ALL FUNCTIONS (that have args) ARE EXPECTING JSON AS DATA TYPE

-

/BankF/admin/close (POST)

-

 attempt  - admin password

-
-

Closes and Saves the server.

-
-

/BankF/user (POST)

-

 name  - name of the user being added (must be less then 50 characters)

-

 init_pass  - initial password for the user being added

-
-

Adds a user to the bank

-
-

/BankF/admin/user (POST)

-

 name  - name of the user being added

-

 attempt  - admin password required to add user with balance

-

 init_bal  - initial balance for user being added

-

 init_pass  - initial password for user being added

-
-

Adds a user with initial balance

-
-

/BankF/sendfunds (POST)

-

 a_name  - sender's name

-

 b_name  - reciever's name

-

 amount  - amount being sent

-

 attempt  - password of sender

-
-

Sends money from one user to another

-
-

/BankF/changepass (PATCH)

-

 name  - name of user's password being changes

-

 attempt  - password of user being changed

-

 new_pass  - new password to replace the current user's password

-
-

Changes password of a user, returns -1 if user doesnt exist

-
-

/BankF/admin/{name}/bal (PATCH)

-

 name  - the name of the user being set

-

 attempt  - the admin password required

-

 amount  - the new balance of the user

-
-

Sets the balance of a user

-
-

/BankF/help (GET)

-
-

the page you're looking at right now!

-
-

/BankF/vpass (POST)

-

 name  - name of user being verified

-

 attempt  - password being verified

-
-

returns 0 or 1 based on if [attempt] is equal to the password of the user [name], or -1 if user does not exist. The intended usage for this function is for connected services

-
-

/BankF/contains/{name} (GET)

-
-

returns a 0 or 1 based on if the bank contains the user

-
-

/BankF/{name}/bal (GET)

-
-

returns the balance of a given user's name, if -1 that means the user does not exist

-
-

/BankF/admin/vpass (POST)

-

 attempt  - admin password

-
-

Verifies if password entered is admin password

-
-

/BankF/{name}/log (POST)

-

 attempt  - user password

-
-

returns a list of last 100 transactions, -1 if user not found, 0 if invalid password

-
-

/BankF/user (DELETE)

-

 name  - name of user being deleted

-

 attempt  - password of user being deleted

-
-

Deletes a user with the password of the user as verification

-
-

/BankF/admin/user (DELETE)

-

 name  - name of user being deleted

-

 attempt  - admin password

-
-

Deletes a user with admin password as verification

-
- - +

Error Responses

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#meaning
-1UserNotFound
-2WrongPassword
-3InvalidRequest
-4WrongAdminPassword
-5NameTooLong
-6UserAlreadyExists
-7InsufficientFunds
+

Things of Note

+
    +
  • all endpoints respond with JSON file type
  • +
  • "A" denotes requiring Authentication in the form of a header titled "Password"
  • +
+

Usage

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePathMethodADescription
GetBal/{name}/balGETtruereturns the balance of a given user {name}
GetLog/{name}/logGETtruereturns a list of last n number of transactions (a configurable amount) of a given user {name}
SendFunds/{name}/send/{to}/amount={amount}POSTfalsesends {amount} from user {name} to user {to}
VerifyPassword/{name}/pass/verifyGETtruereturns true or false depending on if the supplied user {name}'s password matches the password supplied in the header
+

Meta Usage

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePathMethodADescription
ChangePassword/{name}/pass/changePATCHtrueif 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/admin/{name}/bal/amount={amount}PATCHtruesets the balance of a give user {name} if the supplied password matches the admin password
+

System Usage

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePathMethodADescription
Help/helpGETfalsethe page you’re looking at right now!
Close/admin/closePOSTtruesaves and then closes the program if the supplied password matches the admin password
Contains/contains/{name}GETfalsereturns true or false depending on if the supplied user {name} exists
AdminVerifyPass/admin/verifyGETtruereturns true or false depending on if the password supplied in the header matches the admin password
+

User Management

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePathMethodADescription
AddUser/user/{name}POSTtrueregisters a user with the name {name}, balance of 0 and a password of the password supplied in the header
AdminAddUser/admin/user/{name}?init_bal={init_bal}POSTtrueif 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/user/{name}DELETEtrueif the password supplied in the header matches the user {name}'s password, then the user is deleted
AdminDelUser/admin/user/{name}DELETEtrueif the password supplied in the header matches the admin password, then the user is deleted
\ No newline at end of file diff --git a/help.md b/help.md new file mode 100644 index 0000000..3eeb8c0 --- /dev/null +++ b/help.md @@ -0,0 +1,45 @@ +# Error Responses + +| # | meaning | +| --- | ------------------ | +| -1 | UserNotFound | +| -2 | WrongPassword | +| -3 | InvalidRequest | +| -4 | WrongAdminPassword | +| -5 | NameTooLong | +| -6 | UserAlreadyExists | +| -7 | InsufficientFunds | + +# Things of Note +* 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 | /{name}/bal | GET | true | returns the balance of a given user `{name}` | +| GetLog | /{name}/log | GET | true | returns a list of last `n` number of transactions (a configurable amount) of a given user `{name}` | +| SendFunds | /{name}/send/{to}/amount={amount} | POST | false | sends `{amount}` from user `{name}` to user `{to}` | +| VerifyPassword | /{name}/pass/verify | GET | true | returns `true` or `false` depending on if the supplied user `{name}`'s password matches the password supplied in the header | + +# Meta Usage +| Name | Path | Method | A | Description | +| :------------: | :-------------------------------- | :----: | :---: | ---------------------------------------------------------------------------------------------------------------------------------------- | +| ChangePassword | /{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 | /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 | /help | GET | false | the page you're looking at right now! | +| Close | /admin/close | POST | true | saves and then closes the program if the supplied password matches the admin password | +| Contains | /contains/{name} | GET | false | returns `true` or `false` depending on if the supplied user `{name}` exists | +| AdminVerifyPass | /admin/verify | GET | true | returns `true` or `false` depending on if the password supplied in the header matches the admin password | + +# User Management +| Name | Path | Method | A | Description | +| :----------: | :------------------------------------- | :----: | :---: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| AddUser | /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 | /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 | /user/{name} | DELETE | true | if the password supplied in the header matches the user `{name}`'s password, then the user is deleted | +| AdminDelUser | /admin/user/{name} | DELETE | true | if the password supplied in the header matches the admin password, then the user is deleted | \ No newline at end of file diff --git a/include/bank.hpp b/include/bank.hpp index 03e5e4a..b95ce85 100644 --- a/include/bank.hpp +++ b/include/bank.hpp @@ -2,6 +2,7 @@ #include #include #include "xxhash.h" +#include "error_responses.hpp" #include "parallel-hashmap/parallel_hashmap/phmap.h" #include "user.hpp" @@ -32,125 +33,189 @@ private: public: 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 ErrorResponse::NameTooLong; } - std::shared_lock 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 lock{size_l}; - state = users.try_emplace_l( - name, [](User &) {}, init_bal, std::move(init_pass)); + if (!users.try_emplace_l( + name, [](User &) {}, std::move(init_pass))) + { + return ErrorResponse::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 ErrorResponse::NameTooLong; + } + if (admin_pass != attempt) + { + return ErrorResponse::WrongAdminPassword; + } + { + std::shared_lock lock{size_l}; + if (!users.try_emplace_l( + name, [](User &) {}, init_bal, std::move(init_pass))) + { + return ErrorResponse::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 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 ErrorResponse::UserNotFound; + } + else + { + return state * ErrorResponse::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 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 ErrorResponse::UserNotFound; + } + else + { + return state * ErrorResponse::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 if (a_name == b_name || !amount) { - return false; + return ErrorResponse::InvalidRequest; } - //if A exists, A can afford it, and A's password matches - bool state = false; + int_fast8_t state = false; { std::shared_lock lock{send_funds_l}; //because SendFunds requires 3 locking operations - users.modify_if(a_name, [&state, amount, &attempt](User &a) { - if (state = (a.balance >= amount) && (a.password == XXH3_64bits(attempt.data(), attempt.size()))) - { - a.balance -= amount; - } - }); - - if (state) + if (users.modify_if(a_name, [&state, amount, &attempt](User &a) { + //if A exists, A can afford it, and A's password matches + if (a.balance < amount) + { + state = ErrorResponse::InsufficientFunds; + } + else + { + if (a.password != XXH3_64bits(attempt.data(), attempt.size())) + { + state = ErrorResponse::WrongPassword; + } + else + { + a.balance -= amount; + state = true; + } + } + })) { - //if B doesnt exist - if (!users.modify_if(b_name, [amount](User &b) { - b.balance += amount; - })) + return ErrorResponse::UserNotFound; + } + else + { + if (!state) { - //attempt to refund if A exist - users.modify_if(a_name, [amount](User &a) { - a.balance += amount; - }); - return false; //because had to refund transaction + return state; + } + else + { + //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 ErrorResponse::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 { 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) { - 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 ErrorResponse::WrongAdminPassword; + } + else + { + if (!users.modify_if(name, [amount](User &u) { + u.balance = amount; + })) + { + return ErrorResponse::UserNotFound; + } + else + { + return true; + } + } + } int_fast64_t GetBal(const std::string &name) const { - int_fast64_t res = -1; + int_fast64_t res = ErrorResponse::UserNotFound; users.if_contains(name, [&res](const User &u) { res = u.balance; }); return res; } + int_fast8_t VerifyPassword(const std::string &name, const std::string &attempt) const { - int_fast8_t res = -1; + int_fast8_t res = ErrorResponse::UserNotFound; users.if_contains(name, [&res, &attempt](const User &u) { 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 res = -1; + int_fast8_t res = ErrorResponse::UserNotFound; users.modify_if(name, [&res, &attempt, &new_pass](User &u) { - res = (u.password == XXH3_64bits(attempt.data(), attempt.size())); - if (res) + if (u.password != XXH3_64bits(attempt.data(), attempt.size())) + { + res = ErrorResponse::WrongPassword; + } + else { 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 (u.password != XXH3_64bits(attempt.data(), attempt.size())) { - res = 0; + res = ErrorResponse::WrongPassword; } else { @@ -191,17 +259,13 @@ public: } })) { - return -1; + return ErrorResponse::UserNotFound; } return res; } void Save() { - Json::StreamWriterBuilder builder; - const std::unique_ptr writer(builder.newStreamWriter()); - - std::ofstream user_save("../users.json"); Json::Value temp; //loading info into json temp @@ -217,9 +281,16 @@ public: } if (!temp.isNull()) { + std::ofstream user_save("../users.json"); + Json::StreamWriterBuilder builder; + const std::unique_ptr writer(builder.newStreamWriter()); writer->write(temp, &user_save); + user_save.close(); + } + else + { + throw std::invalid_argument("Saving Failed\n"); } - user_save.close(); } //NOT THREAD SAFE, BY NO MEANS SHOULD THIS BE CALLED WHILE RECEIEVING REQUESTS @@ -234,8 +305,8 @@ public: if (!parseFromStream(builder, user_save, &temp, &errs)) { std::cerr << errs << '\n'; - throw std::invalid_argument("Parsing Failed\n"); user_save.close(); + throw std::invalid_argument("Parsing Failed\n"); } else { @@ -254,3 +325,5 @@ public: } } } bank; + +//TODO make branchless \ No newline at end of file diff --git a/include/bank_f.hpp b/include/bank_f.hpp index 795400d..c318865 100644 --- a/include/bank_f.hpp +++ b/include/bank_f.hpp @@ -10,6 +10,7 @@ using namespace drogon; #define GEN_BODY \ const auto temp_req = req->getJsonObject(); \ const auto body = temp_req ? *temp_req : Json::Value(); +#define PASS_HEADER std::string pass = req->getHeader("Password"); template INLINE Json::Value JsonReturn(T &&val) @@ -19,7 +20,7 @@ INLINE Json::Value JsonReturn(T &&val) { res["value"] = (int)val; //becuase of json lib interpreting 67 as 'A' for example } - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { res["value"] = (Json::Int64)val; } @@ -37,15 +38,15 @@ public: { auto resp = HttpResponse::newHttpResponse(); auto handlerInfo = app().getHandlersInfo(); - resp->setBody("

ALL FUNCTIONS (that have args) ARE EXPECTING JSON AS DATA TYPE

/BankF/admin/close (POST)

 attempt  - admin password

Closes and Saves the server.

/BankF/user (POST)

 name  - name of the user being added (must be less then 50 characters)

 init_pass  - initial password for the user being added

Adds a user to the bank

/BankF/admin/user (POST)

 name  - name of the user being added

 attempt  - admin password required to add user with balance

 init_bal  - initial balance for user being added

 init_pass  - initial password for user being added

Adds a user with initial balance

/BankF/sendfunds (POST)

 a_name  - sender's name

 b_name  - reciever's name

 amount  - amount being sent

 attempt  - password of sender

Sends money from one user to another

/BankF/changepass (PATCH)

 name  - name of user's password being changes

 attempt  - password of user being changed

 new_pass  - new password to replace the current user's password

Changes password of a user, returns -1 if user doesnt exist

/BankF/admin/{name}/bal (PATCH)

 name  - the name of the user being set

 attempt  - the admin password required

 amount  - the new balance of the user

Sets the balance of a user

/BankF/help (GET)

the page you're looking at right now!

/BankF/vpass (POST)

 name  - name of user being verified

 attempt  - password being verified

returns 0 or 1 based on if [attempt] is equal to the password of the user [name], or -1 if user does not exist. The intended usage for this function is for connected services

/BankF/contains/{name} (GET)

returns a 0 or 1 based on if the bank contains the user

/BankF/{name}/bal (GET)

returns the balance of a given user's name, if -1 that means the user does not exist

/BankF/admin/vpass (POST)

 attempt  - admin password

Verifies if password entered is admin password

/BankF/{name}/log (POST)

 attempt  - user password

returns a list of last 100 transactions, -1 if user not found, 0 if invalid password

/BankF/user (DELETE)

 name  - name of user being deleted

 attempt  - password of user being deleted

Deletes a user with the password of the user as verification

/BankF/admin/user (DELETE)

 name  - name of user being deleted

 attempt  - admin password

Deletes a user with admin password as verification

"); + resp->setBody("

Error Responses

# meaning
-1 UserNotFound
-2 WrongPassword
-3 InvalidRequest
-4 WrongAdminPassword
-5 NameTooLong
-6 UserAlreadyExists
-7 InsufficientFunds

Things of Note

  • 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 /{name}/bal GET true returns the balance of a given user {name}
GetLog /{name}/log GET true returns a list of last n number of transactions (a configurable amount) of a given user {name}
SendFunds /{name}/send/{to}/amount={amount} POST false sends {amount} from user {name} to user {to}
VerifyPassword /{name}/pass/verify GET true returns true or false depending on if the supplied user {name}'s password matches the password supplied in the header

Meta Usage

Name Path Method A Description
ChangePassword /{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 /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 /help GET false the page you’re looking at right now!
Close /admin/close POST true saves and then closes the program if the supplied password matches the admin password
Contains /contains/{name} GET false returns true or false depending on if the supplied user {name} exists
AdminVerifyPass /admin/verify GET true returns true or false depending on if the password supplied in the header matches the admin password

User Management

Name Path Method A Description
AddUser /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 /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 /user/{name} DELETE true if the password supplied in the header matches the user {name}'s password, then the user is deleted
AdminDelUser /admin/user/{name} DELETE true if the password supplied in the header matches the admin password, then the user is deleted
"); resp->setExpiredTime(0); callback(resp); } void Close(req_args) const { - GEN_BODY + PASS_HEADER bool res; - if (body["attempt"].asCString() == bank.admin_pass) + if (pass == bank.admin_pass) { bank.Save(); @@ -58,35 +59,35 @@ public: } JSON(res); } - void AddUser(req_args) const + void AddUser(req_args, std::string &&name) const { - GEN_BODY - JSON(bank.AddUser(body["name"].asCString(), body["init_pass"].asCString())); + PASS_HEADER + JSON(bank.AddUser(std::move(name), std::move(pass))); } - void AdminAddUser(req_args) const + void AdminAddUser(req_args, std::string &&name, uint32_t init_bal) const { - GEN_BODY - JSON(bank.AdminAddUser(body["attempt"].asCString(), body["name"].asCString(), body["init_bal"].asUInt(), body["init_pass"].asCString())); + PASS_HEADER + JSON(bank.AdminAddUser(pass, std::move(name), init_bal, std::string(req->getBody()))); } - void DelUser(req_args) const + void DelUser(req_args, const std::string &name) const { - GEN_BODY - JSON(bank.DelUser(body["name"].asCString(), body["attempt"].asCString())); + PASS_HEADER + JSON(bank.DelUser(name, pass)); } - void AdminDelUser(req_args) const + void AdminDelUser(req_args, const std::string &name) const { - GEN_BODY - JSON(bank.AdminDelUser(body["name"].asCString(), body["attempt"].asCString())); + PASS_HEADER + JSON(bank.AdminDelUser(name, pass)); } - void SendFunds(req_args) const + void SendFunds(req_args, const std::string name, const std::string to, uint32_t amount) const { - GEN_BODY - JSON(bank.SendFunds(body["a_name"].asCString(), body["b_name"].asCString(), body["amount"].asUInt(), body["attempt"].asCString())); + PASS_HEADER + JSON(bank.SendFunds(name, to, amount, pass)); } - void ChangePassword(req_args) const + void ChangePassword(req_args, const std::string &name) const { - GEN_BODY - JSON(bank.ChangePassword(body["name"].asCString(), body["attempt"].asCString(), body["new_pass"].asCString())); + PASS_HEADER + JSON(bank.ChangePassword(name, pass, std::string(req->getBody()))); } void Contains(req_args, const std::string &name) const { @@ -96,27 +97,27 @@ public: { JSON(bank.GetBal(name)); } - void VerifyPassword(req_args) const + void VerifyPassword(req_args, const std::string &name) const { - GEN_BODY - JSON(bank.VerifyPassword(body["name"].asCString(), body["attempt"].asCString())); + PASS_HEADER + JSON(bank.VerifyPassword(name, pass)); } - void SetBal(req_args, const std::string &name) const + void SetBal(req_args, const std::string &name, uint32_t amount) const { - GEN_BODY - JSON(bank.SetBal(name, body["attempt"].asCString(), body["amount"].asUInt())); + PASS_HEADER + JSON(bank.SetBal(name, pass, amount)); } void AdminVerifyPass(req_args) { - GEN_BODY - JSON(bank.AdminVerifyPass(body["attempt"].asCString())); + PASS_HEADER + JSON(bank.AdminVerifyPass(pass)); } void GetLog(req_args, const std::string &name) { if constexpr (max_log_size) { - GEN_BODY - JSON(bank.GetLogs(name, body["attempt"].asCString())); + PASS_HEADER + JSON(bank.GetLogs(name, pass)); } else { @@ -127,22 +128,28 @@ public: } METHOD_LIST_BEGIN - METHOD_ADD(BankF::Close, "/admin/close", Post, Options); - METHOD_ADD(BankF::AddUser, "/user", Post, Options); - METHOD_ADD(BankF::AdminAddUser, "/admin/user", Post, Options); - METHOD_ADD(BankF::SendFunds, "/sendfunds", Post, Options); - METHOD_ADD(BankF::ChangePassword, "/changepass", Patch, Options); - METHOD_ADD(BankF::SetBal, "/admin/{name}/bal", Patch, Options); - - METHOD_ADD(BankF::Help, "/help", Get, Options); - METHOD_ADD(BankF::VerifyPassword, "/vpass", Post, Options); - METHOD_ADD(BankF::Contains, "/contains/{name}", Get, Options); + //Usage METHOD_ADD(BankF::GetBal, "/{name}/bal", Get, Options); - METHOD_ADD(BankF::AdminVerifyPass, "/admin/vpass", Post, Options); - METHOD_ADD(BankF::GetLog, "/{name}/log", Post, Options); + METHOD_ADD(BankF::GetLog, "/{name}/log", Get, Options); + METHOD_ADD(BankF::SendFunds, "/{name}/send/{to}/amount={amount}", Post, Options); + METHOD_ADD(BankF::VerifyPassword, "/{name}/pass/verify", Get, Options); + + //Meta Usage + METHOD_ADD(BankF::ChangePassword, "/{name}/pass/change", Patch, Options); + METHOD_ADD(BankF::SetBal, "/admin/{name}/bal/amount={amount}", Patch, Options); + + //System Usage + METHOD_ADD(BankF::Help, "/help", Get, Options); + METHOD_ADD(BankF::Close, "/admin/close", Post, Options); + METHOD_ADD(BankF::Contains, "/contains/{name}", Get, Options); + METHOD_ADD(BankF::AdminVerifyPass, "/admin/verify", Get, Options); + + //User Managment + METHOD_ADD(BankF::AddUser, "/user/{name}", Post, Options); + METHOD_ADD(BankF::AdminAddUser, "/admin/user/{name}?init_bal={init_bal}", Post, Options); + METHOD_ADD(BankF::DelUser, "/user/{name}", Delete, Options); + METHOD_ADD(BankF::AdminDelUser, "/admin/user/{name}", Delete, Options); - METHOD_ADD(BankF::DelUser, "/user", Delete, Options); - METHOD_ADD(BankF::AdminDelUser, "/admin/user", Delete, Options); METHOD_LIST_END }; \ No newline at end of file diff --git a/include/log_consts.hpp b/include/consts.hpp similarity index 79% rename from include/log_consts.hpp rename to include/consts.hpp index b0c40bd..fc66c35 100644 --- a/include/log_consts.hpp +++ b/include/consts.hpp @@ -3,3 +3,4 @@ // Setting both values to 0 does not compile logging constexpr unsigned max_log_size = 100; constexpr unsigned pre_log_size = 10; +constexpr unsigned max_name_size = 50; \ No newline at end of file diff --git a/include/error_responses.hpp b/include/error_responses.hpp new file mode 100644 index 0000000..5050d33 --- /dev/null +++ b/include/error_responses.hpp @@ -0,0 +1,11 @@ +#pragma once +enum ErrorResponse +{ + UserNotFound = -1, + WrongPassword = -2, + InvalidRequest = -3, + WrongAdminPassword = -4, + NameTooLong = -5, + UserAlreadyExists = -6, + InsufficientFunds = -7, +}; \ No newline at end of file diff --git a/include/log.hpp b/include/log.hpp index 15674eb..2fbaa5f 100644 --- a/include/log.hpp +++ b/include/log.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include "log_consts.hpp" +#include "consts.hpp" #include "transactions.hpp" struct Log diff --git a/services.md b/services.md new file mode 100644 index 0000000..c7f1da0 --- /dev/null +++ b/services.md @@ -0,0 +1,27 @@ +# Connected Services + +### Implemented: + +- [Web Frontend](https://github.com/Expand-sys/ccashfrontend) + ![image](https://user-images.githubusercontent.com/31377881/121337724-afe9fe80-c8d1-11eb-8851-23ec5e74cd26.png) +- [CC Frontend](https://github.com/Reactified/rpm/blob/main/packages/ccash-wallet) + + ![image](https://user-images.githubusercontent.com/31377881/121338034-fb041180-c8d1-11eb-8640-b18c141eb980.png) +- [CC Shop](https://github.com/Reactified/rpm/tree/main/packages/ccash-shop) + ![image](https://user-images.githubusercontent.com/31377881/120050327-de163700-bfd1-11eb-9d5a-f75c003e867c.png) + ![image](https://user-images.githubusercontent.com/31377881/120050367-09992180-bfd2-11eb-9a22-449d73c196cf.png) +- [CC ATM](https://github.com/Reactified/misc/tree/main/lua/ccash-bank) an ATM for economies allowing for an initial exchange to start up + ![image](https://user-images.githubusercontent.com/31377881/121277361-4d6b1100-c885-11eb-87c8-cfebcf58da4f.png) +- [CC API](https://github.com/Reactified/rpm/blob/main/packages/ccash-api/api.lua) + +### In-Dev: + +- [a Market](https://github.com/STBoyden/market-api-2.0) +- [Python API](https://github.com/fearlessdoggo21/ccashpythonclient) + +### Ideas: + +- Gambling +- Shipping +- High-level bank operations such as loans +- Some trust based system for transactions similiar to Paypal