Ejemplo n.º 1
0
    def get_db_query(self):
        if self.db_query is None:
            self.db_query = self._build_db_query()

            if not self.has['medscan']:
                minus_q = ~HasOnlySource('medscan')
                self.db_query &= minus_q
                if not self.ev_filter:
                    self.ev_filter = minus_q.ev_filter()
                else:
                    self.ev_filter &= minus_q.ev_filter()

            if self.strict:
                num_agents = (self.db_query.list_component_queries()
                              .count(HasAgent.__name__))
                self.db_query &= HasNumAgents((num_agents,))

            # Note the query in the log, if one is running.
            if is_log_running():
                note_in_log(query=self.db_query.to_json())

            logger.info(f"Constructed query \"{self.db_query}\":\n"
                        f"{json.dumps(self.db_query.to_json(), indent=2)}")

            # Prevent someone from breaking the database by querying too many
            # hashes, paper IDs, or MeshIds.
            query_set = set(self.db_query.list_component_queries())
            if {'HasHash', 'FromPapers', 'FromMeshIds'} & query_set:
                for q in self.db_query.iter_component_queries():
                    if isinstance(q, HasHash):
                        list_len = len(q.stmt_hashes)
                        lbl = 'hashes'
                    elif isinstance(q, FromPapers):
                        list_len = len(q.paper_list)
                        lbl = 'paper IDs'
                    elif isinstance(q, FromMeshIds):
                        list_len = len(q.mesh_ids)
                        lbl = 'MeSH IDs'
                    else:
                        list_len = 0
                        lbl = None

                    if list_len > MAX_LIST_LEN:
                        logger.error(f"Length exceeded: {list_len} > "
                                     f"{MAX_LIST_LEN}")
                        raise HttpUserError(f"Too many {lbl}! Only "
                                            f"{MAX_LIST_LEN} {lbl} allowed.")
        return self.db_query
Ejemplo n.º 2
0
def resolve_auth(query):
    """Get the roles for the current request, either by JWT or API key.

    If by API key, the key must be in the query. If by JWT, @jwt_optional or
    similar must wrap the calling function.

    Returns a tuple with the current user, if applicable, and a list of
    associated roles.
    """
    api_key = query.pop('api_key', None)
    logger.info("Got api key %s" % api_key)
    if api_key:
        logger.info("Using API key role.")
        role = Role.get_by_api_key(api_key)
        set_role_in_log(role)
        return None, [role]

    user_identity = get_jwt_identity()
    logger.debug("Got user_identity: %s" % user_identity)
    if not user_identity:
        logger.info("No user identity, no role.")
        return None, []

    try:
        current_user = User.get_by_identity(user_identity)
        logger.debug("Got user: %s" % current_user)
    except BadIdentity:
        logger.info("Identity malformed, no role.")
        return None, []
    except Exception as e:
        logger.exception(e)
        logger.error("Unexpected error looking up user.")
        return None, []

    if not current_user:
        logger.info("Identity not mapped to user, no role.")
        return None, []

    logger.info("Identity mapped to the user, returning roles.")
    if is_log_running():
        set_user_in_log(current_user)
    return current_user, list(current_user.roles)
Ejemplo n.º 3
0
    def get_db_query(self):
        if self.db_query is None:
            self.db_query = self._build_db_query()

            if not self.has['medscan']:
                minus_q = ~HasOnlySource('medscan')
                self.db_query &= minus_q
                if not self.ev_filter:
                    self.ev_filter = minus_q.ev_filter()
                else:
                    self.ev_filter &= minus_q.ev_filter()

            if self.strict:
                num_agents = (self.db_query.list_component_queries()
                              .count(HasAgent.__name__))
                self.db_query &= HasNumAgents((num_agents,))

            # Note the query in the log, if one is running.
            if is_log_running():
                note_in_log(query=self.db_query.to_json())

        logger.info(f"Constructed query \"{self.db_query}\":\n"
                    f"{json.dumps(self.db_query.to_json(), indent=2)}")
        return self.db_query
Ejemplo n.º 4
0
def resolve_auth(query, failure_reason=None):
    """Get the roles for the current request, either by JWT or API key.

    If by API key, the key must be in the query. If by JWT, @jwt_optional or
    similar must wrap the calling function.

    If the reason for credentials failing is of interest, you can pass an empty
    dictionary to `failure_reason`. If there is an auth problem, it will be
    populated with 'auth_attempted' and 'reason', indicating the kind of auth
    (e.g. "API key" or "Identity") that was attempted, and the reason it was
    rejected (e.g. "Invalid").

    Returns a tuple with the current user, if applicable, and a list of
    associated roles.
    """
    api_key = query.pop('api_key', None)
    logger.info("Got api key %s" % api_key)
    if api_key:
        logger.info("Using API key role.")
        try:
            role = Role.get_by_api_key(api_key)
        except UserDatabaseError:
            if failure_reason is not None:
                failure_reason['auth_attempted'] = "API key"
                failure_reason['reason'] = "Invalid"
            return None, []
        set_role_in_log(role)
        return None, [role]

    user_identity = get_jwt_identity()
    logger.debug("Got user_identity: %s" % user_identity)
    if not user_identity:
        logger.info("No user identity, no role.")
        if failure_reason is not None:
            failure_reason['auth_attempted'] = None
            failure_reason['reason'] = "No auth"
        return None, []

    try:
        current_user = User.get_by_identity(user_identity)
        logger.debug("Got user: %s" % current_user)
    except BadIdentity:
        logger.info("Identity malformed, no role.")
        if failure_reason is not None:
            failure_reason['auth_attempted'] = "Identity"
            failure_reason['reason'] = "Invalid"
        return None, []
    except Exception as e:
        logger.exception(e)
        logger.error("Unexpected error looking up user.")
        if failure_reason is not None:
            failure_reason['auth_attempted'] = "Identity"
            failure_reason['reason'] = 'Unexpected'
        return None, []

    if not current_user:
        logger.info("Identity not mapped to user, no role.")
        if failure_reason is not None:
            failure_reason['auth_attempted'] = "Identity"
            failure_reason['reason'] = "No user"
        return None, []

    logger.info("Identity mapped to the user, returning roles.")
    if is_log_running():
        set_user_in_log(current_user)
    return current_user, list(current_user.roles)