diff --git a/.aws/task-definition.json b/.aws/task-definition.json index fab0b6f2..2cc01962 100644 --- a/.aws/task-definition.json +++ b/.aws/task-definition.json @@ -1,167 +1,167 @@ -{ - "taskDefinitionArn": "arn:aws:ecs:us-east-1:768512802988:task-definition/appointments-definition:24", - "containerDefinitions": [ - { - "name": "backend", - "image": "backend-latest", - "cpu": 0, - "portMappings": [ - { - "name": "backend-5000-tcp", - "containerPort": 5000, - "hostPort": 5000, - "protocol": "tcp", - "appProtocol": "http" - } - ], - "essential": true, - "environment": [ - { - "name": "FRONTEND_URL", - "value": "https://stage.appointment.day" - }, - { - "name": "SHORT_BASE_URL", - "value": "https://stage.apmt.day" - }, - { - "name": "TIER_BASIC_CALENDAR_LIMIT", - "value": "3" - }, - { - "name": "TIER_PLUS_CALENDAR_LIMIT", - "value": "5" - }, - { - "name": "TIER_PRO_CALENDAR_LIMIT", - "value": "10" - }, - { - "name": "LOG_USE_STREAM", - "value": "True" - }, - { - "name": "LOG_LEVEL", - "value": "INFO" - }, - { - "name": "APP_ENV", - "value": "stage" - }, - { - "name": "SENTRY_DSN", - "value": "https://5dddca3ecc964284bb8008bc2beef808@o4505428107853824.ingest.sentry.io/4505428124827648" - } - ], - "secrets": [ - { - "name": "DATABASE_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-mysql-Ixf6qD" - }, - { - "name": "AUTH0_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/auth0-0gzF6d" - }, - { - "name": "DB_ENC_SECRET", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-secret-CYKglI" - }, - { - "name": "SMTP_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/socketlabs-UYmjaC" - }, - { - "name": "GOOGLE_OAUTH_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/google-cal-oauth-VevaSo" - } - ], - "mountPoints": [], - "volumesFrom": [], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-create-group": "true", - "awslogs-group": "/ecs/appointments-definition", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "ecs" - } - } - }, - { - "name": "frontend", - "image": "frontend-latest", - "cpu": 0, - "portMappings": [ - { - "name": "frontend-80-tcp", - "containerPort": 80, - "hostPort": 80, - "protocol": "tcp", - "appProtocol": "http" - } - ], - "essential": true, - "environment": [], - "mountPoints": [], - "volumesFrom": [], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-create-group": "true", - "awslogs-group": "/ecs/appointments-definition", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "ecs" - } - } - } - ], - "family": "appointments-definition", - "executionRoleArn": "arn:aws:iam::768512802988:role/apointments-ci-role", - "networkMode": "awsvpc", - "revision": 24, - "volumes": [], - "status": "ACTIVE", - "requiresAttributes": [ - { - "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" - }, - { - "name": "ecs.capability.execution-role-awslogs" - }, - { - "name": "com.amazonaws.ecs.capability.ecr-auth" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" - }, - { - "name": "ecs.capability.execution-role-ecr-pull" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" - }, - { - "name": "ecs.capability.task-eni" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29" - } - ], - "placementConstraints": [], - "compatibilities": [ - "EC2", - "FARGATE" - ], - "requiresCompatibilities": [ - "FARGATE" - ], - "cpu": "512", - "memory": "1024", - "runtimePlatform": { - "cpuArchitecture": "X86_64", - "operatingSystemFamily": "LINUX" - }, - "registeredAt": "2023-03-15T22:19:59.642Z", - "registeredBy": "arn:aws:iam::768512802988:user/melissa", - "tags": [] +{ + "taskDefinitionArn": "arn:aws:ecs:us-east-1:768512802988:task-definition/appointments-definition:24", + "containerDefinitions": [ + { + "name": "backend", + "image": "backend-latest", + "cpu": 0, + "portMappings": [ + { + "name": "backend-5000-tcp", + "containerPort": 5000, + "hostPort": 5000, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "environment": [ + { + "name": "FRONTEND_URL", + "value": "https://stage.appointment.day" + }, + { + "name": "SHORT_BASE_URL", + "value": "https://stage.apmt.day" + }, + { + "name": "TIER_BASIC_CALENDAR_LIMIT", + "value": "3" + }, + { + "name": "TIER_PLUS_CALENDAR_LIMIT", + "value": "5" + }, + { + "name": "TIER_PRO_CALENDAR_LIMIT", + "value": "10" + }, + { + "name": "LOG_USE_STREAM", + "value": "True" + }, + { + "name": "LOG_LEVEL", + "value": "INFO" + }, + { + "name": "APP_ENV", + "value": "stage" + }, + { + "name": "SENTRY_DSN", + "value": "https://5dddca3ecc964284bb8008bc2beef808@o4505428107853824.ingest.sentry.io/4505428124827648" + } + ], + "secrets": [ + { + "name": "DATABASE_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-mysql-Ixf6qD" + }, + { + "name": "AUTH0_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/auth0-0gzF6d" + }, + { + "name": "DB_ENC_SECRET", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-secret-CYKglI" + }, + { + "name": "SMTP_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/socketlabs-UYmjaC" + }, + { + "name": "GOOGLE_OAUTH_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/google-cal-oauth-VevaSo" + } + ], + "mountPoints": [], + "volumesFrom": [], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/appointments-definition", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "frontend", + "image": "frontend-latest", + "cpu": 0, + "portMappings": [ + { + "name": "frontend-80-tcp", + "containerPort": 80, + "hostPort": 80, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "environment": [], + "mountPoints": [], + "volumesFrom": [], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/appointments-definition", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } + } + ], + "family": "appointments-definition", + "executionRoleArn": "arn:aws:iam::768512802988:role/apointments-ci-role", + "networkMode": "awsvpc", + "revision": 24, + "volumes": [], + "status": "ACTIVE", + "requiresAttributes": [ + { + "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" + }, + { + "name": "ecs.capability.execution-role-awslogs" + }, + { + "name": "com.amazonaws.ecs.capability.ecr-auth" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" + }, + { + "name": "ecs.capability.execution-role-ecr-pull" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" + }, + { + "name": "ecs.capability.task-eni" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29" + } + ], + "placementConstraints": [], + "compatibilities": [ + "EC2", + "FARGATE" + ], + "requiresCompatibilities": [ + "FARGATE" + ], + "cpu": "512", + "memory": "1024", + "runtimePlatform": { + "cpuArchitecture": "X86_64", + "operatingSystemFamily": "LINUX" + }, + "registeredAt": "2023-03-15T22:19:59.642Z", + "registeredBy": "arn:aws:iam::768512802988:user/melissa", + "tags": [] } \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index a3dff5a5..8e378874 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,15 +1,15 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true - -[*.py] -charset = utf-8 -indent_style = space -indent_size = 4 - -[*.{vue,html,css,js,json,yml}] -charset = utf-8 -indent_style = space -indent_size = 2 +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.py] +charset = utf-8 +indent_style = space +indent_size = 4 + +[*.{vue,html,css,js,json,yml}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ca08eaa4..96c7e601 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,31 +1,31 @@ ---- -name: Bug report -labels: bug -about: Create a report to help us improve - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**System (please complete the following information):** - -- OS: [e.g. Windows 10] -- Browser Version [e.g. Firefox 114.0b8 (64-Bit)] - -**Additional context** -Add any other context about the problem here. +--- +name: Bug report +labels: bug +about: Create a report to help us improve + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**System (please complete the following information):** + +- OS: [e.g. Windows 10] +- Browser Version [e.g. Firefox 114.0b8 (64-Bit)] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3ba13e0c..ac2e8b47 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1 @@ -blank_issues_enabled: false +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index d3b8683a..cfedea62 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,18 +1,18 @@ ---- -name: Feature request -labels: enhancement -about: Suggest an idea for this project - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. +--- +name: Feature request +labels: enhancement +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7ddc6c56..d0c67874 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,16 +1,16 @@ - - -## Description of the Change - - - -## Benefits - - - -## Applicable Issues - - + + +## Description of the Change + + + +## Benefits + + + +## Applicable Issues + + diff --git a/.github/workflows/aws.yml b/.github/workflows/aws.yml index 28a11ead..61582104 100644 --- a/.github/workflows/aws.yml +++ b/.github/workflows/aws.yml @@ -1,99 +1,99 @@ -# This workflow will build and push a new container image to Amazon ECR, -# and then will deploy a new task definition to Amazon ECS, when there is a push to the "staging" branch. - -name: Deploy to Stage Environment - -# Stop any pending jobs -concurrency: - group: staging - cancel-in-progress: true - -on: - push: - branches: [ "stage" ] - -env: - AWS_REGION: us-east-1 - ECR_REPOSITORY: appointments - ECS_SERVICE: appointments-service - ECS_CLUSTER: appointments - ECS_TASK_DEFINITION: .aws/task-definition.json - - CONTAINER_FRONTEND: frontend - CONTAINER_BACKEND: backend - -permissions: - contents: read - -jobs: - deploy: - name: Build & Deploy - runs-on: ubuntu-latest - environment: - name: staging - url: https://stage.appointment.day - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ env.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push backend to Amazon ECR - id: build-backend - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: backend-${{ github.sha }} - run: | - # Build a docker container and - # push it to ECR so that it can - # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./backend -f ./backend/deploy.dockerfile - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - echo "image_backend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - - name: Build, tag, and push frontend to Amazon ECR - id: build-frontend - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: frontend-${{ github.sha }} - run: | - # Build a docker container and - # push it to ECR so that it can - # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./frontend -f ./frontend/deploy.dockerfile - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - echo "image_frontend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - - name: Fill in the new backend image ID in the Amazon ECS task definition - id: task-def-backend - uses: aws-actions/amazon-ecs-render-task-definition@v1 - with: - task-definition: ${{ env.ECS_TASK_DEFINITION }} - container-name: ${{ env.CONTAINER_BACKEND }} - image: ${{ steps.build-backend.outputs.image_backend }} - - - name: Fill in the new frontend image ID in the Amazon ECS task definition - id: task-def-frontend - uses: aws-actions/amazon-ecs-render-task-definition@v1 - with: - task-definition: ${{ steps.task-def-backend.outputs.task-definition }} - container-name: ${{ env.CONTAINER_FRONTEND }} - image: ${{ steps.build-frontend.outputs.image_frontend }} - - - name: Deploy Amazon ECS task definition - uses: aws-actions/amazon-ecs-deploy-task-definition@v1 - with: - task-definition: ${{ steps.task-def-frontend.outputs.task-definition }} - service: ${{ env.ECS_SERVICE }} - cluster: ${{ env.ECS_CLUSTER }} - wait-for-service-stability: true +# This workflow will build and push a new container image to Amazon ECR, +# and then will deploy a new task definition to Amazon ECS, when there is a push to the "staging" branch. + +name: Deploy to Stage Environment + +# Stop any pending jobs +concurrency: + group: staging + cancel-in-progress: true + +on: + push: + branches: [ "stage" ] + +env: + AWS_REGION: us-east-1 + ECR_REPOSITORY: appointments + ECS_SERVICE: appointments-service + ECS_CLUSTER: appointments + ECS_TASK_DEFINITION: .aws/task-definition.json + + CONTAINER_FRONTEND: frontend + CONTAINER_BACKEND: backend + +permissions: + contents: read + +jobs: + deploy: + name: Build & Deploy + runs-on: ubuntu-latest + environment: + name: staging + url: https://stage.appointment.day + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push backend to Amazon ECR + id: build-backend + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: backend-${{ github.sha }} + run: | + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./backend -f ./backend/deploy.dockerfile + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image_backend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Build, tag, and push frontend to Amazon ECR + id: build-frontend + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: frontend-${{ github.sha }} + run: | + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./frontend -f ./frontend/deploy.dockerfile + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image_frontend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Fill in the new backend image ID in the Amazon ECS task definition + id: task-def-backend + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ env.ECS_TASK_DEFINITION }} + container-name: ${{ env.CONTAINER_BACKEND }} + image: ${{ steps.build-backend.outputs.image_backend }} + + - name: Fill in the new frontend image ID in the Amazon ECS task definition + id: task-def-frontend + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ steps.task-def-backend.outputs.task-definition }} + container-name: ${{ env.CONTAINER_FRONTEND }} + image: ${{ steps.build-frontend.outputs.image_frontend }} + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def-frontend.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/backend/.env.example b/backend/.env.example index 0c2ed570..2e009756 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,74 +1,74 @@ -# Appointment backend configuration. - -# -- GENERAL -- -# Logging level: DEBUG|INFO|WARNING|ERROR|CRITICAL -LOG_LEVEL=ERROR -LOG_USE_STREAM=1 - -# -- FRONTEND -- -FRONTEND_URL=http://localhost:8080 -# Leave blank for no short url -SHORT_BASE_URL= - -# -- DATABASE -- -DATABASE_URL= -DATABASE_SECRETS= -# Secret phrase for database encryption (e.g. create it by running `openssl rand -hex 32`) -DB_SECRET= - -# -- AUTH0 -- -# Management API -AUTH0_API_CLIENT_ID= -AUTH0_API_SECRET= -# Auth API -AUTH0_API_DOMAIN= -AUTH0_API_AUDIENCE= -# Role keys, configurable in Auth0 User Management -> Roles -AUTH0_API_ROLE_ADMIN= -AUTH0_API_ROLE_BASIC= -AUTH0_API_ROLE_PLUS= -AUTH0_API_ROLE_PRO= - -# -- MAIL -- -# Connection security: SSL|STARTTLS|NONE -SMTP_SECURITY=SSL -# Address and port of the SMTP server -SMTP_URL= -SMTP_PORT= -# SMTP user credentials -SMTP_USER= -SMTP_PASS= -# Authorized email address for sending emails -SMTP_SENDER= - -# -- TIERS -- -# Max number of calendars to be simultanously connected for members of the basic tier -TIER_BASIC_CALENDAR_LIMIT=3 -# Max number of calendars to be simultanously connected for members of the plus tier -TIER_PLUS_CALENDAR_LIMIT=5 -# Max number of calendars to be simultanously connected for members of the pro tier -TIER_PRO_CALENDAR_LIMIT=10 - -# -- GOOGLE AUTH -- -GOOGLE_AUTH_CLIENT_ID= -GOOGLE_AUTH_SECRET= -GOOGLE_AUTH_PROJECT_ID= -GOOGLE_AUTH_CALLBACK=http://localhost:5000/google/callback - -# -- SIGNED URL SECRET -- -# Shared secret for url signing (e.g. create it by running `openssl rand -hex 32`) -SIGNED_SECRET= -# If empty, sentry will be disabled -SENTRY_DSN= -# Possible values: prod, dev -APP_ENV=dev - -# -- TESTING -- -AUTH0_TEST_USER= -AUTH0_TEST_PASS= -CALDAV_TEST_PRINCIPAL_URL= -CALDAV_TEST_CALENDAR_URL= -CALDAV_TEST_USER= -CALDAV_TEST_PASS= -GOOGLE_TEST_USER= -GOOGLE_TEST_PASS= +# Appointment backend configuration. + +# -- GENERAL -- +# Logging level: DEBUG|INFO|WARNING|ERROR|CRITICAL +LOG_LEVEL=ERROR +LOG_USE_STREAM=1 + +# -- FRONTEND -- +FRONTEND_URL=http://localhost:8080 +# Leave blank for no short url +SHORT_BASE_URL= + +# -- DATABASE -- +DATABASE_URL= +DATABASE_SECRETS= +# Secret phrase for database encryption (e.g. create it by running `openssl rand -hex 32`) +DB_SECRET= + +# -- AUTH0 -- +# Management API +AUTH0_API_CLIENT_ID= +AUTH0_API_SECRET= +# Auth API +AUTH0_API_DOMAIN= +AUTH0_API_AUDIENCE= +# Role keys, configurable in Auth0 User Management -> Roles +AUTH0_API_ROLE_ADMIN= +AUTH0_API_ROLE_BASIC= +AUTH0_API_ROLE_PLUS= +AUTH0_API_ROLE_PRO= + +# -- MAIL -- +# Connection security: SSL|STARTTLS|NONE +SMTP_SECURITY=SSL +# Address and port of the SMTP server +SMTP_URL= +SMTP_PORT= +# SMTP user credentials +SMTP_USER= +SMTP_PASS= +# Authorized email address for sending emails +SMTP_SENDER= + +# -- TIERS -- +# Max number of calendars to be simultanously connected for members of the basic tier +TIER_BASIC_CALENDAR_LIMIT=3 +# Max number of calendars to be simultanously connected for members of the plus tier +TIER_PLUS_CALENDAR_LIMIT=5 +# Max number of calendars to be simultanously connected for members of the pro tier +TIER_PRO_CALENDAR_LIMIT=10 + +# -- GOOGLE AUTH -- +GOOGLE_AUTH_CLIENT_ID= +GOOGLE_AUTH_SECRET= +GOOGLE_AUTH_PROJECT_ID= +GOOGLE_AUTH_CALLBACK=http://localhost:5000/google/callback + +# -- SIGNED URL SECRET -- +# Shared secret for url signing (e.g. create it by running `openssl rand -hex 32`) +SIGNED_SECRET= +# If empty, sentry will be disabled +SENTRY_DSN= +# Possible values: prod, dev +APP_ENV=dev + +# -- TESTING -- +AUTH0_TEST_USER= +AUTH0_TEST_PASS= +CALDAV_TEST_PRINCIPAL_URL= +CALDAV_TEST_CALENDAR_URL= +CALDAV_TEST_USER= +CALDAV_TEST_PASS= +GOOGLE_TEST_USER= +GOOGLE_TEST_PASS= diff --git a/backend/Dockerfile b/backend/Dockerfile index 473c5c7d..dfe1219f 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,23 +1,23 @@ -FROM python:3.11-buster - -RUN mkdir app -WORKDIR /app - -ENV PATH="${PATH}:/root/.local/bin" -ENV PYTHONPATH=. - -RUN mkdir scripts - -COPY requirements.txt . -COPY pyproject.toml . -COPY alembic.ini.example alembic.ini -COPY scripts/dev-entry.sh scripts/dev-entry.sh - -# Dev only -COPY .env . - -RUN pip install --upgrade pip -RUN pip install . - -EXPOSE 5000 +FROM python:3.11-buster + +RUN mkdir app +WORKDIR /app + +ENV PATH="${PATH}:/root/.local/bin" +ENV PYTHONPATH=. + +RUN mkdir scripts + +COPY requirements.txt . +COPY pyproject.toml . +COPY alembic.ini.example alembic.ini +COPY scripts/dev-entry.sh scripts/dev-entry.sh + +# Dev only +COPY .env . + +RUN pip install --upgrade pip +RUN pip install . + +EXPOSE 5000 CMD ["/bin/sh", "./scripts/dev-entry.sh"] \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt old mode 100755 new mode 100644 index 8c4b4fd5..245af1f1 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,19 +1,19 @@ -alembic==1.9.3 -auth0-python==4.0.0 -caldav==1.0.1 -cryptography==39.0.1 -fastapi-auth0==0.3.2 -fastapi==0.91.0 -google-api-python-client==2.85.0 -google-auth-httplib2==0.1.0 -google-auth-oauthlib==1.0.0 -jinja2==3.1.2 -icalendar==5.0.4 -mysqlclient==2.1.1 -mysql-connector-python==8.0.32 -python-dotenv==1.0.0 -sentry-sdk==1.26.0 -sqlalchemy-utils==0.39.0 -sqlalchemy==1.4.40 -uvicorn==0.20.0 -validators==0.20.0 +alembic==1.9.3 +auth0-python==4.0.0 +caldav==1.0.1 +cryptography==39.0.1 +fastapi-auth0==0.3.2 +fastapi==0.91.0 +google-api-python-client==2.85.0 +google-auth-httplib2==0.1.0 +google-auth-oauthlib==1.0.0 +jinja2==3.1.2 +icalendar==5.0.4 +mysqlclient==2.1.1 +mysql-connector-python==8.0.32 +python-dotenv==1.0.0 +sentry-sdk==1.26.0 +sqlalchemy-utils==0.39.0 +sqlalchemy==1.4.40 +uvicorn==0.20.0 +validators==0.20.0 diff --git a/backend/scripts/dev-entry.sh b/backend/scripts/dev-entry.sh old mode 100755 new mode 100644 diff --git a/backend/scripts/entry.sh b/backend/scripts/entry.sh old mode 100755 new mode 100644 diff --git a/backend/src/appointment/main.py b/backend/src/appointment/main.py old mode 100755 new mode 100644 diff --git a/backend/src/appointment/templates/email/confirm.jinja2 b/backend/src/appointment/templates/email/confirm.jinja2 index 33915edc..de43f357 100644 --- a/backend/src/appointment/templates/email/confirm.jinja2 +++ b/backend/src/appointment/templates/email/confirm.jinja2 @@ -1,38 +1,38 @@ - -
-- {{ attendee.name|title }} ({{ attendee.email }}) just requested this time slot from your schedule: {{ date }}. -
-
- Click here to confirm the booking request:
- Confirm Booking
-
- Or here if you want to deny it:
- Deny Booking
-
- This message is sent from Thunderbird Appointment. -
- - + + ++ {{ attendee.name|title }} ({{ attendee.email }}) just requested this time slot from your schedule: {{ date }}. +
+
+ Click here to confirm the booking request:
+ Confirm Booking
+
+ Or here if you want to deny it:
+ Deny Booking
+
+ This message is sent from Thunderbird Appointment. +
+ + diff --git a/backend/src/appointment/templates/email/invite.jinja2 b/backend/src/appointment/templates/email/invite.jinja2 index 0cb90875..932ce49c 100644 --- a/backend/src/appointment/templates/email/invite.jinja2 +++ b/backend/src/appointment/templates/email/invite.jinja2 @@ -1,5 +1,5 @@ - - -This message is sent from Appointment.
- + + +This message is sent from Appointment.
+ \ No newline at end of file diff --git a/backend/src/appointment/tmp/.gitignore b/backend/src/appointment/tmp/.gitignore index a6c57f5f..933daa68 100644 --- a/backend/src/appointment/tmp/.gitignore +++ b/backend/src/appointment/tmp/.gitignore @@ -1 +1 @@ -*.json +*.json diff --git a/frontend/.env.example b/frontend/.env.example index 555a6525..582f788b 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,18 +1,18 @@ -# Appointment frontend configuration. - -# -- Frontend -- -VUE_APP_BASE_URL=localhost:8080 -VUE_APP_SHORT_BASE_URL=localhost:8080/user - -# -- Backend API -- -VUE_APP_API_URL=localhost -VUE_APP_API_PORT=8090 -VUE_APP_API_SECURE=false - -# -- Auth0 -- -VUE_APP_AUTH0_DOMAIN= -VUE_APP_AUTH0_CLIENT_ID= -VUE_APP_AUTH0_AUDIENCE= - -# -- Sentry -- -VUE_APP_SENTRY_DSN= +# Appointment frontend configuration. + +# -- Frontend -- +VUE_APP_BASE_URL=localhost:8080 +VUE_APP_SHORT_BASE_URL=localhost:8080/user + +# -- Backend API -- +VUE_APP_API_URL=localhost +VUE_APP_API_PORT=8090 +VUE_APP_API_SECURE=false + +# -- Auth0 -- +VUE_APP_AUTH0_DOMAIN= +VUE_APP_AUTH0_CLIENT_ID= +VUE_APP_AUTH0_AUDIENCE= + +# -- Sentry -- +VUE_APP_SENTRY_DSN= diff --git a/frontend/.env.staging.example b/frontend/.env.staging.example index 2a707c36..1133075f 100644 --- a/frontend/.env.staging.example +++ b/frontend/.env.staging.example @@ -1,9 +1,9 @@ -# Production env config, do not put secrets in here !! -VUE_APP_API_URL=stage.appointment.day/api/v1/ -VUE_APP_BASE_URL=stage.appointment.day -VUE_APP_API_SECURE=true -VUE_APP_SHORT_BASE_URL=https://stage.apmt.day - -VUE_APP_AUTH0_DOMAIN=thunderbird.eu.auth0.com -VUE_APP_AUTH0_CLIENT_ID=Dvw6O6hPwXg7jZD7p7yAAnLXR2PXiQHF -VUE_APP_AUTH0_AUDIENCE=http://127.0.0.1:8000/ +# Production env config, do not put secrets in here !! +VUE_APP_API_URL=stage.appointment.day/api/v1/ +VUE_APP_BASE_URL=stage.appointment.day +VUE_APP_API_SECURE=true +VUE_APP_SHORT_BASE_URL=https://stage.apmt.day + +VUE_APP_AUTH0_DOMAIN=thunderbird.eu.auth0.com +VUE_APP_AUTH0_CLIENT_ID=Dvw6O6hPwXg7jZD7p7yAAnLXR2PXiQHF +VUE_APP_AUTH0_AUDIENCE=http://127.0.0.1:8000/ diff --git a/frontend/.eslintignore b/frontend/.eslintignore index 466c1d81..27160a72 100644 --- a/frontend/.eslintignore +++ b/frontend/.eslintignore @@ -1,4 +1,4 @@ -src/assets -src/elements/arts -src/locales +src/assets +src/elements/arts +src/locales node_modules \ No newline at end of file diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index d7fa82a2..23174004 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -1,34 +1,34 @@ -module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: [ - 'plugin:vue/vue3-essential', - 'airbnb-base', - ], - overrides: [], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - plugins: [ - 'vue', - ], - rules: { - 'import/extensions': ['error', 'ignorePackages', { - '': 'never', - js: 'never', - vue: 'off', // TODO: once migrated to Vite, we should set this to 'always' - }], - 'max-len': ['error', { code: 120 }], - 'no-param-reassign': 'off', - }, - settings: { - 'import/resolver': { - webpack: { - config: require.resolve('@vue/cli-service/webpack.config.js'), - }, - }, - }, -}; +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + 'plugin:vue/vue3-essential', + 'airbnb-base', + ], + overrides: [], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: [ + 'vue', + ], + rules: { + 'import/extensions': ['error', 'ignorePackages', { + '': 'never', + js: 'never', + vue: 'off', // TODO: once migrated to Vite, we should set this to 'always' + }], + 'max-len': ['error', { code: 120 }], + 'no-param-reassign': 'off', + }, + settings: { + 'import/resolver': { + webpack: { + config: require.resolve('@vue/cli-service/webpack.config.js'), + }, + }, + }, +}; diff --git a/frontend/.gitignore b/frontend/.gitignore old mode 100755 new mode 100644 index 694a5904..90f89baa --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,24 +1,24 @@ -.DS_Store -node_modules -/dist -.yarn - - -# local env files -.env.local -.env.*.local - -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# Editor directories and files -.idea -.vscode -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +.DS_Store +node_modules +/dist +.yarn + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 6294c3ca..e2bf6d97 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,13 +1,13 @@ -FROM node:lts-alpine - -WORKDIR /app - -ENV PATH /app/node_modules/.bin:$PATH - -# Get git -RUN apk add --no-cache git - -COPY . . -RUN yarn install - +FROM node:lts-alpine + +WORKDIR /app + +ENV PATH /app/node_modules/.bin:$PATH + +# Get git +RUN apk add --no-cache git + +COPY . . +RUN yarn install + CMD vue-cli-service serve \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md old mode 100755 new mode 100644 diff --git a/frontend/docker/etc/nginx/conf.d/appointments.conf b/frontend/docker/etc/nginx/conf.d/appointments.conf index fe3c3c97..f1865df5 100644 --- a/frontend/docker/etc/nginx/conf.d/appointments.conf +++ b/frontend/docker/etc/nginx/conf.d/appointments.conf @@ -1,44 +1,44 @@ -server { - listen 80; - listen [::]:80; - server_name localhost; - - #access_log /var/log/nginx/host.access.log main; - - # Backend API proxy - location ^~ /api/v1/ { - # Remove our fake /api/v1/ prefix for FastAPI - rewrite ^/api/v1/(.*)$ /$1 break; - proxy_pass http://127.0.0.1:5000; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_http_version 1.1; - } - # Frontend Vue static files - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - #auth_basic "Restricted Content"; - #auth_basic_user_file /etc/nginx/.htpasswd; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - #error_page 500 502 503 504 /50x.html; - #location = /50x.html { - # root /usr/share/nginx/html; - #} -} - -# Stage Shortlink Redirect -server { - listen 80; - listen [::]:80; - server_name stage.apmt.local stage.apmt.day; - location / { - # Transform stage.apmt.day/