Skip to content

Commit

Permalink
API: improve Dockerfile, add migrations, add command to create access…
Browse files Browse the repository at this point in the history
… keys
  • Loading branch information
Giacomo Licari committed Feb 28, 2024
1 parent 488116b commit f2972e6
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 24 deletions.
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,38 @@

A simple python implementation of an EVM compatible faucet.

## API
## Python API

### Requirements

Python +3.x, NodeJS v18.x
Python +3.x

### Python API
### Installation

```
cd api
python3 -m venv .venv
. .venv/bin/activate
pip3 install -r requirements.txt
python3 -m flask --app api run --port 8000
pip3 install -r requirements-dev.txt
```

#### Run application
### Run application

Check .env.example for reference.

```
cd api
python3 -m flask --app api run --port 8000
```


#### Run tests
### Run tests

```
cd api
python3 -m pytest -s
```

#### Run Flake8 and isort
### Run Flake8 and isort

```
cd api
Expand All @@ -43,7 +42,13 @@ isort **/*.py --atomic
python3 -m flake8
```

### ReactJS Frontend
## ReactJS Frontend

### Requirements

NodeJS v18.x

### Installation

```
nvm use
Expand All @@ -52,7 +57,7 @@ cd app
yarn
```

#### Run application
### Run application

```
cd app
Expand Down
1 change: 1 addition & 0 deletions api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ FAUCET_RPC_URL=https://rpc.chiadochain.net
FAUCET_CHAIN_ID=10200
FAUCET_ENABLED_TOKENS="[{\"address\": \"0x19C653Da7c37c66208fbfbE8908A5051B57b4C70\", \"name\":\"GNO\", \"maximumAmount\": 0.5}]"
# FAUCET_ENABLED_TOKENS=
FAUCET_DATABASE_URI=sqlite:///:memory
CAPTCHA_VERIFY_ENDPOINT=https://api.hcaptcha.com/siteverify
CAPTCHA_SECRET_KEY=0x0000000000000000000000000000000000000000
2 changes: 1 addition & 1 deletion api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ RUN pip install --no-cache-dir -r /tmp/requirements.txt
COPY . /api
WORKDIR /api

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "api:create_app()"]
ENTRYPOINT ["/sbin/tini", "--"]
5 changes: 4 additions & 1 deletion api/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from flask_cors import CORS
from flask_migrate import Migrate

from .manage import create_access_keys_cmd
from .routes import apiv1
from .services import Cache, Web3Singleton
from .services.database import db
Expand Down Expand Up @@ -37,12 +38,14 @@ def create_app():
app.config['FAUCET_CACHE'] = Cache(app.config['FAUCET_RATE_LIMIT_TIME_LIMIT_SECONDS'])
# Initialize API Routes
app.register_blueprint(apiv1, url_prefix="/api/v1")
# Add cli commands
app.cli.add_command(create_access_keys_cmd)

with app.app_context():
db.init_app(app)
Migrate(app, db)

# Initialize Web3 class
# Initialize Web3 class for latter usage
w3 = Web3Singleton(app.config['FAUCET_RPC_URL'], app.config['FAUCET_PRIVATE_KEY'])

setup_cors(app)
Expand Down
19 changes: 19 additions & 0 deletions api/api/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import logging

import click
from flask.cli import with_appcontext

from .services.database import AccessKey
from .utils import generate_access_key


@click.command(name='create_access_keys')
@with_appcontext
def create_access_keys_cmd():
access_key_id, secret_access_key = generate_access_key()
access_key = AccessKey()
access_key.access_key_id = access_key_id
access_key.secret_access_key = secret_access_key
access_key.save()
logging.info(f'Access Key ID : ${access_key_id}')
logging.info(f'Secret access key: ${secret_access_key}')
10 changes: 6 additions & 4 deletions api/api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ def _ask(request_data, validate_captcha):

@apiv1.route("/ask", methods=["POST"])
def ask():
return _ask(request.get_json(), validate_captcha=True)
data, status_code = _ask(request.get_json(), validate_captcha=True)
return data, status_code


@apiv1.route("/cli/ask", methods=["POST"])
def cli_ask():
access_key_id = request.headers.get('FAUCET_ACCESS_KEY_ID', None)
secret_access_key = request.headers.get('FAUCET_SECRET_ACCESS_KEY', None)
access_key_id = request.headers.get('X-faucet-access-key-id', None)
secret_access_key = request.headers.get('X-faucet-secret-access-key', None)

validation_errors = []

Expand All @@ -127,4 +128,5 @@ def cli_ask():
validation_errors.append('Access denied')
return jsonify(errors=validation_errors), 403

return _ask(request.get_json(), validate_captcha=False)
data, status_code = _ask(request.get_json(), validate_captcha=False)
return data, status_code
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -x
# DB MIGRATIONS:
FLASK_APP=api FAUCET_DATABASE_URI=sqlite:///:memory python3 -m flask db init # only the first time we initialize the DB
FLASK_APP=api FAUCET_DATABASE_URI=sqlite:///:memory python3 -m flask db migrate
# Reflect migrations onto the database:
# Reflect migrations into the database:
# FLASK_APP=api python3 -m flask db upgrade

# Valid SQLite URL forms are:
Expand Down
10 changes: 10 additions & 0 deletions api/scripts/production_run_api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

set -euo pipefail


echo "==> $(date +%H:%M:%S) ==> Migrating DB models... "
FLASK_APP=api python -m flask db upgrade

echo "==> $(date +%H:%M:%S) ==> Running Gunicorn... "
exec gunicorn --bind 0.0.0.0:8000 "api:create_app()"
1 change: 0 additions & 1 deletion api/scripts/run.sh

This file was deleted.

4 changes: 2 additions & 2 deletions api/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ class TestCliAPI(BaseTest):
def test_ask_route_parameters(self, client):
access_key_id, secret_access_key = generate_access_key()
http_headers = {
'FAUCET_ACCESS_KEY_ID': access_key_id,
'FAUCET_SECRET_ACCESS_KEY': secret_access_key
'X-faucet-access-key-id': access_key_id,
'X-faucet-secret-access-key': secret_access_key
}

response = client.post(api_prefix + '/cli/ask', json={})
Expand Down
2 changes: 0 additions & 2 deletions api/tests/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

class TestDatabase(BaseTest):

# db.create_all() # Create database tables for our data models

def test_models(self, client):
access_key_id, secret_access_key = generate_access_key()
assert len(access_key_id) == 16
Expand Down

0 comments on commit f2972e6

Please sign in to comment.