Uklid v alembic migracich, error logging, upravy kvuli autorizaci

This commit is contained in:
Michal Kváček
2023-08-14 15:01:13 +02:00
parent bc260a2a8b
commit 97295c17c0
38 changed files with 203 additions and 957 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
FROM python:3.10-alpine
FROM python:3.11-alpine
RUN apk update && \
apk add --no-cache tzdata mariadb-client mariadb-dev && \
@@ -13,7 +13,7 @@ RUN delgroup www-data && addgroup -g 33 -S www-data && adduser -u 33 -D -S -G ww
COPY requirements.txt /app/requirements.txt
# required packages for pip (becasue of yarl lib)
ENV INSTALL_PACKAGES build-base linux-headers git
ENV INSTALL_PACKAGES build-base linux-headers
RUN apk add --no-cache $INSTALL_PACKAGES
RUN pip install --no-cache-dir -r /app/requirements.txt
@@ -1,34 +0,0 @@
"""password len
Revision ID: 19ce22e5926b
Revises: de421195d45c
Create Date: 2023-05-06 21:01:42.983935
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '19ce22e5926b'
down_revision = 'de421195d45c'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('user', 'password_hashed',
existing_type=mysql.VARCHAR(length=45),
type_=sa.String(length=60),
existing_nullable=False)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('user', 'password_hashed',
existing_type=sa.String(length=60),
type_=mysql.VARCHAR(length=45),
existing_nullable=False)
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""avatar url
Revision ID: 7951a7b79007
Revises: 19ce22e5926b
Create Date: 2023-05-07 21:42:58.261939
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7951a7b79007'
down_revision = '19ce22e5926b'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('avatar_image_url', sa.String(length=128), nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('user', 'avatar_image_url')
# ### end Alembic commands ###
@@ -1,38 +0,0 @@
"""edit
Revision ID: d15debffedf8
Revises: 7951a7b79007
Create Date: 2023-05-23 05:42:29.097139
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'd15debffedf8'
down_revision = '7951a7b79007'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('aircraft', sa.Column('manufacturer', sa.Text(), server_default='', nullable=False))
op.add_column('aircraft', sa.Column('model', sa.String(length=30), nullable=False))
op.drop_column('aircraft', 'type')
op.alter_column('user', 'avatar_image_url',
existing_type=mysql.VARCHAR(length=128),
nullable=True)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('user', 'avatar_image_url',
existing_type=mysql.VARCHAR(length=128),
nullable=False)
op.add_column('aircraft', sa.Column('type', mysql.VARCHAR(length=30), nullable=False))
op.drop_column('aircraft', 'model')
op.drop_column('aircraft', 'manufacturer')
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""edit
Revision ID: 8491bd15ab4a
Revises: d15debffedf8
Create Date: 2023-05-23 05:47:26.866008
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '8491bd15ab4a'
down_revision = 'd15debffedf8'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('aircraft', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('aircraft', 'deleted')
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""aircraft photo
Revision ID: 431adcd37681
Revises: 8491bd15ab4a
Create Date: 2023-05-31 20:18:02.644970
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '431adcd37681'
down_revision = '8491bd15ab4a'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('aircraft', sa.Column('photo_filename', sa.String(length=128), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('aircraft', 'photo_filename')
# ### end Alembic commands ###
@@ -1,32 +0,0 @@
"""flight edit
Revision ID: 66e39f31b1d2
Revises: 431adcd37681
Create Date: 2023-06-06 04:16:07.568446
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '66e39f31b1d2'
down_revision = '431adcd37681'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('takeoff_datetime', sa.DateTime(), nullable=False))
op.add_column('flight', sa.Column('landing_datetime', sa.DateTime(), nullable=False))
op.drop_column('flight', 'duration_total')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('duration_total', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False))
op.drop_column('flight', 'landing_datetime')
op.drop_column('flight', 'takeoff_datetime')
# ### end Alembic commands ###
@@ -1,32 +0,0 @@
"""flight edit
Revision ID: 5781b1432475
Revises: 66e39f31b1d2
Create Date: 2023-06-06 04:35:10.408586
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '5781b1432475'
down_revision = '66e39f31b1d2'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('solo', sa.Boolean(), nullable=False))
op.add_column('flight', sa.Column('with_instructor', sa.Boolean(), nullable=False))
op.add_column('flight', sa.Column('landings', sa.Integer(), nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('flight', 'landings')
op.drop_column('flight', 'with_instructor')
op.drop_column('flight', 'solo')
# ### end Alembic commands ###
@@ -1,34 +0,0 @@
"""add soft delete
Revision ID: fd5fc5c1e2f6
Revises: 5781b1432475
Create Date: 2023-06-06 05:00:23.250817
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'fd5fc5c1e2f6'
down_revision = '5781b1432475'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('copilot', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
op.add_column('flight', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
op.add_column('metar', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
op.add_column('organization', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('organization', 'deleted')
op.drop_column('metar', 'deleted')
op.drop_column('flight', 'deleted')
op.drop_column('copilot', 'deleted')
# ### end Alembic commands ###
@@ -1,32 +0,0 @@
"""add soft delete
Revision ID: 559795b043f3
Revises: fd5fc5c1e2f6
Create Date: 2023-06-06 05:00:51.512887
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '559795b043f3'
down_revision = 'fd5fc5c1e2f6'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('airport', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
op.add_column('point_of_interest', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
op.add_column('point_of_interest_type', sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('point_of_interest_type', 'deleted')
op.drop_column('point_of_interest', 'deleted')
op.drop_column('airport', 'deleted')
# ### end Alembic commands ###
@@ -1,34 +0,0 @@
"""flight duration
Revision ID: 419cf23cbf83
Revises: 559795b043f3
Create Date: 2023-06-06 17:41:26.375394
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '419cf23cbf83'
down_revision = '559795b043f3'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('duration_total', sa.Integer(), nullable=True))
op.alter_column('flight', 'duration_pic',
existing_type=mysql.INTEGER(display_width=11),
nullable=True)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('flight', 'duration_pic',
existing_type=mysql.INTEGER(display_width=11),
nullable=False)
op.drop_column('flight', 'duration_total')
# ### end Alembic commands ###
@@ -1,30 +0,0 @@
"""flight cover photo
Revision ID: 7304ac2f580b
Revises: 419cf23cbf83
Create Date: 2023-06-29 07:35:54.303608
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7304ac2f580b'
down_revision = '419cf23cbf83'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('cover_photo_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'flight', 'photo', ['cover_photo_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'flight', type_='foreignkey')
op.drop_column('flight', 'cover_photo_id')
# ### end Alembic commands ###
@@ -1,56 +0,0 @@
"""zmena v gps, pridani poi_id do photo
Revision ID: ef51b2cd596a
Revises: 7304ac2f580b
Create Date: 2023-06-29 08:21:24.755261
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'ef51b2cd596a'
down_revision = '7304ac2f580b'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('airport', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('airport', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.drop_column('airport', 'gps_position')
op.add_column('flight_track', sa.Column('point_of_interest_id', sa.Integer(), nullable=False))
op.drop_constraint('flight_track_ibfk_2', 'flight_track', type_='foreignkey')
op.create_foreign_key(None, 'flight_track', 'point_of_interest', ['point_of_interest_id'], ['id'])
op.drop_column('flight_track', 'poi_id')
op.add_column('photo', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('photo', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.add_column('photo', sa.Column('poin_of_interest_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'photo', 'point_of_interest', ['poin_of_interest_id'], ['id'])
op.drop_column('photo', 'gps_position')
op.add_column('point_of_interest', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('point_of_interest', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.drop_column('point_of_interest', 'gps_position')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('point_of_interest', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_column('point_of_interest', 'gps_longitude')
op.drop_column('point_of_interest', 'gps_latitude')
op.add_column('photo', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_constraint(None, 'photo', type_='foreignkey')
op.drop_column('photo', 'poin_of_interest_id')
op.drop_column('photo', 'gps_longitude')
op.drop_column('photo', 'gps_latitude')
op.add_column('flight_track', sa.Column('poi_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False))
op.drop_constraint(None, 'flight_track', type_='foreignkey')
op.create_foreign_key('flight_track_ibfk_2', 'flight_track', 'point_of_interest', ['poi_id'], ['id'])
op.drop_column('flight_track', 'point_of_interest_id')
op.add_column('airport', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_column('airport', 'gps_longitude')
op.drop_column('airport', 'gps_latitude')
# ### end Alembic commands ###
@@ -1,34 +0,0 @@
"""fix typo
Revision ID: 7dc6dd7d0f59
Revises: ef51b2cd596a
Create Date: 2023-06-29 15:43:44.520087
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '7dc6dd7d0f59'
down_revision = 'ef51b2cd596a'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('photo', sa.Column('point_of_interest_id', sa.Integer(), nullable=True))
op.drop_constraint('photo_ibfk_3', 'photo', type_='foreignkey')
op.create_foreign_key(None, 'photo', 'point_of_interest', ['point_of_interest_id'], ['id'])
op.drop_column('photo', 'poin_of_interest_id')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('photo', sa.Column('poin_of_interest_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
op.drop_constraint(None, 'photo', type_='foreignkey')
op.create_foreign_key('photo_ibfk_3', 'photo', 'point_of_interest', ['poin_of_interest_id'], ['id'])
op.drop_column('photo', 'point_of_interest_id')
# ### end Alembic commands ###
@@ -1,36 +0,0 @@
"""uprava cover photo u letu, aircraft.call_sign
Revision ID: f19757a615cc
Revises: 7dc6dd7d0f59
Create Date: 2023-06-29 16:03:51.185228
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'f19757a615cc'
down_revision = '7dc6dd7d0f59'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('aircraft', sa.Column('call_sign', sa.String(length=16), nullable=False))
op.drop_column('aircraft', 'name')
op.drop_constraint('flight_ibfk_6', 'flight', type_='foreignkey')
op.drop_column('flight', 'cover_photo_id')
op.add_column('photo', sa.Column('is_flight_cover', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('photo', 'is_flight_cover')
op.add_column('flight', sa.Column('cover_photo_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
op.create_foreign_key('flight_ibfk_6', 'flight', 'photo', ['cover_photo_id'], ['id'])
op.add_column('aircraft', sa.Column('name', mysql.VARCHAR(length=128), nullable=False))
op.drop_column('aircraft', 'call_sign')
# ### end Alembic commands ###
@@ -1,32 +0,0 @@
"""make poi type nullable
Revision ID: 804e55bbf855
Revises: f19757a615cc
Create Date: 2023-07-11 07:42:14.437885
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '804e55bbf855'
down_revision = 'f19757a615cc'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('point_of_interest', 'type_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=True)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('point_of_interest', 'type_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=False)
# ### end Alembic commands ###
@@ -1,40 +0,0 @@
"""gps u letiste nejsou nullable, pridani sloupce photo.exposed_at
Revision ID: 708fc32f6a3b
Revises: 804e55bbf855
Create Date: 2023-07-31 04:51:26.257834
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '708fc32f6a3b'
down_revision = '804e55bbf855'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('airport', 'gps_latitude',
existing_type=mysql.FLOAT(),
nullable=False)
op.alter_column('airport', 'gps_longitude',
existing_type=mysql.FLOAT(),
nullable=False)
op.add_column('photo', sa.Column('exposed_at', sa.DateTime(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('photo', 'exposed_at')
op.alter_column('airport', 'gps_longitude',
existing_type=mysql.FLOAT(),
nullable=True)
op.alter_column('airport', 'gps_latitude',
existing_type=mysql.FLOAT(),
nullable=True)
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""photo.gps_altitude
Revision ID: cf1fb904e9ab
Revises: 708fc32f6a3b
Create Date: 2023-07-31 08:57:10.715298
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'cf1fb904e9ab'
down_revision = '708fc32f6a3b'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('photo', sa.Column('gps_altitude', sa.Float(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('photo', 'gps_altitude')
# ### end Alembic commands ###
@@ -1,38 +0,0 @@
"""add weather info
Revision ID: 36ea098fde31
Revises: cf1fb904e9ab
Create Date: 2023-08-01 04:37:17.188376
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '36ea098fde31'
down_revision = 'cf1fb904e9ab'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('airport', sa.Column('created_by_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'airport', 'user', ['created_by_id'], ['id'])
op.add_column('flight', sa.Column('weather_info_takeoff_id', sa.Integer(), nullable=True))
op.add_column('flight', sa.Column('weather_info_landing_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'flight', 'weather_info', ['weather_info_takeoff_id'], ['id'])
op.create_foreign_key(None, 'flight', 'weather_info', ['weather_info_landing_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('flight_ibfk_6', 'flight', type_='foreignkey')
op.drop_constraint('flight_ibfk_7', 'flight', type_='foreignkey')
op.drop_column('flight', 'weather_info_landing_id')
op.drop_column('flight', 'weather_info_takeoff_id')
op.drop_constraint('airport_ibfk_1', 'airport', type_='foreignkey')
op.drop_column('airport', 'created_by_id')
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""add datetime to weather_info
Revision ID: 2a320e1e093d
Revises: 36ea098fde31
Create Date: 2023-08-01 04:47:22.122423
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '2a320e1e093d'
down_revision = '36ea098fde31'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('weather_info', sa.Column('datetime', sa.DateTime(), nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('weather_info', 'datetime')
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""add gpx to flight
Revision ID: 1e04cd7838dd
Revises: 2a320e1e093d
Create Date: 2023-08-07 18:55:00.914684
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '1e04cd7838dd'
down_revision = '2a320e1e093d'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('gpx_track_filename', sa.String(length=128), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('flight', 'gpx_track_filename')
# ### end Alembic commands ###
@@ -1,38 +0,0 @@
"""airports cannot be nullable
Revision ID: f85556b2ce2c
Revises: 1e04cd7838dd
Create Date: 2023-08-07 19:14:17.791435
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'f85556b2ce2c'
down_revision = '1e04cd7838dd'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('flight', 'takeoff_airport_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=False)
op.alter_column('flight', 'landing_airport_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=False)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('flight', 'landing_airport_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=True)
op.alter_column('flight', 'takeoff_airport_id',
existing_type=mysql.INTEGER(display_width=11),
nullable=True)
# ### end Alembic commands ###
@@ -1,30 +0,0 @@
"""remove not used fields in flight
Revision ID: b5c66e5a2df7
Revises: f85556b2ce2c
Create Date: 2023-08-07 20:53:00.717813
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'b5c66e5a2df7'
down_revision = 'f85556b2ce2c'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('flight', 'with_instructor')
op.drop_column('flight', 'solo')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('solo', mysql.TINYINT(display_width=1), autoincrement=False, nullable=False))
op.add_column('flight', sa.Column('with_instructor', mysql.TINYINT(display_width=1), autoincrement=False, nullable=False))
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""add title photo url for user
Revision ID: b1bd8ecc3251
Revises: b5c66e5a2df7
Create Date: 2023-08-08 19:08:13.021213
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b1bd8ecc3251'
down_revision = 'b5c66e5a2df7'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('title_image_url', sa.String(length=128), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('user', 'title_image_url')
# ### end Alembic commands ###
@@ -1,34 +0,0 @@
"""rename images in user table
Revision ID: 3d51075b5ece
Revises: b1bd8ecc3251
Create Date: 2023-08-08 19:45:21.470315
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '3d51075b5ece'
down_revision = 'b1bd8ecc3251'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('avatar_image_filename', sa.String(length=128), nullable=True))
op.add_column('user', sa.Column('title_image_filename', sa.String(length=128), nullable=True))
op.drop_column('user', 'title_image_url')
op.drop_column('user', 'avatar_image_url')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('avatar_image_url', mysql.VARCHAR(length=128), nullable=True))
op.add_column('user', sa.Column('title_image_url', mysql.VARCHAR(length=128), nullable=True))
op.drop_column('user', 'title_image_filename')
op.drop_column('user', 'avatar_image_filename')
# ### end Alembic commands ###
@@ -1,32 +0,0 @@
"""add public info to user
Revision ID: 707eb800ddcd
Revises: 3d51075b5ece
Create Date: 2023-08-08 20:24:32.728653
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '707eb800ddcd'
down_revision = '3d51075b5ece'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('description', sa.Text(), nullable=False))
op.add_column('user', sa.Column('public_username', sa.String(length=128), nullable=True))
op.create_unique_constraint(None, 'user', ['public_username'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'user', type_='unique')
op.drop_column('user', 'public_username')
op.drop_column('user', 'description')
# ### end Alembic commands ###
@@ -1,28 +0,0 @@
"""add is_public to flight
Revision ID: 300b721e0818
Revises: 707eb800ddcd
Create Date: 2023-08-08 22:08:34.559165
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '300b721e0818'
down_revision = '707eb800ddcd'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('flight', 'is_public')
# ### end Alembic commands ###
@@ -1,15 +1,16 @@
"""first db version
"""initial DB schema
Revision ID: de421195d45c
Revision ID: dd48d8dab743
Revises:
Create Date: 2023-05-06 20:57:49.053470
Create Date: 2023-08-14 10:08:06.796608
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'de421195d45c'
revision = 'dd48d8dab743'
down_revision = None
branch_labels = None
depends_on = None
@@ -17,29 +18,53 @@ depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('airport',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('icao_code', sa.String(length=4), nullable=False),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('elevation', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(length=128), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('password_hashed', sa.String(length=45), nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('public_username', sa.String(length=128), nullable=True),
sa.Column('avatar_image_filename', sa.String(length=128), nullable=True),
sa.Column('title_image_filename', sa.String(length=128), nullable=True),
sa.Column('password_hashed', sa.String(length=60), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
sa.UniqueConstraint('email'),
sa.UniqueConstraint('public_username')
)
op.create_table('weather_info',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('qnh', sa.Integer(), nullable=True),
sa.Column('temperature_surface', sa.Float(), nullable=True),
sa.Column('dewpoint_surface', sa.Float(), nullable=True),
sa.Column('rain', sa.Float(), nullable=True),
sa.Column('cloudcover_low', sa.Float(), nullable=True),
sa.Column('cloudcover_total', sa.Float(), nullable=True),
sa.Column('wind_speed_surface', sa.Float(), nullable=True),
sa.Column('wind_direction_surface', sa.Float(), nullable=True),
sa.Column('datetime', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('airport',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('icao_code', sa.String(length=8), nullable=False),
sa.Column('gps_latitude', sa.Float(), nullable=False),
sa.Column('gps_longitude', sa.Float(), nullable=False),
sa.Column('elevation', sa.Integer(), nullable=True),
sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('copilot',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
@@ -53,19 +78,12 @@ def upgrade() -> None:
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('metar',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('airport_id', sa.Integer(), nullable=False),
sa.Column('metar', sa.Text(), nullable=False),
sa.Column('issued_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['airport_id'], ['airport.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('organization',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
@@ -75,29 +93,44 @@ def upgrade() -> None:
sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('aircraft',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('type', sa.String(length=30), nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('call_sign', sa.String(length=16), nullable=False),
sa.Column('photo_filename', sa.String(length=128), nullable=True),
sa.Column('manufacturer', sa.Text(), server_default='', nullable=False),
sa.Column('model', sa.String(length=30), server_default='', nullable=False),
sa.Column('description', sa.Text(), server_default='', nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('metar',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('airport_id', sa.Integer(), nullable=False),
sa.Column('metar', sa.Text(), nullable=False),
sa.Column('issued_at', sa.DateTime(), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['airport_id'], ['airport.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('point_of_interest',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('type_id', sa.Integer(), nullable=False),
sa.Column('gps_latitude', sa.Float(), nullable=True),
sa.Column('gps_longitude', sa.Float(), nullable=True),
sa.Column('type_id', sa.Integer(), nullable=True),
sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['type_id'], ['point_of_interest_type.id'], ),
sa.PrimaryKeyConstraint('id')
@@ -125,41 +158,57 @@ def upgrade() -> None:
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('takeoff_airport_id', sa.Integer(), nullable=True),
sa.Column('landing_airport_id', sa.Integer(), nullable=True),
sa.Column('takeoff_airport_id', sa.Integer(), nullable=False),
sa.Column('landing_airport_id', sa.Integer(), nullable=False),
sa.Column('takeoff_datetime', sa.DateTime(), nullable=False),
sa.Column('landing_datetime', sa.DateTime(), nullable=False),
sa.Column('duration_total', sa.Integer(), nullable=True),
sa.Column('duration_pic', sa.Integer(), nullable=True),
sa.Column('gpx_track_filename', sa.String(length=128), nullable=True),
sa.Column('aircraft_id', sa.Integer(), nullable=False),
sa.Column('copilot_id', sa.Integer(), nullable=True),
sa.Column('weather_info_takeoff_id', sa.Integer(), nullable=True),
sa.Column('weather_info_landing_id', sa.Integer(), nullable=True),
sa.Column('landings', sa.Integer(), nullable=False),
sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('duration_total', sa.Integer(), nullable=False),
sa.Column('duration_pic', sa.Integer(), nullable=False),
sa.Column('deleted', sa.Boolean(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['aircraft_id'], ['aircraft.id'], ),
sa.ForeignKeyConstraint(['copilot_id'], ['copilot.id'], ),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['landing_airport_id'], ['airport.id'], ),
sa.ForeignKeyConstraint(['takeoff_airport_id'], ['airport.id'], ),
sa.ForeignKeyConstraint(['weather_info_landing_id'], ['weather_info.id'], ),
sa.ForeignKeyConstraint(['weather_info_takeoff_id'], ['weather_info.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('flight_track',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('flight_id', sa.Integer(), nullable=False),
sa.Column('poi_id', sa.Integer(), nullable=False),
sa.Column('point_of_interest_id', sa.Integer(), nullable=False),
sa.Column('order', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['flight_id'], ['flight.id'], ),
sa.ForeignKeyConstraint(['poi_id'], ['point_of_interest.id'], ),
sa.ForeignKeyConstraint(['point_of_interest_id'], ['point_of_interest.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('photo',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('filename', sa.String(length=128), nullable=False),
sa.Column('is_flight_cover', sa.Boolean(), server_default='0', nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('exposed_at', sa.DateTime(), nullable=True),
sa.Column('gps_latitude', sa.Float(), nullable=True),
sa.Column('gps_longitude', sa.Float(), nullable=True),
sa.Column('gps_altitude', sa.Float(), nullable=True),
sa.Column('point_of_interest_id', sa.Integer(), nullable=True),
sa.Column('flight_id', sa.Integer(), nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['flight_id'], ['flight.id'], ),
sa.ForeignKeyConstraint(['point_of_interest_id'], ['point_of_interest.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
@@ -173,12 +222,13 @@ def downgrade() -> None:
op.drop_table('aircraft_notes')
op.drop_table('user_is_in_organization')
op.drop_table('point_of_interest')
op.drop_table('metar')
op.drop_table('aircraft')
op.drop_table('point_of_interest_type')
op.drop_table('organization')
op.drop_table('metar')
op.drop_table('license')
op.drop_table('copilot')
op.drop_table('user')
op.drop_table('airport')
op.drop_table('weather_info')
op.drop_table('user')
# ### end Alembic commands ###
+13
View File
@@ -20,6 +20,18 @@ services:
environment:
TZ: "Europe/Prague"
scrapy:
build:
context: ../crawlers
environment:
- MYSQL_USER=root
- MYSQL_PASSWORD=
- MYSQL_DATABASE=ull_tracker
- MYSQL_HOST=db
volumes:
- db-data:/var/lib/mysql:rw
- ../crawlers:/app
nginx:
image: nginx:alpine
restart: always
@@ -28,5 +40,6 @@ services:
- ./uploads:/app/uploads
ports:
- "8999:8999"
volumes:
db-data: { }
-1
View File
@@ -12,4 +12,3 @@ pillow
exif
aiocache
aiohttp
+14 -2
View File
@@ -1,7 +1,19 @@
from functools import wraps
from fastapi import HTTPException
from starlette.status import HTTP_401_UNAUTHORIZED
def public_endpoint(func):
pass
def private_endpoint(func):
pass
def authenticated_user_only(func):
@wraps(func)
async def decorator(*args, **kwargs):
if 'info' in kwargs:
if not kwargs['info'].context.user_id:
raise HTTPException(HTTP_401_UNAUTHORIZED, "Not authorized")
return await func(*args, **kwargs)
return decorator
+3 -2
View File
@@ -1,5 +1,6 @@
from functools import wraps
from graphql import GraphQLError
from sqlalchemy.exc import NoResultFound
def error_logging(func):
@@ -7,7 +8,7 @@ def error_logging(func):
async def decorator(*args, **kwargs):
try:
return await func(*args, **kwargs)
except Exception as e:
raise GraphQLError(f"Not found")
except NoResultFound as e:
raise GraphQLError(f"Not found", original_error=e)
return decorator
+12 -2
View File
@@ -1,3 +1,13 @@
from fastapi_jwt.jwt import JwtAccess, JwtRefresh
class BaseEndpoint:
def __init__(self, db):
self.db = db
def __init__(self, *args, **kwargs):
self.db = kwargs.get("db")
super().__init__(*args, **kwargs)
class AuthEndpoint:
def __init__(self, *args, **kwargs):
self.access_security: JwtAccess = kwargs.get("access_token")
self.refresh_security: JwtRefresh = kwargs.get("refresh_token")
super().__init__()
+13 -14
View File
@@ -1,11 +1,11 @@
from fastapi import HTTPException
from fastapi_jwt import JwtAuthorizationCredentials
from fastapi_jwt.jwt import JwtAccess, JwtRefresh
from passlib.hash import bcrypt
from sqlalchemy import select
from starlette.responses import Response
from database.models import User
from endpoints.base import BaseEndpoint
from endpoints.base import BaseEndpoint, AuthEndpoint
from pydantic import BaseModel
@@ -14,13 +14,7 @@ class LoginInput(BaseModel):
password: str
class LoginEndpoint(BaseEndpoint):
def __init__(self, db, access_token: JwtAccess, refresh_token: JwtRefresh):
super().__init__(db)
self.access_security = access_token
self.refresh_security = refresh_token
class LoginEndpoint(BaseEndpoint, AuthEndpoint):
async def on_post(self, user_data: LoginInput, resp: Response) -> dict:
query = select(User).filter_by(email=user_data.email)
logged_user = (await self.db.scalars(query)).first()
@@ -48,11 +42,16 @@ class LoginEndpoint(BaseEndpoint):
}
class RefreshEndpoint(BaseEndpoint):
def __init__(self, access_token: JwtAccess, refresh_token: JwtRefresh):
super().__init__(db=None)
self.access_security = access_token
self.refresh_security = refresh_token
class LogoutEndpoint(AuthEndpoint):
async def on_post(self, resp: Response):
self.refresh_security.unset_refresh_cookie(resp)
return {
"logged_out": True
}
class RefreshEndpoint(AuthEndpoint):
async def on_post(self, resp: Response, credentials: JwtAuthorizationCredentials):
access_token = self.access_security.create_access_token(
+18 -2
View File
@@ -1,9 +1,13 @@
from datetime import timedelta
from functools import wraps
from typing import List, Optional, Annotated, TYPE_CHECKING, Tuple
import strawberry
from fastapi import HTTPException
from sqlalchemy import select
from starlette.status import HTTP_401_UNAUTHORIZED
from strawberry.file_uploads import Upload
from database import models
from decorators.endpoints import authenticated_user_only
from decorators.error_logging import error_logging
from graphql_schema.dataloaders import copilots_dataloader
from graphql_schema.dataloaders.aircraft import aircraft_dataloader
@@ -119,6 +123,9 @@ class FlightQueries:
@strawberry.field
async def flights(root, info, username: Optional[str] = None) -> List[Flight]:
if not info.context.user_id and not username:
raise HTTPException(HTTP_401_UNAUTHORIZED)
query = (
get_base_query(user_id=info.context.user_id, username=username, is_auth=bool(info.context.user_id))
.order_by(models.Flight.id.desc())
@@ -128,6 +135,9 @@ class FlightQueries:
@strawberry.field
@error_logging
async def flight(root, info, id: int, username: Optional[str] = None) -> Flight:
if not info.context.user_id and not username:
raise HTTPException(HTTP_401_UNAUTHORIZED)
query = (
get_base_query(user_id=info.context.user_id, username=username, is_auth=bool(info.context.user_id))
.filter(models.Flight.id == id)
@@ -163,6 +173,7 @@ class CreateFlightMutation:
takeoff_airport: ComboboxInput
@strawberry.mutation
@authenticated_user_only
async def create_flight(self, info, input: CreateFlightInput) -> Flight:
db = info.context.db
aircraft_id = await handle_aircraft_save(db, info.context.user_id, input.aircraft)
@@ -187,6 +198,7 @@ class CreateFlightMutation:
})
@strawberry.type
class EditFlightMutation:
@strawberry_sqlalchemy_input(models.Flight, exclude_fields=[
@@ -202,6 +214,7 @@ class EditFlightMutation:
takeoff_airport: Optional[ComboboxInput] = None
@strawberry.mutation
@authenticated_user_only
async def edit_flight(self, info, id: int, input: EditFlightInput) -> Flight:
db = info.context.db
user_id = info.context.user_id
@@ -212,8 +225,11 @@ class EditFlightMutation:
)).one()
data = input.to_dict()
data['takeoff_datetime'] = data['takeoff_datetime'].astimezone()
data['landing_datetime'] = data['landing_datetime'].astimezone()
if input.takeoff_datetime:
data['takeoff_datetime'] = data['takeoff_datetime'].astimezone()
if input.landing_datetime:
data['landing_datetime'] = data['landing_datetime'].astimezone()
if input.gpx_track is not None:
# TODO: poresit validaci uploadovaneho souboru!
+8 -4
View File
@@ -8,6 +8,7 @@ from sqlalchemy.exc import NoResultFound
from strawberry.file_uploads import Upload
from database import models
from database.models import User
from decorators.endpoints import authenticated_user_only
from decorators.error_logging import error_logging
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import handle_file_upload, delete_file
@@ -45,14 +46,16 @@ class UserQueries:
)).one()
@strawberry.field
@authenticated_user_only
# @error_logging
async def logged_user(root, info) -> User:
if not info.context.user_id:
raise GraphQLError("Not authenticated")
return (await info.context.db.scalars(
user = (await info.context.db.scalars(
select(models.User).filter_by(id=info.context.user_id)
)).one()
print(user)
return user
@strawberry.type
class EditUserMutation:
@@ -68,6 +71,7 @@ class EditUserMutation:
title_image: Optional[Upload] = None
@strawberry.mutation
@authenticated_user_only
async def edit_logged_user(root, info, input: EditUserInput) -> User:
user = (await info.context.db.scalars(
select(models.User).filter_by(id=info.context.user_id)
-6
View File
@@ -1,17 +1,11 @@
import dataclasses
from typing import List, Optional
import strawberry
from fastapi_jwt import JwtAuthorizationCredentials
from fastapi_jwt.jwt import JwtAccessBearerCookie
from graphql import GraphQLError
from sqlalchemy.exc import NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.background import BackgroundTasks
from strawberry.extensions import SchemaExtension
from strawberry.fastapi import BaseContext
from strawberry.types import ExecutionContext
from .mutation import Mutation
from .query import Query
+33 -25
View File
@@ -1,17 +1,15 @@
import time
from datetime import timedelta
from fastapi import FastAPI, APIRouter, Depends, Security, HTTPException
from fastapi import FastAPI, APIRouter, Depends, Security
from fastapi_jwt import JwtAuthorizationCredentials, JwtAccessBearerCookie, JwtRefreshBearerCookie
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.background import BackgroundTasks
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import RedirectResponse, Response
from starlette.staticfiles import StaticFiles
from starlette.status import HTTP_401_UNAUTHORIZED
from strawberry.fastapi import GraphQLRouter
from config import APP_SECRET_KEY, GRAPHIQL, APP_DEBUG
from dependencies.db import db_session
from endpoints.login import LoginEndpoint, LoginInput, RefreshEndpoint
from endpoints.login import LoginEndpoint, LoginInput, RefreshEndpoint, LogoutEndpoint
from endpoints.registration import RegistrationInput, RegistrationEndpoint
from graphql_schema.schema import schema, GraphQLContext
@@ -21,11 +19,12 @@ class App:
access_security = JwtAccessBearerCookie(
secret_key=APP_SECRET_KEY,
auto_error=False,
access_expires_delta=timedelta(minutes=20)
access_expires_delta=timedelta(seconds=20),
)
refresh_security = JwtRefreshBearerCookie(
secret_key=APP_SECRET_KEY,
auto_error=True
auto_error=True,
refresh_expires_delta=timedelta(days=30),
)
def create_app(self):
@@ -58,24 +57,14 @@ class App:
app.mount("/static", StaticFiles(directory="/app/static"), name="static")
def setup_graphql_endpoint(self, app: FastAPI):
if APP_DEBUG:
@self.api_router.get("/graphql/autologin")
async def autologin():
access_token = self.access_security.create_access_token(subject={"id": 18, "name": "Franta Vomacka"})
response = RedirectResponse(url="/graphql")
self.access_security.set_access_cookie(response, access_token)
return response
def setup_graphql_context(
credentials: JwtAuthorizationCredentials = Security(self.access_security),
db: AsyncSession = Depends(db_session)
):
return GraphQLContext(
jwt_auth_credentials=credentials,
user_id=credentials['id'] if credentials else None,
db=db,
user_id=credentials['id'] if credentials else None,
jwt_auth_credentials=credentials,
jwt=self.access_security,
background_tasks=Depends(BackgroundTasks)
)
@@ -89,20 +78,39 @@ class App:
app.include_router(graphql_app, prefix="/graphql")
def setup_routes(self, app: FastAPI):
# protected endpoints
@app.post("/refresh")
self.setup_graphql_endpoint(app)
if APP_DEBUG:
@self.api_router.get("/graphql/autologin")
async def autologin():
access_token = self.access_security.create_access_token(subject={"id": 18, "name": "Franta Vomacka"})
response = RedirectResponse(url="/graphql")
self.access_security.set_access_cookie(response, access_token, expires_delta=timedelta(days=14))
return response
@self.api_router.post("/refresh")
async def refresh(
resp: Response,
credentials: JwtAuthorizationCredentials = Security(self.refresh_security)
):
return await RefreshEndpoint(self.access_security, self.refresh_security).on_post(resp, credentials)
return await RefreshEndpoint(
access_token=self.access_security,
refresh_token=self.refresh_security
).on_post(resp, credentials)
self.setup_graphql_endpoint(app)
# public endpoints
@self.api_router.post("/login")
async def login(resp: Response, user: LoginInput, db: AsyncSession = Depends(db_session)):
return await LoginEndpoint(db, self.access_security, self.refresh_security).on_post(user, resp)
return await LoginEndpoint(
db=db,
access_token=self.access_security,
refresh_token=self.refresh_security
).on_post(user, resp)
@self.api_router.post("/logout")
async def login(resp: Response):
return await LogoutEndpoint(access_token=self.access_security, refresh_token=self.refresh_security).on_post(resp)
@self.api_router.post("/registration", status_code=201)
async def registration(user: RegistrationInput, db: AsyncSession = Depends(db_session)):