Skip to content

Commit

Permalink
Adding Set-PnPSearchExternalItem to allow for indexing custom conte…
Browse files Browse the repository at this point in the history
…nt into Microsoft Search (#3420)

* Added functionality

* Adding PR reference

* Changed parameter name from Id to ItemId to clarify its the Id of the external item, added constraint of maximum 128 characters for the itemid

* Fixing build error

---------

Co-authored-by: Gautam Sheth <[email protected]>
  • Loading branch information
KoenZomers and gautamdsheth authored Sep 28, 2023
1 parent b419e21 commit 664c383
Show file tree
Hide file tree
Showing 12 changed files with 642 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Added `Get-PnPFlowOwner` cmdlet which allows retrieving the owners of a Power Automate flow [#3314](https://github.com/pnp/powershell/pull/3314)
- Added `-AvailableForTagging` to `Set-PnPTerm` which allows the available for tagging property on a Term to be set [#3321](https://github.com/pnp/powershell/pull/3321)
- Added `Get-PnPPowerPlatformConnector` cmdlet which allows for all custom connectors to be retrieved [#3309](https://github.com/pnp/powershell/pull/3309)
- Added `Set-PnPSearchExternalItem` cmdlet which allows ingesting external items into the Microsoft Search index for custom connectors. [#3420](https://github.com/pnp/powershell/pull/3420)
- Added `Get-PnPTenantInfo` which allows retrieving tenant information by its Id or domain name [#3414](https://github.com/pnp/powershell/pull/3414)
- Added option to create a Microsft 365 Group with dynamic membership by passing in `-DynamicMembershipRule` [#3426](https://github.com/pnp/powershell/pull/3426)
- Added option to pass in a Stream or XML string to `Read-PnPTenantTemplate` allowing the tenant template to be modified before being applied. [#3431](https://github.com/pnp/powershell/pull/3431)
- Added `Get-PnPTenantInfo` which allows retrieving tenant information by its Id or domain name. [#3414](https://github.com/pnp/powershell/pull/3414)
- Added option to create a Microsoft 365 Group with dynamic membership by passing in `-DynamicMembershipRule` [#3426](https://github.com/pnp/powershell/pull/3426)
Expand Down
228 changes: 228 additions & 0 deletions documentation/Set-PnPSearchExternalItem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
---
Module Name: PnP.PowerShell
schema: 2.0.0
applicable: SharePoint Online
online version: https://pnp.github.io/powershell/cmdlets/Set-PnPSearchExternalItem.html
external help file: PnP.PowerShell.dll-Help.xml
title: Set-PnPSearchExternalItem
---

# Set-PnPSearchExternalItem

## SYNOPSIS
Adds or updates an external item in Microsoft Search

## SYNTAX

```powershell
Set-PnPSearchExternalItem -ItemId <String> -ConnectionId <String> -Properties <Hashtable> [-ContentValue <String>] [-ContentType <SearchExternalItemContentType>] [-GrantUsers <AzureADUserPipeBind[]>] [-GrantGroups <AzureADGroupPipeBind[]>] [-DenyUsers <AzureADUserPipeBind[]>] [-DenyGroups <AzureADGroupPipeBind[]>] [-GrantExternalGroups <String[]>] [-DenyExternalGroups <String[]>] [-GrantEveryone <SwitchParameter>] [-Verbose] [-Connection <PnPConnection>]
```

## DESCRIPTION

This cmdlet can be used to add or update an external item in Microsoft Search on custom connectors. The cmdlet will create a new external item if the item does not exist yet. If the item already exists, it will be updated.

## EXAMPLES

### EXAMPLE 1
```powershell
Set-PnPSearchExternalItem -ConnectionId "pnppowershell" -ItemId "12345" -Properties @{ "Test1"= "Test van deze PnP PowerShell Connector"; "Test2" = "Red","Blue"; "Test3" = ([System.DateTime]::Now)} -ContentValue "Sample value" -ContentType Text -GrantEveryone
```

This will add an item in the external Microsoft Search index with the properties as provided and grants everyone access to find the item back through Microsoft Search.

### EXAMPLE 2
```powershell
Set-PnPSearchExternalItem -ConnectionId "pnppowershell" -ItemId "12345" -Properties @{ "Test1"= "Test van deze PnP PowerShell Connector"; "Test2" = "Red","Blue"; "Test3" = ([System.DateTime]::Now)} -ContentValue "Sample value" -ContentType Text -GrantUsers "[email protected]"
```

This will add an item in the external Microsoft Search index with the properties as provided and grants only the user with the specified UPN access to find the item back through Microsoft Search.

## 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
```
### -ItemId
Unique identifier of the external item in Microsoft Search. You can provide any identifier you want to identity this item. This identifier will be used to update the item if it already exists.
```yaml
Type: String
Parameter Sets: (All)
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ConnectionId
The Connection ID of the custom connector to use. This is the ID that was entered when registering the custom connector and will indicate for which custom connector this external item is being added to the Microsoft Search index.
```yaml
Type: String
Parameter Sets: (All)
Required: True
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Properties
A hashtable with all the managed properties you want to provide for this external item. The key of the hashtable is the name of the managed property, the value is the value you want to provide for this managed property. The value can be a string, a string array or a DateTime object.
```yaml
Type: Hashtable
Parameter Sets: (All)
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ContentValue
A summary of the content that is being indexed. Can be used to display in the search result.
```yaml
Type: String
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ContentType
Defines the type of content used in the ContentValue attribue. Defaults to Text.
```yaml
Type: SearchExternalItemContentType
Parameter Sets: (All)
Accepted values: Text, Html
Required: False
Position: Named
Default value: Text
Accept pipeline input: False
Accept wildcard characters: False
```
### -GrantUsers
When provided, the external item will only be shown to the users provided through this parameter. It can contain one or multiple users by providing AzureADUser objects, user principal names or Entra user IDs.
```yaml
Type: AzureADUserPipeBind[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -GrantGroups
When provided, the external item will only be shown to the users which are members of the groups provided through this parameter. It can contain one or multiple groups by providing AzureADGroup objects, group names or Entra group IDs.
```yaml
Type: AzureADGroupPipeBind[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DenyUsers
When provided, the external item not be shown to the users provided through this parameter. It can contain one or multiple users by providing AzureADUser objects, user principal names or Entra user IDs.
```yaml
Type: AzureADUserPipeBind[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DenyGroups
When provided, the external item will not be shown to the users which are members of the groups provided through this parameter. It can contain one or multiple groups by providing AzureADGroup objects, group names or Entra group IDs.
```yaml
Type: AzureADGroupPipeBind[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -GrantExternalGroups
When provided, the external item will be shown to the groups provided through this parameter. It can contain one or multiple users by providing the external group identifiers.
```yaml
Type: String[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DenyExternalGroups
When provided, the external item will not be shown to the groups provided through this parameter. It can contain one or multiple users by providing the external group identifiers.
```yaml
Type: String[]
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -GrantEveryone
When provided, the external item will be shown to everyone.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Verbose
When provided, additional debug statements will be shown while executing the cmdlet.
```yaml
Type: SwitchParameter
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
## RELATED LINKS
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
19 changes: 19 additions & 0 deletions src/Commands/Enums/SearchExternalItemAclAccessType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace PnP.PowerShell.Commands.Enums
{
/// <summary>
/// Contains the possible ACL access types for external items to define if the ACL instructs a grant or deny
/// </summary>
/// <seealso cref="https://learn.microsoft.com/graph/api/resources/externalconnectors-acl#properties"/>
public enum SearchExternalItemAclAccessType : short
{
/// <summary>
/// Grants access
/// </summary>
Grant = 0,

/// <summary>
/// Denies access
/// </summary>
Deny = 1
}
}
34 changes: 34 additions & 0 deletions src/Commands/Enums/SearchExternalItemAclType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace PnP.PowerShell.Commands.Enums
{
/// <summary>
/// Contains the possible types of ACLs that can be set on external items to define to what type of object the access will be provided
/// </summary>
/// <seealso cref="https://learn.microsoft.com/graph/api/resources/externalconnectors-acl#properties"/>
public enum SearchExternalItemAclType : short
{
/// <summary>
/// Access will be provided to a user
/// </summary>
User = 0,

/// <summary>
/// Access will be provided to a group
/// </summary>
Group = 1,

/// <summary>
/// Access will be provided to everyone
/// </summary>
Everyone = 2,

/// <summary>
/// Access will be provided to everyone except external users
/// </summary>
EveryoneExceptExternalUsers = 3,

/// <summary>
/// Access will be provided to an external group
/// </summary>
ExternalGroup = 4
}
}
19 changes: 19 additions & 0 deletions src/Commands/Enums/SearchExternalItemContentType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace PnP.PowerShell.Commands.Enums
{
/// <summary>
/// Contains the possible content types for the search external item to define the type of content it contains
/// </summary>
/// <seealso cref="https://learn.microsoft.com/graph/api/resources/externalconnectors-externalitemcontent#properties"/>
public enum SearchExternalItemContentType : short
{
/// <summary>
/// The content is HTML
/// </summary>
Html = 0,

/// <summary>
/// The content is plain text
/// </summary>
Text = 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace PnP.PowerShell.Commands.JsonConverters;

/// <summary>
/// Custom JSON converter to convert a Hashtable to the format expected by the Microsoft Search API
/// </summary>
/// <seealso cref="https://learn.microsoft.com/graph/api/externalconnectors-externalconnection-put-items#creating-an-externalitem"/>
internal sealed class MicrosoftSearchExternalItemPropertyConverter : JsonConverter<Hashtable>
{
public override Hashtable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var converter = (JsonConverter<Hashtable>)options.GetConverter(typeof(Hashtable));
return converter.Read(ref reader, typeToConvert, options);
}

public override void Write(Utf8JsonWriter writer, Hashtable hashtable, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach(DictionaryEntry value in hashtable)
{
switch(value.Value)
{
case string:
writer.WritePropertyName($"{value.Key}@odata.type");
writer.WriteStringValue("String");

writer.WritePropertyName(value.Key.ToString());
writer.WriteStringValue(value.Value.ToString());
break;

case DateTime dateTime:
writer.WritePropertyName($"{value.Key}@odata.type");
writer.WriteStringValue("DateTimeOffset");

writer.WritePropertyName(value.Key.ToString());
writer.WriteRawValue($"\"{dateTime:o}\"");
break;

case IEnumerable ieNumerable:
writer.WritePropertyName($"{value.Key}@odata.type");
writer.WriteStringValue("Collection(String)");

writer.WritePropertyName(value.Key.ToString());
writer.WriteStartArray();
foreach(object item in ieNumerable)
{
writer.WriteStringValue(item.ToString());
}
writer.WriteEndArray();
break;

default:
writer.WritePropertyName(value.Key.ToString());
writer.WriteStringValue(value.Value.ToString());
break;
}
}
writer.WriteEndObject();
}
}
Loading

0 comments on commit 664c383

Please sign in to comment.