Merge branch 'EntireTwix:main' into main

This commit is contained in:
Expand-sys 2023-01-23 01:41:58 +11:00 committed by GitHub
commit 8f85e13f11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 257 additions and 101 deletions

View file

@ -96,23 +96,10 @@ int main(int argc, char **argv)
#endif #endif
Op(Bank::GetLogsV2("twix"), "get logs init (v2): ", 1); Op(Bank::GetLogsV2("twix"), "get logs init (v2): ", 1);
Op(Bank::GetLogsV2("twix"), "get logs cached (v2): ", 1000000); Op(Bank::GetLogsV2("twix"), "get logs cached (v2): ", 1000000);
Op(Bank::GetLogsRange("twix", 0, 100), "get logs range: ", 1000000);
#endif #endif
Op(Bank::PruneUsers(0, 0), "prune users: ", 1); Op(Bank::PruneUsers(0, 0), "prune users: ", 1);
Op(Bank::Save(), "saving: ", 1); Op(Bank::Save(), "saving: ", 1);
//GetBal scalining test
//std::default_random_engine generator;
//std::uniform_real_distribution<double> distribution(0.0, 1.0);
// for (size_t i = 0; i < 10000000; ++i)
// {
// Bank::AddUser(std::to_string(i), 100000, "root");
// if (i % 10000 == 0)
// {
// auto u = std::to_string((int)(distribution(generator) * i));
// Op(Bank::GetBal(u), std::to_string(i) + ", ", 100000);
// }
// }
return 0; return 0;
} }

View file

