diff --git a/alembic/versions/002_add_profile_fields.py b/alembic/versions/002_add_profile_fields.py index 5daeaf2..95c0869 100644 --- a/alembic/versions/002_add_profile_fields.py +++ b/alembic/versions/002_add_profile_fields.py @@ -27,7 +27,7 @@ def column_exists(table_name, column_name): def upgrade() -> None: - # List of columns to add + # List of columns to add (without server defaults for SQLite compatibility) columns_to_add = [ ('first_name', sa.Column('first_name', sa.String(), nullable=True)), ('last_name', sa.Column('last_name', sa.String(), nullable=True)), @@ -35,7 +35,7 @@ def upgrade() -> None: ('bio', sa.Column('bio', sa.String(), nullable=True)), ('preferred_language', sa.Column('preferred_language', sa.String(), nullable=True)), ('timezone', sa.Column('timezone', sa.String(), nullable=True)), - ('updated_at', sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True)) + ('updated_at', sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True)) # No server_default for SQLite ] # Add columns only if they don't exist @@ -48,6 +48,9 @@ def upgrade() -> None: op.execute("UPDATE users SET preferred_language = 'en' WHERE preferred_language IS NULL") if column_exists('users', 'timezone'): op.execute("UPDATE users SET timezone = 'UTC' WHERE timezone IS NULL") + if column_exists('users', 'updated_at'): + # Set updated_at to current timestamp for existing users + op.execute("UPDATE users SET updated_at = datetime('now') WHERE updated_at IS NULL") def downgrade() -> None: diff --git a/alembic/versions/003_sync_current_state.py b/alembic/versions/003_sync_current_state.py index a9ebfb9..222c56a 100644 --- a/alembic/versions/003_sync_current_state.py +++ b/alembic/versions/003_sync_current_state.py @@ -53,12 +53,16 @@ def upgrade() -> None: sa.Column('bio', sa.String(), nullable=True), sa.Column('preferred_language', sa.String(), nullable=True), sa.Column('timezone', sa.String(), nullable=True), - sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True), - sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=True), # Remove server_default for SQLite + sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), # Remove server_default for SQLite sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True) op.create_index(op.f('ix_users_id'), 'users', ['id'], unique=False) + + # Set default timestamps for new table + op.execute("UPDATE users SET created_at = datetime('now') WHERE created_at IS NULL") + op.execute("UPDATE users SET updated_at = datetime('now') WHERE updated_at IS NULL") else: # Table exists, check for missing profile columns and add them profile_columns = [ @@ -68,7 +72,7 @@ def upgrade() -> None: ('bio', sa.Column('bio', sa.String(), nullable=True)), ('preferred_language', sa.Column('preferred_language', sa.String(), nullable=True)), ('timezone', sa.Column('timezone', sa.String(), nullable=True)), - ('updated_at', sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True)) + ('updated_at', sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True)) # Remove server_default for SQLite ] for column_name, column_def in profile_columns: @@ -80,6 +84,8 @@ def upgrade() -> None: op.execute("UPDATE users SET preferred_language = 'en' WHERE preferred_language IS NULL") if column_exists('users', 'timezone'): op.execute("UPDATE users SET timezone = 'UTC' WHERE timezone IS NULL") + if column_exists('users', 'updated_at'): + op.execute("UPDATE users SET updated_at = datetime('now') WHERE updated_at IS NULL") def downgrade() -> None: diff --git a/app/models/user.py b/app/models/user.py index 3737515..24f9f1b 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -1,5 +1,5 @@ from sqlalchemy import Column, Integer, String, DateTime -from sqlalchemy.sql import func +from datetime import datetime from app.db.base import Base @@ -15,5 +15,12 @@ class User(Base): bio = Column(String, nullable=True) preferred_language = Column(String, default="en") timezone = Column(String, default="UTC") - created_at = Column(DateTime(timezone=True), server_default=func.now()) - updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) \ No newline at end of file + created_at = Column(DateTime(timezone=True), nullable=True) + updated_at = Column(DateTime(timezone=True), nullable=True) + + def __init__(self, **kwargs): + super().__init__(**kwargs) + if not self.created_at: + self.created_at = datetime.utcnow() + if not self.updated_at: + self.updated_at = datetime.utcnow() \ No newline at end of file diff --git a/app/routes/profile.py b/app/routes/profile.py index ba5a682..0f9986d 100644 --- a/app/routes/profile.py +++ b/app/routes/profile.py @@ -3,6 +3,7 @@ from sqlalchemy.orm import Session from pydantic import BaseModel, EmailStr from typing import Optional import logging +from datetime import datetime from app.db.session import get_db from app.models.user import User from app.utils.auth import get_current_user, get_password_hash, verify_password @@ -90,6 +91,9 @@ async def update_profile( if profile_data.timezone is not None: current_user.timezone = profile_data.timezone + # Update the timestamp manually + current_user.updated_at = datetime.utcnow() + db.commit() db.refresh(current_user) @@ -142,6 +146,7 @@ async def update_password( # Update password current_user.password_hash = get_password_hash(password_data.new_password) + current_user.updated_at = datetime.utcnow() db.commit() logger.info(f"Password updated successfully for user: {current_user.email}") @@ -185,6 +190,7 @@ async def update_email( old_email = current_user.email current_user.email = email_data.new_email + current_user.updated_at = datetime.utcnow() db.commit() logger.info(f"Email updated successfully from {old_email} to {email_data.new_email}")