Skip to content

Compensation Folder Automation - Complete Guide

📌 THIS IS THE OFFICIAL, CONSOLIDATED README - Use this file as your reference guide

Replaces: README-CompensationFolders.md and COMPENSATION-FOLDER-AUTOMATION-README.md


⚡ Quick Reference

If you just want to run it and don't need details:

# 1. Connect to VPN
# 2. Open PowerShell
# 3. Navigate to script directory:
cd "C:\Users\Jricica\OneDrive - Rudolph Libbe Group\Scripts\OneDrive-SharePoint"

# 4. Run THIS command (the production wrapper script):
.\Run-CompensationFolders-Production.ps1

# DO NOT run New-CompensationFolderStructure.ps1 directly!

First time running? Read the full guide below, especially Prerequisites.


📋 Table of Contents


🎯 What This Does

This automation creates a compensation review folder structure in SharePoint Online with automatic cascading permissions based on your Active Directory organizational hierarchy.

What It Creates (Flat Structure - Default):

SharePoint: RLGManagers Site
└── Documents
    └── General
        └── Bonus 2025 NEW
            ├── Rudolph, Bill
            ├── Executive 1
            ├── Executive 2
            ├── Manager A
            ├── Manager B
            ├── Manager C
            ├── Manager D
            └── (all other managers at same level)

Note: All folders are created at the same level (flat structure). This ensures managers can navigate directly to their folders without needing access to parent folders.

Automatic Permissions:

  • Bill Rudolph (CEO) → Edit access to ALL folders (entire company)
  • Executive 1 → Edit access to their folder + all their subordinates' folders (Manager A, Manager B, etc.)
  • Manager A → Edit access to their folder + their subordinates' folders (Manager B, etc.)
  • Manager B → Edit access to only their folder
  • Security: Other site members cannot see any folders (unique permissions)

How It Works: The organizational hierarchy is maintained through permissions, not folder nesting. Each manager can only see and access their own folder and their subordinates' folders, even though all folders appear at the same level.

Key Features:

  • ✅ Reads organizational structure from Active Directory
  • ✅ Creates flat folder structure with one folder per manager
  • ✅ Sets edit permissions for entire management chain (based on org hierarchy)
  • ✅ Breaks permission inheritance for security
  • ✅ Handles email/UPN mismatches automatically
  • ✅ Generates detailed log file for audit trail
  • ✅ Ensures all managers can navigate to their folders without access issues

🔐 How the Cascading Permissions Work

Each manager receives Edit access to:

  • Their own folder
  • All direct reports' folders
  • All managers who report to them (and their folders)
  • All employees down their entire reporting chain

Example Organizational Chart:

CEO (Jane Smith)
├── VP of Operations (John Doe)
│   ├── Plant Manager (Mike Johnson)
│   │   ├── Supervisor (Sarah Lee)
│   │   │   ├── Employee A
│   │   │   └── Employee B
│   │   └── Employee C
│   └── Safety Manager (Tom Wilson)
│       └── Employee D
└── VP of Finance (Lisa Brown)
    └── Controller (David Garcia)
        └── Employee E

Who Can Access What:

Person Can Access These Folders Total Folders
CEO Jane Everyone (herself + all 10 subordinates) 11 folders
VP John Himself + all 7 in Operations chain 8 folders
Plant Manager Mike Himself + Sarah + Employee A + Employee B + Employee C 5 folders
Supervisor Sarah Herself + Employee A + Employee B 3 folders
VP Lisa Herself + David + Employee E 3 folders
Employee A No access since they do not have any direct reports

