Ejemplo n.º 1
0
    def _check_auth(self, req: Request):
        if self.auth_manager is None:
            return

        if req.get_auth() is None:
            self._respond_with_error(req, "NeAuthError", "The bridge only accepts requests based on privileges")
            raise AuthError()

        auth = req.get_auth()
        try:
            if isinstance(auth, CredentialsAuthContainer):
                self.auth_manager.authenticate(auth.username, auth.password)
                self.auth_manager.check_path_access_level_for_user(auth.username,
                                                                   req.get_path())
            elif isinstance(auth, SerialAuthContainer):
                self.auth_manager.check_path_access_level(ApiAccessLevel.admin,
                                                          req.get_path())
            elif isinstance(auth, MqttAuthContainer):
                self.auth_manager.check_path_access_level(ApiAccessLevel.mqtt,
                                                          req.get_path())
            else:
                self._respond_with_error(req, "UnknownAuthError", "Unknown error occurred")
                raise AuthError()
        except AuthenticationFailedException:
            self._respond_with_error(req, "WrongAuthError", "illegal combination of username and password")
            raise AuthError()
        except UserDoesNotExistException:
            self._respond_with_error(req, "UserDoesntExistError", "User does not exist")
            raise AuthError()
        except InsufficientAccessPrivilegeException:
            self._respond_with_error(req, "AccessLevelError", "Insufficient privileges")
            raise AuthError()
        except UnknownUriException:
            self._handle_unknown(req)
            raise AuthError()
Ejemplo n.º 2
0
    def _handle_request(self, req: Request):
        self._log_request(req)

        try:
            self._check_auth(req)
        except AuthError:
            return

        switcher = {
            ApiURIs.heartbeat.uri: self._handle_heartbeat,
            ApiURIs.sync_client.uri: self._handle_client_sync,
            ApiURIs.info_bridge.uri: self._handle_info_bridge,
            ApiURIs.info_gadgets.uri: self._handle_info_gadgets,
            ApiURIs.info_clients.uri: self._handle_info_clients,
            ApiURIs.update_gadget.uri: self._handle_update_gadget,
            ApiURIs.client_reboot.uri: self._handle_client_reboot,
            ApiURIs.client_config_write.uri: self._handle_client_config_write,
            ApiURIs.client_config_delete.uri: self._handle_client_config_delete,
            ApiURIs.config_storage_get_all.uri: self._handle_get_all_configs,
            ApiURIs.config_storage_get.uri: self._handle_get_config,
            ApiURIs.config_storage_save.uri: self._handle_save_config,
            ApiURIs.config_storage_delete.uri: self._handle_delete_config,
            ApiURIs.bridge_update_check.uri: self._handle_check_bridge_for_update,
            ApiURIs.bridge_update_execute.uri: self._handle_bridge_update
        }
        handler: Callable[[Request], None] = switcher.get(req.get_path(), self._handle_unknown)
        handler(req)
Ejemplo n.º 3
0
class RestServerRequestManager:
    _request: Request
    _response: Optional[Request]

    def __init__(self, hostname: str, path: str, payload: dict,
                 auth: Optional[AuthContainer]):
        self._response = None
        self._create_incoming_request(hostname, path, payload, auth)

    def __del__(self):
        pass

    def _create_incoming_request(self, hostname: str, path: str, payload: dict,
                                 auth: Optional[AuthContainer]):
        session_id = random.randint(0, 30000)
        sender = f"rest_client_{session_id}"
        self._request = Request(path=path,
                                session_id=session_id,
                                sender=sender,
                                receiver=hostname,
                                payload=payload)
        if auth is not None:
            self._request.set_auth(auth)
        self._request.set_callback_method(self._get_response_function())

    def _get_response_function(self) -> response_callback_type:
        def respond(req: Request, payload: dict, path: Optional[str]):
            if req.get_session_id() != self._request.get_session_id():
                raise IllegalResponseException(
                    f"Session IDs {req.get_session_id()} and "
                    f"{self._request.get_session_id()} are not matching")
            if path is not None:
                res_path = path
            else:
                res_path = req.get_path()

            self._response = Request(path=res_path,
                                     session_id=req.get_session_id(),
                                     sender=self._request.get_receiver(),
                                     receiver=req.get_sender(),
                                     payload=payload)

        return respond

    def get_request(self) -> Request:
        return self._request

    def await_response(self, timeout: int = 2) -> Request:
        start_time = datetime.now()
        while self._response is None:
            time.sleep(0.1)
            now = datetime.now()
            if now > (start_time + timedelta(seconds=timeout)):
                break

        if self._response is None:
            raise NoResponseReceivedError(self._request.get_path())
        return self._response
