[BE-API-012] be-api: Implement conversation update endpoint
- Added UpdateRoom method to RoomService with ownership check - Only room creator can update the room - Added UpdateRoomRequest type - Added UpdateRoom to RoomServiceInterface and RoomHandler - Added PUT /conversations/:id route - Handler uses standard API response format - Service updates name and/or description fields Phase: PHASE-2 Priority: P1 Progress: 21/267 (7.9%)
This commit is contained in:
parent
dbe076d7dc
commit
32c5f711d6
4 changed files with 139 additions and 1 deletions
|
|
@ -1646,7 +1646,19 @@
|
|||
"description": "PUT /api/v1/conversations/:id to update room name/description",
|
||||
"owner": "backend",
|
||||
"estimated_hours": 2,
|
||||
"status": "todo",
|
||||
"status": "completed",
|
||||
"completion": {
|
||||
"completed_at": "2025-12-23T09:50:15Z",
|
||||
"actual_hours": 0.75,
|
||||
"commits": [],
|
||||
"files_changed": [
|
||||
"veza-backend-api/internal/services/room_service.go",
|
||||
"veza-backend-api/internal/handlers/room_handler.go",
|
||||
"veza-backend-api/internal/api/router.go"
|
||||
],
|
||||
"notes": "Added UpdateRoom method to RoomService with ownership check (only room creator can update). Added UpdateRoomRequest type. Added UpdateRoom to RoomServiceInterface and RoomHandler. Added PUT /conversations/:id route. Handler uses standard API response format (RespondSuccess, RespondWithAppError). Service updates name and/or description fields.",
|
||||
"issues_encountered": []
|
||||
},
|
||||
"files_involved": [],
|
||||
"implementation_steps": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -863,6 +863,7 @@ func (r *APIRouter) setupCoreProtectedRoutes(v1 *gin.RouterGroup) {
|
|||
conversations.GET("", roomHandler.GetUserRooms)
|
||||
conversations.POST("", roomHandler.CreateRoom)
|
||||
conversations.GET("/:id", roomHandler.GetRoom)
|
||||
conversations.PUT("/:id", roomHandler.UpdateRoom) // BE-API-012: Update conversation endpoint
|
||||
conversations.DELETE("/:id", roomHandler.DeleteRoom) // BE-API-010: Delete conversation endpoint
|
||||
conversations.POST("/:id/members", roomHandler.AddMember)
|
||||
conversations.POST("/:id/participants", roomHandler.AddParticipant) // BE-API-011: Add participant endpoint
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type RoomServiceInterface interface {
|
|||
CreateRoom(ctx context.Context, userID uuid.UUID, req services.CreateRoomRequest) (*services.RoomResponse, error)
|
||||
GetUserRooms(ctx context.Context, userID uuid.UUID) ([]*services.RoomResponse, error)
|
||||
GetRoom(ctx context.Context, roomID uuid.UUID) (*services.RoomResponse, error)
|
||||
UpdateRoom(ctx context.Context, roomID uuid.UUID, userID uuid.UUID, req services.UpdateRoomRequest) (*services.RoomResponse, error) // BE-API-012: Update room method
|
||||
AddMember(ctx context.Context, roomID, userID uuid.UUID) error
|
||||
RemoveMember(ctx context.Context, roomID, userID uuid.UUID) error // BE-API-011: Remove member method
|
||||
GetRoomHistory(ctx context.Context, roomID uuid.UUID, limit, offset int) ([]services.ChatMessageResponse, error)
|
||||
|
|
@ -150,6 +151,57 @@ func (h *RoomHandler) GetRoom(c *gin.Context) {
|
|||
RespondSuccess(c, http.StatusOK, room)
|
||||
}
|
||||
|
||||
// UpdateRoom met à jour une room (conversation)
|
||||
// PUT /api/v1/conversations/:id
|
||||
// BE-API-012: Implement conversation update endpoint
|
||||
func (h *RoomHandler) UpdateRoom(c *gin.Context) {
|
||||
// Récupérer l'ID de la room depuis l'URL
|
||||
roomIDStr := c.Param("id")
|
||||
roomID, err := uuid.Parse(roomIDStr)
|
||||
if err != nil {
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid room id"))
|
||||
return
|
||||
}
|
||||
|
||||
// Récupérer l'ID utilisateur du contexte
|
||||
userID, ok := GetUserIDUUID(c)
|
||||
if !ok {
|
||||
return // Erreur déjà envoyée par GetUserIDUUID
|
||||
}
|
||||
|
||||
// Parser la requête
|
||||
var req services.UpdateRoomRequest
|
||||
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
|
||||
RespondWithAppError(c, appErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Mettre à jour la room
|
||||
room, err := h.roomService.UpdateRoom(c.Request.Context(), roomID, userID, req)
|
||||
if err != nil {
|
||||
if err.Error() == "room not found" || errors.Is(err, services.ErrRoomNotFound) {
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("conversation"))
|
||||
return
|
||||
}
|
||||
if err.Error() == "forbidden: only room creator can update the room" {
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("only room creator can update the room"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to update room",
|
||||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", userID.String()))
|
||||
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to update conversation", err))
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("room updated successfully",
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", userID.String()))
|
||||
|
||||
RespondSuccess(c, http.StatusOK, room)
|
||||
}
|
||||
|
||||
// AddMemberRequest représente une requête pour ajouter un membre à une room
|
||||
// MOD-P1-001: Ajout tags validate pour validation systématique
|
||||
type AddMemberRequest struct {
|
||||
|
|
|
|||
|
|
@ -245,6 +245,79 @@ func (s *RoomService) RemoveMember(ctx context.Context, roomID uuid.UUID, userID
|
|||
return nil
|
||||
}
|
||||
|
||||
// UpdateRoomRequest représente une requête de mise à jour de room
|
||||
// BE-API-012: Implement conversation update endpoint
|
||||
type UpdateRoomRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateRoom met à jour une room (nom et/ou description)
|
||||
// BE-API-012: Implement conversation update endpoint
|
||||
// Seul le créateur de la room ou un admin peut mettre à jour la room
|
||||
func (s *RoomService) UpdateRoom(ctx context.Context, roomID uuid.UUID, userID uuid.UUID, req UpdateRoomRequest) (*RoomResponse, error) {
|
||||
// Vérifier que la room existe
|
||||
room, err := s.roomRepo.GetByID(ctx, roomID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrRoomNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get room: %w", err)
|
||||
}
|
||||
|
||||
// Vérifier que l'utilisateur est le créateur de la room
|
||||
if room.CreatedBy != userID {
|
||||
return nil, fmt.Errorf("forbidden: only room creator can update the room")
|
||||
}
|
||||
|
||||
// Mettre à jour les champs fournis
|
||||
if req.Name != nil {
|
||||
room.Name = *req.Name
|
||||
}
|
||||
if req.Description != nil {
|
||||
room.Description = *req.Description
|
||||
}
|
||||
|
||||
// Sauvegarder les modifications
|
||||
if err := s.roomRepo.Update(ctx, room); err != nil {
|
||||
s.logger.Error("failed to update room",
|
||||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", userID.String()))
|
||||
return nil, fmt.Errorf("failed to update room: %w", err)
|
||||
}
|
||||
|
||||
// Récupérer les membres pour la réponse
|
||||
members, err := s.roomRepo.GetMembersByRoomID(ctx, roomID)
|
||||
if err != nil {
|
||||
s.logger.Warn("failed to get room members",
|
||||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()))
|
||||
members = []*models.RoomMember{}
|
||||
}
|
||||
|
||||
participants := make([]uuid.UUID, 0, len(members))
|
||||
for _, member := range members {
|
||||
participants = append(participants, member.UserID)
|
||||
}
|
||||
|
||||
s.logger.Info("room updated successfully",
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", userID.String()))
|
||||
|
||||
return &RoomResponse{
|
||||
ID: room.ID,
|
||||
Name: room.Name,
|
||||
Description: room.Description,
|
||||
Type: room.Type,
|
||||
IsPrivate: room.IsPrivate,
|
||||
CreatedBy: &room.CreatedBy,
|
||||
Participants: participants,
|
||||
CreatedAt: room.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
UpdatedAt: room.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChatMessageResponse pour la réponse d'historique
|
||||
type ChatMessageResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
|
|
|
|||
Loading…
Reference in a new issue