From 188cca8c39dbcf0218592126b3189e860a417ffd Mon Sep 17 00:00:00 2001 From: Dan Cojocaru Date: Tue, 30 Nov 2021 14:13:57 +0200 Subject: [PATCH] Added initial server database work --- server/.dockerignore | 2 ++ server/.gitignore | 2 ++ server/.vscode/extensions.json | 4 +-- server/.vscode/settings.json | 3 ++ server/Dockerfile | 13 ++++++++ server/Pipfile | 1 + server/Pipfile.lock | 18 +++++++++- server/db.py | 36 ++++++++++++++++++++ server/docker-compose.yml | 9 +++++ server/init.sql | 61 ++++++++++++++++++++++++++++++++++ server/server.py | 10 ++++++ 11 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 server/.dockerignore create mode 100644 server/.gitignore create mode 100644 server/.vscode/settings.json create mode 100644 server/Dockerfile create mode 100644 server/db.py create mode 100644 server/docker-compose.yml create mode 100644 server/init.sql create mode 100644 server/server.py diff --git a/server/.dockerignore b/server/.dockerignore new file mode 100644 index 0000000..54e6782 --- /dev/null +++ b/server/.dockerignore @@ -0,0 +1,2 @@ +__pycache__/ +data/ \ No newline at end of file diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..54e6782 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +data/ \ No newline at end of file diff --git a/server/.vscode/extensions.json b/server/.vscode/extensions.json index f2e0e83..73cca8d 100644 --- a/server/.vscode/extensions.json +++ b/server/.vscode/extensions.json @@ -1,5 +1,3 @@ { - "recommendations": [ - "ms-python.python" - ] + "recommendations": [] } \ No newline at end of file diff --git a/server/.vscode/settings.json b/server/.vscode/settings.json new file mode 100644 index 0000000..c3bfabb --- /dev/null +++ b/server/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "/home/kbruen/.local/share/virtualenvs/server-4otskhbj/bin/python" +} \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..a3a4096 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.10-slim + +RUN pip3 install pipenv + +WORKDIR /app + +COPY Pipfile Pipfile.lock ./ +RUN pipenv install + +COPY . . + +EXPOSE 5000 +CMD [ "pipenv", "run", "gunicorn", "-b", "0.0.0.0:5000", "server:app" ] \ No newline at end of file diff --git a/server/Pipfile b/server/Pipfile index 0f41118..c3a312f 100644 --- a/server/Pipfile +++ b/server/Pipfile @@ -5,6 +5,7 @@ name = "pypi" [packages] flask = "*" +gunicorn = "*" [dev-packages] diff --git a/server/Pipfile.lock b/server/Pipfile.lock index dc6f3cf..593ee26 100644 --- a/server/Pipfile.lock +++ b/server/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "295fa60b4ad3b19ec29744ec2dfafba79ad5ee9a0b9ff095ac626e3d3981f117" + "sha256": "8886b8a6c0d31987ddea5b9e25bd02f7891650c967351486fd3cf0fd4d16271e" }, "pipfile-spec": 6, "requires": { @@ -32,6 +32,14 @@ "index": "pypi", "version": "==2.0.2" }, + "gunicorn": { + "hashes": [ + "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e", + "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8" + ], + "index": "pypi", + "version": "==20.1.0" + }, "itsdangerous": { "hashes": [ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c", @@ -123,6 +131,14 @@ "markers": "python_version >= '3.6'", "version": "==2.0.1" }, + "setuptools": { + "hashes": [ + "sha256:b4c634615a0cf5b02cf83c7bedffc8da0ca439f00e79452699454da6fbd4153d", + "sha256:feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060" + ], + "markers": "python_version >= '3.6'", + "version": "==59.4.0" + }, "werkzeug": { "hashes": [ "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f", diff --git a/server/db.py b/server/db.py new file mode 100644 index 0000000..aaa55de --- /dev/null +++ b/server/db.py @@ -0,0 +1,36 @@ +import sqlite3 + +from flask import current_app, g + +DB_FILE = './data/db.sqlite' + +def get(): + if 'db' not in g: + g.db = sqlite3.connect( + DB_FILE, + detect_types=sqlite3.PARSE_DECLTYPES, + ) + g.db.row_factory = sqlite3.Row + + return g.db + +def close(e=None): + db = g.pop('db', None) + + if db: + db.close() + +def init(): + db = get() + + with current_app.open_resource('init.sql') as f: + db.executescript(f.read().decode('utf8')) + db.commit() + +def init_app(app): + app.teardown_appcontext(close) + + import os.path + if not os.path.exists(DB_FILE): + with app.app_context(): + init() diff --git a/server/docker-compose.yml b/server/docker-compose.yml new file mode 100644 index 0000000..87ef756 --- /dev/null +++ b/server/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3.9' +services: + web: + build: . + image: foxbank-server + ports: + - ${PORT:-5000}:5000 + volumes: + - ./data:/app/data diff --git a/server/init.sql b/server/init.sql new file mode 100644 index 0000000..c241a9d --- /dev/null +++ b/server/init.sql @@ -0,0 +1,61 @@ +drop table if exists users; +drop table if exists accounts; +drop table if exists users_accounts; +drop table if exists transactions; +drop table if exists accounts_transactions; +drop table if exists notifications; +drop table if exists users_notifications; + +create table users ( + id integer primary key autoincrement, + username text unique not null, + email text unique not null, + otp text not null, + fullname text not null +); + +create table accounts ( + id integer primary key autoincrement, + iban text unique not null, -- RO16 FOXB 0000 0000 0000 0000 + currency text not null, -- EUR, RON, USD, ? + account_type text not null, -- checking, savings, ? + custom_name text -- 'Car Savings'; name set by user +); + +create table users_accounts ( + user_id integer not null, -- one user can have multiple accounts + account_id integer UNIQUE not null, -- one account can only have one user + foreign key (user_id) references users (id), + foreign key (account_id) references accounts (id) +); + +create table transactions ( + id integer primary key autoincrement, + datetime text not null, + other_party text not null, -- JSON data describing sender/recipient/etc + -- depending on transaction type + status text not null, -- processed, failed, reverted, pending, etc + type text not null, -- send_transfer, receive_transfer, card_payment, fee, ... + extra text -- depending on type, JSON data describing extra info +); + +create table accounts_transactions ( + account_id integer not null, + transaction_id integer UNIQUE not null, + foreign key (account_id) references accounts (id), + foreign key (transaction_id) references transactions (id) +); + +create table notifications ( + id integer primary key autoincrement, + body text not null, + datetime text not null, + read integer not null +); + +create table users_notifications ( + user_id integer not null, + notification_id integer UNIQUE not null, + foreign key (user_id) references users (id), + foreign key (notification_id) references notifications (id) +); \ No newline at end of file diff --git a/server/server.py b/server/server.py new file mode 100644 index 0000000..e03bd00 --- /dev/null +++ b/server/server.py @@ -0,0 +1,10 @@ +from flask import Flask + +import db + +app = Flask(__name__) +db.init_app(app) + +@app.get('/') +def root(): + return 'Hello from FoxBank!'