diff --git a/data/event.go b/data/event.go index 14c666f..35f4308 100644 --- a/data/event.go +++ b/data/event.go @@ -1,28 +1,81 @@ package data import ( + "errors" + "slices" "time" "github.com/google/uuid" + "gorm.io/datatypes" + "gorm.io/gorm" + "gorm.io/gorm/clause" ) type Event struct { - Id uint `json:"id" gorm:"primarykey;autoincrement"` - UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueindex;not null"` - EventId uuid.UUID `json:"event_id" gorm:"type:uuid;uniqueindex;not null"` - Name string `json:"name" gorm:"type:varchar(255);index;not null"` - StartTime time.Time `json:"start_time" gorm:"index"` - EndTime time.Time `json:"end_time" gorm:"index"` + Id uint `json:"id" gorm:"primarykey;autoincrement"` + UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueIndex;not null"` + EventId uuid.UUID `json:"event_id" gorm:"type:uuid;uniqueIndex;not null"` + Name string `json:"name" gorm:"type:varchar(255);index;not null"` + StartTime time.Time `json:"start_time" gorm:"index"` + EndTime time.Time `json:"end_time" gorm:"index"` + JoinedUsers datatypes.JSONSlice[uuid.UUID] `json:"joined_users"` } func (self *Event) GetEventById(eventId uuid.UUID) error { - return nil + return Database.Transaction(func(tx *gorm.DB) error { + if err := tx.Where("event_id = ?", eventId).First(&self).Error; err != nil { + return err + } + return nil + }) } func (self *Event) UpdateEventById(eventId uuid.UUID) error { - return nil + return Database.Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&Event{}).Where("event_id = ?", eventId).Updates(&self).Error; err != nil { + return err + } + return nil + }) } func (self *Event) CreateEvent() error { - return nil + if self.UUID == uuid.Nil { + self.UUID = uuid.New() + } + if self.EventId == uuid.Nil { + self.EventId = uuid.New() + } + + return Database.Transaction(func(tx *gorm.DB) error { + if err := tx.Create(&self).Error; err != nil { + return err + } + return nil + }) +} + +func (self *Event) UserJoinEvent(userId, eventId uuid.UUID) error { + return Database.Transaction(func(tx *gorm.DB) error { + var event Event + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}). + Where("event_id = ?", eventId). + First(&event).Error; err != nil { + return err + } + + // Check if user already joined + if slices.Contains(event.JoinedUsers, userId) { + return errors.New("user already joined") + } + + // Add user to list + event.JoinedUsers = append(event.JoinedUsers, userId) + if err := tx.Model(&Event{}).Where("event_id = ?", eventId).Update("joined_users", event.JoinedUsers).Error; err != nil { + return err + } + + *self = event + return nil + }) } diff --git a/data/user.go b/data/user.go index a2a91f0..c692500 100644 --- a/data/user.go +++ b/data/user.go @@ -16,17 +16,16 @@ import ( // Super User: 30 type User struct { - Id uint `json:"id" gorm:"primarykey;autoincrement"` - UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueindex;not null"` - UserId uuid.UUID `json:"user_id" gorm:"type:uuid;uniqueindex;not null"` - Email string `json:"email" gorm:"type:varchar(255);uniqueindex;not null"` - Type string `json:"type" gorm:"type:varchar(32);index;not null"` - Nickname string `json:"nickname"` - Subtitle string `json:"subtitle"` - Avatar string `json:"avatar"` - Checkin datatypes.JSONMap `json:"checkin"` - JoinedEvent datatypes.JSONSlice[uuid.UUID] `json:"joined_event"` - PermissionLevel uint `json:"permission_level" gorm:"default:10;not null"` + Id uint `json:"id" gorm:"primarykey;autoincrement"` + UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueindex;not null"` + UserId uuid.UUID `json:"user_id" gorm:"type:uuid;uniqueindex;not null"` + Email string `json:"email" gorm:"type:varchar(255);uniqueindex;not null"` + Type string `json:"type" gorm:"type:varchar(32);index;not null"` + Nickname string `json:"nickname"` + Subtitle string `json:"subtitle"` + Avatar string `json:"avatar"` + Checkin datatypes.JSONMap `json:"checkin"` + PermissionLevel uint `json:"permission_level" gorm:"default:10;not null"` } func (self *User) GetByEmail(email string) error { @@ -43,7 +42,7 @@ func (self *User) GetByUserId(userId uuid.UUID) error { return nil } -func (self *User) UpdateCheckin(userId uuid.UUID, eventId uuid.UUID, time time.Time) error { +func (self *User) UpdateCheckin(userId, eventId uuid.UUID, time time.Time) error { return Database.Transaction(func(tx *gorm.DB) error { if err := tx. Clauses(clause.Locking{Strength: "UPDATE"}). @@ -79,44 +78,11 @@ func (self *User) Create() error { }) } -type UserUpdateInput struct { - Email *string `json:"email"` - Nickname *string `json:"nickname"` - Subtitle *string `json:"subtitle"` - Avatar *string `json:"avatar"` - Type *string `json:"type"` -} - -func (self *User) UpdateByUserID(userID uuid.UUID, in *UserUpdateInput) error { +func (self *User) UpdateByUserID(userId uuid.UUID) error { return Database.Transaction(func(tx *gorm.DB) error { - if err := tx. - Where("user_id = ?", userID). - First(self).Error; err != nil { + if err := tx.Model(&User{}).Where("user_id = ?", userId).Updates(&self).Error; err != nil { return err } - - updates := map[string]any{} - - if in.Email != nil { - updates["email"] = *in.Email - } - if in.Nickname != nil { - updates["nickname"] = *in.Nickname - } - if in.Subtitle != nil { - updates["subtitle"] = *in.Subtitle - } - if in.Avatar != nil { - updates["avatar"] = *in.Avatar - } - if in.Type != nil { - updates["type"] = *in.Type - } - - if len(updates) == 0 { - return nil - } - - return tx.Model(self).Updates(updates).Error + return nil }) } diff --git a/service/auth/magic.go b/service/auth/magic.go index dfc709d..30d01b2 100644 --- a/service/auth/magic.go +++ b/service/auth/magic.go @@ -82,18 +82,8 @@ func VerifyMagicLink(c *gin.Context) { if err != nil { if err == gorm.ErrRecordNotFound { // Create user - newUUID, err := uuid.NewUUID() - if err != nil { - c.JSON(500, gin.H{"status": "internal server error"}) - return - } - newUserId, err := uuid.NewUUID() - if err != nil { - c.JSON(500, gin.H{"status": "internal server error"}) - return - } - user.UUID = newUUID - user.UserId = newUserId + user.UUID = uuid.New() + user.UserId = uuid.New() user.Email = email user.Type = "Normal" user.PermissionLevel = 10 diff --git a/service/user/info.go b/service/user/info.go index ea1d7f5..5252182 100644 --- a/service/user/info.go +++ b/service/user/info.go @@ -40,7 +40,6 @@ func Info(c *gin.Context) { "subtitle": data.Subtitle, "avatar": data.Avatar, "checkin": data.Checkin, - "joined_event": data.JoinedEvent, "permission_level": data.PermissionLevel, }) } diff --git a/service/user/update.go b/service/user/update.go index 27f8746..b64c876 100644 --- a/service/user/update.go +++ b/service/user/update.go @@ -8,7 +8,7 @@ import ( ) func Update(c *gin.Context) { - var ReqInfo data.UserUpdateInput + var ReqInfo data.User c.BindJSON(&ReqInfo) // New user model @@ -32,13 +32,17 @@ func Update(c *gin.Context) { return } + user.Avatar = ReqInfo.Avatar + user.Email = ReqInfo.Email + user.Nickname = ReqInfo.Nickname + user.Subtitle = ReqInfo.Subtitle // Cant change user type under permission 2 - if user.PermissionLevel < 2 { - ReqInfo.Type = nil + if user.PermissionLevel >= 2 { + user.Type = ReqInfo.Type } // Update user info - user.UpdateByUserID(userId.(uuid.UUID), &ReqInfo) + user.UpdateByUserID(userId.(uuid.UUID)) c.JSON(200, gin.H{ "status": "success",