def get(self): # perhaps don't document this because it's only used by the web GUI """ Get current user info --- tags: [util] responses: 200: description: user type: object properties: is_authenticated: type: string example: true is_active: type: string example: true is_anonymous: type: string example: false is_admin: type: string example: false username: type: string example: [email protected] """ user = getAuthData() return user
def get(self): # perhaps don't document this because it's only used by the web GUI """ Get current user info --- tags: [users] responses: 200: description: user content: application/json: schema: type: object properties: is_authenticated: type: string example: true is_active: type: string example: true is_anonymous: type: string example: false is_admin: type: string example: false username: type: string example: [email protected] """ user = getAuthData() return user
def get(self, qa_id): """ Get answerset --- tags: [answer] parameters: - in: path name: qa_id description: "<question_id>_<answerset_id>" type: string required: true responses: 200: description: "answerset data" type: object properties: answerset: schema: $ref: '#/definitions/Response' user: type: object question: type: object other_questions: type: array items: type: object other_answersets: type: array items: type: object feedback: type: array items: type: object 404: description: "invalid answerset id" type: string """ try: question_id, answerset_id = qa_id.split('_') question = get_question_by_id(question_id) answerset = get_answerset_by_id(answerset_id) answersets = question.answersets if not answerset in answersets: raise AssertionError() except Exception as err: return "Invalid answerset key.", 404 user = getAuthData() feedback = list_feedback_by_question_answerset(question, answerset) return {'question': question.toJSON(),\ 'answerset': answerset.toStandard(),\ 'feedback': [f.toJSON() for f in feedback],\ 'other_answersets': [], 'other_questions': []}, 200
def delete(self, question_id): """ Delete question --- tags: [questions] parameters: - in: path name: question_id description: "question id" schema: type: string required: true responses: 200: description: "question deleted" content: text/plain: schema: type: string 401: description: "unauthorized" content: text/plain: schema: type: string 404: description: "invalid question key" content: text/plain: schema: type: string """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) user_id = user['id'] else: user = getAuthData() user_id = user['id'] user_email = user['email'] try: question = get_question_by_id(question_id) except Exception as err: return "Invalid question id.", 404 if not (user_email == question['owner_email'] or user['is_admin']): return "UNAUTHORIZED", 401 # not authorized # User is authoriced logger.info('Deleting question %s at the request of %s', question_id, user_email) delete_question_by_id(question_id) return "SUCCESS", 200
def post(self, question_id): """ Refresh KG for question --- tags: [questions] parameters: - in: path name: question_id description: "question id" schema: type: string required: true responses: 202: description: "refreshing in progress" content: text/plain: schema: type: string 404: description: "invalid question key" content: text/plain: schema: type: string """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) user_id = user['id'] else: user = getAuthData() user_id = user['id'] user_email = user['email'] # Update the knowledge graph for a question logger.info( f'Adding update task for question {question_id} for user {user_email} to the queue' ) task = update_kg.apply_async(args=[question_id], kwargs={'user_email': user_email}) logger.info( f'Update task for question {question_id} for user {user_email} to the queue has recieved task_id {task.id}' ) return {'task_id': task.id}, 202
def post(self, question_id): """ Edit question metadata --- tags: [questions] parameters: - in: path name: question_id description: "question id" schema: type: string required: true requestBody: description: request body content: application/json: schema: type: object required: - name - natural_question - notes properties: name: description: "name of question" schema: type: string natural_question: description: "natural-language question" schema: type: string notes: description: "notes" schema: type: string responses: 200: description: "question edited" content: text/plain: schema: type: string 401: description: "unauthorized" content: text/plain: schema: type: string 404: description: "invalid question key" content: text/plain: schema: type: string """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) user_id = user['id'] else: user = getAuthData() user_id = user['id'] user_email = user['email'] try: question = get_question_by_id(question_id) except Exception as err: return "Invalid question id.", 404 if not (user_email == question['owner_email'] or user['is_admin']): return "UNAUTHORIZED", 401 # not authorized # User is authorized logger.info('Editing question %s at the request of %s', question_id, user_email) mods = {} if 'notes' in request.json: mods['notes'] = request.json['notes'] if 'natural_question' in request.json: mods['natural_question'] = request.json['natural_question'] modify_question_by_id(question_id, mods) return "SUCCESS", 200
def post(self, question_id): """ Set Question Visiblity. --- tags: [questions] parameters: - in: path name: question_id description: "question id" schema: type: string required: true - in: query name: visibility description: "question visibility" required: true schema: type: string enum: - private - public - promoted default: private example: private responses: 200: description: "question visibility edited" content: text/plain: schema: type: string 401: description: "unauthorized" content: text/plain: schema: type: string 404: description: "invalid question key" content: text/plain: schema: type: string """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) user_id = user['id'] else: user = getAuthData() user_id = user['id'] user_email = user['email'] try: question = get_question_by_id(question_id) except Exception as err: return "Invalid question id.", 404 visibility = request.args.get('visibility', default='private') if 'roles' in user: user_is_admin = any(role['name'] == 'admin' for role in user['roles']) else: user_is_admin = user['is_admin'] if not (user_email == question['owner_email'] or user_is_admin): return "UNAUTHORIZED", 401 # not authorized if visibility == 'promoted' and not user_is_admin: return "UNAUTHORIZED", 401 # User is authorized mods = { 'visibility': visibility } modify_question_by_id(question_id, mods) return "SUCCESS", 200
def post(self): """ Create a question. --- tags: [questions] requestBody: name: question content: application/json: schema: $ref: '#/components/schemas/Question' required: true responses: 201: description: "question id" content: text/plain: schema: type: string """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) user_id = user['id'] else: user = getAuthData() user_id = user['id'] user_email = user['email'] logger.debug(f"Creating new question for user {user_email}.") request_json = request.json if 'question_graph' not in request_json: request_json['question_graph'] = request_json.pop( 'machine_question', None) question_id = add_question(request.json, owner_id=user_id) if request.headers.get('RebuildCache', default='true') == 'true': # To speed things along we start an answerset generation task for this question # This isn't the standard answerset generation task because we might also trigger a KG Update logger.info( f'Adding update and answer tasks for question {question_id} for user {user_email} to the queue' ) ug_task = update_kg.signature(args=[question_id], kwargs={'user_email': user_email}, immutable=True) as_task = answer_question.signature( args=[question_id], kwargs={'user_email': user_email}, immutable=True) task = answer_question.apply_async( args=[question_id], kwargs={'user_email': user_email}, link_error=ug_task | as_task) logger.info( f'Update task for question {question_id} for user {user_email} to the queue has recieved task_id {task.id}' ) elif request.headers.get('AnswerNow', default='true') == 'true': logger.info( f'Adding answer task for question {question_id} for user {user_email} to the queue' ) task = answer_question.apply_async( args=[question_id], kwargs={'user_email': user_email}) logger.info( f'Answer task for question {question_id} for user {user_email} to the queue has recieved task_id {task.id}' ) return question_id, 201
def get(self, qa_id, answer_id): """ Get answer --- tags: [answer] parameters: - in: path name: qa_id description: "<question_id>_<answerset_id>" type: string required: true - in: path name: answer_id description: "answer/result id" type: string required: true responses: 200: description: "answer data" type: object properties: answer: schema: $ref: '#/definitions/Result' answerset: schema: $ref: '#/definitions/Response' user: type: object question: type: object other_questions: type: array items: type: object other_answersets: type: array items: type: object feedback: type: array items: type: object 404: description: "invalid answerset/answer id" type: string """ try: question_id, answerset_id = qa_id.split('_') question = get_question_by_id(question_id) answerset = get_answerset_by_id(answerset_id) answersets = question.answersets if not answerset in answersets: raise AssertionError() answer = get_answer_by_id(answer_id) if not answer in answerset.answers: raise AssertionError() except Exception as err: return "Invalid answerset or answer key.", 404 questions = answerset.questions idx = questions.index(question) questions.pop(idx) idx = answersets.index(answerset) answersets.pop(idx) feedback = list_feedback_by_question_answer(question, answer) user = getAuthData() return {'user': user,\ 'answerset': answerset.toJSON(),\ 'answer': answer.toJSON(),\ 'feedback': [f.toJSON() for f in feedback],\ 'question': question.toJSON(),\ 'other_answersets': [aset.toJSON() for aset in answersets], 'other_questions': [q.toJSON() for q in questions]}, 200
def get(self): """ Get list of questions --- tags: [question] responses: 200: description: list of questions schema: type: "array" items: $ref: '#/definitions/Question' """ user = getAuthData() question_list = list_questions() # user_question_list = list_questions_by_username(user['username']) # nonuser_question_list = list_questions_by_username(user['username'], invert=True) tasks = get_tasks().values() # filter out the SUCCESS/FAILURE tasks tasks = [ t for t in tasks if not (t['state'] == 'SUCCESS' or t['state'] == 'FAILURE' or t['state'] == 'REVOKED') ] # get question hashes question_tasks = {q.id: [] for q in question_list} for t in tasks: if not t['args']: continue match = re.match(r"[\[(]'(.*)',?[)\]]", t['args']) if not match: continue question_id = match.group(1) question_tasks[question_id].append(t) # split into answer and update tasks for t in tasks: t['type'] = 'answering' if t['name'] == 'manager.tasks.answer_question' else \ 'refreshing KG' if t['name'] == 'manager.tasks.update_kg' else \ 'something?' def augment_info(question): answerset_timestamps = [a.timestamp for a in question.answersets] if answerset_timestamps: latest_idx = answerset_timestamps.index( max(answerset_timestamps)) latest_answerset_id = question.answersets[latest_idx].id latest_answerset_timestamp = question.answersets[ latest_idx].timestamp else: latest_answerset_id = None latest_answerset_timestamp = None q = question.toJSON() q['user_email'] = question.user.email q.pop('user_id') q.pop('machine_question') return { 'latest_answerset_id': latest_answerset_id, 'latest_answerset_timestamp': latest_answerset_timestamp.isoformat() if latest_answerset_timestamp else None, 'tasks': [t['type'] for t in question_tasks[question.id]], **q } return [augment_info(q) for q in question_list], 200