Refactor code structure for improved readability and maintainability
This commit is contained in:
281
COMPANY_MAGICO_APP_MANAGMENT.md
Normal file
281
COMPANY_MAGICO_APP_MANAGMENT.md
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
# Zarządzanie aplikacją TravelManager w ekosystemie Magico
|
||||||
|
|
||||||
|
Dokumentacja procesu aktywacji i zarządzania aplikacją TravelManager dla firm w systemie Magico.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Przegląd
|
||||||
|
|
||||||
|
Proces aktywacji TravelManager dla firmy składa się z dwóch głównych kroków:
|
||||||
|
|
||||||
|
1. **Aktywacja aplikacji** – użytkownik/admin włącza TravelManager w panelu Magico
|
||||||
|
2. **Tworzenie tenanta** – automatyczne utworzenie środowiska dla firmy w TravelManager
|
||||||
|
3. **Synchronizacja użytkowników** – pobranie listy użytkowników firmy z Magico do TravelManager
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 1: Aktywacja aplikacji TravelManager
|
||||||
|
|
||||||
|
### Scenariusze aktywacji
|
||||||
|
|
||||||
|
**Scenariusz A:** Użytkownik w sklepie aplikacji (magico.pro)
|
||||||
|
- Użytkownik przegląda sklep aplikacji w magico.pro
|
||||||
|
- Kliknięcie "Aktywuj" przy aplikacji TravelManager
|
||||||
|
|
||||||
|
**Scenariusz B:** Administrator w panelu zarządzania Magico
|
||||||
|
- Administrator loguje się do panelu zarządzania całym systemem Magico
|
||||||
|
- Włączenie aplikacji TravelManager dla konkretnej firmy
|
||||||
|
|
||||||
|
### Rezultat aktywacji
|
||||||
|
|
||||||
|
Po kliknięciu aktywacji system Magico wykonuje automatycznie **POST** do TravelManager API w celu utworzenia nowego tenanta.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 2: Tworzenie tenanta w TravelManager
|
||||||
|
|
||||||
|
### Endpoint tworzenia tenanta
|
||||||
|
|
||||||
|
**POST** `manager.travelmanager.pl/api/tenant`
|
||||||
|
|
||||||
|
System Magico automatycznie wywołuje ten endpoint po aktywacji aplikacji.
|
||||||
|
|
||||||
|
### Nagłówki
|
||||||
|
|
||||||
|
```
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {magico_system_token}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Body żądania (minimalne/przykładowe)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"company_name": "Nazwa Firmy Sp. z o.o.",
|
||||||
|
"company_id": 34
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parametr | Typ | Opis |
|
||||||
|
|---------------|--------|-----------------------------------------|
|
||||||
|
| `company_name`| string | Pełna nazwa firmy z systemu Magico |
|
||||||
|
| `company_id` | int | Unikalny identyfikator firmy w Magico |
|
||||||
|
|
||||||
|
### Odpowiedź sukces (201)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"message": "Tenant created successfully",
|
||||||
|
"tenant_id": "tenant_34_travelmanager",
|
||||||
|
"company_id": 34,
|
||||||
|
"created_at": "2026-02-17T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź błąd
|
||||||
|
|
||||||
|
**400 Bad Request** - Nieprawidłowe dane
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"message": "Invalid company data",
|
||||||
|
"errors": ["company_id is required", "company_name is required"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**409 Conflict** - Tenant już istnieje
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"message": "Tenant already exists for this company",
|
||||||
|
"existing_tenant_id": "tenant_34_travelmanager"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 3: Synchronizacja użytkowników z Magico
|
||||||
|
|
||||||
|
Po utworzeniu tenanta, TravelManager automatycznie pobiera listę użytkowników firmy z systemu Magico.
|
||||||
|
|
||||||
|
### Endpoint pobierania użytkowników
|
||||||
|
|
||||||
|
**GET** `company.magico.pro/api/company/{company_id}/users`
|
||||||
|
|
||||||
|
TravelManager wykonuje to zapytanie używając tokena systemowego.
|
||||||
|
|
||||||
|
### Nagłówki
|
||||||
|
|
||||||
|
```
|
||||||
|
Authorization: Bearer {travelmanager_system_token}
|
||||||
|
Accept: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parametry URL
|
||||||
|
|
||||||
|
| Parametr | Typ | Opis |
|
||||||
|
|-------------|-----|-------------------------------------------|
|
||||||
|
| `company_id`| int | ID firmy (np. 34) z kroku tworzenia tenanta |
|
||||||
|
|
||||||
|
### Przykładowe zapytanie
|
||||||
|
|
||||||
|
```
|
||||||
|
GET https://company.magico.pro/api/company/34/users
|
||||||
|
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
|
||||||
|
Accept: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź Magico API (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"company_id": 34,
|
||||||
|
"company_name": "Nazwa Firmy Sp. z o.o.",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "Jan Kowalski",
|
||||||
|
"email": "jan.kowalski@firma.pl",
|
||||||
|
"global_user_id": 123,
|
||||||
|
"username": "jan.kowalski",
|
||||||
|
"role": "admin",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Anna Nowak",
|
||||||
|
"email": "anna.nowak@firma.pl",
|
||||||
|
"global_user_id": 124,
|
||||||
|
"username": "anna.nowak",
|
||||||
|
"role": "user",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_users": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Struktura użytkownika
|
||||||
|
|
||||||
|
| Pole | Typ | Opis |
|
||||||
|
|------------------|---------|----------------------------------------|
|
||||||
|
| `name` | string | Pełne imię i nazwisko użytkownika |
|
||||||
|
| `email` | string | Adres email użytkownika |
|
||||||
|
| `global_user_id` | int | Globalny ID użytkownika w systemie Magico |
|
||||||
|
| `username` | string | Login użytkownika |
|
||||||
|
| `role` | string | Rola użytkownika (admin, user, etc.) |
|
||||||
|
| `active` | boolean | Status aktywności konta |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 4: Tworzenie powiązań użytkowników w TravelManager
|
||||||
|
|
||||||
|
### Proces powiązywania
|
||||||
|
|
||||||
|
Po otrzymaniu listy użytkowników z Magico, TravelManager:
|
||||||
|
|
||||||
|
1. **Tworzy rekordy użytkowników** w swoim tenantcie
|
||||||
|
2. **Zapisuje mapowanie** między `global_user_id` (Magico) a lokalnym ID w TravelManager
|
||||||
|
3. **Umożliwia powiązanie** użytkowników między systemem Magico a TravelManager
|
||||||
|
|
||||||
|
### Przykładowa struktura w bazie TravelManager
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Tabela tenantów
|
||||||
|
CREATE TABLE tenants (
|
||||||
|
id VARCHAR(50) PRIMARY KEY,
|
||||||
|
company_id INT NOT NULL,
|
||||||
|
company_name VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela użytkowników tenanta
|
||||||
|
CREATE TABLE tenant_users (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
tenant_id VARCHAR(50) NOT NULL,
|
||||||
|
global_user_id INT NOT NULL, -- ID z Magico
|
||||||
|
local_user_id INT, -- lokalne ID w TravelManager
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(100) NOT NULL,
|
||||||
|
role VARCHAR(50),
|
||||||
|
active BOOLEAN DEFAULT TRUE,
|
||||||
|
synced_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pełny flow aktywacji
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant U as Użytkownik/Admin
|
||||||
|
participant M as Magico.pro
|
||||||
|
participant T as TravelManager
|
||||||
|
participant C as Company.Magico.pro
|
||||||
|
|
||||||
|
U->>M: Kliknięcie "Aktywuj TravelManager"
|
||||||
|
M->>T: POST /api/tenant (company_name, company_id)
|
||||||
|
T->>T: Tworzenie tenanta w bazie
|
||||||
|
T->>M: 201 Tenant created
|
||||||
|
T->>C: GET /api/company/{id}/users
|
||||||
|
C->>T: Lista użytkowników firmy
|
||||||
|
T->>T: Tworzenie powiązań użytkowników
|
||||||
|
M->>U: Aplikacja aktywowana pomyślnie
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bezpieczeństwo i tokeny
|
||||||
|
|
||||||
|
### Tokeny systemowe
|
||||||
|
|
||||||
|
- **Magico System Token** - używany do tworzenia tenantów w TravelManager
|
||||||
|
- **TravelManager System Token** - używany do pobierania użytkowników z Magico
|
||||||
|
|
||||||
|
### Konfiguracja tokenów
|
||||||
|
|
||||||
|
Tokeny muszą być skonfigurowane w:
|
||||||
|
- **Magico** - endpoint TravelManager dla tworzenia tenantów
|
||||||
|
- **TravelManager** - endpoint Magico dla pobierania użytkowników
|
||||||
|
- **Company.Magico.pro** - autoryzacja zapytań od TravelManager
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Obsługa błędów
|
||||||
|
|
||||||
|
### Scenariusze błędów
|
||||||
|
|
||||||
|
1. **Błąd tworzenia tenanta**
|
||||||
|
- Logowanie błędu w systemie Magico
|
||||||
|
- Informowanie użytkownika o problemie z aktywacją
|
||||||
|
|
||||||
|
2. **Błąd pobierania użytkowników**
|
||||||
|
- Tenant zostaje utworzony, ale bez użytkowników
|
||||||
|
- Możliwość ponownej synchronizacji
|
||||||
|
|
||||||
|
3. **Problemy z tokenami**
|
||||||
|
- Sprawdzanie ważności tokenów systemowych
|
||||||
|
- Procedury odnawiania tokenów
|
||||||
|
|
||||||
|
### Retry i ponowne próby
|
||||||
|
|
||||||
|
- **Retry logic** dla zapytań HTTP
|
||||||
|
- **Timeout** dla długotrwałych operacji
|
||||||
|
- **Kolejka zadań** dla operacji asynchronicznych
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Logi systemowe
|
||||||
|
|
||||||
|
Każda operacja powinna być logowana:
|
||||||
|
- Aktywacja aplikacji przez użytkownika
|
||||||
|
- Tworzenie tenanta
|
||||||
|
- Pobieranie użytkowników
|
||||||
|
- Błędy i wyjątki
|
||||||
|
|
||||||
345
COMPANY_MAGICO_APP_MANAGMENT_V2.md
Normal file
345
COMPANY_MAGICO_APP_MANAGMENT_V2.md
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
# Zarządzanie aplikacją TravelManager w ekosystemie Magico
|
||||||
|
|
||||||
|
Dokumentacja procesu aktywacji i zarządzania aplikacją TravelManager dla firm w systemie Magico.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Przegląd
|
||||||
|
|
||||||
|
Proces aktywacji TravelManager dla firmy składa się z następujących kroków:
|
||||||
|
|
||||||
|
1. **Aktywacja aplikacji** – użytkownik/admin włącza TravelManager w panelu Magico
|
||||||
|
2. **Tworzenie tenanta z użytkownikami** – automatyczne utworzenie środowiska dla firmy w TravelManager wraz z przesłaniem listy użytkowników
|
||||||
|
3. **Synchronizacja zmian** – automatyczne aktualizowanie listy użytkowników przy każdej zmianie w systemie Magico
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 1: Aktywacja aplikacji TravelManager
|
||||||
|
|
||||||
|
### Scenariusze aktywacji
|
||||||
|
|
||||||
|
**Scenariusz A:** Użytkownik w sklepie aplikacji (magico.pro)
|
||||||
|
- Użytkownik przegląda sklep aplikacji w magico.pro
|
||||||
|
- Kliknięcie "Aktywuj" przy aplikacji TravelManager
|
||||||
|
|
||||||
|
**Scenariusz B:** Administrator w panelu zarządzania Magico
|
||||||
|
- Administrator loguje się do panelu zarządzania całym systemem Magico
|
||||||
|
- Włączenie aplikacji TravelManager dla konkretnej firmy
|
||||||
|
|
||||||
|
### Rezultat aktywacji
|
||||||
|
|
||||||
|
Po kliknięciu aktywacji system Magico:
|
||||||
|
1. Pobiera listę użytkowników firmy z bazy danych
|
||||||
|
2. Wykonuje automatycznie **POST** do TravelManager API z pełnymi danymi tenanta i użytkowników
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 2: Tworzenie tenanta z użytkownikami w TravelManager
|
||||||
|
|
||||||
|
### Endpoint tworzenia tenanta z użytkownikami
|
||||||
|
|
||||||
|
**POST** `manager.travelmanager.pl/api/tenant`
|
||||||
|
|
||||||
|
System Magico automatycznie wywołuje ten endpoint po aktywacji aplikacji, przesyłając od razu pełną listę użytkowników firmy.
|
||||||
|
|
||||||
|
### Nagłówki
|
||||||
|
|
||||||
|
```
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {magico_system_token}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Body żądania
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"company_name": "Nazwa Firmy Sp. z o.o.",
|
||||||
|
"company_id": 34,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "Jan Kowalski",
|
||||||
|
"email": "jan.kowalski@firma.pl",
|
||||||
|
"global_user_id": 123,
|
||||||
|
"username": "jan.kowalski",
|
||||||
|
"role": "admin",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Anna Nowak",
|
||||||
|
"email": "anna.nowak@firma.pl",
|
||||||
|
"global_user_id": 124,
|
||||||
|
"username": "anna.nowak",
|
||||||
|
"role": "user",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parametr | Typ | Opis |
|
||||||
|
|---------------|--------|-----------------------------------------|
|
||||||
|
| `company_name`| string | Pełna nazwa firmy z systemu Magico |
|
||||||
|
| `company_id` | int | Unikalny identyfikator firmy w Magico |
|
||||||
|
| `users` | array | Lista wszystkich użytkowników firmy |
|
||||||
|
|
||||||
|
### Struktura użytkownika w tablicy `users`
|
||||||
|
|
||||||
|
| Pole | Typ | Opis |
|
||||||
|
|------------------|---------|----------------------------------------|
|
||||||
|
| `name` | string | Pełne imię i nazwisko użytkownika |
|
||||||
|
| `email` | string | Adres email użytkownika |
|
||||||
|
| `global_user_id` | int | Globalny ID użytkownika w systemie Magico |
|
||||||
|
| `username` | string | Login użytkownika |
|
||||||
|
| `role` | string | Rola użytkownika (admin, user, etc.) |
|
||||||
|
| `active` | boolean | Status aktywności konta |
|
||||||
|
|
||||||
|
### Odpowiedź sukces (201)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"message": "Tenant created successfully with users",
|
||||||
|
"tenant_id": "tenant_34_travelmanager",
|
||||||
|
"company_id": 34,
|
||||||
|
"users_imported": 2,
|
||||||
|
"created_at": "2026-02-17T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź błąd
|
||||||
|
|
||||||
|
**400 Bad Request** - Nieprawidłowe dane
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"message": "Invalid company data",
|
||||||
|
"errors": ["company_id is required", "company_name is required"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**409 Conflict** - Tenant już istnieje
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"message": "Tenant already exists for this company",
|
||||||
|
"existing_tenant_id": "tenant_34_travelmanager"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 3: Synchronizacja zmian użytkowników
|
||||||
|
|
||||||
|
Kiedy lista użytkowników w systemie Magico ulegnie zmianie (dodanie, usunięcie, edycja użytkownika), system automatycznie wysyła aktualizację do wszystkich połączonych aplikacji, w tym TravelManager.
|
||||||
|
|
||||||
|
### Endpoint aktualizacji użytkowników
|
||||||
|
|
||||||
|
**PUT** `manager.travelmanager.pl/api/tenant/{company_id}/users`
|
||||||
|
|
||||||
|
Magico.pro wywołuje ten endpoint za każdym razem gdy:
|
||||||
|
- Dodany zostanie nowy użytkownik do firmy
|
||||||
|
- Usunięty zostanie użytkownik z firmy
|
||||||
|
- Zmienione zostaną dane użytkownika (email, rola, status aktywności)
|
||||||
|
- Zmieniony zostanie status aktywności użytkownika
|
||||||
|
|
||||||
|
### Nagłówki
|
||||||
|
|
||||||
|
```
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {magico_system_token}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parametry URL
|
||||||
|
|
||||||
|
| Parametr | Typ | Opis |
|
||||||
|
|-------------|-----|-------------------------------------------|
|
||||||
|
| `company_id`| int | ID firmy (np. 34) dla której aktualizujemy użytkowników |
|
||||||
|
|
||||||
|
### Body żądania
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"company_id": 34,
|
||||||
|
"company_name": "Nazwa Firmy Sp. z o.o.",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "Jan Kowalski",
|
||||||
|
"email": "jan.kowalski@firma.pl",
|
||||||
|
"global_user_id": 123,
|
||||||
|
"username": "jan.kowalski",
|
||||||
|
"role": "admin",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Anna Nowak",
|
||||||
|
"email": "anna.nowak@firma.pl",
|
||||||
|
"global_user_id": 124,
|
||||||
|
"username": "anna.nowak",
|
||||||
|
"role": "user",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Michał Wiśniewski",
|
||||||
|
"email": "michal.wisniewski@firma.pl",
|
||||||
|
"global_user_id": 125,
|
||||||
|
"username": "michal.wisniewski",
|
||||||
|
"role": "user",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_users": 3,
|
||||||
|
"updated_at": "2026-02-17T11:45:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź TravelManager (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"message": "Users synchronized successfully",
|
||||||
|
"company_id": 34,
|
||||||
|
"users_updated": 3,
|
||||||
|
"users_added": 1,
|
||||||
|
"users_removed": 0,
|
||||||
|
"users_modified": 2,
|
||||||
|
"synchronized_at": "2026-02-17T11:45:15Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 4: Zarządzanie użytkownikami w TravelManager
|
||||||
|
|
||||||
|
### Proces zarządzania
|
||||||
|
|
||||||
|
TravelManager otrzymuje pełną listę użytkowników od Magico i:
|
||||||
|
|
||||||
|
1. **Podczas tworzenia tenanta:**
|
||||||
|
- Tworzy rekordy wszystkich użytkowników w swoim tenantcie
|
||||||
|
- Zapisuje mapowanie między `global_user_id` (Magico) a lokalnym ID w TravelManager
|
||||||
|
|
||||||
|
2. **Podczas synchronizacji zmian:**
|
||||||
|
- Porównuje otrzymaną listę z aktualnym stanem
|
||||||
|
- Dodaje nowych użytkowników
|
||||||
|
- Usuwa użytkowników nieobecnych na nowej liście
|
||||||
|
- Aktualizuje dane zmodyfikowanych użytkowników
|
||||||
|
|
||||||
|
### Przykładowa struktura w bazie TravelManager
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Tabela tenantów
|
||||||
|
CREATE TABLE tenants (
|
||||||
|
id VARCHAR(50) PRIMARY KEY,
|
||||||
|
company_id INT NOT NULL,
|
||||||
|
company_name VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela użytkowników tenanta
|
||||||
|
CREATE TABLE tenant_users (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
tenant_id VARCHAR(50) NOT NULL,
|
||||||
|
global_user_id INT NOT NULL, -- ID z Magico
|
||||||
|
local_user_id INT, -- lokalne ID w TravelManager
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(100) NOT NULL,
|
||||||
|
role VARCHAR(50),
|
||||||
|
active BOOLEAN DEFAULT TRUE,
|
||||||
|
synced_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pełny flow aktywacji
|
||||||
|

|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant U as Użytkownik/Admin
|
||||||
|
participant M as Magico.pro
|
||||||
|
participant DB as Magico DB
|
||||||
|
participant T as TravelManager
|
||||||
|
|
||||||
|
U->>M: Kliknięcie "Aktywuj TravelManager"
|
||||||
|
M->>DB: Pobierz listę użytkowników firmy
|
||||||
|
DB->>M: Lista użytkowników
|
||||||
|
M->>T: POST /api/tenant (company_name, company_id, users[])
|
||||||
|
T->>T: Tworzenie tenanta + import użytkowników
|
||||||
|
T->>M: 201 Tenant created with users
|
||||||
|
M->>U: Aplikacja aktywowana pomyślnie
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flow synchronizacji zmian
|
||||||
|

|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant A as Admin/System
|
||||||
|
participant M as Magico.pro
|
||||||
|
participant DB as Magico DB
|
||||||
|
participant T as TravelManager
|
||||||
|
|
||||||
|
A->>M: Dodanie/edycja/usunięcie użytkownika
|
||||||
|
M->>DB: Aktualizacja danych użytkownika
|
||||||
|
M->>DB: Pobierz aktualną listę użytkowników firmy
|
||||||
|
DB->>M: Aktualna lista użytkowników
|
||||||
|
M->>T: PUT /api/tenant/{company_id}/users (users[])
|
||||||
|
T->>T: Synchronizacja użytkowników
|
||||||
|
T->>M: 200 Users synchronized
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bezpieczeństwo i tokeny
|
||||||
|
|
||||||
|
### Tokeny systemowe
|
||||||
|
|
||||||
|
- **Magico System Token** - używany do tworzenia tenantów i synchronizacji użytkowników w TravelManager
|
||||||
|
|
||||||
|
### Konfiguracja tokenów
|
||||||
|
|
||||||
|
Tokeny muszą być skonfigurowane w:
|
||||||
|
- **Magico** - endpoint TravelManager dla tworzenia tenantów i synchronizacji użytkowników
|
||||||
|
- **TravelManager** - autoryzacja zapytań od systemu Magico
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Obsługa błędów
|
||||||
|
|
||||||
|
### Scenariusze błędów
|
||||||
|
|
||||||
|
1. **Błąd tworzenia tenanta z użytkownikami**
|
||||||
|
- Logowanie błędu w systemie Magico
|
||||||
|
- Informowanie użytkownika o problemie z aktywacją
|
||||||
|
- Rollback - brak utworzenia tenanta
|
||||||
|
|
||||||
|
2. **Błąd synchronizacji użytkowników**
|
||||||
|
- Logowanie błędu synchronizacji
|
||||||
|
- Retry automatyczny po określonym czasie
|
||||||
|
- Alert dla administratorów o problemach synchronizacji
|
||||||
|
|
||||||
|
3. **Problemy z tokenami**
|
||||||
|
- Sprawdzanie ważności tokena systemowego Magico
|
||||||
|
- Procedury odnawiania tokenów
|
||||||
|
|
||||||
|
### Retry i ponowne próby
|
||||||
|
|
||||||
|
- **Retry logic** dla zapytań synchronizacji użytkowników (maksymalnie 3 próby)
|
||||||
|
- **Timeout** dla długotrwałych operacji (30 sekund)
|
||||||
|
- **Kolejka zadań** dla operacji synchronizacji w przypadku błędów
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Logi systemowe
|
||||||
|
|
||||||
|
Każda operacja powinna być logowana:
|
||||||
|
- Aktywacja aplikacji przez użytkownika
|
||||||
|
- Tworzenie tenanta z użytkownikami
|
||||||
|
- Synchronizacja zmian użytkowników (dodanie, usunięcie, modyfikacja)
|
||||||
|
- Błędy i wyjątki
|
||||||
|
|
||||||
330
ID_MAGICO_AUTH_PROCCESS.md
Normal file
330
ID_MAGICO_AUTH_PROCCESS.md
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
# Logowanie i ustawianie sesji z Id Magico
|
||||||
|
|
||||||
|
Dokumentacja autentykacji przez Id Magico (https://id.magico.pro) i ustawiania sesji w API TravelManager.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Przegląd
|
||||||
|
|
||||||
|
API TravelManager korzysta z **Id Magico** jako centralnego systemu autentykacji. Pełny flow:
|
||||||
|
|
||||||
|
1. **OAuth** – przekierowanie użytkownika do Id Magico, otrzymanie `code`
|
||||||
|
2. **Token** – wymiana `code` na `access_token`
|
||||||
|
3. **Sesja** – użycie tokena w `POST v1/auth/session` do ustawienia sesji w API TravelManager
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 1: Uzyskiwanie tokena (OAuth 2.0 – Authorization Code)
|
||||||
|
|
||||||
|
### 1.1. Generowanie linku autoryzacyjnego
|
||||||
|
|
||||||
|
Przekieruj użytkownika do Id Magico, aby się zalogował. Skonstruuj URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET {id.baseURL}oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&scope={scope}&state={state}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parametr | Opis |
|
||||||
|
|----------------|----------------------------------------------------------------------|
|
||||||
|
| `client_id` | ID aplikacji w Id Magico (otrzymane przy rejestracji klienta OAuth) |
|
||||||
|
| `redirect_uri` | Adres powrotu po autoryzacji – musi być zarejestrowany w Id Magico |
|
||||||
|
| `response_type`| Stała: `code` |
|
||||||
|
| `scope` | Zakres uprawnień (np. `openid`, `profile` – wg dokumentacji Id Magico) |
|
||||||
|
| `state` | Losowy ciąg do weryfikacji (zabezpieczenie CSRF) |
|
||||||
|
|
||||||
|
**Przykład:**
|
||||||
|
|
||||||
|
```
|
||||||
|
https://id.magico.pro/oauth/authorize?client_id=travelmanager&redirect_uri=https://manager.travel360.pl/auth/callback&response_type=code&scope=openid&state=abc123xyz
|
||||||
|
```
|
||||||
|
|
||||||
|
Użytkownik zaloguje się w Id Magico. Po akceptacji zostanie przekierowany z powrotem na `redirect_uri` z parametrem `code`:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://manager.travel360.pl/auth/callback?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&state=abc123xyz
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2. Wymiana code na access_token
|
||||||
|
|
||||||
|
Wyślij żądanie POST do endpointu tokenów Id Magico:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST {id.baseURL}oauth/token
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
grant_type=authorization_code&code={code}&redirect_uri={redirect_uri}&client_id={client_id}&client_secret={client_secret}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parametr | Opis |
|
||||||
|
|-----------------|---------------------------------------------------------------|
|
||||||
|
| `grant_type` | Stała: `authorization_code` |
|
||||||
|
| `code` | Kod autoryzacyjny z kroku 1 (jeden raz, krótko ważny) |
|
||||||
|
| `redirect_uri` | Ten sam adres co w żądaniu autoryzacji |
|
||||||
|
| `client_id` | ID aplikacji |
|
||||||
|
| `client_secret` | Tajny klucz aplikacji (tylko po stronie serwera) |
|
||||||
|
|
||||||
|
**Przykład odpowiedzi (200):**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 3600
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Krok 2: Ustawianie sesji w API TravelManager
|
||||||
|
|
||||||
|
Mając `access_token` z kroku 1, wywołaj endpoint sesji API TravelManager.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Endpoint ustawiania sesji
|
||||||
|
|
||||||
|
**POST** `v1/auth/session`
|
||||||
|
|
||||||
|
Weryfikuje token Bearer z Id Magico i ustawia sesję. W tym miejscu zwracany jest company_id (tenant_id), używany do rozróźnienia tenanta na backendzie
|
||||||
|
|
||||||
|
### Nagłówek
|
||||||
|
|
||||||
|
```
|
||||||
|
Authorization: Bearer {token_z_id_magico}
|
||||||
|
Content-Type: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Przykładowe żądanie
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /v1/auth/session
|
||||||
|
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
|
||||||
|
Accept: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź sukces (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": true,
|
||||||
|
"message": "is login"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź błąd (401)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": false,
|
||||||
|
"message": "401 Unauthorized"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Błąd 401 zwracany jest gdy:
|
||||||
|
- token jest nieprawidłowy lub wygasły,
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Co jest zapisywane w sesji
|
||||||
|
|
||||||
|
Po poprawnym wywołaniu `v1/auth/session` w sesji zapisywane są m.in.:
|
||||||
|
|
||||||
|
| Klucz sesji | Opis |
|
||||||
|
|---------------|--------------------------------------------------|
|
||||||
|
| `userdata` | Obiekt z danymi użytkownika (patrz niżej) |
|
||||||
|
| `user_id` | ID użytkownika z Id Magico |
|
||||||
|
|
||||||
|
### Struktura `userdata`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "jan.kowalski",
|
||||||
|
"id": 123,
|
||||||
|
"user_id": 123,
|
||||||
|
"level": "admin",
|
||||||
|
"image": "https://...",
|
||||||
|
"name": "Jan Kowalski",
|
||||||
|
"client_id": 123,
|
||||||
|
"guid": "uuid-guid",
|
||||||
|
"company_id": 123,
|
||||||
|
"token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Pole | Opis |
|
||||||
|
|-------------|-------------------------------------------|
|
||||||
|
| `username` | Login użytkownika |
|
||||||
|
| `user_id` | ID użytkownika w Id Magico |
|
||||||
|
| `level` | Rola (np. `admin`) |
|
||||||
|
| `company_id`| ID firmy |
|
||||||
|
| `token` | Token Bearer z Id Magico |
|
||||||
|
| `guid` | Identyfikator GUID z Id Magico |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wylogowanie
|
||||||
|
|
||||||
|
**GET** `v1/auth/logout`
|
||||||
|
**POST** `v1/auth/logout`
|
||||||
|
|
||||||
|
Niszczy sesję i usuwa dane użytkownika.
|
||||||
|
|
||||||
|
### Przykład
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /v1/auth/logout
|
||||||
|
Cookie: app_session=...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Odpowiedź (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": true,
|
||||||
|
"message": "logout"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Weryfikacja tokena w Id Magico
|
||||||
|
|
||||||
|
API TravelManager weryfikuje token przez wywołanie Id Magico:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET {magico.auth.serwer}api/v1/authorize/me
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
Accept: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
Zmienna środowiskowa: `magico.auth.serwer` (np. `https://id.magico.pro/`).
|
||||||
|
|
||||||
|
### Oczekiwana odpowiedź Id Magico
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"user": {
|
||||||
|
"username": "jan.kowalski",
|
||||||
|
"user_id": 123,
|
||||||
|
"image": "https://...",
|
||||||
|
"name": "Jan Kowalski"
|
||||||
|
},
|
||||||
|
"company_id": 123,
|
||||||
|
"role": "admin",
|
||||||
|
"guid": "uuid-guid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flow integracji (pełny przebieg)
|
||||||
|
|
||||||
|
1. **Generuj link** do Id Magico (Krok 1.1) i przekieruj użytkownika.
|
||||||
|
2. Po zalogowaniu Id Magico przekierowuje na `redirect_uri` z parametrem `code`.
|
||||||
|
3. **Wymień `code` na token** – POST do Id Magico `/oauth/token` (Krok 1.2).
|
||||||
|
4. **Ustaw sesję** – `POST v1/auth/session` z nagłówkiem `Authorization: Bearer {access_token}`.
|
||||||
|
5. API zwraca `200` i ustawia sesję (ciastko `app_session`).
|
||||||
|
6. Kolejne żądania do chronionych endpointów wysyłają ciastko sesji.
|
||||||
|
7. Przy wylogowaniu: `POST v1/auth/logout`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Diagram sekwencji procesu autentykacji
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant User as Użytkownik
|
||||||
|
participant App as Aplikacja TravelManager
|
||||||
|
participant IdMagico as Id Magico
|
||||||
|
participant API as TravelManager API
|
||||||
|
|
||||||
|
Note over User, API: OAuth 2.0 Authorization Code Flow
|
||||||
|
|
||||||
|
User->>App: Chce się zalogować
|
||||||
|
App->>User: Przekierowanie do Id Magico
|
||||||
|
Note right of App: GET /oauth/authorize?<br/>client_id={client_id}&<br/>redirect_uri={redirect_uri}&<br/>response_type=code&<br/>scope={scope}&<br/>state={state}
|
||||||
|
|
||||||
|
User->>IdMagico: Logowanie użytkownika
|
||||||
|
IdMagico->>User: Formularz logowania
|
||||||
|
User->>IdMagico: Dane logowania
|
||||||
|
IdMagico->>User: Przekierowanie z kodem
|
||||||
|
Note right of IdMagico: Redirect na: {redirect_uri}?<br/>code={authorization_code}&<br/>state={state}
|
||||||
|
|
||||||
|
User->>App: Powrót z kodem autoryzacyjnym
|
||||||
|
App->>IdMagico: Wymiana code na token
|
||||||
|
Note right of App: POST /oauth/token<br/>grant_type=authorization_code<br/>code={code}<br/>client_id={client_id}<br/>client_secret={client_secret}
|
||||||
|
|
||||||
|
IdMagico->>App: access_token
|
||||||
|
Note left of IdMagico: {<br/>"access_token": "eyJ...",<br/>"token_type": "Bearer",<br/>"expires_in": 3600<br/>}
|
||||||
|
|
||||||
|
App->>API: Ustawienie sesji
|
||||||
|
Note right of App: POST /v1/auth/session<br/>Authorization: Bearer {access_token}
|
||||||
|
|
||||||
|
API->>IdMagico: Weryfikacja tokena
|
||||||
|
Note right of API: GET /api/v1/authorize/me<br/>Authorization: Bearer {access_token}
|
||||||
|
|
||||||
|
IdMagico->>API: Dane użytkownika
|
||||||
|
Note left of IdMagico: {<br/>"user": {...},<br/>"company_id": 123,<br/>"role": "admin"<br/>}
|
||||||
|
|
||||||
|
alt Użytkownik ma prawidłowy token
|
||||||
|
API->>API: Utworzenie sesji
|
||||||
|
API->>App: Sukces (200)
|
||||||
|
Note left of API: {<br/>"status": true,<br/>"message": "is login"<br/>}<br/>+ cookie app_session
|
||||||
|
App->>User: Zalogowany - dostęp do aplikacji
|
||||||
|
|
||||||
|
Note over User, API: Dalsze żądania z ciastkiem sesji
|
||||||
|
User->>App: Żądania do chronionych zasobów
|
||||||
|
App->>API: Żądania z cookie app_session
|
||||||
|
API->>App: Odpowiedzi (autoryzowane)
|
||||||
|
App->>User: Dane/funkcjonalność
|
||||||
|
|
||||||
|
Note over User, API: Wylogowanie
|
||||||
|
User->>App: Wyloguj
|
||||||
|
App->>API: POST /v1/auth/logout
|
||||||
|
API->>App: Sukces wylogowania
|
||||||
|
App->>User: Wylogowany
|
||||||
|
else Nieprawidłowy token lub brak uprawnień
|
||||||
|
API->>App: Błąd (401)
|
||||||
|
Note left of API: {<br/>"status": false,<br/>"message": "401 Unauthorized"<br/>}
|
||||||
|
App->>User: Błąd autoryzacji
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Endpointy chronione
|
||||||
|
|
||||||
|
Endpointy z filtrem `login` (np. `v1/project`, `v1/ticket`, `v1/setting`) wymagają:
|
||||||
|
- poprawnej sesji (ciastko `app_session`), lub
|
||||||
|
- wcześniejszego wywołania `POST v1/auth/session` z tokenem Bearer.
|
||||||
|
|
||||||
|
Brak sesji skutkuje odpowiedzią **401 Unauthorized**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": false,
|
||||||
|
"data": [],
|
||||||
|
"message": "Nieautoryzowany dostęp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfiguracja
|
||||||
|
|
||||||
|
| Zmienna | Opis |
|
||||||
|
|----------------------|-----------------------------------------------------|
|
||||||
|
| `magico.auth.serwer` | URL serwera Id Magico (np. `https://id.magico.pro/`) |
|
||||||
|
| `id.baseURL` | URL panelu Id Magico (np. `https://id.magico.pro/`) |
|
||||||
|
|
||||||
|
Dla OAuth (krok 1) potrzebujesz także `client_id` i `client_secret` aplikacji zarejestrowanej w Id Magico. `redirect_uri` musi być zgłoszony w konfiguracji klienta OAuth.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Uwagi
|
||||||
|
|
||||||
|
- Token Bearer jest przekazywany **tylko przy wywołaniu** `v1/auth/session`.
|
||||||
|
- Po ustawieniu sesji używane jest **ciastko sesji** (`app_session`), nie token w nagłówku.
|
||||||
BIN
tenant_auth.png
Normal file
BIN
tenant_auth.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
BIN
tenant_create_v1.png
Normal file
BIN
tenant_create_v1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
tenant_create_v2.png
Normal file
BIN
tenant_create_v2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
tenant_user_sync_v2.png
Normal file
BIN
tenant_user_sync_v2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
Reference in New Issue
Block a user