Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TK-2] Document Interactions - Comments #27 #34

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ DocFlow is a powerful Document Management API designed to streamline document ha

## 😎 Upcoming Updates

- 🟨 Document Interactions - Adding Comments and Tags
- 🟨 Document Interactions - Adding Comments
- 🟨 Import documents from unread emails
- 🟨 Video Preview
- 🟨 Adding custom metadata fields to document
Expand Down
2 changes: 2 additions & 0 deletions app/api/router.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import APIRouter

from app.api.routes.auth.auth import router as auth_router
from app.api.routes.documents.comments import router as document_comment
from app.api.routes.documents.documents_metadata import (
router as documents_metadata_router,
)
Expand All @@ -15,6 +16,7 @@

router.include_router(auth_router, prefix="/u")
router.include_router(documents_router, prefix="")
router.include_router(document_comment, prefix="/comments")
router.include_router(notify_router, prefix="/notifications")
router.include_router(documents_metadata_router, prefix="/metadata")
router.include_router(document_organization_router, prefix="/filter")
Expand Down
67 changes: 67 additions & 0 deletions app/api/routes/documents/comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import List
from uuid import UUID

from fastapi import APIRouter, status, Depends

from app.api.dependencies.auth_utils import get_current_user
from app.api.dependencies.repositories import get_repository
from app.db.repositories.documents.comments import CommentRepository
from app.db.repositories.documents.documents import DocumentRepository
from app.schemas.auth.bands import TokenData
from app.schemas.documents.comments import CommentRead, CommentCreate, CommentUpdate

router = APIRouter(tags=["Comments"])


@router.post(
"/",
response_model=CommentRead,
status_code=status.HTTP_201_CREATED,
name="create_comment",
)
async def create_comment(
comment: CommentCreate,
user: TokenData = Depends(get_current_user),
doc_repo: DocumentRepository = Depends(get_repository(DocumentRepository)),
repository: CommentRepository = Depends(get_repository(CommentRepository)),
) -> CommentRead: ...


@router.get(
"/{doc_id}",
response_model=List[CommentRead],
status_code=status.HTTP_200_OK,
name="get_comments",
)
async def get_document_comments(
doc_id: UUID,
user: TokenData = Depends(get_current_user),
doc_repo: DocumentRepository = Depends(get_repository(DocumentRepository)),
repository: CommentRepository = Depends(get_repository(CommentRepository)),
) -> List[CommentRead]: ...


@router.put(
"/{comment_id}",
response_model=CommentRead,
status_code=status.HTTP_200_OK,
name="update_comment",
)
async def update_comment(
comment_id: UUID,
comment_update: CommentUpdate,
user: TokenData = Depends(get_current_user),
repository: CommentRepository = Depends(get_repository(CommentRepository)),
) -> CommentRead: ...


@router.delete(
"/{comment_id}",
status_code=status.HTTP_204_NO_CONTENT,
name="delete_comment",
)
async def delete_comment(
comment_id: UUID,
user: TokenData = Depends(get_current_user),
repository: CommentRepository = Depends(get_repository(CommentRepository)),
) -> None: ...
28 changes: 28 additions & 0 deletions app/db/repositories/documents/comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Optional, List
from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from app.db.tables.documents.documents_metadata import DocumentComment
from app.schemas.documents.comments import CommentCreate, CommentUpdate


class CommentRepository:
def __init__(self, session: AsyncSession):
self.session = session

async def create(
self, comment: CommentCreate, author_id: str
) -> DocumentComment: ...

async def get(self, comment_id: UUID) -> Optional[DocumentComment]: ...

async def get_document_comments(self, doc_id: UUID) -> List[DocumentComment]: ...

async def update(
self, comment_id: UUID, comment_update: CommentUpdate
) -> Optional[DocumentComment]: ...

async def delete(self, comment_id: UUID) -> bool: ...

async def user_can_modify(self, comment_id: UUID, user_id: str) -> bool: ...
1 change: 1 addition & 0 deletions app/db/tables/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class User(Base):
)

