public Mono<HandleFriendRequestResult> authAndHandleFriendRequest(
            @NotNull Long friendRequestId,
            @NotNull Long requesterId,
            @NotNull @ValidResponseAction ResponseAction action,
            @Nullable String reason) {
        try {
            Validator.notNull(friendRequestId, "friendRequestId");
            Validator.notNull(requesterId, "requesterId");
            Validator.notNull(action, "action");
            DataValidator.validResponseAction(action);
            Validator.maxLength(reason, "reason", maxResponseReasonLength);
        } catch (ResponseException e) {
            return Mono.error(e);
        }
        return queryRequesterIdAndRecipientIdAndCreationDateAndStatus(friendRequestId)
                // If the requester is not authorized to the request,
                // they should not know the status of the request from the error code.
                // So we should not tell if the request exists or not.
                .switchIfEmpty(Mono.error(ResponseException
                        .get(ResponseStatusCode.NOT_RECIPIENT_TO_UPDATE_FRIEND_REQUEST)))
                .flatMap(request -> {
                    // If the requester is not authorized to the request,
                    // they should not know the status of the request from the error code.
                    // So we check whether the requester is authorized first.
                    if (!request.getRecipientId()
                            .equals(requesterId)) {
                        return Mono.error(ResponseException
                                .get(ResponseStatusCode.NOT_RECIPIENT_TO_UPDATE_FRIEND_REQUEST));
                    }
                    RequestStatus status = request.getStatus();
                    if (status == RequestStatus.PENDING) {
                        if (userFriendRequestRepository.isExpired(request.getCreationDate()
                                .getTime())) {
                            return Mono.error(ResponseException.get(
                                    ResponseStatusCode.UPDATE_NON_PENDING_FRIEND_REQUEST,
                                    "The request is under the status "
                                            + RequestStatus.EXPIRED));
                        }
                    } else {
                        return Mono.error(ResponseException.get(
                                ResponseStatusCode.UPDATE_NON_PENDING_FRIEND_REQUEST,
                                "The request is under the status "
                                        + status));
                    }
                    return switch (action) {
                        case ACCEPT -> userFriendRequestRepository
                                .inTransaction(session -> updatePendingFriendRequestStatus(
                                        friendRequestId,
                                        RequestStatus.ACCEPTED,
                                        reason,
                                        session)
                                        .then(userRelationshipService
                                                .friendTwoUsers(request.getRequesterId(),
                                                        // Note that the client request requester is
                                                        // the recipient
                                                        // of the friend request.
                                                        requesterId,
                                                        session)
                                                .map(pair -> new HandleFriendRequestResult(
                                                        request,
                                                        pair.first()
                                                                .newRelationshipGroupIndex(),
                                                        pair.second()
                                                                .newRelationshipGroupIndex()))))
                                .retryWhen(TRANSACTION_RETRY);
                        case IGNORE -> updatePendingFriendRequestStatus(friendRequestId,
                                RequestStatus.IGNORED,
                                reason,
                                null)
                                .thenReturn(new HandleFriendRequestResult(request, null, null));
                        case DECLINE -> updatePendingFriendRequestStatus(friendRequestId,
                                RequestStatus.DECLINED,
                                reason,
                                null)
                                .thenReturn(new HandleFriendRequestResult(request, null, null));
                        default ->
                            Mono.error(ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
                                    "The response action must not be UNRECOGNIZED"));
                    };
                });
    }
@return The requester ID, recipient ID, creation date and status.
turms-service/src/main/java/im/turms/service/domain/user/service/UserFriendRequestService.java