Implemented API routes for getting all, creating, updating, and deleting resources, services, and tags.

This commit is contained in:
Aidan Kim 2024-10-14 18:30:35 -04:00
parent a43fb7429a
commit 4c3d49004a
11 changed files with 729 additions and 614 deletions

View File

@ -1,26 +1,43 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from ..services import ResourceService, UserService
from ..models.resource_model import Resource from backend.models.user_model import User
from ..services import ResourceService, UserService
from typing import List from ..models.resource_model import Resource
api = APIRouter(prefix="/api/resource") from typing import List
openapi_tags = { api = APIRouter(prefix="/api/resource")
"name": "Resource",
"description": "Resource search and related operations.", openapi_tags = {
} "name": "Resource",
"description": "Resource search and related operations.",
}
# TODO: Add security using HTTP Bearer Tokens
# TODO: Enable authorization by passing user uuid to API
# TODO: Create custom exceptions # TODO: Add security using HTTP Bearer Tokens
@api.get("", response_model=List[Resource], tags=["Resource"]) # TODO: Enable authorization by passing user uuid to API
def get_all( # TODO: Create custom exceptions
user_id: str, @api.post("", response_model=Resource, tags=["Resource"])
resource_svc: ResourceService = Depends(), def create(
user_svc: UserService = Depends(), subject: User, resource: Resource, resource_svc: ResourceService = Depends()
): ):
subject = user_svc.get_user_by_uuid(user_id) return resource_svc.create(subject, resource)
return resource_svc.get_resource_by_user(subject)
@api.get("", response_model=List[Resource], tags=["Resource"])
def get_all(subject: User, resource_svc: ResourceService = Depends()):
return resource_svc.get_resource_by_user(subject)
@api.put("", response_model=Resource, tags=["Resource"])
def update(
subject: User, resource: Resource, resource_svc: ResourceService = Depends()
):
return resource_svc.update(subject, resource)
@api.delete("", response_model=None, tags=["Resource"])
def delete(
subject: User, resource: Resource, resource_svc: ResourceService = Depends()
):
resource_svc.delete(subject, resource)

View File

@ -1,26 +1,50 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from ..services import ServiceService, UserService
from ..models.service_model import Service from backend.models.user_model import User
from ..services import ServiceService, UserService
from typing import List from ..models.service_model import Service
api = APIRouter(prefix="/api/service") from typing import List
openapi_tags = { api = APIRouter(prefix="/api/service")
"name": "Service",
"description": "Service search and related operations.", openapi_tags = {
} "name": "Service",
"description": "Service search and related operations.",
}
# TODO: Add security using HTTP Bearer Tokens
# TODO: Enable authorization by passing user uuid to API
# TODO: Create custom exceptions # TODO: Add security using HTTP Bearer Tokens
@api.get("", response_model=List[Service], tags=["Service"]) # TODO: Enable authorization by passing user uuid to API
def get_all( # TODO: Create custom exceptions
user_id: str, @api.post("", response_model=Service, tags=["Service"])
service_svc: ServiceService = Depends(), def create(
user_svc: UserService = Depends(), subject: User,
): service: Service,
subject = user_svc.get_user_by_uuid(user_id) service_svc: ServiceService = Depends()
):
return service_svc.get_service_by_user(subject) return service_svc.create(subject, service)
@api.get("", response_model=List[Service], tags=["Service"])
def get_all(
subject: User,
service_svc: ServiceService = Depends()
):
return service_svc.get_service_by_user(subject)
@api.put("", response_model=Service, tags=["Service"])
def update(
subject: User,
service: Service,
service_svc: ServiceService = Depends()
):
return service_svc.update(subject, service)
@api.delete("", response_model=None, tags=["Service"])
def delete(
subject: User,
service: Service,
service_svc: ServiceService = Depends()
):
service_svc.delete(subject, service)

51
backend/api/tag.py Normal file
View File