Ejemplo n.º 4
0
 def mock_response_function(req: Request, payload: dict, path: str):
     if path is None:
         buf_path = req.get_path()
     else:
         buf_path = path
     out_req = Request(path=buf_path,
                       session_id=req.get_session_id(),
                       sender=req.get_receiver(),
                       receiver=req.get_sender(),
                       payload=payload)
     self._last_response = out_req
Ejemplo n.º 5
0
    def _send(self, req: Request):
        """Sends a request on the serial port"""

        json_str = json.dumps(req.get_body())

        req_line = "!r_p[{}]_b[{}]_\n".format(req.get_path(), json_str)
        self._logger.debug("Sending: {}".format(req_line[:-1]))
        out_data = req_line.encode()
        bytes_written = self._serial_client.write(out_data)
        if not bytes_written == len(out_data):
            self._logger.error(
                f"Problem sending request: only {bytes_written} of {len(out_data)} bytes written."
            )
Ejemplo n.º 6
0
    def _respond_to(self,
                    req: Request,
                    payload: dict,
                    path: Optional[str] = None):
        if path:
            out_path = path
        else:
            out_path = req.get_path()

        receiver = req.get_sender()

        out_req = Request(out_path, req.get_session_id(), self._host_name,
                          receiver, payload)

        self._send(out_req)
Ejemplo n.º 7
0
        def respond(req: Request, payload: dict, path: Optional[str]):
            if req.get_session_id() != self._request.get_session_id():
                raise IllegalResponseException(
                    f"Session IDs {req.get_session_id()} and "
                    f"{self._request.get_session_id()} are not matching")
            if path is not None:
                res_path = path
            else:
                res_path = req.get_path()

            self._response = Request(path=res_path,
                                     session_id=req.get_session_id(),
                                     sender=self._request.get_receiver(),
                                     receiver=req.get_sender(),
                                     payload=payload)
 def _format_request(req: Request) -> str:
     req_obj = {"path": req.get_path(), "body": req.get_body()}
     req_str = json.dumps(req_obj)
     return req_str
Ejemplo n.º 9
0
    def _format_request(req: Request) -> str:
        json_str = json.dumps(req.get_body())

        req_line = "!r_p[{}]_b[{}]_\n".format(req.get_path(), json_str)
        return req_line
Ejemplo n.º 10
0
    def send_request_split(self,
                           path: str,
                           receiver: str,
                           payload: dict,
                           part_max_size: int = 30,
                           timeout: Optional[int] = None) -> Optional[Request]:
        """
        Sends a request to all attached networks.
        The request will be split into individual parts with a maximum length.

        :param path: Path to send the request on
        :param receiver: Receiver for the Request
        :param payload: Payload to be send
        :param part_max_size: Maximum size in bytes for each individual payload chunk
        :param timeout: Maximum timeout to wait for an answer
        :return: The response if there is any
        """
        if timeout is None:
            timeout = self._default_timeout
        req = Request(path, None, self._hostname, receiver, payload)
        session_id = req.get_session_id()
        path = req.get_path()
        sender = req.get_sender()
        receiver = req.get_receiver()

        payload_str = json.dumps(req.get_payload())

        # Make string ready to be contained in json itself
        payload_str = payload_str.replace('"', "$*$")

        payload_len = len(payload_str)
        parts = []
        start = 0
        package_index = 0

        while start < payload_len:
            end = start + part_max_size
            payload_part = payload_str[start:(
                end if end < payload_len else payload_len)]
            parts.append(payload_part)
            start = end

        last_index = len(parts)

        for payload_part in parts:

            out_dict = {
                "package_index": package_index,
                "split_payload": payload_part
            }
            if package_index == 0:
                out_dict["last_index"] = last_index

            out_req = Request(path, session_id, sender, receiver, out_dict)
            if package_index == last_index - 1:
                responses = self._send_request_obj(out_req, timeout, 1)
                if not responses:
                    return None
                return responses[0]
            else:
                self._send_request_obj(out_req, 0, 0)
            package_index += 1
            sleep(0.1)
        return None