Skip to content

Commit

Permalink
✨ feat: Implement class information update functionality
Browse files Browse the repository at this point in the history
Adds the capability to update class information, including handling image uploads and other class details like name, limitation, and description.

Related issue: #174
  • Loading branch information
yuminn-k committed Apr 7, 2024
1 parent 6483451 commit 2660301
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 0 deletions.
49 changes: 49 additions & 0 deletions controllers/class_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,55 @@ func (c *ClassController) handleImageUpload(ctx *gin.Context) (string, error) {
return imageUrl, nil
}

// UpdateClass godoc
// @Summary クラス情報を更新します
// @Description 指定されたIDを持つクラスの情報を更新します。
// @Tags Class
// @Accept multipart/form-data
// @Produce json
// @Param uid path int true "ユーザーID"
// @Param cid path int true "クラスID"
// @Param name formData string false "クラス名"
// @Param limitation formData int false "参加制限人数"
// @Param description formData string false "クラス説明"
// @Param image formData file false "クラス画像"
// @Success 200 {object} map[string]interface{} "message: クラスが正常に更新されました"
// @Failure 400 {object} map[string]interface{} "error: 不正なリクエストのエラーメッセージ"
// @Failure 401 {object} map[string]interface{} "error: 認証エラー"
// @Failure 500 {object} map[string]interface{} "error: サーバー内部エラー"
// @Router /cl/{uid}/{cid} [patch]
func (cc *ClassController) UpdateClass(ctx *gin.Context) {
userID, _ := strconv.ParseUint(ctx.Param("uid"), 10, 32)
classID, _ := strconv.ParseUint(ctx.Param("cid"), 10, 32)

var updateDTO dto.UpdateClassRequest
if err := ctx.ShouldBindWith(&updateDTO, binding.Form); err != nil {
respondWithError(ctx, constants.StatusBadRequest, constants.BadRequestMessage)
return
}

if fileHeader, _ := ctx.FormFile("image"); fileHeader != nil {
imageUrl, fileErr := cc.uploader.UploadImage(fileHeader, uint(classID), false)
if fileErr != nil {
respondWithError(ctx, http.StatusInternalServerError, "Image upload failed: "+fileErr.Error())
return
}

// Call a separate method to update the image URL
if err := cc.classService.UpdateClassImage(uint(classID), imageUrl); err != nil {
respondWithError(ctx, http.StatusInternalServerError, "Failed to update class image: "+err.Error())
return
}
}

if err := cc.classService.UpdateClass(uint(classID), uint(userID), updateDTO); err != nil {
respondWithError(ctx, http.StatusInternalServerError, "Class update failed: "+err.Error())
return
}

respondWithSuccess(ctx, constants.StatusOK, constants.Success)
}

// DeleteClass godoc
// @Summary クラスを削除します
// @Description 指定されたIDを持つクラスを削除します。
Expand Down
6 changes: 6 additions & 0 deletions dto/class_dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ type CreateClassRequest struct {
Description *string `form:"description"` // クラス説明
UID uint `form:"uid" binding:"required"` // ユーザID
}

type UpdateClassRequest struct {
Name string `form:"name"`
Limitation *int `form:"limitation"`
Description *string `form:"description"`
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ func setupCreateClassRoutes(router *gin.Engine, controller *controllers.ClassCon
{
cl.GET(":cid", controller.GetClass)
cl.POST("create", controller.CreateClass)
cl.PATCH(":uid/:cid", controller.UpdateClass)
cl.DELETE(":uid/:cid", controller.DeleteClass)
}
}
Expand Down
5 changes: 5 additions & 0 deletions repositories/class_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type ClassRepository interface {
Create(class *models.Class) error
Save(class *models.Class) (uint, error)
UpdateClassImage(classID uint, imageUrl string) error
Update(class *models.Class) error
Delete(classID uint) error
}

Expand Down Expand Up @@ -49,6 +50,10 @@ func (r *classRepository) UpdateClassImage(classID uint, imageUrl string) error
return r.db.Model(&models.Class{}).Where("id = ?", classID).Update("image", imageUrl).Error
}

func (r *classRepository) Update(class *models.Class) error {
return r.db.Save(class).Error
}

func (r *classRepository) Delete(classID uint) error {
return r.db.Delete(&models.Class{}, classID).Error
}
33 changes: 33 additions & 0 deletions services/class_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type ClassService interface {
GetClass(classID uint) (*models.Class, error)
CreateClass(request dto.CreateClassRequest) (uint, error)
UpdateClassImage(classID uint, imageUrl string) error
UpdateClass(classID uint, userID uint, request dto.UpdateClassRequest) error
DeleteClass(classID uint, userID uint) error
}

Expand Down Expand Up @@ -51,6 +52,38 @@ func (s *classServiceImpl) UpdateClassImage(classID uint, imageUrl string) error
return s.classRepo.UpdateClassImage(classID, imageUrl)
}

func (s *classServiceImpl) UpdateClass(classID uint, userID uint, request dto.UpdateClassRequest) error {
isAdmin, err := s.IsAdmin(userID, classID)
if err != nil || !isAdmin {
return errors.New("unauthorized: user is not an admin")
}

class, err := s.GetClass(classID)
if err != nil {
return err
}

if request.Name != "" {
class.Name = request.Name
}
if request.Limitation != nil {
class.Limitation = request.Limitation
}
if request.Description != nil {
class.Description = request.Description
}

return s.classRepo.Update(class)
}

func (s *classServiceImpl) IsAdmin(userID uint, classID uint) (bool, error) {
roleID, err := s.classUserRepo.GetRole(userID, classID)
if err != nil {
return false, err
}
return roleID == 2, nil
}

func (s *classServiceImpl) DeleteClass(classID uint, userID uint) error {
roleID, err := s.classUserRepo.GetRole(userID, classID)
if err != nil {
Expand Down

0 comments on commit 2660301

Please sign in to comment.