diff --git a/src/backend/base/langflow/alembic/versions/e3bc869fa272_fix_nullable.py b/src/backend/base/langflow/alembic/versions/e3bc869fa272_fix_nullable.py index 594afefa1..f4ea219b0 100644 --- a/src/backend/base/langflow/alembic/versions/e3bc869fa272_fix_nullable.py +++ b/src/backend/base/langflow/alembic/versions/e3bc869fa272_fix_nullable.py @@ -9,7 +9,6 @@ from typing import Sequence, Union import sqlalchemy as sa from alembic import op -from sqlalchemy.dialects import postgresql from sqlalchemy.engine.reflection import Inspector # revision identifiers, used by Alembic. @@ -35,7 +34,9 @@ def upgrade() -> None: "created_at", existing_type=sa.TIMESTAMP(timezone=True), nullable=True, - existing_server_default=sa.text("now()"), + # existing_server_default expects str | bool | Identity | Computed | None + # sa.text("now()") is not a valid value for existing_server_default + existing_server_default=False, ) # ### end Alembic commands ### @@ -54,7 +55,7 @@ def downgrade() -> None: "created_at", existing_type=sa.TIMESTAMP(timezone=True), nullable=False, - existing_server_default=sa.text("now()"), + existing_server_default=False, ) # ### end Alembic commands ### diff --git a/src/backend/base/langflow/services/database/models/api_key/model.py b/src/backend/base/langflow/services/database/models/api_key/model.py index 9937e7e73..e110258b9 100644 --- a/src/backend/base/langflow/services/database/models/api_key/model.py +++ b/src/backend/base/langflow/services/database/models/api_key/model.py @@ -1,8 +1,8 @@ -from datetime import datetime +from datetime import datetime, timezone from typing import TYPE_CHECKING, Optional from uuid import UUID, uuid4 -from pydantic import validator +from pydantic import field_validator, validator from sqlmodel import Field, Relationship, SQLModel, Column, func, DateTime if TYPE_CHECKING: @@ -11,7 +11,9 @@ if TYPE_CHECKING: class ApiKeyBase(SQLModel): name: Optional[str] = Field(index=True, nullable=True, default=None) - created_at: datetime = Field(sa_column=Column(DateTime(timezone=True), server_default=func.now(), nullable=False)) + created_at: datetime = Field( + default=None, sa_column=Column(DateTime(timezone=True), server_default=func.now(), nullable=False) + ) last_used_at: Optional[datetime] = Field(default=None, nullable=True) total_uses: int = Field(default=0) is_active: bool = Field(default=True) @@ -33,6 +35,10 @@ class ApiKeyCreate(ApiKeyBase): api_key: Optional[str] = None user_id: Optional[UUID] = None + @field_validator("created_at", mode="before") + def set_created_at(cls, v): + return v or datetime.now(timezone.utc) + class UnmaskedApiKeyRead(ApiKeyBase): id: UUID diff --git a/src/backend/base/langflow/services/database/models/variable/model.py b/src/backend/base/langflow/services/database/models/variable/model.py index c8897098c..1fab92b4c 100644 --- a/src/backend/base/langflow/services/database/models/variable/model.py +++ b/src/backend/base/langflow/services/database/models/variable/model.py @@ -26,10 +26,12 @@ class Variable(VariableBase, table=True): ) # name is unique per user created_at: datetime = Field( + default=None, sa_column=Column(DateTime(timezone=True), server_default=func.now(), nullable=True), description="Creation time of the variable", ) updated_at: Optional[datetime] = Field( + default=None, sa_column=Column(DateTime(timezone=True), nullable=True), description="Last update time of the variable", ) diff --git a/tests/test_api_key.py b/tests/test_api_key.py index 31f484d60..92d649cae 100644 --- a/tests/test_api_key.py +++ b/tests/test_api_key.py @@ -1,5 +1,4 @@ import pytest - from langflow.services.database.models.api_key import ApiKeyCreate @@ -7,7 +6,7 @@ from langflow.services.database.models.api_key import ApiKeyCreate def api_key(client, logged_in_headers, active_user): api_key = ApiKeyCreate(name="test-api-key") - response = client.post("api/v1/api_key", data=api_key.json(), headers=logged_in_headers) + response = client.post("api/v1/api_key", data=api_key.model_dump_json(), headers=logged_in_headers) assert response.status_code == 200, response.text return response.json() diff --git a/tests/test_initial_setup.py b/tests/test_initial_setup.py index 815b28569..a8f4e8548 100644 --- a/tests/test_initial_setup.py +++ b/tests/test_initial_setup.py @@ -1,17 +1,12 @@ from datetime import datetime from pathlib import Path -import pytest -from langflow.graph.graph.base import Graph -from langflow.graph.schema import RunOutputs from langflow.initial_setup.setup import ( STARTER_FOLDER_NAME, create_or_update_starter_projects, get_project_data, load_starter_projects, ) -from langflow.memory import delete_messages -from langflow.processing.process import process_tweaks from langflow.services.database.models.flow.model import Flow from langflow.services.deps import session_scope from sqlalchemy import func diff --git a/tests/test_login.py b/tests/test_login.py index 29a8a852e..f4bc05bd5 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -1,8 +1,8 @@ import pytest from langflow.services.auth.utils import get_password_hash from langflow.services.database.models.user import User -from langflow.services.database.utils import session_getter -from langflow.services.deps import get_db_service +from langflow.services.deps import session_scope +from sqlalchemy.exc import IntegrityError @pytest.fixture @@ -17,9 +17,12 @@ def test_user(): def test_login_successful(client, test_user): # Adding the test user to the database - with session_getter(get_db_service()) as session: - session.add(test_user) - session.commit() + try: + with session_scope() as session: + session.add(test_user) + session.commit() + except IntegrityError: + pass response = client.post("api/v1/login", data={"username": "testuser", "password": "testpassword"}) assert response.status_code == 200