tillio-crm/oauth-resources

Official PHP SDK for Tillio app resources: per-app document storage and file storage proxy.

Maintainers

Package info

github.com/tillio-crm/oauth-resources

pkg:composer/tillio-crm/oauth-resources

Transparency log

Statistics

Installs: 20

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-24 13:29 UTC

This package is auto-updated.

Last update: 2026-07-24 13:32:49 UTC


README

Oficjalne SDK PHP do zasobów aplikacji Tillio: prywatny magazyn dokumentów i plików per (aplikacja × workspace), udostępniany przez storage proxy serwera Tillio.

Twoja aplikacja nigdy nie dotyka Firestore/GCS bezpośrednio — wszystko przechodzi przez API Tillio z tokenem OAuth. Przestrzeń danych jest wyznaczana po stronie serwera z tokenu, więc aplikacja widzi wyłącznie własne dane w obrębie workspace'u, który ją zainstalował.

Latest Version Total Downloads PHP Version License

Uzupełnia tillio-crm/oauth-client (logowanie OAuth 2.0 + PKCE) — razem stanowią komplet do budowy aplikacji Tillio.

Spis treści

Wymagania

  • PHP ^8.3
  • rozszerzenia: ext-curl, ext-json
  • Composer
  • Aplikacja zarejestrowana w Tillio (zainstalowana w workspace) z tokenem OAuth zawierającym scope app_storage

Instalacja

composer require tillio-crm/oauth-resources

Szybki start

Najwygodniej w parze z tillio-crm/oauth-client — callable z tokenem załatwia auto-refresh:

use TillioCrm\OAuth\Client\Client;
use TillioCrm\OAuth\Resources\ResourcesClient;

$oauth = new Client([
    'clientId'     => '...',
    'clientSecret' => '...',
    'redirectUri'  => 'https://twoja-apka.pl/callback',
    'scopes'       => ['profile', 'email', 'offline_access', 'app_storage'],
]);

$resources = new ResourcesClient([
    'accessToken' => fn () => $oauth->accessToken(),
    // 'server' => 'https://auth.tillio.app', // default
]);

Token można też podać wprost: new ResourcesClient(['accessToken' => $jwt]).

Dokumenty

Dokument to tablica JSON-owalna (max 256 KB). Nazwy kolekcji i ID: [a-zA-Z0-9_-], max 64 znaki.

$storage = $resources->storage();

// Zapis (upsert — pełne nadpisanie)
$storage->put('sync_state', 'wfirma', [
    'last_run_at' => '2026-07-24T03:00:00Z',
    'cursor'      => 18234,
    'status'      => 'ok',
]);

// Odczyt
$doc = $storage->get('sync_state', 'wfirma');   // NotFoundException gdy brak
$doc = $storage->find('sync_state', 'wfirma');  // null gdy brak
echo $doc['data']['status'];                     // 'ok'

// Lista z filtrem i paginacją
$page = $storage->list('invoices', [
    'limit'  => 100,
    'filter' => ['status', '==', 'pending'],
]);
$next = $storage->list('invoices', ['after' => $page['next_cursor']]);

// Iteracja po całej kolekcji (paginacja automatyczna)
foreach ($storage->all('invoices') as $invoice) {
    // ...
}

// Usunięcie
$storage->delete('sync_state', 'wfirma');

Operatory filtra: ==, !=, >, >=, <, <=, in, array-contains. Wartości filtra zachowują typ (string "5" ≠ liczba 5).

Pliki

Pliki trafiają bezpośrednio do Google Cloud Storage przez krótkoterminowe signed URLs (15 min) — nie przechodzą przez serwer Tillio. SDK ukrywa cały flow:

$files = $resources->files();

// Upload / download w jednej linii
$files->upload('invoices/2026/07/faktura-123.pdf', $pdfBytes, 'application/pdf');
$pdf = $files->download('invoices/2026/07/faktura-123.pdf');

