async def import_project(request: web.Request): # bumping this requests's max size # pylint: disable=protected-access exporter_settings = get_plugin_settings(request.app) assert ( # nosec exporter_settings is not None ), "this call was not expected with a disabled plugin" # nosec request._client_max_size = exporter_settings.EXPORTER_MAX_UPLOAD_FILE_SIZE * ONE_GB post_contents = await request.post() log.info("POST body %s", post_contents) user_id = request[RQT_USERID_KEY] file_name_field: FileField = post_contents.get("fileName", None) if file_name_field is None: raise ExporterException("Expected a file as 'fileName' form parmeter") if not isinstance(file_name_field, FileField): raise ExporterException("Please select a file") temp_dir: str = await get_empty_tmp_dir() imported_project_uuid = await study_import(app=request.app, temp_dir=temp_dir, file_field=file_name_field, user_id=user_id) await remove_dir(directory=temp_dir) return dict(uuid=imported_project_uuid)
async def _command_proxy( self, path: str, request: web.Request) -> web.Response | web.StreamResponse: """Return a client request with proxy origin for Hass.io supervisor. This method is a coroutine. """ read_timeout = _get_timeout(path) client_timeout = 10 data = None headers = _init_header(request) if path == "snapshots/new/upload": # We need to reuse the full content type that includes the boundary headers["Content-Type"] = request._stored_content_type # pylint: disable=protected-access # Snapshots are big, so we need to adjust the allowed size request._client_max_size = ( # pylint: disable=protected-access MAX_UPLOAD_SIZE) client_timeout = 300 try: with async_timeout.timeout(client_timeout): data = await request.read() method = getattr(self._websession, request.method.lower()) client = await method( f"http://{self._host}/{path}", data=data, headers=headers, timeout=read_timeout, ) # Simple request if int(client.headers.get(CONTENT_LENGTH, 0)) < 4194000: # Return Response body = await client.read() return web.Response(content_type=client.content_type, status=client.status, body=body) # Stream response response = web.StreamResponse(status=client.status, headers=client.headers) response.content_type = client.content_type await response.prepare(request) async for data in client.content.iter_chunked(4096): await response.write(data) return response except aiohttp.ClientError as err: _LOGGER.error("Client error on api %s request %s", path, err) except asyncio.TimeoutError: _LOGGER.error("Client timeout error on API request %s", path) raise HTTPBadGateway()
async def post(self, request: web.Request) -> web.Response: """Handle upload.""" if not request["hass_user"].is_admin: raise Unauthorized() # Increase max payload request._client_max_size = MAX_UPLOAD_SIZE # pylint: disable=protected-access try: data = self.schema(dict(await request.post())) except vol.Invalid as err: LOGGER.error("Received invalid upload data: %s", err) raise web.HTTPBadRequest() from err try: item = MediaSourceItem.from_uri(self.hass, data["media_content_id"]) except ValueError as err: LOGGER.error("Received invalid upload data: %s", err) raise web.HTTPBadRequest() from err try: source_dir_id, location = self.source.async_parse_identifier(item) except Unresolvable as err: LOGGER.error("Invalid local source ID") raise web.HTTPBadRequest() from err uploaded_file: FileField = data["file"] if not uploaded_file.content_type.startswith( ("image/", "video/", "audio/")): LOGGER.error("Content type not allowed") raise vol.Invalid("Only images and video are allowed") try: raise_if_invalid_filename(uploaded_file.filename) except ValueError as err: LOGGER.error("Invalid filename") raise web.HTTPBadRequest() from err try: await self.hass.async_add_executor_job( self._move_file, self.source.async_full_path(source_dir_id, location), uploaded_file, ) except ValueError as err: LOGGER.error("Moving upload failed: %s", err) raise web.HTTPBadRequest() from err return self.json({ "media_content_id": f"{data['media_content_id']}/{uploaded_file.filename}" })
async def _upload_file(self, request: web.Request) -> web.Response: """Handle uploaded file.""" # Increase max payload request._client_max_size = MAX_SIZE # pylint: disable=protected-access data = await request.post() file_field = data.get("file") if not isinstance(file_field, web.FileField): raise vol.Invalid("Expected a file") try: raise_if_invalid_filename(file_field.filename) except ValueError as err: raise web.HTTPBadRequest from err hass: HomeAssistant = request.app["hass"] file_id = ulid_hex() if DOMAIN not in hass.data: hass.data[DOMAIN] = await FileUploadData.create(hass) file_upload_data: FileUploadData = hass.data[DOMAIN] file_dir = file_upload_data.file_dir(file_id) def _sync_work() -> None: file_dir.mkdir() # MyPy forgets about the isinstance check because we're in a function scope assert isinstance(file_field, web.FileField) with (file_dir / file_field.filename).open("wb") as target_fileobj: shutil.copyfileobj(file_field.file, target_fileobj) await hass.async_add_executor_job(_sync_work) file_upload_data.files[file_id] = file_field.filename return self.json({"file_id": file_id})
async def post(self, request: web.Request, config_entry_id: str, node_id: str) -> web.Response: """Handle upload.""" if not request["hass_user"].is_admin: raise Unauthorized() hass = request.app["hass"] if config_entry_id not in hass.data[DOMAIN]: raise web_exceptions.HTTPBadRequest entry = hass.config_entries.async_get_entry(config_entry_id) client: Client = hass.data[DOMAIN][config_entry_id][DATA_CLIENT] node = client.driver.controller.nodes.get(int(node_id)) if not node: raise web_exceptions.HTTPNotFound # Increase max payload request._client_max_size = 1024 * 1024 * 10 # pylint: disable=protected-access data = await request.post() if "file" not in data or not isinstance(data["file"], web_request.FileField): raise web_exceptions.HTTPBadRequest uploaded_file: web_request.FileField = data["file"] try: await begin_firmware_update( entry.data[CONF_URL], node, uploaded_file.filename, await hass.async_add_executor_job(uploaded_file.file.read), async_get_clientsession(hass), ) except BaseZwaveJSServerError as err: raise web_exceptions.HTTPBadRequest from err return self.json(None)
async def mainHandler(self, WebRequest: Request, handler: Callable) -> Response or StreamResponse: if WebRequest.match_info.get("x", "") == "import": # import files can be giants WebRequest._client_max_size = -1 # db is about to shutdown or its currently importing if not self.active: return self.response(status=400, body=json.dumps( dict(code=400, status="rejected", msg="DB is marked as disabled"))) # is limited to certain ip's if self.PhaazeDBS.allowed_ips != []: if WebRequest.remote not in self.PhaazeDBS.allowed_ips: return self.response(status=400, body=json.dumps( dict(code=400, status="rejected", msg="ip not allowed"))) # get process method, default is json WebRequest.db_method: str = await self.getMethod(WebRequest) try: Resp: Response = await handler(WebRequest) return Resp except HTTPException as Http_ex: return self.response(body=json.dumps( dict(msg=Http_ex.reason, status=Http_ex.status)), status=Http_ex.status) except Exception as e: self.PhaazeDBS.Logger.error(str(e)) return self.response(status=500)