Skip to content

Commit

Permalink
feat: show permissions in file tree
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke authored and rhelmke committed Oct 28, 2024
1 parent fafebe8 commit bde744c
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 13 deletions.
24 changes: 20 additions & 4 deletions src/storage/db_interface_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def get_number_of_total_matches(self, search_dict: dict, only_parent_firmwares:
def generate_file_tree_nodes_for_uid_list(
self, uid_list: list[str], root_uid: str, parent_uid: str | None, whitelist: list[str] | None = None
):
file_tree_data = self.get_file_tree_data(uid_list)
file_tree_data = self.get_file_tree_data(uid_list, parent_uid)
for entry in file_tree_data:
yield from self.generate_file_tree_level(entry.uid, root_uid, parent_uid, whitelist, entry)

Expand All @@ -262,13 +262,14 @@ def generate_file_tree_level(
data: FileTreeData | None = None,
):
if data is None:
data = self.get_file_tree_data([uid])[0]
data = self.get_file_tree_data([uid], parent_uid)[0]
try:
yield from VirtualPathFileTree(root_uid, parent_uid, data, whitelist).get_file_tree_nodes()
except (KeyError, TypeError): # the file has not been analyzed yet
yield FileTreeNode(uid, root_uid, not_analyzed=True, name=f'{uid} (not analyzed yet)')

def get_file_tree_data(self, uid_list: list[str]) -> list[FileTreeData]:
def get_file_tree_data(self, uid_list: list[str], parent_uid: str | None) -> list[FileTreeData]:
mode_data = self._get_mode_dict(parent_uid)
with self.get_read_only_session() as session:
# get included files in a separate query because it is way faster than FileObjectEntry.get_included_uids()
included_files = self._get_included_files_for_uid_list(session, uid_list)
Expand All @@ -282,7 +283,13 @@ def get_file_tree_data(self, uid_list: list[str]) -> list[FileTreeData]:
).filter(FileObjectEntry.uid.in_(uid_list))
return [
FileTreeData(
uid, file_name, size, vfp_data.get(uid), type_analyses.get(uid), included_files.get(uid, set())
uid,
file_name,
size,
vfp_data.get(uid),
type_analyses.get(uid),
included_files.get(uid, set()),
mode_data,
)
for uid, file_name, size in session.execute(query)
]
Expand Down Expand Up @@ -437,3 +444,12 @@ def get_root_uid(self, uid: str) -> str:
)
)
return session.execute(query.limit(1)).scalar() or ''

def _get_mode_dict(self, parent_uid: str | None) -> dict[str, str]:
fs_metadata = self.get_analysis(parent_uid, 'file_system_metadata') if parent_uid else None
if not fs_metadata:
return {}
return {
meta_dict['path'].lstrip('/'): meta_dict['mode']
for meta_dict in fs_metadata.get('result', {}).get('files', [])
}
2 changes: 1 addition & 1 deletion src/test/integration/storage/test_db_interface_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def test_get_file_tree_data(frontend_db, backend_db):
child_fo.processed_analysis = {} # simulate that file_type did not run yet
backend_db.insert_multiple_objects(fw, parent_fo, child_fo)

result = frontend_db.get_file_tree_data([fw.uid, parent_fo.uid, child_fo.uid])
result = frontend_db.get_file_tree_data([fw.uid, parent_fo.uid, child_fo.uid], fw.uid)
assert len(result) == 3 # noqa: PLR2004
result_by_uid = {r.uid: r for r in result}
assert result_by_uid[parent_fo.uid].uid == parent_fo.uid
Expand Down
1 change: 1 addition & 0 deletions src/test/unit/web_interface/test_file_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class TestVirtualPathFileTree:
'size': 1,
'mime': 'footype',
'included_files': set(),
'file_mode_data': {},
}

def test_multiple_paths(self):
Expand Down
17 changes: 10 additions & 7 deletions src/web_interface/file_tree/file_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class FileTreeData(NamedTuple):
virtual_file_path: dict[str, list[str]]
mime: str
included_files: set[str]
file_mode_data: dict | None = None


