Files
SnapOtter/apps/docs/pl/guide/scim.md
T
SnapOtterandGitHub d10d0f544f fix: release QA hardening across processing, media, security, and CI gates (#649)
A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
2026-07-27 15:37:30 +08:00

14 KiB

description, i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
description i18n_source_hash i18n_provenance i18n_output_hash i18n_hash_version
Skonfiguruj provisioning SCIM 2.0, aby synchronizować użytkowników i grupy z Twojego dostawcy tożsamości do SnapOtter. Obejmuje Okta, Azure AD / Entra ID oraz integracje niestandardowe. 06ee702b386e human 2c93409c4926 2

Provisioning SCIM

SnapOtter implementuje SCIM 2.0 (System for Cross-domain Identity Management) do automatycznego provisioningu użytkowników i grup. Twój dostawca tożsamości może automatycznie tworzyć, aktualizować, dezaktywować i ponownie aktywować konta użytkowników oraz synchronizować członkostwo w grupach.

::: tip Funkcja enterprise Provisioning SCIM wymaga licencji enterprise z funkcją scim. Nie jest dostępny w planie team. Bez tej funkcji wszystkie punkty końcowe SCIM (poza discovery) zwracają 403. :::

Wymagania wstępne

  • Działająca instancja SnapOtter dostępna pod publicznym adresem URL
  • Klucz licencji enterprise z funkcją scim
  • Wbudowane konto SnapOtter admin z pełnym efektywnym zestawem uprawnień. Delegowana rola niestandardowa lub klucz API administratora, któremu brakuje uprawnień administratora, nie mogą wygenerować ani unieważnić globalnego tokena SCIM.
  • Dostęp administracyjny do ustawień provisioningu Twojego dostawcy tożsamości

Szybki start

  1. Wygeneruj token bearer SCIM:
curl -X POST https://photos.example.com/api/v1/enterprise/scim/token \
  -H "Cookie: snapotter-session=YOUR_SESSION" \
  -H "Content-Type: application/json"

Odpowiedź zawiera token. Zapisz go natychmiast; nie można go pobrać ponownie.

{
  "token": "so_scim_v2_a1b2c3d4e5f6...",
  "message": "Save this token - it cannot be retrieved again"
}
  1. W swoim dostawcy tożsamości skonfiguruj provisioning SCIM za pomocą:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • Uwierzytelnianie: token bearer (wklej token z kroku 1)

Uwierzytelnianie

Punkty końcowe SCIM używają dedykowanego tokenu Bearer, odrębnego od sesji użytkowników i kluczy API.

Generowanie tokenu

POST /api/v1/enterprise/scim/token generuje nowy token SCIM. Ponieważ token może udostępniać i mutować użytkowników w całej instancji, ten punkt końcowy wymaga wbudowanej roli admin z pełnym efektywnym zestawem uprawnień administratora. Trzymanie users:manage w roli niestandardowej nie jest wystarczające.

Token jest zwracany w postaci jawnej dokładnie raz. SnapOtter przechowuje tylko hash scrypt. Jeśli utracisz token, odwołaj go i wygeneruj nowy.

Jednocześnie aktywny jest tylko jeden token SCIM. Wygenerowanie nowego tokenu zastępuje poprzedni.

::: warning Ponowne wydanie tokena po aktualizacji Starsze, niewersjonowane tokeny SCIM są odrzucane. Po uaktualnieniu do wersji, która wystawia tokeny so_scim_v2_..., wygeneruj nowy token i zaktualizuj dostawcę tożsamości przed wznowieniem udostępniania. :::

Odwoływanie tokenu

DELETE /api/v1/enterprise/scim/token unieważnia bieżący token SCIM. Ma te same pełne wbudowane wymagania administracyjne, co generowanie tokenów.

Ograniczanie liczby żądań

Punkty końcowe SCIM mają limit 1000 żądań na minutę na token. Przekroczenie tego limitu zwraca HTTP 429.

Obsługiwane zasoby

Zasób SCIM Pojęcie w SnapOtter Tworzenie Odczyt Aktualizacja Usuwanie
User Konto użytkownika Tak Tak Tak Miękkie usunięcie
Group Zespół Tak Tak Tak Tak

::: warning Grupy SCIM są mapowane na zespoły SnapOtter, a nie na role. SCIM nie może ustawić roli użytkownika. Wszyscy użytkownicy utworzeni przez SCIM otrzymują rolę user. Aby zmienić rolę użytkownika, użyj interfejsu administracyjnego SnapOtter. :::

Operacje na użytkownikach

Tworzenie użytkownika

POST /api/v1/scim/v2/Users

Tworzy nowe konto użytkownika z authProvider ustawionym na scim i rolą user. Użytkownik zostaje przypisany do zespołu Default. Jeśli active ma wartość false, rola jest zamiast tego ustawiana na disabled.

Wymagane atrybuty: userName. Opcjonalne: externalId, emails, active (domyślnie true).

Wyświetlanie i filtrowanie użytkowników

GET /api/v1/scim/v2/Users

Zwraca stronicowaną listę użytkowników. Obsługuje parametry zapytania startIndex i count (maksymalnie 200 wyników na stronę).

Filtrowanie obsługuje tylko eq (równa się) na tych atrybutach:

  • userName eq "jane"
  • externalId eq "ext-12345"

Inne operatory filtrów i atrybuty zwracają HTTP 400.

Pobieranie użytkownika

GET /api/v1/scim/v2/Users/:id

Zwraca pojedynczego użytkownika według jego identyfikatora użytkownika SnapOtter.

Zastępowanie użytkownika

PUT /api/v1/scim/v2/Users/:id

Zastępuje atrybuty użytkownika. Obsługuje userName, externalId, emails oraz active. Zmiany nazwy użytkownika są sprawdzane pod kątem konfliktów (409, jeśli nowa nazwa użytkownika jest zajęta przez innego użytkownika).

Częściowa aktualizacja użytkownika

PATCH /api/v1/scim/v2/Users/:id

Częściowa aktualizacja przy użyciu SCIM PatchOp. Obsługiwane operacje:

Operacja Ścieżki
replace active, userName, externalId, emails, emails[type eq "work"].value, name.formatted, displayName
add Tak samo jak replace
remove externalId, emails

Ścieżki name.formatted i displayName są akceptowane w celu zachowania zgodności, ale nie mają trwałego efektu (SnapOtter nie przechowuje osobnej nazwy wyświetlanej).

Obsługiwane są także operacje replace bez wartości (gdzie wartość jest obiektem bez path), z kluczami userName, externalId, emails oraz active.

Dezaktywacja użytkownika (miękkie usunięcie)

DELETE /api/v1/scim/v2/Users/:id

SnapOtter nie usuwa użytkowników trwale przez SCIM. Zamiast tego DELETE wykonuje miękką dezaktywację:

  1. Rola użytkownika zostaje zmieniona z jej bieżącej wartości (np. editor) na disabled:editor, zachowując oryginalną rolę.
  2. Hasło użytkownika zostaje wyczyszczone.
  3. Wszystkie aktywne sesje zostają odwołane.
  4. Wszystkie klucze API zostają odwołane.

Użytkownik nie może już się logować ani używać żadnych kluczy API. Jego dane (pliki, historia) są zachowywane.

Ponowna aktywacja użytkownika

Aby ponownie aktywować wcześniej dezaktywowanego użytkownika, wyślij żądanie PUT lub PATCH z active: true. SnapOtter przywraca oryginalną rolę sprzed dezaktywacji (np. disabled:editor ponownie staje się editor). Jeśli oryginalnej roli nie da się ustalić, następuje powrót do user.

::: details Przykład: dezaktywacja i ponowna aktywacja przez PATCH

// Deactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": false }
  ]
}

// Reactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": true }
  ]
}

:::

Operacje na grupach

Grupy SCIM są mapowane na zespoły SnapOtter. Utworzenie grupy tworzy zespół. Członkostwo w grupie steruje tym, do którego zespołu należy użytkownik.

Tworzenie grupy

POST /api/v1/scim/v2/Groups

Wymagane: displayName. Opcjonalne: members (tablica { value: userId }).

Wyświetlanie i filtrowanie grup

GET /api/v1/scim/v2/Groups

Filtrowanie obsługuje tylko displayName eq "...". Stronicowane za pomocą startIndex i count (maksymalnie 200 wyników na stronę).

Pobieranie grupy

GET /api/v1/scim/v2/Groups/:id

Zastępowanie grupy

PUT /api/v1/scim/v2/Groups/:id

Zastępuje nazwę grupy i pełną listę członków. Istniejący członkowie, których nie ma na nowej liście, zostają przeniesieni do zespołu Default.

Częściowa aktualizacja grupy

PATCH /api/v1/scim/v2/Groups/:id

Obsługuje te operacje:

Operacja Ścieżka Efekt
add members Dodaje użytkowników do zespołu
remove members[value eq "userId"] Przenosi użytkownika do zespołu Default
replace displayName Zmienia nazwę zespołu
replace members Zastępuje wszystkich członków (usunięci członkowie zostają przeniesieni do zespołu Default)

Usuwanie grupy

DELETE /api/v1/scim/v2/Groups/:id

Usuwa zespół. Wszyscy członkowie usuniętego zespołu zostają przeniesieni do zespołu Default. Użytkownicy nie są dezaktywowani ani usuwani.

Konfiguracja IdP

Okta

  1. W konsoli administracyjnej Okta otwórz swoją aplikację SnapOtter (lub ją utwórz).
  2. Przejdź do zakładki Provisioning i kliknij Configure API Integration.
  3. Zaznacz Enable API Integration i wprowadź:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • API Token: wygenerowany powyżej token bearer SCIM
  4. Kliknij Test API Credentials, a następnie Save.
  5. W sekcji Provisioning > To App włącz:
    • Create Users
    • Update User Attributes
    • Deactivate Users
  6. W sekcji Push Groups skonfiguruj, które grupy Okta mają być synchronizowane jako zespoły SnapOtter.

