diff --git a/components/entitiy_ident/entity_ident.py b/components/entitiy_ident/entity_ident.py index c42550a..7dde0d3 100644 --- a/components/entitiy_ident/entity_ident.py +++ b/components/entitiy_ident/entity_ident.py @@ -1,6 +1,8 @@ from flask import Flask from flask_pymongo import PyMongo +# see https://flask-pymongo.readthedocs.io/en/latest/ + app = Flask(__name__) app.config["MONGO_URI"] = "mongodb://localhost:27017/myDatabase" mongo = PyMongo(app) diff --git a/components/entitiy_ident/requirements.txt b/components/entitiy_ident/requirements.txt index ef79637..0205823 100644 --- a/components/entitiy_ident/requirements.txt +++ b/components/entitiy_ident/requirements.txt @@ -1,2 +1,3 @@ +pika flask Flask-PyMongo diff --git a/components/event_store/.gitignore b/components/event_store/.gitignore deleted file mode 100644 index 23385d0..0000000 --- a/components/event_store/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -venv -*.pyc -staticfiles -.env -*.sqlite3 -homeschooling_be_app.egg-info diff --git a/components/event_store/.run/createsuperuser.run.xml b/components/event_store/.run/createsuperuser.run.xml deleted file mode 100644 index 5fc8ae4..0000000 --- a/components/event_store/.run/createsuperuser.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/components/event_store/.run/makemigrations.run.xml b/components/event_store/.run/makemigrations.run.xml deleted file mode 100644 index b341723..0000000 --- a/components/event_store/.run/makemigrations.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/components/event_store/.run/migrate.run.xml b/components/event_store/.run/migrate.run.xml deleted file mode 100644 index 268a119..0000000 --- a/components/event_store/.run/migrate.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/components/event_store/.run/runserver.run.xml b/components/event_store/.run/runserver.run.xml deleted file mode 100644 index 3f7b118..0000000 --- a/components/event_store/.run/runserver.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/components/event_store/Dockerfile b/components/event_store/Dockerfile deleted file mode 100644 index 5a797cf..0000000 --- a/components/event_store/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM python:3.8-slim -ENV PYTHONUNBUFFERED 1 -RUN apt-get update -RUN apt-get install -y build-essential gcc - -RUN python -m venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" - -RUN python -m pip install --upgrade pip - -ENV PATH="/opt/venv/bin:$PATH" - -RUN mkdir /code -WORKDIR /code -COPY setup.py /code/ -COPY requirements.txt /code/ -RUN pip install -r requirements.txt - -COPY . /code/ diff --git a/components/event_store/README.md b/components/event_store/README.md deleted file mode 100644 index 274fb7c..0000000 --- a/components/event_store/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# AIC Django Middleware - -## Tips -* use Jetbrains Pycharm IDE -* create and use a virtual environment - -## Setup - $ cd ./middleware - - $ pip install -r requirements.txt - - $ python manage.py makemigrations - $ python manage.py migrate - $ python manage.py createsuperuser - - $ python mangge.py runserver - -## ERROR handling -Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools" -
Install missing deps https://visualstudio.microsoft.com/visual-cpp-build-tools/ diff --git a/components/event_store/__init__.py b/components/event_store/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/__init__.py b/components/event_store/app_be/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/admin.py b/components/event_store/app_be/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/components/event_store/app_be/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/components/event_store/app_be/apps.py b/components/event_store/app_be/apps.py deleted file mode 100644 index d4828a5..0000000 --- a/components/event_store/app_be/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class AppBeConfig(AppConfig): - name = 'app_be' diff --git a/components/event_store/app_be/models.py b/components/event_store/app_be/models.py deleted file mode 100644 index 71a8362..0000000 --- a/components/event_store/app_be/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/components/event_store/app_be/routing.py b/components/event_store/app_be/routing.py deleted file mode 100644 index b635884..0000000 --- a/components/event_store/app_be/routing.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.conf.urls import url - -from channels.routing import ProtocolTypeRouter, URLRouter -from channels.sessions import SessionMiddlewareStack -from django.core.asgi import get_asgi_application - -from .views.ws_api import CustomConsumer - -application = ProtocolTypeRouter({ - # Django's ASGI application to handle traditional HTTP requests - "http": get_asgi_application(), - - # WebSocket send handler - "websocket": SessionMiddlewareStack(URLRouter([ - url(r"^test-ws-endpoint/$", CustomConsumer.as_asgi()), - ])) -}) diff --git a/components/event_store/app_be/serializers.py b/components/event_store/app_be/serializers.py deleted file mode 100644 index de8ae38..0000000 --- a/components/event_store/app_be/serializers.py +++ /dev/null @@ -1,3 +0,0 @@ -from rest_framework import serializers - -# add serializer here diff --git a/components/event_store/app_be/services/data_factory.py b/components/event_store/app_be/services/data_factory.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/services/tests/test_data_factory.py b/components/event_store/app_be/services/tests/test_data_factory.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/settings.py b/components/event_store/app_be/settings.py deleted file mode 100644 index 1c23499..0000000 --- a/components/event_store/app_be/settings.py +++ /dev/null @@ -1,221 +0,0 @@ -""" -For more information on this file, see -https://docs.djangoproject.com/en/2.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/2.0/ref/settings/ -""" -import datetime -import os - -# set the websocket routing module location here -ASGI_APPLICATION = 'app_be.routing.application' - - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "{{ secret_key }}" - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -# Application definition - -INSTALLED_APPS = [ - 'app_be', - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'channels', - 'rest_framework' -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'whitenoise.middleware.WhiteNoiseMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -] - -""" -default permission and authentication classes -sets the standard privileges needed to access an api -for now, no classes necessary and therefore disabled! -""" -REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': ( - # 'rest_framework.permissions.IsAuthenticated', # last comma is MANDATORY - [] - ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # last comma is MANDATORY - [] - ) -} - - -# configuration of jason web token authentication -JWT_AUTH = { - 'JWT_VERIFY': True, - 'JWT_AUTH_HEADER_PREFIX': 'Bearer', - 'JWT_ALLOW_REFRESH': True, - # 60 minutes - 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600), - # debug 10 seconds - # 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=10), -} - -if DEBUG: - # install corsheaders to enable to run - # the rest (django) an gui (angular) server on two different ports - INSTALLED_APPS.append("corsheaders") - MIDDLEWARE.append('corsheaders.middleware.CorsMiddleware') - MIDDLEWARE.append('django.middleware.common.BrokenLinkEmailsMiddleware') - MIDDLEWARE.append('django.middleware.common.CommonMiddleware') - CORS_ORIGIN_ALLOW_ALL = True - ALLOWED_HOSTS = [ - "*" - ] -else: - ALLOWED_HOSTS = [ - "*", - "127.0.0.1" - ] - -ROOT_URLCONF = 'app_be.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - 'debug': DEBUG, - }, - }, -] - -WSGI_APPLICATION = 'app_be.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/2.0/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } -} - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - -# Internationalization -# https://docs.djangoproject.com/en/2.0/topics/i18n/ - -LANGUAGE_CODE = 'en-us' -TIME_ZONE = 'UTC' -USE_I18N = True -USE_L10N = True -USE_TZ = True - -# Change 'default' database configuration with $DATABASE_URL. -# DATABASES['default'].update(dj_database_url.config(conn_max_age=500, ssl_require=True)) - -# Honor the 'X-Forwarded-Proto' header for request.is_secure() -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.0/howto/static-files/ - -STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles') -STATIC_URL = '/static/' - -# Extra places for collectstatic to find static files. -STATICFILES_DIRS = [ - os.path.join(PROJECT_ROOT, 'static'), -] - -# Simplified static file serving. -# https://warehouse.python.org/project/whitenoise/ -STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'verbose': { - 'format': '{asctime} - {levelname}: {message} ({pathname}:{lineno})', - 'style': '{', - } - }, - 'handlers': { - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'formatter': 'verbose' - }, - 'logfile': { - 'level': 'DEBUG', - 'class': 'logging.FileHandler', - 'filename': BASE_DIR + "/../logfile", - 'formatter': 'verbose' - }, - }, - - 'loggers': { - 'rdg': { - 'handlers': ['console', 'logfile'], - 'level': 'DEBUG', - }, - 'rdg_rest': { - 'handlers': ['console', 'logfile'], - 'level': 'DEBUG', - }, - 'rdg_angular': { - 'handlers': ['console', 'logfile'], - 'level': 'DEBUG', - }, - }, - 'root': { - 'level': 'DEBUG', - 'handlers': [] # pass a empty list to avoid duplicte log entries - }, -} - -# increase the maximum upload size of files -DATA_UPLOAD_MAX_MEMORY_SIZE = 104857600 - diff --git a/components/event_store/app_be/tests.py b/components/event_store/app_be/tests.py deleted file mode 100644 index 4890637..0000000 --- a/components/event_store/app_be/tests.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.test import TestCase - -# Create your tests here. -from rest_framework import status -from rest_framework.test import APITestCase - - -class AccountTests(APITestCase): - def test_create_account(self): - """ - Ensure we can create a new account object. - """ - url = '/test/' - response = self.client.get(url, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/components/event_store/app_be/urls.py b/components/event_store/app_be/urls.py deleted file mode 100644 index 79a7a73..0000000 --- a/components/event_store/app_be/urls.py +++ /dev/null @@ -1,30 +0,0 @@ -"""{{ project_name }} URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/2.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" -from django.conf.urls import url -from django.contrib import admin -from django.urls import path -from rest_framework.routers import DefaultRouter - -from app_be.views.rest_api import TestApiClass - -urlpatterns = [ - path('admin/', admin.site.urls), - url(r'^test/', TestApiClass.test_api), -] - -router = DefaultRouter() - -urlpatterns.extend(router.urls) diff --git a/components/event_store/app_be/views/__init__.py b/components/event_store/app_be/views/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/views/rest_api.py b/components/event_store/app_be/views/rest_api.py deleted file mode 100644 index de7bb8a..0000000 --- a/components/event_store/app_be/views/rest_api.py +++ /dev/null @@ -1,15 +0,0 @@ -import logging - -from django.http import JsonResponse - -from rest_framework.decorators import api_view - -logger = logging.getLogger(__name__) - - -class TestApiClass: - @staticmethod - @api_view(['GET']) - def test_api(request): - logger.debug('Test api call: {}'.format(request)) - return JsonResponse({'Result': 'success'}, safe=False) diff --git a/components/event_store/app_be/views/tests/__init__.py b/components/event_store/app_be/views/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/views/tests/test_rest_api.py b/components/event_store/app_be/views/tests/test_rest_api.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/views/tests/test_ws_api.py b/components/event_store/app_be/views/tests/test_ws_api.py deleted file mode 100644 index e69de29..0000000 diff --git a/components/event_store/app_be/views/ws_api.py b/components/event_store/app_be/views/ws_api.py deleted file mode 100644 index a648867..0000000 --- a/components/event_store/app_be/views/ws_api.py +++ /dev/null @@ -1,18 +0,0 @@ -import logging - -from channels.generic.websocket import WebsocketConsumer - - -logger = logging.getLogger(__name__) - - -class CustomConsumer(WebsocketConsumer): - def connect(self): - self.accept() - - def receive(self, text_data=None, bytes_data=None): - self.send('1. response: {}'.format(text_data)) - self.send('2. response: {}'.format(text_data)) - - def disconnect(self, code): - pass diff --git a/components/event_store/app_be/wsgi.py b/components/event_store/app_be/wsgi.py deleted file mode 100644 index 8addf73..0000000 --- a/components/event_store/app_be/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for {{ project_name }} project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ app_be }}.settings") - -application = get_wsgi_application() diff --git a/components/event_store/event_store.py b/components/event_store/event_store.py new file mode 100644 index 0000000..07f143c --- /dev/null +++ b/components/event_store/event_store.py @@ -0,0 +1,22 @@ +from flask import Flask +from flask_redis import Redis + +# see https://flask-and-redis.readthedocs.io/en/latest/ +# see https://github.com/andymccurdy/redis-py + +app = Flask(__name__) +app.config["REDIS_HOST"] = "localhost" +app.config["REDIS_PORT"] = 6379 +redis = Redis(app) + + +@app.route("/") +def home_page(): + redis.set('foo', 'bar') + print(redis.get('foo')) + + return 'redis works' + + +if __name__ == '__main__': + app.run() diff --git a/components/event_store/manage.py b/components/event_store/manage.py deleted file mode 100644 index 06a5a5d..0000000 --- a/components/event_store/manage.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_be.settings") - try: - from django.core.management import execute_from_command_line - except ImportError as exc: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) - execute_from_command_line(sys.argv) diff --git a/components/event_store/requirements.txt b/components/event_store/requirements.txt index 9470d20..7522705 100644 --- a/components/event_store/requirements.txt +++ b/components/event_store/requirements.txt @@ -1,11 +1,3 @@ -# install setup.py in dev mode --e . - -Django==3.2 -djangorestframework==3.12.4 -djangorestframework-jwt==1.11.0 -django-cors-headers==3.7.0 -channels==3.0.3 -channels_redis==3.2.0 -whitenoise==5.2.0 pika +flask +Flask-And-Redis diff --git a/components/event_store/setup.py b/components/event_store/setup.py deleted file mode 100644 index 1bb48c6..0000000 --- a/components/event_store/setup.py +++ /dev/null @@ -1,14 +0,0 @@ -import os -from setuptools import find_packages, setup - -# allow setup.py to be run from any path -os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) - -setup( - name='homeschooling-be-app', - version='0.0.0', - packages=find_packages(), - include_package_data=True, - license='BSD License', # example license - description='DESCRIPTION' -) diff --git a/components/orchestration/README.md b/components/orchestration/README.md deleted file mode 100644 index 5681d10..0000000 --- a/components/orchestration/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Super Lightweight Flask Web Server -* `pip install requirements.txt` -* `python entitiy_ident_service.py` -* `http://127.0.0.1:5000` -> `Hello World` -* `http://127.0.0.1:5000/api1` -> `api1` -* `http://127.0.0.1:5000/api2` -> `api2` diff --git a/components/orchestration/requirements.txt b/components/orchestration/requirements.txt index 8ab6294..73d38a4 100644 --- a/components/orchestration/requirements.txt +++ b/components/orchestration/requirements.txt @@ -1 +1,2 @@ +pika flask \ No newline at end of file diff --git a/components/x_way/README.md b/components/x_way/README.md index 5681d10..ef7e400 100644 --- a/components/x_way/README.md +++ b/components/x_way/README.md @@ -1,6 +1,6 @@ # Super Lightweight Flask Web Server * `pip install requirements.txt` -* `python entitiy_ident_service.py` +* `python x_way.py` * `http://127.0.0.1:5000` -> `Hello World` * `http://127.0.0.1:5000/api1` -> `api1` * `http://127.0.0.1:5000/api2` -> `api2` diff --git a/project_plan/arch proposal.drawio b/project_plan/arch proposal.drawio index 5677517..dafac07 100644 --- a/project_plan/arch proposal.drawio +++ b/project_plan/arch proposal.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file