vgrem / Office365-REST-Python-Client

Microsoft 365 & Microsoft Graph Library for Python
MIT License
1.34k stars 335 forks source link

Extracting the Permission Levels on Each File, Folder and List for Each SharePoint Group and User #839

Open enestarlace opened 7 months ago

enestarlace commented 7 months ago

Hello,

I should extract the permission levels on the files, folders, and lists which a SharePoint Group and User has. I have examined the library and its issues and anything else related to the job, but I can not find anything useful. (I need a help as fast as possible)

Extracting the Permission Levels on Each List for Each SharePoint Group and User

import pandas as pd
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.client_credential import ClientCredential

# Setup client credentials and context
client_id = "client_id"
client_secret = "client_secret"
sp_url = "https://company.sharepoint.com/sites/relative_url"
ctx = ClientContext(sp_url).with_credentials(ClientCredential(client_id, client_secret))

# Listing all of the list IDs
lists = ctx.web.lists
ctx.load(lists)
ctx.execute_query()

# DataFrame to store permissions data
df_permissions = pd.DataFrame(columns=["ListName", "ListURL", "Type", "GroupName", "Permission"])

# Function to retrieve and store permissions for a given SharePoint list for a specific group
def get_permissions_for_group(sp_list, group_name, df_permissions):
    try:
        role_assignments = sp_list.role_assignments
        ctx.load(role_assignments)
        ctx.execute_query()
        for role_assignment in role_assignments:
            ra_group = role_assignment.principal
            ctx.load(ra_group)
            ctx.execute_query()
            # Check if the role assignment principal matches the SharePoint group we're interested in
            if ra_group.title == group_name:
                ctx.load(role_assignment.role_definition_bindings)
                ctx.execute_query()
                permissions = [role_def.name for role_def in role_assignment.role_definition_bindings]
                # Store the permissions in the DataFrame
                df_permissions = df_permissions.append({
                    "ListName": sp_list.properties['Title'],
                    "ListURL": sp_list.resource_url,
                    "Type": "List",
                    "GroupName": group_name,
                    "Permission": ', '.join(permissions)
                }, ignore_index=True)
    except Exception as e:
        print(f"An error occurred with group '{group_name}': {e}")
        # Optionally, log the error or take other actions as necessary
    return df_permissions

# Iterate over all lists
for sp_list in lists:
    # Then for each list, iterate through each SharePoint group to get permissions
    for group_name in df_groups["GroupName"]:
        df_permissions = get_permissions_for_group(sp_list, group_name, df_permissions)

# At this point, df_permissions will contain the permissions info, excluding any lists/groups that resulted in an error
df_permissions

When I execute the code, I got the error:

_An error occurred with group 'SharePoint Group': (None, None, '401 Client Error: Unauthorized for url: https://company.sharepoint.com/sites/relative_url/_api/Web/lists(%3Ckey%3E)/RoleAssignments')_

I've successfully extracted the SharePoint Group name and users of the group (Users' display name, user name, and mail address). But I can not achieve to reach permission informations like "Edit", "Edit Limited", "Full Control", "Read", and "Viewer" which a SP Group or User has on a file, folder, or list. Any help for it?

Additionally, the code for extracting all of the files and folders in the below:

def list_all_contents(ctx, relative_url, df, depth=0):
    if depth > MAX_DEPTH:  # MAX_DEPTH is a predefined constant limiting recursion depth
        return df
    try:
        library_root = ctx.web.get_folder_by_server_relative_url(relative_url)
        ctx.load(library_root, ['Folders', 'Files'])
        ctx.execute_query()
        # Process folders
        folder_data = [{'FolderName': folder.properties["Name"], 'FolderURL': folder.properties["ServerRelativeUrl"], 'ItemID': None, 'ItemTitle': None, 'ItemURL': None} for folder in library_root.folders]
        df = pd.concat([df, pd.DataFrame(folder_data)], ignore_index=True)
        for folder in library_root.folders:
            df = list_all_contents(ctx, folder.properties["ServerRelativeUrl"], df, depth + 1)
        # Process files
        file_data = [{'FolderName': None, 'FolderURL': relative_url, 'ItemID': file.properties["UniqueId"], 'ItemTitle': file.properties["Name"], 'ItemURL': file.properties["ServerRelativeUrl"]} for file in library_root.files]
        df = pd.concat([df, pd.DataFrame(file_data)], ignore_index=True)
    except Exception as e:
        print(f'Problem processing {relative_url}: {e}')
    return df
# Set a reasonable MAX_DEPTH to avoid too deep recursion
MAX_DEPTH = 4  # Adjust based on your needs
df_files = pd.DataFrame(columns=["FolderName", "FolderURL", "ItemID", "ItemTitle", "ItemURL"])
df_result = list_all_contents(ctx, "/sites/dmc", df_files)
df_result
dulalbert commented 6 months ago

Did you find a solution?