@ -0,0 +1,51 @@
from fastapi import APIRouter, Depends
from backend.models.tag_model import Tag
from backend.models.user_model import User
from backend.services.tag import TagService
from ..services import ResourceService, UserService
from ..models.resource_model import Resource
from typing import List
api = APIRouter(prefix="/api/tag")
openapi_tags = {
"name": "Tag",
"description": "Tag CRUD operations.",
}
# TODO: Add security using HTTP Bearer Tokens
# TODO: Enable authorization by passing user uuid to API
# TODO: Create custom exceptions
@api.post("", response_model=Tag, tags=["Tag"])
def create(
subject: User,
tag: Tag,
tag_service: TagService
):
return tag_service.create(subject, tag)
@api.get("", response_model=List[Tag], tags=["Tag"])
def get_all(
subject: User,
tag_svc: TagService
):
return tag_svc.get_all()
@api.put("", response_model=Tag, tags=["Tag"])
def delete(
subject: User,
tag: Tag,
tag_svc: TagService
):
return tag_svc.delete(subject, tag)
@api.delete("", response_model=None, tags=["Tag"])
def delete(
subject: User,
tag: Tag,
tag_svc: TagService
):
tag_svc.delete(subject, tag)

View File

@ -1,67 +1,65 @@
""" Defines the table for storing resources """ """ Defines the table for storing resources """
# Import our mapped SQL types from SQLAlchemy # Import our mapped SQL types from SQLAlchemy
from sqlalchemy import Integer, String, DateTime, Enum from sqlalchemy import ForeignKey, Integer, String, DateTime, Enum
# Import mapping capabilities from the SQLAlchemy ORM # Import mapping capabilities from the SQLAlchemy ORM
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
# Import the EntityBase that we are extending # Import the EntityBase that we are extending
from .entity_base import EntityBase from .entity_base import EntityBase
# Import datetime for created_at type # Import datetime for created_at type
from datetime import datetime from datetime import datetime
# Import self for to model # Import self for to model
from typing import Self from typing import Self
from backend.entities.program_enum import Program_Enum from backend.entities.program_enum import Program_Enum
from ..models.resource_model import Resource from ..models.resource_model import Resource
class ResourceEntity(EntityBase): class ResourceEntity(EntityBase):
# set table name # set table name
__tablename__ = "resource" __tablename__ = "resource"
# set fields # set fields
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
name: Mapped[str] = mapped_column(String(64), nullable=False) name: Mapped[str] = mapped_column(String(64), nullable=False)
summary: Mapped[str] = mapped_column(String(100), nullable=False) summary: Mapped[str] = mapped_column(String(100), nullable=False)
link: Mapped[str] = mapped_column(String, nullable=False) link: Mapped[str] = mapped_column(String, nullable=False)
program: Mapped[Program_Enum] = mapped_column(Enum(Program_Enum), nullable=False) program: Mapped[Program_Enum] = mapped_column(Enum(Program_Enum), nullable=False)
# relationships # relationships
resourceTags: Mapped[list["ResourceTagEntity"]] = relationship( tags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="resource")
back_populates="resource", cascade="all,delete"
) @classmethod
def from_model(cls, model: Resource) -> Self:
@classmethod """
def from_model(cls, model: Resource) -> Self: Create a UserEntity from a User model.
"""
Create a UserEntity from a User model. Args:
model (User): The model to create the entity from.
Args:
model (User): The model to create the entity from. Returns:
Self: The entity (not yet persisted).
Returns: """
Self: The entity (not yet persisted).
""" return cls(
id=model.id,
return cls( created_at=model.created_at,
id=model.id, name=model.name,
created_at=model.created_at, summary=model.summary,
name=model.name, link=model.link,
summary=model.summary, program=model.program,
link=model.link, )
program=model.program,
) def to_model(self) -> Resource:
return Resource(
def to_model(self) -> Resource: id=self.id,
return Resource( created_at=self.created_at,
id=self.id, name=self.name,
created_at=self.created_at, summary=self.summary,
name=self.name, link=self.link,
summary=self.summary, program=self.program,
link=self.link, )
program=self.program,
)

View File

