216 lines
6.2 KiB
Markdown
216 lines
6.2 KiB
Markdown
|
|
# Client Profile API Documentation
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
API endpoint untuk mendapatkan detail client berdasarkan client ID yang diambil dari auth token, tanpa perlu menyertakan client ID sebagai path parameter.
|
||
|
|
|
||
|
|
## Endpoint
|
||
|
|
|
||
|
|
### Get Client Profile
|
||
|
|
**GET** `/clients/profile`
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
Mendapatkan detail client yang sedang login menggunakan client ID dari auth token.
|
||
|
|
|
||
|
|
#### Parameters
|
||
|
|
- Tidak ada path parameter, client ID diambil dari auth token
|
||
|
|
|
||
|
|
#### Headers
|
||
|
|
- **Authorization** (required): Bearer token untuk autentikasi user
|
||
|
|
|
||
|
|
#### Response
|
||
|
|
|
||
|
|
##### Success Response (200)
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"messages": ["Client profile successfully retrieved"],
|
||
|
|
"data": {
|
||
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||
|
|
"name": "Client Name",
|
||
|
|
"description": "Client description",
|
||
|
|
"clientType": "standalone",
|
||
|
|
"parentClientId": null,
|
||
|
|
"logoUrl": "https://example.com/logo.png",
|
||
|
|
"logoImagePath": "clients/logos/client-id/logo.png",
|
||
|
|
"address": "Jl. Example No. 123",
|
||
|
|
"phoneNumber": "+62-123-456-7890",
|
||
|
|
"website": "https://example.com",
|
||
|
|
"maxUsers": 100,
|
||
|
|
"maxStorage": 1073741824,
|
||
|
|
"settings": "{\"theme\": \"dark\"}",
|
||
|
|
"isActive": true,
|
||
|
|
"createdAt": "2024-01-01T00:00:00Z",
|
||
|
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||
|
|
"parentClient": null,
|
||
|
|
"subClients": []
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
##### Response Fields
|
||
|
|
- **id** (string): UUID client
|
||
|
|
- **name** (string): Nama client
|
||
|
|
- **description** (string): Deskripsi client
|
||
|
|
- **clientType** (string): Tipe client (`parent_client`, `sub_client`, `standalone`)
|
||
|
|
- **parentClientId** (string, nullable): ID parent client (untuk sub client)
|
||
|
|
- **logoUrl** (string, nullable): URL logo client
|
||
|
|
- **logoImagePath** (string, nullable): Path logo di MinIO storage
|
||
|
|
- **address** (string, nullable): Alamat client
|
||
|
|
- **phoneNumber** (string, nullable): Nomor telepon client
|
||
|
|
- **website** (string, nullable): Website resmi client
|
||
|
|
- **maxUsers** (integer, nullable): Batas maksimal user
|
||
|
|
- **maxStorage** (integer, nullable): Batas maksimal storage dalam bytes
|
||
|
|
- **settings** (string, nullable): JSON string untuk custom settings
|
||
|
|
- **isActive** (boolean, nullable): Status aktif client
|
||
|
|
- **createdAt** (string): Tanggal pembuatan
|
||
|
|
- **updatedAt** (string): Tanggal terakhir diupdate
|
||
|
|
- **parentClient** (object, nullable): Informasi parent client
|
||
|
|
- **subClients** (array): Daftar sub clients
|
||
|
|
|
||
|
|
#### Error Responses
|
||
|
|
|
||
|
|
##### 401 Unauthorized
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": false,
|
||
|
|
"messages": ["user not found"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
##### 500 Internal Server Error
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": false,
|
||
|
|
"messages": ["client ID not found in user token"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### cURL Example
|
||
|
|
```bash
|
||
|
|
curl -X GET "http://localhost:8080/clients/profile" \
|
||
|
|
-H "Authorization: Bearer YOUR_TOKEN_HERE"
|
||
|
|
```
|
||
|
|
|
||
|
|
### JavaScript Example
|
||
|
|
```javascript
|
||
|
|
const getClientProfile = async () => {
|
||
|
|
try {
|
||
|
|
const response = await fetch('/clients/profile', {
|
||
|
|
method: 'GET',
|
||
|
|
headers: {
|
||
|
|
'Authorization': `Bearer ${token}`,
|
||
|
|
'Content-Type': 'application/json'
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.success) {
|
||
|
|
console.log('Client profile:', data.data);
|
||
|
|
return data.data;
|
||
|
|
} else {
|
||
|
|
console.error('Failed to get profile:', data.messages);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error getting client profile:', error);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Usage
|
||
|
|
const profile = await getClientProfile();
|
||
|
|
if (profile) {
|
||
|
|
console.log('Client name:', profile.name);
|
||
|
|
console.log('Client type:', profile.clientType);
|
||
|
|
console.log('Max users:', profile.maxUsers);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### React Hook Example
|
||
|
|
```javascript
|
||
|
|
import { useState, useEffect } from 'react';
|
||
|
|
|
||
|
|
const useClientProfile = (token) => {
|
||
|
|
const [profile, setProfile] = useState(null);
|
||
|
|
const [loading, setLoading] = useState(true);
|
||
|
|
const [error, setError] = useState(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const fetchProfile = async () => {
|
||
|
|
try {
|
||
|
|
setLoading(true);
|
||
|
|
const response = await fetch('/clients/profile', {
|
||
|
|
headers: {
|
||
|
|
'Authorization': `Bearer ${token}`,
|
||
|
|
'Content-Type': 'application/json'
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.success) {
|
||
|
|
setProfile(data.data);
|
||
|
|
setError(null);
|
||
|
|
} else {
|
||
|
|
setError(data.messages[0]);
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
setError('Failed to fetch client profile');
|
||
|
|
} finally {
|
||
|
|
setLoading(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
if (token) {
|
||
|
|
fetchProfile();
|
||
|
|
}
|
||
|
|
}, [token]);
|
||
|
|
|
||
|
|
return { profile, loading, error };
|
||
|
|
};
|
||
|
|
|
||
|
|
// Usage in component
|
||
|
|
const ClientProfile = () => {
|
||
|
|
const { profile, loading, error } = useClientProfile(token);
|
||
|
|
|
||
|
|
if (loading) return <div>Loading...</div>;
|
||
|
|
if (error) return <div>Error: {error}</div>;
|
||
|
|
if (!profile) return <div>No profile found</div>;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<h1>{profile.name}</h1>
|
||
|
|
<p>{profile.description}</p>
|
||
|
|
<p>Type: {profile.clientType}</p>
|
||
|
|
<p>Max Users: {profile.maxUsers}</p>
|
||
|
|
{profile.logoUrl && <img src={profile.logoUrl} alt="Logo" />}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
## Use Cases
|
||
|
|
1. **Profile Display**: Menampilkan profil client di dashboard
|
||
|
|
2. **Settings Page**: Mengambil data client untuk halaman pengaturan
|
||
|
|
3. **Header/Navigation**: Menampilkan nama dan logo client di header
|
||
|
|
4. **Client Information**: Menampilkan informasi kontak client
|
||
|
|
5. **Resource Monitoring**: Mengecek batas user dan storage yang tersedia
|
||
|
|
6. **Logo Display**: Menampilkan logo client di berbagai halaman
|
||
|
|
|
||
|
|
## Security Features
|
||
|
|
- **Authentication Required**: Harus menggunakan Bearer token yang valid
|
||
|
|
- **Client Isolation**: User hanya bisa melihat profil client mereka sendiri
|
||
|
|
- **Token Validation**: Client ID diambil dari token yang sudah diverifikasi
|
||
|
|
- **No Path Parameters**: Tidak ada client ID yang bisa diubah di URL
|
||
|
|
|
||
|
|
## Notes
|
||
|
|
- Endpoint ini menggunakan middleware `UserMiddleware` untuk mengekstrak informasi user dari JWT token
|
||
|
|
- Client ID diambil dari `user.ClientId` dalam token
|
||
|
|
- Jika user tidak ditemukan atau client ID tidak ada dalam token, akan mengembalikan error
|
||
|
|
- Endpoint ini lebih aman daripada endpoint show dengan path parameter karena mencegah user melihat profil client lain
|
||
|
|
- Response mencakup semua informasi client termasuk parent client dan sub clients jika ada
|
||
|
|
- Field yang nullable akan berisi `null` jika tidak ada data
|