org.sardineproject.sbyod.rest.AppWebUser.java Source code

Java tutorial

Introduction

Here is the source code for org.sardineproject.sbyod.rest.AppWebUser.java

Source

/*
 * Copyright 2015 Lorenz Reinhart
 *
 * 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.
 *
 *
 */
package org.sardineproject.sbyod.rest;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostService;
import org.onosproject.rest.AbstractWebResource;

import org.sardineproject.sbyod.portal.PortalManager;
import org.sardineproject.sbyod.portal.PortalService;
import org.sardineproject.sbyod.dns.DnsService;
import org.sardineproject.sbyod.service.ServiceId;
import org.slf4j.Logger;
import org.sardineproject.sbyod.connection.Connection;
import org.sardineproject.sbyod.connection.ConnectionStore;
import org.sardineproject.sbyod.connection.DefaultConnection;
import org.sardineproject.sbyod.service.Service;
import org.sardineproject.sbyod.service.ServiceStore;

import static org.slf4j.LoggerFactory.getLogger;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import java.security.InvalidParameterException;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Manage the users of the Sardine-BYOD network and their connections.
 */
@Path("/user")
public class AppWebUser extends AbstractWebResource {

    private static final Logger log = getLogger(PortalManager.class);

    private static final String INVALID_PARAMETER = "INVALID_PARAMETER\n";
    private final ObjectNode ENABLED_TRUE = mapper().createObjectNode().put("enabled", true);
    private final ObjectNode ENABLED_FALSE = mapper().createObjectNode().put("enabled", false);

    /**
     * Get the services the user with userIp is connected to.
     *
     * @param userIp_ the IP address of the user
     * @return PRECONDITION_FAILED if some parameter was wrong
     *          array of services
     */
    @GET
    @Path("/{userIp}")
    public Response getUserRules(@PathParam("userIp") String userIp_) {
        log.debug("AppWebUser: Getting services for userIp = {}", userIp_);

        if (userIp_ == null)
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        Set<Host> users;
        try {
            users = get(HostService.class).getHostsByIp(Ip4Address.valueOf(userIp_));
        } catch (Exception e) {
            return Response.status(Response.Status.PRECONDITION_FAILED).build();
        }

        // return invalid, if no user with this ip address is connected
        if (users.isEmpty())
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        // get the services the user is allowed to use without the portal service
        Iterable<Service> services = removeConfigurationServices(get(ServiceStore.class).getServices());
        // get all services a user has connected to
        Set<Service> userServices = Sets.newHashSet();
        for (Host host : users) {
            get(ConnectionStore.class).getConnections(host).forEach(c -> userServices.add(c.getService()));
        }

        ArrayNode arrayNode = mapper().createArrayNode();

        for (Service service : services) {
            ObjectNode serviceNode = mapper().createObjectNode().put("serviceName", service.name())
                    .put("serviceId", service.id().toString())
                    .put("serviceTpPort", (service.tpPort() == null ? "" : service.tpPort().toString()))
                    .put("icon", service.icon());
            if (userServices.contains(service))
                serviceNode.put("serviceEnabled", true);
            else
                serviceNode.put("serviceEnabled", false);

            arrayNode.add(serviceNode);
        }

        JsonNode result = mapper().createObjectNode().set("services", arrayNode);
        return Response.ok(result).build();

    }

    /**
     * Ask if a user with userIp has a access to the service with serviceId.
     *
     * @param userIp_ the IP address of the user
     * @param serviceId_ the ID of the service
     * @return PRECONDITION_FAILED if some parameter was wrong
     *          "enabled : false" if service is disabled
     *          "enabled : true" if service is enabled
     */
    @GET
    @Path("/{userIp}/service/{serviceId}")
    public Response getUserServices(@PathParam("userIp") String userIp_,
            @PathParam("serviceId") String serviceId_) {
        log.debug("AppWebUser: Getting rules for userIp = {} and serviceId = {}", userIp_, serviceId_);

        if (userIp_ == null || serviceId_ == null)
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        Set<Host> users;
        ServiceId serviceId;
        try {
            users = get(HostService.class).getHostsByIp(Ip4Address.valueOf(userIp_));
            serviceId = ServiceId.serviceId(serviceId_);
        } catch (Exception e) {
            return Response.status(Response.Status.PRECONDITION_FAILED).build();
        }

        // get all connections a user has activated
        Set<Connection> connections = Sets.newHashSet();
        users.forEach(u -> connections.addAll(get(ConnectionStore.class).getConnections(u)));

        // check if the connections contain a service with given service id
        if (connections.stream().map(Connection::getService).map(Service::id).collect(Collectors.toSet())
                .contains(serviceId)) {
            return Response.ok(ENABLED_TRUE).build();
        }
        return Response.ok(ENABLED_FALSE).build();
    }

