def valid_conclusion(request): """ Given a conclusion id, query the object from the database and return it in the request. :param request: :return: """ conclusion_id = request.json_body.get('conclusion_id') issue = request.validated.get('issue') _tn = Translator(get_language_from_cookie(request)) if not issue: find_issue_in_request = issue_handler.get_issue_id(request) if find_issue_in_request: issue = DBDiscussionSession.query(Issue).get( issue_handler.get_issue_id(request)) else: add_error(request, 'Issue is missing', _tn.get(_.issueNotFound)) return False if conclusion_id and isinstance(conclusion_id, int): db_statement2issue = DBDiscussionSession.query( StatementToIssue).filter( StatementToIssue.issue_uid == issue.uid, StatementToIssue.statement_uid == conclusion_id).first() if db_statement2issue: db_conclusion = DBDiscussionSession.query(Statement).filter_by( uid=conclusion_id, is_disabled=False).first() if db_conclusion: request.validated['conclusion'] = db_conclusion return True add_error(request, 'Conclusion id is missing', _tn.get(_.conclusionIsMissing)) return False
def validate_credentials(request, **_kwargs) -> None: """ Parse credentials from POST request and validate it against DBA-S' database. :param request: :return: """ if request.errors: return secret = request.registry.settings['secret_key'] nickname = request.validated['nickname'] password = request.validated['password'] del request.validated['password'] # Check in DB-AS' database, if the user's credentials are valid logged_in = login_local_user(nickname, password, request.mailer) db_user: User = logged_in.get('user') if db_user: token = jwt.encode({ 'nickname': db_user.nickname, 'id': db_user.uid }, secret, algorithm='ES256') request.validated['nickname']: str = db_user.nickname request.validated['user']: User = db_user request.validated['token'] = token else: add_error(request, 'Could not login user', location="header", status_code=401)
def valid_premisegroups(request): """ Validates the correct build of premisegroups :param request: :return: """ premisegroups = request.json_body.get('premisegroups') if not premisegroups \ or not isinstance(premisegroups, list) \ or not all([isinstance(l, list) for l in premisegroups]): _tn = Translator(get_language_from_cookie(request)) add_error(request, 'Invalid conclusion id', _tn.get(_.requestFailed)) return False min_length = int(environ.get('MIN_LENGTH_OF_STATEMENT', 10)) for premisegroup in premisegroups: for premise in premisegroup: if isinstance(premise, str): if len(premise) < min_length: __set_min_length_error(request, min_length) return False else: add_error(request, 'At least one premise isn\'t a string!') return False request.validated['premisegroups'] = premisegroups return True
def valid_issue_by_slug(request: Request) -> bool: """ Query issue by slug from the path. :param request: :return: """ if has_keywords_in_path(('slug', str))(request): db_issue: Issue = DBDiscussionSession.query(Issue).filter( Issue.slug == request.validated['slug']).one_or_none() if db_issue: if db_issue.is_disabled: add_error(request, 'Issue no longer available', location='path', status_code=410) return False else: request.validated['issue'] = db_issue return True add_error(request, 'Invalid slug \'{}\' for issue'.format( request.validated['slug']), location='path', status_code=404) return False
def valid_api_token(request, **kwargs) -> bool: valid_token(request, **kwargs) if request.validated.get('auth-by-api-token', False): return True else: add_error(request, "This method is only allowed with an API-token!") return False
def __valid_id_from_location(request, entity_name, location='path') -> int: """ Find id in specified location. :param request: :param entity_name: :param location: :return: """ if location == 'path': success = has_keywords_in_path((entity_name, int))(request) return success elif location == 'json_body': if entity_name in request.json_body: value = request.json_body.get(entity_name) try: request.validated[entity_name] = int(value) return True except ValueError: add_error(request, '\'{}\' is not int parsable!'.format(value)) return False else: add_error(request, '{} is missing in json_body'.format(entity_name)) return False else: raise KeyError("location has to be one of: ('path', 'json_body')")
def validate_credentials(request, **_kwargs) -> None: """ Parse credentials from POST request and validate it against DBA-S' database. :param request: :return: """ if request.errors: return nickname = request.validated['nickname'] password = request.validated['password'] del request.validated['password'] # Check in DB-AS' database, if the user's credentials are valid logged_in = login_local_user(nickname, password, request.mailer) db_user: User = logged_in.get('user') if db_user: request.validated['nickname']: str = db_user.nickname request.validated['user']: User = db_user request.validated['token'] = get_api_token(request, db_user) else: add_error(request, 'Could not login user', location="header", status_code=401)
def valid_keywords(request: Request, **_kwargs): error_occured = False for (keyword, ktype) in keywords: value = request.matchdict.get(keyword) if value is not None and isinstance(value, ktype): request.validated[keyword] = value elif value is not None: if ktype in [int, float]: try: request.validated[keyword] = ktype(value) continue except ValueError: pass elif ktype is bool and value.lower() in ['true', 'false']: request.validated[keyword] = value.lower() == 'true' continue add_error( request, 'Parameter {} has wrong type'.format(keyword), '{} is {}, expected {}'.format(keyword, type(value), ktype)) error_occured = True else: add_error(request, 'Parameter {} is missing in path'.format(keyword)) error_occured = True return not error_occured
def empty(request): """ Returns 404 because no route is given :return: 404 """ add_error(request, 'Route not found', 'There was no route given')
def validate_credentials(request, **kwargs): """ Parse credentials from POST request and validate it against DBA-S' database. :param request: :return: """ if request.errors: return nickname = request.validated['nickname'] password = request.validated['password'] # Check in DB-AS' database, if the user's credentials are valid logged_in = login_user(nickname, password, request.mailer) db_user = logged_in.get('user') if db_user: token = __create_token(db_user.nickname) token_to_database(db_user, token) request.validated['nickname'] = db_user.nickname request.validated['user'] = db_user request.validated['token'] = token else: add_error(request, 'Could not login user', location="header", status_code=401)
def valid_new_issue(request): """ Verifies given data for a new issue :param request: :return: """ fn_validator = has_keywords_in_json_path(('title', str), ('info', str), ('long_info', str)) if not fn_validator(request): return False title = escape_if_string(request.validated, 'title') info = escape_if_string(request.validated, 'info') long_info = escape_if_string(request.validated, 'long_info') new_issue = __check_for_empty_fields(title=title, info=info, long_info=long_info, request=request) if new_issue.get('contains_empty_field'): add_error(request, 'There is an empty field', new_issue.get('error')) return False new_issue = __check_for_duplicated_field(title=title, info=info, long_info=long_info, request=request) if new_issue.get('contains_duplicated_field'): add_error(request, 'Issue data is a duplicate', new_issue.get('error')) return False return True
def __process_user_token(request, nickname, token): log.info("[API] Login Attempt from user {}".format(nickname)) db_user = get_user_by_case_insensitive_nickname(nickname) if not db_user.token or not db_user.token == token and not check_token(token): add_error(request, "Invalid token", status_code=401, location="header") return request.validated['user'] = db_user
def check_not_temporary_token(request) -> bool: payload = request.validated['token-payload'] if 'sub' in payload and payload['sub'] == 'tmp': add_error(request, "Temporary token", verbose_long="You can use a temporary token only with an application token to get a general user token", status_code=401, location="header") return False return True
def valid_model(request): uid = request.json_body.get(keyword) db_review = DBDiscussionSession \ .query(model).filter(model.uid == uid, model.is_executed == False).first() if is_integer(uid) else None if db_review: request.validated['db_review'] = db_review return True else: add_error(request, 'Database has no row {} of {}'.format(uid, model)) return False
def valid_reason_in_body(request): long_error = "JSON Body has to contain the key \'reason\'" reason = request.json_body.get('reason') if not (reason and isinstance(reason, str)): add_error(request, "Missing \'reason\' in body.", long_error) return False request.validated["reason-text"] = reason return True
def valid_model(request): uid = request.json_body.get(keyword) db_something = DBDiscussionSession.query(model).get( uid) if is_integer(uid) and model else None if db_something: request.validated['db_model'] = db_something return True else: add_error(request, 'Database has no row {} of {}'.format(uid, model)) return False
def check_auth_token(request, nickname: str, token: str) -> bool: log.info("[API] Login attempt from user {}".format(nickname)) if is_api_token(token): if check_api_token(token): request.validated['user'] = get_user_by_case_insensitive_nickname(nickname) request.validated['auth-by-api-token'] = True return True else: add_error(request, "Invalid token", status_code=401, location="header") return False return check_jwt(request, token) and check_not_temporary_token(request)
def valid_new_position_in_body(request): long_error = "JSON Body has to look like this: {\"position\": \"my position\", \"reason\": \"My reason for the position\" " position = request.json_body.get('position') if not (position and isinstance(position, str)): add_error(request, "Missing \'position\' in body.", long_error) return False request.validated["position-text"] = position return True
def valid_table_name(request): """ :param request: :return: """ table_name = escape_if_string(request.json_body, 'table') if table_name and table_name.lower() in table_mapper: request.validated['table'] = table_name return True else: _tn = Translator(get_language_from_cookie(request)) add_error(request, 'Invalid table name', _tn.get(_.invalidTableName)) return False
def valid_fuzzy_search_mode(request): """ Validate fuzzy search modes. :param request: :return: """ mode = request.json_body['type'] if mode in list(FuzzyMode): request.validated['type'] = mode return True else: add_error(request, 'Invalid fuzzy mode') return False
def valid_user_as_author(request): """ :param request: :return: """ _tn = Translator(get_language_from_cookie(request)) if valid_user(request): db_user = request.validated['user'] if db_user.is_admin() or db_user.is_author(): return True else: add_error(request, 'Invalid user group', _tn.get(_.justLookDontTouch)) return False
def check_jwt(request, token) -> bool: try: payload = decode_jwt(request, token) except jwt.ExpiredSignatureError as e: add_error(request, "Token expired", verbose_long=str(e), status_code=401, location="header") return False except jwt.InvalidTokenError: add_error(request, "Invalid token", status_code=401, location="header") return False request.validated['token-payload'] = payload request.validated['user'] = DBDiscussionSession.query(User).get(payload['id']) request.validated['auth-by-api-token'] = False return True
def __set_min_length_error(request, min_length): """ Add an error to the request due to too short statements text. :param request: :param min_length: minimum length of the statement :return: """ _tn = Translator(get_language_from_cookie(request)) a = _tn.get(_.notInsertedErrorBecauseEmpty) b = _tn.get(_.minLength) c = _tn.get(_.eachStatement) error_msg = '{} ({}: {} {})'.format(a, b, min_length, c) add_error(request, 'Text too short', error_msg)
def valid_uid_as_row_in_review_queue(request): uid = request.json_body.get('uid') queue = request.json_body.get('queue', '') model = get_review_model_by_key(queue) db_review = DBDiscussionSession.query(model).get(uid) if is_integer(uid) and model else None if db_review: request.validated['queue'] = queue request.validated['uid'] = uid request.validated['review'] = db_review return True else: add_error(request, 'Invalid id for any review queue found: {}'.format(queue)) return False
def valid_review_queue_key(request): """ Validates the correct keyword for a review queue :param request: :return: """ queue = request.json_body.get('queue') if queue in review_queues: request.validated[queue] = queue return True else: add_error(request, 'No queue found: {}'.format(queue)) return False
def check_jwt(request, token) -> bool: secret = request.registry.settings['public_key'] try: payload = jwt.decode(token, secret, algorithms=['ES256', 'ES512', 'ES384']) except jwt.DecodeError: add_error(request, "Invalid token", status_code=401, location="header") return False request.validated['user'] = DBDiscussionSession.query(User).get( payload['id']) request.validated['auth-by-api-token'] = False return True
def valid_keywords(request): error_occured = False for (keyword, ktype, kdefault) in keywords: value = request.json_body.get(keyword) if value is not None and isinstance(value, ktype): request.validated[keyword] = value elif value is None: request.validated[keyword] = kdefault else: add_error( request, 'Parameter {} has wrong type'.format(keyword), '{} is {}, expected {}'.format(keyword, type(keyword), ktype)) error_occured = True return not error_occured
def valid_review_queue_name(request): """ Given a name for a queue, validates the correctness for our review system :param request: :return: """ queue = request.matchdict.get('queue') if queue in all_queues: request.validated['queue'] = queue return True else: _tn = Translator(get_language_from_cookie(request)) add_error(request, 'Invalid queue', _tn.get(_.internalError)) return False
def valid_statement_or_argument(request): is_argument = request.json_body.get('is_argument') t = Argument if is_argument else Statement uid = request.json_body.get('uid') if uid: db_arg_or_stmt = DBDiscussionSession.query(t).get(uid) else: add_error(request, 'Missing uid for ' + t.__name__) return False if db_arg_or_stmt: request.validated['arg_or_stmt'] = db_arg_or_stmt return True else: add_error(request, t.__name__ + ' is invalid') return False
def valid_any_issue_by_id(request): """ Query issue from database and put it into the request, even if it is disabled :param request: :return: """ issue_id = issue_handler.get_issue_id(request) if issue_id: db_issue: Issue = DBDiscussionSession.query(Issue).get(issue_id) request.validated['issue'] = db_issue return True add_error(request, 'Invalid issue {}'.format(issue_id)) return False