@cryptotaxi247 / CoPilot / commits / ebec2cab

upload file for storage (#86)

* upload file for storage accept uploaded yaml file for velociraptor connector authentication * file upload for velo api creds * precommit passing

taylor_socfortress committed Jul 31, 2023 at 16:46 UTC ebec2cabd52c053772cc87988c719ffef3eecf70
4 files changed +84
.gitignore
+1
@@ -41,3 +41,4 @@ wheels/
41 .env
42 *.sqbpro
43 site/
44 +backend/app/file-store/api.config.yaml
backend/app/routes/connectors.py
+18
@@ -76,3 +76,21 @@ def update_connector_route(id: str):
76 return validate_and_update_connector(id, request_data, service)
77 else:
78 return jsonify(connector), 404
79 +
80 +
81 +@bp.route("/connectors/upload", methods=["POST"])
82 +def upload_file():
83 + logger.info("Received request to upload a file")
84 + # check if the post request has the file part
85 + if "file" not in request.files:
86 + logger.error("No file part in the request")
87 + return {"message": "No file part in the request", "success": False}, 400
88 + file = request.files["file"]
89 + # if user does not select file, browser also
90 + # submit an empty part without filename
91 + if file.filename == "":
92 + logger.error("No selected file")
93 + return {"message": "No selected file", "success": False}, 400
94 +
95 + service = ConnectorService(db)
96 + return service.save_file(file)
backend/app/services/connectors/connectors.py
+23
@@ -1,7 +1,10 @@
1 # from app.models.connectors import ConnectorFactory
2 +import os
3 +
4 from flask import current_app
5 from loguru import logger
6 from sqlalchemy.exc import SQLAlchemyError
7 +from werkzeug.utils import secure_filename
8
9 from app.models.connectors import Connector
10 from app.models.connectors import connector_factory
@@ -10,6 +13,10 @@ from app.models.models import Connectors
13 # from app.models.models import ConnectorsAvailable
14 # from app.models.models import connectors_schema
15
16 +UPLOAD_FOLDER = "file-store"
17 +UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), UPLOAD_FOLDER)
18 +ALLOWED_EXTENSIONS = set(["yaml"]) # replace with your allowed file extensions
19 +
20
21 class ConnectorService:
22 """
@@ -234,3 +241,19 @@ class ConnectorService:
241 "message": "Request data is invalid. Ensure connector_url and connector_api_key are present",
242 "success": False,
243 }
244 +
245 + @staticmethod
246 + def allowed_file(filename):
247 + return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
248 +
249 + def save_file(self, file):
250 + if file and self.allowed_file(file.filename):
251 + filename = secure_filename(file.filename)
252 + file.save(os.path.join(UPLOAD_FOLDER, filename))
253 + connector = self.db.session.query(Connectors).filter_by(connector_name="Velociraptor").first()
254 + # Write location to `connectors` table
255 + connector.connector_api_key = os.path.join(UPLOAD_FOLDER, filename)
256 + self.db.session.commit()
257 + return {"message": "File successfully uploaded", "success": True}
258 + else:
259 + return {"message": "File type not allowed", "success": False}, 400
backend/app/static/swagger.json
+42
@@ -354,6 +354,48 @@
354 }
355 }
356 },
357 + "/connectors/upload": {
358 + "post": {
359 + "tags": ["Connectors"],
360 + "summary": "Upload a file",
361 + "description": "Endpoint to upload a file to the server.",
362 + "requestBody": {
363 + "content": {
364 + "multipart/form-data": {
365 + "schema": {
366 + "type": "object",
367 + "properties": {
368 + "file": {
369 + "type": "string",
370 + "format": "binary"
371 + }
372 + }
373 + }
374 + }
375 + }
376 + },
377 + "responses": {
378 + "200": {
379 + "description": "A JSON response containing the details of the uploaded file.",
380 + "content": {
381 + "application/json": {
382 + "schema": {
383 + "type": "object",
384 + "properties": {
385 + "message": {
386 + "type": "string"
387 + },
388 + "success": {
389 + "type": "boolean"
390 + }
391 + }
392 + }
393 + }
394 + }
395 + }
396 + }
397 + }
398 + },
399 "/customers/create": {
400 "post": {
401 "tags": ["Customers"],