@ -1,46 +1,44 @@
""" Defines the table for resource tags """ """ Defines the table for resource tags """
# Import our mapped SQL types from SQLAlchemy # Import our mapped SQL types from SQLAlchemy
from sqlalchemy import ForeignKey, Integer, String, DateTime from sqlalchemy import ForeignKey, Integer, String, DateTime
# Import mapping capabilities from the SQLAlchemy ORM # Import mapping capabilities from the SQLAlchemy ORM
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
# Import the EntityBase that we are extending # Import the EntityBase that we are extending
from .entity_base import EntityBase from .entity_base import EntityBase
# Import datetime for created_at type # Import datetime for created_at type
from datetime import datetime from datetime import datetime
# Import self for to model # Import self for to model
from typing import Self from typing import Self
class ResourceTagEntity(EntityBase): class ResourceTagEntity(EntityBase):
# set table name to user in the database # set table name to user in the database
__tablename__ = "resource_tag" __tablename__ = "resource_tag"
# set fields or 'columns' for the user table # set fields or 'columns' for the user table
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
resourceId: Mapped[int] = mapped_column(ForeignKey("resource.id")) resource_id: Mapped[int] = mapped_column(ForeignKey("resource.id"), primary_key=True)
tagId: Mapped[int] = mapped_column(ForeignKey("tag.id")) tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
resource: Mapped["ResourceEntity"] = mapped_column(backpopulates="tags")
# relationships tag: Mapped["TagEntity"] = mapped_column(backpopulates="resource_tags")
resource: Mapped["ResourceEntity"] = relationship(back_populates="resourceTags")
tag: Mapped["TagEntity"] = relationship(back_populates="resourceTags") # @classmethod
# def from_model (cls, model: resource_tag_model) -> Self:
# @classmethod # return cls (
# def from_model (cls, model: resource_tag_model) -> Self: # id = model.id,
# return cls ( # resourceId = model.resourceId,
# id = model.id, # tagId = model.tagId,
# resourceId = model.resourceId, # )
# tagId = model.tagId,
# ) # def to_model (self) -> resource_tag_model:
# return user_model(
# def to_model (self) -> resource_tag_model: # id = self.id,
# return user_model( # resourceId = self.resourceId,
# id = self.id, # tagId = self.tagId,
# resourceId = self.resourceId, # )
# tagId = self.tagId,
# )

View File

@ -1,47 +1,64 @@
""" Defines the table for storing services """ """ Defines the table for storing services """
# Import our mapped SQL types from SQLAlchemy # Import our mapped SQL types from SQLAlchemy
from sqlalchemy import Integer, String, DateTime, ARRAY from sqlalchemy import Integer, String, DateTime, ARRAY
# Import mapping capabilities from the SQLAlchemy ORM # Import mapping capabilities from the SQLAlchemy ORM
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
# Import the EntityBase that we are extending # Import the EntityBase that we are extending
from .entity_base import EntityBase from .entity_base import EntityBase
# Import datetime for created_at type # Import datetime for created_at type
from datetime import datetime from datetime import datetime
# Import enums for Program # Import enums for Program
import enum import enum
from sqlalchemy import Enum from sqlalchemy import Enum
from backend.models.service_model import Service from backend.models.service_model import Service
from typing import Self from typing import Self
from backend.models.enum_for_models import ProgramTypeEnum from backend.models.enum_for_models import ProgramTypeEnum
class ServiceEntity(EntityBase):
class ServiceEntity(EntityBase):
# set table name
__tablename__ = "service" # set table name
__tablename__ = "service"
# set fields
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) # set fields
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(32), nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
status: Mapped[str] = mapped_column(String(32), nullable=False) name: Mapped[str] = mapped_column(String(32), nullable=False)
summary: Mapped[str] = mapped_column(String(100), nullable=False) status: Mapped[str] = mapped_column(String(32), nullable=False)
requirements: Mapped[list[str]] = mapped_column(ARRAY(String)) summary: Mapped[str] = mapped_column(String(100), nullable=False)
program: Mapped[ProgramTypeEnum] = mapped_column(Enum(ProgramTypeEnum), nullable=False) requirements: Mapped[list[str]] = mapped_column(ARRAY(String))
program: Mapped[ProgramTypeEnum] = mapped_column(
# relationships Enum(ProgramTypeEnum), nullable=False
serviceTags: Mapped[list["ServiceTagEntity"]] = relationship( )
back_populates="service", cascade="all,delete"
) # relationships
tags: Mapped[list["ServiceTagEntity"]] = relationship(
def to_model(self) -> Service: back_populates="service", cascade="all,delete"
return Service(id=self.id, name=self.name, status=self.status, summary=self.summary, requirements=self.requirements, program=self.program) )
@classmethod def to_model(self) -> Service:
def from_model(cls, model:Service) -> Self: return Service(
return cls(id=model.id, name=model.name, status=model.status, summary=model.summary, requirements=model.requirements, program=model.program) id=self.id,
name=self.name,
status=self.status,
summary=self.summary,
requirements=self.requirements,
program=self.program,
)
@classmethod
def from_model(cls, model: Service) -> Self:
return cls(
id=model.id,
name=model.name,
status=model.status,
summary=model.summary,
requirements=model.requirements,
program=model.program,
)

