BonelessPi / lower-wismer-ordering-server

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

This is a webserver that hosts the system that the app will post orders to and the queues will read from

Requirements overview

You will need...

  • A recent version of Python 3 installed
  • Docker and Docker compose installed
  • A processor that can handle running the MongoDB docker container or a Mongo Atlas database
  • An HTTPS ready certificate. If running on linux, the script will autogenerate a self-signed cert

Virtual environment

Using a virtual environment is not required, but it slightly helps with IDE hints

  • If you wish to use a virtual environment for development, run the following command python -m venv python-venv.
  • Then activate the virtual environment. On Windows, the command is python-venv\Scripts\activate. If you get an error when using Powershell about "running scripts is disabled", run cmd first then retry the previous command.
  • Then, install the dependencies with pip install -r requirements.txt.
  • Now select the virtual environment as the interpreter for your IDE. For VSCode, you can select the python interpreter in the bottom right corner when on a python file.

Note that there is a funny issue where the VSCode extension for Python virtual environments seems to cache the .env file and load those into the environment for any terminals. As a result, docker-compose will read those values first even if they are stale. To fix this, close and relaunch VSCode and have it relaunch the terminal; that's what fixed it for me finally. Restarting the extension might work but I'm not entirely sure. This might help: https://code.visualstudio.com/docs/python/environments.

Starting the server

Make sure python and docker are installed. Run the command python run.py. If there is no .env file, it will create one. You can also force recreation by passing the --new flag. To connect to an Altas cloud backend, use the --atlas flag. Then, the script will run the docker compose file. To pause the server without deleting the database, run docker compose stop. To stop and delete the database run python reset.py (this will also delete the docker image for the webserver).

The server now runs with HTTPS. Name your keyfile and certfile "lwo.key" and "lwo.crt" respectively. If one doesn't exist, run.py will attempt to create one (the --new flag doesn't attempt to overwrite any existing key or cert). This will fail on windows, so if you are on windows make sure to make them manually. The autogenerated certificate is self-signed, so browsers will be upset. In production, this issue should be dealt with by using a CA-signed certificate.

Note: Docker does not seem to like running the starting command over an SSH connection. From what I can tell, it has some credential problem when attempting to pull the python image in the build stage for the webserver image.

General developer notes

To test the endpoints of the server, you should use the Swagger API. It is autogenerated by the fastapi framework and is very useful. Goto localhost:8000/docs to see it.

If weird things are happening after changing the .env file, try restarting your IDE. See the note in the Virtual environment section

I tried using the HTTPS redirect middleware but it didn't work. This is a problem for the future.

File purposes

  • main.py tells the database client to start and aggregates the endpoints from the routers
  • The routers folder holds files that contain the HTTP endpoints
  • init.py files are to make python happy
  • crud.py file contains functions that modify the database
  • database.py contains functions relating to connections to the database
  • dependencies.py contains functions that are used by endpoints to assert levels of permissions
  • exceptions.py contains user-defined exception types to make control flow easier (hopefully)
  • schemas.py contains the structure of requests and reponses that the server deals with
  • security.py contains security related functions

Debugging notes

  • If the server returns HTTP 500, the python code likely has a bug. See the logs from the docker container for info.
  • If the server returns HTTP 422, the python function handling that endpoint rejected your input. Look at your request, the type annotations of the function, and the schema objects.

Notes on modifying the database schema

Technically, MongoDB (and most NoSQL engines) are schema-less. However, we are using validators with mongo to essentially force a particular schema for consistency. If you wish to modify the schema, make sure to modify the validators, the example documents (also located inside the init.js file), the schema object in the schema.py file, and all functions that use that schema object.

I wish we could write a script to generate the schema.py file from the validators, but this is likely impossible since some attributes should not be included in certain schemas (like how orders are not allowed to change the dateOrdered field in update requests, or the hashed password field for users should NEVER be sent to the frontend) and it would be hard to make a script to do it correctly.

TODO

Research, consider, or implement the following:

  • /prevOrder endpoint?
  • menuitem options advanced config, EX: quantities, defaults??
  • CSRF protection??
  • injection attack protection?
  • XSS protection??
  • SSRF protection??
  • CORS middleware?
  • HTTP redirect middleware?
  • test if spaces and special chars break run.py or docker
  • test special characters in usernames, passwords, itemnames, menunames, kitchennames
  • add checks on updating roles
  • add limit to blocking sleep test endpoint?
  • write docstrings for all handlers
  • specify hint on every crud/database call
  • switch to RSA??
  • TODOs listed in files
  • block bruteforce password attempts
  • consider using menuitem_id when placing orders?
  • ensure that "none" alg JWTs fail auth
  • have docker compose create a superadmin on init launch?
  • Consider modifying the changepassword endpoint? (move newpassword to body, ensure that it can handle unicode/quotes/spaces/etc, add oldpassword field)

About


Languages

Language:Python 79.7%Language:JavaScript 19.4%Language:Dockerfile 0.8%