Loading README.md +29 −29 Original line number Diff line number Diff line Loading @@ -4,12 +4,12 @@ Fablab 3d printing request application ## Minimum Viable Version - [ ] *Tests* - [ ] _Tests_ - [x] User Connection - [ ] User administration - [ ] Backend - [ ] List users, - [ ] Change access level - [x] User administration - [x] Backend - [x] List users, - [x] Change access level - [x] Submit a print request - [x] Upload a STL file - [x] Backend Loading back/myfab/api.py +205 −122 Original line number Diff line number Diff line import myfab.log as log from flask import Flask, request from flask_jwt_extended import ( JWTManager, jwt_required, create_refresh_token, get_raw_jwt, current_user JWTManager, jwt_required, create_refresh_token, get_raw_jwt, current_user, ) import datetime from myfab.model import Event, PrintRequest, User, init_db_connection, Queue, QueueElement from myfab.model import ( Event, PrintRequest, User, init_db_connection, Queue, QueueElement, ) from flask_api import status from flask import jsonify import string Loading @@ -20,17 +30,21 @@ log.info("Database connected") app = Flask(__name__) CORS(app) app.debug = True app.config['SECRET_KEY'] = 'super-secret' #! CHANGEME app.config['JWT_IDENTITY_CLAIM'] = "login_name" app.config["SECRET_KEY"] = "super-secret" #! CHANGEME app.config["JWT_IDENTITY_CLAIM"] = "login_name" FILE_SAVE_PATH = "../ui/static/files" jwt = JWTManager(app) @jwt.user_loader_callback_loader def identity(payload): payload = get_raw_jwt() return get_or_create_user(payload['login_name'], payload['firstname'] + ' '+ payload['lastname']) return get_or_create_user( payload["login_name"], payload["firstname"] + " " + payload["lastname"] ) ### ENUMS ### Loading Loading @@ -60,13 +74,14 @@ REQUEST_USER_ELEMENTS = set(["title","description","project"]) # region UTILS def get_or_create_user(username: str, fullname: str = None): req = User.select().where(User.username == username) if(req.count()): if req.count(): return req.get() else: if not fullname: raise Exception("fullname cannot be None") return User.create(username=username, fullname=fullname) def lookup_requests(author: str = None, status=None, req_id=None): where_req = [] if author: Loading @@ -84,28 +99,38 @@ def lookup_requests(author: str = None, status = None, req_id = None): if req_id: where_req.append(PrintRequest.id == req_id) req = PrintRequest.select().join(User, on=(PrintRequest.author == User.username)).limit(30) # .join(Queue, on=(PrintRequest.queue == Queue.id)) req = ( PrintRequest.select() .join(User, on=(PrintRequest.author == User.username)) .limit(30) ) # .join(Queue, on=(PrintRequest.queue == Queue.id)) if len(where_req) > 0: req = req.where(*where_req) req = req.order_by(PrintRequest.last_modification.desc()) return req def get_request_by_id(rid): req = PrintRequest.select().where(PrintRequest.id == rid) return req.get() if req.count() else None def add_request_event(req: PrintRequest, desc: str, op: User = None): log.info("Req %s: %s" % (req.id, desc)) req.last_modification = datetime.datetime.now() req.save() Event.create(request=req, description=desc, operator=op) def extract_date_time(elem): if type(elem) == tuple: elem = elem[0] # elem = datetime.datetime.fromisoformat(repr(elem)) return f'{elem.day}/{elem.month}/{elem.year} {elem.hour}:{elem.minute}:{elem.second}' return ( f"{elem.day}/{elem.month}/{elem.year} {elem.hour}:{elem.minute}:{elem.second}" ) def loop_requests(reqs): rqs = [] Loading @@ -114,7 +139,8 @@ def loop_requests(reqs): for req in reqs: if get_access_level_to_request(req, current_user) == REQUEST_ACCESS_DENIED: continue rqs.append({ rqs.append( { "request_id": req.id, "title": req.title, "creation": extract_date_time(req.creation), Loading @@ -128,10 +154,12 @@ def loop_requests(reqs): "gcode": req.gcode, "operator": req.operator.username if req.operator is not None else "", "queue": req.queue.name if req.queue is not None else "", "recup": req.recup_id }) "recup": req.recup_id, } ) return rqs def get_access_level_to_request(req: PrintRequest, user): # req is id or req same for user # TODO Loading @@ -152,28 +180,39 @@ def get_access_level_to_request(req: PrintRequest, user): else: return REQUEST_ACCESS_DENIED # user does not have access def update_requires_operator_rights(update_json): s = set(update_json) s.discard(REQUEST_USER_ELEMENTS) return len(s) > 0 # endregion UTILS # region routes # region Project management & basic routes @app.route("/whoami") @jwt_required def whoami(): return jsonify({'username': current_user.username, 'fullname': current_user.fullname, 'access': current_user.access}) return jsonify( { "username": current_user.username, "fullname": current_user.fullname, "access": current_user.access, } ) @app.route("/requests/my") @jwt_required def get_my_requests(): return jsonify(loop_requests(lookup_requests(current_user.username))) @app.route("/requests/<req_id>", methods=['PUT']) @app.route("/requests/<req_id>", methods=["PUT"]) @jwt_required def update_request(req_id): # Author can update request initial parameters when status is 0 Loading @@ -183,14 +222,18 @@ def update_request(req_id): req: PrintRequest = get_request_by_id(req_id) changes = request.get_json() if not changes: return jsonify({'error': 'No modifications'}), status.HTTP_400_BAD_REQUEST return jsonify({"error": "No modifications"}), status.HTTP_400_BAD_REQUEST if req is None: return jsonify({'error': 'No such request'}), status.HTTP_404_NOT_FOUND return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND required_access = REQUEST_ACCESS_OPERATOR if req.status > 0 or update_requires_operator_rights(changes) else REQUEST_ACCESS_USER required_access = ( REQUEST_ACCESS_OPERATOR if req.status > 0 or update_requires_operator_rights(changes) else REQUEST_ACCESS_USER ) if get_access_level_to_request(req, current_user) < required_access: return jsonify({'error': 'Access denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED for e in changes: setattr(req, e, changes[e]) Loading @@ -198,46 +241,59 @@ def update_request(req_id): req.save() return jsonify({}) @app.route("/requests/new", methods=['POST']) @app.route("/requests/new", methods=["POST"]) @jwt_required def add_new_request(): data = request.get_json() if not 'title' in data or data['title'] == "": return jsonify({'error': 'Title field required'}), status.HTTP_404_NOT_FOUND if not 'description' in data or data['description'] == "": return jsonify({'error': 'Description field is required'}), status.HTTP_404_NOT_FOUND if not 'project' in data or data['project'] == "": return jsonify({'error': 'Project field is required'}), status.HTTP_404_NOT_FOUND req = PrintRequest.create(title = data['title'], description = data['description'], if not "title" in data or data["title"] == "": return jsonify({"error": "Title field required"}), status.HTTP_404_NOT_FOUND if not "description" in data or data["description"] == "": return ( jsonify({"error": "Description field is required"}), status.HTTP_404_NOT_FOUND, ) if not "project" in data or data["project"] == "": return ( jsonify({"error": "Project field is required"}), status.HTTP_404_NOT_FOUND, ) req = PrintRequest.create( title=data["title"], description=data["description"], author=current_user, project = data['project']) log.info("Created print request '%s' by user %s (%s)"%(req.title, current_user.username, current_user.fullname)) project=data["project"], ) log.info( "Created print request '%s' by user %s (%s)" % (req.title, current_user.username, current_user.fullname) ) add_request_event(req, "Request created") return jsonify({ "request_id": req.id }) return jsonify({"request_id": req.id}) @app.route("/files/<kind>/upload/<req_id>", methods=['POST']) @app.route("/files/<kind>/upload/<req_id>", methods=["POST"]) @jwt_required def stl_upload(kind, req_id): if not kind in ['stl', 'gcode']: return jsonify({'error': 'Invalid file kind'}, status.HTTP_400_BAD_REQUEST) if not kind in ["stl", "gcode"]: return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) req: PrintRequest = get_request_by_id(int(req_id)) if req == None: return jsonify({'error': 'No such print request'}, status.HTTP_404_NOT_FOUND) return jsonify({"error": "No such print request"}, status.HTTP_404_NOT_FOUND) required_access = REQUEST_ACCESS_USER if kind == "stl" else REQUEST_ACCESS_OPERATOR if get_access_level_to_request(req_id, current_user) < required_access: return jsonify({'error': 'Access denied'}, status.HTTP_401_UNAUTHORIZED) file = request.files['file'] if file.filename == '': return jsonify({'error': 'No file'}, status.HTTP_400_BAD_REQUEST) return jsonify({"error": "Access denied"}, status.HTTP_401_UNAUTHORIZED) file = request.files["file"] if file.filename == "": return jsonify({"error": "No file"}, status.HTTP_400_BAD_REQUEST) name = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(64)]) name = "".join( [random.choice(string.ascii_letters + string.digits) for n in range(64)] ) if kind == "stl": req.stl = name Loading @@ -245,28 +301,33 @@ def stl_upload(kind, req_id): req.gcode = name req.status = REQUEST_STATUS_AWAITING_PRINT else: return jsonify({'error': "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) file.save(os.path.join(FILE_SAVE_PATH, name)) req.save() add_request_event(req, f'Added {kind} file') add_request_event(req, f"Added {kind} file") return jsonify({"ok": True}) return jsonify({'ok': True}) @app.route("/requests/<req_id>") @jwt_required def get_request_infos(req_id): return jsonify(loop_requests(lookup_requests(req_id=req_id))) # ! FIXME Don't get request if no access return jsonify( loop_requests(lookup_requests(req_id=req_id)) ) # ! FIXME Don't get request if no access @app.route("/requests/list", methods=['POST']) @app.route("/requests/list", methods=["POST"]) @jwt_required def get_requests(): #! FIXME Don't get request if not access params = request.get_json() if not 'username' in params: params['username'] = None if not 'status' in params: params['status'] = None return jsonify(loop_requests(lookup_requests(params['username'], params['status']))) if not "username" in params: params["username"] = None if not "status" in params: params["status"] = None return jsonify(loop_requests(lookup_requests(params["username"], params["status"]))) # endregion Loading @@ -277,23 +338,26 @@ def get_requests(): #! FIXME Don't get request if not access @jwt_required def list_users(): if current_user.access != USER_ACCESS_OPERATOR: return jsonify({'error': 'Access denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED users = [] for user in User.select(): users.append({ 'username': user.username, 'fullname': user.fullname, 'access': user.access }) users.append( { "username": user.username, "fullname": user.fullname, "access": user.access, } ) return jsonify(users) # change user TODO @app.route("/users/<username>", methods=['PUT']) @app.route("/users/<username>", methods=["PUT"]) @jwt_required def update_user(username): if current_user.access != USER_ACCESS_OPERATOR: return jsonify({'error': 'Access Denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access Denied"}), status.HTTP_401_UNAUTHORIZED user = get_or_create_user(username) # FIXME no such user is 500 changes = request.get_json() Loading @@ -303,8 +367,25 @@ def update_user(username): user.save() return jsonify({}) # endregion user management # region Message system routes @app.route("/message/<request_id>") @jwt_required def get_messages(request_id): pass @app.route("/message/<request_id>", methods=["POST"]) @jwt_required def post_message(request_id): pass # endregion # region printer management routes TODO # list printers & status Loading @@ -328,6 +409,7 @@ def list_printers(): """ pass # action on printer TODO v2 @app.route("/printers/<printer_id>/action", methods=["POST"]) @jwt_required Loading @@ -340,12 +422,14 @@ def action_printer(printer_id): """ pass # Edit printer config @app.route("/printers/<printer_id>", methods=["PUT"]) @jwt_required def update_printer(printer_id): pass # Add printer config @app.route("/printers/new", methods=["POST"]) @jwt_required Loading Loading @@ -375,6 +459,7 @@ def list_queues(): """ pass # create queue # delete queue Loading Loading @@ -415,8 +500,6 @@ POST /slicer/usage # endregion routes # peewee usage # user = User.select().where(User.username == "test").count() Loading back/myfab/model.py +3 −2 Original line number Diff line number Diff line from peewee import Model, MySQLDatabase, AutoField, IntegerField, CharField, TextField, ForeignKeyField, DateTimeField, DoubleField from peewee import Model, MySQLDatabase, AutoField, IntegerField, CharField, TextField, ForeignKeyField, DateTimeField, DoubleField, BooleanField import datetime import sys, os import myfab.log as log Loading Loading @@ -39,6 +39,7 @@ class User(Model): class Queue(Model): id = AutoField(primary_key=True) enabled = BooleanField() name = CharField() weight = IntegerField(default=1) Loading Loading @@ -82,7 +83,7 @@ class Printer(Model): # with connection information name = CharField() model = CharField() config = CharField() # json current_print = ForeignKeyField(PrintRequest) current_print = ForeignKeyField(PrintRequest, null = True) class PrinterQueue(Model): printer = ForeignKeyField(Printer) Loading back/myfab/queue.py +11 −3 Original line number Diff line number Diff line Loading @@ -46,9 +46,17 @@ def get_queue_element_pos(queue_element: QueueElement): #region PRINTER UTILS & class def get_printers_from_db(): # for p in Printer.select(): # p.model pass printers = [] for p in Printer.select(): if p.model == "fake": # fake printer printers.append(FakePrinter(p)) elif p.model == "octoprint": # octo printer printers.append(OctoPrinter(p)) else: raise Exception("Unknown printer model") class PrinterBase: Loading Loading
README.md +29 −29 Original line number Diff line number Diff line Loading @@ -4,12 +4,12 @@ Fablab 3d printing request application ## Minimum Viable Version - [ ] *Tests* - [ ] _Tests_ - [x] User Connection - [ ] User administration - [ ] Backend - [ ] List users, - [ ] Change access level - [x] User administration - [x] Backend - [x] List users, - [x] Change access level - [x] Submit a print request - [x] Upload a STL file - [x] Backend Loading
back/myfab/api.py +205 −122 Original line number Diff line number Diff line import myfab.log as log from flask import Flask, request from flask_jwt_extended import ( JWTManager, jwt_required, create_refresh_token, get_raw_jwt, current_user JWTManager, jwt_required, create_refresh_token, get_raw_jwt, current_user, ) import datetime from myfab.model import Event, PrintRequest, User, init_db_connection, Queue, QueueElement from myfab.model import ( Event, PrintRequest, User, init_db_connection, Queue, QueueElement, ) from flask_api import status from flask import jsonify import string Loading @@ -20,17 +30,21 @@ log.info("Database connected") app = Flask(__name__) CORS(app) app.debug = True app.config['SECRET_KEY'] = 'super-secret' #! CHANGEME app.config['JWT_IDENTITY_CLAIM'] = "login_name" app.config["SECRET_KEY"] = "super-secret" #! CHANGEME app.config["JWT_IDENTITY_CLAIM"] = "login_name" FILE_SAVE_PATH = "../ui/static/files" jwt = JWTManager(app) @jwt.user_loader_callback_loader def identity(payload): payload = get_raw_jwt() return get_or_create_user(payload['login_name'], payload['firstname'] + ' '+ payload['lastname']) return get_or_create_user( payload["login_name"], payload["firstname"] + " " + payload["lastname"] ) ### ENUMS ### Loading Loading @@ -60,13 +74,14 @@ REQUEST_USER_ELEMENTS = set(["title","description","project"]) # region UTILS def get_or_create_user(username: str, fullname: str = None): req = User.select().where(User.username == username) if(req.count()): if req.count(): return req.get() else: if not fullname: raise Exception("fullname cannot be None") return User.create(username=username, fullname=fullname) def lookup_requests(author: str = None, status=None, req_id=None): where_req = [] if author: Loading @@ -84,28 +99,38 @@ def lookup_requests(author: str = None, status = None, req_id = None): if req_id: where_req.append(PrintRequest.id == req_id) req = PrintRequest.select().join(User, on=(PrintRequest.author == User.username)).limit(30) # .join(Queue, on=(PrintRequest.queue == Queue.id)) req = ( PrintRequest.select() .join(User, on=(PrintRequest.author == User.username)) .limit(30) ) # .join(Queue, on=(PrintRequest.queue == Queue.id)) if len(where_req) > 0: req = req.where(*where_req) req = req.order_by(PrintRequest.last_modification.desc()) return req def get_request_by_id(rid): req = PrintRequest.select().where(PrintRequest.id == rid) return req.get() if req.count() else None def add_request_event(req: PrintRequest, desc: str, op: User = None): log.info("Req %s: %s" % (req.id, desc)) req.last_modification = datetime.datetime.now() req.save() Event.create(request=req, description=desc, operator=op) def extract_date_time(elem): if type(elem) == tuple: elem = elem[0] # elem = datetime.datetime.fromisoformat(repr(elem)) return f'{elem.day}/{elem.month}/{elem.year} {elem.hour}:{elem.minute}:{elem.second}' return ( f"{elem.day}/{elem.month}/{elem.year} {elem.hour}:{elem.minute}:{elem.second}" ) def loop_requests(reqs): rqs = [] Loading @@ -114,7 +139,8 @@ def loop_requests(reqs): for req in reqs: if get_access_level_to_request(req, current_user) == REQUEST_ACCESS_DENIED: continue rqs.append({ rqs.append( { "request_id": req.id, "title": req.title, "creation": extract_date_time(req.creation), Loading @@ -128,10 +154,12 @@ def loop_requests(reqs): "gcode": req.gcode, "operator": req.operator.username if req.operator is not None else "", "queue": req.queue.name if req.queue is not None else "", "recup": req.recup_id }) "recup": req.recup_id, } ) return rqs def get_access_level_to_request(req: PrintRequest, user): # req is id or req same for user # TODO Loading @@ -152,28 +180,39 @@ def get_access_level_to_request(req: PrintRequest, user): else: return REQUEST_ACCESS_DENIED # user does not have access def update_requires_operator_rights(update_json): s = set(update_json) s.discard(REQUEST_USER_ELEMENTS) return len(s) > 0 # endregion UTILS # region routes # region Project management & basic routes @app.route("/whoami") @jwt_required def whoami(): return jsonify({'username': current_user.username, 'fullname': current_user.fullname, 'access': current_user.access}) return jsonify( { "username": current_user.username, "fullname": current_user.fullname, "access": current_user.access, } ) @app.route("/requests/my") @jwt_required def get_my_requests(): return jsonify(loop_requests(lookup_requests(current_user.username))) @app.route("/requests/<req_id>", methods=['PUT']) @app.route("/requests/<req_id>", methods=["PUT"]) @jwt_required def update_request(req_id): # Author can update request initial parameters when status is 0 Loading @@ -183,14 +222,18 @@ def update_request(req_id): req: PrintRequest = get_request_by_id(req_id) changes = request.get_json() if not changes: return jsonify({'error': 'No modifications'}), status.HTTP_400_BAD_REQUEST return jsonify({"error": "No modifications"}), status.HTTP_400_BAD_REQUEST if req is None: return jsonify({'error': 'No such request'}), status.HTTP_404_NOT_FOUND return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND required_access = REQUEST_ACCESS_OPERATOR if req.status > 0 or update_requires_operator_rights(changes) else REQUEST_ACCESS_USER required_access = ( REQUEST_ACCESS_OPERATOR if req.status > 0 or update_requires_operator_rights(changes) else REQUEST_ACCESS_USER ) if get_access_level_to_request(req, current_user) < required_access: return jsonify({'error': 'Access denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED for e in changes: setattr(req, e, changes[e]) Loading @@ -198,46 +241,59 @@ def update_request(req_id): req.save() return jsonify({}) @app.route("/requests/new", methods=['POST']) @app.route("/requests/new", methods=["POST"]) @jwt_required def add_new_request(): data = request.get_json() if not 'title' in data or data['title'] == "": return jsonify({'error': 'Title field required'}), status.HTTP_404_NOT_FOUND if not 'description' in data or data['description'] == "": return jsonify({'error': 'Description field is required'}), status.HTTP_404_NOT_FOUND if not 'project' in data or data['project'] == "": return jsonify({'error': 'Project field is required'}), status.HTTP_404_NOT_FOUND req = PrintRequest.create(title = data['title'], description = data['description'], if not "title" in data or data["title"] == "": return jsonify({"error": "Title field required"}), status.HTTP_404_NOT_FOUND if not "description" in data or data["description"] == "": return ( jsonify({"error": "Description field is required"}), status.HTTP_404_NOT_FOUND, ) if not "project" in data or data["project"] == "": return ( jsonify({"error": "Project field is required"}), status.HTTP_404_NOT_FOUND, ) req = PrintRequest.create( title=data["title"], description=data["description"], author=current_user, project = data['project']) log.info("Created print request '%s' by user %s (%s)"%(req.title, current_user.username, current_user.fullname)) project=data["project"], ) log.info( "Created print request '%s' by user %s (%s)" % (req.title, current_user.username, current_user.fullname) ) add_request_event(req, "Request created") return jsonify({ "request_id": req.id }) return jsonify({"request_id": req.id}) @app.route("/files/<kind>/upload/<req_id>", methods=['POST']) @app.route("/files/<kind>/upload/<req_id>", methods=["POST"]) @jwt_required def stl_upload(kind, req_id): if not kind in ['stl', 'gcode']: return jsonify({'error': 'Invalid file kind'}, status.HTTP_400_BAD_REQUEST) if not kind in ["stl", "gcode"]: return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) req: PrintRequest = get_request_by_id(int(req_id)) if req == None: return jsonify({'error': 'No such print request'}, status.HTTP_404_NOT_FOUND) return jsonify({"error": "No such print request"}, status.HTTP_404_NOT_FOUND) required_access = REQUEST_ACCESS_USER if kind == "stl" else REQUEST_ACCESS_OPERATOR if get_access_level_to_request(req_id, current_user) < required_access: return jsonify({'error': 'Access denied'}, status.HTTP_401_UNAUTHORIZED) file = request.files['file'] if file.filename == '': return jsonify({'error': 'No file'}, status.HTTP_400_BAD_REQUEST) return jsonify({"error": "Access denied"}, status.HTTP_401_UNAUTHORIZED) file = request.files["file"] if file.filename == "": return jsonify({"error": "No file"}, status.HTTP_400_BAD_REQUEST) name = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(64)]) name = "".join( [random.choice(string.ascii_letters + string.digits) for n in range(64)] ) if kind == "stl": req.stl = name Loading @@ -245,28 +301,33 @@ def stl_upload(kind, req_id): req.gcode = name req.status = REQUEST_STATUS_AWAITING_PRINT else: return jsonify({'error': "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST) file.save(os.path.join(FILE_SAVE_PATH, name)) req.save() add_request_event(req, f'Added {kind} file') add_request_event(req, f"Added {kind} file") return jsonify({"ok": True}) return jsonify({'ok': True}) @app.route("/requests/<req_id>") @jwt_required def get_request_infos(req_id): return jsonify(loop_requests(lookup_requests(req_id=req_id))) # ! FIXME Don't get request if no access return jsonify( loop_requests(lookup_requests(req_id=req_id)) ) # ! FIXME Don't get request if no access @app.route("/requests/list", methods=['POST']) @app.route("/requests/list", methods=["POST"]) @jwt_required def get_requests(): #! FIXME Don't get request if not access params = request.get_json() if not 'username' in params: params['username'] = None if not 'status' in params: params['status'] = None return jsonify(loop_requests(lookup_requests(params['username'], params['status']))) if not "username" in params: params["username"] = None if not "status" in params: params["status"] = None return jsonify(loop_requests(lookup_requests(params["username"], params["status"]))) # endregion Loading @@ -277,23 +338,26 @@ def get_requests(): #! FIXME Don't get request if not access @jwt_required def list_users(): if current_user.access != USER_ACCESS_OPERATOR: return jsonify({'error': 'Access denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED users = [] for user in User.select(): users.append({ 'username': user.username, 'fullname': user.fullname, 'access': user.access }) users.append( { "username": user.username, "fullname": user.fullname, "access": user.access, } ) return jsonify(users) # change user TODO @app.route("/users/<username>", methods=['PUT']) @app.route("/users/<username>", methods=["PUT"]) @jwt_required def update_user(username): if current_user.access != USER_ACCESS_OPERATOR: return jsonify({'error': 'Access Denied'}), status.HTTP_401_UNAUTHORIZED return jsonify({"error": "Access Denied"}), status.HTTP_401_UNAUTHORIZED user = get_or_create_user(username) # FIXME no such user is 500 changes = request.get_json() Loading @@ -303,8 +367,25 @@ def update_user(username): user.save() return jsonify({}) # endregion user management # region Message system routes @app.route("/message/<request_id>") @jwt_required def get_messages(request_id): pass @app.route("/message/<request_id>", methods=["POST"]) @jwt_required def post_message(request_id): pass # endregion # region printer management routes TODO # list printers & status Loading @@ -328,6 +409,7 @@ def list_printers(): """ pass # action on printer TODO v2 @app.route("/printers/<printer_id>/action", methods=["POST"]) @jwt_required Loading @@ -340,12 +422,14 @@ def action_printer(printer_id): """ pass # Edit printer config @app.route("/printers/<printer_id>", methods=["PUT"]) @jwt_required def update_printer(printer_id): pass # Add printer config @app.route("/printers/new", methods=["POST"]) @jwt_required Loading Loading @@ -375,6 +459,7 @@ def list_queues(): """ pass # create queue # delete queue Loading Loading @@ -415,8 +500,6 @@ POST /slicer/usage # endregion routes # peewee usage # user = User.select().where(User.username == "test").count() Loading
back/myfab/model.py +3 −2 Original line number Diff line number Diff line from peewee import Model, MySQLDatabase, AutoField, IntegerField, CharField, TextField, ForeignKeyField, DateTimeField, DoubleField from peewee import Model, MySQLDatabase, AutoField, IntegerField, CharField, TextField, ForeignKeyField, DateTimeField, DoubleField, BooleanField import datetime import sys, os import myfab.log as log Loading Loading @@ -39,6 +39,7 @@ class User(Model): class Queue(Model): id = AutoField(primary_key=True) enabled = BooleanField() name = CharField() weight = IntegerField(default=1) Loading Loading @@ -82,7 +83,7 @@ class Printer(Model): # with connection information name = CharField() model = CharField() config = CharField() # json current_print = ForeignKeyField(PrintRequest) current_print = ForeignKeyField(PrintRequest, null = True) class PrinterQueue(Model): printer = ForeignKeyField(Printer) Loading
back/myfab/queue.py +11 −3 Original line number Diff line number Diff line Loading @@ -46,9 +46,17 @@ def get_queue_element_pos(queue_element: QueueElement): #region PRINTER UTILS & class def get_printers_from_db(): # for p in Printer.select(): # p.model pass printers = [] for p in Printer.select(): if p.model == "fake": # fake printer printers.append(FakePrinter(p)) elif p.model == "octoprint": # octo printer printers.append(OctoPrinter(p)) else: raise Exception("Unknown printer model") class PrinterBase: Loading