From e7ba9255dffab23677013b0dc7db022d8dc4825f Mon Sep 17 00:00:00 2001 From: Melissa Autumn Date: Mon, 2 Oct 2023 15:19:37 -0700 Subject: [PATCH] Change how the backend and database migrations are structured (Fixes #119) - BREAKING: Added `appointment` module folder in `src`. - BREAKING: alembic.ini should now be placed in the backend root folder. You will need to grab a fresh copy as there's been additional changes. - Added a super simple cli interface handled by main.py - Adjusted main.py to bootstrap either a fast api server or a cli interface. - Added a `update-db` command that is installed when pip install this module. - The `update-db` command will initialize a fresh database or run migrations, resolving most of our database woes. - New folder structure more closely matches the deployed folder structure for easier deployments. - Local docker now only mounts the `src` folder - Commented out some non-existent columns/constraints in a recent migration - Added missing trailing slash to the frontend for `schedule/` - Added sentry support to migrations - Adjusted code-referenced folder locations as required --- .gitignore | 1 + backend/Dockerfile | 14 ++- backend/{src => }/alembic.ini.example | 4 +- backend/deploy.dockerfile | 20 +++-- backend/pyproject.toml | 3 + backend/scripts/dev-entry.sh | 9 +- backend/scripts/entry.sh | 9 +- backend/src/appointment/commands/update_db.py | 37 ++++++++ .../src/{ => appointment}/controller/auth.py | 0 .../{ => appointment}/controller/calendar.py | 0 .../src/{ => appointment}/controller/data.py | 0 .../controller/google_client.py | 0 .../{ => appointment}/controller/mailer.py | 2 +- .../{ => appointment}/database/database.py | 0 .../src/{ => appointment}/database/models.py | 0 .../src/{ => appointment}/database/repo.py | 0 .../src/{ => appointment}/database/schemas.py | 0 .../{ => appointment}/dependencies/auth.py | 0 .../dependencies/database.py | 0 .../{ => appointment}/dependencies/google.py | 0 .../src/{ => appointment}/download_readme.py | 0 .../exceptions/account_api.py | 0 .../exceptions/google_api.py | 0 backend/src/{ => appointment}/main.py | 88 +++++++++++-------- .../src/{ => appointment}/migrations/env.py | 13 +++ .../migrations/script.py.mako | 0 ...03-eb50007f7a21_change_subscriber_table.py | 0 ..._25_1303-5aec90d60d85_calendar_provider.py | 0 ...4_26_1452-d9ecfcaf83a6_add_google_token.py | 0 ...7_1633-81ace90a911b_add_google_state_id.py | 0 ...201-da069f44bca7_add_calendar_connected.py | 0 ...0_2216-845089644770_add_short_link_hash.py | 0 ...871710e_add_general_availability_tables.py | 0 ...102-f9c5471478d0_modify_schedules_table.py | 4 +- ...157-3789c9fd57c5_extend_schedules_table.py | 0 .../src/{ => appointment}/routes/account.py | 0 backend/src/{ => appointment}/routes/api.py | 0 .../src/{ => appointment}/routes/google.py | 0 .../src/{ => appointment}/routes/schedule.py | 0 backend/src/{ => appointment}/secrets.py | 0 .../templates/email/invite.jinja2 | 0 backend/src/{ => appointment}/tmp/.gitignore | 0 docker-compose.yml | 6 +- .../docker/etc/nginx/conf.d/appointments.conf | 2 +- frontend/src/views/ScheduleView.vue | 3 +- 45 files changed, 147 insertions(+), 68 deletions(-) rename backend/{src => }/alembic.ini.example (97%) create mode 100644 backend/src/appointment/commands/update_db.py rename backend/src/{ => appointment}/controller/auth.py (100%) rename backend/src/{ => appointment}/controller/calendar.py (100%) rename backend/src/{ => appointment}/controller/data.py (100%) rename backend/src/{ => appointment}/controller/google_client.py (100%) rename backend/src/{ => appointment}/controller/mailer.py (98%) rename backend/src/{ => appointment}/database/database.py (100%) rename backend/src/{ => appointment}/database/models.py (100%) rename backend/src/{ => appointment}/database/repo.py (100%) rename backend/src/{ => appointment}/database/schemas.py (100%) rename backend/src/{ => appointment}/dependencies/auth.py (100%) rename backend/src/{ => appointment}/dependencies/database.py (100%) rename backend/src/{ => appointment}/dependencies/google.py (100%) rename backend/src/{ => appointment}/download_readme.py (100%) rename backend/src/{ => appointment}/exceptions/account_api.py (100%) rename backend/src/{ => appointment}/exceptions/google_api.py (100%) rename backend/src/{ => appointment}/main.py (52%) rename backend/src/{ => appointment}/migrations/env.py (84%) rename backend/src/{ => appointment}/migrations/script.py.mako (100%) rename backend/src/{ => appointment}/migrations/versions/2023_04_05_1703-eb50007f7a21_change_subscriber_table.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_04_25_1303-5aec90d60d85_calendar_provider.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_04_26_1452-d9ecfcaf83a6_add_google_token.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_04_27_1633-81ace90a911b_add_google_state_id.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_06_08_2201-da069f44bca7_add_calendar_connected.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_06_20_2216-845089644770_add_short_link_hash.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_06_27_1108-f9660871710e_add_general_availability_tables.py (100%) rename backend/src/{ => appointment}/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py (94%) rename backend/src/{ => appointment}/migrations/versions/2023_09_22_1157-3789c9fd57c5_extend_schedules_table.py (100%) rename backend/src/{ => appointment}/routes/account.py (100%) rename backend/src/{ => appointment}/routes/api.py (100%) rename backend/src/{ => appointment}/routes/google.py (100%) rename backend/src/{ => appointment}/routes/schedule.py (100%) rename backend/src/{ => appointment}/secrets.py (100%) rename backend/src/{ => appointment}/templates/email/invite.jinja2 (100%) rename backend/src/{ => appointment}/tmp/.gitignore (100%) diff --git a/.gitignore b/.gitignore index 09fc95a2..026e248e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist *.pickle .env venv +.idea \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index 96640e5c..473c5c7d 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,10 +6,18 @@ WORKDIR /app ENV PATH="${PATH}:/root/.local/bin" ENV PYTHONPATH=. +RUN mkdir scripts + COPY requirements.txt . -RUN pip install --upgrade pip -RUN pip install -r requirements.txt +COPY pyproject.toml . +COPY alembic.ini.example alembic.ini +COPY scripts/dev-entry.sh scripts/dev-entry.sh -COPY src/ . +# 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/src/alembic.ini.example b/backend/alembic.ini.example similarity index 97% rename from backend/src/alembic.ini.example rename to backend/alembic.ini.example index ac0e6d73..a3fdec17 100644 --- a/backend/src/alembic.ini.example +++ b/backend/alembic.ini.example @@ -2,7 +2,7 @@ [alembic] # path to migration scripts -script_location = migrations +script_location = src/appointment/migrations # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s # Uncomment the line below if you want the files to be prepended with date and time @@ -12,7 +12,7 @@ file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(re # sys.path path, will be prepended to sys.path if present. # defaults to the current working directory. -prepend_sys_path = . +prepend_sys_path = src/appointment # timezone to use when rendering the date within the migration file # as well as the filename. diff --git a/backend/deploy.dockerfile b/backend/deploy.dockerfile index 616cd801..5c84d88b 100644 --- a/backend/deploy.dockerfile +++ b/backend/deploy.dockerfile @@ -6,14 +6,24 @@ WORKDIR /app ENV PATH="${PATH}:/root/.local/bin" ENV PYTHONPATH=. +RUN mkdir scripts + COPY requirements.txt . -RUN pip install --upgrade pip -RUN pip install -r requirements.txt +COPY pyproject.toml . +COPY alembic.ini.example alembic.ini +COPY scripts/entry.sh scripts/entry.sh -COPY src/ ./src -COPY scripts/ ./scripts +# Needed for deploy, we don't have a volume attached +COPY src . + +RUN pip install --upgrade pip +RUN pip install . -RUN cp ./src/alembic.ini.example ./src/alembic.ini +# install removes the src file and installs the application as /app/appointment +# that's fine, but uhh let's add this hack to line it up with our dev environment. +# I'll buy whoever fixes this a coffee. +RUN mkdir src +RUN ln -s /app/appointment src/appointment EXPOSE 5000 CMD ["/bin/sh", "./scripts/entry.sh"] \ No newline at end of file diff --git a/backend/pyproject.toml b/backend/pyproject.toml index ff513445..72d7982e 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -5,6 +5,9 @@ description = "Backend component to Thunderbird Appointment" requires-python = ">3.10" dynamic = ["dependencies"] +[project.scripts] +run-command = "src.appointment.main:cli" + [project.urls] homepage = "https://appointment.day" repository = "https://github.com/thundernest/appointment.git" diff --git a/backend/scripts/dev-entry.sh b/backend/scripts/dev-entry.sh index 4319d935..6a69b985 100755 --- a/backend/scripts/dev-entry.sh +++ b/backend/scripts/dev-entry.sh @@ -1,10 +1,5 @@ #!/bin/sh -cd src -echo 'Starting migrations...' -alembic current -alembic upgrade head -echo 'Finished migrations!' -cd ../ +run-command update-db -uvicorn src.main:app --reload --host 0.0.0.0 --port 8090 \ No newline at end of file +uvicorn --factory src.appointment.main:server --reload --host 0.0.0.0 --port 8090 \ No newline at end of file diff --git a/backend/scripts/entry.sh b/backend/scripts/entry.sh index 0264377e..22ddedfa 100755 --- a/backend/scripts/entry.sh +++ b/backend/scripts/entry.sh @@ -1,10 +1,5 @@ #!/bin/sh -cd src -echo 'Starting migrations...' -alembic current -alembic upgrade head -echo 'Finished migrations!' -cd ../ +run-command update-db -uvicorn src.main:app --host 0.0.0.0 --port 5000 \ No newline at end of file +uvicorn --factory src.appointment.main:server --host 0.0.0.0 --port 5000 \ No newline at end of file diff --git a/backend/src/appointment/commands/update_db.py b/backend/src/appointment/commands/update_db.py new file mode 100644 index 00000000..03457ceb --- /dev/null +++ b/backend/src/appointment/commands/update_db.py @@ -0,0 +1,37 @@ +import os + +from ..database import models +from ..database.database import engine +from alembic.runtime import migration + + +def run(): + print("Checking if we have a fresh database...") + + # then, load the Alembic configuration and generate the + # version table, "stamping" it with the most recent rev: + from alembic import command + from alembic.config import Config + + # TODO: Does this work on stage? + alembic_cfg = Config("./alembic.ini") + + # If we have our database url env variable set, use that instead! + if os.getenv("DATABASE_URL"): + alembic_cfg.set_main_option("sqlalchemy.url", os.getenv("DATABASE_URL")) + + with engine.begin() as connection: + context = migration.MigrationContext.configure(connection) + # Returns a tuple, empty if there's no revisions saved + revisions = context.get_current_heads() + + # If we have no revisions, then fully create the database from the model metadata, + # and set our revision number to the latest revision. Otherwise run any new migrations + if len(revisions) == 0: + print("Initializing database, and setting it to the latest revision") + models.Base.metadata.create_all(bind=engine) + command.stamp(alembic_cfg, "head") + else: + print("Database already initialized, running migrations") + command.upgrade(alembic_cfg, 'head') + diff --git a/backend/src/controller/auth.py b/backend/src/appointment/controller/auth.py similarity index 100% rename from backend/src/controller/auth.py rename to backend/src/appointment/controller/auth.py diff --git a/backend/src/controller/calendar.py b/backend/src/appointment/controller/calendar.py similarity index 100% rename from backend/src/controller/calendar.py rename to backend/src/appointment/controller/calendar.py diff --git a/backend/src/controller/data.py b/backend/src/appointment/controller/data.py similarity index 100% rename from backend/src/controller/data.py rename to backend/src/appointment/controller/data.py diff --git a/backend/src/controller/google_client.py b/backend/src/appointment/controller/google_client.py similarity index 100% rename from backend/src/controller/google_client.py rename to backend/src/appointment/controller/google_client.py diff --git a/backend/src/controller/mailer.py b/backend/src/appointment/controller/mailer.py similarity index 98% rename from backend/src/controller/mailer.py rename to backend/src/appointment/controller/mailer.py index d33b2814..c180655f 100644 --- a/backend/src/controller/mailer.py +++ b/backend/src/appointment/controller/mailer.py @@ -17,7 +17,7 @@ from email.mime.text import MIMEText from fastapi.templating import Jinja2Templates -templates = Jinja2Templates("src/templates/email") +templates = Jinja2Templates("src/appointment/templates/email") def get_template(template_name) -> "jinja2.Template": diff --git a/backend/src/database/database.py b/backend/src/appointment/database/database.py similarity index 100% rename from backend/src/database/database.py rename to backend/src/appointment/database/database.py diff --git a/backend/src/database/models.py b/backend/src/appointment/database/models.py similarity index 100% rename from backend/src/database/models.py rename to backend/src/appointment/database/models.py diff --git a/backend/src/database/repo.py b/backend/src/appointment/database/repo.py similarity index 100% rename from backend/src/database/repo.py rename to backend/src/appointment/database/repo.py diff --git a/backend/src/database/schemas.py b/backend/src/appointment/database/schemas.py similarity index 100% rename from backend/src/database/schemas.py rename to backend/src/appointment/database/schemas.py diff --git a/backend/src/dependencies/auth.py b/backend/src/appointment/dependencies/auth.py similarity index 100% rename from backend/src/dependencies/auth.py rename to backend/src/appointment/dependencies/auth.py diff --git a/backend/src/dependencies/database.py b/backend/src/appointment/dependencies/database.py similarity index 100% rename from backend/src/dependencies/database.py rename to backend/src/appointment/dependencies/database.py diff --git a/backend/src/dependencies/google.py b/backend/src/appointment/dependencies/google.py similarity index 100% rename from backend/src/dependencies/google.py rename to backend/src/appointment/dependencies/google.py diff --git a/backend/src/download_readme.py b/backend/src/appointment/download_readme.py similarity index 100% rename from backend/src/download_readme.py rename to backend/src/appointment/download_readme.py diff --git a/backend/src/exceptions/account_api.py b/backend/src/appointment/exceptions/account_api.py similarity index 100% rename from backend/src/exceptions/account_api.py rename to backend/src/appointment/exceptions/account_api.py diff --git a/backend/src/exceptions/google_api.py b/backend/src/appointment/exceptions/google_api.py similarity index 100% rename from backend/src/exceptions/google_api.py rename to backend/src/appointment/exceptions/google_api.py diff --git a/backend/src/main.py b/backend/src/appointment/main.py similarity index 52% rename from backend/src/main.py rename to backend/src/appointment/main.py index 67ebaae9..8dd6b1c9 100755 --- a/backend/src/main.py +++ b/backend/src/appointment/main.py @@ -48,21 +48,6 @@ logging.debug("Logger started!") -# database -from .database import models -from .database.database import engine - -models.Base.metadata.create_all(bind=engine) - -# extra routes -from .routes import api -from .routes import account -from .routes import google -from .routes import schedule - -# init app -app = FastAPI() - if os.getenv("SENTRY_DSN") != "" or os.getenv("SENTRY_DSN") is not None: sentry_sdk.init( dsn=os.getenv("SENTRY_DSN"), @@ -73,29 +58,58 @@ environment=os.getenv("APP_ENV", "dev"), ) -# allow requests from own frontend running on a different port -app.add_middleware( - CORSMiddleware, - # Work around for now :) - allow_origins=[ - os.getenv("FRONTEND_URL", "http://localhost:8080"), - "https://accounts.google.com", - "https://www.googleapis.com/auth/calendar", - ], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) + +def server(): + """ + Main function for the fast api server + """ + # extra routes + from .routes import api + from .routes import account + from .routes import google + from .routes import schedule + + # init app + app = FastAPI() + + # allow requests from own frontend running on a different port + app.add_middleware( + CORSMiddleware, + # Work around for now :) + allow_origins=[ + os.getenv("FRONTEND_URL", "http://localhost:8080"), + "https://accounts.google.com", + "https://www.googleapis.com/auth/calendar", + ], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + @app.exception_handler(RefreshError) + async def catch_google_refresh_errors(request, exc): + """Catch google refresh errors, and use our error instead.""" + return await http_exception_handler(request, APIGoogleRefreshError()) + + # Mix in our extra routes + app.include_router(api.router) + app.include_router(account.router, prefix="/account") + app.include_router(google.router, prefix="/google") + app.include_router(schedule.router, prefix="/schedule") + + return app -@app.exception_handler(RefreshError) -async def catch_google_refresh_errors(request, exc): - """Catch google refresh errors, and use our error instead.""" - return await http_exception_handler(request, APIGoogleRefreshError()) +def cli(): + """ + A very simple cli handler + """ + if len(sys.argv) < 2: + print("No command specified") + return + command = sys.argv[1:] -# Mix in our extra routes -app.include_router(api.router) -app.include_router(account.router, prefix="/account") -app.include_router(google.router, prefix="/google") -app.include_router(schedule.router, prefix="/schedule") + if command[0] == 'update-db': + from .commands import update_db + update_db.run() diff --git a/backend/src/migrations/env.py b/backend/src/appointment/migrations/env.py similarity index 84% rename from backend/src/migrations/env.py rename to backend/src/appointment/migrations/env.py index e4b1c717..b14c9bab 100644 --- a/backend/src/migrations/env.py +++ b/backend/src/appointment/migrations/env.py @@ -9,6 +9,8 @@ # This is ran from src/ so ignore the errors from secrets import normalize_secrets +import sentry_sdk + # Normalize any AWS secrets normalize_secrets() @@ -32,6 +34,17 @@ # my_important_option = config.get_main_option("my_important_option") # ... etc. +# Catch any errors that may run during migrations +if os.getenv("SENTRY_DSN") != "" or os.getenv("SENTRY_DSN") is not None: + sentry_sdk.init( + dsn=os.getenv("SENTRY_DSN"), + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + # We recommend adjusting this value in production, + traces_sample_rate=1.0, + environment=os.getenv("APP_ENV", "dev"), + ) + def run_migrations_offline() -> None: """Run migrations in 'offline' mode. diff --git a/backend/src/migrations/script.py.mako b/backend/src/appointment/migrations/script.py.mako similarity index 100% rename from backend/src/migrations/script.py.mako rename to backend/src/appointment/migrations/script.py.mako diff --git a/backend/src/migrations/versions/2023_04_05_1703-eb50007f7a21_change_subscriber_table.py b/backend/src/appointment/migrations/versions/2023_04_05_1703-eb50007f7a21_change_subscriber_table.py similarity index 100% rename from backend/src/migrations/versions/2023_04_05_1703-eb50007f7a21_change_subscriber_table.py rename to backend/src/appointment/migrations/versions/2023_04_05_1703-eb50007f7a21_change_subscriber_table.py diff --git a/backend/src/migrations/versions/2023_04_25_1303-5aec90d60d85_calendar_provider.py b/backend/src/appointment/migrations/versions/2023_04_25_1303-5aec90d60d85_calendar_provider.py similarity index 100% rename from backend/src/migrations/versions/2023_04_25_1303-5aec90d60d85_calendar_provider.py rename to backend/src/appointment/migrations/versions/2023_04_25_1303-5aec90d60d85_calendar_provider.py diff --git a/backend/src/migrations/versions/2023_04_26_1452-d9ecfcaf83a6_add_google_token.py b/backend/src/appointment/migrations/versions/2023_04_26_1452-d9ecfcaf83a6_add_google_token.py similarity index 100% rename from backend/src/migrations/versions/2023_04_26_1452-d9ecfcaf83a6_add_google_token.py rename to backend/src/appointment/migrations/versions/2023_04_26_1452-d9ecfcaf83a6_add_google_token.py diff --git a/backend/src/migrations/versions/2023_04_27_1633-81ace90a911b_add_google_state_id.py b/backend/src/appointment/migrations/versions/2023_04_27_1633-81ace90a911b_add_google_state_id.py similarity index 100% rename from backend/src/migrations/versions/2023_04_27_1633-81ace90a911b_add_google_state_id.py rename to backend/src/appointment/migrations/versions/2023_04_27_1633-81ace90a911b_add_google_state_id.py diff --git a/backend/src/migrations/versions/2023_06_08_2201-da069f44bca7_add_calendar_connected.py b/backend/src/appointment/migrations/versions/2023_06_08_2201-da069f44bca7_add_calendar_connected.py similarity index 100% rename from backend/src/migrations/versions/2023_06_08_2201-da069f44bca7_add_calendar_connected.py rename to backend/src/appointment/migrations/versions/2023_06_08_2201-da069f44bca7_add_calendar_connected.py diff --git a/backend/src/migrations/versions/2023_06_20_2216-845089644770_add_short_link_hash.py b/backend/src/appointment/migrations/versions/2023_06_20_2216-845089644770_add_short_link_hash.py similarity index 100% rename from backend/src/migrations/versions/2023_06_20_2216-845089644770_add_short_link_hash.py rename to backend/src/appointment/migrations/versions/2023_06_20_2216-845089644770_add_short_link_hash.py diff --git a/backend/src/migrations/versions/2023_06_27_1108-f9660871710e_add_general_availability_tables.py b/backend/src/appointment/migrations/versions/2023_06_27_1108-f9660871710e_add_general_availability_tables.py similarity index 100% rename from backend/src/migrations/versions/2023_06_27_1108-f9660871710e_add_general_availability_tables.py rename to backend/src/appointment/migrations/versions/2023_06_27_1108-f9660871710e_add_general_availability_tables.py diff --git a/backend/src/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py b/backend/src/appointment/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py similarity index 94% rename from backend/src/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py rename to backend/src/appointment/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py index 6abe54b3..63233ad5 100644 --- a/backend/src/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py +++ b/backend/src/appointment/migrations/versions/2023_07_27_1102-f9c5471478d0_modify_schedules_table.py @@ -26,8 +26,8 @@ def secret(): def upgrade() -> None: - op.drop_column("appointments", "appointment_type") - op.drop_constraint("schedules_ibfk_1", "schedules", type_="foreignkey") + # op.drop_column("appointments", "appointment_type") + #op.drop_constraint("schedules_ibfk_1", "schedules", type_="foreignkey") op.drop_column("schedules", "appointment_id") op.add_column("schedules", sa.Column("calendar_id", sa.Integer, sa.ForeignKey("calendars.id"))) op.add_column("schedules", sa.Column("location_type", sa.Enum(LocationType), default=LocationType.online)) diff --git a/backend/src/migrations/versions/2023_09_22_1157-3789c9fd57c5_extend_schedules_table.py b/backend/src/appointment/migrations/versions/2023_09_22_1157-3789c9fd57c5_extend_schedules_table.py similarity index 100% rename from backend/src/migrations/versions/2023_09_22_1157-3789c9fd57c5_extend_schedules_table.py rename to backend/src/appointment/migrations/versions/2023_09_22_1157-3789c9fd57c5_extend_schedules_table.py diff --git a/backend/src/routes/account.py b/backend/src/appointment/routes/account.py similarity index 100% rename from backend/src/routes/account.py rename to backend/src/appointment/routes/account.py diff --git a/backend/src/routes/api.py b/backend/src/appointment/routes/api.py similarity index 100% rename from backend/src/routes/api.py rename to backend/src/appointment/routes/api.py diff --git a/backend/src/routes/google.py b/backend/src/appointment/routes/google.py similarity index 100% rename from backend/src/routes/google.py rename to backend/src/appointment/routes/google.py diff --git a/backend/src/routes/schedule.py b/backend/src/appointment/routes/schedule.py similarity index 100% rename from backend/src/routes/schedule.py rename to backend/src/appointment/routes/schedule.py diff --git a/backend/src/secrets.py b/backend/src/appointment/secrets.py similarity index 100% rename from backend/src/secrets.py rename to backend/src/appointment/secrets.py diff --git a/backend/src/templates/email/invite.jinja2 b/backend/src/appointment/templates/email/invite.jinja2 similarity index 100% rename from backend/src/templates/email/invite.jinja2 rename to backend/src/appointment/templates/email/invite.jinja2 diff --git a/backend/src/tmp/.gitignore b/backend/src/appointment/tmp/.gitignore similarity index 100% rename from backend/src/tmp/.gitignore rename to backend/src/appointment/tmp/.gitignore diff --git a/docker-compose.yml b/docker-compose.yml index 2dcae872..73419f23 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,13 @@ services: backend: - build: ./backend + build: + context: ./backend + dockerfile: ./Dockerfile ports: - 8090:8090 volumes: - - ./backend:/app + - ./backend/src:/app/src environment: - DATABASE_URL=mysql+mysqldb://tba:tba@mysql:3306/appointment depends_on: diff --git a/frontend/docker/etc/nginx/conf.d/appointments.conf b/frontend/docker/etc/nginx/conf.d/appointments.conf index 47f9afd2..fe3c3c97 100644 --- a/frontend/docker/etc/nginx/conf.d/appointments.conf +++ b/frontend/docker/etc/nginx/conf.d/appointments.conf @@ -6,7 +6,7 @@ server { #access_log /var/log/nginx/host.access.log main; # Backend API proxy - location /api/v1 { + location ^~ /api/v1/ { # Remove our fake /api/v1/ prefix for FastAPI rewrite ^/api/v1/(.*)$ /$1 break; proxy_pass http://127.0.0.1:5000; diff --git a/frontend/src/views/ScheduleView.vue b/frontend/src/views/ScheduleView.vue index dd15535c..5dfdd10a 100644 --- a/frontend/src/views/ScheduleView.vue +++ b/frontend/src/views/ScheduleView.vue @@ -165,7 +165,8 @@ const firstSchedule = computed(() => schedules.value.length > 0 const schedulesReady = ref(false); const getFirstSchedule = async () => { calendarEvents.value = []; - const { data } = await call('schedule').get().json(); + // trailing slash to prevent fast api redirect which doesn't work great on our container setup + const { data } = await call('schedule/').get().json(); schedules.value = data.value; };