Skip to content

Commit

Permalink
Added Get-PnPUserProfilePhoto cmdlet
Browse files Browse the repository at this point in the history
  • Loading branch information
erwinvanhunen committed Dec 16, 2024
1 parent ab2c5d2 commit 8bc7508
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Added `-ListPermissionScopes` parameter on `Get-PnPAccessToken` cmdlet to list the current permission scopes on the current access token.
- Added `Get-PnPCopilotAgent` cmdlet that returns the Microsoft Copilot Agents in a site collection.
- Added `Get-PnPFileRetentionLabel` cmdlet to fetch the file retention labels. [#4603](https://github.com/pnp/powershell/pull/4603)
- Added `Set/Remove-PnPUserProfilePhoto` cmdlet to upload or remove the profile photo of the specified user.
- Added `Get/Set/Remove-PnPUserProfilePhoto` cmdlet to download, upload or remove the profile photo of the specified user.

### Changed

Expand Down
89 changes: 89 additions & 0 deletions documentation/Get-PnPUserProfilePhoto.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
Module Name: PnP.PowerShell
title: Get-PnPUserProfilePhoto
schema: 2.0.0
applicable: SharePoint Online
external help file: PnP.PowerShell.dll-Help.xml
online version: https://pnp.github.io/powershell/cmdlets/Get-PnPUserProfilePhoto.html
---

# Get-PnPUserProfilePhoto

## SYNOPSIS

**Required Permissions**

* Microsoft Graph API: One of ProfilePhoto.ReadWrite.All, User.ReadWrite or User.ReadWrite.All

Gets the profile picture of a user.

## SYNTAX

```powershell
Get-PnPUserProfilePhoto -Identity <AzureADUserPipeBind> [-Filename <String>] [-Connection <PnPConnection>]
```

## DESCRIPTION
This cmdlet downloads the user profile photo to the specified path and filename. If no filename has been specified it will default to the Display Name of the user with the either the extension .png or .jpeg depending on the format of the file.

## EXAMPLES

### EXAMPLE 1
```powershell
Get-PnPUserProfilePhoto -Identity "john@contoso.onmicrosoft.com"
```
Downloads the photo for the user specified to the current folder.

### EXAMPLE 2
```powershell
Get-PnPUserProfilePhoto -Identity "john@contoso.onmicrosoft.com" -Filename "john.png"
```
Downloads the photo for the user specified to the current folder and will name the file 'john.png'.

## PARAMETERS

### -Connection
Optional connection to be used by the cmdlet. Retrieve the value for this parameter by either specifying -ReturnConnection on Connect-PnPOnline or by executing Get-PnPConnection.

```yaml
Type: PnPConnection
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Filename
The path to the image file to save.
```yaml
Type: String
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Identity
The identity of the user to remove. This can be the UPN, the GUID or an instance of the user.
```yaml
Type: AzureADUserPipeBind
Parameter Sets: (All)

Required: True
Position: Named
Default value: None
Accept pipeline input: True (ByValue)
Accept wildcard characters: False
```
## RELATED LINKS
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
106 changes: 106 additions & 0 deletions src/Commands/UserProfiles/GetUserProfilePhoto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using AngleSharp.Io;
using PnP.Framework.Diagnostics;
using PnP.PowerShell.Commands.Attributes;
using PnP.PowerShell.Commands.Base;
using PnP.PowerShell.Commands.Base.PipeBinds;
using PnP.PowerShell.Commands.Utilities;
using System.IO;
using System.Management.Automation;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace PnP.PowerShell.Commands.UserProfiles
{
[Cmdlet(VerbsCommon.Get, "PnPUserProfilePhoto")]
[RequiredApiDelegatedOrApplicationPermissions("graph/ProfilePhoto.ReadWrite.All")]
[RequiredApiDelegatedPermissions("graph/User.ReadWrite")]
[RequiredApiDelegatedOrApplicationPermissions("graph/User.ReadWrite.All")]
public class GetUserProfilePhoto : PnPGraphCmdlet
{
[Parameter(Mandatory = true, ValueFromPipeline = true)]
public AzureADUserPipeBind Identity;

[Parameter(Mandatory = false)]
public string Filename;

[Parameter(Mandatory = false)]
public SwitchParameter Force;


protected override void ExecuteCmdlet()
{
WriteVerbose($"Looking up user provided through the {nameof(Identity)} parameter");
Model.AzureAD.User user = Identity.GetUser(AccessToken, Connection.AzureEnvironment);

if (user == null)
{
Log.Error("Get-PnPUserProfilePhoto", $"User provided through the {nameof(Identity)} parameter could not be found");
throw new PSArgumentException($"User provided through the {nameof(Identity)} parameter could not be found");
}

WriteVerbose($"Setting profile photo for user {user.UserPrincipalName}");

if (Filename == null)
{
// retrieve the metadata first to figure out the file type
var photoData = RequestHelper.Get<PhotoMetadata>($"users/{user.Id}/photo");
if (photoData != null)
{
switch (photoData.ContentType)
{
case "image/jpeg":
{
Filename = $"{user.DisplayName}.jpg";
break;
}
case "image/png":
{
Filename = $"{user.DisplayName}.png";
break;
}
}
}
else
{
Log.Error("Get-PnPUserProfilePhoto", "Photo not found");
throw new PSArgumentException("Photo for user not found");
}
}

if (!System.IO.Path.IsPathRooted(Filename))
{
Filename = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Filename);
}

var getphoto = true;
if (File.Exists(Filename))
{
if (Force || ShouldContinue($"File {Filename} exists. Overwrite?", Properties.Resources.Confirm))
{
getphoto = true;
}
else
{
getphoto = false;
}
}
if (getphoto)
{
var response = RequestHelper.GetResponse($"users/{user.Id}/photo/$value");
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
System.IO.File.WriteAllBytes(Filename, content);
WriteObject($"File saved as: {Filename}");
}
}
}

internal class PhotoMetadata
{
[JsonPropertyName("@odata.mediaContentType")]
public string ContentType { get; set; }
}
}
}
1 change: 1 addition & 0 deletions src/Commands/Utilities/Microsoft365GroupsUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using PnP.PowerShell.Commands.Utilities.REST;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
Expand Down

0 comments on commit 8bc7508

Please sign in to comment.