Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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 alembic.ini
Comment thread
DanielleBadobre marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne
# are written from script.py.mako
# output_encoding = utf-8

sqlalchemy.url =
sqlalchemy.url =


[post_write_hooks]
Expand Down
2 changes: 1 addition & 1 deletion api/v1/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
from api.v1.models.wishlist import Wishlist
from api.v1.models.totp_device import TOTPDevice
from api.v1.models.bookmark import Bookmark

from api.v1.models.feature_request import FeatureRequest
26 changes: 26 additions & 0 deletions api/v1/models/feature_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Feature Request data model
"""

from sqlalchemy import Column, String, text, Boolean, ForeignKey
from sqlalchemy.orm import relationship
from api.v1.models.base_model import BaseTableModel


class FeatureRequest(BaseTableModel):
__tablename__ = "feature_requests"

title = Column(String, nullable=False)
description = Column(String, nullable=False)
priority = Column(String, server_default=text("'Low'")) # Low, Medium, High
status = Column(String, server_default=text("'Pending'")) # Pending, Approved, Rejected
is_deleted = Column(Boolean, server_default=text("false"))

# Foreign Keys
user_id = Column(String, ForeignKey("users.id"), nullable=False)

# Relationships
user = relationship("User", back_populates="feature_requests")

def __str__(self):
return self.title
4 changes: 4 additions & 0 deletions api/v1/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ class User(BaseTableModel):
"Bookmark", back_populates="user", cascade="delete"
)

feature_requests = relationship(
"FeatureRequest", back_populates="user", cascade="all, delete-orphan"
)

def to_dict(self):
obj_dict = super().to_dict()
obj_dict.pop("password")
Expand Down
2 changes: 2 additions & 0 deletions api/v1/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from api.v1.routes.terms_and_conditions import terms_and_conditions
from api.v1.routes.stripe import subscription_
from api.v1.routes.wishlist import wishlist
from api.v1.routes.feature_request import feature_request

api_version_one = APIRouter(prefix="/api/v1")

Expand Down Expand Up @@ -98,3 +99,4 @@
api_version_one.include_router(product_comment)
api_version_one.include_router(subscription_)
api_version_one.include_router(wishlist)
api_version_one.include_router(feature_request)
126 changes: 126 additions & 0 deletions api/v1/routes/feature_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from api.db.database import get_db
from api.v1.schemas.feature_request import (
FeatureRequestCreate,
FeatureRequestResponse,
FeatureRequestUpdate
)
from api.v1.services.feature_request import FeatureRequestService
from api.v1.services.user import user_service
from api.v1.models.user import User

feature_request = APIRouter(prefix="/feature-request", tags=["Feature Requests"])


@feature_request.post("/", response_model=FeatureRequestResponse, status_code=status.HTTP_201_CREATED)
def create_feature_request(
feature_request_data: FeatureRequestCreate,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
):
"""
Create a new feature request
"""
return FeatureRequestService.create_feature_request(db, feature_request_data, current_user.id)


@feature_request.get("/", response_model=List[FeatureRequestResponse])
def get_feature_requests(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
):
"""
Get all feature requests
"""
# If user is a superadmin, return all feature requests
if current_user.is_superadmin:
return FeatureRequestService.get_feature_requests(db, skip, limit)
# Otherwise, return only the user's feature requests
return FeatureRequestService.get_user_feature_requests(db, current_user.id, skip, limit)


@feature_request.get("/{feature_request_id}", response_model=FeatureRequestResponse)
def get_feature_request(
feature_request_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
):
"""
Get a feature request by ID
"""
feature_request = FeatureRequestService.get_feature_request_by_id(db, feature_request_id)
if not feature_request:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Feature request not found"
)

# Check if the user is allowed to access this feature request
if not current_user.is_superadmin and feature_request.user_id != current_user.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not authorized to access this feature request"
)

return feature_request


@feature_request.put("/{feature_request_id}", response_model=FeatureRequestResponse)
def update_feature_request(
feature_request_id: str,
feature_request_update: FeatureRequestUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
):
"""
Update a feature request
"""
existing_feature_request = FeatureRequestService.get_feature_request_by_id(db, feature_request_id)
if not existing_feature_request:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Feature request not found"
)

# Check if the user is allowed to update this feature request
if not current_user.is_superadmin and existing_feature_request.user_id != current_user.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not authorized to update this feature request"
)

updated_feature_request = FeatureRequestService.update_feature_request(
db, feature_request_id, feature_request_update
)
return updated_feature_request


@feature_request.delete("/{feature_request_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_feature_request(
feature_request_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
):
"""
Delete a feature request
"""
existing_feature_request = FeatureRequestService.get_feature_request_by_id(db, feature_request_id)
if not existing_feature_request:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Feature request not found"
)

# Check if the user is allowed to delete this feature request
if not current_user.is_superadmin and existing_feature_request.user_id != current_user.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not authorized to delete this feature request"
)

FeatureRequestService.delete_feature_request(db, feature_request_id)
return None
36 changes: 36 additions & 0 deletions api/v1/schemas/feature_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field


class FeatureRequestBase(BaseModel):
title: str = Field(..., description="Title of the feature request")
description: str = Field(..., description="Detailed description of the requested feature")
priority: str = Field(default="Low", description="Priority level (Low, Medium, High)")
status: str = Field(default="Pending", description="Status (Pending, Approved, Rejected)")


class FeatureRequestCreate(FeatureRequestBase):
pass


class FeatureRequestUpdate(BaseModel):
title: Optional[str] = Field(None, description="Title of the feature request")
description: Optional[str] = Field(None, description="Detailed description of the requested feature")
priority: Optional[str] = Field(None, description="Priority level (Low, Medium, High)")
status: Optional[str] = Field(None, description="Status (Pending, Approved, Rejected)")


class FeatureRequestInDB(FeatureRequestBase):
id: str
created_at: datetime
updated_at: datetime
user_id: str
is_deleted: bool = False

class Config:
orm_mode = True


class FeatureRequestResponse(FeatureRequestInDB):
pass
77 changes: 77 additions & 0 deletions api/v1/services/feature_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
from api.v1.models.feature_request import FeatureRequest
from api.v1.schemas.feature_request import FeatureRequestCreate, FeatureRequestUpdate


class FeatureRequestService:
@staticmethod
def create_feature_request(db: Session, feature_request_data: FeatureRequestCreate, user_id: str):
db_feature_request = FeatureRequest(**feature_request_data.dict(), user_id=user_id)
db.add(db_feature_request)
db.commit()
db.refresh(db_feature_request)
return db_feature_request

@staticmethod
def get_feature_requests(db: Session, skip: int = 0, limit: int = 100):
return db.query(FeatureRequest).offset(skip).limit(limit).all()

@staticmethod
def get_user_feature_requests(db: Session, user_id: str, skip: int = 0, limit: int = 100):
return db.query(FeatureRequest).filter(FeatureRequest.user_id == user_id).offset(skip).limit(limit).all()

@staticmethod
def get_feature_request_by_id(db: Session, feature_request_id: str):
return db.query(FeatureRequest).filter(FeatureRequest.id == feature_request_id).first()

@staticmethod
def update_feature_request(db: Session, feature_request_id: str, feature_request_update: FeatureRequestUpdate):
db_feature_request = db.query(FeatureRequest).filter(FeatureRequest.id == feature_request_id).first()
if db_feature_request:
for key, value in feature_request_update.dict(exclude_unset=True).items():
setattr(db_feature_request, key, value)
db.commit()
db.refresh(db_feature_request)
return db_feature_request

@staticmethod
def delete_feature_request(db: Session, feature_request_id: str):
db_feature_request = db.query(FeatureRequest).filter(FeatureRequest.id == feature_request_id).first()
if db_feature_request:
db.delete(db_feature_request)
db.commit()
return db_feature_request
class FeatureRequestBase(BaseModel):
title: str = Field(..., description="Title of the feature request")
description: str = Field(..., description="Detailed description of the requested feature")
priority: str = Field(default="Low", description="Priority level (Low, Medium, High)")
status: str = Field(default="Pending", description="Status (Pending, Approved, Rejected)")


class FeatureRequestCreate(FeatureRequestBase):
pass


class FeatureRequestUpdate(BaseModel):
title: Optional[str] = Field(None, description="Title of the feature request")
description: Optional[str] = Field(None, description="Detailed description of the requested feature")
priority: Optional[str] = Field(None, description="Priority level (Low, Medium, High)")
status: Optional[str] = Field(None, description="Status (Pending, Approved, Rejected)")
Comment thread
DanielleBadobre marked this conversation as resolved.
Outdated


class FeatureRequestInDB(FeatureRequestBase):
id: str
created_at: datetime
updated_at: datetime
user_id: str
is_deleted: bool = False

class Config:
orm_mode = True


class FeatureRequestResponse(FeatureRequestInDB):
pass
Binary file added test.db
Binary file not shown.
Loading