API for the Bazaar Realm Skyrim mod
Go to file
Tyler Hallada 08c8dcb07b Working create_transaction endpoint
Creates the transaction record and updates the merchandise quantity in one db transaction.

Managed to do the merchandise update in one UPDATE query, but the error that's thrown when an item to buy is not found is pretty confusing, so I convert it to a 404.

I also added some DB indexes.
2020-10-31 20:34:20 -04:00
.cargo Move filters into main.rs for SPEED 2020-10-20 21:50:01 -04:00
src Working create_transaction endpoint 2020-10-31 20:34:20 -04:00
test_data Working create_transaction endpoint 2020-10-31 20:34:20 -04:00
.gitignore Update setup instructions 2020-07-23 00:12:56 -04:00
Cargo.lock Simplify db migrations 2020-10-28 22:20:39 -04:00
Cargo.toml Simplify db migrations 2020-10-28 22:20:39 -04:00
devserver.bat Update README with Windows setup and db seeding 2020-10-11 03:03:09 -04:00
devserver.sh Update setup instructions 2020-07-23 00:12:56 -04:00
LICENSE Rename the project and add more README docs 2020-10-12 20:54:34 -04:00
README.md Handle update merchandise quantity to 0 and < 0 2020-10-28 23:40:38 -04:00

BazaarRealmAPI

The API for the Bazaar Realm Skyrim mod which is responsible for storing and serving data related to the mod to all users.

Right now, the types of data the API stores and the endpoints to access them are (all prefixed under /v1, the API version):

  • /owners: Every player character that has registered with this API server. Contains their unique api key. Owners own shops.
  • /shops: Metadata about each shop including name, description, and who owns it.
  • /interior_ref_lists: Lists of in-game ObjectReferences that are in the interior of individual shops. When a user visits a shop, these references are loaded into the cell.
  • /merchandise_lists: Lists of in-game Forms that are in the merchant chest of individual shops. When a user visits a shop, these forms are loaded onto the shop's shelves and are purchasable.

Bazaar Realm was designed to allow users to change the API they are using the mod under, if they wish. The API can run on a small server with minimal resources, which should be suitable for a small group of friends to share shops with each other.

It uses the warp web server framework and sqlx for database queries to a PostgreSQL database.

Related projects:

Development Setup

  1. Install and run postgres.
  2. Create postgres user and database (and add uuid extension while you're there ):
createuser bazaarrealm
createdb bazaarrealm
sudo -u postgres -i psql
postgres=# ALTER DATABASE bazaarrealm OWNER TO bazaarrealm;
\password bazaarrealm
postgres=# CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

# Or, on Windows in PowerShell:

& 'C:\Program Files\PostgreSQL\13\bin\createuser.exe' -U postgres bazaarrealm
& 'C:\Program Files\PostgreSQL\13\bin\createdb.exe' -U postgres bazaarrealm
& 'C:\Program Files\PostgreSQL\13\bin\psql.exe' -U postgres
postgres=# ALTER DATABASE bazaarrealm OWNER TO bazaarrealm;
\password bazaarrealm
postgres=# CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  1. Save password somewhere safe and then and add a .env file to the project directory with the contents:
DATABASE_URL=postgresql://bazaarrealm:<password>@localhost/bazaarrealm
RUST_LOG="bazaar_realm_api=debug"
HOST="http://localhost:3030"
  1. Create a new file at src/db/refinery.toml with the contents:
[main]
db_type = "Postgres"
db_host = "localhost"
db_port = "5432"
db_user = "bazaarrealm"
db_pass = "<database-password-here>"
db_name = "bazaarrealm"
  1. Install refinery_cli with cargo install refinery_cli and run refinery migrate -c ./src/db/refinery.toml files -p ./src/db/migrations/ which will run the database migrations.
  2. Run ./devserver.sh to run the dev server (by default it listens at 127.0.0.1:3030).

Testing Data

Using httpie you can use the json files in test_data/ to seed the database with data.

The POST endpoints require an API key. You can just generate a random uuidv4, just make sure to use the same one in all future requests.

http POST "http://localhost:3030/v1/owners" @test_data\owner.json api-key:"13e2f39c-033f-442f-b42a-7ad640d2e439"
http POST "http://localhost:3030/v1/shops" @test_data\shop.json api-key:"13e2f39c-033f-442f-b42a-7ad640d2e439"
http PATCH "http://localhost:3030/v1/shops/1/interior_ref_list" @test_data\interior_ref_list.json api-key:"13e2f39c-033f-442f-b42a-7ad640d2e439"
http PATCH "http://localhost:3030/v1/shops/1/merchandise_list" @test_data\merchandise_list.json api-key:"13e2f39c-033f-442f-b42a-7ad640d2e439"
# Then, you can test the GET endpoints
http GET "http://localhost:3030/v1/owners"
http GET "http://localhost:3030/v1/shops"
http GET "http://localhost:3030/v1/interior_ref_lists"
http GET "http://localhost:3030/v1/merchandise_lists"

Authentication

I don't want to require users of Bazaar Realm to have to remember a password, so I forgoed the typical username and password authentication in favor of a unique UUID identifier instead. This is the api key that the BazaarRealmClient generates when the user first starts the mod in a game. The api key is stored in the save game files for the player character and is required to be sent with any API request that modifies data.

Yes, it's not most secure solution, but I'm not convinced security is a huge concern here. As long as users don't share their API key or the save game files that contain it, their data should be secure.

Todo

  • Add update endpoints.
  • Add endpoints for the other models.
  • Make self-contained docker container that can run the app without any setup.
  • Add rate-limiting per IP address. The tower crate has a service that might be useful for this.