owner_of = relationship("DocumentMetadata", back_populates="owner")
comments = relationship("DocumentComment", back_populates="author")
34 changes: 33 additions & 1 deletion app/db/tables/documents/documents_metadata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime, timezone
from uuid import uuid4

from typing import List, Optional
from typing import List, Optional, Text
from sqlalchemy import (
Column,
String,
Expand Down Expand Up @@ -61,3 +61,35 @@ class DocumentMetadata(Base):
"User", secondary=doc_user_access, passive_deletes=True
)
owner = relationship("User", back_populates="owner_of")
comments = relationship(
"DocumentComment", back_populates="document", cascade="all, delete-orphan"
)


class DocumentComment(Base):
__tablename__ = "document_comments"

id: UUID = Column(
UUID(as_uuid=True), default=uuid4, primary_key=True, index=True, nullable=False
)
doc_id: UUID = Column(
UUID(as_uuid=True), ForeignKey("document_metadata.id", ondelete="CASCADE")
)
author_id: str = Column(String, ForeignKey("users.id"), nullable=False)
comment: str = Column(Text, nullable=False)
created_at = Column(
DateTime(timezone=True),
default=datetime.now(timezone.utc),
nullable=False,
server_default=text("NOW()"),
)
updated_at = Column(
DateTime(timezone=True),
default=datetime.now(timezone.utc),
onupdate=datetime.now(timezone.utc),
nullable=False,
server_default=text("NOW()"),
)

document = relationship("DocumentMetadata", back_populates="comments")
author = relationship("User", back_populates="comments")
5 changes: 5 additions & 0 deletions app/schemas/documents/bands.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,8 @@ class Notification(BaseModel):
class NotifyPatchStatus(BaseModel):
status: NotifyEnum = NotifyEnum.unread
mark_all: bool = False


# comments
class CommentBase(BaseModel):
comment: str
22 changes: 22 additions & 0 deletions app/schemas/documents/comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from datetime import datetime
from uuid import UUID

from app.schemas.documents.bands import CommentBase


class CommentCreate(CommentBase):
doc_id: UUID


class CommentUpdate(CommentBase): ...


class CommentRead(CommentBase):
id: UUID
doc_id: UUID
author_id: str
created_at: datetime
updated_at: datetime

class Config:
from_attribute = True
2 changes: 1 addition & 1 deletion migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from app.db.models import Base

from app.core.config import settings
from app.db.tables.documents.documents_metadata import DocumentMetadata
from app.db.tables.documents.documents_metadata import DocumentMetadata, DocumentComment
from app.db.tables.auth.auth import User
from app.db.tables.documents.document_sharing import DocumentSharing
from app.db.tables.documents.notify import Notify
Expand Down
1 change: 1 addition & 0 deletions migrations/versions/2a02384ab925_initial_almebic.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###

op.create_table(
"notify",
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
Expand Down
64 changes: 64 additions & 0 deletions migrations/versions/cb2ea87be0bd_document_comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""document comments

Revision ID: cb2ea87be0bd
Revises: 2a02384ab925
Create Date: 2024-12-15 01:24:30.954923

"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = "cb2ea87be0bd"
down_revision: Union[str, None] = "2a02384ab925"
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(
"document_comments",
sa.Column("id", sa.UUID(), nullable=False),
sa.Column("doc_id", sa.UUID(), nullable=True),
sa.Column("author_id", sa.String(), nullable=False),
sa.Column("comment", sa.Text(), nullable=False),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.text("NOW()"),
nullable=False,
),
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("NOW()"),
nullable=False,
),
sa.ForeignKeyConstraint(
["author_id"],
["users.id"],
),
sa.ForeignKeyConstraint(
["doc_id"], ["document_metadata.id"], ondelete="CASCADE"
),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(
op.f("ix_document_comments_id"), "document_comments", ["id"], unique=False
)
op.drop_index("ix_notify_id", table_name="notify")
op.create_unique_constraint(None, "share_url", ["url_id"])
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, "share_url", type_="unique")
op.drop_index(op.f("ix_document_comments_id"), table_name="document_comments")
op.drop_table("document_comments")
# ### end Alembic commands ###
Loading