Skip to content

Commit

Permalink
188 make all users follow sac super club (#255)
Browse files Browse the repository at this point in the history
Co-authored-by: Garrett Ladley <[email protected]>
  • Loading branch information
DOOduneye and garrettladley authored Mar 6, 2024
1 parent 3f4a802 commit 8111e21
Show file tree
Hide file tree
Showing 24 changed files with 243 additions and 238 deletions.
1 change: 1 addition & 0 deletions backend/src/controllers/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func NewCategoryController(categoryService services.CategoryServiceInterface) *C
// @Failure 400 {string} errors.Error
// @Failure 401 {string} errors.Error
// @Failure 404 {string} errors.Error
// @Failure 409 {string} errors.Error
// @Failure 500 {string} errors.Error
// @Router /categories/ [post]
func (cat *CategoryController) CreateCategory(c *fiber.Ctx) error {
Expand Down
1 change: 1 addition & 0 deletions backend/src/controllers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func NewUserController(userService services.UserServiceInterface) *UserControlle
// @Failure 400 {object} errors.Error
// @Failure 401 {object} errors.Error
// @Failure 404 {object} errors.Error
// @Failure 409 {object} errors.Error
// @Failure 500 {object} errors.Error
// @Router /users/ [post]
func (u *UserController) CreateUser(c *fiber.Ctx) error {
Expand Down
3 changes: 2 additions & 1 deletion backend/src/controllers/user_follower.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

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

Expand Down Expand Up @@ -33,7 +34,7 @@ func (uf *UserFollowerController) CreateFollowing(c *fiber.Ctx) error {
if err != nil {
return err.FiberError(c)
}
return c.SendStatus(fiber.StatusCreated)
return utilities.FiberMessage(c, fiber.StatusCreated, "Successfully followed club")
}

// DeleteFollowing godoc
Expand Down
3 changes: 2 additions & 1 deletion backend/src/controllers/user_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

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

Expand Down Expand Up @@ -34,7 +35,7 @@ func (um *UserMemberController) CreateMembership(c *fiber.Ctx) error {
return err.FiberError(c)
}

return c.SendStatus(fiber.StatusCreated)
return utilities.FiberMessage(c, fiber.StatusCreated, "Successfully joined club")
}

// DeleteMembership godoc
Expand Down
28 changes: 21 additions & 7 deletions backend/src/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ func MigrateDB(settings config.Settings, db *gorm.DB) error {
return err
}

// Check if the database already has a super user
var superUser models.User
if err := db.Where("role = ?", models.Super).First(&superUser).Error; err != nil {
if err := createSuperUser(settings, db); err != nil {
Expand All @@ -112,26 +111,30 @@ func createSuperUser(settings config.Settings, db *gorm.DB) error {
var user models.User

if err := db.Where("nuid = ?", superUser.NUID).First(&user).Error; err != nil {
tx := db.Begin()
tx := db.Begin().Session(&gorm.Session{SkipHooks: true})

if err := tx.Error; err != nil {
return err
}

if err := tx.Create(&superUser).Error; err != nil {
superClub := SuperClub()
if err := tx.Create(&superClub).Error; err != nil {
tx.Rollback()
return err
}

SuperUserUUID = superUser.ID

superClub := SuperClub()
if err := tx.Model(&superClub).Update("num_members", gorm.Expr("num_members + 1")).Error; err != nil {
tx.Rollback()
return err
}

if err := tx.Create(&superClub).Error; err != nil {
if err := tx.Create(&superUser).Error; err != nil {
tx.Rollback()
return err
}

SuperUserUUID = superUser.ID

membership := models.Membership{
ClubID: superClub.ID,
UserID: superUser.ID,
Expand All @@ -143,7 +146,18 @@ func createSuperUser(settings config.Settings, db *gorm.DB) error {
return err
}

follower := models.Follower{
ClubID: superClub.ID,
UserID: superUser.ID,
}

if err := tx.Create(&follower).Error; err != nil {
tx.Rollback()
return err
}

return tx.Commit().Error
}

return nil
}
8 changes: 8 additions & 0 deletions backend/src/errors/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,12 @@ var (
StatusCode: fiber.StatusInternalServerError,
Message: "failed to get club events",
}
FailedToJoinClub = Error{
StatusCode: fiber.StatusInternalServerError,
Message: "failed to join club",
}
AlreadyMemberOfClub = Error{
StatusCode: fiber.StatusBadRequest,
Message: "already member of club",
}
)
4 changes: 4 additions & 0 deletions backend/src/errors/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ var (
StatusCode: fiber.StatusNotFound,
Message: "user not following club",
}
FailedToFollowClub = Error{
StatusCode: fiber.StatusInternalServerError,
Message: "failed to follow club",
}
)
12 changes: 1 addition & 11 deletions backend/src/models/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Club struct {

SoftDeletedAt gorm.DeletedAt `gorm:"type:timestamptz;default:NULL" json:"-" validate:"-"`

Name string `gorm:"type:varchar(255)" json:"name" validate:"required,max=255"`
Name string `gorm:"type:varchar(255);unique" json:"name" validate:"required,max=255"`
Preview string `gorm:"type:varchar(255)" json:"preview" validate:"required,max=255"`
Description string `gorm:"type:varchar(255)" json:"description" validate:"required,http_url,mongo_url,max=255"` // MongoDB URL
NumMembers int `gorm:"type:int" json:"num_members" validate:"required,min=1"`
Expand Down Expand Up @@ -114,16 +114,6 @@ func (cqp *ClubQueryParams) IntoWhere() string {
return "WHERE " + strings.Join(conditions, " AND ")
}

func (c *Club) AfterCreate(tx *gorm.DB) (err error) {
tx.Model(&c).Update("num_members", c.NumMembers+1)
return
}

func (c *Club) AfterDelete(tx *gorm.DB) (err error) {
tx.Model(&c).Update("num_members", c.NumMembers-1)
return
}

func (c *Club) SearchId() string {
return c.ID.String()
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type Series struct {

// TODO: add not null to required fields on all gorm models
type EventSeries struct {
EventID uuid.UUID `gorm:"not null; type:uuid; primary_key;" json:"event_id" validate:"uuid4"`
EventID uuid.UUID `gorm:"not null; type:uuid; primaryKey;" json:"event_id" validate:"uuid4"`
Event Event `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
SeriesID uuid.UUID `gorm:"not null; type:uuid;" json:"series_id" validate:"uuid4"`
Series Series `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Expand Down
17 changes: 17 additions & 0 deletions backend/src/models/follower.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package models

import (
"github.com/google/uuid"
)

func (Follower) TableName() string {
return "user_club_followers"
}

type Follower struct {
UserID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"club_id" validate:"required,uuid4"`

Club *Club `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
}
14 changes: 5 additions & 9 deletions backend/src/models/membership.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package models

import "github.com/google/uuid"
import (
"github.com/google/uuid"
)

type MembershipType string

Expand All @@ -9,19 +11,13 @@ const (
MembershipTypeAdmin MembershipType = "admin"
)

type Tabler interface {
TableName() string
}

func (Membership) TableName() string {
return "user_club_members"
}

type Membership struct {
Model

UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;not null" json:"club_id" validate:"required,uuid4"`
UserID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"club_id" validate:"required,uuid4"`

Club *Club `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Expand Down
6 changes: 5 additions & 1 deletion backend/src/models/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import (
"github.com/google/uuid"
)

type Tabler interface {
TableName() string
}

type Model struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id" example:"123e4567-e89b-12d3-a456-426614174000"`
ID uuid.UUID `gorm:"type:uuid;primaryKey;default:uuid_generate_v4()" json:"id" example:"123e4567-e89b-12d3-a456-426614174000"`
CreatedAt time.Time `gorm:"type:timestamp;default:CURRENT_TIMESTAMP" json:"created_at" example:"2023-09-20T16:34:50Z"`
UpdatedAt time.Time `gorm:"type:timestamp;default:CURRENT_TIMESTAMP" json:"updated_at" example:"2023-09-20T16:34:50Z"`
}
35 changes: 35 additions & 0 deletions backend/src/models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models

import (
"github.com/google/uuid"
"gorm.io/gorm"
)

type UserRole string
Expand Down Expand Up @@ -89,3 +90,37 @@ type UpdatePasswordRequestBody struct {
type CreateUserTagsBody struct {
Tags []uuid.UUID `json:"tags" validate:"required"`
}

func (u *User) AfterCreate(tx *gorm.DB) (err error) {
sac := &Club{}
if err := tx.Where("name = ?", "SAC").First(sac).Error; err != nil {
return err
}

if err := tx.Model(u).Association("Member").Append(sac); err != nil {
return err
}

if err := tx.Model(u).Association("Follower").Append(sac); err != nil {
return err
}

if err := tx.Model(&Club{}).Where("id = ?", sac.ID).Update("num_members", gorm.Expr("num_members + 1")).Error; err != nil {
return err
}

return nil
}

func (u *User) AfterDelete(tx *gorm.DB) (err error) {
sac := &Club{}
if err := tx.Where("name = ?", "SAC").First(sac).Error; err != nil {
return err
}

if err := tx.Model(&Club{}).Where("id = ?", sac.ID).Update("num_members", gorm.Expr("num_members - 1")).Error; err != nil {
return err
}

return nil
}
2 changes: 1 addition & 1 deletion backend/src/services/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (a *AuthService) UpdatePassword(id string, passwordBody models.UpdatePasswo
return err
}

correct, passwordErr := auth.ComparePasswordAndHash(passwordBody.OldPassword, passwordHash)
correct, passwordErr := auth.ComparePasswordAndHash(passwordBody.OldPassword, *passwordHash)
if passwordErr != nil || !correct {
return &errors.FailedToValidateUser
}
Expand Down
15 changes: 14 additions & 1 deletion backend/src/transactions/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,25 @@ func CreateClub(db *gorm.DB, userId uuid.UUID, club models.Club) (*models.Club,

tx := db.Begin()

club.NumMembers = 1

if err := tx.Create(&club).Error; err != nil {
tx.Rollback()
return nil, &errors.FailedToCreateClub
}

if err := tx.Model(&club).Association("Admin").Append(user); err != nil {
membership := models.Membership{
ClubID: club.ID,
UserID: user.ID,
MembershipType: models.MembershipTypeAdmin,
}

if err := tx.Create(&membership).Error; err != nil {
tx.Rollback()
return nil, &errors.FailedToCreateClub
}

if err := tx.Model(&user).Association("Follower").Append(&club); err != nil {
tx.Rollback()
return nil, &errors.FailedToCreateClub
}
Expand Down
11 changes: 5 additions & 6 deletions backend/src/transactions/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ func GetUser(db *gorm.DB, id uuid.UUID, preloads ...OptionalQuery) (*models.User
return &user, nil
}

func GetUserPasswordHash(db *gorm.DB, id uuid.UUID) (string, *errors.Error) {
func GetUserPasswordHash(db *gorm.DB, id uuid.UUID) (*string, *errors.Error) {
var user models.User
if err := db.Select("password_hash").First(&user, id).Error; err != nil {
if stdliberrors.Is(err, gorm.ErrRecordNotFound) {
return "", &errors.UserNotFound
return nil, &errors.UserNotFound
} else {
return "", &errors.FailedToGetUser
return nil, &errors.FailedToGetUser
}
}

return user.PasswordHash, nil
return &user.PasswordHash, nil
}

func UpdateUser(db *gorm.DB, id uuid.UUID, user models.User) (*models.User, *errors.Error) {
Expand Down Expand Up @@ -107,8 +107,7 @@ func UpdatePassword(db *gorm.DB, id uuid.UUID, passwordHash string) *errors.Erro
}

func DeleteUser(db *gorm.DB, id uuid.UUID) *errors.Error {
result := db.Delete(&models.User{}, id)
if result.RowsAffected == 0 {
if result := db.Delete(&models.User{}, id); result.RowsAffected == 0 {
if result.Error == nil {
return &errors.UserNotFound
} else {
Expand Down
20 changes: 4 additions & 16 deletions backend/src/transactions/user_follower.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package transactions

import (
"slices"

"github.com/GenerateNU/sac/backend/src/errors"
"github.com/GenerateNU/sac/backend/src/models"
"github.com/google/uuid"
Expand All @@ -21,35 +19,25 @@ func CreateFollowing(db *gorm.DB, userId uuid.UUID, clubId uuid.UUID) *errors.Er
}

if err := db.Model(&user).Association("Follower").Append(club); err != nil {
return &errors.FailedToUpdateUser
return &errors.FailedToFollowClub
}

return nil
}

func DeleteFollowing(db *gorm.DB, userId uuid.UUID, clubId uuid.UUID) *errors.Error {
user, err := GetUser(db, userId, PreloadFollwer())
user, err := GetUser(db, userId)
if err != nil {
return err
}

club, err := GetClub(db, clubId, PreloadFollwer())
club, err := GetClub(db, clubId)
if err != nil {
return err
}

userFollowingClubIDs := make([]uuid.UUID, len(user.Follower))

for i, club := range user.Follower {
userFollowingClubIDs[i] = club.ID
}

if !slices.Contains(userFollowingClubIDs, club.ID) {
return &errors.UserNotFollowingClub
}

if err := db.Model(&user).Association("Follower").Delete(club); err != nil {
return &errors.FailedToUpdateUser
return &errors.UserNotFollowingClub
}

return nil
Expand Down
Loading

0 comments on commit 8111e21

Please sign in to comment.