/* ScheduleTogether Backend Copyright (C) 2024, Zervó Zadachin DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License version 3 for more details. This program incorporates external libraries for certain functionalities. These libraries are covered by their respective licenses, and their usage agreements are as outlined in their respective documentation or source code. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package friends import ( "slices" "github.com/kataras/iris/v12" db "git.zervo.org/scheduletogether/backend/internal/database" "git.zervo.org/scheduletogether/backend/pkg/helpers/request" "git.zervo.org/scheduletogether/backend/pkg/types" ) func FriendAccept_Service(ctx iris.Context, req types.FriendsAcceptRequest) { // Start a transaction tx := db.Db.Begin() // Get requesting user's ID from claims claims := request.GetUserClaims(ctx) id := claims.UserId // Make sure target user exists // Here target user refers to the user that *created* the friendrequest, opposite to friends_add var targetUser db.User err := tx.Where("uuid = ?", req.Uuid).First(&targetUser).Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusBadRequest) ctx.JSON(types.CommonErrorResponse{ Error: "User does not exist", }) return } // Get user from database // Here source user refers to the user *recieving* (accepting) the friendrequest, opposite to friends_add var sourceUser db.User err = tx.Where("id = ?", id).First(&sourceUser).Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusInternalServerError) ctx.JSON(types.CommonErrorResponse{ Error: "Something went wrong, please try again later", }) logboi.Warn("Failed to retrieve user from the database: " + err.Error()) return } // Make sure users are not already friends if slices.Contains(sourceUser.Friends, targetUser.Uuid) { tx.Rollback() ctx.StatusCode(iris.StatusBadRequest) ctx.JSON(types.CommonErrorResponse{ Error: "You are already friends with this user", }) } // Make sure friend request exists var friendRequest db.FriendRequest err = tx.Where("target = ? AND source = ?", sourceUser.Uuid, targetUser.Uuid).First(&friendRequest).Error if err == nil { tx.Rollback() ctx.StatusCode(iris.StatusBadRequest) ctx.JSON(types.CommonErrorResponse{ Error: "Friend request not found", }) return } // Add friend to source (receiving) user err = tx.Model(&db.User{}).Where("id = ?", id).Update("friends", append(sourceUser.Friends, targetUser.Uuid)).Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusInternalServerError) ctx.JSON(types.CommonErrorResponse{ Error: "Something went wrong, please try again later", }) logboi.Warn("Failed to update user on the database: " + err.Error()) return } // Add friend to target (accepting) user err = tx.Model(&db.User{}).Where("id = ?", targetUser.ID).Update("friends", append(targetUser.Friends, sourceUser.Uuid)).Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusInternalServerError) ctx.JSON(types.CommonErrorResponse{ Error: "Something went wrong, please try again later", }) logboi.Warn("Failed to update user on the database: " + err.Error()) return } // Remove friend request err = tx.Where("target = ? AND source = ?", targetUser.Uuid, sourceUser.Uuid).Delete(&db.FriendRequest{}).Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusInternalServerError) ctx.JSON(types.CommonErrorResponse{ Error: "Something went wrong, please try again later", }) logboi.Warn("Failed to delete friend request from the database: " + err.Error()) return } // Commit the transaction if everything is successful err = tx.Commit().Error if err != nil { tx.Rollback() ctx.StatusCode(iris.StatusInternalServerError) ctx.JSON(types.CommonErrorResponse{ Error: "Something went wrong, please try again later", }) return } ctx.JSON(types.CommonMessageResponse{ Message: "Friend request accepted", }) }