From 13415fc313cd190ac8ed78b9a374e6e8867d7ae3 Mon Sep 17 00:00:00 2001 From: Damian Borowiecki Date: Mon, 28 Aug 2023 00:03:32 +0200 Subject: [PATCH] Added example Application --- examples/deepDiveDemo/Dockerfile | 23 ++++++++ examples/deepDiveDemo/docker-compose.yml | 17 ++++++ examples/deepDiveDemo/flask_app/app.py | 55 +++++++++++++++++++ .../flask_app/static/css/main.css | 1 + .../deepDiveDemo/flask_app/static/js/main.js | 1 + .../flask_app/templates/index.html | 14 +++++ .../deepDiveDemo/flask_app/utils/__init__.py | 2 + .../utils/informationMediatorAuth.py | 10 ++++ .../flask_app/utils/jsonEncoder.py | 8 +++ examples/deepDiveDemo/requirements.txt | 3 + 10 files changed, 134 insertions(+) create mode 100644 examples/deepDiveDemo/Dockerfile create mode 100644 examples/deepDiveDemo/docker-compose.yml create mode 100644 examples/deepDiveDemo/flask_app/app.py create mode 100644 examples/deepDiveDemo/flask_app/static/css/main.css create mode 100644 examples/deepDiveDemo/flask_app/static/js/main.js create mode 100644 examples/deepDiveDemo/flask_app/templates/index.html create mode 100644 examples/deepDiveDemo/flask_app/utils/__init__.py create mode 100644 examples/deepDiveDemo/flask_app/utils/informationMediatorAuth.py create mode 100644 examples/deepDiveDemo/flask_app/utils/jsonEncoder.py create mode 100644 examples/deepDiveDemo/requirements.txt diff --git a/examples/deepDiveDemo/Dockerfile b/examples/deepDiveDemo/Dockerfile new file mode 100644 index 0000000..bd3ac23 --- /dev/null +++ b/examples/deepDiveDemo/Dockerfile @@ -0,0 +1,23 @@ +# Use an official Python runtime as the base image +FROM python:3.9-slim-buster + +# Set the working directory in the container +WORKDIR /deepDiveDemo + +# Copy the current directory contents into the container +COPY . . + +# Set environment variable for Python to enable absolute imports +ENV PYTHONPATH=/deepDiveDemo + +# Install required packages using pip +RUN pip install --trusted-host pypi.python.org -r requirements.txt + +# Expose port 5000 for Flask +EXPOSE 5000 + +# Define environment variable for Flask to run in production mode +ENV FLASK_ENV=production + +# Run app.py using Python when the container launches +CMD ["python", "flask_app/app.py"] diff --git a/examples/deepDiveDemo/docker-compose.yml b/examples/deepDiveDemo/docker-compose.yml new file mode 100644 index 0000000..7fa9720 --- /dev/null +++ b/examples/deepDiveDemo/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3' + +services: + web: + build: . + ports: + - "3333:5000" + volumes: + - .:/app + depends_on: + - mongo + environment: + - EXPECTED_CLIENT_HEADER=eGovStack/GOV/90000009/digitalregistries + mongo: + image: "mongo" + ports: + - "27017:27017" diff --git a/examples/deepDiveDemo/flask_app/app.py b/examples/deepDiveDemo/flask_app/app.py new file mode 100644 index 0000000..6c689f1 --- /dev/null +++ b/examples/deepDiveDemo/flask_app/app.py @@ -0,0 +1,55 @@ +import os + +from flask import Flask, render_template, jsonify, request, Response +from flask_pymongo import PyMongo + +from flask_app.utils import validate_information_mediator_header, JSONEncoderCustom + + +app = Flask(__name__) + + +MONGO_URI = os.getenv("MONGO_URI", "mongodb://mongo:27017/mydatabase") +app.config["MONGO_URI"] = MONGO_URI + +# Initialize MongoDB with Flask App +mongo = PyMongo(app) +db = mongo.db + + +@app.route('/') +def index(): + return render_template('index.html') + + +@app.route('/data///create', methods=['POST']) +def create_record(registryname, versionnumber): + # Extract header value + client_header = request.headers.get('Information-Mediator-Client') + if not client_header: + return jsonify({"error": "Information-Mediator-Client header missing"}), 400 + + client_header_valid = validate_information_mediator_header(client_header) + if not client_header_valid['success']: + return jsonify(client_header_valid), 403 + + # Validate the body + data = request.json.get('write', {}).get('content') + if not data: + return jsonify({"error": "Invalid request body"}), 400 + # Save the record to MongoDB + collection = db[registryname] # Using registryname as the collection name for this example + collection.insert_one(data) + + data.pop('_id') + + response = Response( + JSONEncoderCustom().encode({'content': data}), + mimetype="application/json" + ) + response.headers['Content-Type'] = 'application/json; charset=utf-8' # setting the content-type header explicitly + return response + + +if __name__ == '__main__': + app.run(host='0.0.0.0', debug=True) diff --git a/examples/deepDiveDemo/flask_app/static/css/main.css b/examples/deepDiveDemo/flask_app/static/css/main.css new file mode 100644 index 0000000..d0725a1 --- /dev/null +++ b/examples/deepDiveDemo/flask_app/static/css/main.css @@ -0,0 +1 @@ +body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; } diff --git a/examples/deepDiveDemo/flask_app/static/js/main.js b/examples/deepDiveDemo/flask_app/static/js/main.js new file mode 100644 index 0000000..e54009d --- /dev/null +++ b/examples/deepDiveDemo/flask_app/static/js/main.js @@ -0,0 +1 @@ +// Add your JS code here diff --git a/examples/deepDiveDemo/flask_app/templates/index.html b/examples/deepDiveDemo/flask_app/templates/index.html new file mode 100644 index 0000000..45a2ab7 --- /dev/null +++ b/examples/deepDiveDemo/flask_app/templates/index.html @@ -0,0 +1,14 @@ + + + + + + + Deep Dive Example Aplication + + + +

