diff --git a/.azure/config b/.azure/config new file mode 100644 index 00000000..2204489e --- /dev/null +++ b/.azure/config @@ -0,0 +1,7 @@ +[defaults] +group = vbv-prod_group +sku = P2v2 +appserviceplan = prod +location = switzerlandnorth +web = vbv-prod + diff --git a/.dockerignore b/.dockerignore index 83653a41..ab0ded02 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,3 +13,4 @@ venv .git .envrc /server/vbv_lernwelt/media/documents +env_secrets diff --git a/.gitignore b/.gitignore index 3d1e0c04..a511dff6 100644 --- a/.gitignore +++ b/.gitignore @@ -287,6 +287,7 @@ git-crypt-encrypted-files-check.txt /server/vbv_lernwelt/static/css/tailwind.css /server/vbv_lernwelt/static/vue/ +/server/vbv_lernwelt/static/storybook /server/vbv_lernwelt/templates/vue/index.html /server/vbv_lernwelt/media /client/src/gql/minifiedSchema.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 301f8b74..00000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,33 +0,0 @@ -exclude: "^docs/|/migrations/" -default_stages: [commit] - -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - - repo: https://github.com/psf/black - rev: 21.12b0 - hooks: - - id: black - - - repo: https://github.com/PyCQA/isort - rev: 5.10.1 - hooks: - - id: isort - - - repo: https://github.com/PyCQA/flake8 - rev: 4.0.1 - hooks: - - id: flake8 - args: ["--config=setup.cfg"] - additional_dependencies: [flake8-isort] - -# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date -ci: - autoupdate_schedule: weekly - skip: [] - submodules: false diff --git a/README_generated.md b/README_generated.md deleted file mode 100644 index ba101e7b..00000000 --- a/README_generated.md +++ /dev/null @@ -1,59 +0,0 @@ -# VBV Lernwelt - -Behold My Awesome Project! - -[![Built with Cookiecutter Django](https://img.shields.io/badge/built%20with-Cookiecutter%20Django-ff69b4.svg?logo=cookiecutter)](https://github.com/cookiecutter/cookiecutter-django/) -[![Black code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) - -## Settings - -Moved to [settings](http://cookiecutter-django.readthedocs.io/en/latest/settings.html). - -## Basic Commands - -### Setting Up Your Users - -- To create a **normal user account**, just go to Sign Up and fill out the form. Once you submit it, you'll see a "Verify Your E-mail Address" page. Go to your console to see a simulated email verification message. Copy the link into your browser. Now the user's email should be verified and ready to go. - -- To create an **superuser account**, use this command: - - $ python manage.py createsuperuser - -For convenience, you can keep your normal user logged in on Chrome and your superuser logged in on Firefox (or similar), so that you can see how the site behaves for both kinds of users. - -### Type checks - -Running type checks with mypy: - - $ mypy vbv_lernwelt - -### Test coverage - -To run the tests, check your test coverage, and generate an HTML coverage report: - - $ coverage run -m pytest - $ coverage html - $ open htmlcov/index.html - -#### Running tests with pytest - - $ pytest - -### Live reloading and Sass CSS compilation - -Moved to [Live reloading and SASS compilation](http://cookiecutter-django.readthedocs.io/en/latest/live-reloading-and-sass-compilation.html). - -### Sentry - -Sentry is an error logging aggregator service. You can sign up for a free account at or download and host it yourself. -The system is set up with reasonable defaults, including 404 logging and integration with the WSGI application. - -You must set the DSN url in production. - -## Deployment - -The following details how to deploy this application. - -### Docker - -See detailed [cookiecutter-django Docker documentation](http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html). diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 0365e271..4e60ffd8 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -129,11 +129,17 @@ pipelines: name: prepare prod deployment script: - echo "Release ready!" - - step: - <<: *deploy - name: deploy prod - deployment: prod - trigger: manual + - parallel: + - step: + <<: *deploy + name: deploy prod + deployment: prod + trigger: manual + - step: + <<: *deploy + name: deploy prod-azure + deployment: prod-azure + trigger: manual custom: deploy-stage: - step: diff --git a/caprover_create_app.py b/caprover_create_app.py index d67eb866..549b5b23 100644 --- a/caprover_create_app.py +++ b/caprover_create_app.py @@ -70,6 +70,7 @@ def main(app_name, image_name, environment_file): force_ssl=True, expose_as_web_app=True, image_name=image_name, + container_http_port=7555, environment_variables={ # 'DJANGO_SETTINGS_MODULE': 'config.settings.base', "IT_APP_ENVIRONMENT": env.str("IT_APP_ENVIRONMENT", "caprover_feature"), @@ -84,25 +85,9 @@ def main(app_name, image_name, environment_file): "IT_DJANGO_SECRET_KEY": env.str( "IT_DJANGO_SECRET_KEY", generate_random_string(63) ), - "IT_DJANGO_ADMIN_URL": env.str("IT_DJANGO_ADMIN_URL", "admin/"), "IT_DJANGO_DEBUG": "false", "IT_SERVE_VUE": "false", "IT_ALLOW_LOCAL_LOGIN": "true", - # used for deployment of "real" environments, not used now for feature branches - # 'IT_ALLOW_LOCAL_LOGIN': env.str('IT_ALLOW_LOCAL_LOGIN'), - # 'IT_SENTRY_DSN': env.str('IT_SENTRY_DSN'), - # 'IT_OAUTH_CLIENT_NAME': env.str('IT_OAUTH_CLIENT_NAME'), - # 'IT_OAUTH_CLIENT_ID': env.str('IT_OAUTH_CLIENT_ID'), - # 'IT_OAUTH_CLIENT_SECRET': env.str('IT_OAUTH_CLIENT_SECRET'), - # 'IT_OAUTH_ACCESS_TOKEN_URL': env.str('IT_OAUTH_ACCESS_TOKEN_URL'), - # 'IT_OAUTH_AUTHORIZE_URL': env.str('IT_OAUTH_AUTHORIZE_URL'), - # 'IT_OAUTH_API_BASE_URL': env.str('IT_OAUTH_API_BASE_URL'), - # 'IT_OAUTH_LOCAL_DIRECT_URI': env.str('IT_OAUTH_LOCAL_DIRECT_URI'), - # 'IT_OAUTH_TENANT_ID': env.str('IT_OAUTH_TENANT_ID'), - # 'IT_OAUTH_SCOPE': env.str('IT_OAUTH_SCOPE'), - # 'IT_OAUTH_SERVER_METADATA_URL': env.str('IT_OAUTH_SERVER_METADATA_URL'), - # 'IT_OAUTH_TOKEN_NAME': env.str('IT_OAUTH_TOKEN_NAME'), - # 'IT_OAUTH_LOGOUT_URL': env.str('IT_OAUTH_LOGOUT_URL'), }, ) diff --git a/caprover_deploy.sh b/caprover_deploy.sh index f31cdba0..8772aaf4 100755 --- a/caprover_deploy.sh +++ b/caprover_deploy.sh @@ -3,74 +3,79 @@ # script should fail when any process returns non zero code set -ev -VERSION=$(git log -1 --pretty=%h) -REPO="iterativ/vbv-lernwelt-django" -LATEST="${REPO}:latest" -BUILD_TIMESTAMP=$( date '+%F_%H:%M:%S' ) -VERSION_TAG="${REPO}:$VERSION" +function generate_default_app_name() { + local branch_name=$(git rev-parse --abbrev-ref HEAD) + local branch_name_slug=$(echo "$branch_name" | sed -e 's/[^[:alnum:]]/-/g' | tr -s '-' | tr A-Z a-z) -BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) -BRANCH_NAME_SLUG=$(echo "$BRANCH_NAME" | sed -e 's/[^[:alnum:]]/-/g' | tr -s '-' | tr A-Z a-z) -echo "$BRANCH_NAME_SLUG" + local default_app_name="vbv-$branch_name_slug" -DEFAULT_APP_NAME="vbv-$BRANCH_NAME_SLUG" -APP_NAME=${1:-$DEFAULT_APP_NAME} + # shorten default_app_name to 32 characters + if ((${#default_app_name} > 32)); then + local hash="$(echo -n "$default_app_name" | md5sum | cut -c1-4)" + default_app_name=$(echo -n "${default_app_name:0:28}-${hash}") + fi -# shorten APP_NAME to 32 characters -# app names with more character seem to fail in some steps in CapRover -# CapRover generates longer names out from the app name and there -# seems to be a limit in Docker of 64 characters -if (( ${#APP_NAME} > 32 )); then - hash="$(echo -n "$APP_NAME" | md5sum | cut -c1-4)" - APP_NAME=$(echo -n "${APP_NAME:0:28}-${hash}") -fi + # remove multiple dashes and make sure it does not end with a dash + default_app_name=$(echo "$default_app_name" | sed -E 's/-+/-/g') + default_app_name=$(echo "$default_app_name" | sed 's/-\+$//') -# remove multiple dashes and make sure it does not end with a dash -APP_NAME=$(echo "$APP_NAME" | sed -E 's/-+/-/g') -APP_NAME=$(echo "$APP_NAME" | sed 's/-\+$//') + echo "$default_app_name" +} + +# take app name as first argument or use the default generated app name +APP_NAME=${1:-$(generate_default_app_name)} echo "Deploy to $APP_NAME" -VITE_GRAPHQL_URL="/server/graphql/" -VITE_LOGOUT_REDIRECT="/" VITE_SENTRY_ENV="development" -if [[ "$APP_NAME" == "myvbv" ]] -then - VITE_LOGOUT_REDIRECT="https://edumgr.b2clogin.com/edumgr.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://myvbv.iterativ.ch/" - VITE_SENTRY_ENV="production" -elif [[ "$APP_NAME" == "myvbv-stage" ]] -then - VITE_LOGOUT_REDIRECT="https://vbvtst.b2clogin.com/vbvtst.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://myvbv-stage.iterativ.ch/" - VITE_SENTRY_ENV="stage" -elif [[ "$APP_NAME" == "vbv-lernwelt" ]] -then - VITE_LOGOUT_REDIRECT="https://vbvdev.b2clogin.com/vbvdev.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://vbv-lernwelt.control.iterativ.ch" - VITE_SENTRY_ENV="development" +if [[ "$APP_NAME" == "myvbv" ]]; then + VITE_LOGOUT_REDIRECT="https://edumgr.b2clogin.com/edumgr.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://myvbv.iterativ.ch/" + VITE_SENTRY_ENV="production" +elif [[ "$APP_NAME" == "myvbv-stage" ]]; then + VITE_LOGOUT_REDIRECT="https://vbvtst.b2clogin.com/vbvtst.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://myvbv-stage.iterativ.ch/" + VITE_SENTRY_ENV="stage" +elif [[ "$APP_NAME" == "vbv-lernwelt" ]]; then + VITE_LOGOUT_REDIRECT="https://vbvdev.b2clogin.com/vbvdev.onmicrosoft.com/b2c_1_signupandsignin/oauth2/v2.0/logout/?post_logout_redirect_uri=https://vbv-lernwelt.control.iterativ.ch" + VITE_SENTRY_ENV="development" fi # create client for django npm run build python server/manage.py collectstatic --no-input -# create and push new docker container -docker build --platform=linux/amd64 -f compose/django/Dockerfile -t "$REPO" -t "$LATEST" -t "$VERSION_TAG" --build-arg VERSION="$VERSION" --build-arg BUILD_TIMESTAMP="$BUILD_TIMESTAMP" --build-arg GIT_COMMIT="$(git log -1 --format=%h)" . -docker push "$VERSION_TAG" +if [[ "$APP_NAME" == "prod-azure" ]]; then + # build and push azure docker container + docker build --platform linux/amd64 -f compose/django/Dockerfile -t iterativ/vbv-lernwelt-django:azure . + docker image push iterativ/vbv-lernwelt-django:azure + # FIXME: It seems that in Azure we have to manually restart the container for now + echo "https://my.vbv-afa.ch/" >/tmp/caprover_app_url.txt +else + # create and push new docker container + VERSION=$(git log -1 --pretty=%h) + REPO="iterativ/vbv-lernwelt-django" + LATEST="${REPO}:latest" + BUILD_TIMESTAMP=$(date '+%F_%H:%M:%S') + VERSION_TAG="${REPO}:$VERSION" + docker build --platform=linux/amd64 -f compose/django/Dockerfile -t "$REPO" -t "$LATEST" -t "$VERSION_TAG" --build-arg VERSION="$VERSION" --build-arg BUILD_TIMESTAMP="$BUILD_TIMESTAMP" --build-arg GIT_COMMIT="$(git log -1 --format=%h)" . + docker push "$VERSION_TAG" -APP_URL="$APP_NAME.control.iterativ.ch" + # caprover specific deployment + APP_URL="$APP_NAME.control.iterativ.ch" -echo "Checking if $APP_URL is available..." -if ! curl --output /dev/null --silent --head --fail "$APP_URL"; then - echo "HTTP request to $APP_URL did not return a 200 status code, so we need to create the caprover app" - python caprover_cleanup.py -a "$APP_NAME*" --automated - python caprover_create_app.py -a "$APP_NAME" -fi - -# deploy to caprover, explicitly use the version tag... so if there is a mismatch you get an error message -caprover deploy -h https://captain.control.iterativ.ch -a "$APP_NAME" -i docker.io/"$VERSION_TAG" - -if [ -n "$CI" ]; then - echo "Running within Bitbucket Pipelines" - export CAPROVER_APP_URL="$APP_URL" - echo "https://$CAPROVER_APP_URL" > /tmp/caprover_app_url.txt + echo "Checking if $APP_URL is available..." + if ! curl --output /dev/null --silent --head --fail "$APP_URL"; then + echo "HTTP request to $APP_URL did not return a 200 status code, so we need to create the caprover app" + python caprover_cleanup.py -a "$APP_NAME*" --automated + python caprover_create_app.py -a "$APP_NAME" + fi + + # deploy to caprover, explicitly use the version tag... so if there is a mismatch you get an error message + caprover deploy -h https://captain.control.iterativ.ch -a "$APP_NAME" -i docker.io/"$VERSION_TAG" + + if [ -n "$CI" ]; then + echo "Running within Bitbucket Pipelines" + export CAPROVER_APP_URL="$APP_URL" + echo "https://$CAPROVER_APP_URL" >/tmp/caprover_app_url.txt + fi fi diff --git a/compose/django/Dockerfile b/compose/django/Dockerfile index b3fa66f2..aa489641 100644 --- a/compose/django/Dockerfile +++ b/compose/django/Dockerfile @@ -104,4 +104,6 @@ RUN chown django:django ${APP_HOME} USER django +EXPOSE 7555 + ENTRYPOINT ["/entrypoint"] diff --git a/compose/django/docker_start.sh b/compose/django/docker_start.sh index ea492112..e888148f 100644 --- a/compose/django/docker_start.sh +++ b/compose/django/docker_start.sh @@ -9,4 +9,6 @@ python /app/manage.py collectstatic --no-input --no-post-process # TODO remove after stabilisation python /app/manage.py reset_schema -/usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:80 --chdir=/app -k uvicorn.workers.UvicornWorker +/usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:7555 --chdir=/app -k uvicorn.workers.UvicornWorker + + diff --git a/compose/django/sshd_config b/compose/django/sshd_config new file mode 100644 index 00000000..e69de29b diff --git a/docs/azure-tricks.md b/docs/azure-tricks.md new file mode 100644 index 00000000..08fc8876 --- /dev/null +++ b/docs/azure-tricks.md @@ -0,0 +1,11 @@ +# Azure tricks + +This document should help the user with a few commands, how to handle the azure app. + + +# Get logs of the container + +```bash +az webapp log tail --resource-group VBV + + diff --git a/env/azure/azure-infos.md b/env/azure/azure-infos.md new file mode 100644 index 00000000..bab329ba --- /dev/null +++ b/env/azure/azure-infos.md @@ -0,0 +1,27 @@ +# VBV installstion on Azure + +## Prerequisites + +- Azure subscription +- Azure CLI + + +## For this project we use the +vbv resource group. + +[Azure app services tutorial](https://learn.microsoft.com/en-us/azure/app-service/media/tutorial-python-postgresql-app/python-postgresql-app-architecture-240px.png) +![](https://learn.microsoft.com/en-us/azure/app-service/media/tutorial-python-postgresql-app/python-postgresql-app-architecture-240px.png) +For the app we use azure app services, wiht a potgres database. + + + +Deployment for django: +https://tonybaloney.github.io/posts/django-on-azure-beyond-hello-world.html + +az webapp deployment user set --user-name --password + +# Docker image for the app + + To be able to pull the docker image from dockerhub you need to create an access token on dockerhub. +the access token is then the password in azure and the username is the dockerhub username. + diff --git a/env/azure/commands.sh b/env/azure/commands.sh new file mode 100644 index 00000000..6e679b0f --- /dev/null +++ b/env/azure/commands.sh @@ -0,0 +1,16 @@ +# create a webapp deploment user +# you can not run these command wiht the free tier subscription... at least developer tier is needed. +az webapp deployment user set --user-name iterativ_developer --password 1password + +# Create plans for stage and prod +az appservice plan create --name stage --resource-group VBV --sku P1V2 --is-linux +az appservice plan create --name prod --resource-group VBV --sku P2V2 --is-linux + +# create the two applications on Python 3.10, change +az webapp create --resource-group VBV --plan stage --name app-stage --runtime "PYTHON|3.10" --deployment-local-git +az webapp create --resource-group VBV --plan prod --name app-prod --runtime "PYTHON|3.10" --deployment-local-git + + +az webapp up --resource-group VBV --plan prod --name app-prod --runtime "PYTHON|3.10" --logs + + diff --git a/env/azure/vbv-prod.json b/env/azure/vbv-prod.json new file mode 100644 index 00000000..ea449371 --- /dev/null +++ b/env/azure/vbv-prod.json @@ -0,0 +1,213 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "sites_vbv_prod_name": { + "defaultValue": "vbv-prod", + "type": "String" + }, + "serverfarms_prod_externalid": { + "defaultValue": "/subscriptions/b93dcf47-7d82-4af9-8dbc-3317650d0ad7/resourceGroups/VBV/providers/Microsoft.Web/serverfarms/prod", + "type": "String" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Web/sites", + "apiVersion": "2022-09-01", + "name": "[parameters('sites_vbv_prod_name')]", + "location": "Switzerland North", + "kind": "app,linux", + "properties": { + "enabled": true, + "hostNameSslStates": [ + { + "name": "[concat(parameters('sites_vbv_prod_name'), '.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Standard" + }, + { + "name": "[concat(parameters('sites_vbv_prod_name'), '.scm.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Repository" + } + ], + "serverFarmId": "[parameters('serverfarms_prod_externalid')]", + "reserved": true, + "isXenon": false, + "hyperV": false, + "vnetRouteAllEnabled": false, + "vnetImagePullEnabled": false, + "vnetContentShareEnabled": false, + "siteConfig": { + "numberOfWorkers": 1, + "linuxFxVersion": "PYTHON|3.10", + "acrUseManagedIdentityCreds": false, + "alwaysOn": true, + "http20Enabled": false, + "functionAppScaleLimit": 0, + "minimumElasticInstanceCount": 0 + }, + "scmSiteAlsoStopped": false, + "clientAffinityEnabled": false, + "clientCertEnabled": false, + "clientCertMode": "Required", + "hostNamesDisabled": false, + "customDomainVerificationId": "A2AB57353045150ADA4488FAA8AA9DFBBEDDD311934653F55243B336C2F3358E", + "containerSize": 0, + "dailyMemoryTimeQuota": 0, + "httpsOnly": true, + "redundancyMode": "None", + "publicNetworkAccess": "Enabled", + "storageAccountRequired": false, + "keyVaultReferenceIdentity": "SystemAssigned" + } + }, + { + "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", + "apiVersion": "2022-09-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/ftp')]", + "location": "Switzerland North", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ], + "properties": { + "allow": false + } + }, + { + "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", + "apiVersion": "2022-09-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/scm')]", + "location": "Switzerland North", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ], + "properties": { + "allow": false + } + }, + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2022-09-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/web')]", + "location": "Switzerland North", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ], + "properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "linuxFxVersion": "PYTHON|3.10", + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "remoteDebuggingVersion": "VS2019", + "httpLoggingEnabled": false, + "acrUseManagedIdentityCreds": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "$vbv-prod", + "scmType": "BitbucketGit", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true + } + ], + "loadBalancing": "LeastRequests", + "experiments": { + "rampUpRules": [] + }, + "autoHealEnabled": false, + "vnetRouteAllEnabled": false, + "vnetPrivatePortsCount": 0, + "publicNetworkAccess": "Enabled", + "localMySqlEnabled": false, + "ipSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 2147483647, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 2147483647, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictionsUseMain": false, + "http20Enabled": false, + "minTlsVersion": "1.2", + "scmMinTlsVersion": "1.2", + "ftpsState": "Disabled", + "preWarmedInstanceCount": 0, + "elasticWebAppScaleLimit": 0, + "functionsRuntimeScaleMonitoringEnabled": false, + "minimumElasticInstanceCount": 0, + "azureStorageAccounts": {} + } + }, + { + "type": "Microsoft.Web/sites/deployments", + "apiVersion": "2022-09-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/96334b4eb6a7ae5b0d86abd7febcbcc67323bb94')]", + "location": "Switzerland North", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ], + "properties": { + "status": 4, + "author_email": "ramon.wenger@iterativ.ch", + "author": "Ramon Wenger", + "message": "Merged in feature/VBV-304-praesenztag-ui (pull request #65)\n \n Feature/VBV-304 praesenztag ui\n \n Approved-by: Daniel Egger", + "start_time": "2023-05-02T12:43:38.4426574Z", + "end_time": "2023-05-02T12:43:58.307067Z", + "active": true + } + }, + { + "type": "Microsoft.Web/sites/hostNameBindings", + "apiVersion": "2022-09-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/', parameters('sites_vbv_prod_name'), '.azurewebsites.net')]", + "location": "Switzerland North", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ], + "properties": { + "siteName": "vbv-prod", + "hostNameType": "Verified" + } + }, + { + "type": "Microsoft.Web/sites/snapshots", + "apiVersion": "2015-08-01", + "name": "[concat(parameters('sites_vbv_prod_name'), '/2023-05-02T12_40_23_4355704')]", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('sites_vbv_prod_name'))]" + ] + } + ] +} diff --git a/env/docker_local.env b/env/docker_local.env index 7919aebc..409e30f8 100644 --- a/env/docker_local.env +++ b/env/docker_local.env @@ -3,10 +3,11 @@ POSTGRES_HOST=postgres POSTGRES_PORT=5432 POSTGRES_DB=vbv_lernwelt -POSTGRES_USER=MRsLOrFLFqmAnAxxWMsHXfUSqWHThtGQ +POSTGRES_USER=postgres POSTGRES_PASSWORD=hNqfCdG6bwCLcnfboDtNM1L2Hiwp8GuKp1DJ6t2rcKl15Vls2QbByoIZ6IQlciKM # General # ------------------------------------------------------------------------------ IT_DJANGO_LOCAL_DOCKER=True IPYTHONDIR=/app/.ipython +IT_APP_ENVIRONMENT=local diff --git a/env_secrets/pg_backup_local.env b/env_secrets/pg_backup_local.env new file mode 100644 index 00000000..ca8e7f15 Binary files /dev/null and b/env_secrets/pg_backup_local.env differ diff --git a/env_secrets/production_azure.env b/env_secrets/production_azure.env new file mode 100644 index 00000000..b5149493 Binary files /dev/null and b/env_secrets/production_azure.env differ diff --git a/env_secrets/production_azure_from_cloud.json b/env_secrets/production_azure_from_cloud.json new file mode 100644 index 00000000..0f4d6615 Binary files /dev/null and b/env_secrets/production_azure_from_cloud.json differ diff --git a/git-crypt-encrypted-files.txt b/git-crypt-encrypted-files.txt index 9136f91d..3d9c4040 100644 --- a/git-crypt-encrypted-files.txt +++ b/git-crypt-encrypted-files.txt @@ -5,4 +5,7 @@ encrypted: env_secrets/local_daniel.env encrypted: env_secrets/local_elia.env encrypted: env_secrets/local_lorenz.env + encrypted: env_secrets/pg_backup_local.env encrypted: env_secrets/production.env + encrypted: env_secrets/production_azure.env + encrypted: env_secrets/production_azure_from_cloud.json diff --git a/requests.http b/requests.http deleted file mode 100644 index 01ddd65e..00000000 --- a/requests.http +++ /dev/null @@ -1,2 +0,0 @@ -# Logout -POST http://localhost:8000/core/logout/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..3ea08861 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +-r server/requirements/requirements.txt diff --git a/server/config/settings/base.py b/server/config/settings/base.py index 11b0c53d..06b57573 100644 --- a/server/config/settings/base.py +++ b/server/config/settings/base.py @@ -507,6 +507,7 @@ else: SECRET_KEY = env("IT_DJANGO_SECRET_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts + ALLOWED_HOSTS = env.list( "IT_DJANGO_ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1"] ) diff --git a/server/requirements/requirements-dev.txt b/server/requirements/requirements-dev.txt index f3875c8b..62594c31 100644 --- a/server/requirements/requirements-dev.txt +++ b/server/requirements/requirements-dev.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: # # pip-compile --output-file=requirements-dev.txt requirements-dev.in # @@ -10,6 +10,8 @@ anyascii==0.3.1 # via wagtail anyio==3.5.0 # via watchfiles +appnope==0.1.3 + # via ipython argon2-cffi==21.3.0 # via -r requirements.in argon2-cffi-bindings==21.2.0 @@ -29,6 +31,16 @@ attrs==21.4.0 # usort authlib==1.0.0 # via -r requirements.in +azure-core==1.26.4 + # via + # azure-identity + # azure-storage-blob +azure-identity==1.13.0 + # via -r requirements.in +azure-storage-blob==12.16.0 + # via + # -r requirements.in + # django-storages backcall==0.2.0 # via ipython beautifulsoup4==4.9.3 @@ -82,7 +94,12 @@ coverage==6.3.2 # -r requirements-dev.in # django-coverage-plugin cryptography==36.0.2 - # via authlib + # via + # authlib + # azure-identity + # azure-storage-blob + # msal + # pyjwt decorator==5.1.1 # via # ipdb @@ -155,7 +172,7 @@ django-ratelimit==3.0.1 # via -r requirements.in django-redis==5.2.0 # via -r requirements.in -django-storages==1.13.1 +django-storages[azure]==1.13.1 # via -r requirements.in django-stubs==1.10.1 # via @@ -241,6 +258,8 @@ ipdb==0.13.9 # via -r requirements-dev.in ipython==8.2.0 # via ipdb +isodate==0.6.1 + # via azure-storage-blob isort==5.10.1 # via # flake8-isort @@ -281,6 +300,12 @@ moreorless==0.4.0 # via # ufmt # usort +msal==1.22.0 + # via + # azure-identity + # msal-extensions +msal-extensions==1.0.0 + # via azure-identity mypy==0.942 # via # -r requirements-dev.in @@ -330,7 +355,9 @@ pluggy==1.0.0 polib==1.1.1 # via wagtail-localize portalocker==2.4.0 - # via concurrent-log-handler + # via + # concurrent-log-handler + # msal-extensions pre-commit==2.17.0 # via -r requirements-dev.in promise==2.3 @@ -353,6 +380,8 @@ pyflakes==2.4.0 # via flake8 pygments==2.11.2 # via ipython +pyjwt[crypto]==2.7.0 + # via msal pylint==2.13.4 # via # pylint-django @@ -409,9 +438,11 @@ redis==4.2.1 # django-redis requests==2.27.1 # via + # azure-core # caprover-api # coreapi # djangorestframework-stubs + # msal # wagtail s3transfer==0.6.0 # via boto3 @@ -422,8 +453,11 @@ sentry-sdk==1.5.8 six==1.16.0 # via # asttokens + # azure-core + # azure-identity # django-coverage-plugin # html5lib + # isodate # l18n # promise # python-dateutil @@ -490,8 +524,10 @@ types-pytz==2021.3.6 # via django-stubs types-pyyaml==6.0.5 # via django-stubs -typing-extensions==4.1.1 +typing-extensions==4.5.0 # via + # azure-core + # azure-storage-blob # django-stubs # django-stubs-ext # djangorestframework-stubs diff --git a/server/requirements/requirements.in b/server/requirements/requirements.in index cd4615ef..7910d91e 100644 --- a/server/requirements/requirements.in +++ b/server/requirements/requirements.in @@ -25,6 +25,7 @@ django-ratelimit django-ipware django-csp django-storages +django-storages[azure] django-notifications-hq django-jsonform @@ -42,4 +43,7 @@ wagtail-factories>=4 wagtail-localize>=1.5 wagtail_grapple>=0.19.2 +azure-storage-blob +azure-identity + boto3 diff --git a/server/requirements/requirements.txt b/server/requirements/requirements.txt index 230e6b7d..b3015ddd 100644 --- a/server/requirements/requirements.txt +++ b/server/requirements/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: # # pip-compile --output-file=requirements.txt requirements.in # @@ -22,6 +22,16 @@ attrs==21.4.0 # via jsonschema authlib==1.0.0 # via -r requirements.in +azure-core==1.26.4 + # via + # azure-identity + # azure-storage-blob +azure-identity==1.13.0 + # via -r requirements.in +azure-storage-blob==12.16.0 + # via + # -r requirements.in + # django-storages beautifulsoup4==4.9.3 # via wagtail boto3==1.26.11 @@ -50,7 +60,12 @@ click==8.1.1 concurrent-log-handler==0.9.20 # via -r requirements.in cryptography==36.0.2 - # via authlib + # via + # authlib + # azure-identity + # azure-storage-blob + # msal + # pyjwt deprecated==1.2.13 # via redis dj-database-url==1.0.0 @@ -104,7 +119,7 @@ django-ratelimit==3.0.1 # via -r requirements.in django-redis==5.2.0 # via -r requirements.in -django-storages==1.13.1 +django-storages[azure]==1.13.1 # via -r requirements.in django-taggit==2.1.0 # via wagtail @@ -154,6 +169,8 @@ idna==3.3 # requests inflection==0.5.1 # via drf-spectacular +isodate==0.6.1 + # via azure-storage-blob jmespath==1.0.1 # via # boto3 @@ -166,6 +183,12 @@ l18n==2021.3 # via wagtail marshmallow==3.15.0 # via environs +msal==1.22.0 + # via + # azure-identity + # msal-extensions +msal-extensions==1.0.0 + # via azure-identity openpyxl==3.1.2 # via wagtail packaging==21.3 @@ -179,13 +202,17 @@ pillow==9.0.1 polib==1.1.1 # via wagtail-localize portalocker==2.4.0 - # via concurrent-log-handler + # via + # concurrent-log-handler + # msal-extensions promise==2.3 # via graphene-django psycopg2-binary==2.9.3 # via -r requirements.in pycparser==2.21 # via cffi +pyjwt[crypto]==2.7.0 + # via msal pyparsing==3.0.7 # via packaging pyrsistent==0.18.1 @@ -221,7 +248,10 @@ redis==4.2.1 # -r requirements.in # django-redis requests==2.27.1 - # via wagtail + # via + # azure-core + # msal + # wagtail s3transfer==0.6.0 # via boto3 sendgrid==6.9.7 @@ -230,7 +260,10 @@ sentry-sdk==1.5.8 # via -r requirements.in six==1.16.0 # via + # azure-core + # azure-identity # html5lib + # isodate # l18n # promise # python-dateutil @@ -252,8 +285,11 @@ text-unidecode==1.3 # via # graphene-django # python-slugify -typing-extensions==4.2.0 - # via wagtail-localize +typing-extensions==4.5.0 + # via + # azure-core + # azure-storage-blob + # wagtail-localize uritemplate==4.1.1 # via drf-spectacular urllib3==1.26.9 diff --git a/trufflehog-allow.json b/trufflehog-allow.json index c74e9e1d..a183a7c5 100644 --- a/trufflehog-allow.json +++ b/trufflehog-allow.json @@ -5,8 +5,10 @@ "ignore hash 4": "1NpUCSvAKLpDZL9e3tqDaUe8Kk2xAuF1tXosFjBanc4lFCgNcfBp02MD3UjB72ZS", "ignore hash 5": "1LhwZ0DvP4cGBgbBdCfaBQV7eiaOc4jWKdzO9WEXLFT7AaqBN6jqd0uyaZeAZ19K", "ignore hash 6": "A035C8C19219BA821ECEA86B64E628F8D684696D", + "ignore hash 7": "96334b4eb6a7ae5b0d86abd7febcbcc67323bb94", "json base64 content": "regex:\"content\": \"", "img base64 content": "regex:data:image/png;base64,.*", "sentry url": "https://2df6096a4fd94bd6b4802124d10e4b8d@o8544.ingest.sentry.io/4504157846372352", - "git commit": "bdadf52b849bb5fa47854a3094f4da6fe9d54d02" + "git commit": "bdadf52b849bb5fa47854a3094f4da6fe9d54d02", + "customDomainVerificationId": "A2AB57353045150ADA4488FAA8AA9DFBBEDDD311934653F55243B336C2F3358E" }