Skip to content

Commit

Permalink
SAC-27 Club-Tags CRUD (#163)
Browse files Browse the repository at this point in the history
Co-authored-by: Garrett Ladley <[email protected]>
Co-authored-by: garrettladley <[email protected]>
  • Loading branch information
3 people authored Feb 11, 2024
1 parent ca7841b commit b2874b4
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 4 deletions.
87 changes: 87 additions & 0 deletions backend/src/controllers/club_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package controllers

import (
"github.com/GenerateNU/sac/backend/src/errors"
"github.com/GenerateNU/sac/backend/src/models"
"github.com/GenerateNU/sac/backend/src/services"
"github.com/gofiber/fiber/v2"
)

type ClubTagController struct {
clubTagService services.ClubTagServiceInterface
}

func NewClubTagController(clubTagService services.ClubTagServiceInterface) *ClubTagController {
return &ClubTagController{clubTagService: clubTagService}
}

// CreateClubTags godoc
//
// @Summary Create Club Tags
// @Description Adds Tags to a Club
// @ID create-club-tags
// @Tags club
// @Accept json
// @Produce json
// @Success 201 {object} []models.Tag
// @Failure 404 {string} string "club not found"
// @Failure 400 {string} string "invalid request body"
// @Failure 400 {string} string "failed to validate id"
// @Failure 500 {string} string "database error"
// @Router /api/v1/clubs/:id/tags [post]
func (l *ClubTagController) CreateClubTags(c *fiber.Ctx) error {
var clubTagsBody models.CreateClubTagsRequestBody
if err := c.BodyParser(&clubTagsBody); err != nil {
return errors.FailedToParseRequestBody.FiberError(c)
}

clubTags, err := l.clubTagService.CreateClubTags(c.Params("clubID"), clubTagsBody)
if err != nil {
return err.FiberError(c)
}

return c.Status(fiber.StatusCreated).JSON(clubTags)
}

// GetClubTags godoc
//
// @Summary Get Club Tags
// @Description Retrieves the tags for a club
// @ID get-club-tags
// @Tags club
// @Produce json
// @Success 200 {object} []models.Tag
// @Failure 404 {string} string "club not found"
// @Failure 400 {string} string "invalid request body"
// @Failure 400 {string} string "failed to validate id"
// @Failure 500 {string} string "database error"
// @Router /api/v1/clubs/:id/tags [get]
func (l *ClubTagController) GetClubTags(c *fiber.Ctx) error {
clubTags, err := l.clubTagService.GetClubTags(c.Params("clubID"))
if err != nil {
return err.FiberError(c)
}

return c.Status(fiber.StatusOK).JSON(clubTags)
}

// DeleteClubTags godoc
//
// @Summary Delete Club Tags
// @Description Deletes the tags for a club
// @ID delete-club-tags
// @Tags club
// @Success 204
// @Failure 404 {string} string "club not found"
// @Failure 400 {string} string "invalid request body"
// @Failure 400 {string} string "failed to validate id"
// @Failure 500 {string} string "database error"
// @Router /api/v1/clubs/:id/tags/:tagId [delete]
func (l *ClubTagController) DeleteClubTag(c *fiber.Ctx) error {
err := l.clubTagService.DeleteClubTag(c.Params("clubID"), c.Params("tagID"))
if err != nil {
return err.FiberError(c)
}

return c.SendStatus(fiber.StatusNoContent)
}
4 changes: 4 additions & 0 deletions backend/src/errors/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ var (
StatusCode: fiber.StatusNotFound,
Message: "club not found",
}
FailedToValidateClubTags = Error{
StatusCode: fiber.StatusBadRequest,
Message: "failed to validate club tags",
}
FailedToGetMembers = Error{
StatusCode: fiber.StatusNotFound,
Message: "failed to get members",
Expand Down
6 changes: 5 additions & 1 deletion backend/src/models/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ type UpdateClubRequestBody struct {
RecruitmentCycle RecruitmentCycle `gorm:"type:varchar(255);default:always" json:"recruitment_cycle" validate:"required,max=255,oneof=fall spring fallSpring always"`
RecruitmentType RecruitmentType `gorm:"type:varchar(255);default:unrestricted" json:"recruitment_type" validate:"required,max=255,oneof=unrestricted tryout application"`
ApplicationLink string `json:"application_link" validate:"omitempty,required,max=255,http_url"`
Logo string `json:"logo" validate:"omitempty,http_url,s3_url,max=255"` // S3 URL
Logo string `json:"logo" validate:"omitempty,s3_url,max=255,http_url"` // S3 URL
}

type CreateClubTagsRequestBody struct {
Tags []uuid.UUID `json:"tags" validate:"required"`
}

func (c *Club) AfterCreate(tx *gorm.DB) (err error) {
Expand Down
17 changes: 17 additions & 0 deletions backend/src/server/routes/club_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package routes

import (
"github.com/GenerateNU/sac/backend/src/controllers"
"github.com/GenerateNU/sac/backend/src/services"
"github.com/gofiber/fiber/v2"
)

func ClubTag(router fiber.Router, clubTagService services.ClubTagServiceInterface) {
clubTagController := controllers.NewClubTagController(clubTagService)

clubTags := router.Group("/:clubID/tags")

clubTags.Post("/", clubTagController.CreateClubTags)
clubTags.Get("/", clubTagController.GetClubTags)
clubTags.Delete("/:tagID", clubTagController.DeleteClubTag)
}
1 change: 1 addition & 0 deletions backend/src/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func Init(db *gorm.DB, settings config.Settings) *fiber.App {
routes.Contact(apiv1, services.NewContactService(db, validate))

clubsIDRouter := routes.Club(apiv1, services.NewClubService(db, validate), middlewareService)
routes.ClubTag(clubsIDRouter, services.NewClubTagService(db, validate))
routes.ClubFollower(clubsIDRouter, services.NewClubFollowerService(db))
routes.ClubMember(clubsIDRouter, services.NewClubMemberService(db, validate))
routes.ClubContact(clubsIDRouter, services.NewClubContactService(db, validate))
Expand Down
66 changes: 66 additions & 0 deletions backend/src/services/club_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package services

import (
"github.com/GenerateNU/sac/backend/src/errors"
"github.com/GenerateNU/sac/backend/src/models"
"github.com/GenerateNU/sac/backend/src/transactions"
"github.com/GenerateNU/sac/backend/src/utilities"
"github.com/go-playground/validator/v10"
"gorm.io/gorm"
)

type ClubTagServiceInterface interface {
CreateClubTags(id string, clubTagsBody models.CreateClubTagsRequestBody) ([]models.Tag, *errors.Error)
GetClubTags(id string) ([]models.Tag, *errors.Error)
DeleteClubTag(id string, tagId string) *errors.Error
}

type ClubTagService struct {
DB *gorm.DB
Validate *validator.Validate
}

func NewClubTagService(db *gorm.DB, validate *validator.Validate) ClubTagServiceInterface {
return &ClubTagService{DB: db, Validate: validate}
}

func (c *ClubTagService) CreateClubTags(id string, clubTagsBody models.CreateClubTagsRequestBody) ([]models.Tag, *errors.Error) {
idAsUUID, err := utilities.ValidateID(id)
if err != nil {
return nil, err
}

if err := c.Validate.Struct(clubTagsBody); err != nil {
return nil, &errors.FailedToValidateClubTags
}

tags, err := transactions.GetTagsByIDs(c.DB, clubTagsBody.Tags)
if err != nil {
return nil, err
}

return transactions.CreateClubTags(c.DB, *idAsUUID, tags)
}

func (c *ClubTagService) GetClubTags(id string) ([]models.Tag, *errors.Error) {
idAsUUID, err := utilities.ValidateID(id)
if err != nil {
return nil, &errors.FailedToValidateID
}

return transactions.GetClubTags(c.DB, *idAsUUID)
}

func (c *ClubTagService) DeleteClubTag(id string, tagId string) *errors.Error {
idAsUUID, err := utilities.ValidateID(id)
if err != nil {
return &errors.FailedToValidateID
}

tagIdAsUUID, err := utilities.ValidateID(tagId)
if err != nil {
return &errors.FailedToValidateID
}

return transactions.DeleteClubTag(c.DB, *idAsUUID, *tagIdAsUUID)
}
6 changes: 3 additions & 3 deletions backend/src/services/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (

type TagServiceInterface interface {
CreateTag(tagBody models.TagRequestBody) (*models.Tag, *errors.Error)
GetTag(tagID string) (*models.Tag, *errors.Error)
UpdateTag(tagID string, tagBody models.TagRequestBody) (*models.Tag, *errors.Error)
DeleteTag(tagID string) *errors.Error
GetTag(id string) (*models.Tag, *errors.Error)
UpdateTag(id string, tagBody models.TagRequestBody) (*models.Tag, *errors.Error)
DeleteTag(id string) *errors.Error
}

type TagService struct {
Expand Down
56 changes: 56 additions & 0 deletions backend/src/transactions/club_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package transactions

import (
"github.com/GenerateNU/sac/backend/src/errors"
"github.com/GenerateNU/sac/backend/src/models"
"github.com/google/uuid"

"gorm.io/gorm"
)

// Create tags for a club
func CreateClubTags(db *gorm.DB, id uuid.UUID, tags []models.Tag) ([]models.Tag, *errors.Error) {
user, err := GetClub(db, id)
if err != nil {
return nil, &errors.UserNotFound
}

if err := db.Model(&user).Association("Tag").Replace(tags); err != nil {
return nil, &errors.FailedToUpdateUser
}

return tags, nil
}

// Get tags for a club
func GetClubTags(db *gorm.DB, id uuid.UUID) ([]models.Tag, *errors.Error) {
var tags []models.Tag

club, err := GetClub(db, id)
if err != nil {
return nil, &errors.ClubNotFound
}

if err := db.Model(&club).Association("Tag").Find(&tags); err != nil {
return nil, &errors.FailedToGetTag
}
return tags, nil
}

// Delete tag for a club
func DeleteClubTag(db *gorm.DB, id uuid.UUID, tagId uuid.UUID) *errors.Error {
club, err := GetClub(db, id)
if err != nil {
return &errors.ClubNotFound
}

tag, err := GetTag(db, tagId)
if err != nil {
return &errors.TagNotFound
}

if err := db.Model(&club).Association("Tag").Delete(&tag); err != nil {
return &errors.FailedToUpdateClub
}
return nil
}
15 changes: 15 additions & 0 deletions backend/src/transactions/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,18 @@ func GetTagsByIDs(db *gorm.DB, selectedTagIDs []uuid.UUID) ([]models.Tag, *error
}
return []models.Tag{}, nil
}

// Get clubs for a tag
func GetTagClubs(db *gorm.DB, id uuid.UUID) ([]models.Club, *errors.Error) {
var clubs []models.Club

tag, err := GetTag(db, id)
if err != nil {
return nil, &errors.ClubNotFound
}

if err := db.Model(&tag).Association("Club").Find(&clubs); err != nil {
return nil, &errors.FailedToGetTag
}
return clubs, nil
}
Loading

0 comments on commit b2874b4

Please sign in to comment.