Skip to content

Commit

Permalink
add preferences
Browse files Browse the repository at this point in the history
  • Loading branch information
habibasseiss committed Dec 27, 2024
1 parent e927ef6 commit 863a467
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 1 deletion.
3 changes: 2 additions & 1 deletion app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.routers import auth, organizations, projects, users
from app.routers import auth, organizations, preferences, projects, users
from app.schemas import Message
from app.settings import Settings

Expand All @@ -24,6 +24,7 @@
api.include_router(auth.router)
api.include_router(organizations.router)
api.include_router(projects.router)
api.include_router(preferences.router)


@api.get('/', status_code=HTTPStatus.OK, response_model=Message)
Expand Down
14 changes: 14 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,17 @@ class File:
init=False,
back_populates='files',
)


@table_registry.mapped_as_dataclass
class Preference:
__tablename__ = 'preferences'

key: Mapped[str] = mapped_column(init=True, primary_key=True)
value: Mapped[str] = mapped_column(init=True)
created_at: Mapped[datetime] = mapped_column(
init=False, server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
init=False, server_default=func.now(), onupdate=func.now()
)
83 changes: 83 additions & 0 deletions app/routers/preferences.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from typing import Annotated

from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.database import get_session
from app.models import Preference, User
from app.schemas import PreferencesList, PreferencesPublic
from app.security import get_current_user

router = APIRouter(prefix='/preferences', tags=['preferences'])

DbSession = Annotated[Session, Depends(get_session)]
CurrentUser = Annotated[User, Depends(get_current_user)]


# Routes
@router.get('/', response_model=PreferencesList)
def list_settings(session: DbSession, user: CurrentUser):
preferences = session.scalars(select(Preference)).all()
return {
'preferences': [
PreferencesPublic.model_validate(p) for p in preferences
]
}


@router.put('/', response_model=PreferencesList)
def update_preferences(
request: PreferencesList,
session: DbSession,
user: CurrentUser,
):
# Map the incoming preferences by key for quick lookup
incoming_preferences = {
pref.key: pref.value for pref in request.preferences
}

# Fetch existing preferences from the database that match the incoming keys
existing_preferences = list(
session.scalars(
select(Preference).where(
Preference.key.in_(incoming_preferences.keys())
)
).all()
)

# Update values for existing preferences
updated_keys = set()
for pref in existing_preferences:
if pref.key in incoming_preferences:
pref.value = incoming_preferences[pref.key]
updated_keys.add(pref.key)

# Create new preferences for keys that were not updated
new_preferences = [
Preference(key=key, value=value) # type: ignore
for key, value in incoming_preferences.items()
if key not in updated_keys
]
session.add_all(new_preferences)

# Commit all changes at once
session.commit()

# Refresh all preferences (both updated and new)
all_preferences = existing_preferences + new_preferences
for pref in all_preferences:
session.refresh(pref)

# Prepare the response
return {
'preferences': [
PreferencesPublic(
key=p.key,
value=p.value,
created_at=p.created_at,
updated_at=p.updated_at,
)
for p in all_preferences
]
}
17 changes: 17 additions & 0 deletions app/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ class UserList(BaseModel):
users: list[UserPublic]


class PreferenceSchema(BaseModel):
key: str
value: str


class PreferencesPublic(BaseModel):
key: str
value: str
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)


class PreferencesList(BaseModel):
preferences: list[PreferenceSchema]


class Token(BaseModel):
access_token: str
refresh_token: str
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""create preferences table
Revision ID: 59f0de858d13
Revises: f6b2d59ed89a
Create Date: 2024-12-27 06:35:08.610715
"""
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = '59f0de858d13'
down_revision: Union[str, None] = 'f6b2d59ed89a'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('preferences',
sa.Column('key', sa.String(), nullable=False),
sa.Column('value', sa.String(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.PrimaryKeyConstraint('key')
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('preferences')
# ### end Alembic commands ###

0 comments on commit 863a467

Please sign in to comment.