Skip to main content

add-office365-users

Adds Office 365 Users by delegating to `/add-data-source` with `api-id=shared_office365users` and action mode. Use for user profiles, managers, direct reports, people search, and profile photos.

Quellinformationen

Repository
microsoft/managed-apps
Letzte Quellaktivität
23. September 2026 um 17:51
Erkannte Sprache von SKILL.md
Englisch
Sterne
24
Forks
8

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
add-office365-users
description
Adds Office 365 Users by delegating to `/add-data-source` with `api-id=shared_office365users` and action mode. Use for user profiles, managers, direct reports, people search, and profile photos.
user-invocable
true
allowed-tools
Read, AskUserQuestion, Skill
model
sonnet
**📋 Shared Instructions: [shared-instructions.md](${CLAUDE_PLUGIN_ROOT}/shared/shared-instructions.md)** — Cross-cutting concerns. # Add Office 365 Users (Wrapper) This skill is a thin wrapper. Use `/add-data-source` as the single implementation path. ## Delegation contract Invoke `/add-data-source` with: - `api-id`: `shared_office365users` - `mode`: `action` --- # Office 365 Users: Method Selection Guide After the connector is added, import the generated service: ```typescript import { Office365UsersService } from '../../generated/services/Office365UsersService' ``` Use the V2 methods for profiles and reporting relationships: | Scenario | Method | Result | | --- | --- | --- | | Current signed-in user | `MyProfile_V2($select?)` | One `GraphUser_V1` | | Specific user by ID or UPN | `UserProfile_V2(id, $select?)` | One `GraphUser_V1` | | User's manager | `Manager_V2(id, $select?)` | One `GraphUser_V1` | | Direct reports | `DirectReports_V2(id, $select?, $top?)` | Profiles in `result.data.value` | | Search people | `SearchUserV2(searchTerm, top?, ...)` | Search response in `result.data.value` | | Profile photo | `UserPhotoMetadata(userId)`, then `UserPhoto_V2(id)` | Metadata, then binary image data | `DirectReports_V2` requires the target manager's Microsoft Entra directory ID or user principal name (UPN). For the signed-in user, call `MyProfile_V2('id,userPrincipalName')`, then pass the returned `id` or fall back to `userPrincipalName`. For a known person, pass their directory ID or UPN directly. ## Profile and direct-report pattern Request only the fields the UI needs: ```typescript const fields = [ 'id', 'displayName', 'jobTitle', 'department', 'mail', 'userPrincipalName', 'officeLocation', ].join(',') const myProfile = await Office365UsersService.MyProfile_V2( 'id,userPrincipalName', ) if (!myProfile.success) { throw new Error(myProfile.error?.message ?? 'Failed to resolve current user') } const managerId = myProfile.data?.id ?? myProfile.data?.userPrincipalName if (!managerId) { throw new Error('Current user profile did not include an ID or UPN') } const result = await Office365UsersService.DirectReports_V2( managerId, fields, ) if (!result.success) { throw new Error(result.error?.message ?? 'Failed to load direct reports') } const people = result.data?.value ?? [] ``` An empty `value` array is valid and means the user has no direct reports. ## Profile photos: binary response and CSP-safe rendering Call `UserPhotoMetadata` before downloading the photo. `HasPhoto: false` is a valid no-photo state; render initials or another accessible fallback. Image responses are a special runtime contract: the generated `UserPhoto_V2` signature may declare `IOperationResult<string>`, but the Managed Apps SDK decodes an `image/*` response into a `Uint8Array`. Do not interpolate that byte array directly into a base64 URL, and do not use a `blob:` URL—the deployed App Player content security policy may block `blob:` under `img-src`. Convert the bytes to a `data:` URL: ```typescript function bytesToBase64(bytes: Uint8Array) { const chunkSize = 0x8000 let binary = '' for (let offset = 0; offset < bytes.length; offset += chunkSize) { binary += String.fromCharCode( ...bytes.subarray(offset, Math.min(offset + chunkSize, bytes.length)), ) } return btoa(binary) } function toImageDataUrl(value: unknown, contentType = 'image/jpeg') { if (value instanceof Uint8Array) { return `data:${contentType};base64,${bytesToBase64(value)}` } if (value instanceof ArrayBuffer) { return `data:${contentType};base64,${bytesToBase64(new Uint8Array(value))}` } if (typeof value === 'string') { if (/^data:image\/[a-z0-9.+-]+;base64,/i.test(value)) { return value } if (/^https?:/i.test(value)) { throw new Error( 'Profile photo returned an HTTP URL instead of binary image data.', ) } return `data:${contentType};base64,${value}` } throw new Error('The profile photo response used an unsupported format.') } ``` `UserPhoto_V2` has a binary response contract and does not return an external image URL. An HTTP value indicates an unexpected response shape, so the helper rejects it rather than passing a potentially CSP-blocked or authenticated URL to `<img src>`. Complete photo flow: ```typescript const metadata = await Office365UsersService.UserPhotoMetadata(userId) if (!metadata.success) { throw new Error(metadata.error?.message ?? 'Failed to check profile photo') } if (!metadata.data?.HasPhoto) { return undefined } const photo = await Office365UsersService.UserPhoto_V2(userId) if (!photo.success) { throw new Error(photo.error?.message ?? 'Failed to load profile photo') } return photo.data ? toImageDataUrl(photo.data, metadata.data.ContentType) : undefined ``` Always fetch photos through the generated connector service. Do not call Microsoft Graph directly and do not assign the authenticated connector runtime URL to `<img src>`.
Auf GitHub ansehen