def browse(): from_path = request.args.get('path', '') if from_path == '': from_path = os.path.sep # #2475 Default this in case of error in get_directory_listing() directory_info = DirectoryInfo(from_path) db_session = data_engine.db_get_session() db_committed = False try: directory_info = get_directory_listing(from_path, True) # Auto-populate the folders database db_folder = auto_sync_folder( from_path, data_engine, task_engine, _db_session=db_session ) db_session.commit() db_committed = True if db_folder is not None: # Require view permission or file admin permissions_engine.ensure_folder_permitted( db_folder, FolderPermission.ACCESS_VIEW, get_session_user() ) # Remember last path for the Browse and Upload menus if directory_info.exists() and db_folder: session['last_browse_path'] = from_path return render_template( 'list.html', formats=image_engine.get_image_formats(), pathsep=os.path.sep, timezone=get_timezone_code(), directory_info=directory_info, folder_name=filepath_filename(from_path), db_info=db_folder, db_parent_info=db_folder.parent if db_folder else None, STATUS_ACTIVE=Folder.STATUS_ACTIVE ) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise return render_template( 'list.html', directory_info=directory_info, err_msg='This folder cannot be viewed: ' + str(e) ) finally: try: if not db_committed: db_session.rollback() finally: db_session.close()
def folder_browse(): from_path = request.args.get('path', '') show_files = request.args.get('show_files', '') embed = request.args.get('embed', '') msg = request.args.get('msg', '') if from_path == '': from_path = os.path.sep db_session = data_engine.db_get_session() db_committed = False try: # This also checks for path existence folder_list = get_directory_listing(from_path, True) # Auto-populate the folders database db_folder = auto_sync_folder( from_path, data_engine, task_engine, _db_session=db_session ) db_session.commit() db_committed = True # Should never happen if db_folder is None: raise DoesNotExistError(from_path) # Require view permission or file admin permissions_engine.ensure_folder_permitted( db_folder, FolderPermission.ACCESS_VIEW, get_session_user() ) return render_template( 'folder_list.html', formats=image_engine.get_image_formats(), embed=embed, msg=msg, name=filepath_filename(from_path), path=from_path, pathsep=os.path.sep, parent_path=filepath_parent(from_path), folder_list=folder_list, show_files=show_files, db_info=db_folder, db_parent_info=db_folder.parent, STATUS_ACTIVE=Folder.STATUS_ACTIVE ) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise return render_template( 'folder_list.html', embed=embed, msg=msg, name=filepath_filename(from_path), path=from_path, err_msg='This folder cannot be viewed: ' + str(e) ) finally: try: if not db_committed: db_session.rollback() finally: db_session.close()
def calculate_folder_permissions(self, folder, user=None, folder_must_exist=True): """ Returns an integer indicating the highest access level that is permitted for a folder, based on all a user's groups. This value will be returned from cache if possible. The folder parameter can be either a Folder object or a folder path. If user is None, the anonymous user's permissions are checked, using the Public group. If folder_must_exist is False, the folder parameter can be a path that does not yet exist (access will be calculated for the nearest existing path). Raises a ValueError if folder is None. Raises a DoesNotExistError if folder_must_exist is True but the folder is an invalid path, or if a user is provided but is not a valid user. """ if folder is None: raise ValueError('Empty folder provided for permissions checking') folder_path = self._normalize_path( folder.path if hasattr(folder, 'path') else folder ) # Periodically ensure our data is up to date self._check_data_version() # Note this now in case another thread changes it mid-flow further on current_version = self._fp_data_version # Try the cache first if user is None: cache_val = self._public_fp_cache.get(folder_path) else: cache_val = self._cache.raw_get( self._get_cache_key(user, folder_path), integrity_check=True ) # Cache entries are (value, version) if cache_val and cache_val[1] == current_version: return cache_val[0] # We need to (re)calculate the folder access # !!! Also update _trace_folder_permissions() if changing this !!! db_session = self._db.db_get_session() db_commit = False try: # Get the folder and public group objects db_folder = db_session.merge(folder, load=False) if hasattr(folder, 'path') else \ auto_sync_folder(folder, self._db, self._tasks, _db_session=db_session) db_public_group = self._db.get_group( group_id=Group.ID_PUBLIC, load_users=False, _db_session=db_session ) # Handle non-existent folder if db_folder is None and not folder_must_exist: db_folder = _get_nearest_parent_folder(folder_path, self._db, db_session) # Hopefully won't need these if db_folder is None: raise DoesNotExistError(folder_path) if db_public_group is None: raise DoesNotExistError('Public group') # Get the Public group access public_permission = self._db.get_nearest_folder_permission( db_folder, db_public_group, _db_session=db_session ) if public_permission is None: # Hopefully never get here self._logger.error('No root folder permission found for the Public group') public_permission = FolderPermission( db_folder, db_public_group, FolderPermission.ACCESS_NONE ) if user is None: # Debug log only if self._settings['DEBUG']: self._logger.debug( 'Public access to folder ' + folder_path + ' is ' + str(public_permission) ) # Add result to cache and return it self._public_fp_cache.set( folder_path, (public_permission.access, current_version) ) db_commit = True return public_permission.access else: db_user = user if self._db.attr_is_loaded(user, 'groups') else \ self._db.get_user(user.id, load_groups=True, _db_session=db_session) # Hopefully won't need this if db_user is None: raise DoesNotExistError('User %d' % user.id) # Look at access for each of the user's groups final_access = FolderPermission.ACCESS_NONE for db_user_group in db_user.groups: g_permission = self._db.get_nearest_folder_permission( db_folder, db_user_group, _db_session=db_session ) # The final access = the highest level from all the groups if g_permission is not None and g_permission.access > final_access: final_access = g_permission.access # Fast path if final_access == FolderPermission.ACCESS_ALL: break # Use the public group access as a fallback if public_permission.access > final_access: final_access = public_permission.access # Debug log only if self._settings['DEBUG']: self._logger.debug( str(user) + '\'s access to folder ' + folder_path + ' is ' + str(final_access) ) # Add result to cache and return it self._cache.raw_put( self._get_cache_key(user, folder_path), (final_access, current_version), PermissionsManager.USER_PERMISSIONS_TIMEOUT, integrity_check=True ) db_commit = True return final_access finally: try: if db_commit: db_session.commit() else: db_session.rollback() finally: db_session.close()