public Mono<Void> authAndUpdateGroupInformation(
            @NotNull Long requesterId,
            @NotNull Long groupId,
            @Nullable Long typeId,
            @Nullable Long creatorId,
            @Nullable Long ownerId,
            @Nullable String name,
            @Nullable String intro,
            @Nullable String announcement,
            @Nullable @Min(0) Integer minimumScore,
            @Nullable Boolean isActive,
            @Nullable @PastOrPresent Date creationDate,
            @Nullable @PastOrPresent Date deletionDate,
            @Nullable Date muteEndDate,
            @Nullable Map<String, Value> userDefinedAttributes,
            @Nullable ClientSession session) {
        try {
            Validator.notNull(requesterId, "requesterId");
            Validator.min(minimumScore, "minimumScore", 0);
            Validator.pastOrPresent(creationDate, "creationDate");
            Validator.pastOrPresent(deletionDate, "deletionDate");
            Validator.before(creationDate, deletionDate, "creationDate", "deletionDate");
        } catch (ResponseException e) {
            return Mono.error(e);
        }
        Mono<Void> checkIfAllowedToUpdateTypeId;
        if (typeId == null) {
            checkIfAllowedToUpdateTypeId = Mono.empty();
        } else {
            if (allowGroupOwnerChangeGroupType) {
                checkIfAllowedToUpdateTypeId =
                        isAllowedUpdateGroupToGroupType(requesterId, typeId, null)
                                .flatMap(permission -> {
                                    ResponseStatusCode code = permission.code();
                                    return code == ResponseStatusCode.OK
                                            ? Mono.empty()
                                            : Mono.error(ResponseException.get(code,
                                                    permission.reason()));
                                });
            } else {
                checkIfAllowedToUpdateTypeId = Mono.error(
                        ResponseException.get(ResponseStatusCode.UPDATING_GROUP_TYPE_IS_DISABLED));
            }
        }
        boolean noUserDefinedAttribute =
                userDefinedAttributes == null || userDefinedAttributes.isEmpty();
        if (Validator.areAllNull(creatorId,
                ownerId,
                name,
                intro,
                announcement,
                minimumScore,
                isActive,
                creationDate,
                deletionDate,
                muteEndDate) && noUserDefinedAttribute) {
            return checkIfAllowedToUpdateTypeId;
        }
        return checkIfAllowedToUpdateTypeId
                .then(Mono.defer(() -> queryGroupTypeIfActiveAndNotDeleted(groupId)
                        .switchIfEmpty(Mono.error(ResponseException
                                .get(ResponseStatusCode.UPDATE_INFO_OF_NONEXISTENT_GROUP)))
                        .flatMap(groupType -> {
                            GroupUpdateStrategy groupUpdateStrategy =
                                    groupType.getGroupInfoUpdateStrategy();
                            return switch (groupUpdateStrategy) {
                                case OWNER -> groupMemberService
                                        .isOwner(requesterId, groupId, false)
                                        .map(isOwner -> isOwner
                                                ? ResponseStatusCode.OK
                                                : ResponseStatusCode.NOT_GROUP_OWNER_TO_UPDATE_GROUP_INFO);
                                case OWNER_MANAGER -> groupMemberService
                                        .isOwnerOrManager(requesterId, groupId, false)
                                        .map(isOwnerOrManager -> isOwnerOrManager
                                                ? ResponseStatusCode.OK
                                                : ResponseStatusCode.NOT_GROUP_OWNER_OR_MANAGER_TO_UPDATE_GROUP_INFO);
                                case OWNER_MANAGER_MEMBER -> groupMemberService
                                        .isOwnerOrManagerOrMember(requesterId, groupId, false)
                                        .map(isMember -> isMember
                                                ? ResponseStatusCode.OK
                                                : ResponseStatusCode.NOT_GROUP_MEMBER_TO_UPDATE_GROUP_INFO);
                                case ALL -> Mono.just(ResponseStatusCode.OK);
                            };
                        })
                        .flatMap(code -> {
                            if (code != ResponseStatusCode.OK) {
                                return Mono.error(ResponseException.get(code));
                            }
                            if (noUserDefinedAttribute) {
                                return updateGroupInformation(groupId,
                                        typeId,
                                        creatorId,
                                        ownerId,
                                        name,
                                        intro,
                                        announcement,
                                        minimumScore,
                                        isActive,
                                        creationDate,
                                        deletionDate,
                                        muteEndDate,
                                        null,
                                        session);
                            }
                            return groupInfoUserCustomAttributesService
                                    .parseAttributesForUpsert(userDefinedAttributes)
                                    .flatMap(attributes -> updateGroupInformation(groupId,
                                            typeId,
                                            creatorId,
                                            ownerId,
                                            name,
                                            intro,
                                            announcement,
                                            minimumScore,
                                            isActive,
                                            creationDate,
                                            deletionDate,
                                            muteEndDate,
                                            attributes,
                                            session));
                        })));
    }
TODO: remove and keep {@link GroupService#queryGroupTypeIfActiveAndNotDeleted(Long, boolean)}
only.
turms-service/src/main/java/im/turms/service/domain/group/service/GroupService.java