// Signed URL np. dla przeglądarki użytkownika (ważny 15 minut)
$grant = $files->downloadUrl('invoices/2026/07/faktura-123.pdf');
header('Location: ' . $grant['url']);

// Listing i kasowanie
$list = $files->list('invoices/2026/07/');
$files->delete('invoices/2026/07/faktura-123.pdf');

Ścieżki są względne w obrębie przestrzeni aplikacji; segmenty [a-zA-Z0-9._-], bez .. i bez segmentów zaczynających się kropką. Limit uploadu: 100 MB (egzekwowany kryptograficznie w podpisie URL).

API

Klasa ResourcesClient

Metoda / opcja Opis
new ResourcesClient(array $config) accessToken (string | callable, wymagane), server (default https://auth.tillio.app), timeout (default 30.0), handler (Guzzle HandlerStack, do testów)
storage(): Storage dokumentowy magazyn danych
files(): Files magazyn plików

Klasa Storage

Metoda Opis
put(string $collection, string $docId, array $data): array upsert; zwraca {id, data, created_at, updated_at}
get(string $collection, string $docId): array odczyt; NotFoundException gdy brak
find(string $collection, string $docId): ?array jak get(), ale null zamiast wyjątku
delete(string $collection, string $docId): void usunięcie dokumentu
list(string $collection, array $options = []): array limit (≤500), after (cursor), filter ([pole, operator, wartość]); zwraca {documents, next_cursor}
all(string $collection, array $options = []): Generator iterator po całej kolekcji (auto-paginacja)

Klasa Files

Metoda Opis
upload(string $path, mixed $contents, string $contentType): void string albo stream
download(string $path): string NotFoundException gdy brak
uploadUrl(string $path, string $contentType, ?int $maxBytes): array {url, method, headers, expires_in} — nagłówki są wymagane przy PUT
downloadUrl(string $path): array {url, method, expires_in}
list(string $prefix = ''): array [{path, size, content_type, updated_at}]
delete(string $path): void NotFoundException gdy brak

Wyjątki

Wszystkie dziedziczą po ResourcesException (\RuntimeException); kod wyjątku = status HTTP.

Wyjątek Kiedy
AuthenticationException 401/403 — zły/pusty token, brak scope app_storage, apka niezainstalowana w workspace
NotFoundException 404 — dokument/plik nie istnieje
ValidationException pozostałe 4xx — zły input (nazwa kolekcji, limit 256 KB itd.)
ServerException 5xx — błąd serwera/magazynu
use TillioCrm\OAuth\Resources\Exception\NotFoundException;

try {
    $doc = $resources->storage()->get('sync_state', 'wfirma');
} catch (NotFoundException) {
    // pierwsza synchronizacja — brak stanu
}

Bezpieczeństwo

  • Namespace z tokenu, nie z inputu — prefiks przestrzeni danych (workspace × aplikacja) serwer wyprowadza z claimów tokenu OAuth. Aplikacja nie zna i nie podaje pełnych ścieżek, więc nie może odczytać danych innej aplikacji ani innego workspace'u.
  • Token Tillio nigdy nie trafia do GCS — komunikacja z signed URLs odbywa się osobnym klientem HTTP bez nagłówka Authorization (podpis jest w samym URL-u).
  • Ścieżki walidowane po stronie serwera.., //, ukryte segmenty i ścieżki absolutne są odrzucane (ValidationException).
  • Rewokacja tokenu / odinstalowanie aplikacji odcina dostęp natychmiast — serwer sprawdza ważność tokenu przy każdym wywołaniu.

Testy

composer install
vendor/bin/phpunit

Testy nie wymagają sieci (Guzzle MockHandler przez opcję handler).

Wersjonowanie

SemVer. Do wersji 1.0.0 drobne zmiany łamiące mogą pojawić się w wydaniach minor.

Zgłaszanie błędów / pull requesty

Issues i PR-y: github.com/tillio-crm/oauth-resources. Zgłoszenia bezpieczeństwa — nie przez publiczne issues; napisz na adres wsparcia Tillio.

Licencja

MIT — patrz LICENSE.