View File

@ -1,25 +1,23 @@
""" Defines the table for service tags """ """ Defines the table for service tags """
# Import our mapped SQL types from SQLAlchemy # Import our mapped SQL types from SQLAlchemy
from sqlalchemy import ForeignKey, Integer from sqlalchemy import ForeignKey, Integer
# Import mapping capabilities from the SQLAlchemy ORM # Import mapping capabilities from the SQLAlchemy ORM
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
# Import the EntityBase that we are extending # Import the EntityBase that we are extending
from .entity_base import EntityBase from .entity_base import EntityBase
class ServiceTagEntity(EntityBase): class ServiceTagEntity(EntityBase):
# set table name to user in the database # set table name to user in the database
__tablename__ = "service_tag" __tablename__ = "service_tag"
# set fields or 'columns' for the user table # set fields or 'columns' for the user table
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
serviceId: Mapped[int] = mapped_column(ForeignKey("service.id")) resource_id: Mapped[int] = mapped_column(ForeignKey("service.id"), primary_key=True)
tagId: Mapped[int] = mapped_column(ForeignKey("tag.id")) tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
service: Mapped["ServiceEntity"] = mapped_column(backpopulates="tags")
# relationships tag: Mapped["TagEntity"] = mapped_column(backpopulates="service_tags")
service: Mapped["ServiceEntity"] = relationship(back_populates="serviceTags")
tag: Mapped["TagEntity"] = relationship(back_populates="serviceTags")

View File

@ -1,65 +1,63 @@
""" Defines the table for storing tags """ """ Defines the table for storing tags """
# Import our mapped SQL types from SQLAlchemy # Import our mapped SQL types from SQLAlchemy
from sqlalchemy import Integer, String, DateTime from sqlalchemy import Integer, String, DateTime
# Import mapping capabilities from the SQLAlchemy ORM # Import mapping capabilities from the SQLAlchemy ORM
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
# Import the EntityBase that we are extending # Import the EntityBase that we are extending
from .entity_base import EntityBase from .entity_base import EntityBase
# Import datetime for created_at type # Import datetime for created_at type
from datetime import datetime from datetime import datetime
from ..models.tag_model import Tag from ..models.tag_model import Tag
from typing import Self from typing import Self
class TagEntity(EntityBase):
class TagEntity(EntityBase):
#set table name
__tablename__ = "tag" # set table name
__tablename__ = "tag"
#set fields
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) # set fields
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
content: Mapped[str] = mapped_column(String(100), nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
content: Mapped[str] = mapped_column(String(100), nullable=False)
#relationships resource_tags: Mapped[list["ResourceTagEntity"]] = relationship(
resourceTags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete") back_populates="tag"
serviceTags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete") )
service_tags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag")
@classmethod
@classmethod def from_model(cls, model: Tag) -> Self:
def from_model(cls, model: Tag) -> Self: """
""" Create a user entity from model
Create a user entity from model
Args: model (User): the model to create the entity from
Args: model (User): the model to create the entity from
Returns:
Returns: self: The entity
self: The entity """
"""
return cls(
return cls( id=model.id,
id=model.id, content=model.id,
content=model.id, created_at=model.created_at
) )
def to_model(self) -> Tag: def to_model(self) -> Tag:
""" """
Create a user model from entity Create a user model from entity
Returns: Returns:
User: A User model for API usage User: A User model for API usage
""" """
return Tag( return Tag(
id=self.id, id=self.id,
content=self.content, content=self.content,
) created_at=self.created_at
)

View File

@ -1,165 +1,160 @@
from fastapi import Depends from fastapi import Depends
from ..database import db_session from ..database import db_session
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy import select from sqlalchemy import select
from ..models.resource_model import Resource from ..models.resource_model import Resource
from ..entities.resource_entity import ResourceEntity from ..entities.resource_entity import ResourceEntity
from ..models.user_model import User, UserTypeEnum from ..models.user_model import User, UserTypeEnum
from .exceptions import ResourceNotFoundException from .exceptions import ResourceNotFoundException
class ResourceService: class ResourceService:
def __init__(self, session: Session = Depends(db_session)): def __init__(self, session: Session = Depends(db_session)):
self._session = session self._session = session
def get_resource_by_user(self, subject: User): def get_resource_by_user(self, subject: User) -> list[Resource]:
"""Resource method getting all of the resources that a user has access to based on role""" """Resource method getting all of the resources that a user has access to based on role"""
if subject.role != UserTypeEnum.VOLUNTEER: if subject.role != UserTypeEnum.VOLUNTEER:
query = select(ResourceEntity) query = select(ResourceEntity)
entities = self._session.scalars(query).all() entities = self._session.scalars(query).all()
return [resource.to_model() for resource in entities]
return [resource.to_model() for resource in entities] else:
else: programs = subject.program
programs = subject.program resources = []
resources = [] for program in programs:
for program in programs: entities = self._session.query(ResourceEntity).where(ResourceEntity.program == program).all()
query = select(ResourceEntity).filter(ResourceEntity.program == program) for entity in entities:
entities = self._session.scalars(query).all() resources.append(entity.to_model())
for entity in entities: return [resource for resource in resources]
resources.append(entity)
def create(self, subject: User, resource: Resource) -> Resource:
return [resource.to_model() for resource in resources] """
Creates a resource based on the input object and adds it to the table if the user has the right permissions.
def create(self, user: User, resource: Resource) -> Resource:
""" Parameters:
Creates a resource based on the input object and adds it to the table if the user has the right permissions. user: a valid User model representing the currently logged in User
resource: Resource object to add to table
Parameters:
user: a valid User model representing the currently logged in User Returns:
resource: Resource object to add to table Resource: Object added to table
"""
Returns: # Ask about what the requirements for making a resource are.
Resource: Object added to table if resource.role != subject.role or resource.group != subject.group:
""" raise PermissionError(
if resource.role != user.role or resource.group != user.group: "User does not have permission to add resources in this role or group."
raise PermissionError( )
"User does not have permission to add resources in this role or group."
) resource_entity = ResourceEntity.from_model(resource)
self._session.add(resource_entity)
resource_entity = ResourceEntity.from_model(resource) self._session.commit()
self._session.add(resource_entity)
self._session.commit() return resource_entity.to_model()
return resource_entity.to_model() def get_by_id(self, user: User, id: int) -> Resource:
"""
def get_by_id(self, user: User, id: int) -> Resource: Gets a resource based on the resource id that the user has access to
"""
Gets a resource based on the resource id that the user has access to Parameters:
user: a valid User model representing the currently logged in User
Parameters: id: int, the id of the resource
user: a valid User model representing the currently logged in User
id: int, the id of the resource Returns:
Resource
Returns:
Resource Raises:
ResourceNotFoundException: If no resource is found with id
Raises: """
ResourceNotFoundException: If no resource is found with id resource = (
""" self._session.query(ResourceEntity)
resource = ( .filter(
self._session.query(ResourceEntity) ResourceEntity.id == id,
.filter( ResourceEntity.role == user.role,
ResourceEntity.id == id, ResourceEntity.group == user.group,
ResourceEntity.role == user.role, )
ResourceEntity.group == user.group, .one_or_none()
) )
.one_or_none()
) if resource is None:
raise ResourceNotFoundException(f"No resource found with id: {id}")
if resource is None:
raise ResourceNotFoundException(f"No resource found with id: {id}") return resource.to_model()
return resource.to_model() def update(self, subject: User, resource: Resource) -> Resource:
"""
def update(self, user: User, resource: ResourceEntity) -> Resource: Update the resource if the user has access
"""
Update the resource if the user has access Parameters:
user: a valid User model representing the currently logged in User
Parameters: resource (ResourceEntity): Resource to update
user: a valid User model representing the currently logged in User
resource (ResourceEntity): Resource to update Returns:
Resource: Updated resource object
Returns:
Resource: Updated resource object Raises:
ResourceNotFoundException: If no resource is found with the corresponding ID
Raises: """
ResourceNotFoundException: If no resource is found with the corresponding ID if resource.role != subject.role or resource.group != subject.group:
""" raise PermissionError(
if resource.role != user.role or resource.group != user.group: "User does not have permission to update this resource."
raise PermissionError( )
"User does not have permission to update this resource."
) query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
entity = self._session.scalars(query).one_or_none()
obj = self._session.get(ResourceEntity, resource.id) if resource.id else None
if entity is None:
if obj is None: raise ResourceNotFoundException(
raise ResourceNotFoundException( f"No resource found with matching id: {resource.id}"
f"No resource found with matching id: {resource.id}" )
)
entity.name = resource.name
obj.update_from_model(resource) # Assuming an update method exists entity.summary = resource.summary
self._session.commit() entity.link = resource.link
entity.program = resource.program
return obj.to_model() self._session.commit()
def delete(self, user: User, id: int) -> None: return entity.to_model()
"""
Delete resource based on id that the user has access to def delete(self, subject: User, resource: Resource) -> None:
"""
Parameters: Delete resource based on id that the user has access to
user: a valid User model representing the currently logged in User
id: int, a unique resource id Parameters:
user: a valid User model representing the currently logged in User
Raises: id: int, a unique resource id
ResourceNotFoundException: If no resource is found with the corresponding id
""" Raises:
resource = ( ResourceNotFoundException: If no resource is found with the corresponding id
self._session.query(ResourceEntity) """
.filter( query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
ResourceEntity.id == id, entity = self._session.scalars(query).one_or_none()
ResourceEntity.role == user.role,
ResourceEntity.group == user.group, if entity is None:
) raise ResourceNotFoundException(f"No resource found with matching id: {resource.id}")
.one_or_none()
) self._session.delete(entity)
self._session.commit()
if resource is None:
raise ResourceNotFoundException(f"No resource found with matching id: {id}") def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
"""
self._session.delete(resource) Get a list of resources given a search string that the user has access to
self._session.commit()
Parameters:
def get_by_slug(self, user: User, search_string: str) -> list[Resource]: user: a valid User model representing the currently logged in User
""" search_string: a string to search resources by
Get a list of resources given a search string that the user has access to
Returns:
Parameters: list[Resource]: list of resources relating to the string
user: a valid User model representing the currently logged in User
search_string: a string to search resources by Raises:
ResourceNotFoundException if no resource is found with the corresponding slug
Returns: """
list[Resource]: list of resources relating to the string query = select(ResourceEntity).where(
ResourceEntity.title.ilike(f"%{search_string}%"),
Raises: ResourceEntity.role == user.role,
ResourceNotFoundException if no resource is found with the corresponding slug ResourceEntity.group == user.group,
""" )
query = select(ResourceEntity).where( entities = self._session.scalars(query).all()
ResourceEntity.title.ilike(f"%{search_string}%"),
ResourceEntity.role == user.role, return [entity.to_model() for entity in entities]
ResourceEntity.group == user.group,
)
entities = self._session.scalars(query).all()
return [entity.to_model() for entity in entities]

View File

@ -1,127 +1,114 @@
from fastapi import Depends from fastapi import Depends
from ..database import db_session from ..database import db_session
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy import func, select, and_, func, or_, exists, or_ from sqlalchemy import func, select, and_, func, or_, exists, or_
from backend.models.service_model import Service from backend.models.service_model import Service
from backend.models.user_model import User from backend.models.user_model import User
from backend.entities.service_entity import ServiceEntity from backend.entities.service_entity import ServiceEntity
from backend.models.enum_for_models import ProgramTypeEnum, UserTypeEnum from backend.models.enum_for_models import ProgramTypeEnum, UserTypeEnum
from backend.services.exceptions import ( from backend.services.exceptions import (
ServiceNotFoundException, ServiceNotFoundException,
ProgramNotAssignedException, ProgramNotAssignedException,
) )
class ServiceService: class ServiceService:
def __init__(self, session: Session = Depends(db_session)): def __init__(self, session: Session = Depends(db_session)):
self._session = session self._session = session
def get_service_by_program(self, program: ProgramTypeEnum) -> list[Service]: def get_service_by_user(self, subject: User) -> list[Service]:
"""Service method getting services belonging to a particular program.""" """Resource method getting all of the resources that a user has access to based on role"""
query = select(ServiceEntity).filter(ServiceEntity.program == program) if subject.role != UserTypeEnum.VOLUNTEER:
entities = self._session.scalars(query) query = select(ServiceEntity)
entities = self._session.scalars(query).all()
return [entity.to_model() for entity in entities] return [service.to_model() for service in entities]
else:
def get_service_by_id(self, id: int) -> Service: programs = subject.program
"""Service method getting services by id.""" resources = []
query = select(ServiceEntity).filter(ServiceEntity.id == id) for program in programs:
entity = self._session.scalars(query).one_or_none() entities = self._session.query(ServiceEntity).where(ServiceEntity.program == program).all()
for entity in entities:
if entity is None: resources.append(entity.to_model())
raise ServiceNotFoundException(f"Service with id: {id} does not exist") return [service for service in resources]
return entity.to_model() def get_service_by_program(self, program: ProgramTypeEnum) -> list[Service]:
"""Service method getting services belonging to a particular program."""
def get_service_by_name(self, name: str) -> Service: query = select(ServiceEntity).filter(ServiceEntity.program == program)
"""Service method getting services by id.""" entities = self._session.scalars(query)
query = select(ServiceEntity).filter(ServiceEntity.name == name)
entity = self._session.scalars(query).one_or_none() return [entity.to_model() for entity in entities]
if entity is None: def get_service_by_id(self, id: int) -> Service:
raise ServiceNotFoundException(f"Service with name: {name} does not exist") """Service method getting services by id."""
query = select(ServiceEntity).filter(ServiceEntity.id == id)
return entity.to_model() entity = self._session.scalars(query).one_or_none()
def get_service_by_user(self, subject: User): if entity is None:
"""Service method getting all of the services that a user has access to based on role""" raise ServiceNotFoundException(f"Service with id: {id} does not exist")
if subject.role != UserTypeEnum.VOLUNTEER:
query = select(ServiceEntity) return entity.to_model()
entities = self._session.scalars(query).all()
def get_service_by_name(self, name: str) -> Service:
return [service.to_model() for service in entities] """Service method getting services by id."""
else: query = select(ServiceEntity).filter(ServiceEntity.name == name)
programs = subject.program entity = self._session.scalars(query).one_or_none()
services = []
for program in programs: if entity is None:
query = select(ServiceEntity).filter(ServiceEntity.program == program) raise ServiceNotFoundException(f"Service with name: {name} does not exist")
entities = self._session.scalars(query).all()
for entity in entities: return entity.to_model()
services.append(entity)
def create(self, subject: User, service: Service) -> Service:
return [service.to_model() for service in services] """Creates/adds a service to the table."""
if subject.role != UserTypeEnum.ADMIN:
def get_all(self, subject: User) -> list[Service]: raise ProgramNotAssignedException(
"""Service method retrieving all of the services in the table.""" f"User is not {UserTypeEnum.ADMIN}, cannot create service"
if subject.role == UserTypeEnum.VOLUNTEER: )
raise ProgramNotAssignedException(
f"User is not {UserTypeEnum.ADMIN} or {UserTypeEnum.VOLUNTEER}, cannot get all" service_entity = ServiceEntity.from_model(service)
) self._session.add(service_entity)
self._session.commit()
query = select(ServiceEntity) return service_entity.to_model()
entities = self._session.scalars(query).all()
def update(self, subject: User, service: Service) -> Service:
return [service.to_model() for service in entities] """Updates a service if in the table."""
if subject.role != UserTypeEnum.ADMIN:
def create(self, subject: User, service: Service) -> Service: raise ProgramNotAssignedException(
"""Creates/adds a service to the table.""" f"User is not {UserTypeEnum.ADMIN}, cannot update service"
if subject.role != UserTypeEnum.ADMIN: )
raise ProgramNotAssignedException(
f"User is not {UserTypeEnum.ADMIN}, cannot create service" query = select(ServiceEntity).where(ServiceEntity.id == service.id)
) entity = self._session.scalars(query).one_or_none()
service_entity = ServiceEntity.from_model(service) if entity is None:
self._session.add(service_entity) raise ServiceNotFoundException(
self._session.commit() "The service you are searching for does not exist."
return service_entity.to_model() )
def update(self, subject: User, service: Service) -> Service: entity.name = service.name
"""Updates a service if in the table.""" entity.status = service.status
if subject.role != UserTypeEnum.ADMIN: entity.summary = service.summary
raise ProgramNotAssignedException( entity.requirements = service.requirements
f"User is not {UserTypeEnum.ADMIN}, cannot update service" entity.program = service.program
) self._session.commit()
service_entity = self._session.get(ServiceEntity, service.id) return entity.to_model()
if service_entity is None: def delete(self, subject: User, service: Service) -> None:
raise ServiceNotFoundException( """Deletes a service from the table."""
"The service you are searching for does not exist." if subject.role != UserTypeEnum.ADMIN:
) raise ProgramNotAssignedException(f"User is not {UserTypeEnum.ADMIN}")
service_entity.name = service.name query = select(ServiceEntity).where(ServiceEntity.id == service.id)
service_entity.status = service.status entity = self._session.scalars(query).one_or_none()
service_entity.summary = service.summary
service_entity.requirements = service.requirements if entity is None:
service_entity.program = service.program raise ServiceNotFoundException(
"The service you are searching for does not exist."
self._session.commit() )
return service_entity.to_model() self._session.delete(entity)
self._session.commit()
def delete(self, subject: User, service: Service) -> None:
"""Deletes a service from the table."""
if subject.role != UserTypeEnum.ADMIN:
raise ProgramNotAssignedException(f"User is not {UserTypeEnum.ADMIN}")
service_entity = self._session.get(ServiceEntity, service.id)
if service_entity is None:
raise ServiceNotFoundException(
"The service you are searching for does not exist."
)
self._session.delete(service_entity)
self._session.commit()

View File

@ -1,20 +1,52 @@
from fastapi import Depends from fastapi import Depends
from ..database import db_session
from sqlalchemy.orm import Session from backend.models.enum_for_models import UserTypeEnum
from ..models.tag_model import Tag from backend.models.user_model import User
from ..entities.tag_entity import TagEntity from backend.services.exceptions import TagNotFoundException
from sqlalchemy import select from ..database import db_session
from sqlalchemy.orm import Session
from ..models.tag_model import Tag
class TagService: from ..entities.tag_entity import TagEntity
from sqlalchemy import select
def __init__(self, session: Session = Depends(db_session)):
self._session = session # Add in checks for user permission?
class TagService:
def all(self) -> list[Tag]:
"""Returns a list of all Tags""" def __init__(self, session: Session = Depends(db_session)):
self._session = session
query = select(TagEntity)
entities = self._session.scalars(query).all() def get_all(self) -> list[Tag]:
"""Returns a list of all Tags"""
return [entity.to_model() for entity in entities] query = select(TagEntity)
entities = self._session.scalars(query).all()
return [entity.to_model() for entity in entities]
def create(self, subject: User, tag: Tag) -> Tag:
entity = TagEntity.from_model(tag)
self._session.add(entity)
self._session.commit()
return entity.to_model()
def update(self, subject: User, tag: Tag) -> Tag:
query = select(TagEntity).where(TagEntity.id == tag.id)
entity = self._session.scalars(query).one_or_none()
if entity is None:
raise TagNotFoundException(f"Tag with id {tag.id} does not exist")
entity.content = tag.content
self._session.commit()
return entity.to_model()
def delete(self, subject: User, tag: Tag) -> None:
query = select(TagEntity).where(TagEntity.id == tag.id)
entity = self._session.scalars(query).one_or_none()
if entity is None:
raise TagNotFoundException(f"Tag with id {tag.id} does not exist")
self._session.delete(entity)
self._session.commit()