Azure AD / Entra ID

  1. W portalu Azure przejdź do swojej aplikacji korporacyjnej SnapOtter.
  2. Przejdź do Provisioning i ustaw Provisioning Mode na Automatic.
  3. W sekcji Admin Credentials wprowadź:
    • Tenant URL: https://photos.example.com/api/v1/scim/v2
    • Secret Token: wygenerowany powyżej token bearer SCIM
  4. Kliknij Test Connection, a następnie Save.
  5. W sekcji Mappings skonfiguruj mapowania atrybutów użytkowników i grup. Wartości domyślne zwykle działają, ale sprawdź, czy userName jest zgodnie z oczekiwaniami mapowany na userPrincipalName lub mail.
  6. Ustaw Provisioning Status na On i zapisz.

Azure prowadzi provisioning użytkowników i grup w stałym cyklu synchronizacji (zwykle co 40 minut).

Punkty końcowe discovery

Te trzy punkty końcowe są dostępne bez uwierzytelniania i opisują możliwości serwera SCIM:

Punkt końcowy Opis
GET /api/v1/scim/v2/ServiceProviderConfig Możliwości serwera i obsługiwane funkcje
GET /api/v1/scim/v2/Schemas Definicje schematów User i Group
GET /api/v1/scim/v2/ResourceTypes Dostępne typy zasobów (User, Group)

ServiceProviderConfig ogłasza te możliwości:

Funkcja Obsługiwane
Patch Tak
Bulk Nie
Filter Tak (maks. 200 wyników, tylko operator eq)
Zmiana hasła Nie
Sort Nie
ETag Nie

Ograniczenia

  • Filtrowanie: obsługiwany jest tylko operator eq. Filtry złożone, operatory and/or, co (zawiera) oraz sw (zaczyna się od) nie są zaimplementowane.
  • Operacje zbiorcze: nieobsługiwane.
  • Sort i ETag: nieobsługiwane.
  • Role: SCIM nie może przypisywać ról SnapOtter. Wszyscy provisionowani użytkownicy otrzymują rolę user.
  • MAX_USERS: limit zmiennej środowiskowej MAX_USERS nie jest egzekwowany przy tworzeniu użytkowników przez SCIM. Jeśli musisz ograniczyć liczbę użytkowników, zarządzaj przypisaniami w swoim IdP.
  • Jeden token: jednocześnie aktywny może być tylko jeden token SCIM. Jeśli wiele IdP potrzebuje dostępu SCIM, muszą współdzielić ten token.
  • Grupy to zespoły: grupy SCIM odpowiadają zespołom, a nie rolom czy grupom uprawnień.

Rozwiązywanie problemów

403 "SCIM provisioning requires an enterprise license with the scim feature"

Twoja licencja nie zawiera funkcji scim albo nie skonfigurowano żadnej licencji. SCIM wymaga licencji planu enterprise. Sprawdź, czy SNAPOTTER_LICENSE_KEY jest ustawione, a licencja zawiera funkcję scim.

401 "Bearer token required"

Żądanie SCIM nie zawierało nagłówka Authorization: Bearer <token>. Sprawdź konfigurację provisioningu w swoim IdP.

401 "Invalid token"

Token jest zniekształcony, używa wycofanego formatu niewersjonowanego lub nie pasuje do zapisanego skrótu. Wygeneruj aktualny token so_scim_v2_... i zaktualizuj token w ustawieniach udostępniania IdP.

401 "SCIM not configured"

Nie wygenerowano jeszcze żadnego tokenu SCIM. Użyj punktu końcowego POST /api/v1/enterprise/scim/token, aby go utworzyć.

409 "User already exists" / "userName already taken"

Użytkownik o tej samej nazwie użytkownika już istnieje. Może się to zdarzyć, gdy IdP ponawia nieudane utworzenie. Sprawdź, czy w panelu administracyjnym SnapOtter nie ma zduplikowanych nazw użytkowników.

429 "SCIM rate limit exceeded"

IdP wysyła ponad 1000 żądań na minutę. Zwykle dzieje się tak podczas dużej synchronizacji początkowej. Większość IdP automatycznie ponawia próbę po zresetowaniu okna limitu. Jeśli problem się utrzymuje, sprawdź interwał synchronizacji provisioningu swojego IdP.

Użytkownicy zostali deprovisioned, ale nie usunięto ich z interfejsu

SCIM DELETE to miękka dezaktywacja. Dezaktywowani użytkownicy nadal pojawiają się na liście użytkowników administratora ze statusem wyłączony. Jest to działanie zamierzone, aby zachować ich dane. Ich rola jest wyświetlana jako disabled:<original-role>.