@ -4,7 +4,7 @@
You can with [build docs](https://github.com/EntireTwix/CCash/blob/main/docs/building.md) you can build from source or use the Docker package. You can with [build docs](https://github.com/EntireTwix/CCash/blob/main/docs/building.md) you can build from source or use the Docker package.
### Why is my username invalid ### Why is my username invalid
Usernames are restricted by minecraft's requirements Usernames are restricted by minecraft's requirements
* lowercase letters * letters
* numbers * numbers
* _ * _
* length must be atleast 3 and at most 16 characters. * length must be atleast 3 and at most 16 characters.
@ -16,7 +16,5 @@ Because this usecase requires none of the features a database would offer.
Consider disabling `ADD_USER_OPEN` in the [build proccess](https://github.com/EntireTwix/CCash/blob/main/docs/building.md). Consider disabling `ADD_USER_OPEN` in the [build proccess](https://github.com/EntireTwix/CCash/blob/main/docs/building.md).
### My instance is taking up too much storage or RAM ### My instance is taking up too much storage or RAM
Reduce log size and/or use the prune users endpoint to remove dead accounts. Reduce log size and/or use the prune users endpoint to remove dead accounts.
### How do I start an economy
I believe setting up a commodities exchange is the best way to get an economy going initially.
### Why not use an economy mod ### Why not use an economy mod
Speed of operations, CCash being external to MC (and so compatible with any version/configuration), and the API are the main advantages to an economy mod. Speed of operations, CCash being external to MC (and so compatible with any version/configuration), and the API are the main advantages to an economy mod.

View file

@ -6,21 +6,23 @@
| supported | :heavy_check_mark: | | supported | :heavy_check_mark: |
| uses deprecated endpoints | ⚠ | | uses deprecated endpoints | ⚠ |
| uses defunt endpoints | :no_entry: | | uses defunt endpoints | :no_entry: |
| in development | :hammer: |
## General ## General
| author | name | support | image | | author | name | support | image |
| :-------------------------------------- | ----------------------------------------------------------- | :----------------: | :-------------------------------------------------------------------------------------------------------------: | | :-------------------------------------- | ----------------------------------------------------------- | :----------------: | :-------------------------------------------------------------------------------------------------------------: |
| [Expand](https://github.com/Expand-sys) | [Web Frontend](https://github.com/Expand-sys/ccashfrontend) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/121337724-afe9fe80-c8d1-11eb-8851-23ec5e74cd26.png) | | [Expand](https://github.com/Expand-sys) | [Web Frontend](https://github.com/Expand-sys/ccashfrontend) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/121337724-afe9fe80-c8d1-11eb-8851-23ec5e74cd26.png) | |
| [Expand](https://github.com/Expand-sys) | [Discord Bot](https://github.com/Expand-sys/ccashbot) | :heavy_check_mark: | |
| [ArcNyxx](https://github.com/ArcNyxx) | [CCash CLI](https://github.com/ArcNyxx/ccash_cmd) | ⚠ | | | [ArcNyxx](https://github.com/ArcNyxx) | [CCash CLI](https://github.com/ArcNyxx/ccash_cmd) | ⚠ | |
## Minecraft ## Minecraft
| author | name | support | image | | author | name | support | image |
| :------------------------------------------ | --------------------------------------------------------------------------- | :----------------: | :-------------------------------------------------------------------------------------------------------------: | | :------------------------------------------ | ---------------------------------------------------------------------------------------- | :----------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| [Reactified](https://github.com/Reactified) | [Shop](https://github.com/Reactified/rpm/tree/main/packages/ccash-shop) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/120050327-de163700-bfd1-11eb-9d5a-f75c003e867c.png) | | [Reactified](https://github.com/Reactified) | [Shop](https://github.com/Reactified/rpm/tree/main/packages/ccash-shop) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/120050327-de163700-bfd1-11eb-9d5a-f75c003e867c.png) |
| [Reactified](https://github.com/Reactified) | [Wallet](https://github.com/Reactified/rpm/tree/main/packages/ccash-wallet) | ⚠ | ![image](https://user-images.githubusercontent.com/31377881/121338034-fb041180-c8d1-11eb-8640-b18c141eb980.png) | | [Reactified](https://github.com/Reactified) | [Wallet](https://github.com/Reactified/rpm/tree/main/packages/ccash-wallet) | ⚠ | ![image](https://user-images.githubusercontent.com/31377881/121338034-fb041180-c8d1-11eb-8640-b18c141eb980.png) |
| [Reactified](https://github.com/Reactified) | [ATM](https://github.com/Reactified/rpm/tree/main/packages/ccash-bank) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/121277361-4d6b1100-c885-11eb-87c8-cfebcf58da4f.png) | | [Reactified](https://github.com/Reactified) | [ATM](https://github.com/Reactified/rpm/tree/main/packages/ccash-bank) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/121277361-4d6b1100-c885-11eb-87c8-cfebcf58da4f.png) |
| [STBoyden](https://github.com/STBoyden) | Commodities Exchange (in-development) | :heavy_check_mark: | | | [Reactified](https://github.com/Reactified) | [Chunk Loader Shop](https://github.com/Reactified/rpm/tree/main/packages/forceload-shop) | :heavy_check_mark: | ![image](https://user-images.githubusercontent.com/31377881/209894520-f7183f45-bbac-40f3-9f95-043bda3c0097.png) ![image](https://user-images.githubusercontent.com/31377881/209894553-16ef7e04-52e7-4198-8a39-9ad2ada6eaf7.png) |
| [STBoyden](https://github.com/STBoyden) | [Commodities Exchange](https://github.com/STBoyden/ccash-market) | :hammer: | |
## Desired ## Desired
| idea | description | | idea | description |

View file

@ -17,73 +17,77 @@
## all error responses have JSON string along with them to describe ## all error responses have JSON string along with them to describe
### Usage endpoints ### Usage endpoints
| name | added on | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U | | name | last change | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U |
| :------------- | :------: | ------------------------------------------------------------------------------ | -------------------------------- | ------------------------------- | :---------: | :------------: | :--------------: | :-----------------------------------------------------------: | :----------------: | :----------------: | :---: | :----------------: | | :------------- | :---------: | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------------------- | :---------: | :------------: | :--------------: | :-----------------------------------------------------------: | :----------------: | :----------------: | :---: | :----------------: |
| GetBal | `v2.3.0` | retrieving the balance of a given user, `{name}` | `N/A` | api/v1/user/balance?name={name} | `GET` | 200 | uint32 | the user's balance | :heavy_check_mark: | :x: | :x: | :x: | | GetBal | `v2.3.0` | retrieving the balance of a given user, `{name}` | `N/A` | api/v1/user/balance?name={name} | `GET` | 200 | uint32 | the user's balance | :heavy_check_mark: | :x: | :x: | :x: |
| GetLog | `v2.3.0` | retrieves the logs of a given user, length varies by server configuration | `N/A` | ⚠ api/v1/user/log | `GET` | 200 | array of objects | [{"to":string, "from":string, "amount":uint32, "time":int64}] | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | | GetLogs | `v2.3.0` | retrieves the logs of a given user, length varies by server configuration (oldest to newest transactions) | `N/A` | ⚠ api/v1/user/log | `GET` | 200 | array of objects | [{"to":string, "from":string, "amount":uint32, "time":int64}] | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| GetLogV2 | `v2.5.1` | retrieves the logs of a given user, length varies by server configuration | `N/A` | api/v2/user/log | `GET` | 200 | array of objects | [{"counterparty":string, "amount":int64, "time":int64}] | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | | GetLogsV2 | `v2.6.1` | retrieves the logs of a given user, length varies by server configuration (newest to oldest transactions) | `N/A` | api/v2/user/log | `GET` | 200 | array of objects | [{"counterparty":string, "amount":int64, "time":int64}] | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| SendFunds | `v2.3.0` | sends funds from the authenticated user to the user `{name}` given in the json | {"name":string, "amount":uint32} | api/v1/user/transfer | `POST` | 200 | uint32 | the user's balance after the transaction | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | | GetLogsRange | `v2.6.1` | retrieves the logs of a given user, where `{start}` is the 0-indexed first log and `{length}` is the number of logs after that index. | `N/A` | api/v1/user/log_range | `GET` | 200 | array of objects | [{"counterparty":string, "amount":int64, "time":int64}] | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| SendFunds | `v2.3.0` | sends funds from the authenticated user to the user `"name"` given in the json | {"name":string, "amount":uint32} | api/v1/user/transfer | `POST` | 200 | uint32 | the user's balance after the transaction | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| ChangePassword | `v2.3.0` | changes the password of the Authenticated user | {"pass":string} | api/v1/user/change_password | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| VerifyPassword | `v2.3.0` | verifies the credentials, used for connected services for ease of use | `N/A` | api/v1/user/verify_password | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | | VerifyPassword | `v2.3.0` | verifies the credentials, used for connected services for ease of use | `N/A` | api/v1/user/verify_password | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
### Usage enpoint errors ### Usage enpoint errors
| name | 400 | 401 | 404 | 406 | | name | 400 | 401 | 404 | 406 |
| :------------- | :----------------: | :----------------: | :----------------: | :----------------: | | :------------- | :----------------: | :----------------: | :----------------: | :----------------: |
| GetBal | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | | GetBal | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: |
| GetLog | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | GetLogs | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| GetLogV2 | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | GetLogsV2 | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| GetLogsRange | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| SendFunds | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | SendFunds | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| VerifyPassword | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: | | VerifyPassword | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| ChangePassword | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
### Meta Usage endpoints ### Meta Usage endpoints
| name | added on | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U | | name | last change | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U |
| :------------------ | :------: | -------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------- | :---------: | :------------: | :---------: | :----------------------------: | :----------------: | :----------------: | :----------------: | :----------------: | | :------------------ | :---------: | -------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------- | :---------: | :------------: | :--------------: | :-----------------------------------------------------: | :----------------: | :----------------: | :----------------: | :---: |
| ChangePassword | `v2.3.0` | changes the password of the Authenticated user | {"pass":string} | api/v1/user/change_password | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | | AdminGetLogs | `v2.6.1` | retreives the logs of a given user `{name}`, length varies by server configuration | `N/A` | api/v1/admin/user/log?name={name} | `GET` | 200 | array of objects | [{"counterparty":string, "amount":int64, "time":int64}] | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: |
| AdminChangePassword | `v2.3.0` | changes the password of a given user `{name}` | {"name":string,"pass":string} | api/v1/admin/user/change_password | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | | AdminChangePassword | `v2.3.0` | changes the password of a given user `"name"` | {"name":string,"pass":string} | api/v1/admin/user/change_password | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| SetBal | `v2.3.0` | sets the balance of a given user `{name}` | {"name":string,"amount":uint32} | api/v1/admin/set_balance | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | | AdminVerifyAccount | `v2.3.0` | checks wether a user is the admin | `N/A` | api/v1/admin/verify_account | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: |
| ImpactBal | `v2.3.0` | modifies the user `{name}`'s balance by `{amount}` if positive itll add, if negative itll subtract | {"name":string,"amount":int64} | api/v1/admin/impact_balance | `POST` | 200 | uint32 | new balance after modification | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | | SetBal | `v2.3.0` | sets the balance of a given user `"name"` | {"name":string,"amount":uint32} | api/v1/admin/set_balance | `PATCH` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| ImpactBal | `v2.3.0` | modifies the user `"name"`'s balance by `"amount"` if positive itll add, if negative itll subtract | {"name":string,"amount":int64} | api/v1/admin/impact_balance | `POST` | 200 | uint32 | new balance after modification | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
### Meta Usage endpoint errors ### Meta Usage endpoint errors
| name | 400 | 401 | 404 | 406 | | name | 400 | 401 | 404 | 406 |
| :------------------ | :----------------: | :----------------: | :----------------: | :----------------: | | :------------------ | :----------------: | :----------------: | :----------------: | :----------------: |
| ChangePassword | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | | AdminGetLogs | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| AdminChangePassword | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | AdminChangePassword | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| AdminVerifyAccount | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| SetBal | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | SetBal | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| ImpactBal | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | ImpactBal | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
### Sytem Usage endpoints ### Sytem Usage endpoints
| name | added on | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U | | name | last change | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U |
| :----------------- | :------: | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------ | :---------: | :------------: | :---------: | :-----------------------------------------------------------------: | :----------------: | :----------------: | :----------------: | :---: | | :------------ | :---------: | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------ | :---------: | :------------: | :---------: | :-----------------------------------------------------------------: | :----------------: | :----------------: | :----------------: | :---: |
| Help | `v2.3.0` | redirects to GitHub projects Docs | `N/A` | api/help | `GET` | 301 | `N/A` | `N/A` | :x: | :x: | :x: | :x: | | Help | `v2.3.0` | redirects to GitHub projects Docs | `N/A` | api/help | `GET` | 301 | `N/A` | `N/A` | :x: | :x: | :x: | :x: |
| Close | `v2.3.0` | saves & closes the CCash webserver | `N/A` | api/v1/admin/shutdown | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | | Close | `v2.3.0` | saves & closes the CCash webserver | `N/A` | api/v1/admin/shutdown | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: |
| Contains | `v2.3.0` | checks wether a user exists | `N/A` | api/v1/user/exists?name={name} | `GET` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :x: | | Contains | `v2.3.0` | checks wether a given user `{name}` exists | `N/A` | api/v1/user/exists?name={name} | `GET` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :x: |
| AdminVerifyAccount | `v2.3.0` | checks wether a user is the admin | `N/A` | api/v1/admin/verify_account | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | | PruneUsers | `v2.3.0` | deletes users with most recent transactions older then `"time"` (if logs are enabled) and have less money then `"amount"` | {"time":int64,"amount":uint32} or just {"amount":uint32} | api/v1/admin/prune_users | `POST` | 200 | uint64 | number of users deleted | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| PruneUsers | `v2.3.0` | deletes users with most recent transactions older then `{time}` (if logs are enabled) and have less money then `{amount}` | {"time":int64,"amount":uint32} or just {"amount":uint32} | api/v1/admin/prune_users | `POST` | 200 | uint64 | number of users deleted | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| ApiProperties | `v2.5.1` | properties of the given instance | `N/A` | api/properties | `GET` | 200 | json object | {"max_log":uint64, "add_user_open":boolean, "return_on_del":string} | :heavy_check_mark: | :x: | :x: | :x: | | ApiProperties | `v2.5.1` | properties of the given instance | `N/A` | api/properties | `GET` | 200 | json object | {"max_log":uint64, "add_user_open":boolean, "return_on_del":string} | :heavy_check_mark: | :x: | :x: | :x: |
### System Usage endpoin errors ### System Usage endpoin errors
| name | 401 | 404 | 406 | | name | 401 | 404 | 406 |
| :----------------- | :----------------: | :----------------: | :----------------: | | :------------ | :----------------: | :----------------: | :----------------: |
| Help | :x: | :x: | :x: | | Help | :x: | :x: | :x: |
| Close | :heavy_check_mark: | :x: | :heavy_check_mark: | | Close | :heavy_check_mark: | :x: | :heavy_check_mark: |
| Contains | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Contains | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| AdminVerifyAccount | :heavy_check_mark: | :x: | :heavy_check_mark: |
| PruneUsers | :heavy_check_mark: | :x: | :heavy_check_mark: | | PruneUsers | :heavy_check_mark: | :x: | :heavy_check_mark: |
| ApiProperties | :x: | :x: | :x: | | ApiProperties | :x: | :x: | :x: |
### Username Requirements ### Username Requirements
Valid Valid
* lowercase letters * letters
* numbers * numbers
* _ * _
* Length must be atleast 3 and at most 16 characters. * Length must be atleast 3 and at most 16 characters.
### User Management endpoints ### User Management endpoints
| name | added on | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U | | name | last change | purpose | json input | path | HTTP Method | correct status | return type | return value | Jresp | Jreq | A | U |
| :----------- | :------: | --------------------------------------- | --------------------------------------------- | -------------------------- | :---------: | :------------: | :---------: | :----------: | :----------------: | :----------------: | :----------------: | :----------------: | | :----------- | :---------: | --------------------------------------- | --------------------------------------------- | -------------------------- | :---------: | :------------: | :---------: | :----------: | :----------------: | :----------------: | :----------------: | :----------------: |
| AddUser | `v2.3.0` | adding a user with a balance of 0 | {"name":string,"pass":string} | api/v1/user/register | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | | AddUser | `v2.3.0` | adding a user with a balance of 0 | {"name":string,"pass":string} | api/v1/user/register | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: |
| AdminAddUser | `v2.3.0` | adding a user with an arbitrary balance | {"name":string,"amount":uint32,"pass":string} | api/v1/admin/user/register | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | | AdminAddUser | `v2.3.0` | adding a user with an arbitrary balance | {"name":string,"amount":uint32,"pass":string} | api/v1/admin/user/register | `POST` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| DelSelf | `v2.3.0` | deletes a user | `N/A` | api/v1/user/delete | `DELETE` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | | DelSelf | `v2.3.0` | deletes a user | `N/A` | api/v1/user/delete | `DELETE` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| AdminDelUser | `v2.3.0` | deletes a given user `{name}` | {"name":string} | api/v1/admin/user/delete | `DELETE` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | | AdminDelUser | `v2.3.0` | deletes a given user `"name"` | {"name":string} | api/v1/admin/user/delete | `DELETE` | 204 | `N/A` | `N/A` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
### User Management endpoint errors ### User Management endpoint errors
| name | 400 | 401 | 404 | 406 | 409 | | name | 400 | 401 | 404 | 406 | 409 |

View file

@ -49,13 +49,13 @@ public:
static BankResponse GetLogs(const std::string &name) noexcept; static BankResponse GetLogs(const std::string &name) noexcept;
#endif #endif
static BankResponse GetLogsV2(const std::string &name) noexcept; static BankResponse GetLogsV2(const std::string &name) noexcept;
static BankResponse GetLogsRange(const std::string &name, size_t n, size_t m) noexcept;
#endif #endif
static BankResponse SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount) noexcept; static BankResponse SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount) noexcept;
static bool VerifyPassword(const std::string &name, const std::string_view &attempt) noexcept; static bool VerifyPassword(const std::string &name, const std::string_view &attempt) noexcept;
static void ChangePassword(const std::string &name, const std::string &new_pass) noexcept; static void ChangePassword(const std::string &name, const std::string &new_pass) noexcept;
static BankResponse SetBal(const std::string &name, uint32_t amount) noexcept; static BankResponse SetBal(const std::string &name, int64_t amount) noexcept;
static BankResponse ImpactBal(const std::string &name, int64_t amount) noexcept; static BankResponse ImpactBal(const std::string &name, int64_t amount) noexcept;
static bool Contains(const std::string &name) noexcept; static bool Contains(const std::string &name) noexcept;

View file

@ -16,18 +16,20 @@ public:
static void GetLogs(req_args); static void GetLogs(req_args);
#endif #endif
static void GetLogsV2(req_args); static void GetLogsV2(req_args);
static void GetLogsRange(req_args, size_t start, size_t length);
static void SendFunds(req_args); static void SendFunds(req_args);
static void ChangePassword(req_args);
static void VerifyPassword(req_args); static void VerifyPassword(req_args);
static void ChangePassword(req_args); static void AdminGetLogs(req_args, const std::string& name);
static void AdminChangePassword(req_args); static void AdminChangePassword(req_args);
static void AdminVerifyAccount(req_args);
static void SetBal(req_args); static void SetBal(req_args);
static void ImpactBal(req_args); static void ImpactBal(req_args);
static void Help(req_args); static void Help(req_args);
static void Close(req_args); static void Close(req_args);
static void Contains(req_args, const std::string &name); static void Contains(req_args, const std::string &name);
static void AdminVerifyAccount(req_args);
static void PruneUsers(req_args); static void PruneUsers(req_args);
static void ApiProperties(req_args); static void ApiProperties(req_args);
@ -38,36 +40,46 @@ public:
METHOD_LIST_BEGIN METHOD_LIST_BEGIN
METHOD_ADD(api::Help, "/help", Get, Options);
METHOD_ADD(api::ApiProperties, "/properties", Get, Options);
//Usage //Usage
METHOD_ADD(api::GetBal, "/v1/user/balance?name={name}", Get, Options, "JsonFilter<false>"); METHOD_ADD(api::GetBal, "/v1/user/balance?name={name}", Get, Options, "JsonFilter<false>");
#if MAX_LOG_SIZE > 0 #if MAX_LOG_SIZE > 0
#if USE_DEPRECATED_ENDPOINTS #if USE_DEPRECATED_ENDPOINTS
METHOD_ADD(api::GetLogs, "/v1/user/log", Get, Options, "JsonFilter<false>", "UserFilter<true, false>"); METHOD_ADD(api::GetLogs, "/v1/user/log", Get, Options, "JsonFilter<false>", "UserFilter<true, false>");
#endif #endif
METHOD_ADD(api::GetLogsV2, "/v2/user/log", Get, Options, "JsonFilter<false>", "UserFilter<true, false>"); METHOD_ADD(api::GetLogsV2, "/v2/user/log", Get, Options, "JsonFilter<false>", "UserFilter<true, false>");
METHOD_ADD(api::GetLogsRange, "/v1/user/log_range?start={start}&length={length}", Get, Options, "JsonFilter<false>", "UserFilter<true, false>");
METHOD_ADD(api::AdminGetLogs, "/v1/admin/user/log?name={name}", Get, Options, "JsonFilter<false>", "UserFilter<false, true>");
#else #else
#if USE_DEPRECATED_ENDPOINTS #if USE_DEPRECATED_ENDPOINTS
METHOD_ADD(api::GetLogs, "/v1/user/log", Get, Options, "JsonFilter<false>"); METHOD_ADD(api::GetLogs, "/v1/user/log", Get, Options, "JsonFilter<false>");
#endif #endif
METHOD_ADD(api::GetLogsV2, "/v2/user/log", Get, Options, "JsonFilter<false>"); METHOD_ADD(api::GetLogsV2, "/v2/user/log", Get, Options, "JsonFilter<false>");
METHOD_ADD(api::GetLogsRange, "/v1/user/log_range?start={start}&length={length}", Get, Options, "JsonFilter<false>");
METHOD_ADD(api::AdminGetLogs, "/v1/admin/user/log?name={name}", Get, Options, "JsonFilter<false>");
#endif #endif
METHOD_ADD(api::SendFunds, "/v1/user/transfer", Post, Options, "JsonFilter<true>", "UserFilter<true, false>"); //expects ["name"](string) and ["amount"](uint32) METHOD_ADD(api::SendFunds, "/v1/user/transfer", Post, Options, "JsonFilter<true>", "UserFilter<true, false>"); //expects ["name"](string) and ["amount"](uint32)
METHOD_ADD(api::ChangePassword, "/v1/user/change_password", Patch, Options, "JsonFilter<true>", "UserFilter<true, false>"); //expects ["pass"](string)
METHOD_ADD(api::VerifyPassword, "/v1/user/verify_password", Post, Options, "UserFilter<false, false>", "JsonFilter<false>"); METHOD_ADD(api::VerifyPassword, "/v1/user/verify_password", Post, Options, "UserFilter<false, false>", "JsonFilter<false>");
//Meta Usage //Meta Usage
METHOD_ADD(api::ChangePassword, "/v1/user/change_password", Patch, Options, "JsonFilter<true>", "UserFilter<true, false>"); //expects ["pass"](string)
METHOD_ADD(api::AdminChangePassword, "/v1/admin/user/change_password", Patch, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["pass"](string) METHOD_ADD(api::AdminChangePassword, "/v1/admin/user/change_password", Patch, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["pass"](string)
METHOD_ADD(api::AdminVerifyAccount, "/v1/admin/verify_account", Post, Options, "UserFilter<false, true>", "JsonFilter<false>");
METHOD_ADD(api::SetBal, "/v1/admin/set_balance", Patch, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["amount"](uint32) METHOD_ADD(api::SetBal, "/v1/admin/set_balance", Patch, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["amount"](uint32)
METHOD_ADD(api::ImpactBal, "/v1/admin/impact_balance", Post, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["amount"](uint32) METHOD_ADD(api::ImpactBal, "/v1/admin/impact_balance", Post, Options, "JsonFilter<true>", "UserFilter<false, true>"); //expects ["name"](string) and ["amount"](uint32)
//System Usage //System Usage
METHOD_ADD(api::Help, "/help", Get, Options);
METHOD_ADD(api::Close, "/v1/admin/shutdown", Post, Options, "UserFilter<false, true>", "JsonFilter<false>"); METHOD_ADD(api::Close, "/v1/admin/shutdown", Post, Options, "UserFilter<false, true>", "JsonFilter<false>");
METHOD_ADD(api::Contains, "/v1/user/exists?name={name}", Get, Options, "JsonFilter<false>"); METHOD_ADD(api::Contains, "/v1/user/exists?name={name}", Get, Options, "JsonFilter<false>");
METHOD_ADD(api::AdminVerifyAccount, "/v1/admin/verify_account", Post, Options, "UserFilter<false, true>", "JsonFilter<false>");
METHOD_ADD(api::PruneUsers, "/v1/admin/prune_users", Post, "UserFilter<false, true>", "JsonFilter<true>"); //expects ["time"](int64) and ["amount"](uint32) METHOD_ADD(api::PruneUsers, "/v1/admin/prune_users", Post, "UserFilter<false, true>", "JsonFilter<true>"); //expects ["time"](int64) and ["amount"](uint32)
METHOD_ADD(api::ApiProperties, "/properties", Get, Options);
//User Managment //User Managment
METHOD_ADD(api::AddUser, "/v1/user/register", Post, Options); //expects ["name"](string) ["pass"](string) METHOD_ADD(api::AddUser, "/v1/user/register", Post, Options); //expects ["name"](string) ["pass"](string)

View file

@ -26,5 +26,6 @@ public:
std::string GetLogs(const std::string& name) noexcept; std::string GetLogs(const std::string& name) noexcept;
#endif #endif
std::string GetLogsV2() noexcept; std::string GetLogsV2() noexcept;
std::string GetLogsRange(size_t n, size_t m) noexcept;
void AddTrans(const std::string &counterparty_str, bool receiving, uint32_t amount, time_t time) noexcept; void AddTrans(const std::string &counterparty_str, bool receiving, uint32_t amount, time_t time) noexcept;
}; };

View file

@ -34,28 +34,29 @@ int main(int argc, char **argv)
uint8_t temp[16]{16, 0, 0, 0, 4}; uint8_t temp[16]{16, 0, 0, 0, 4};
users_save.write((char *)temp, 16); users_save.write((char *)temp, 16);
users_save.close(); users_save.close();
std::cout << "User save file generated\nUsage: sudo ./bank <admin account name> <saving frequency in minutes> [daemon flag {default: false}]\n"; std::cout << "User save file generated\n" << "Usage: sudo ./bank <admin account> <saving frequency in minutes> [daemon flag {default: false}]\n";
return 0;
} }
else else
{ {
std::cerr << "File cannot be created (may already exist)\n"; std::cerr << "File cannot be created (may already exist)\n";
return -1;
} }
return 0;
} }
if (argc < 3) if (argc < 3)
{ {
std::cerr << "Usage: sudo ./bank <admin account> <saving frequency in minutes> [daemon flag {default: false}]\n"; std::cerr << "Usage: sudo ./bank <admin account> <saving frequency in minutes> [daemon flag {default: false}]\n";
return 0; return -1;
} }
if (geteuid() != 0) if (geteuid() != 0)
{ {
std::cerr << "ERROR: CCash MUST be ran as root\n"; std::cerr << "ERROR: CCash MUST be ran as root\n";
return 0; return -1;
} }
const unsigned long saving_freq = std::stoul(std::string(argv[2])); const unsigned long saving_freq = std::stoul(std::string(argv[2]));
std::cout std::cout
<< "\nAPI : v2.5.1" << "\nAPI : v2.6.1\n"
<< "\n\nAVX : " << (__builtin_cpu_supports("avx") ? "enabled" : "disabled") << "\nAVX : " << (__builtin_cpu_supports("avx") ? "enabled" : "disabled")
<< "\nAVX 2 : " << (__builtin_cpu_supports("avx2") ? "enabled" : "disabled") << "\nAVX 2 : " << (__builtin_cpu_supports("avx2") ? "enabled" : "disabled")
<< "\nSSE 2 : " << (__builtin_cpu_supports("sse2") ? "enabled" : "disabled") << "\nSSE 2 : " << (__builtin_cpu_supports("sse2") ? "enabled" : "disabled")
<< "\nSSE 3 : " << (__builtin_cpu_supports("sse3") ? "enabled" : "disabled") << "\nSSE 3 : " << (__builtin_cpu_supports("sse3") ? "enabled" : "disabled")
@ -96,14 +97,18 @@ int main(int argc, char **argv)
while (1) while (1)
{ {
std::this_thread::sleep_for(std::chrono::minutes(saving_freq)); std::this_thread::sleep_for(std::chrono::minutes(saving_freq));
std::cout << "Saving " << std::time(0) << "...\n" std::cout << "Saving " << std::time(0) << "...\n" << Bank::Save();
<< Bank::Save();
} }
}) })
.detach(); .detach();
} }
if (argc == 4 && !strcmp(argv[3], "true")) { app().enableRunAsDaemon(); } if (argc == 4 && !strcmp(argv[3], "true")) { app().enableRunAsDaemon(); }
else if (argc == 4 && strcmp(argv[3], "false"))
{
std::cerr << "daemon flag must be \"true\" or \"false\"\n";
return -1;
}
} //destroying setup variables } //destroying setup variables
app() app()

