From 4dec9ace88d8290cdf8147853244b3c9eb6408da Mon Sep 17 00:00:00 2001 From: Akshat Jain <125379408+akshat1423@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:20:40 +0530 Subject: [PATCH] Update support for unique user IDs (#2921) --- ...0efbd06b_add_unique_user_id_constraints.py | 36 +++++++++++++++++++ openmemory/api/app/models.py | 7 +++- openmemory/api/app/routers/memories.py | 3 +- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 openmemory/api/alembic/versions/afd00efbd06b_add_unique_user_id_constraints.py diff --git a/openmemory/api/alembic/versions/afd00efbd06b_add_unique_user_id_constraints.py b/openmemory/api/alembic/versions/afd00efbd06b_add_unique_user_id_constraints.py new file mode 100644 index 00000000..a685f4e2 --- /dev/null +++ b/openmemory/api/alembic/versions/afd00efbd06b_add_unique_user_id_constraints.py @@ -0,0 +1,36 @@ +"""remove_global_unique_constraint_on_app_name_add_composite_unique + +Revision ID: afd00efbd06b +Revises: add_config_table +Create Date: 2025-06-04 01:59:41.637440 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'afd00efbd06b' +down_revision: Union[str, None] = 'add_config_table' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('ix_apps_name', table_name='apps') + op.create_index(op.f('ix_apps_name'), 'apps', ['name'], unique=False) + op.create_index('idx_app_owner_name', 'apps', ['owner_id', 'name'], unique=True) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('idx_app_owner_name', table_name='apps') + op.drop_index(op.f('ix_apps_name'), table_name='apps') + op.create_index('ix_apps_name', 'apps', ['name'], unique=True) + # ### end Alembic commands ### \ No newline at end of file diff --git a/openmemory/api/app/models.py b/openmemory/api/app/models.py index 488b9e5e..7bc3546d 100644 --- a/openmemory/api/app/models.py +++ b/openmemory/api/app/models.py @@ -1,6 +1,7 @@ import enum import uuid import datetime +import sqlalchemy as sa from sqlalchemy import ( Column, String, Boolean, ForeignKey, Enum, Table, DateTime, JSON, Integer, UUID, Index, event @@ -43,7 +44,7 @@ class App(Base): __tablename__ = "apps" id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) owner_id = Column(UUID, ForeignKey("users.id"), nullable=False, index=True) - name = Column(String, unique=True, nullable=False, index=True) + name = Column(String, nullable=False, index=True) description = Column(String) metadata_ = Column('metadata', JSON, default=dict) is_active = Column(Boolean, default=True, index=True) @@ -55,6 +56,10 @@ class App(Base): owner = relationship("User", back_populates="apps") memories = relationship("Memory", back_populates="app") + __table_args__ = ( + sa.UniqueConstraint('owner_id', 'name', name='idx_app_owner_name'), + ) + class Config(Base): __tablename__ = "configs" diff --git a/openmemory/api/app/routers/memories.py b/openmemory/api/app/routers/memories.py index 61077b7e..ff7d3c4b 100644 --- a/openmemory/api/app/routers/memories.py +++ b/openmemory/api/app/routers/memories.py @@ -212,7 +212,8 @@ async def create_memory( if not user: raise HTTPException(status_code=404, detail="User not found") # Get or create app - app_obj = db.query(App).filter(App.name == request.app).first() + app_obj = db.query(App).filter(App.name == request.app, + App.owner_id == user.id).first() if not app_obj: app_obj = App(name=request.app, owner_id=user.id) db.add(app_obj)