Przejdź do treści
Biblioteka skilli
Dokumenty i biuro · Integracja z narzędziem

add-office365-users

/add-office365-users

Dodaje Office 365 Users: profile użytkowników, przełożonych, podwładnych, wyszukiwanie osób i zdjęcia profilowe.

Repozytorium
managed-apps ↗
Licencja
MIT
Ostatnia zmiana repozytorium
09.10.2026

Ocena i bezpieczeństwo

95/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść30 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 09.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Dodaje Office 365 Users: profile użytkowników, przełożonych, podwładnych, wyszukiwanie osób i zdjęcia profilowe.

Oryginalny opis (EN)

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.

Jak działa

  1. Delegation contract
  2. Profile and direct-report pattern
  3. Profile photos: binary response and CSP-safe rendering
Sekcje z nagłówków SKILL.md, w oryginale · 165 linii, 625 słów
Podgląd SKILL.md
---
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>`.

Wersje

W bazie nie ma innych skilli o nazwie add-office365-users.

Migawka bazy z 28.10.2026 · wersja paczki 2e2fe0e42dde (skrót SHA-256 całej paczki)

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100add-office365
    Dodaje Office 365 Outlook (poczta i kalendarz) przez delegowanie do add-data-source z api-id shared_office365 w trybie akcji.
  • 100add-workiq
    Dodaje Work IQ Copilot MCP przez delegowanie do add-data-source z api-id shared_a365copilotchatmcp, dla wyszukiwania i czatu opartego na wiedzy Microsoft 365.
  • 100rover-people
    Wyszukuje pracowników Red Hat po nazwisku lub e-mailu, pokazuje przełożonych, podwładnych i schematy organizacyjne przez rh-dataverse.
  • 84profile
    Zarządza zapisanymi profilami boxel-cli: listuje, dodaje, przełącza i usuwa profile oraz migruje z pliku .env.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.