Skip to content
Merged
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c900e73
feat: add method to get user's groups
allison-truhlar Sep 16, 2025
0b864f7
feat: add filtering by group to FileSharePathsHandler
allison-truhlar Oct 3, 2025
aac00a5
Merge branch 'main' into add-user-groups-to-api
allison-truhlar Oct 3, 2025
558b788
fix: return fsp is group is local
allison-truhlar Oct 3, 2025
f98a712
fix: update old variable name to new one
allison-truhlar Oct 3, 2025
bfeeb2c
feat: add method to get user's groups
allison-truhlar Sep 16, 2025
7e4984b
feat: add filtering by group to FileSharePathsHandler
allison-truhlar Oct 3, 2025
849b647
fix: return fsp is group is local
allison-truhlar Oct 3, 2025
087266c
fix: update old variable name to new one
allison-truhlar Oct 3, 2025
48f7b7f
refactor: fetch all preferences with one useEffect and network request
allison-truhlar Oct 3, 2025
62bb118
fix: revert get handler for file-share-paths back to original
allison-truhlar Oct 6, 2025
e07b392
feat: return groups in the profile get handler
allison-truhlar Oct 6, 2025
17e0e6f
feat: add isFilteredByGroups and toggle func to Preferences context
allison-truhlar Oct 6, 2025
58faef0
feat: add toggle for isFilteredByGroups to UI
allison-truhlar Oct 6, 2025
a84a200
refactor: add groups to profile data type
allison-truhlar Oct 6, 2025
bb85beb
refactor: add filtering by groups to hook; rename to reflect updated …
allison-truhlar Oct 6, 2025
e15c341
feat: add filtering message and link to prefs page to Zones browser
allison-truhlar Oct 6, 2025
81154ae
Merge branch 'filter-by-group-preference' into add-user-groups-to-api
allison-truhlar Oct 6, 2025
6ccd1c6
chore: linter changes
allison-truhlar Oct 6, 2025
b261805
Merge branch 'main' into add-user-groups-to-api
allison-truhlar Oct 6, 2025
7504eed
chore: linter
allison-truhlar Oct 6, 2025
6b641c4
fix: default to no filtering for local zones; make zones selector mor…
allison-truhlar Oct 6, 2025
a2ce63e
fix: try to fix docs link error in GH action
allison-truhlar Oct 6, 2025
283fdb6
fix: add add'tl context provider to test setup to fix failures
allison-truhlar Oct 6, 2025
a51abfb
fix: links for gh build action
allison-truhlar Oct 6, 2025
768faee
fix: toHaveTitle not working on page fixture
allison-truhlar Oct 6, 2025
23cf217
docs: update ui-test readme
allison-truhlar Oct 6, 2025
1b8874c
fix: update fileglancer-user-docs links to fileglancer-docs
allison-truhlar Oct 6, 2025
96591e2
fix: revert file share paths handler back to no group filtering
allison-truhlar Oct 7, 2025
45b87c8
Merge branch 'main' into add-user-groups-to-api
allison-truhlar Oct 7, 2025
9df8346
Merge branch 'main' into add-user-groups-to-api
allison-truhlar Oct 8, 2025
3f1b75a
update wording
krokicki Oct 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions fileglancer/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import json
import requests
import re
import grp
import pwd
from datetime import datetime, timezone
from abc import ABC
from mimetypes import guess_type
Expand Down Expand Up @@ -54,8 +56,18 @@ def _get_mounted_filestore(fsp):
return filestore


def _should_show_fsp(fsp, user_groups):
"""
Determine if a file share path should be shown to the user based on the user's groups.
"""
if fsp.group == "public" or fsp.group == 'local' or fsp.group in user_groups:
return True
return False


class BaseHandler(APIHandler):
_home_file_share_path_cache = {}
_groups_cache = {}

def get_current_user(self):
"""
Expand Down Expand Up @@ -98,6 +110,36 @@ def get_home_file_share_path_name(self):
return None


def get_user_groups(self):
"""
Get the groups for the current user.

Returns:
list: List of group names the user belongs to.
"""
username = self.get_current_user()

if username in self._groups_cache:
return self._groups_cache[username]

try:
user_info = pwd.getpwnam(username)
user_groups = []
all_groups = grp.getgrall() # Get all groups on the system
for group in all_groups:
if username in group.gr_mem: # Check if user is a member of this group
user_groups.append(group.gr_name)
primary_group = grp.getgrgid(user_info.pw_gid).gr_name
if primary_group not in user_groups: # Add primary group if not already included
user_groups.append(primary_group)
self._groups_cache[username] = user_groups
return user_groups
except Exception as e:
self.log.error(f"Error getting groups for user {username}: {str(e)}")
self._groups_cache[username] = []
return []


class StreamingProxy(BaseHandler):
"""
API handler for proxying responses from the central server
Expand Down Expand Up @@ -130,17 +172,36 @@ class FileSharePathsHandler(BaseHandler):
"""
@web.authenticated
def get(self):
self.log.info("GET /api/fileglancer/file-share-paths")
username = self.get_current_user()
self.log.info("GET /api/fileglancer/file-share-paths username={username}")
file_share_paths = get_fsp_manager(self.settings).get_file_share_paths()

# Check user preference for group filtering
preference_manager = get_preference_manager(self.settings)

try:
filter_by_groups = preference_manager.get_preference(username, "filter_zones_by_group")
except KeyError:
filter_by_groups = True # Default to True if preference not set
except Exception as e:
self.log.error(f"Error getting user preference: {str(e)}")
filter_by_groups = False # Default to False on an error other than KeyError. Better to show too many zones than too few.

if filter_by_groups:
user_groups = self.get_user_groups()
filtered_paths = [fsp for fsp in file_share_paths if _should_show_fsp(fsp, user_groups)]
# Convert Pydantic objects to dicts before JSON serialization
response_data = {"paths": [fsp.model_dump() for fsp in filtered_paths]}
else:
# Convert Pydantic objects to dicts before JSON serialization
response_data = {"paths": [fsp.model_dump() for fsp in file_share_paths]}

self.set_header('Content-Type', 'application/json')
self.set_status(200)
# Convert Pydantic objects to dicts before JSON serialization
file_share_paths_json = {"paths": [fsp.model_dump() for fsp in file_share_paths]}
self.write(json.dumps(file_share_paths_json))
self.write(json.dumps(response_data))
self.finish()



class FileShareHandler(BaseHandler, ABC):
"""
Abstract base handler for endpoints that use the Filestore class.
Expand Down