# Personnalisation des runbooks

## Vue d’ensemble

L’implémentation des runbooks RealmJoin offre des capacités de personnalisation à l’auteur d’un runbook ou à l’administrateur d’un environnement, afin qu’ils puissent :

* Héberger des paramètres et des modèles spécifiques au client/tenant
* Proposer des éléments d’interface utilisateur comme des sélecteurs d’utilisateurs ou des listes déroulantes
* Présenter des explications lisibles par l’humain des paramètres
* Masquer les éléments d’interface utilisateur inutiles

<figure><img src="https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2FmVmZrDFgG1ShkZlo1Fbe%2Fimage.png?alt=media&#x26;token=39876732-3578-41d2-acf1-8571bb941e68" alt=""><figcaption></figcaption></figure>

Les personnalisations peuvent être incluses dans le runbook lui-même et/ou stockées dans l’instance RealmJoin Portal du client. Par défaut, nous essaierons de proposer des valeurs par défaut pertinentes dans les runbooks proposés sur [GitHub](https://github.com/realmjoin/realmjoin-runbooks).

Certains runbooks seront fournis avec des exemples montrant comment configurer des modèles spécifiques au client, par exemple en précisant les bureaux de l’utilisateur lors de l’intégration.

### Formater

La personnalisation peut être définie (par ordre décroissant de priorité)

* Bloc de JSON dans [Paramètres de RealmJoin Portal](https://portal.realmjoin.com/settings/runbooks-customizations), en remplaçant le comportement par défaut du runbook
* Bloc de JSON dans l’en-tête d’un runbook

De plus (avec la plus faible priorité)

* par paramètre dans l’en-tête du runbook
* par paramètre dans le bloc de paramètres des runbooks (en utilisant le module RJRb Helper)

Certaines fonctionnalités (comme les modèles) ne sont disponibles qu’au format JSON. Certaines fonctionnalités (comme la création d’un sélecteur d’utilisateur) ne sont disponibles qu’en spécifiant un type de données dans le bloc de paramètres. Vous pouvez combiner plusieurs types de personnalisations pour obtenir de meilleurs résultats.

## Bloc de paramètres du runbook

RealmJoin Portal analyse le bloc de paramètres PowerShell d’un runbook pour déterminer quels champs de saisie afficher. Lorsque c’est possible, il validera aussi les entrées selon le type .NET fourni pour une variable.

Les types de données suivants sont actuellement compris :

* `[bool]`, `[boolean]` - affichera un interrupteur binaire
* `[string]` - affichera une zone de texte permettant de saisir toute entrée alphanumérique
* `[int]` - affichera une zone de texte, n’autorisant que les entrées numériques
* `[DateTime]`, `[DateTimeOffset]` - affichera un sélecteur de date/heure

Vous pouvez appliquer les modificateurs PowerShell standard aux paramètres. RealmJoin Portal, en particulier, comprendra si vous spécifiez `[Parameter(Mandatory = $true)]` pour indiquer un paramètre obligatoire et imposer que ces paramètres soient renseignés.

Lorsque c’est possible, RealmJoin Portal lira aussi et affichera dans l’interface les valeurs par défaut fournies.

Attention, les valeurs par défaut du runbook peuvent être remplacées par des personnalisations. De plus, les paramètres peuvent être complètement masqués par des personnalisations.

### Personnalisation des paramètres

Pour pouvoir personnaliser les paramètres, veuillez vous assurer d’inclure le module PS Runbook Helper de RealmJoin dans votre runbook :

`#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.6.0" }`

Vous pouvez ensuite inclure `[ValidateScript( { Use-RJInterface ... } )]` des instructions dans les définitions de paramètres. Par exemple, ce qui suit créera un sélecteur d’utilisateur, permettant de choisir un utilisateur Entra ID et transmettra son ID d’objet sous forme de chaîne au runbook.

```powershell
param(
    [ValidateScript( { Use-RJInterface -DisplayName "Attribuer l’appareil à cet utilisateur (facultatif)" -Type Graph -Entity User } )]
    [string] $AssignedUserId = ""
)
```

Prenons cela morceau par morceau. `[ValidateScript...]` est un modificateur pour le paramètre suivant défini dans le bloc param. Dans ce cas, la variable `$AssignedUserId`.

`Use-RJInterface` fait partie de notre [module PowerShell RealmJoin Runbook Helper](https://github.com/realmjoin/RealmJoin.RunbookHelper) Il vous permet de spécifier le type d’entrée attendu en utilisant `-Type` et `-Entity`si cela n’est pas déjà entièrement défini par le type de la variable.

`-DisplayName` vous permet de transmettre à RealmJoin Portal une invite / description lisible par l’humain pour ce paramètre.

#### Ressources Graph

Dans l’exemple ci-dessus, la source d’information est MS Graph, comme indiqué par `-Type Graph`. Pour MS Graph, utilisez `-Entity` pour spécifier le type de ressource attendu. Les entités disponibles sont `utilisateurs`, `Groupe`, `Appareil`. Cela produira un sélecteur pour les utilisateurs, groupes ou appareils dans l’Entra ID donné.

Le sélecteur inclut une recherche rapide, pour retrouver facilement la ressource requise.

![Exemple de sélecteur](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-0c393c4ea73a77b34da2c678b0712a6556ed3bc2%2Frunbook-customization-img2.png?alt=media)

Actuellement, la sélection multiple n’est pas possible avec un sélecteur.

Par défaut, un sélecteur MS Graph renverra l’ID de l’objet. Si vous avez besoin par exemple du nom principal d’utilisateur à la place, veillez à inclure "name" comme suffixe dans le nom de votre variable. Donc, pour obtenir l’ID d’un utilisateur, nommez le paramètre `$userid`. Si vous voulez un UPN, nommez-le `$username`.

#### Filtrage Graph

Si vous utilisez un sélecteur basé sur MS Graph, vous pouvez aussi spécifier `-Filter` et utiliser un [filtre ODATA](https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0\&view=graph-rest-1.0#filter-parameter) pour limiter les objets proposés dans le sélecteur.

L’exemple suivant n’affichera que les groupes d’Entra ID commençant par "LIC\_".

```powershell
param(
    [Parameter(Mandatory = $true)]
    [ValidateScript( { Use-RJInterface -Type Graph -Entity Group -Filter "startswith(DisplayName, 'LIC_')" -DisplayName "Groupe de licences" } )]
    [String] $GroupID_License
)
```

Vous pouvez préparer des filtres et les réutiliser dans plusieurs scripts en utilisant le [magasin de données central](#graph-filters). Dans ce cas, il suffit de référencer le filtre par son nom en utilisant `-Filter "ref:LicenseGroup"`, où `ref:` indique qu’il faut rechercher un filtre stocké.

```powershell
param(
    [Parameter(Mandatory = $true)]
    [ValidateScript( { Use-RJInterface -Type Graph -Entity Group -Filter "ref:LicenseGroup" } )]
    [String] $GroupID_License
)
```

Cet exemple spécifique `ref:LicenseGroup` est disponible par défaut sans configuration supplémentaire.

![filtre ODATA](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-4913ddfbc3324fc7a3522de2bc6887e8d2745e35%2Frunbook-customization-img3.png?alt=media)

## En-tête du runbook

Le portail peut analyser la [aide basée sur les commentaires](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help?view=powershell-5.1) d’un runbook, si elle est présente.

Voici un exemple :

```powershell
<#
  .SYNOPSIS
  Attribuer (ou retirer) une licence à un utilisateur via l’appartenance à un groupe.

  .DESCRIPTION
  Attribuer (ou retirer) une licence à un utilisateur via l’appartenance à un groupe. Description plus détaillée...

  .PARAMETER DefaultGroups
  Liste séparée par des virgules des groupes à attribuer. par ex. "DL Sales,LIC Internal Product"

  .NOTES
  Autorisations :
  MS Graph (API) :
  - User.Read.All
  - GroupMember.ReadWrite.All 
  - Group.ReadWrite.All

  .INPUTS
  RunbookCustomization: {
        "Parameters" : {
            "UserName": {
                "Hide": true
            },
            "Remove": {
                "DisplayName": "Attribuer ou supprimer une licence",
                "SelectSimple": {
                    "Attribuer une licence à l’utilisateur": false,
                    "Supprimer la licence de l’utilisateur": true
                }
            }
        }
    }
#>
```

`.SYNOPSIS` - Donner une description très brève de la fonction de votre runbook. Elle sera affichée dans la liste des runbooks disponibles.

`.DESCRIPTION` - Donner une description de la fonction de votre runbook. Peut contenir un peu plus de détails, car elle sera affichée dans la boîte de dialogue d’exécution / de paramètres du runbook.

`.PARAMETER` - Doit être suivi du nom d’un paramètre. Vous permet de donner une explication détaillée de l’entrée attendue pour le paramètre concerné.

`.INPUTS` - Peut contenir un bloc de personnalisation de runbook basé sur JSON.

`.NOTES` - N’est pas analysé / rendu. Veuillez utiliser cet espace pour noter quelles autorisations et exigences existent pour votre runbook.

`.EXAMPLE` - N’est pas analysé / rendu. Peut contenir un exemple de personnalisation basée sur JSON à utiliser dans le magasin de données RealmJoin de votre tenant. Il peut s’agir d’exemples montrant comment créer des modèles, par exemple pour différents workflows ou classes d’utilisateurs.

## Personnalisation basée sur JSON

### Magasin de données central

Chaque tenant Azure peut héberger un magasin de données "Runbook Customizations", disponible à <https://portal.realmjoin.com/settings/runbooks-customizations> .

Le format est du JSON avec commentaires, autorisant les virgules finales. Actuellement, il y a trois sections pertinentes, `Paramètres`, `Modèles`, `Runbooks`.

```json
{
    "Settings": {
    },
    "Templates": {
    },
    "Runbooks" : {
    }
}
```

### Section Runbooks

`Runbooks` est analysée par le portail lors du lancement d’un runbook. Si une section portant le nom du Runbook Azure Automation actuel existe, son contenu sera utilisé pour personnaliser le frontend affiché à l’utilisateur.

Supposons le simple runbook de démonstration suivant, appelé `rjgit-device_demo-runbook-customizing`.

```powershell
<#
  .SYNOPSIS
  Démontrer la personnalisation d’un runbook

  .DESCRIPTION
  Démontrer la personnalisation d’un runbook, comme une liste déroulante/sélection
#>

#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.6.0" }

param(
    [string] $DeviceId,
    [bool] $ExtraWorkflow = $true,
    [int] $ExtraWorkflowTime = 15
)

"## Faire des choses sur l’appareil '$DeviceID'"

# Flux de travail complexe très optionnel
if ($ExtraWorkflow) {
    "## Exécution de la méditation..."
    Start-Sleep -Seconds $ExtraWorkflowTime
}
```

Si elle n’est pas personnalisée, elle sera présentée comme ceci dans le frontend :

![Démo - avant](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-931b958f4b949268736f6ff3f174913cf56adcf7%2Frunbook-customization-img4.png?alt=media)

Réflexions :

* Comme ce runbook est lancé depuis le contexte d’un appareil dans le portail, le `$DeviceId` est une information redondante pour un utilisateur. Je sais déjà sur quel appareil je travaille.
* Que se passe-t-il si j’active ou désactive le "Flux de travail supplémentaire" ? Dois-je me préoccuper du "Temps du flux de travail supplémentaire" si je désactive le "Flux de travail supplémentaire" ?

Améliorons cela. Le JSON d’exemple suivant dans le magasin de données central modifiera l’interface utilisateur du runbook.

```json
{
    "Runbooks" : {
        "rjgit-device_demo-runbook-customizing": {
            "ParameterList": [
                {
                    "Name": "DeviceId",
                    "Hide": true
                }, 
                {
                    "Name": "ExtraWorkflow",
                    "Hide": true
                },
                {
                    "Name": "ExtraWorkflowTime",
                    "DisplayName": "Combien de temps méditer ?",
                },
                {
                    "DisplayName": "Exécuter le flux de travail supplémentaire",
                    "DisplayBefore": "ExtraWorkflowTime",
                    "Select": {
                        "Options": [
                            {
                                "Display": "Exécuter la méditation (facultatif)",
                                "Customization": {
                                    "Default": {
                                        "ExtraWorkflow": true
                                    }
                                }
                            },
                            {
                                "Display": "Passer la pleine conscience de l’appareil",
                                "Customization": {
                                    "Default": {
                                        "ExtraWorkflow": false
                                    },
                                    "Hide": [
                                        "ExtraWorkflowTime"
                                    ]
                                }
                            }
                        ],
                        
                    },
                    "Default": "Passer la pleine conscience de l’appareil"
                }
            ]
        }
    }
}
```

Vous pouvez utiliser la même notation / les mêmes fonctionnalités dans votre [en-tête du runbook](#runbook-header).

#### ParameterList

Chaque paramètre a sa propre section dans `ParameterList`. [Modificateurs](#modifiers) permettent de changer le comportement de ce paramètre.

Le résultat ressemblera à ceci :

![Démo - après masquage](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-4ae4e681371ad29f076063c5f1925a0cb8113872%2Frunbook-customization-img5.png?alt=media)

Le choix du flux de travail supplémentaire affichera (dévoilera) d’autres paramètres :

![Démo - après dévoilement](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-7960cf8309d8bbdf12ab1539c073714211715411%2Frunbook-customization-img6.png?alt=media)

Cela montre moins d’encombrement par rapport à l’état précédent l’application de la personnalisation. En même temps, davantage d’informations sur les alternatives au "Flux de travail supplémentaire" sont disponibles pour l’utilisateur. De plus, l’utilisateur ne se préoccupera désormais du "Temps du flux de travail supplémentaire" que si cela est pertinent.

Changer la visibilité de ce champ a été fait à l’aide d’un `"Customization"` bloc dans l’une des options `"Select"` . Vous pouvez actuellement n’avoir qu’un seul tel `"Customization"` bloc actif à la fois.

Comme vous pouvez le voir, le paramètre `$DeviceId` est complètement masqué. Cela se fait en définissant le `"Hide": true` pour ce paramètre.

Les paramètres peuvent avoir un `DisplayName`. Nous avons proposé un `DisplayName` convivial pour remplacer `$ExtraWorkflowTime` dans l’interface utilisateur. Voir les autres [modificateurs](#modifiers) pour en savoir plus.

Vous pouvez insérer des paramètres "sans nom" (en omettant l’instruction `Nom` comme la section "Exécuter le flux de travail supplémentaire", si vous souhaitez proposer des éléments d’interface utilisateur sans renvoyer directement une valeur. Cela n’est normalement utilisé qu’en combinaison avec `Sélectionnez`.

#### Sélectionnez

Nous avons utilisé `Sélectionnez`, pour afficher une liste de `Options` dans une liste déroulante. Chaque option peut `Affichage` texte, ou déclencher un `Personnalisation`, comme définir `Hide` ou une valeur `Default` sur d’autres paramètres. Dans notre exemple, nous l’avons utilisé pour (dé)masquer `$ExtraWorkflowTime` et remplacer `$ExtraWorkflow`valeur.

`$ExtraWorkflowTime` est donc affiché uniquement lorsque cela est pertinent et l’interrupteur binaire `$ExtraWorkflow` est maintenant remplacé par des alternatives significatives du point de vue de l’utilisateur.

Dans le cas d’un `Sélectionnez` pour un paramètre nommé, chaque option doit avoir un `"ParameterValue": "..."` à transmettre au runbook. Vous pouvez placer un `"ShowValue: false"` dans le `Sélectionnez` bloc pour n’afficher que la liste déroulante et pas de champ pour la valeur résultante du paramètre.

Exemple de paramètre nommé :

```json
{
    "Name": "ExtraWorkflow",
    "DefaultValue": true,
    "DisplayName": "Exécuter le flux de travail supplémentaire",
    "DisplayBefore": "ExtraWorkflowTime",
    "Select": {
        "Options": [
            {
                "Display": "Exécuter la méditation (facultatif)",
                "ParameterValue": true
            },
            {
                "Display": "Passer la pleine conscience de l’appareil",
                "ParameterValue": false,
                "Customization": {
                    "Hide": [
                        "ExtraWorkflowTime"
                    ]
                }
            }
        ],
        "ShowValue": false
    }
}
```

Le `Default` / `DefaultValue` instruction dans le paramètre spécifie également l’état initial de la liste déroulante. Dans le cas d’un paramètre sans nom, utilisez la `DisplayName` de l’option souhaitée, sinon donnez une valeur de retour par défaut, comme "true" ou "false" ou une chaîne quelconque.

#### Paramètres

Si vous n’avez que des paramètres nommés, vous pouvez utiliser le format légèrement plus court `Paramètres` à la place de `ParameterList`.

Pour un exemple, voir SelectSimple

#### SelectSimple

Si toute la puissance d’un `Sélectionnez` n’est pas nécessaire et que vous souhaitez simplement proposer une liste de valeurs possibles dans une liste déroulante (sans appliquer de personnalisation supplémentaire), vous pouvez utiliser `SelectSimple`.

`SelectSimple` n’est utilisable que pour les paramètres nommés.

Exemple :

```json
{
    "Runbooks" : {
        "rjgit-device_demo-runbook-customizing": {
            "Parameters" : {
                "DeviceId": {
                    "Hide": true
                }, 
                "ExtraWorkflow": {
                    "Name": "ExtraWorkflow",
                    "DisplayName": "Exécuter le flux de travail supplémentaire",
                    "Default": false,
                    "SelectSimple": {
                        "Execute Meditation (optional)": true,
                        "Skip Device Mindfulness": false
                    }
                },
                "ExtraWorkflowTime": {
                    "DisplayName": "Combien de temps méditer ?"
                }
            }
        }
    }
}
```

La plus grande différence (outre le fait d’être beaucoup plus court) par rapport à notre exemple précédent est que `$ExtraWorkflowTime` est toujours visible.

#### Modificateurs

Chaque paramètre peut avoir un ou plusieurs des modificateurs suivants :

* `"DisplayName": "texte"` - Afficher "texte" comme nom du paramètre dans l’interface utilisateur
* `"Hide": true / false` - Masquer ce paramètre
* `"Mandatory": true / false` - Exiger que ce paramètre soit renseigné
* `"ReadOnly": true / false` - Empêcher la modification de ce paramètre par rapport à sa valeur par défaut
* `"DefaultValue": "..."` - Définir une valeur par défaut pour ce paramètre. (Vous pouvez aussi utiliser `Default` à la place.)
* `"GraphFilter": "startswith(DisplayName, 'LIC_')"` - voir [Filtrage Graph](#graph-filtering)
* `"AllowEdit": true / false` - Empêcher la modification manuelle de ce paramètre. (à combiner avec les modèles)

### Paramètres

`Paramètres` vous permet de stocker des données de configuration comme des noms de comptes de stockage Azure à un emplacement central, tout en les gardant séparées de vos runbooks.

Vous pouvez accéder à des valeurs individuelles d’un bloc de paramètres de runbook en utilisant `Use-RJInterface`.

Prenons cet exemple de bloc param d’un runbook :

```powershell
param(
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.Container" } )]
    [string] $ContainerName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.ResourceGroup" } )]
    [string] $ResourceGroupName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Name" } )]
    [string] $StorageAccountName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Location" } )]
    [string] $StorageAccountLocation,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Sku" } )]
    [string] $StorageAccountSku
)
```

Le portail essaiera de préremplir chaque paramètre avec les valeurs du magasin de données central - si elles sont présentes. Cela fonctionne aussi si le paramètre a été masqué dans l’interface utilisateur.

Un JSON possible dans le magasin de données pour ce runbook serait :

```json
{
    "Settings": {
        "CaPoliciesExport": {
            "ResourceGroup": "rj-runbooks-01",
            "StorageAccount": {
                "Name": "rjrbexports01",
                "Location": "West Europe",
                "Sku": "Standard_LRS"
            }
        }
    }
}
```

Le `Container` élément manquant ne sera simplement pas prérempli dans l’interface utilisateur.

### Modèles

`Modèles` utiliser des références JSON pour importer des données - par exemple une longue liste d’emplacements de bureaux - lors de l’utilisation d’une `Sélectionnez` instruction.

Cela permet de garder une personnalisation neutre/réutilisable/séparée des données réelles.

Prenons l’exemple de l’intégration de nouveaux utilisateurs. Vous pouvez avoir plusieurs options pour les départements ou les emplacements de bureaux, où l’attribution d’un emplacement de bureau impose aussi une certaine adresse, un pays, un état, etc.

L’exemple suivant d’une personnalisation de runbook utilise la section `$ref` dans le `Runbooks` pour référencer/importer un sous-arbre depuis la section `Modèles` . Recherchez les mots-clés `$id`/`$values` . Sachez que `$id`/`$values` doivent être définis avant d’être référencés à l’aide de `$ref`. C’est pourquoi `Modèles` est défini avant `Runbooks` dans cet exemple.

Dans cet exemple, nous indiquons au portail de récupérer le sous-arbre avec le `$id` appelé `LocationOptions` et d’inclure ses `$values`, en remplaçant l’instruction `$ref` . Ainsi, le portail affichera un `Sélectionnez` comme décrit dans la section `Runbooks` mais inclura les options réelles de `Modèles`.

Un modèle peut contenir toute instruction prise en charge à l’endroit de référencement. Dans cet exemple, nous utilisons une instruction `Personnalisation` pour modifier d’autres paramètres comme `StreetAddress`.

Ainsi, nous pouvons avoir une personnalisation spécifique au runbook dans `Runbooks` réutilisable dans plusieurs environnements, tout en gardant les données réelles séparées.

```json
{
    "Templates": {
        "Options": [
            {
                "$id": "LocationOptions",
                "$values": [
                    {
                        "Display": "DE-OF",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Kaiserstraße 39",
                                "PostalCode": "63065",
                                "City": "Offenbach",
                                "Country": "Germany"
                            }
                        }
                    },
                    {
                        "Display": "DE-DEG",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Lateinschulgassse 24-26",
                                "PostalCode": "94469",
                                "City": "Deggendorf",
                                "Country": "Germany"
                            }
                        }
                    },
                    {
                        "Display": "DE-HH",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Hans-Henny-Jahnn-Weg 53",
                                "PostalCode": "22085",
                                "City": "Hamburg",
                                "Country": "Germany"
                            }
                        }
                    },
                    {
                        "Display": "FI-HS",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Somewhere 42",
                                "PostalCode": "12345",
                                "City": "Helsinki",
                                "Country": "Finland"
                            }
                        }
                    }
                ]
            },
            {
                "$id": "CompanyOptions",
                "$values": [
                    {
                        "Id": "gkg",
                        "Display": "glueckkanja",
                        "Value": "glueckkanja AG"
                    },
                    {
                        "Id": "pp",
                        "Display": "PRIMEPULSE",
                        "Value": "PRIMEPULSE SE"
                    }
                ]
            }
        ]
    },
    "Runbooks" : {
        "rjgit-org_general_add-user": {
            "ParameterList": [
                {
                    "DisplayName": "Emplacement du bureau",
                    "DisplayAfter": "CompanyName",
                    "Select": {
                        "Options": {
                            "$ref": "LocationOptions"
                        }
                    }
                },
                {
                    "Name": "CompanyName",
                    "Select": {
                        "Options": {
                            "$ref": "CompanyOptions"
                        },
                        "AllowEdit": false
                    }
                }
            ],
            "ReadOnly": [
                "StreetAddress",
                "PostalCode",
                "City",
                "Country"
            ]
        }
    }
}
```

Cela créera l’interface utilisateur suivante :

![Démo - ref-location](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-93295541748dcc12dbc72208851138efd0808d51%2Frunbook-customization-img7.png?alt=media)

![Démo - ref-address](https://1100180853-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkrcM7cKOpXKri1kVrh%2Fuploads%2Fgit-blob-11e2812670e56cf10bb03fe7588059d232a8addf%2Frunbook-customization-img8.png?alt=media)

### Filtres Graph

Vous pouvez préparer des [filtres Graph ODATA](https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0\&view=graph-rest-1.0#filter-parameter) à utiliser dans plusieurs runbooks. Stockez-les dans une section appelée `GraphFilters`.

L’exemple suivant filtre un certain préfixe dans le `DisplayName` d’un groupe, afin d’afficher uniquement les groupes liés aux licences dans un sélecteur de groupes.

```json
"GraphFilters": {
    "LicenseGroup": "startswith(DisplayName, 'LIC_')" // également inclus dans le code RJ par défaut
  }
```

Voir [filtrage Graph](#graph-filtering) sur la manière d’utiliser cela depuis un runbook.
