def test_find_by_hash(self, m_Tag, m_File): m_session = MagicMock() hash_type, hash = "something", "anotherthing" tag = MagicMock() tag.id = randint(0, 10) tags = [tag.id] FileExt.query_find_by_hash(hash_type, hash, tags, m_session) m_session.query.called_with(FileExt) m_Tag.find_by_id.assert_called_once_with(tag.id, m_session)
def test_find_by_hash(self, m_Tag, m_File): m_session = MagicMock() hash_type, hash = "something", "anotherthing" tag = MagicMock() tag.id = randint(0, 10) tags = [tag.id] FileExt.query_find_by_hash(hash_type, hash, tags, m_session) m_session.query.called_with(FileExt) m_session.query().filter_by.assert_called_once_with(id=tag.id) m_session.query().filter_by().one.assert_called_once()
def test_find_by_hash_distinct_false(self, m_Tag, m_File): m_session = MagicMock() hash_type, hash = "something", "anotherthing" tag = MagicMock() tag.id = randint(0, 10) tags = [tag.id] FileExt.query_find_by_hash(hash_type, hash, tags, m_session, distinct_name=False) m_session.query.called_with(FileExt) m_session.query().filter_by.assert_called_once_with(id=tag.id) m_session.query().filter_by().one.assert_called_once()
def list(name: text = None, hash: text = None, tags: comma_separated_list = None, offset: number = 0, limit: number = 25): """ Search a file using query filters (tags + hash or name). Support pagination. :param name: lookup name :param hash: lookup hash value :param tags: lookup tag list :param offset: start index in matching results :param limit: max number of results :rtype: dict of 'total': int, 'page': int, 'per_page': int, 'items': list of file(s) found :return: on success 'items' contains a list of files found on error 'msg' gives reason message """ session = db.session if name is not None: name = decode_utf8(name) log.debug("name %s h_value %s tags %s", name, hash, tags) if name is not None and hash is not None: raise ValueError("Can't find using both name and hash") if name is not None: base_query = FileExt.query_find_by_name(name, tags, session) elif hash is not None: h_type = guess_hash_type(hash) if h_type is None: raise ValueError("Hash not supported") base_query = FileExt.query_find_by_hash( h_type, hash, tags, session) else: # FIXME this is just a temporary way to output # all files, need a dedicated # file route and controller base_query = FileExt.query_find_by_name("", tags, session) # TODO: Find a way to move pagination as a BaseQuery like in # flask_sqlalchemy. # https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L422 items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("Found %s results", total) return { 'total': total, 'offset': offset, 'limit': limit, 'items': file_ext_schema_lite.dump(items, many=True).data, }
def get(response, sha256: text, alt: one_of(('media', '')) = '', offset: number = 0, limit: number = 25): """ Detail about one file and all known scans summary where file was present (identified by sha256). Support pagination. :param all params are sent using query method :param if alt parameter is "media", response will contains the binary data :rtype: dict of 'total': int, 'page': int, 'per_page': int, :return: on success fileinfo contains file information on success 'items' contains a list of files found on error 'msg' gives reason message """ session = db.session log.debug("h_value %s", sha256) # Check wether its a download attempt or not if alt == "media": return _download(response, sha256) file = File.load_from_sha256(sha256, session) # query all known results not only those with different names base_query = FileExt.query_find_by_hash("sha256", sha256, None, session, distinct_name=False) # TODO: Find a way to move pagination as a BaseQuery like in # flask_sqlalchemy. # https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L422 items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("offset %d limit %d total %d", offset, limit, total) file_ext_schema = FileExtSchema(exclude=('probe_results', 'file_infos')) fileinfo_schema = FileSchema() # TODO: allow formatted to be a parameter formatted = True fileinfo_schema.context = {'formatted': formatted} return { 'file_infos': fileinfo_schema.dump(file).data, 'total': total, 'offset': offset, 'limit': limit, 'items': file_ext_schema.dump(items, many=True).data, }