Important Notes:

  • ✅ Permissions cascade down the org chart (managers can see subordinates)
  • ❌ Permissions do NOT cascade up (employees cannot see their managers' folders)
  • ✅ Peers cannot see each other's folders (John can't see Lisa's folders)
  • ✅ Site Collection Administrators (HR Director) can see everything

✅ Prerequisites

1. Network Access

  • Connected to RLG VPN (required for Active Directory access)
  • Internet connection (required for SharePoint Online)

2. PowerShell Modules

Open PowerShell as Administrator and run:

# Check if modules are installed
Get-Module -ListAvailable PnP.PowerShell, ActiveDirectory

# If missing, install them:
Install-Module -Name PnP.PowerShell -Scope CurrentUser -Force
# ActiveDirectory module comes with RSAT tools (usually already installed)

3. Permissions Required

  • Active Directory: Read access to user objects and organizational hierarchy
  • SharePoint: Site Owner or Site Collection Administrator on https://rlgbuilds.sharepoint.com/sites/RLGManagers
  • Azure AD App: Access to the RLG SharePoint enterprise app (authentication handled automatically)

4. Site Collection Administrator Setup (CRITICAL for HR Access)

⚠️ IMPORTANT: The HR Director (or person responsible for compensation management) MUST be a Site Collection Administrator to access all folders.

Why? The script breaks permission inheritance on all folders for security. Only these people will have access:

  • ✅ Site Collection Administrators (HR Director, IT admins)
  • ✅ Managers in the reporting chain (granted by script)
  • ❌ Regular Site Owners (no access to folders)
  • ❌ Site Members (no access to folders)

How to Add HR Director as Site Collection Administrator:

  1. Navigate to the site: https://rlgbuilds.sharepoint.com/sites/RLGManagers
  2. Click the Settings gear (⚙️) in the top right
  3. Select Site settings
  4. Under Users and Permissions, click Site Collection Administrators
  5. In the text box, enter the HR Director's email (e.g., hr.director@rlgbuilds.com)
  6. Click OK

Verify:

# Connect to SharePoint
.\Connect-SharePoint.ps1 -SiteUrl "https://rlgbuilds.sharepoint.com/sites/RLGManagers"

# Check who has Site Collection Admin rights
Get-PnPSiteCollectionAdmin

You should see:

  • Your account (IT admin)
  • HR Director's account
  • Any other administrators

✅ Checklist:

  • HR Director is listed as Site Collection Administrator
  • HR Director can access the site
  • After running script, HR Director can access all folders

5. Active Directory Cleanup

⚠️ IMPORTANT: Before running, ask HR to ensure:

  • Terminated employees with direct reports have been reassigned to active managers
  • Disabled accounts are not in manager positions with active reports
  • Bill Rudolph (CEO) is at the top of the org chart

Why? The script grants permissions via Microsoft 365. Disabled/unlicensed accounts will cause permission failures.


🚦 Pre-Flight Checklist

Before running the production script, verify:

1. Site Collection Administrators Configured

CRITICAL FIRST STEP - Ensure HR Director has full access:

# Connect to the site
.\Connect-SharePoint.ps1 -SiteUrl "https://rlgbuilds.sharepoint.com/sites/RLGManagers"

# Verify Site Collection Administrators
Get-PnPSiteCollectionAdmin

Confirm:

  • HR Director is listed as Site Collection Administrator
  • Your account is listed (you're running the script)
  • All required admins are listed

If HR Director is missing: Follow the steps in Prerequisites > Site Collection Administrator Setup

2. SharePoint Site Structure

Navigate to: https://rlgbuilds.sharepoint.com/sites/RLGManagers/Shared%20Documents

Confirm:

  • "General" folder exists in the Documents library
  • You have edit permissions (can create folders)

3. Working Directory & Understanding the Scripts

Navigate to the script directory:

cd "C:\Users\YourUsername\OneDrive - Rudolph Libbe Group\Scripts\OneDrive-SharePoint"

# Verify files exist
ls *.ps1

⚠️ IMPORTANT: Understanding Which Script to Run

There are multiple PowerShell scripts in this directory. Here's what each one does:

Scripts You Will Run:

Run-CompensationFolders-Production.ps1 ⭐ ← RUN THIS FOR PRODUCTION

  • This is your main production script
  • Pre-configured with correct defaults:
  • Site: RLGManagers
  • Path: General/Bonus 2025 NEW
  • Top Manager: Bill Rudolph
  • Structure: Flat
  • Shows confirmation prompts before running
  • Analyzes and displays results afterward
  • Internally calls the main engine script

Test-CompensationScript.ps1 ⭐ ← RUN THIS FOR TESTING

  • Test version that uses the JRTestTeam site
  • Safe for testing without affecting production
  • Same functionality as production script
  • Internally calls the main engine script

Scripts Called Automatically (Don't Run Directly):

New-CompensationFolderStructure.ps1 🔧 ← THE ENGINE (800+ lines)

  • DO NOT run this directly unless you know what you're doing
  • This is the main automation engine with all the logic:
  • Active Directory queries
  • Folder creation
  • Permission management
  • Graph API integration
  • Called by Run-CompensationFolders-Production.ps1 and Test-CompensationScript.ps1
  • Requires all parameters to be specified
  • Both files are needed - don't delete either one!

Connect-SharePoint.ps1 🔌 ← HELPER SCRIPT

  • Authentication helper
  • Called automatically by other scripts
  • Can run manually if you need to connect to SharePoint for troubleshooting

How They Work Together:

You run:  Run-CompensationFolders-Production.ps1
              ↓
         (Shows settings, asks for confirmation)
              ↓
         Calls: New-CompensationFolderStructure.ps1
              ↓
         (Does all the work: AD queries, folders, permissions)
              ↓
         Returns control to production script
              ↓
         (Production script shows summary and results)

Analogy:

  • New-CompensationFolderStructure.ps1 = The car engine (complex, powerful, requires expertise)
  • Run-CompensationFolders-Production.ps1 = The steering wheel and dashboard (easy to use, has defaults)

You could operate the engine directly with manual controls, but the steering wheel makes it much easier!

DO NOT DELETE:

  • ❌ Don't delete New-CompensationFolderStructure.ps1 - Nothing will work
  • ❌ Don't delete Run-CompensationFolders-Production.ps1 - You'll lose production defaults
  • ❌ Don't delete Connect-SharePoint.ps1 - Authentication will fail
  • ✅ Keep all scripts in the directory

Before production, test with a smaller department:

.\Test-CompensationScript.ps1 -TopManager "Doug.Mallette@rlgbuilds.com"

This creates a test folder in the JRTestTeam site using flat structure (default) that you can verify and delete afterward.


🚀 Running the Script

⭐ QUICK START: The command you need to run is:

.\Run-CompensationFolders-Production.ps1

DO NOT RUN New-CompensationFolderStructure.ps1 directly - it's the engine that gets called automatically!


Production Run - Step by Step

Step 1: Open PowerShell

  1. Press Windows + X
  2. Select "Windows PowerShell" or "Terminal"
  3. Navigate to script directory:
cd "C:\Users\YourUsername\OneDrive - Rudolph Libbe Group\Scripts\OneDrive-SharePoint"

Step 2: Execute Production Script

.\Run-CompensationFolders-Production.ps1

Default Settings:

  • Site: https://rlgbuilds.sharepoint.com/sites/RLGManagers
  • Path: Documents > General > Bonus 2025 NEW
  • Top Manager: Bill.Rudolph@rlgbuilds.com
  • Structure: Flat (all folders at same level - recommended)

Step 3: Review Configuration

The script will display:

========================================
Compensation Folder Creation - 2025
========================================

This script will:
  ✓ Build organizational hierarchy from AD
  ✓ Connect to SharePoint: https://rlgbuilds.sharepoint.com/sites/RLGManagers
  ✓ Create folder structure: General/Bonus 2025 NEW
  ✓ Set cascading edit permissions automatically
  ✓ Break permission inheritance for security

Configuration:
  Top-level manager: Bill.Rudolph@rlgbuilds.com
  Folder structure: Flat
    (All manager folders at same level - ensures proper navigation)

Continue? (Y/n)

Step 4: Authenticate to SharePoint

When prompted:

  1. A browser window will open
  2. Go to https://microsoft.com/devicelogin
  3. Enter the device code shown in PowerShell
  4. Sign in with your RLG Microsoft 365 account
  5. Accept the permissions prompt

Step 5: Monitor Progress

The script will show:

[Step 1/4] Building organizational hierarchy from Active Directory...
[0] Rudolph, Bill - 8 direct reports
  [1] Schaller, Jeff - 12 direct reports
    [2] Manager Name - 5 direct reports
...

[Step 2/4] Connecting to SharePoint Online...
  ✓ Connected

[Step 3/4] Creating folder structure...
  Creating root folder: General/Bonus 2025 NEW
    Root folder created/verified
  Creating folder: General/Bonus 2025 NEW/Rudolph, Bill
    SUCCESS: Created Rudolph, Bill
    Breaking permission inheritance...
    ✓ Unique permissions set (inheritance broken)
...

[Step 4/4] Applying cascading permissions...
  Security Model:
    - Each folder has unique permissions (inheritance broken)
    - Only managers in the chain can access folders
    - Site admins/owners retain access for administration

Setting permissions for: Rudolph, Bill
  Folder: General/Bonus 2025 NEW/Rudolph, Bill
  Granting edit access to 150 folders
    Granted edit to: General/Bonus 2025 NEW/Rudolph, Bill
    Granted edit to: General/Bonus 2025 NEW/Schaller, Jeff
    ...

Step 6: Review Results

========================================
Deployment Complete!
========================================
Location: https://rlgbuilds.sharepoint.com/sites/RLGManagers
Path: Documents → General/Bonus 2025 NEW

Permission Grants: 4,523
  Successful: 4,498
  Failed: 25

✓ All permissions set successfully!
Managers can now access their compensation folders.

Security:
  • Each folder has unique permissions (inheritance broken)
  • Only managers in the chain can access folders
  • Managers have EDIT permissions to modify files

Log file: CompensationFolderStructure_Log_20251120_143022.csv

📊 What to Expect

Timing

  • Small department (10-20 managers): 2-3 minutes
  • Full company (150+ managers): 10-15 minutes
  • Permission grants: ~2 seconds per folder per manager

Success Metrics

Metric Expected Action if Different
Folder creation 100% success Check SharePoint permissions
Permission grants 95%+ success Review log for failed users
Failed permissions <5% (disabled accounts) Expected - see Troubleshooting

Folder Name Handling

Special Character Sanitization: The script automatically removes characters that are invalid in SharePoint folder names:

  • Periods → Removed (e.g., "King, A.J." becomes "King, AJ")
  • Special chars → Removed: \ / : * ? " < > | # { } % ~ &

When a name is sanitized, you'll see a console message:

Sanitized folder name: 'King, A.J.' -> 'King, AJ'

Generated Files

The script creates a date and timestamped CSV log file:

CompensationFolderStructure_Log_20251120_143022.csv

Log Format:

Manager,ManagerEmail,FolderPath,Permission,Status
"Rudolph, Bill",Bill.Rudolph@rlgbuilds.com,General/Bonus 2025 NEW/Rudolph, Bill,Edit,Success
"Schaller, Jeff",Jeff.Schaller@rlgbuilds.com,General/Bonus 2025 NEW/Schaller, Jeff,Edit,Success
"Manager Name",manager@rlgbuilds.com,General/Bonus 2025 NEW/Manager Name,Edit,Failed: noResolvedUsers

Note: The Manager column shows the original AD name, while FolderPath shows the sanitized folder name created in SharePoint.


🔧 Troubleshooting

Issue: "Unable to find a default server with Active Directory Web Services running"

Cause: Not connected to VPN

Solution:

  1. Connect to RLG VPN
  2. Re-run script

Issue: "Access is denied" when creating folders

Cause: Insufficient SharePoint permissions

Solution:

  1. Verify you're a Site Owner on https://rlgbuilds.sharepoint.com/sites/RLGManagers
  2. Check with SharePoint admins to grant Site Owner role
  3. Try: Site Settings → Site Permissions → Check Members group

Issue: Many "noResolvedUsers" permission failures

Cause: Users exist in AD but not in Microsoft 365 (disabled/unlicensed accounts)

What happens:

ERROR: Failed to set permission on [folder] -
{
  "error": {
    "code": "noResolvedUsers",
    "message": "Exception of type 'Microsoft.Vroom.Exceptions.NoResolvedUsersVroomException' was thrown."
  }
}

Solution:

  1. Check the log file - it lists all failed users
  2. Review with HR - these are typically:
  3. Terminated employees still in AD
  4. Disabled accounts with direct reports
  5. Accounts without M365 licenses
  6. Options:
  7. Have HR reassign reports to active managers → re-run script
  8. Manually grant permissions in SharePoint for specific cases
  9. Accept failures for accounts that don't need SharePoint access

The script automatically retries with UPN if email fails, so most legitimate users will succeed.


Issue: "Retrying with UPN" messages for many users

Cause: AD EmailAddress doesn't match M365 identity (common in hybrid environments)

Example:

Retrying with UPN: Jim.Philo@rlgbuilds.com
✓ Granted edit to: [folder] (via UPN)

Solution: This is normal and expected. The script automatically handles this. No action needed.


Issue: Script creates "Bill Rudolph/Bill Rudolph/Bill Rudolph/..." infinitely

Cause: CEO's Manager field in AD points to himself (circular reference)

Solution: This has been fixed in the script (filters out self-references). If you still see this, the fix isn't applied - contact IT.


Issue: "General" folder not found

Cause: Root path doesn't exist in SharePoint

Solution:

  1. Verify "General" folder exists in Documents library
  2. If missing, either:
  3. Create "General" folder manually in SharePoint
  4. OR edit production script to use different path (edit line 98)

Issue: Want to see detailed troubleshooting output

Solution: Run with -Verbose flag:

.\Run-CompensationFolders-Production.ps1 -Verbose

This shows:

  • HTTP requests/responses
  • Graph API calls
  • Detailed error messages
  • CSOM operations

✔️ Post-Run Verification

1. Check SharePoint Structure

Navigate to: https://rlgbuilds.sharepoint.com/sites/RLGManagers/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FRLGManagers%2FShared%20Documents%2FGeneral%2FBonus%202025%20NEW

Verify:

  • All expected manager folders exist
  • Folders show lock icon (unique permissions)
  • Folders are all at the same level (flat structure)

2. Spot-Check Permissions

Pick 2-3 random managers and verify:

Example: Check "Manager Name"

  1. Right-click folder → Manage access
  2. Confirm:
  3. Manager has Edit access
  4. Manager's boss has Edit access
  5. Manager's boss's boss has Edit access
  6. Other unrelated managers do not appear

3. Review Log File

Open the CSV log in Excel:

# Find latest log
Get-ChildItem CompensationFolderStructure_Log_*.csv | Sort-Object LastWriteTime -Descending | Select-Object -First 1

Review:

  • Success rate is >95%
  • Failed users are expected (disabled accounts)
  • No unexpected errors

4. Verify HR Director Access (CRITICAL)

Test HR Director can access ALL folders:

  1. Have the HR Director log in to SharePoint
  2. Navigate to: Documents → General → Bonus 2025 NEW
  3. Verify they can:
  4. See ALL folders (every manager's folder)
  5. Open any folder (click into any folder)
  6. Edit/upload files in any folder
  7. Access is not blocked or restricted

If HR Director CANNOT access folders:

5. Test Access as Manager

Ask a manager to test:

  1. Navigate to SharePoint site
  2. Go to: Documents → General → Bonus 2025 NEW
  3. Verify they can:
  4. See their own folder
  5. See their subordinates' folders
  6. Edit/upload files in those folders
  7. Cannot see unrelated managers' folders

6. Rename Folder (After Verification)

Once everything is confirmed working:

  1. In SharePoint, navigate to "General"
  2. Right-click "Bonus 2025 NEW"
  3. Select Rename
  4. Change to: Bonus 2025
  5. All permissions are preserved during rename

🔀 Advanced Usage

Run for a Specific Department Only

Instead of full company, create folders for just one department:

.\Run-CompensationFolders-Production.ps1 -TopManager "dept.head@rlgbuilds.com"

Example - IT Department only:

.\Run-CompensationFolders-Production.ps1 -TopManager "Doug.Mallette@rlgbuilds.com"

⚠️ WARNING: Hierarchical structure has a critical limitation - managers cannot navigate to their folders if they don't have access to parent folders. This is a fundamental SharePoint security restriction.

If you need hierarchical structure for a specific reason:

.\Run-CompensationFolders-Production.ps1 -Structure "Hierarchical"

Flat Structure (Default - Recommended):

Bonus 2025 NEW/
├── Rudolph, Bill
├── Schaller, Jeff
├── Manager A
├── Manager B
└── Manager C
  • ✅ Managers can access their folders directly
  • ✅ No parent folder navigation required
  • ✅ Permissions work as expected

Hierarchical Structure (Not Recommended):

Bonus 2025 NEW/
└── Rudolph, Bill/
    └── Schaller, Jeff/
        ├── Manager A/
        ├── Manager B/
        └── Manager C/
  • ❌ Manager A cannot access their folder without also having access to Rudolph and Schaller's folders
  • ❌ SharePoint requires Read permission on ALL parent folders to traverse the path
  • ❌ Defeats the purpose of unique permissions per folder

Recommendation: Always use Flat structure unless you have a specific requirement and understand the navigation limitations.


Different Year

For 2026 compensation:

.\Run-CompensationFolders-Production.ps1 -Year 2026

This creates: General/Bonus 2026 NEW


Combine Multiple Options

# IT Department, Flat structure, 2026, with verbose output
.\Run-CompensationFolders-Production.ps1 `
    -TopManager "Doug.Mallette@rlgbuilds.com" `
    -Structure "Flat" `
    -Year 2026 `
    -Verbose

Test Before Production

Always test first with a small department:

# Test with IT department (smaller hierarchy)
.\Test-CompensationScript.ps1 -TopManager "Doug.Mallette@rlgbuilds.com"

Test site: Creates folders in https://rlgbuilds.sharepoint.com/sites/JRTestTeam using flat structure (default)

After verifying test works, run production script.


🔍 Technical Details

How It Works

Phase 1: Build Organizational Hierarchy

  1. Connects to Active Directory via PowerShell
  2. Queries for top-level manager (Bill Rudolph)
  3. Recursively finds all direct reports
  4. Builds tree structure with manager/subordinate relationships
  5. Filters out:
  6. Self-references (CEO reporting to self)
  7. Circular manager relationships
  8. Duplicate entries

Phase 2: Connect to SharePoint

  1. Uses Azure AD enterprise app for authentication
  2. Opens device code authentication flow
  3. Acquires Microsoft Graph API token with Sites.FullControl.All permission
  4. Establishes PnP PowerShell connection

Phase 3: Create Folder Structure

  1. Creates root folder: General/Bonus 2025 NEW
  2. For each manager with direct reports:
  3. Sanitizes display name (removes periods and invalid SharePoint characters)
  4. Creates folder named "LastName, FirstName"
  5. If hierarchical: nests under their manager's folder
  6. If flat: creates at root level
  7. Immediately breaks permission inheritance on each folder:
  8. Removes all inherited permissions
  9. Starts with clean slate (only admins have access)

Phase 4: Set Cascading Permissions

  1. For each manager in hierarchy:
  2. Identifies all folders they should access:
    • Their own folder
    • All direct reports' folders
    • All subordinates down the chain
  3. Uses Microsoft Graph API /invite endpoint to grant Edit permission:
  4. Gets folder item ID via Graph API
  5. Sends invite request with roles: ["write"]
  6. Sets requireSignIn: true (internal users only)
  7. Sets sendInvitation: false (no email notification)
  8. If email fails with "noResolvedUsers":
  9. Automatically retries with UserPrincipalName
  10. Handles AD/M365 identity mismatches
  11. Logs success/failure for each permission grant

Phase 5: Generate Report

  1. Exports CSV log with all operations
  2. Shows summary statistics
  3. Identifies any failures for manual review

Architecture

Main Script: New-CompensationFolderStructure.ps1

  • Core automation logic
  • 800+ lines of PowerShell
  • Key Functions:
  • Build-OrgHierarchy - Recursive AD tree builder
  • Get-SanitizedFolderName - Remove invalid SharePoint characters
  • New-SharePointFolderStructure - Folder creation with sanitization
  • Set-UniquePermissions - Break inheritance via CSOM
  • Initialize-GraphAPI - Get Graph tokens and site/drive IDs
  • Get-GraphFolderItem - Find folder item ID via Graph API
  • Set-CascadingPermissions - Recursive permission grants via Graph API

Wrapper Scripts:

  • Run-CompensationFolders-Production.ps1 - Production defaults
  • Test-CompensationScript.ps1 - Test site wrapper

Helper Scripts:

  • Connect-SharePoint.ps1 - Multi-method authentication
  • Find-ITManager.ps1 - Utility to find test managers

Authentication Flow

User runs script
    ↓
PnP.PowerShell requests Graph token
    ↓
Browser opens to microsoft.com/devicelogin
    ↓
User enters device code
    ↓
User signs in with M365 account
    ↓
Azure AD issues token with:
    - Audience: https://graph.microsoft.com
    - Permission: Sites.FullControl.All
    ↓
Script uses token for:
    - PnP PowerShell operations (folder creation, CSOM context)
    - Microsoft Graph API (permission granting)
    - CSOM direct manipulation (inheritance breaking only)

APIs and Methods Used

PnP PowerShell:

  • Add-PnPFolder - Create folders in document library
  • Get-PnPFolder - Retrieve folder metadata and list item IDs
  • Get-PnPContext - Get CSOM context for inheritance breaking

Microsoft Graph API:

  • GET /sites/{hostname}:{path} - Get SharePoint site ID
  • GET /sites/{siteId}/drives - Get document library drive ID
  • GET /sites/{siteId}/drives/{driveId}/root:/{path} - Get folder item ID
  • POST /sites/{siteId}/drives/{driveId}/items/{itemId}/invite - Grant permissions

CSOM (SharePoint Client Side Object Model):

  • $listItem.BreakRoleInheritance($false, $true) - Break permission inheritance

Permission Model

Folder: "Manager A"
    │
    ├── Unique Permissions (inheritance broken)
    │   ├── Site Admins: Full Control (automatic)
    │   ├── Manager A: Edit (granted by script)
    │   ├── Manager A's Boss: Edit (granted by script)
    │   └── CEO: Edit (granted by script)
    │
    └── Hidden from:
        ├── Other managers
        ├── General site members
        └── Manager A's peers

Why Graph API Instead of PnP Cmdlets?

Problem: PnP cmdlets like Set-PnPListItemPermission require SharePoint API tokens, but DeviceLogin authentication provides Graph API tokens.

Solution: Use Graph API's /invite endpoint directly, which:

  • Accepts Graph tokens (what we have)
  • Grants permissions to SharePoint items
  • Handles email resolution automatically
  • Supports retry logic for email/UPN mismatches

File Structure

OneDrive-SharePoint/
├── New-CompensationFolderStructure.ps1    # Main script (800+ lines)
├── Run-CompensationFolders-Production.ps1 # Production wrapper
├── Test-CompensationScript.ps1            # Test wrapper
├── Connect-SharePoint.ps1                 # Authentication helper
├── Find-ITManager.ps1                     # Test utility
├── SharePoint-Config.json                 # Azure AD app config
├── README-Compensation-Folders-CONSOLIDATED.md  # This file (OFFICIAL)
└── NotNeeded/                             # Archived diagnostic scripts
    ├── Test-*.ps1                         # 30+ test scripts
    └── Check-*.ps1                        # Diagnostic utilities

Logs

CSV Format:

Manager,ManagerEmail,FolderPath,Permission,Status
"Rudolph, Bill","Bill.Rudolph@rlgbuilds.com","General/Bonus 2025 NEW/Rudolph, Bill","Edit","Success"

Status Values:

  • Success - Permission granted with EmailAddress
  • Success (via UPN) - Permission granted after UPN retry
  • Failed: noResolvedUsers - User doesn't exist in M365
  • Failed: serviceNotAvailable - Temporary Microsoft API issue
  • Failed: [other error] - Other Graph API errors

📞 Support

Common Questions

Q: Can I run this script multiple times? A: Yes, but it will create duplicate folders. For updates, manually adjust permissions or delete/recreate the folder structure.

Q: What if someone's manager changes mid-year? A: Re-run the script to create a new folder structure reflecting the current org chart, or manually adjust permissions in SharePoint.

Q: Can external users see these folders? A: No. Permissions are limited to internal managers with M365 accounts. Inheritance is broken so only explicitly granted users have access.

Q: How do I delete the test folders? A: In SharePoint, navigate to the test folder → Delete. All permissions are deleted with it.

Q: What if Bill Rudolph retires and we have a new CEO? A: Update the production script (line 34) to change the default TopManager, or specify at runtime:

.\Run-CompensationFolders-Production.ps1 -TopManager "new.ceo@rlgbuilds.com"

Q: Why can't the HR Director access folders even though they're a Site Owner? A: Site Owners do not have access after the script runs because permission inheritance is broken. Only Site Collection Administrators have automatic access to all folders. To fix:

  1. Follow Prerequisites > Site Collection Administrator Setup
  2. Add HR Director as Site Collection Administrator
  3. Verify with: Get-PnPSiteCollectionAdmin

Q: Who will be able to access the compensation folders? A: Only these people:

  • ✅ Site Collection Administrators (HR Director, IT admins) - Full access to everything
  • ✅ Managers in reporting chain - Edit access to their own folder and all subordinates
  • ✅ Bill Rudolph (CEO) - Edit access to all folders (top of hierarchy)
  • ❌ Site Owners (unless also Site Collection Admins) - No access
  • ❌ Site Members - No access
  • ❌ General users - No access

Q: A new HR Director has started, what do I do? A: Add them as a Site Collection Administrator so they can access all folders:

  1. Go to: https://rlgbuilds.sharepoint.com/sites/RLGManagers
  2. Settings gear ⚙️ → Site settings
  3. Under Users and Permissions → Site Collection Administrators
  4. Add the new HR Director's email
  5. (Optional) Remove the old HR Director if they've left

Q: Why is the folder name different from the person's name in Active Directory? A: The script automatically sanitizes folder names to comply with SharePoint restrictions. For example:

  • "King, A.J." (AD) → "King, AJ" (SharePoint folder)
  • Periods, special characters like * ? " < > are removed
  • The original AD name is preserved in the CSV log under the Manager column
  • This is automatic and ensures all folders can be created successfully

Q: Why do we use flat structure instead of hierarchical? A: SharePoint has a fundamental security restriction - users cannot navigate through folders they don't have Read access to. In a hierarchical structure, even if a manager has Edit permissions on their own folder 3 levels deep, they cannot access it because they don't have Read permissions on the parent folders. Flat structure solves this by putting all folders at the same level, while still maintaining the organizational hierarchy through permissions.

Getting Help

  1. Check this README - Most issues are documented
  2. Review the log file - Shows exactly what failed
  3. Run with -Verbose - Shows detailed error messages
  4. Contact: Jeff Ricica (script author) - jeff.ricica@rlgbuilds.com

📝 Change Log

Version 2.1 (November 2025)

  • ✅ Changed default structure to Flat (was Hierarchical)
  • ✅ Updated documentation to clearly explain flat vs hierarchical limitations
  • ✅ Consolidated two separate README files into single source of truth
  • ✅ Added detailed cascading permission example with fictional org chart
  • ✅ Enhanced troubleshooting section

Version 2.0 (November 2025)

  • ✅ Automatic permission inheritance breaking for security (CSOM)
  • ✅ Email/UPN retry logic for AD/M365 mismatches
  • ✅ Self-referencing manager filter (CEO circular reference fix)
  • ✅ Hierarchical and flat folder structure support
  • ✅ Cleaner output (verbose is optional)
  • ✅ Microsoft Graph API permission grants (modern, future-proof)
  • ✅ Folder name sanitization (removes periods and special characters)
  • ✅ Comprehensive error handling and logging

Version 1.0 (2024)

  • Initial version
  • Manual permission setup required after folder creation

Last Updated: November 21, 2025 Script Author: Jeff Ricica, IT Department Script Location: C:\Users\[Username]\OneDrive - Rudolph Libbe Group\Scripts\OneDrive-SharePoint README File: README-Compensation-Folders-CONSOLIDATED.md (official version)