View file

@ -36,7 +36,7 @@ inline bool ValidUsername(const std::string &name) noexcept
} }
for (char c : name) for (char c : name)
{ {
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')) if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'))
{ {
return false; return false;
} }
@ -116,6 +116,28 @@ BankResponse Bank::GetLogsV2(const std::string &name) noexcept
} }
} }
BankResponse Bank::GetLogsRange(const std::string &name, size_t start, size_t length) noexcept
{
BankResponse res;
if (start >= MAX_LOG_SIZE)
{
return {k400BadRequest, "\"Invalid {start} index\""};
}
if (!length)
{
return {k400BadRequest, "\"Invalid {length}\""};
}
if (!Bank::users.modify_if(name, [&name, &res, start, length](User &u) { res = {k200OK, u.log.GetLogsRange(start, length)}; }))
{
return {k404NotFound, "\"User not found\""};
}
else
{
return res;
}
}
#endif #endif
BankResponse Bank::SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount) noexcept BankResponse Bank::SendFunds(const std::string &a_name, const std::string &b_name, uint32_t amount) noexcept
@ -179,15 +201,20 @@ bool Bank::VerifyPassword(const std::string &name, const std::string_view &attem
Bank::users.if_contains(name, [&res, &attempt](const User &u) { res = (u.password == xxHashStringGen{}(attempt)); }); Bank::users.if_contains(name, [&res, &attempt](const User &u) { res = (u.password == xxHashStringGen{}(attempt)); });
return res; return res;
} }
void Bank::ChangePassword(const std::string &name, const std::string &new_pass) noexcept void Bank::ChangePassword(const std::string &name, const std::string &new_pass) noexcept
{ {
SET_CHANGES_ON; SET_CHANGES_ON;
Bank::users.modify_if(name, [&new_pass](User &u) { u.password = xxHashStringGen{}(new_pass); }); Bank::users.modify_if(name, [&new_pass](User &u) { u.password = xxHashStringGen{}(new_pass); });
} }
BankResponse Bank::SetBal(const std::string &name, uint32_t amount) noexcept BankResponse Bank::SetBal(const std::string &name, int64_t amount) noexcept
{ {
if (ValidUsername(name) && Bank::users.modify_if(name, [amount](User &u) { u.balance = amount; })) if (ValidUsername(name) && Bank::users.modify_if(name, [&amount](User &u) {
amount -= u.balance;
u.balance += amount;
#if MAX_LOG_SIZE > 0
u.log.AddTrans("Ω", (amount > 0), std::abs(amount), time(NULL));
#endif
}))
{ {
SET_CHANGES_ON; SET_CHANGES_ON;
return {k204NoContent, std::nullopt}; //returns new balance return {k204NoContent, std::nullopt}; //returns new balance
@ -204,7 +231,13 @@ BankResponse Bank::ImpactBal(const std::string &name, int64_t amount) noexcept
return {k400BadRequest, "\"Amount cannot be 0\""}; return {k400BadRequest, "\"Amount cannot be 0\""};
} }
uint32_t bal; uint32_t bal;
if (ValidUsername(name) && Bank::users.modify_if(name, [&bal, amount](User &u) { bal = (u.balance < (amount * -1) ? u.balance = 0 : u.balance += amount); })) if (ValidUsername(name) && Bank::users.modify_if(name, [&bal, &amount](User &u) {
if (u.balance < (amount * -1)) { amount = -int64_t(u.balance); };
bal = u.balance += amount;
#if MAX_LOG_SIZE > 0
u.log.AddTrans("Ω", (amount > 0), std::abs(amount), time(NULL));
#endif
}))
{ {
SET_CHANGES_ON; SET_CHANGES_ON;
return {k200OK, std::to_string(bal)}; //may return new balance return {k200OK, std::to_string(bal)}; //may return new balance

View file

@ -54,6 +54,30 @@ void api::GetLogsV2(req_args)
#endif #endif
} }
void api::GetLogsRange(req_args, size_t start, size_t length)
{
#if MAX_LOG_SIZE > 0
RESPONSE_PARSE(Bank::GetLogsRange(NAME_PARAM, start, length));
#else
auto resp = HttpResponse::newCustomHttpResponse(BankResponse{k404NotFound, "\"Logs are Disabled\""});
CORS;
CACHE_FOREVER;
callback(resp);
#endif
}
void api::AdminGetLogs(req_args, const std::string& name)
{
#if MAX_LOG_SIZE > 0
RESPONSE_PARSE(Bank::GetLogsV2(name));
#else
auto resp = HttpResponse::newCustomHttpResponse(BankResponse{k404NotFound, "\"Logs are Disabled\""});
CORS;
CACHE_FOREVER;
callback(resp);
#endif
}
void api::SendFunds(req_args) void api::SendFunds(req_args)
{ {
SIMD_JSON_GEN; SIMD_JSON_GEN;

View file

@ -9,7 +9,7 @@ void Log::AddTrans(const std::string &counterparty_str, bool receiving, uint32_t
if (data.size() == MAX_LOG_SIZE) if (data.size() == MAX_LOG_SIZE)
{ {
data.pop_back(); data.pop_front();
} }
data.emplace_back(counterparty_str, receiving, amount, time); data.emplace_back(counterparty_str, receiving, amount, time);
} }
@ -59,7 +59,7 @@ std::string Log::GetLogsV2() noexcept
log_snapshot_v2.reserve(predicted_size); log_snapshot_v2.reserve(predicted_size);
} }
log_snapshot_v2 = '['; //1 log_snapshot_v2 = '['; //1
for (size_t i = 0; i < data.size(); ++i) for (size_t i = data.size(); i --> 0;)
{ {
log_snapshot_v2 += "{\"counterparty\":\""; //17 log_snapshot_v2 += "{\"counterparty\":\""; //17
log_snapshot_v2 += data[i].counterparty; //max_name_size? log_snapshot_v2 += data[i].counterparty; //max_name_size?
@ -76,3 +76,93 @@ std::string Log::GetLogsV2() noexcept
return log_snapshot_v2; return log_snapshot_v2;
} }
std::string Log::GetLogsRange(size_t start, size_t length) noexcept
{
if (start >= data.size()) { return "[]"; }
if (start == 0 && length == MAX_LOG_SIZE) { return log_snapshot_v2; }
if (log_flag_v2.GetChangeState() && data.size()) { GetLogsV2(); }
size_t log_index_n, i;
if (start < (0.5 * MAX_LOG_SIZE))
{
// std::cout << "a\n";
i = 0;
log_index_n = 0;
while(i < log_snapshot_v2.size())
{
if (log_index_n == start)
{
log_index_n = i;
break;
}
i += (41 + min_name_size);
while (log_snapshot_v2[i] != ',') { ++i; }
++log_index_n;
}
}
else
{
// std::cout << "b\n";
i = log_snapshot_v2.size();
log_index_n = data.size();
while(i --> 0)
{
if (log_index_n == start)
{
log_index_n = i + 1;
break;
}
i -= (41 + min_name_size);
while (log_snapshot_v2[i] != ',') { --i; }
--log_index_n;
}
}
size_t log_index_m = std::string::npos;
if ((start + length) < data.size())
{
if (length < (0.5 * MAX_LOG_SIZE))
{
// std::cout << "c\n";
log_index_m = 0;
while(i < log_snapshot_v2.size())
{
if (log_index_m == length)
{
log_index_m = i + 1;
break;
}
i += (41 + min_name_size);
while (log_snapshot_v2[i] != ',') { ++i; }
++log_index_m;
}
}
else
{
// std::cout << "d\n";
i = log_snapshot_v2.size();
log_index_m = data.size();
while(i --> 0)
{
if (log_index_m == length)
{
log_index_m = i + 1;
break;
}
i -= (41 + min_name_size);
while (log_snapshot_v2[i] != ',') { --i; }
--log_index_m;
}
}
log_index_m -= log_index_n;
}
std::string res(log_snapshot_v2.substr(log_index_n, log_index_m));
res[0] = '[';
res[res.size() - 1] = ']';
// std::cout << res << '\n';
return res;
}

View file

@ -8,7 +8,7 @@ inline bool ValidUsername(const std::string &name) noexcept
} }
for (char c : name) for (char c : name)
{ {
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')) if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'))
{ {
return false; return false;
} }