com.devicehive.service.NetworkService.java Source code

Java tutorial

Introduction

Here is the source code for com.devicehive.service.NetworkService.java

Source

package com.devicehive.service;

/*
 * #%L
 * DeviceHive Java Server Common business logic
 * %%
 * Copyright (C) 2016 DataArt
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.devicehive.auth.HiveAuthentication;
import com.devicehive.auth.HivePrincipal;
import com.devicehive.configuration.Messages;
import com.devicehive.dao.NetworkDao;
import com.devicehive.exceptions.ActionNotAllowedException;
import com.devicehive.exceptions.IllegalParametersException;
import com.devicehive.model.rpc.ListNetworkRequest;
import com.devicehive.model.rpc.ListNetworkResponse;
import com.devicehive.model.updates.NetworkUpdate;
import com.devicehive.service.configuration.ConfigurationService;
import com.devicehive.service.helpers.ResponseConsumer;
import com.devicehive.shim.api.Request;
import com.devicehive.shim.api.Response;
import com.devicehive.shim.api.client.RpcClient;
import com.devicehive.util.HiveValidator;
import com.devicehive.vo.DeviceVO;
import com.devicehive.vo.NetworkVO;
import com.devicehive.vo.NetworkWithUsersAndDevicesVO;
import com.devicehive.vo.UserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static java.util.Optional.*;

@Component
public class NetworkService {
    public static final String ALLOW_NETWORK_AUTO_CREATE = "allowNetworkAutoCreate";
    private static final Logger logger = LoggerFactory.getLogger(NetworkService.class);
    @Autowired
    private UserService userService;
    @Autowired
    private ConfigurationService configurationService;
    @Autowired
    private HiveValidator hiveValidator;
    @Autowired
    private NetworkDao networkDao;
    @Autowired
    private RpcClient rpcClient;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public NetworkWithUsersAndDevicesVO getWithDevicesAndDeviceClasses(@NotNull Long networkId,
            @NotNull HiveAuthentication hiveAuthentication) {
        HivePrincipal principal = (HivePrincipal) hiveAuthentication.getPrincipal();

        Set<Long> permittedNetworks = principal.getNetworkIds();
        Set<String> permittedDevices = principal.getDeviceGuids();

        Optional<NetworkWithUsersAndDevicesVO> result = of(principal).flatMap(pr -> {
            if (pr.getUser() != null)
                return of(pr.getUser());
            else
                return empty();
        }).flatMap(user -> {
            Long idForFiltering = user.isAdmin() ? null : user.getId();
            List<NetworkWithUsersAndDevicesVO> found = networkDao.getNetworksByIdsAndUsers(idForFiltering,
                    Collections.singleton(networkId), permittedNetworks);
            return found.stream().findFirst();
        }).map(network -> {
            //fixme - important, restore functionality once permission evaluator is switched to jwt
            /*if (principal.getKey() != null) {
                Set<AccessKeyPermissionVO> permissions = principal.getKey().getPermissions();
                Set<AccessKeyPermissionVO> filtered = CheckPermissionsHelper
                        .filterPermissions(principal.getKey(), permissions, AccessKeyAction.GET_DEVICE,
                                details.getClientInetAddress(), details.getOrigin());
                if (filtered.isEmpty()) {
                    network.setDevices(Collections.emptySet());
                }
            }*/
            if (permittedDevices != null && !permittedDevices.isEmpty()) {
                Set<DeviceVO> allowed = network.getDevices().stream()
                        .filter(device -> permittedDevices.contains(device.getGuid())).collect(Collectors.toSet());
                network.setDevices(allowed);
            }
            return network;
        });

        return result.orElse(null);
    }

    @Transactional
    public boolean delete(long id) {
        logger.trace("About to execute named query \"Network.deleteById\" for ");
        int result = networkDao.deleteById(id);
        logger.debug("Deleted {} rows from Network table", result);
        return result > 0;
    }

    @Transactional
    public NetworkVO create(NetworkVO newNetwork) {
        logger.debug("Creating network {}", newNetwork);
        if (newNetwork.getId() != null) {
            logger.error("Can't create network entity with id={} specified", newNetwork.getId());
            throw new IllegalParametersException(Messages.ID_NOT_ALLOWED);
        }
        List<NetworkVO> existing = networkDao.findByName(newNetwork.getName());
        if (!existing.isEmpty()) {
            logger.error("Network with name {} already exists", newNetwork.getName());
            throw new ActionNotAllowedException(Messages.DUPLICATE_NETWORK);
        }
        hiveValidator.validate(newNetwork);
        networkDao.persist(newNetwork);
        logger.info("Entity {} created successfully", newNetwork);
        return newNetwork;
    }

    @Transactional
    public NetworkVO update(@NotNull Long networkId, NetworkUpdate networkUpdate) {
        NetworkVO existing = networkDao.find(networkId);
        if (existing == null) {
            throw new NoSuchElementException(String.format(Messages.NETWORK_NOT_FOUND, networkId));
        }
        if (networkUpdate.getKey() != null) {
            existing.setKey(networkUpdate.getKey().orElse(null));
        }
        if (networkUpdate.getName() != null) {
            existing.setName(networkUpdate.getName().orElse(null));
        }
        if (networkUpdate.getDescription() != null) {
            existing.setDescription(networkUpdate.getDescription().orElse(null));
        }
        hiveValidator.validate(existing);

        return networkDao.merge(existing);
    }

    //@Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CompletableFuture<List<NetworkVO>> list(String name, String namePattern, String sortField,
            boolean sortOrderAsc, Integer take, Integer skip, HivePrincipal principal) {
        Optional<HivePrincipal> principalOpt = ofNullable(principal);

        ListNetworkRequest request = new ListNetworkRequest();
        request.setName(name);
        request.setNamePattern(namePattern);
        request.setSortField(sortField);
        request.setSortOrderAsc(sortOrderAsc);
        request.setTake(take);
        request.setSkip(skip);
        request.setPrincipal(principalOpt);

        CompletableFuture<Response> future = new CompletableFuture<>();

        rpcClient.call(Request.newBuilder().withBody(request).build(), new ResponseConsumer(future));

        return future.thenApply(r -> ((ListNetworkResponse) r.getBody()).getNetworks());
    }

    @Transactional
    public NetworkVO createOrVerifyNetwork(Optional<NetworkVO> networkNullable) {
        //case network is not defined
        if (networkNullable == null || networkNullable.orElse(null) == null) {
            return null;
        }
        NetworkVO network = networkNullable.get();

        Optional<NetworkVO> storedOpt = findNetworkByIdOrName(network);
        if (storedOpt.isPresent()) {
            return validateNetworkKey(storedOpt.get(), network);
        } else {
            if (network.getId() != null) {
                throw new IllegalParametersException(Messages.INVALID_REQUEST_PARAMETERS);
            }
            boolean allowed = configurationService.getBoolean(ALLOW_NETWORK_AUTO_CREATE, false);
            if (allowed) {
                NetworkWithUsersAndDevicesVO newNetwork = new NetworkWithUsersAndDevicesVO(network);
                networkDao.persist(newNetwork);
                network.setId(newNetwork.getId());
            }
            return network;
        }
    }

    @Transactional
    public NetworkVO createOrUpdateNetworkByUser(Optional<NetworkVO> networkNullable, UserVO user) {
        //case network is not defined
        if (networkNullable == null || networkNullable.orElse(null) == null) {
            return null;
        }

        NetworkVO network = networkNullable.orElse(null);

        Optional<NetworkVO> storedOpt = findNetworkByIdOrName(network);
        if (storedOpt.isPresent()) {
            NetworkVO stored = validateNetworkKey(storedOpt.get(), network);
            if (!userService.hasAccessToNetwork(user, stored)) {
                throw new ActionNotAllowedException(Messages.NO_ACCESS_TO_NETWORK);
            }
            return stored;
        } else {
            if (network.getId() != null) {
                throw new IllegalParametersException(Messages.INVALID_REQUEST_PARAMETERS);
            }
            boolean allowed = configurationService.getBoolean(ALLOW_NETWORK_AUTO_CREATE, false);
            if (user.isAdmin() || allowed) {
                NetworkWithUsersAndDevicesVO newNetwork = new NetworkWithUsersAndDevicesVO(network);
                networkDao.persist(newNetwork);
                network.setId(newNetwork.getId());
                userService.assignNetwork(user.getId(), network.getId()); // Assign created network to user
            } else {
                throw new ActionNotAllowedException(Messages.NETWORK_CREATION_NOT_ALLOWED);
            }
            return network;
        }
    }

    private Optional<NetworkVO> findNetworkByIdOrName(NetworkVO network) {
        return ofNullable(network.getId()).map(id -> ofNullable(networkDao.find(id)))
                .orElseGet(() -> networkDao.findFirstByName(network.getName()));
    }

    private NetworkVO validateNetworkKey(NetworkVO stored, NetworkVO received) {
        if (stored.getKey() != null && !stored.getKey().equals(received.getKey())) {
            throw new ActionNotAllowedException(Messages.INVALID_NETWORK_KEY);
        }
        return stored;
    }
}