def get_mime_for_text_file(filename: str) -> str:
Expand Down Expand Up @@ -201,20 +202,21 @@ def get_file_tree_nodes(self) -> Iterable[FileTreeNode]:
yield self._get_node_for_real_file()
else:
for path in self.virtual_file_paths:
yield self._create_node_from_virtual_path(path.lstrip('/').split('/'))
mode = self.fo_data.file_mode_data.get(path.lstrip('/'))
yield self._create_node_from_virtual_path(path.lstrip('/').split('/'), mode)

def _create_node_from_virtual_path(self, current_virtual_path: list[str]) -> FileTreeNode:
def _create_node_from_virtual_path(self, current_virtual_path: list[str], mode: str | None = None) -> FileTreeNode:
if len(current_virtual_path) > 1:
return self._get_node_for_virtual_file(current_virtual_path)
return self._get_node_for_real_file(current_virtual_path[0])
return self._get_node_for_virtual_file(current_virtual_path, mode)
return self._get_node_for_real_file(current_virtual_path[0], mode)

def _get_node_for_virtual_file(self, current_virtual_path: list[str]) -> FileTreeNode:
def _get_node_for_virtual_file(self, current_virtual_path: list[str], mode: str | None) -> FileTreeNode:
current_element, *rest_of_virtual_path = current_virtual_path
node = FileTreeNode(uid=None, root_uid=self.root_uid, virtual=True, name=current_element)
node.add_child_node(self._create_node_from_virtual_path(rest_of_virtual_path))
node.add_child_node(self._create_node_from_virtual_path(rest_of_virtual_path, mode))
return node

def _get_node_for_real_file(self, virtual_path: str | None = None) -> FileTreeNode:
def _get_node_for_real_file(self, virtual_path: str | None = None, mode: str | None = None) -> FileTreeNode:
return FileTreeNode(
self.uid,
self.root_uid,
Expand All @@ -223,6 +225,7 @@ def _get_node_for_real_file(self, virtual_path: str | None = None) -> FileTreeNo
size=self.fo_data.size,
mime_type=self.fo_data.mime,
has_children=self._has_children(),
mode=mode,
)

def _get_file_name(self, current_virtual_path: list[str]) -> str:
Expand Down
2 changes: 2 additions & 0 deletions src/web_interface/file_tree/file_tree_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ def __init__( # noqa: PLR0913
mime_type=None,
has_children=False,
not_analyzed=False,
mode: str | None = None,
):
self.uid = uid
self.root_uid = root_uid
self.virtual = virtual
self.name = name
self.size = size
self.mode = mode
self.type = mime_type
self.has_children = has_children
self.not_analyzed = not_analyzed
Expand Down
5 changes: 4 additions & 1 deletion src/web_interface/file_tree/jstree_conversion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import stat

from common_helper_files import human_readable_file_size

from web_interface.file_tree.file_tree import get_icon_for_mime, get_mime_for_text_file
Expand Down Expand Up @@ -33,7 +35,8 @@ def _get_not_analyzed_jstree_node(node: FileTreeNode):

def _get_file_jstree_node(node: FileTreeNode):
link = f'/analysis/{node.uid}/ro/{node.root_uid}'
label = f'<b>{node.name}</b> (<span style="color:gray;">{human_readable_file_size(node.size)}</span>)'
mode = f', {stat.filemode(int(node.mode, 8)).lstrip("?")}' if node.mode else ''
label = f'<b>{node.name}</b> (<span style="color:gray;">{human_readable_file_size(node.size)}{mode}</span>)'
mime = get_mime_for_text_file(node.name) if node.type == 'text/plain' else node.type
result = _get_jstree_node_contents(label, link, get_icon_for_mime(mime))
result['data'] = {'uid': node.uid}
Expand Down

0 comments on commit bde744c

Please sign in to comment.