Welcome to the Demo Application!

+ + + diff --git a/examples/deepDiveDemo/flask_app/utils/__init__.py b/examples/deepDiveDemo/flask_app/utils/__init__.py new file mode 100644 index 0000000..67dc66a --- /dev/null +++ b/examples/deepDiveDemo/flask_app/utils/__init__.py @@ -0,0 +1,2 @@ +from .informationMediatorAuth import validate_information_mediator_header +from .jsonEncoder import JSONEncoderCustom \ No newline at end of file diff --git a/examples/deepDiveDemo/flask_app/utils/informationMediatorAuth.py b/examples/deepDiveDemo/flask_app/utils/informationMediatorAuth.py new file mode 100644 index 0000000..c8108e7 --- /dev/null +++ b/examples/deepDiveDemo/flask_app/utils/informationMediatorAuth.py @@ -0,0 +1,10 @@ +import os + + +def validate_information_mediator_header(header_value): + EXPECTED_CLIENT_HEADER = os.getenv('EXPECTED_CLIENT_HEADER', None) + + if not EXPECTED_CLIENT_HEADER or (header_value != EXPECTED_CLIENT_HEADER): + return {'success': False, "error": "Unauthorized"} + + return {'success': True} diff --git a/examples/deepDiveDemo/flask_app/utils/jsonEncoder.py b/examples/deepDiveDemo/flask_app/utils/jsonEncoder.py new file mode 100644 index 0000000..02c18ec --- /dev/null +++ b/examples/deepDiveDemo/flask_app/utils/jsonEncoder.py @@ -0,0 +1,8 @@ +from bson import ObjectId +from json import JSONEncoder + +class JSONEncoderCustom(JSONEncoder): + def default(self, o): + if isinstance(o, ObjectId): + return str(o) + return super().default(o) diff --git a/examples/deepDiveDemo/requirements.txt b/examples/deepDiveDemo/requirements.txt new file mode 100644 index 0000000..983d10d --- /dev/null +++ b/examples/deepDiveDemo/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.0.1 +pymongo +Flask-PyMongo \ No newline at end of file