async def clear_tasks_for_callback_func(data, cid, user): try: query = await db_model.callback_query() callback = await db_objects.get(query, id=cid) query = await db_model.operation_query() operation = await db_objects.get(query, id=callback.operation) tasks_removed = [] if "all" == data['task']: query = await db_model.task_query() tasks = await db_objects.prefetch(query.where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp), Command.select()) elif len(data['task']) > 0: # if the user specifies a task, make sure that it's not being processed or already done query = await db_model.task_query() tasks = await db_objects.prefetch(query.where( (Task.id == data['task']) & (Task.status == "submitted")), Command.select()) else: # if you don't actually specify a task, remove the the last task that was entered query = await db_model.task_query() tasks = await db_objects.prefetch(query.where( (Task.status == "submitted") & (Task.callback == callback) ).order_by(-Task.timestamp).limit(1), Command.select()) for t in list(tasks): if operation.name in user['operations']: try: t_removed = t.to_json() # don't actually delete it, just mark it as completed with a response of "CLEARED TASK" t.status = "processed" t.timestamp = datetime.utcnow() await db_objects.update(t) # we need to adjust all of the things associated with this task now since it didn't actually happen # find/remove ATTACKTask, TaskArtifact, FileMeta query = await db_model.attacktask_query() attack_tasks = await db_objects.execute(query.where(ATTACKTask.task == t)) for at in attack_tasks: await db_objects.delete(at, recursive=True) query = await db_model.taskartifact_query() task_artifacts = await db_objects.execute(query.where(TaskArtifact.task == t)) for ta in task_artifacts: await db_objects.delete(ta, recursive=True) query = await db_model.filemeta_query() file_metas = await db_objects.execute(query.where(FileMeta.task == t)) for fm in file_metas: os.remove(fm.path) await db_objects.delete(fm, recursive=True) # now create the response so it's easy to track what happened with it response = "CLEARED TASK by " + user['username'] await db_objects.create(Response, task=t, response=response) tasks_removed.append(t_removed) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return {'status': 'error', 'error': 'failed to delete task: ' + t.command.cmd} return {'status': 'success', 'tasks_removed': tasks_removed} except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return {'status': 'error', 'error': 'failed to set up for removing tasks'}
async def get_all_commands(request, user): all_commands = [] commands = await db_objects.execute(Command.select().order_by(Command.id)) for cmd in commands: params = await db_objects.execute(CommandParameters.select().where(CommandParameters.command == cmd).order_by(CommandParameters.id)) all_commands.append({**cmd.to_json(), "params": [p.to_json() for p in params]}) return json(all_commands)
async def get_all_tasks_by_callback_in_current_operation(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) except Exception as e: return json({'status': 'error', 'error': 'Not part of an operation'}) output = [] query = await db_model.callback_query() callbacks = await db_objects.execute( query.where(Callback.operation == operation).order_by(Callback.id)) for callback in callbacks: c = callback.to_json( ) # hold this callback, task, and response info to push to our output stack c['tasks'] = [] query = await db_model.task_query() tasks = await db_objects.prefetch( query.where(Task.callback == callback).order_by(Task.id), Command.select()) for t in tasks: t_data = t.to_json() t_data['responses'] = [] query = await db_model.response_query() responses = await db_objects.execute( query.where(Response.task == t).order_by(Response.id)) for r in responses: t_data['responses'].append(r.to_json()) c['tasks'].append(t_data) output.append(c) return json({'status': 'success', 'output': output})
async def get_all_tasks_for_callback(request, cid, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.callback_query() callback = await db_objects.get(query, id=cid) query = await db_model.operation_query() operation = await db_objects.get(query, id=callback.operation) except Exception as e: return json({'status': 'error', 'error': 'Callback does not exist'}) if operation.name in user['operations']: try: query = await db_model.task_query() cb_task_data = await db_objects.prefetch( query.where(Task.callback == callback).order_by(Task.id), Command.select()) return json([c.to_json() for c in cb_task_data]) except Exception as e: return json({ 'status': 'error', 'error': 'No Tasks', 'msg': str(e) }) else: return json({ 'status': 'error', 'error': 'You must be part of the right operation to see this information' })
async def export_command_list(request, user, ptype): payload_type = unquote_plus(ptype) try: payload_ptype = await db_objects.get(PayloadType, ptype=payload_type) except Exception as e: print(e) return json({'status': 'error', 'error': 'unable to find that payload type'}) cmdlist = [] try: commands = await db_objects.execute(Command.select().where(Command.payload_type == payload_ptype)) for c in commands: cmd_json = c.to_json() del cmd_json['id'] del cmd_json['creation_time'] del cmd_json['operator'] del cmd_json['payload_type'] params = await db_objects.execute(CommandParameters.select().where(CommandParameters.command == c)) params_list = [] for p in params: p_json = p.to_json() del p_json['id'] del p_json['command'] del p_json['cmd'] del p_json['operator'] params_list.append(p_json) cmd_json['parameters'] = params_list cmdlist.append(cmd_json) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to get commands for that payload type'}) return json({"payload_types": [{"name": payload_type, "commands": cmdlist}]})
async def ws_commands(request, ws): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newcommand";') # BEFORE WE START GETTING NEW THINGS, UPDATE WITH ALL OF THE OLD DATA commands = await db_objects.execute(Command.select()) for c in commands: await ws.send(js.dumps(c.to_json())) await ws.send("") # now pull off any new payloads we got queued up while processing old data while True: try: msg = conn.notifies.get_nowait() id = (msg.payload) p = await db_objects.get(Command, id=id) await ws.send(js.dumps(p.to_json())) except asyncio.QueueEmpty as e: await asyncio.sleep(2) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: pool.close()
async def callbacks_get_all_tasking(request, user, id): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") # Get all of the tasks and responses so far for the specified agent try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.callback_query() callback = await db_objects.get(query, id=id, operation=operation) cb_json = callback.to_json() cb_json['tasks'] = [] query = await db_model.task_query() tasks = await db_objects.prefetch( query.where(Task.callback == callback).order_by(Task.id), Command.select()) for t in tasks: query = await db_model.response_query() responses = await db_objects.execute( query.where(Response.task == t).order_by(Response.id)) cb_json['tasks'].append({ **t.to_json(), "responses": [r.to_json() for r in responses] }) return json({'status': 'success', **cb_json}) except Exception as e: print(e) return json({'status': 'error', 'error': str(e)})
async def get_all_responses(request, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: responses = [] query = await db_model.operation_query() operation = await db_objects.get(query, name=user["current_operation"]) query = await db_model.callback_query() callbacks = await db_objects.execute( query.where(Callback.operation == operation)) for c in callbacks: query = await db_model.task_query() tasks = await db_objects.prefetch(query.where(Task.callback == c), Command.select()) for t in tasks: query = await db_model.response_query() task_responses = await db_objects.execute( query.where(Response.task == t)) responses += [r.to_json() for r in task_responses] except Exception as e: return json({ "status": "error", "error": "Cannot get responses: " + str(e) }) return json(responses)
async def list_all_screencaptures_per_callback(request, user, id): try: query = await db_model.callback_query() callback = await db_objects.get(query, id=id) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to find callback'}) screencapture_paths = [] if callback.operation.name in user['operations']: query = await db_model.filemeta_query() screencaptures = await db_objects.prefetch( query.where( FileMeta.path.regexp(".*{}/downloads/.*/screenshots/".format( callback.operation.name))), Task.select(), Command.select(), Callback.select()) for s in screencaptures: if s.task.callback == callback: screencapture_paths.append(s.to_json()) return json({ 'status': 'success', 'callback': callback.id, 'files': screencapture_paths }) else: return json({ 'status': 'error', 'error': 'must be part of that callback\'s operation to see its screenshots' })
async def get_all_tasks_for_callback(request, cid, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: query = await db_model.callback_query() callback = await db_objects.get(query, id=cid) query = await db_model.operation_query() operation = await db_objects.get(query, id=callback.operation) except Exception as e: return json({"status": "error", "error": "Callback does not exist"}) if operation.name in user["operations"]: try: query = await db_model.task_query() cb_task_data = await db_objects.prefetch( query.where(Task.callback == callback).order_by(Task.id), Command.select(), ) return json([c.to_json() for c in cb_task_data]) except Exception as e: return json({ "status": "error", "error": "No Tasks", "msg": str(e) }) else: return json({ "status": "error", "error": "You must be part of the right operation to see this information", })
async def remove_task_comment(request, tid, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") try: if user['view_mode'] == 'spectator': return json({ 'status': 'error', 'error': 'Spectators cannot remove comments on tasks' }) query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] query = await db_model.operator_query() operator = await db_objects.get(query, username=user['username']) if task.callback.operation.name in user['operations']: task.comment = "" task.comment_operator = operator await db_objects.update(task) return json({'status': "success", "task": task.to_json()}) else: return json({ 'status': 'error', 'error': 'you don\'t have access to that task' }) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({'status': 'error', 'error': 'failed to find that task'})
async def get_all_tasks(request, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) query = await db_model.task_query() full_task_data = await db_objects.prefetch(query, Command.select()) if user["admin"]: # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) return json([c.to_json() for c in full_task_data]) elif user["current_operation"] != "": query = await db_model.operation_query() operation = await db_objects.get(query, name=user["current_operation"]) return json([ c.to_json() for c in full_task_data if c.callback.operation == operation ]) else: return json({ "status": "error", "error": "must be admin to see all tasks or part of a current operation", })
async def get_all_not_completed_tasks_for_callback_func(cid, user): try: query = await db_model.callback_query() callback = await db_objects.get(query, id=cid) query = await db_model.operation_query() operation = await db_objects.get(query, id=callback.operation) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return { "status": "error", "error": "failed to get callback or operation" } if operation.name in user["operations"]: # Get all tasks that have a status of submitted or processing query = await db_model.task_query() tasks = await db_objects.prefetch( query.where((Task.callback == callback) & (Task.completed != True)).order_by(Task.timestamp), Command.select(), ) return {"status": "success", "tasks": [x.to_json() for x in tasks]} else: return { "status": "error", "error": "You must be part of the operation to view this information", }
async def remove_task_comment(request, tid, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: if user["view_mode"] == "spectator": return json({ "status": "error", "error": "Spectators cannot remove comments on tasks", }) query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] query = await db_model.operator_query() operator = await db_objects.get(query, username=user["username"]) if task.callback.operation.name in user["operations"]: task.comment = "" task.comment_operator = operator await db_objects.update(task) await log_to_siem(task.to_json(), mythic_object="task_comment") return json({"status": "success", "task": task.to_json()}) else: return json({ "status": "error", "error": "you don't have access to that task" }) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({"status": "error", "error": "failed to find that task"})
async def list_all_screencaptures_per_operation(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") if user['current_operation'] != "": query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() screencaptures = await db_objects.prefetch( query.where( FileMeta.path.regexp(".*{}/downloads/.*/screenshots/".format( operation.name))), Task.select(), Command.select(), Callback.select()) screencapture_paths = [] for s in screencaptures: screencapture_paths.append(s.to_json()) return json({'status': 'success', 'files': screencapture_paths}) else: return json({ "status": 'error', 'error': 'must be part of a current operation to see an operation\'s screencaptures' })
async def get_all_files_meta(request, user): try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if f.operation.name in user['operations']])
async def get_all_files_meta(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message="Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json([f.to_json() for f in files if f.operation.name in user['operations']])
async def create_filemeta_in_database_func(data): # create a filemeta object where we will then start uploading our file # expects total_chunks, and task if 'total_chunks' not in data: return {'status': 'error', 'error': 'total_chunks required'} try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == data['task']), Command.select()) task = list(task)[0] query = await db_model.callback_query() callback = await db_objects.get(query.where(Callback.id == task.callback)) operation = callback.operation except Exception as e: print("{} {}".format(str(sys.exc_info()[-1].tb_lineno), str(e))) return {'status': 'error', 'error': "failed to find task"} try: filename = os.path.split(task.params)[1].strip() if task.command.cmd == "screencapture": # we want to save these in a specific folder save_path = os.path.abspath( './app/files/{}/downloads/{}/{}/{}'.format(operation.name, callback.host, "screenshots", filename)) else: save_path = os.path.abspath('./app/files/{}/downloads/{}/{}'.format(operation.name, callback.host, filename)) extension = filename.split(".")[-1] if "." in filename else "" save_path = save_path[:((len(extension)+1)*-1)] if extension != "" else save_path count = 1 if "." in filename: tmp_path = save_path + "." + str(extension) else: tmp_path = save_path while os.path.exists(tmp_path): if "." in filename: tmp_path = save_path + str(count) + "." + str(extension) else: tmp_path = save_path + str(count) count += 1 save_path = tmp_path if not os.path.exists(os.path.split(save_path)[0]): os.makedirs(os.path.split(save_path)[0]) open(save_path, 'a').close() if "full_path" not in data: data['full_path'] = "" filemeta = await db_objects.create(FileMeta, total_chunks=data['total_chunks'], task=task, operation=operation, path=save_path, operator=task.operator, full_remote_path=data['full_path'], temp_file=False) if data['total_chunks'] == 0: filemeta.complete = True contents = open(filemeta.path, 'rb').read() filemeta.md5 = await hash_MD5(contents) filemeta.sha1 = await hash_SHA1(contents) await db_objects.update(filemeta) except Exception as e: print("{} {}".format(str(sys.exc_info()[-1].tb_lineno), str(e))) return {'status': 'error', 'error': "failed to create file"} status = {'status': 'success'} return {**status, **filemeta.to_json()}
async def get_all_tasks(request, user): query = await db_model.task_query() full_task_data = await db_objects.prefetch(query, Command.select()) if user['admin']: # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) return json([c.to_json() for c in full_task_data]) elif user['current_operation'] != "": query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) return json([c.to_json() for c in full_task_data if c.callback.operation == operation]) else: return json({'status': 'error', 'error': 'must be admin to see all tasks or part of a current operation'})
async def get_commands_for_payloadtype(request, user, ptype): payload_type = unquote_plus(ptype) try: payloadtype = await db_objects.get(PayloadType, ptype=payload_type) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to get payload type'}) commands = await db_objects.execute(Command.select().where(Command.payload_type == payloadtype).order_by(Command.cmd)) all_commands = [] for cmd in commands: params = await db_objects.execute(CommandParameters.select().where(CommandParameters.command == cmd)) all_commands.append({**cmd.to_json(), "params": [p.to_json() for p in params]}) status = {'status': 'success'} return json({**status, 'commands': all_commands})
async def get_all_files_meta(request, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({"status": "error", "error": "failed to get files"}) return json( [f.to_json() for f in files if f.operation.name in user["operations"]])
async def get_one_task_and_responses(request, tid, user): try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] if task.callback.operation.name in user['operations']: query = await db_model.response_query() responses = await db_objects.execute(query.where(Response.task == task).order_by(Response.id)) query = await db_model.callback_query() callback = await db_objects.get(query.where(Callback.id == task.callback)) return json({'status': "success", "callback": callback.to_json(), "task": task.to_json(), "responses": [r.to_json() for r in responses]}) else: return json({'status': 'error', 'error': 'you don\'t have access to that task'}) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({'status': 'error', 'error': 'failed to find that task'})
async def get_one_task_and_responses(request, tid, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({ "status": "error", "error": "failed to find that task: " + str(tid) }) try: if task.callback.operation.name in user["operations"]: query = await db_model.response_query() responses = await db_objects.execute( query.where(Response.task == task).order_by(Response.id)) query = await db_model.callback_query() callback = await db_objects.get( query.where(Callback.id == task.callback)) return json({ "status": "success", "callback": callback.to_json(), "task": task.to_json(), "responses": [r.to_json() for r in responses], }) else: return json({ "status": "error", "error": "you don't have access to that task" }) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({ "status": "error", "error": "Failed to fetch task: " + str(sys.exc_info()[-1].tb_lineno) + " " + str(e), })
async def remove_task_comment(request, tid, user): try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] query = await db_model.operator_query() operator = await db_objects.get(query, username=user['username']) if task.callback.operation.name in user['operations']: task.comment = "" task.comment_operator = operator await db_objects.update(task) return json({'status': "success", "task": task.to_json()}) else: return json({'status': 'error', 'error': 'you don\'t have access to that task'}) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({'status': 'error', 'error': 'failed to find that task'})
async def get_all_responses(request, user): try: responses = [] query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.callback_query() callbacks = await db_objects.execute(query.where(Callback.operation == operation)) for c in callbacks: query = await db_model.task_query() tasks = await db_objects.prefetch(query.where(Task.callback == c), Command.select()) for t in tasks: query = await db_model.response_query() task_responses = await db_objects.execute(query.where(Response.task == t)) responses += [r.to_json() for r in task_responses] except Exception as e: return json({'status': 'error', 'error': 'Cannot get responses: ' + str(e)}) return json(responses)
async def get_current_operations_files_meta(request, user): if user['current_operation'] != "": try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() files = await db_objects.prefetch( query.where(FileMeta.operation == operation), Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if not "screenshots" in f.path]) else: return json({ "status": 'error', 'error': 'must be part of an active operation' })
async def get_one_task_and_responses_as_raw_output(request, tid, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] if task.callback.operation.name in user["operations"]: query = await db_model.response_query() responses = await db_objects.execute( query.where(Response.task == task).order_by(Response.id)) output = "".join([ bytes(r.response).decode( "unicode-escape", errors="backslashreplace").encode( "utf-8", errors="backslashreplace").decode() for r in responses ]) return json({ "status": "success", "output": base64.b64encode(output.encode()).decode("utf-8"), }) else: return json({ "status": "error", "error": "you don't have access to that task" }) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({ "status": "error", "error": "failed to find that task {}".format( str(sys.exc_info()[-1].tb_lineno) + " " + str(e)), })
async def get_one_task_and_responses_as_raw_output(request, tid, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.task_query() task = await db_objects.prefetch(query.where(Task.id == tid), Command.select()) task = list(task)[0] if task.callback.operation.name in user['operations']: query = await db_model.response_query() responses = await db_objects.execute( query.where(Response.task == task).order_by(Response.id)) output = ''.join([ bytes(r.response).decode( 'unicode-escape', errors='backslashreplace').encode( 'utf-8', errors="backslashreplace").decode() for r in responses ]) return json({ 'status': 'success', 'output': base64.b64encode(output.encode()).decode('utf-8') }) else: return json({ 'status': 'error', 'error': 'you don\'t have access to that task' }) except Exception as e: print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) return json({ 'status': 'error', 'error': 'failed to find that task {}'.format( str(sys.exc_info()[-1].tb_lineno) + " " + str(e)) })
async def get_current_operations_files_meta(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") if user['current_operation'] != "": try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() files = await db_objects.prefetch( query.where(FileMeta.operation == operation), Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if not "screenshots" in f.path]) else: return json({ "status": 'error', 'error': 'must be part of an active operation' })
async def search_comments_by_callback_in_current_operation(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message="Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.operator_query() operator = await db_objects.get(query, username=user['username']) query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) data = request.json if 'search' not in data: return json({'status': 'error', 'error': 'search is required'}) except Exception as e: return json({'status': 'error', 'error': 'failed to find operator or operation: ' + str(e)}) query = await db_model.task_query() tasks = await db_objects.prefetch(query.where(Task.comment.contains(data['search'])).where(Callback.operation == operation).order_by(Task.id), Command.select()) callbacks = {} for t in tasks: query = await db_model.response_query() responses = await db_objects.execute(query.where(Response.task == t)) if t.callback.id not in callbacks: query = await db_model.callback_query() cback = await db_objects.get(query.where(Callback.id == t.callback)) callbacks[t.callback.id] = cback.to_json() callbacks[t.callback.id]['tasks'] = [] callbacks[t.callback.id]['tasks'].append({**t.to_json(), "responses": [r.to_json() for r in responses]}) return json({'status': 'success', 'callbacks': list(callbacks.values())})