From 0de73a5ec260e11bf76123405814bdbc402e59f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kv=C3=A1=C4=8Dek?= Date: Tue, 31 Oct 2023 17:30:29 +0100 Subject: [PATCH] Pridani sentry, fix mazani upravenych fotek --- ...cascade_u_photo_adjustment_d42172840f6c.py | 30 +++++++++++++++++++ docker-compose.prod.yml | 2 ++ docker-compose.yml | 1 + requirements.txt | 2 +- src/config.py | 8 ++++- src/database/models.py | 4 +-- src/main.py | 11 ++++--- src/utils/image.py | 1 + 8 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 alembic/versions/20231030-163057_on_delete_cascade_u_photo_adjustment_d42172840f6c.py diff --git a/alembic/versions/20231030-163057_on_delete_cascade_u_photo_adjustment_d42172840f6c.py b/alembic/versions/20231030-163057_on_delete_cascade_u_photo_adjustment_d42172840f6c.py new file mode 100644 index 0000000..436ca68 --- /dev/null +++ b/alembic/versions/20231030-163057_on_delete_cascade_u_photo_adjustment_d42172840f6c.py @@ -0,0 +1,30 @@ +"""on delete cascade u photo adjustment + +Revision ID: d42172840f6c +Revises: 4996ad8bc231 +Create Date: 2023-10-30 16:30:57.118694 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd42172840f6c' +down_revision = '4996ad8bc231' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('photo_adjustment_ibfk_1', 'photo_adjustment', type_='foreignkey') + op.create_foreign_key(None, 'photo_adjustment', 'photo', ['photo_id'], ['id'], ondelete='CASCADE') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'photo_adjustment', type_='foreignkey') + op.create_foreign_key('photo_adjustment_ibfk_1', 'photo_adjustment', 'photo', ['photo_id'], ['id']) + # ### end Alembic commands ### diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 86d4e6d..a50f184 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -8,5 +8,7 @@ services: restart: "always" env_file: - .env + environment: + SENTRY_DSN: "https://184d1d6bd39f4fbb94804ae84e9afdd5@o472821.ingest.sentry.io/5506983" volumes: - ./uploads:/app/uploads diff --git a/docker-compose.yml b/docker-compose.yml index 415400a..debedd8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,7 @@ services: API_URL: "http://localhost:8000" APP_ENV: "development" ALLOW_CORS_ORIGINS: "http://localhost:9000 http://localhost:9001" + SENTRY_DSN: "https://184d1d6bd39f4fbb94804ae84e9afdd5@o472821.ingest.sentry.io/5506983" scrapy: diff --git a/requirements.txt b/requirements.txt index c664531..f95773c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ aiomysql==0.2.0 alembic==1.11.1 passlib==1.7.4 pydantic==1.10.11 # vysla uz 2.0, ale nejak mi to nefunguje - +sentry-sdk[fastapi] pillow exif aiocache diff --git a/src/config.py b/src/config.py index 078874e..f0db6b9 100644 --- a/src/config.py +++ b/src/config.py @@ -2,9 +2,15 @@ import os APP_DEBUG = True GRAPHIQL = True + +ACCESS_TOKEN_VALIDITY_MINUTES = 20 +REFRESH_TOKEN_VALIDITY_DAYS = 30 + API_URL = os.environ.get("API_URL") or "http://localhost:8000" -APP_SECRET_KEY = os.environ.get("APP_SECRET_KEY") or "test" ALLOW_CORS_ORIGINS = os.environ.get("ALLOW_CORS_ORIGINS", "").split() +SENTRY_DSN = os.environ.get("SENTRY_DSN") + +APP_SECRET_KEY = os.environ.get("APP_SECRET_KEY") or "test" if not APP_SECRET_KEY: raise ValueError("Missing APP_SECRET_KEY!") diff --git a/src/database/models.py b/src/database/models.py index 8391a7d..a17b6d8 100644 --- a/src/database/models.py +++ b/src/database/models.py @@ -132,7 +132,7 @@ class Photo(BaseModel): flight: Mapped['Flight'] = relationship(foreign_keys=[flight_id]) point_of_interest: Mapped['PointOfInterest'] = relationship() - adjustment: Mapped['PhotoAdjustment'] = relationship() + adjustment: Mapped['PhotoAdjustment'] = relationship(passive_deletes=True) created_by: Mapped['User'] = relationship() @@ -140,7 +140,7 @@ class PhotoAdjustment(BaseModel): __tablename__ = "photo_adjustment" id: Mapped[int] = mapped_column(primary_key=True) - photo_id: Mapped[int] = mapped_column(Integer, ForeignKey('photo.id'), nullable=False) + photo_id: Mapped[int] = mapped_column(Integer, ForeignKey('photo.id', ondelete='CASCADE'), nullable=False) rotate: Mapped[float] = mapped_column(Float, nullable=True) contrast: Mapped[float] = mapped_column(Float, nullable=True) brightness: Mapped[float] = mapped_column(Float, nullable=True) diff --git a/src/main.py b/src/main.py index c449e60..14dd380 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,6 @@ +import sentry_sdk from datetime import timedelta from typing import Optional - from fastapi import FastAPI, APIRouter, Depends, Security from fastapi_jwt import JwtAuthorizationCredentials, JwtAccessBearerCookie, JwtRefreshBearerCookie from sqlalchemy import select @@ -9,7 +9,7 @@ from starlette.middleware.cors import CORSMiddleware from starlette.responses import RedirectResponse, Response from starlette.staticfiles import StaticFiles from strawberry.fastapi import GraphQLRouter -from config import APP_SECRET_KEY, GRAPHIQL, APP_DEBUG, ALLOW_CORS_ORIGINS +from config import APP_SECRET_KEY, GRAPHIQL, APP_DEBUG, ALLOW_CORS_ORIGINS, SENTRY_DSN, ACCESS_TOKEN_VALIDITY_MINUTES, REFRESH_TOKEN_VALIDITY_DAYS from database import models, async_session from endpoints.login import LoginEndpoint, LoginInput, RefreshEndpoint, LogoutEndpoint from endpoints.photo_editor_preview import PhotoEditorEndpoint @@ -22,15 +22,18 @@ class App: access_security = JwtAccessBearerCookie( secret_key=APP_SECRET_KEY, auto_error=False, - access_expires_delta=timedelta(minutes=20), + access_expires_delta=timedelta(minutes=ACCESS_TOKEN_VALIDITY_MINUTES), ) refresh_security = JwtRefreshBearerCookie( secret_key=APP_SECRET_KEY, auto_error=True, - refresh_expires_delta=timedelta(days=30), + refresh_expires_delta=timedelta(days=REFRESH_TOKEN_VALIDITY_DAYS), ) def create_app(self): + if SENTRY_DSN: + sentry_sdk.init(dsn=SENTRY_DSN, enable_tracing=True) + app = FastAPI() self.setup_exception_handlers(app) diff --git a/src/utils/image.py b/src/utils/image.py index 10ba998..207c951 100644 --- a/src/utils/image.py +++ b/src/utils/image.py @@ -75,6 +75,7 @@ class PhotoEditor: return round(w), round(h) def rotate(self, degrees: float, crop_after_rotate: bool = False): + degrees *= -1 self.img = self.img.rotate(degrees, resample=Image.Resampling.BICUBIC, expand=True) if crop_after_rotate: