From 4c3d49004a66b0eeaf190d1e64ca5eba85d9dbb6 Mon Sep 17 00:00:00 2001
From: Aidan Kim <aidankim528@gmail.com>
Date: Mon, 14 Oct 2024 18:30:35 -0400
Subject: [PATCH 1/5] Implemented API routes for getting all, creating,
 updating, and deleting resources, services, and tags.

---
 backend/api/resource.py                 |  69 +++--
 backend/api/service.py                  |  76 ++++--
 backend/api/tag.py                      |  51 ++++
 backend/entities/resource_entity.py     | 132 +++++-----
 backend/entities/resource_tag_entity.py |  90 ++++---
 backend/entities/service_entity.py      | 111 ++++----
 backend/entities/service_tag_entity.py  |  48 ++--
 backend/entities/tag_entity.py          | 128 +++++-----
 backend/services/resource.py            | 325 ++++++++++++------------
 backend/services/service.py             | 241 +++++++++---------
 backend/services/tag.py                 |  72 ++++--
 11 files changed, 729 insertions(+), 614 deletions(-)
 create mode 100644 backend/api/tag.py

diff --git a/backend/api/resource.py b/backend/api/resource.py
index 98dcaae..0b11539 100644
--- a/backend/api/resource.py
+++ b/backend/api/resource.py
@@ -1,26 +1,43 @@
-from fastapi import APIRouter, Depends
-from ..services import ResourceService, UserService
-from ..models.resource_model import Resource
-
-from typing import List
-
-api = APIRouter(prefix="/api/resource")
-
-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
-@api.get("", response_model=List[Resource], tags=["Resource"])
-def get_all(
-    user_id: str,
-    resource_svc: ResourceService = Depends(),
-    user_svc: UserService = Depends(),
-):
-    subject = user_svc.get_user_by_uuid(user_id)
-
-    return resource_svc.get_resource_by_user(subject)
+from fastapi import APIRouter, Depends
+
+from backend.models.user_model import User
+from ..services import ResourceService, UserService
+from ..models.resource_model import Resource
+
+from typing import List
+
+api = APIRouter(prefix="/api/resource")
+
+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
+@api.post("", response_model=Resource, tags=["Resource"])
+def create(
+    subject: User, resource: Resource, resource_svc: ResourceService = Depends()
+):
+    return resource_svc.create(subject, resource)
+
+
+@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)
diff --git a/backend/api/service.py b/backend/api/service.py
index 97508a9..de73d13 100644
--- a/backend/api/service.py
+++ b/backend/api/service.py
@@ -1,26 +1,50 @@
-from fastapi import APIRouter, Depends
-from ..services import ServiceService, UserService
-from ..models.service_model import Service
-
-from typing import List
-
-api = APIRouter(prefix="/api/service")
-
-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
-@api.get("", response_model=List[Service], tags=["Service"])
-def get_all(
-    user_id: str,
-    service_svc: ServiceService = Depends(),
-    user_svc: UserService = Depends(),
-):
-    subject = user_svc.get_user_by_uuid(user_id)
-
-    return service_svc.get_service_by_user(subject)
+from fastapi import APIRouter, Depends
+
+from backend.models.user_model import User
+from ..services import ServiceService, UserService
+from ..models.service_model import Service
+
+from typing import List
+
+api = APIRouter(prefix="/api/service")
+
+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
+@api.post("", response_model=Service, tags=["Service"])
+def create(
+    subject: User,
+    service: Service,
+    service_svc: ServiceService = Depends()
+):
+    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)
diff --git a/backend/api/tag.py b/backend/api/tag.py
new file mode 100644
index 0000000..da6256f
--- /dev/null
+++ b/backend/api/tag.py
@@ -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)
diff --git a/backend/entities/resource_entity.py b/backend/entities/resource_entity.py
index 299decb..c510bf4 100644
--- a/backend/entities/resource_entity.py
+++ b/backend/entities/resource_entity.py
@@ -1,67 +1,65 @@
-""" Defines the table for storing resources """
-
-# Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import Integer, String, DateTime, Enum
-
-# Import mapping capabilities from the SQLAlchemy ORM
-from sqlalchemy.orm import Mapped, mapped_column, relationship
-
-# Import the EntityBase that we are extending
-from .entity_base import EntityBase
-
-# Import datetime for created_at type
-from datetime import datetime
-
-# Import self for to model
-from typing import Self
-from backend.entities.program_enum import Program_Enum
-from ..models.resource_model import Resource
-
-
-class ResourceEntity(EntityBase):
-
-    # set table name
-    __tablename__ = "resource"
-
-    # set fields
-    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
-    name: Mapped[str] = mapped_column(String(64), nullable=False)
-    summary: Mapped[str] = mapped_column(String(100), nullable=False)
-    link: Mapped[str] = mapped_column(String, nullable=False)
-    program: Mapped[Program_Enum] = mapped_column(Enum(Program_Enum), nullable=False)
-    # relationships
-    resourceTags: Mapped[list["ResourceTagEntity"]] = relationship(
-        back_populates="resource", cascade="all,delete"
-    )
-
-    @classmethod
-    def from_model(cls, model: Resource) -> Self:
-        """
-        Create a UserEntity from a User model.
-
-        Args:
-            model (User): The model to create the entity from.
-
-        Returns:
-            Self: The entity (not yet persisted).
-        """
-
-        return cls(
-            id=model.id,
-            created_at=model.created_at,
-            name=model.name,
-            summary=model.summary,
-            link=model.link,
-            program=model.program,
-        )
-
-    def to_model(self) -> Resource:
-        return Resource(
-            id=self.id,
-            created_at=self.created_at,
-            name=self.name,
-            summary=self.summary,
-            link=self.link,
-            program=self.program,
-        )
+""" Defines the table for storing resources """
+
+# Import our mapped SQL types from SQLAlchemy
+from sqlalchemy import ForeignKey, Integer, String, DateTime, Enum
+
+# Import mapping capabilities from the SQLAlchemy ORM
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+# Import the EntityBase that we are extending
+from .entity_base import EntityBase
+
+# Import datetime for created_at type
+from datetime import datetime
+
+# Import self for to model
+from typing import Self
+from backend.entities.program_enum import Program_Enum
+from ..models.resource_model import Resource
+
+
+class ResourceEntity(EntityBase):
+
+    # set table name
+    __tablename__ = "resource"
+
+    # set fields
+    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
+    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
+    name: Mapped[str] = mapped_column(String(64), nullable=False)
+    summary: Mapped[str] = mapped_column(String(100), nullable=False)
+    link: Mapped[str] = mapped_column(String, nullable=False)
+    program: Mapped[Program_Enum] = mapped_column(Enum(Program_Enum), nullable=False)
+    # relationships
+    tags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="resource")
+
+    @classmethod
+    def from_model(cls, model: Resource) -> Self:
+        """
+        Create a UserEntity from a User model.
+
+        Args:
+            model (User): The model to create the entity from.
+
+        Returns:
+            Self: The entity (not yet persisted).
+        """
+
+        return cls(
+            id=model.id,
+            created_at=model.created_at,
+            name=model.name,
+            summary=model.summary,
+            link=model.link,
+            program=model.program,
+        )
+
+    def to_model(self) -> Resource:
+        return Resource(
+            id=self.id,
+            created_at=self.created_at,
+            name=self.name,
+            summary=self.summary,
+            link=self.link,
+            program=self.program,
+        )
diff --git a/backend/entities/resource_tag_entity.py b/backend/entities/resource_tag_entity.py
index e6d863b..6ae5d1b 100644
--- a/backend/entities/resource_tag_entity.py
+++ b/backend/entities/resource_tag_entity.py
@@ -1,46 +1,44 @@
-""" Defines the table for resource tags """
-
-# Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import ForeignKey, Integer, String, DateTime
-
-# Import mapping capabilities from the SQLAlchemy ORM
-from sqlalchemy.orm import Mapped, mapped_column, relationship
-
-# Import the EntityBase that we are extending
-from .entity_base import EntityBase
-
-# Import datetime for created_at type
-from datetime import datetime
-
-# Import self for to model
-from typing import Self
-
-
-class ResourceTagEntity(EntityBase):
-
-    # set table name to user in the database
-    __tablename__ = "resource_tag"
-
-    # set fields or 'columns' for the user table
-    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    resourceId: Mapped[int] = mapped_column(ForeignKey("resource.id"))
-    tagId: Mapped[int] = mapped_column(ForeignKey("tag.id"))
-
-    # relationships
-    resource: Mapped["ResourceEntity"] = relationship(back_populates="resourceTags")
-    tag: Mapped["TagEntity"] = relationship(back_populates="resourceTags")
-
-    # @classmethod
-    # def from_model (cls, model: resource_tag_model) -> Self:
-    #     return cls (
-    #         id = model.id,
-    #         resourceId = model.resourceId,
-    #         tagId = model.tagId,
-    #     )
-
-    # def to_model (self) -> resource_tag_model:
-    #     return user_model(
-    #         id = self.id,
-    #         resourceId = self.resourceId,
-    #         tagId = self.tagId,
-    #     )
+""" Defines the table for resource tags """
+
+# Import our mapped SQL types from SQLAlchemy
+from sqlalchemy import ForeignKey, Integer, String, DateTime
+
+# Import mapping capabilities from the SQLAlchemy ORM
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+# Import the EntityBase that we are extending
+from .entity_base import EntityBase
+
+# Import datetime for created_at type
+from datetime import datetime
+
+# Import self for to model
+from typing import Self
+
+
+class ResourceTagEntity(EntityBase):
+
+    # set table name to user in the database
+    __tablename__ = "resource_tag"
+
+    # set fields or 'columns' for the user table
+    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
+    resource_id: Mapped[int] = mapped_column(ForeignKey("resource.id"), primary_key=True)
+    tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
+    resource: Mapped["ResourceEntity"] = mapped_column(backpopulates="tags")
+    tag: Mapped["TagEntity"] = mapped_column(backpopulates="resource_tags")
+
+    # @classmethod
+    # def from_model (cls, model: resource_tag_model) -> Self:
+    #     return cls (
+    #         id = model.id,
+    #         resourceId = model.resourceId,
+    #         tagId = model.tagId,
+    #     )
+
+    # def to_model (self) -> resource_tag_model:
+    #     return user_model(
+    #         id = self.id,
+    #         resourceId = self.resourceId,
+    #         tagId = self.tagId,
+    #     )
diff --git a/backend/entities/service_entity.py b/backend/entities/service_entity.py
index 4f1f9fc..63b2093 100644
--- a/backend/entities/service_entity.py
+++ b/backend/entities/service_entity.py
@@ -1,47 +1,64 @@
-""" Defines the table for storing services """
-
-# Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import Integer, String, DateTime, ARRAY
-
-# Import mapping capabilities from the SQLAlchemy ORM
-from sqlalchemy.orm import Mapped, mapped_column, relationship
-
-# Import the EntityBase that we are extending
-from .entity_base import EntityBase
-
-# Import datetime for created_at type
-from datetime import datetime
-
-# Import enums for Program
-import enum
-from sqlalchemy import Enum
-
-from backend.models.service_model import Service
-from typing import Self
-from backend.models.enum_for_models import ProgramTypeEnum
-
-class ServiceEntity(EntityBase):
-
-    # set table name
-    __tablename__ = "service"
-
-    # set fields
-    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
-    name: Mapped[str] = mapped_column(String(32), nullable=False)
-    status: Mapped[str] = mapped_column(String(32), nullable=False)
-    summary: Mapped[str] = mapped_column(String(100), nullable=False)
-    requirements: Mapped[list[str]] = mapped_column(ARRAY(String))
-    program: Mapped[ProgramTypeEnum] = mapped_column(Enum(ProgramTypeEnum), nullable=False)
-
-    # relationships
-    serviceTags: Mapped[list["ServiceTagEntity"]] = relationship(
-        back_populates="service", cascade="all,delete"
-    )
-
-    def to_model(self) -> Service:
-        return Service(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)
\ No newline at end of file
+""" Defines the table for storing services """
+
+# Import our mapped SQL types from SQLAlchemy
+from sqlalchemy import Integer, String, DateTime, ARRAY
+
+# Import mapping capabilities from the SQLAlchemy ORM
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+# Import the EntityBase that we are extending
+from .entity_base import EntityBase
+
+# Import datetime for created_at type
+from datetime import datetime
+
+# Import enums for Program
+import enum
+from sqlalchemy import Enum
+
+from backend.models.service_model import Service
+from typing import Self
+from backend.models.enum_for_models import ProgramTypeEnum
+
+
+class ServiceEntity(EntityBase):
+
+    # set table name
+    __tablename__ = "service"
+
+    # set fields
+    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
+    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
+    name: Mapped[str] = mapped_column(String(32), nullable=False)
+    status: Mapped[str] = mapped_column(String(32), nullable=False)
+    summary: Mapped[str] = mapped_column(String(100), nullable=False)
+    requirements: Mapped[list[str]] = mapped_column(ARRAY(String))
+    program: Mapped[ProgramTypeEnum] = mapped_column(
+        Enum(ProgramTypeEnum), nullable=False
+    )
+
+    # relationships
+    tags: Mapped[list["ServiceTagEntity"]] = relationship(
+        back_populates="service", cascade="all,delete"
+    )
+
+    def to_model(self) -> Service:
+        return Service(
+            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,
+        )
diff --git a/backend/entities/service_tag_entity.py b/backend/entities/service_tag_entity.py
index 0f05738..7896e56 100644
--- a/backend/entities/service_tag_entity.py
+++ b/backend/entities/service_tag_entity.py
@@ -1,25 +1,23 @@
-""" Defines the table for service tags """
-
-# Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import ForeignKey, Integer
-
-# Import mapping capabilities from the SQLAlchemy ORM
-from sqlalchemy.orm import Mapped, mapped_column, relationship
-
-# Import the EntityBase that we are extending
-from .entity_base import EntityBase
-
-
-class ServiceTagEntity(EntityBase):
-
-    # set table name to user in the database
-    __tablename__ = "service_tag"
-
-    # set fields or 'columns' for the user table
-    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    serviceId: Mapped[int] = mapped_column(ForeignKey("service.id"))
-    tagId: Mapped[int] = mapped_column(ForeignKey("tag.id"))
-
-    # relationships
-    service: Mapped["ServiceEntity"] = relationship(back_populates="serviceTags")
-    tag: Mapped["TagEntity"] = relationship(back_populates="serviceTags")
+""" Defines the table for service tags """
+
+# Import our mapped SQL types from SQLAlchemy
+from sqlalchemy import ForeignKey, Integer
+
+# Import mapping capabilities from the SQLAlchemy ORM
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+# Import the EntityBase that we are extending
+from .entity_base import EntityBase
+
+
+class ServiceTagEntity(EntityBase):
+
+    # set table name to user in the database
+    __tablename__ = "service_tag"
+
+    # set fields or 'columns' for the user table
+    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
+    resource_id: Mapped[int] = mapped_column(ForeignKey("service.id"), primary_key=True)
+    tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
+    service: Mapped["ServiceEntity"] = mapped_column(backpopulates="tags")
+    tag: Mapped["TagEntity"] = mapped_column(backpopulates="service_tags")
diff --git a/backend/entities/tag_entity.py b/backend/entities/tag_entity.py
index 0d1548b..b42616d 100644
--- a/backend/entities/tag_entity.py
+++ b/backend/entities/tag_entity.py
@@ -1,65 +1,63 @@
-""" Defines the table for storing tags """
-
-# Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import Integer, String, DateTime
-
-# Import mapping capabilities from the SQLAlchemy ORM
-from sqlalchemy.orm import Mapped, mapped_column, relationship
-
-# Import the EntityBase that we are extending
-from .entity_base import EntityBase
-
-# Import datetime for created_at type
-from datetime import datetime
-
-from ..models.tag_model import Tag
-
-from typing import Self
-
-class TagEntity(EntityBase):
-
-    #set table name
-    __tablename__ = "tag"
-
-    #set fields
-    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
-    content: Mapped[str] = mapped_column(String(100), nullable=False)
-
-    #relationships
-    resourceTags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete")
-    serviceTags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete")
-
-  
-    
-    @classmethod
-    def from_model(cls, model: Tag) -> Self:
-        """
-        Create a user entity from model
-
-        Args: model (User): the model to create the entity from
-
-        Returns:
-            self: The entity
-        """
-            
-        return cls(
-            id=model.id,
-            content=model.id,
-        )
-
-    def to_model(self) -> Tag:
-        """
-        Create a user model from entity
-
-        Returns:
-            User: A User model for API usage
-        """
-
-        return Tag(
-            id=self.id,
-            content=self.content,
-        )
-
-
-
+""" Defines the table for storing tags """
+
+# Import our mapped SQL types from SQLAlchemy
+from sqlalchemy import Integer, String, DateTime
+
+# Import mapping capabilities from the SQLAlchemy ORM
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+# Import the EntityBase that we are extending
+from .entity_base import EntityBase
+
+# Import datetime for created_at type
+from datetime import datetime
+
+from ..models.tag_model import Tag
+
+from typing import Self
+
+
+class TagEntity(EntityBase):
+
+    # set table name
+    __tablename__ = "tag"
+
+    # set fields
+    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
+    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
+    content: Mapped[str] = mapped_column(String(100), nullable=False)
+    resource_tags: Mapped[list["ResourceTagEntity"]] = relationship(
+        back_populates="tag"
+    )
+    service_tags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag")
+
+    @classmethod
+    def from_model(cls, model: Tag) -> Self:
+        """
+        Create a user entity from model
+
+        Args: model (User): the model to create the entity from
+
+        Returns:
+            self: The entity
+        """
+
+        return cls(
+            id=model.id,
+            content=model.id,
+            created_at=model.created_at
+        )
+
+    def to_model(self) -> Tag:
+        """
+        Create a user model from entity
+
+        Returns:
+            User: A User model for API usage
+        """
+
+        return Tag(
+            id=self.id,
+            content=self.content,
+            created_at=self.created_at
+        )
diff --git a/backend/services/resource.py b/backend/services/resource.py
index 2648ad6..2ccbee9 100644
--- a/backend/services/resource.py
+++ b/backend/services/resource.py
@@ -1,165 +1,160 @@
-from fastapi import Depends
-from ..database import db_session
-from sqlalchemy.orm import Session
-from sqlalchemy import select
-from ..models.resource_model import Resource
-from ..entities.resource_entity import ResourceEntity
-from ..models.user_model import User, UserTypeEnum
-
-from .exceptions import ResourceNotFoundException
-
-
-class ResourceService:
-
-    def __init__(self, session: Session = Depends(db_session)):
-        self._session = session
-
-    def get_resource_by_user(self, subject: User):
-        """Resource method getting all of the resources that a user has access to based on role"""
-        if subject.role != UserTypeEnum.VOLUNTEER:
-            query = select(ResourceEntity)
-            entities = self._session.scalars(query).all()
-
-            return [resource.to_model() for resource in entities]
-        else:
-            programs = subject.program
-            resources = []
-            for program in programs:
-                query = select(ResourceEntity).filter(ResourceEntity.program == program)
-                entities = self._session.scalars(query).all()
-                for entity in entities:
-                    resources.append(entity)
-
-            return [resource.to_model() for resource in resources]
-
-    def create(self, user: User, resource: Resource) -> Resource:
-        """
-        Creates a resource based on the input object and adds it to the table if the user has the right permissions.
-
-        Parameters:
-            user: a valid User model representing the currently logged in User
-            resource: Resource object to add to table
-
-        Returns:
-            Resource: Object added to table
-        """
-        if resource.role != user.role or resource.group != user.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)
-        self._session.commit()
-
-        return resource_entity.to_model()
-
-    def get_by_id(self, user: User, id: int) -> Resource:
-        """
-        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
-            id: int, the id of the resource
-
-        Returns:
-            Resource
-
-        Raises:
-            ResourceNotFoundException: If no resource is found with id
-        """
-        resource = (
-            self._session.query(ResourceEntity)
-            .filter(
-                ResourceEntity.id == id,
-                ResourceEntity.role == user.role,
-                ResourceEntity.group == user.group,
-            )
-            .one_or_none()
-        )
-
-        if resource is None:
-            raise ResourceNotFoundException(f"No resource found with id: {id}")
-
-        return resource.to_model()
-
-    def update(self, user: User, resource: ResourceEntity) -> Resource:
-        """
-        Update the resource if the user has access
-
-        Parameters:
-            user: a valid User model representing the currently logged in User
-            resource (ResourceEntity): Resource to update
-
-        Returns:
-            Resource: Updated resource object
-
-        Raises:
-            ResourceNotFoundException: If no resource is found with the corresponding ID
-        """
-        if resource.role != user.role or resource.group != user.group:
-            raise PermissionError(
-                "User does not have permission to update this resource."
-            )
-
-        obj = self._session.get(ResourceEntity, resource.id) if resource.id else None
-
-        if obj is None:
-            raise ResourceNotFoundException(
-                f"No resource found with matching id: {resource.id}"
-            )
-
-        obj.update_from_model(resource)  # Assuming an update method exists
-        self._session.commit()
-
-        return obj.to_model()
-
-    def delete(self, user: User, id: int) -> None:
-        """
-        Delete resource based on id that the user has access to
-
-        Parameters:
-            user: a valid User model representing the currently logged in User
-            id: int, a unique resource id
-
-        Raises:
-            ResourceNotFoundException: If no resource is found with the corresponding id
-        """
-        resource = (
-            self._session.query(ResourceEntity)
-            .filter(
-                ResourceEntity.id == id,
-                ResourceEntity.role == user.role,
-                ResourceEntity.group == user.group,
-            )
-            .one_or_none()
-        )
-
-        if resource is None:
-            raise ResourceNotFoundException(f"No resource found with matching id: {id}")
-
-        self._session.delete(resource)
-        self._session.commit()
-
-    def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
-        """
-        Get a list of resources given a search string that the user has access to
-
-        Parameters:
-            user: a valid User model representing the currently logged in User
-            search_string: a string to search resources by
-
-        Returns:
-            list[Resource]: list of resources relating to the string
-
-        Raises:
-            ResourceNotFoundException if no resource is found with the corresponding slug
-        """
-        query = select(ResourceEntity).where(
-            ResourceEntity.title.ilike(f"%{search_string}%"),
-            ResourceEntity.role == user.role,
-            ResourceEntity.group == user.group,
-        )
-        entities = self._session.scalars(query).all()
-
-        return [entity.to_model() for entity in entities]
+from fastapi import Depends
+from ..database import db_session
+from sqlalchemy.orm import Session
+from sqlalchemy import select
+from ..models.resource_model import Resource
+from ..entities.resource_entity import ResourceEntity
+from ..models.user_model import User, UserTypeEnum
+
+from .exceptions import ResourceNotFoundException
+
+
+class ResourceService:
+
+    def __init__(self, session: Session = Depends(db_session)):
+        self._session = session
+
+    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"""
+        if subject.role != UserTypeEnum.VOLUNTEER:
+            query = select(ResourceEntity)
+            entities = self._session.scalars(query).all()
+            return [resource.to_model() for resource in entities]
+        else:
+            programs = subject.program
+            resources = []
+            for program in programs:
+                entities = self._session.query(ResourceEntity).where(ResourceEntity.program == program).all()
+                for entity in entities:
+                    resources.append(entity.to_model())
+        return [resource for resource in resources]
+
+    def create(self, subject: User, resource: Resource) -> Resource:
+        """
+        Creates a resource based on the input object and adds it to the table if the user has the right permissions.
+
+        Parameters:
+            user: a valid User model representing the currently logged in User
+            resource: Resource object to add to table
+
+        Returns:
+            Resource: Object added to table
+        """
+        # Ask about what the requirements for making a resource are.
+        if resource.role != subject.role or resource.group != subject.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)
+        self._session.commit()
+
+        return resource_entity.to_model()
+
+    def get_by_id(self, user: User, id: int) -> Resource:
+        """
+        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
+            id: int, the id of the resource
+
+        Returns:
+            Resource
+
+        Raises:
+            ResourceNotFoundException: If no resource is found with id
+        """
+        resource = (
+            self._session.query(ResourceEntity)
+            .filter(
+                ResourceEntity.id == id,
+                ResourceEntity.role == user.role,
+                ResourceEntity.group == user.group,
+            )
+            .one_or_none()
+        )
+
+        if resource is None:
+            raise ResourceNotFoundException(f"No resource found with id: {id}")
+
+        return resource.to_model()
+
+    def update(self, subject: User, resource: Resource) -> Resource:
+        """
+        Update the resource if the user has access
+
+        Parameters:
+            user: a valid User model representing the currently logged in User
+            resource (ResourceEntity): Resource to update
+
+        Returns:
+            Resource: Updated resource object
+
+        Raises:
+            ResourceNotFoundException: If no resource is found with the corresponding ID
+        """
+        if resource.role != subject.role or resource.group != subject.group:
+            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()
+
+        if entity is None:
+            raise ResourceNotFoundException(
+                f"No resource found with matching id: {resource.id}"
+            )
+
+        entity.name = resource.name
+        entity.summary = resource.summary
+        entity.link = resource.link
+        entity.program = resource.program
+        self._session.commit()
+
+        return entity.to_model()
+
+    def delete(self, subject: User, resource: Resource) -> None:
+        """
+        Delete resource based on id that the user has access to
+
+        Parameters:
+            user: a valid User model representing the currently logged in User
+            id: int, a unique resource id
+
+        Raises:
+            ResourceNotFoundException: If no resource is found with the corresponding id
+        """
+        query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
+        entity = self._session.scalars(query).one_or_none()
+
+        if entity is None:
+            raise ResourceNotFoundException(f"No resource found with matching id: {resource.id}")
+
+        self._session.delete(entity)
+        self._session.commit()
+
+    def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
+        """
+        Get a list of resources given a search string that the user has access to
+
+        Parameters:
+            user: a valid User model representing the currently logged in User
+            search_string: a string to search resources by
+
+        Returns:
+            list[Resource]: list of resources relating to the string
+
+        Raises:
+            ResourceNotFoundException if no resource is found with the corresponding slug
+        """
+        query = select(ResourceEntity).where(
+            ResourceEntity.title.ilike(f"%{search_string}%"),
+            ResourceEntity.role == user.role,
+            ResourceEntity.group == user.group,
+        )
+        entities = self._session.scalars(query).all()
+
+        return [entity.to_model() for entity in entities]
diff --git a/backend/services/service.py b/backend/services/service.py
index f8afe2e..edce109 100644
--- a/backend/services/service.py
+++ b/backend/services/service.py
@@ -1,127 +1,114 @@
-from fastapi import Depends
-
-from ..database import db_session
-from sqlalchemy.orm import Session
-from sqlalchemy import func, select, and_, func, or_, exists, or_
-
-from backend.models.service_model import Service
-from backend.models.user_model import User
-from backend.entities.service_entity import ServiceEntity
-from backend.models.enum_for_models import ProgramTypeEnum, UserTypeEnum
-from backend.services.exceptions import (
-    ServiceNotFoundException,
-    ProgramNotAssignedException,
-)
-
-
-class ServiceService:
-
-    def __init__(self, session: Session = Depends(db_session)):
-        self._session = session
-
-    def get_service_by_program(self, program: ProgramTypeEnum) -> list[Service]:
-        """Service method getting services belonging to a particular program."""
-        query = select(ServiceEntity).filter(ServiceEntity.program == program)
-        entities = self._session.scalars(query)
-
-        return [entity.to_model() for entity in entities]
-
-    def get_service_by_id(self, id: int) -> Service:
-        """Service method getting services by id."""
-        query = select(ServiceEntity).filter(ServiceEntity.id == id)
-        entity = self._session.scalars(query).one_or_none()
-
-        if entity is None:
-            raise ServiceNotFoundException(f"Service with id: {id} does not exist")
-
-        return entity.to_model()
-
-    def get_service_by_name(self, name: str) -> Service:
-        """Service method getting services by id."""
-        query = select(ServiceEntity).filter(ServiceEntity.name == name)
-        entity = self._session.scalars(query).one_or_none()
-
-        if entity is None:
-            raise ServiceNotFoundException(f"Service with name: {name} does not exist")
-
-        return entity.to_model()
-
-    def get_service_by_user(self, subject: User):
-        """Service method getting all of the services that a user has access to based on role"""
-        if subject.role != UserTypeEnum.VOLUNTEER:
-            query = select(ServiceEntity)
-            entities = self._session.scalars(query).all()
-
-            return [service.to_model() for service in entities]
-        else:
-            programs = subject.program
-            services = []
-            for program in programs:
-                query = select(ServiceEntity).filter(ServiceEntity.program == program)
-                entities = self._session.scalars(query).all()
-                for entity in entities:
-                    services.append(entity)
-
-            return [service.to_model() for service in services]
-
-    def get_all(self, subject: User) -> list[Service]:
-        """Service method retrieving all of the services in the table."""
-        if subject.role == UserTypeEnum.VOLUNTEER:
-            raise ProgramNotAssignedException(
-                f"User is not {UserTypeEnum.ADMIN} or {UserTypeEnum.VOLUNTEER}, cannot get all"
-            )
-
-        query = select(ServiceEntity)
-        entities = self._session.scalars(query).all()
-
-        return [service.to_model() for service in entities]
-
-    def create(self, subject: User, service: Service) -> Service:
-        """Creates/adds a service to the table."""
-        if subject.role != UserTypeEnum.ADMIN:
-            raise ProgramNotAssignedException(
-                f"User is not {UserTypeEnum.ADMIN}, cannot create service"
-            )
-
-        service_entity = ServiceEntity.from_model(service)
-        self._session.add(service_entity)
-        self._session.commit()
-        return service_entity.to_model()
-
-    def update(self, subject: User, service: Service) -> Service:
-        """Updates a service if in the table."""
-        if subject.role != UserTypeEnum.ADMIN:
-            raise ProgramNotAssignedException(
-                f"User is not {UserTypeEnum.ADMIN}, cannot update service"
-            )
-
-        service_entity = self._session.get(ServiceEntity, service.id)
-
-        if service_entity is None:
-            raise ServiceNotFoundException(
-                "The service you are searching for does not exist."
-            )
-
-        service_entity.name = service.name
-        service_entity.status = service.status
-        service_entity.summary = service.summary
-        service_entity.requirements = service.requirements
-        service_entity.program = service.program
-
-        self._session.commit()
-
-        return service_entity.to_model()
-
-    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()
+from fastapi import Depends
+
+from ..database import db_session
+from sqlalchemy.orm import Session
+from sqlalchemy import func, select, and_, func, or_, exists, or_
+
+from backend.models.service_model import Service
+from backend.models.user_model import User
+from backend.entities.service_entity import ServiceEntity
+from backend.models.enum_for_models import ProgramTypeEnum, UserTypeEnum
+from backend.services.exceptions import (
+    ServiceNotFoundException,
+    ProgramNotAssignedException,
+)
+
+
+class ServiceService:
+
+    def __init__(self, session: Session = Depends(db_session)):
+        self._session = session
+
+    def get_service_by_user(self, subject: User) -> list[Service]:
+        """Resource method getting all of the resources that a user has access to based on role"""
+        if subject.role != UserTypeEnum.VOLUNTEER:
+            query = select(ServiceEntity)
+            entities = self._session.scalars(query).all()
+            return [service.to_model() for service in entities]
+        else:
+            programs = subject.program
+            resources = []
+            for program in programs:
+                entities = self._session.query(ServiceEntity).where(ServiceEntity.program == program).all()
+                for entity in entities:
+                    resources.append(entity.to_model())
+        return [service for service in resources]
+
+    def get_service_by_program(self, program: ProgramTypeEnum) -> list[Service]:
+        """Service method getting services belonging to a particular program."""
+        query = select(ServiceEntity).filter(ServiceEntity.program == program)
+        entities = self._session.scalars(query)
+
+        return [entity.to_model() for entity in entities]
+
+    def get_service_by_id(self, id: int) -> Service:
+        """Service method getting services by id."""
+        query = select(ServiceEntity).filter(ServiceEntity.id == id)
+        entity = self._session.scalars(query).one_or_none()
+
+        if entity is None:
+            raise ServiceNotFoundException(f"Service with id: {id} does not exist")
+
+        return entity.to_model()
+
+    def get_service_by_name(self, name: str) -> Service:
+        """Service method getting services by id."""
+        query = select(ServiceEntity).filter(ServiceEntity.name == name)
+        entity = self._session.scalars(query).one_or_none()
+
+        if entity is None:
+            raise ServiceNotFoundException(f"Service with name: {name} does not exist")
+
+        return entity.to_model()
+
+    def create(self, subject: User, service: Service) -> Service:
+        """Creates/adds a service to the table."""
+        if subject.role != UserTypeEnum.ADMIN:
+            raise ProgramNotAssignedException(
+                f"User is not {UserTypeEnum.ADMIN}, cannot create service"
+            )
+
+        service_entity = ServiceEntity.from_model(service)
+        self._session.add(service_entity)
+        self._session.commit()
+        return service_entity.to_model()
+
+    def update(self, subject: User, service: Service) -> Service:
+        """Updates a service if in the table."""
+        if subject.role != UserTypeEnum.ADMIN:
+            raise ProgramNotAssignedException(
+                f"User is not {UserTypeEnum.ADMIN}, cannot update service"
+            )
+        
+        query = select(ServiceEntity).where(ServiceEntity.id == service.id)
+        entity = self._session.scalars(query).one_or_none()
+
+        if entity is None:
+            raise ServiceNotFoundException(
+                "The service you are searching for does not exist."
+            )
+
+        entity.name = service.name
+        entity.status = service.status
+        entity.summary = service.summary
+        entity.requirements = service.requirements
+        entity.program = service.program
+        self._session.commit()
+
+        return entity.to_model()
+
+    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}")
+        
+        query = select(ServiceEntity).where(ServiceEntity.id == service.id)
+        entity = self._session.scalars(query).one_or_none()
+
+        if entity is None:
+            raise ServiceNotFoundException(
+                "The service you are searching for does not exist."
+            )
+
+        self._session.delete(entity)
+        self._session.commit()
diff --git a/backend/services/tag.py b/backend/services/tag.py
index dfc369a..b2299bd 100644
--- a/backend/services/tag.py
+++ b/backend/services/tag.py
@@ -1,20 +1,52 @@
-from fastapi import Depends
-from ..database import db_session
-from sqlalchemy.orm import Session
-from ..models.tag_model import Tag
-from ..entities.tag_entity import TagEntity
-from sqlalchemy import select
-
-
-class TagService:
-
-    def __init__(self, session: Session = Depends(db_session)):
-        self._session = session
-
-    def all(self) -> list[Tag]:
-        """Returns a list of all Tags"""
-
-        query = select(TagEntity)   
-        entities = self._session.scalars(query).all()
-
-        return [entity.to_model() for entity in entities]
+from fastapi import Depends
+
+from backend.models.enum_for_models import UserTypeEnum
+from backend.models.user_model import User
+from backend.services.exceptions import TagNotFoundException
+from ..database import db_session
+from sqlalchemy.orm import Session
+from ..models.tag_model import Tag
+from ..entities.tag_entity import TagEntity
+from sqlalchemy import select
+
+# Add in checks for user permission?
+class TagService:
+
+    def __init__(self, session: Session = Depends(db_session)):
+        self._session = session
+
+    def get_all(self) -> list[Tag]:
+        """Returns a list of all Tags"""
+        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()
+

From a563ca2bfa9bc982945081e76963cf6e52fd222b Mon Sep 17 00:00:00 2001
From: Aidan Kim <aidankim528@gmail.com>
Date: Tue, 15 Oct 2024 19:49:47 -0400
Subject: [PATCH 2/5] Updated main.py for API routes to include tags and rolled
 entities back.

---
 backend/api/tag.py                      | 10 ++--
 backend/entities/resource_entity.py     |  8 +--
 backend/entities/resource_tag_entity.py | 12 +++--
 backend/entities/service_entity.py      | 27 ++--------
 backend/entities/service_tag_entity.py  | 11 ++--
 backend/entities/tag_entity.py          | 23 ++++----
 backend/main.py                         | 71 +++++++++++++------------
 7 files changed, 78 insertions(+), 84 deletions(-)

diff --git a/backend/api/tag.py b/backend/api/tag.py
index da6256f..36e7e4a 100644
--- a/backend/api/tag.py
+++ b/backend/api/tag.py
@@ -23,22 +23,22 @@ openapi_tags = {
 def create(
     subject: User,
     tag: Tag,
-    tag_service: TagService
+    tag_service: TagService=Depends()
 ):
     return tag_service.create(subject, tag)
 
 @api.get("", response_model=List[Tag], tags=["Tag"])
 def get_all(
     subject: User,
-    tag_svc: TagService
+    tag_svc: TagService=Depends()
 ):
     return tag_svc.get_all()
 
 @api.put("", response_model=Tag, tags=["Tag"])
-def delete(
+def update(
     subject: User,
     tag: Tag,
-    tag_svc: TagService
+    tag_svc: TagService=Depends()
 ):
     return tag_svc.delete(subject, tag)
 
@@ -46,6 +46,6 @@ def delete(
 def delete(
     subject: User,
     tag: Tag,
-    tag_svc: TagService
+    tag_svc: TagService=Depends()
 ):
     tag_svc.delete(subject, tag)
diff --git a/backend/entities/resource_entity.py b/backend/entities/resource_entity.py
index c510bf4..208929b 100644
--- a/backend/entities/resource_entity.py
+++ b/backend/entities/resource_entity.py
@@ -1,7 +1,7 @@
 """ Defines the table for storing resources """
 
 # Import our mapped SQL types from SQLAlchemy
-from sqlalchemy import ForeignKey, Integer, String, DateTime, Enum
+from sqlalchemy import Integer, String, DateTime, Enum
 
 # Import mapping capabilities from the SQLAlchemy ORM
 from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -31,7 +31,9 @@ class ResourceEntity(EntityBase):
     link: Mapped[str] = mapped_column(String, nullable=False)
     program: Mapped[Program_Enum] = mapped_column(Enum(Program_Enum), nullable=False)
     # relationships
-    tags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="resource")
+    resourceTags: Mapped[list["ResourceTagEntity"]] = relationship(
+        back_populates="resource", cascade="all,delete"
+    )
 
     @classmethod
     def from_model(cls, model: Resource) -> Self:
@@ -62,4 +64,4 @@ class ResourceEntity(EntityBase):
             summary=self.summary,
             link=self.link,
             program=self.program,
-        )
+        )
\ No newline at end of file
diff --git a/backend/entities/resource_tag_entity.py b/backend/entities/resource_tag_entity.py
index 6ae5d1b..53a9323 100644
--- a/backend/entities/resource_tag_entity.py
+++ b/backend/entities/resource_tag_entity.py
@@ -23,10 +23,12 @@ class ResourceTagEntity(EntityBase):
 
     # set fields or 'columns' for the user table
     id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    resource_id: Mapped[int] = mapped_column(ForeignKey("resource.id"), primary_key=True)
-    tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
-    resource: Mapped["ResourceEntity"] = mapped_column(backpopulates="tags")
-    tag: Mapped["TagEntity"] = mapped_column(backpopulates="resource_tags")
+    resourceId: Mapped[int] = mapped_column(ForeignKey("resource.id"))
+    tagId: Mapped[int] = mapped_column(ForeignKey("tag.id"))
+
+    # relationships
+    resource: Mapped["ResourceEntity"] = relationship(back_populates="resourceTags")
+    tag: Mapped["TagEntity"] = relationship(back_populates="resourceTags")
 
     # @classmethod
     # def from_model (cls, model: resource_tag_model) -> Self:
@@ -41,4 +43,4 @@ class ResourceTagEntity(EntityBase):
     #         id = self.id,
     #         resourceId = self.resourceId,
     #         tagId = self.tagId,
-    #     )
+    #     )
\ No newline at end of file
diff --git a/backend/entities/service_entity.py b/backend/entities/service_entity.py
index 63b2093..809f5d9 100644
--- a/backend/entities/service_entity.py
+++ b/backend/entities/service_entity.py
@@ -20,7 +20,6 @@ from backend.models.service_model import Service
 from typing import Self
 from backend.models.enum_for_models import ProgramTypeEnum
 
-
 class ServiceEntity(EntityBase):
 
     # set table name
@@ -33,32 +32,16 @@ class ServiceEntity(EntityBase):
     status: Mapped[str] = mapped_column(String(32), nullable=False)
     summary: Mapped[str] = mapped_column(String(100), nullable=False)
     requirements: Mapped[list[str]] = mapped_column(ARRAY(String))
-    program: Mapped[ProgramTypeEnum] = mapped_column(
-        Enum(ProgramTypeEnum), nullable=False
-    )
+    program: Mapped[ProgramTypeEnum] = mapped_column(Enum(ProgramTypeEnum), nullable=False)
 
     # relationships
-    tags: Mapped[list["ServiceTagEntity"]] = relationship(
+    serviceTags: Mapped[list["ServiceTagEntity"]] = relationship(
         back_populates="service", cascade="all,delete"
     )
 
     def to_model(self) -> Service:
-        return Service(
-            id=self.id,
-            name=self.name,
-            status=self.status,
-            summary=self.summary,
-            requirements=self.requirements,
-            program=self.program,
-        )
+        return Service(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,
-        )
+    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)
\ No newline at end of file
diff --git a/backend/entities/service_tag_entity.py b/backend/entities/service_tag_entity.py
index 7896e56..6d4e908 100644
--- a/backend/entities/service_tag_entity.py
+++ b/backend/entities/service_tag_entity.py
@@ -17,7 +17,10 @@ class ServiceTagEntity(EntityBase):
 
     # set fields or 'columns' for the user table
     id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
-    resource_id: Mapped[int] = mapped_column(ForeignKey("service.id"), primary_key=True)
-    tag_id: Mapped[int] = mapped_column(ForeignKey("tag.id", primary_key=True))
-    service: Mapped["ServiceEntity"] = mapped_column(backpopulates="tags")
-    tag: Mapped["TagEntity"] = mapped_column(backpopulates="service_tags")
+    serviceId: Mapped[int] = mapped_column(ForeignKey("service.id"))
+    tagId: Mapped[int] = mapped_column(ForeignKey("tag.id"))
+
+    # relationships
+    service: Mapped["ServiceEntity"] = relationship(back_populates="serviceTags")
+    tag: Mapped["TagEntity"] = relationship(back_populates="serviceTags")
+    
\ No newline at end of file
diff --git a/backend/entities/tag_entity.py b/backend/entities/tag_entity.py
index b42616d..3916798 100644
--- a/backend/entities/tag_entity.py
+++ b/backend/entities/tag_entity.py
@@ -16,21 +16,22 @@ from ..models.tag_model import Tag
 
 from typing import Self
 
-
 class TagEntity(EntityBase):
 
-    # set table name
+    #set table name
     __tablename__ = "tag"
 
-    # set fields
+    #set fields
     id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
     created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
     content: Mapped[str] = mapped_column(String(100), nullable=False)
-    resource_tags: Mapped[list["ResourceTagEntity"]] = relationship(
-        back_populates="tag"
-    )
-    service_tags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag")
 
+    #relationships
+    resourceTags: Mapped[list["ResourceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete")
+    serviceTags: Mapped[list["ServiceTagEntity"]] = relationship(back_populates="tag", cascade="all,delete")
+
+  
+    
     @classmethod
     def from_model(cls, model: Tag) -> Self:
         """
@@ -41,11 +42,11 @@ class TagEntity(EntityBase):
         Returns:
             self: The entity
         """
-
+            
         return cls(
             id=model.id,
+            created_at=model.created_at,
             content=model.id,
-            created_at=model.created_at
         )
 
     def to_model(self) -> Tag:
@@ -58,6 +59,6 @@ class TagEntity(EntityBase):
 
         return Tag(
             id=self.id,
+            create_at=self.created_at,
             content=self.content,
-            created_at=self.created_at
-        )
+        )
\ No newline at end of file
diff --git a/backend/main.py b/backend/main.py
index d8af3ff..5720633 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,34 +1,37 @@
-from fastapi import FastAPI, Request
-from fastapi.responses import JSONResponse
-from fastapi.middleware.gzip import GZipMiddleware
-
-from .api import user, health, service, resource
-
-description = """
-Welcome to the **COMPASS** RESTful Application Programming Interface.
-"""
-
-app = FastAPI(
-    title="Compass API",
-    version="0.0.1",
-    description=description,
-    openapi_tags=[
-        user.openapi_tags,
-        health.openapi_tags,
-        service.openapi_tags,
-        resource.openapi_tags,
-    ],
-)
-
-app.add_middleware(GZipMiddleware)
-
-feature_apis = [user, health, service, resource]
-
-for feature_api in feature_apis:
-    app.include_router(feature_api.api)
-
-
-# Add application-wide exception handling middleware for commonly encountered API Exceptions
-@app.exception_handler(Exception)
-def permission_exception_handler(request: Request, e: Exception):
-    return JSONResponse(status_code=403, content={"message": str(e)})
+from fastapi import FastAPI, Request
+from fastapi.responses import JSONResponse
+from fastapi.middleware.gzip import GZipMiddleware
+
+
+
+from .api import user, health, service, resource, tag
+
+description = """
+Welcome to the **COMPASS** RESTful Application Programming Interface.
+"""
+
+app = FastAPI(
+    title="Compass API",
+    version="0.0.1",
+    description=description,
+    openapi_tags=[
+        user.openapi_tags,
+        health.openapi_tags,
+        service.openapi_tags,
+        resource.openapi_tags,
+        tag.openapi_tags
+    ],
+)
+
+app.add_middleware(GZipMiddleware)
+
+feature_apis = [user, health, service, resource, tag]
+
+for feature_api in feature_apis:
+    app.include_router(feature_api.api)
+
+
+# Add application-wide exception handling middleware for commonly encountered API Exceptions
+@app.exception_handler(Exception)
+def permission_exception_handler(request: Request, e: Exception):
+    return JSONResponse(status_code=403, content={"message": str(e)})

From 3814d6d290dc70f6993e77fe3c27a718488f793e Mon Sep 17 00:00:00 2001
From: Aidan Kim <aidankim528@gmail.com>
Date: Tue, 29 Oct 2024 19:24:07 -0400
Subject: [PATCH 3/5] Created API routes for create, update, delete, get_all,
 and get_by_name. Deleted service methods for get by id.

---
 backend/api/resource.py        |  21 +++++--
 backend/api/service.py         |  26 ++++----
 backend/main.py                |   1 -
 backend/services/exceptions.py |   2 +
 backend/services/resource.py   | 105 +++++++++++----------------------
 backend/services/service.py    |  33 ++++-------
 6 files changed, 78 insertions(+), 110 deletions(-)

diff --git a/backend/api/resource.py b/backend/api/resource.py
index 0b11539..97d25af 100644
--- a/backend/api/resource.py
+++ b/backend/api/resource.py
@@ -19,25 +19,38 @@ openapi_tags = {
 # TODO: Create custom exceptions
 @api.post("", response_model=Resource, tags=["Resource"])
 def create(
-    subject: User, resource: Resource, resource_svc: ResourceService = Depends()
+    uuid: str, resource: Resource, user_svc: UserService = Depends(), resource_svc: ResourceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     return resource_svc.create(subject, resource)
 
 
 @api.get("", response_model=List[Resource], tags=["Resource"])
-def get_all(subject: User, resource_svc: ResourceService = Depends()):
+def get_all(
+    uuid: str, user_svc: UserService = Depends(), resource_svc: ResourceService = Depends()
+):
+    subject = user_svc.get_user_by_uuid(uuid)
     return resource_svc.get_resource_by_user(subject)
 
+@api.get("/{name}", response_model=Resource, tags=["Resource"])
+def get_by_name(
+    name:str, uuid:str, user_svc: UserService = Depends(), resource_svc: ResourceService = Depends()
+):
+    subject = user_svc.get_user_by_uuid(uuid)
+    return resource_svc.get_resource_by_name(name, subject)
+
 
 @api.put("", response_model=Resource, tags=["Resource"])
 def update(
-    subject: User, resource: Resource, resource_svc: ResourceService = Depends()
+    uuid: str, resource: Resource, user_svc: UserService = Depends(), resource_svc: ResourceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     return resource_svc.update(subject, resource)
 
 
 @api.delete("", response_model=None, tags=["Resource"])
 def delete(
-    subject: User, resource: Resource, resource_svc: ResourceService = Depends()
+    uuid: str, resource: Resource, user_svc: UserService = Depends(), resource_svc: ResourceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     resource_svc.delete(subject, resource)
diff --git a/backend/api/service.py b/backend/api/service.py
index de73d13..bd3c4dc 100644
--- a/backend/api/service.py
+++ b/backend/api/service.py
@@ -19,32 +19,36 @@ openapi_tags = {
 # TODO: Create custom exceptions
 @api.post("", response_model=Service, tags=["Service"])
 def create(
-    subject: User,
-    service: Service,
-    service_svc: ServiceService = Depends()
+    uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     return service_svc.create(subject, service)
 
 
 @api.get("", response_model=List[Service], tags=["Service"])
 def get_all(
-    subject: User,
-    service_svc: ServiceService = Depends()
+    uuid: str, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     return service_svc.get_service_by_user(subject)
 
+@api.get("/{name}", response_model=Service, tags=["Service"])
+def get_by_name(
+    name: str, uuid: str, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
+):
+    subject = user_svc.get_user_by_uuid(uuid)
+    return service_svc.get_service_by_name(name, subject)
+
 @api.put("", response_model=Service, tags=["Service"])
 def update(
-    subject: User,
-    service: Service,
-    service_svc: ServiceService = Depends()
+    uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     return service_svc.update(subject, service)
 
 @api.delete("", response_model=None, tags=["Service"])
 def delete(
-    subject: User,
-    service: Service,
-    service_svc: ServiceService = Depends()
+    uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
 ):
+    subject = user_svc.get_user_by_uuid(uuid)
     service_svc.delete(subject, service)
diff --git a/backend/main.py b/backend/main.py
index 5720633..12ecaad 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -3,7 +3,6 @@ from fastapi.responses import JSONResponse
 from fastapi.middleware.gzip import GZipMiddleware
 
 
-
 from .api import user, health, service, resource, tag
 
 description = """
diff --git a/backend/services/exceptions.py b/backend/services/exceptions.py
index 069bff1..daa4b9b 100644
--- a/backend/services/exceptions.py
+++ b/backend/services/exceptions.py
@@ -20,6 +20,8 @@ class UserPermissionException(Exception):
 class ServiceNotFoundException(Exception):
     """Exception for when the service being requested is not in the table."""
 
+class TagNotFoundException(Exception):
+    """Exception for when the tag being requested is not in the table."""
 
 class ProgramNotAssignedException(Exception):
     """Exception for when the user does not have correct access for requested services."""
diff --git a/backend/services/resource.py b/backend/services/resource.py
index 2ccbee9..3522003 100644
--- a/backend/services/resource.py
+++ b/backend/services/resource.py
@@ -1,12 +1,12 @@
 from fastapi import Depends
 from ..database import db_session
 from sqlalchemy.orm import Session
-from sqlalchemy import select
+from sqlalchemy import and_, select
 from ..models.resource_model import Resource
 from ..entities.resource_entity import ResourceEntity
 from ..models.user_model import User, UserTypeEnum
 
-from .exceptions import ResourceNotFoundException
+from .exceptions import ProgramNotAssignedException, ResourceNotFoundException
 
 
 class ResourceService:
@@ -24,11 +24,29 @@ class ResourceService:
             programs = subject.program
             resources = []
             for program in programs:
-                entities = self._session.query(ResourceEntity).where(ResourceEntity.program == program).all()
+                entities = (
+                    self._session.query(ResourceEntity)
+                    .where(ResourceEntity.program == program)
+                    .all()
+                )
                 for entity in entities:
                     resources.append(entity.to_model())
         return [resource for resource in resources]
 
+    def get_resource_by_name(self, name: str, subject: User) -> Resource:
+        """Get a resource by name."""
+        query = select(ResourceEntity).where(
+            and_(
+                ResourceEntity.name == name, ResourceEntity.program.in_(subject.program)
+            )
+        )
+        entity = self._session.scalars(query).one_or_none()
+        if entity is None:
+            raise ResourceNotFoundException(
+                f"Resource with name: {name} does not exist or program has not been assigned."
+            )
+        return entity.to_model()
+
     def create(self, subject: User, resource: Resource) -> Resource:
         """
         Creates a resource based on the input object and adds it to the table if the user has the right permissions.
@@ -40,47 +58,15 @@ class ResourceService:
         Returns:
             Resource: Object added to table
         """
-        # Ask about what the requirements for making a resource are.
-        if resource.role != subject.role or resource.group != subject.group:
-            raise PermissionError(
-                "User does not have permission to add resources in this role or group."
+        if subject.role != UserTypeEnum.ADMIN:
+            raise ProgramNotAssignedException(
+                f"User is not {UserTypeEnum.ADMIN}, cannot update service"
             )
-
         resource_entity = ResourceEntity.from_model(resource)
         self._session.add(resource_entity)
         self._session.commit()
-
         return resource_entity.to_model()
 
-    def get_by_id(self, user: User, id: int) -> Resource:
-        """
-        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
-            id: int, the id of the resource
-
-        Returns:
-            Resource
-
-        Raises:
-            ResourceNotFoundException: If no resource is found with id
-        """
-        resource = (
-            self._session.query(ResourceEntity)
-            .filter(
-                ResourceEntity.id == id,
-                ResourceEntity.role == user.role,
-                ResourceEntity.group == user.group,
-            )
-            .one_or_none()
-        )
-
-        if resource is None:
-            raise ResourceNotFoundException(f"No resource found with id: {id}")
-
-        return resource.to_model()
-
     def update(self, subject: User, resource: Resource) -> Resource:
         """
         Update the resource if the user has access
@@ -95,25 +81,21 @@ class ResourceService:
         Raises:
             ResourceNotFoundException: If no resource is found with the corresponding ID
         """
-        if resource.role != subject.role or resource.group != subject.group:
-            raise PermissionError(
-                "User does not have permission to update this resource."
+        if subject.role != UserTypeEnum.ADMIN:
+            raise ProgramNotAssignedException(
+                f"User is not {UserTypeEnum.ADMIN}, cannot update service"
             )
-
         query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
         entity = self._session.scalars(query).one_or_none()
-
         if entity is None:
             raise ResourceNotFoundException(
                 f"No resource found with matching id: {resource.id}"
             )
-
         entity.name = resource.name
         entity.summary = resource.summary
         entity.link = resource.link
         entity.program = resource.program
         self._session.commit()
-
         return entity.to_model()
 
     def delete(self, subject: User, resource: Resource) -> None:
@@ -127,34 +109,15 @@ class ResourceService:
         Raises:
             ResourceNotFoundException: If no resource is found with the corresponding id
         """
+        if subject.role != UserTypeEnum.ADMIN:
+            raise ProgramNotAssignedException(
+                f"User is not {UserTypeEnum.ADMIN}, cannot update service"
+            )
         query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
         entity = self._session.scalars(query).one_or_none()
-
         if entity is None:
-            raise ResourceNotFoundException(f"No resource found with matching id: {resource.id}")
-
+            raise ResourceNotFoundException(
+                f"No resource found with matching id: {resource.id}"
+            )
         self._session.delete(entity)
         self._session.commit()
-
-    def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
-        """
-        Get a list of resources given a search string that the user has access to
-
-        Parameters:
-            user: a valid User model representing the currently logged in User
-            search_string: a string to search resources by
-
-        Returns:
-            list[Resource]: list of resources relating to the string
-
-        Raises:
-            ResourceNotFoundException if no resource is found with the corresponding slug
-        """
-        query = select(ResourceEntity).where(
-            ResourceEntity.title.ilike(f"%{search_string}%"),
-            ResourceEntity.role == user.role,
-            ResourceEntity.group == user.group,
-        )
-        entities = self._session.scalars(query).all()
-
-        return [entity.to_model() for entity in entities]
diff --git a/backend/services/service.py b/backend/services/service.py
index edce109..e10309e 100644
--- a/backend/services/service.py
+++ b/backend/services/service.py
@@ -27,37 +27,24 @@ class ServiceService:
             return [service.to_model() for service in entities]
         else:
             programs = subject.program
-            resources = []
+            services = []
             for program in programs:
                 entities = self._session.query(ServiceEntity).where(ServiceEntity.program == program).all()
                 for entity in entities:
-                    resources.append(entity.to_model())
-        return [service for service in resources]
+                    services.append(entity.to_model())
+        return [service for service in services]
 
-    def get_service_by_program(self, program: ProgramTypeEnum) -> list[Service]:
-        """Service method getting services belonging to a particular program."""
-        query = select(ServiceEntity).filter(ServiceEntity.program == program)
-        entities = self._session.scalars(query)
-
-        return [entity.to_model() for entity in entities]
-
-    def get_service_by_id(self, id: int) -> Service:
+    def get_service_by_name(self, name: str, subject: User) -> Service:
         """Service method getting services by id."""
-        query = select(ServiceEntity).filter(ServiceEntity.id == id)
+        query = select(ServiceEntity).where(
+            and_(
+                ServiceEntity.name == name, ServiceEntity.program.in_(subject.program)
+            )
+        )
         entity = self._session.scalars(query).one_or_none()
 
         if entity is None:
-            raise ServiceNotFoundException(f"Service with id: {id} does not exist")
-
-        return entity.to_model()
-
-    def get_service_by_name(self, name: str) -> Service:
-        """Service method getting services by id."""
-        query = select(ServiceEntity).filter(ServiceEntity.name == name)
-        entity = self._session.scalars(query).one_or_none()
-
-        if entity is None:
-            raise ServiceNotFoundException(f"Service with name: {name} does not exist")
+            raise ServiceNotFoundException(f"Service with name: {name} does not exist or program has not been assigned")
 
         return entity.to_model()
 

From 638f1098962e68c3e3419ac2e8dbe235cf2216b9 Mon Sep 17 00:00:00 2001
From: pmoharana-cmd <pmoharana032474@gmail.com>
Date: Mon, 4 Nov 2024 16:25:47 -0500
Subject: [PATCH 4/5] Defaults created_at to current time

---
 backend/models/resource_model.py | 2 +-
 backend/models/service_model.py  | 2 +-
 backend/models/tag_model.py      | 2 +-
 backend/models/user_model.py     | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/backend/models/resource_model.py b/backend/models/resource_model.py
index 8c9fde0..81e49cc 100644
--- a/backend/models/resource_model.py
+++ b/backend/models/resource_model.py
@@ -12,4 +12,4 @@ class Resource(BaseModel):
     summary: str = Field(..., max_length=300, description="The summary of the resource")
     link: str = Field(..., max_length=150, description="link to the resource")
     program: ProgramTypeEnum
-    created_at: Optional[datetime]
+    created_at: Optional[datetime] = datetime.now()
diff --git a/backend/models/service_model.py b/backend/models/service_model.py
index 36c336b..9671974 100644
--- a/backend/models/service_model.py
+++ b/backend/models/service_model.py
@@ -8,7 +8,7 @@ from .enum_for_models import ProgramTypeEnum
 
 class Service(BaseModel):
     id: int | None = None
-    created_at: datetime | None = None
+    created_at: datetime | None = datetime.now()
     name: str
     status: str
     summary: str
diff --git a/backend/models/tag_model.py b/backend/models/tag_model.py
index 44dcb02..fee566c 100644
--- a/backend/models/tag_model.py
+++ b/backend/models/tag_model.py
@@ -10,4 +10,4 @@ class Tag(BaseModel):
     content: str = Field(
         ..., max_length=600, description="content associated with the tag"
     )
-    created_at: datetime | None = None
+    created_at: datetime | None = datetime.now()
diff --git a/backend/models/user_model.py b/backend/models/user_model.py
index d7c1521..e2c25da 100644
--- a/backend/models/user_model.py
+++ b/backend/models/user_model.py
@@ -14,5 +14,5 @@ class User(BaseModel):
     group: str
     program: List[ProgramTypeEnum]
     role: UserTypeEnum
-    created_at: Optional[datetime]
+    created_at: Optional[datetime] = datetime.now()
     uuid: str | None = None

From 9c621db0309a955af63885b2eb0d3087189787b2 Mon Sep 17 00:00:00 2001
From: Aidan Kim <aidankim528@gmail.com>
Date: Mon, 4 Nov 2024 20:29:20 -0500
Subject: [PATCH 5/5] Write markdown file for HTTP requests using curl

---
 backend/api/test_routes.md | 147 +++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)
 create mode 100644 backend/api/test_routes.md

diff --git a/backend/api/test_routes.md b/backend/api/test_routes.md
new file mode 100644
index 0000000..64528ba
--- /dev/null
+++ b/backend/api/test_routes.md
@@ -0,0 +1,147 @@
+# Synopsis
+Collection of sample curl requests for api routes.
+
+# Resources
+## Get All
+Given an admin UUID, gets all of the resources from ResourceEntity.
+```
+curl -X 'GET' \
+  'http://127.0.0.1:8000/api/resource?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json'
+```
+
+## Get by Name
+Given the name of a resource and an admin UUID, gets a resource from ResourceEntity by name.
+```
+curl -X 'GET' \
+  'http://127.0.0.1:8000/api/resource/Financial%20Empowerment%20Center?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json'
+```
+
+## Create 
+Given an admin UUID and a new resource object, adds a resource to ResourceEntity.
+```
+curl -X 'POST' \
+  'http://127.0.0.1:8000/api/resource?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "name": "algorithms and analysis textbook",
+  "summary": "textbook written by kevin sun for c550",
+  "link": "kevinsun.org",
+  "program": "DOMESTIC",
+  "created_at": "2024-11-04T20:07:31.875166"
+}'
+```
+
+## Update
+Given an admin UUID and a modified resource object, updates the resource with a matching ID if it exists.
+```
+curl -X 'PUT' \
+  'http://127.0.0.1:8000/api/resource?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "name": "algorithms and analysis textbook",
+  "summary": "textbook written by the goat himself, kevin sun, for c550",
+  "link": "kevinsun.org",
+  "program": "DOMESTIC",
+  "created_at": "2024-11-04T20:07:31.875166"
+}'
+```
+
+## Delete
+Given an admin UUID and a resource object, deletes the resource with a matching ID if it exists.
+```
+curl -X 'DELETE' \
+  'http://127.0.0.1:8000/api/resource?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "name": "algorithms and analysis textbook",
+  "summary": "textbook written by the goat himself, kevin sun, for c550",
+  "link": "kevinsun.org",
+  "program": "DOMESTIC",
+  "created_at": "2024-11-04T20:07:31.875166"
+}'
+```
+
+# Services
+## Get All
+Given an admin UUID, gets all of the services from ServiceEntity.
+```
+curl -X 'GET' \
+  'http://127.0.0.1:8000/api/service?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json'
+```
+
+## Get by Name
+Given the name of a service and an admin UUID, gets a service from ServiceEntity by name.
+```
+curl -X 'GET' \
+  'http://127.0.0.1:8000/api/service/Shelter%20Placement?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json'
+```
+
+## Create 
+Given an admin UUID and a new service object, adds a service to ServiceEntity.
+```
+curl -X 'POST' \
+  'http://127.0.0.1:8000/api/service?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "created_at": "2024-11-04T20:07:31.890412",
+  "name": "c550 tutoring",
+  "status": "open",
+  "summary": "tutoring for kevin sun'\''s c550 class",
+  "requirements": [
+    "must be in c550"
+  ],
+  "program": "COMMUNITY"
+}'
+```
+
+## Update
+Given an admin UUID and a modified service object, updates the service with a matching ID if it exists.
+```
+curl -X 'PUT' \
+  'http://127.0.0.1:8000/api/service?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "created_at": "2024-11-04T20:07:31.890412",
+  "name": "c550 tutoring",
+  "status": "closed",
+  "summary": "tutoring for kevin sun'\''s c550 class",
+  "requirements": [
+    "must be in c550"
+  ],
+  "program": "COMMUNITY"
+}'
+```
+
+## Delete
+Given an admin UUID and a service object, deletes the service with a matching ID if it exists.
+```
+curl -X 'DELETE' \
+  'http://127.0.0.1:8000/api/service?uuid=acc6e112-d296-4739-a80c-b89b2933e50b' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "id": 25,
+  "created_at": "2024-11-04T20:07:31.890412",
+  "name": "c550 tutoring",
+  "status": "closed",
+  "summary": "tutoring for kevin sun'\''s c550 class",
+  "requirements": [
+    "must be in c550"
+  ],
+  "program": "COMMUNITY"
+}'
+```
\ No newline at end of file