    /**
     * Connect a host with userIP address to a service with serviceId.
     *
     * @param userIp_ the IP address of the user
     * @param serviceId_ the ID of the service
     * @return PRECONDITION_FAILED if some parameter was wrong
     *          "enabled : false" if service connection went wrong
     *          "enabled : true" if service is enabled
     */
    @POST
    @Path("/{userIp}/service/{serviceId}")
    public Response allowHostTraffic(@PathParam("userIp") String userIp_,
            @PathParam("serviceId") String serviceId_) {
        log.debug("AppWebUser: Adding connection between user ip = {} and serviceId = {}",
                new String[] { userIp_, serviceId_ });

        if (userIp_ == null || serviceId_ == null)
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        Service service;
        Set<Host> srcHosts;
        try {
            Ip4Address userIp = Ip4Address.valueOf(userIp_);
            srcHosts = get(HostService.class).getHostsByIp(userIp);
            service = get(ServiceStore.class).getService(ServiceId.serviceId(serviceId_));
        } catch (Exception e) {
            return Response.status(Response.Status.PRECONDITION_FAILED).build();
        }

        if (srcHosts.isEmpty()) {
            log.debug("AppWebUser: No host found with IP = {}", userIp_);
            return Response.ok(ENABLED_FALSE).build();
        } else if (service == null) {
            log.debug("AppWebUser: No service found with id = {}", serviceId_);
            return Response.ok(ENABLED_FALSE).build();
        }

        // install connection for every host and service
        for (Host srcHost : srcHosts) {
            try {
                Connection connection = new DefaultConnection(srcHost, service);
                // if the connection does not already exist
                if (!get(ConnectionStore.class).contains(connection)) {
                    log.debug("AppWebUser: Installing connection {}", connection.toString());
                    get(ConnectionStore.class).addConnection(connection);
                } else {
                    log.debug("AppWebUser: Connection {} already exists", connection.toString());
                }
            } catch (InvalidParameterException ipe) {
                log.debug("AppWebUser: InvalidParameterException {}", ipe);
                return Response.ok(ENABLED_FALSE).build();
            }
        }

        return Response.ok(ENABLED_TRUE).build();
    }

    /**
     * Disconnect a user from a service.
     * @param userIp_ the IP address of the user
     * @param serviceId_ the ID of the service
     * @return PRECONDITION_FAILED if some parameter was wrong
     *          "enabled : false" if user is disconnected
     *          "enabled : true" if user disconnection went wrong
     */
    @DELETE
    @Path("/{userIp}/service/{serviceId}")
    public Response deleteHostTraffic(@PathParam("userIp") String userIp_,
            @PathParam("serviceId") String serviceId_) {
        log.debug("AppWebUser: Removing connection between user ip = {} and serviceId = {}",
                new String[] { userIp_, serviceId_ });

        if (userIp_ == null || serviceId_ == null)
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        Service service;
        Set<Host> srcHosts;
        try {
            Ip4Address userIp = Ip4Address.valueOf(userIp_);
            srcHosts = get(HostService.class).getHostsByIp(userIp);
            service = get(ServiceStore.class).getService(ServiceId.serviceId(serviceId_));
        } catch (Exception e) {
            return Response.status(Response.Status.PRECONDITION_FAILED).build();
        }

        Service portalService = get(PortalService.class).getPortalService();
        if (service.equals(portalService)) {
            log.warn("AppWebUser: The portal service can not be disabled.");
            return Response.ok(ENABLED_TRUE).build();
        }

        if (srcHosts.isEmpty()) {
            log.debug("AppWebUser: No host found with IP = {}", userIp_);
            return Response.ok(ENABLED_FALSE).build();
        } else if (service == null) {
            log.debug("AppWebUser: No service found with id = {}", serviceId_);
            return Response.ok(ENABLED_FALSE).build();
        }

        // remove connection for every host
        for (Host user : srcHosts) {
            Connection connection = get(ConnectionStore.class).getConnection(user, service);
            if (connection != null) {
                log.debug("AppWebUser: Removing connection {}", connection.toString());
                get(ConnectionStore.class).removeConnection(connection);
            }
        }

        return Response.ok(ENABLED_FALSE).build();
    }

    /**
     * Disconnect a user from all services.
     * @param userIp_ the IP address of the user
     * @return PRECONDITION_FAILED if some parameter was wrong
     *          "enabled : false" if user is disconnected
     *          "enabled : true" if user disconnection went wrong
     */
    @DELETE
    @Path("/{userIp}")
    public Response resetHostTraffic(@PathParam("userIp") String userIp_) {
        log.debug("AppWebUser: Removing all connections of user with ip = {}.", userIp_);

        if (userIp_ == null)
            return Response.status(Response.Status.PRECONDITION_FAILED).build();

        Set<Host> srcHosts;
        try {
            Ip4Address userIp = Ip4Address.valueOf(userIp_);
            // get all hosts with given ip
            srcHosts = get(HostService.class).getHostsByIp(userIp);
        } catch (Exception e) {
            return Response.status(Response.Status.PRECONDITION_FAILED).build();
        }

        if (srcHosts.isEmpty()) {
            log.debug("AppWebUser: No host found with IP = {}", userIp_);
            return Response.ok(ENABLED_FALSE).build();
        }

        // remove connection for every host
        for (Host user : srcHosts) {
            // get all connections of the host
            Set<Connection> connections = get(ConnectionStore.class).getConnections(user);
            // filter out portal and dns services
            connections = connections.stream()
                    .filter(c -> !c.getService().equals(get(PortalService.class).getPortalService()))
                    .filter(c -> !(get(DnsService.class).getDnsServices().contains(c.getService())))
                    .collect(Collectors.toSet());

            // remove all connections in set
            for (Connection connection : connections) {
                log.debug("AppWebUser: Removing connection {}", connection.toString());
                get(ConnectionStore.class).removeConnection(connection);
            }
        }

        return Response.ok(ENABLED_FALSE).build();
    }

    /**
     * This method removes all services from a set that are not intended for the user to manipulate,
     * for example the portal service or the dns service
     * @param services a set of services
     * @return an iterable of services without configuration services
     */
    private Iterable<Service> removeConfigurationServices(Set<Service> services) {
        // get the portalService
        Service portalService = get(PortalService.class).getPortalService();
        // get the dns services
        Set<Service> dnsServices = get(DnsService.class).getDnsServices();

        // remove the configuration services
        return services.stream().filter(s -> !s.equals(portalService)).filter(s -> !dnsServices.contains(s))
                .collect(Collectors.toSet());
    }
}