feat: update client-user

This commit is contained in:
hanif salafi 2025-10-02 05:23:26 +07:00
parent e1b11647c5
commit adb0184035
8 changed files with 330 additions and 326 deletions

View File

@ -459,14 +459,11 @@ func (_i *clientsController) BulkCreateSubClients(c *fiber.Ctx) error {
// CreateClientWithUser creates a client and admin user in one request // CreateClientWithUser creates a client and admin user in one request
// @Summary Create client with admin user // @Summary Create client with admin user
// @Description API for creating a client and its admin user in a single request // @Description API for creating a client and its admin user in a single request (Public endpoint)
// @Tags Clients // @Tags Clients
// @Security Bearer
// @Param Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param payload body request.ClientWithUserCreateRequest true "Required payload" // @Param payload body request.ClientWithUserCreateRequest true "Required payload"
// @Success 200 {object} response.Response // @Success 200 {object} response.Response
// @Failure 400 {object} response.BadRequestError // @Failure 400 {object} response.BadRequestError
// @Failure 401 {object} response.UnauthorizedError
// @Failure 500 {object} response.InternalServerError // @Failure 500 {object} response.InternalServerError
// @Router /clients/with-user [post] // @Router /clients/with-user [post]
func (_i *clientsController) CreateClientWithUser(c *fiber.Ctx) error { func (_i *clientsController) CreateClientWithUser(c *fiber.Ctx) error {
@ -475,8 +472,7 @@ func (_i *clientsController) CreateClientWithUser(c *fiber.Ctx) error {
return err return err
} }
authToken := c.Get("Authorization") result, err := _i.clientsService.CreateClientWithUser(*req)
result, err := _i.clientsService.CreateClientWithUser(*req, authToken)
if err != nil { if err != nil {
return utilRes.Resp(c, utilRes.Response{ return utilRes.Resp(c, utilRes.Response{
Success: false, Success: false,

View File

@ -43,7 +43,7 @@ type ClientsService interface {
BulkCreateSubClients(req request.BulkCreateSubClientsRequest) (*response.BulkOperationResponse, error) BulkCreateSubClients(req request.BulkCreateSubClientsRequest) (*response.BulkOperationResponse, error)
// Client with user creation // Client with user creation
CreateClientWithUser(req request.ClientWithUserCreateRequest, authToken string) (*response.ClientWithUserResponse, error) CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error)
} }
// NewClientsService init ClientsService // NewClientsService init ClientsService
@ -310,8 +310,8 @@ func (_i *clientsService) BulkCreateSubClients(req request.BulkCreateSubClientsR
} }
// CreateClientWithUser creates a client and admin user in one transaction // CreateClientWithUser creates a client and admin user in one transaction
func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateRequest, authToken string) (*response.ClientWithUserResponse, error) { func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error) {
_i.Log.Info().Interface("data", req).Msg("Creating client with admin user") _i.Log.Info().Interface("data", req).Msg("Creating client with admin user (Public endpoint)")
// Step 1: Create the client // Step 1: Create the client
clientReq := req.Client clientReq := req.Client
@ -328,13 +328,8 @@ func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateR
// Generate new UUID for client // Generate new UUID for client
newClient.ID = uuid.New() newClient.ID = uuid.New()
// Set created by if auth token provided // For public endpoint, no created by user
if authToken != "" { newClient.CreatedById = nil
createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if createdBy != nil {
newClient.CreatedById = &createdBy.ID
}
}
// Create client // Create client
createdClient, err := _i.Repo.Create(newClient) createdClient, err := _i.Repo.Create(newClient)
@ -364,13 +359,14 @@ func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateR
IdentityNumber: adminUserReq.IdentityNumber, IdentityNumber: adminUserReq.IdentityNumber,
DateOfBirth: adminUserReq.DateOfBirth, DateOfBirth: adminUserReq.DateOfBirth,
LastEducation: adminUserReq.LastEducation, LastEducation: adminUserReq.LastEducation,
ClientId: &createdClient.ID,
// Set default admin level and role (you may need to adjust these based on your system) // Set default admin level and role (you may need to adjust these based on your system)
UserLevelId: 1, // Assuming level 1 is admin level UserLevelId: 1, // Assuming level 1 is admin level
UserRoleId: 1, // Assuming role 1 is admin role UserRoleId: 1, // Assuming role 1 is admin role
} }
// Create user with the new client ID // Create user with the new client ID
createdUser, err := _i.UsersSvc.Save(authToken, userCreateReq) createdUser, err := _i.UsersSvc.Save("", userCreateReq)
if err != nil { if err != nil {
_i.Log.Error().Err(err).Msg("Failed to create admin user") _i.Log.Error().Err(err).Msg("Failed to create admin user")
// Rollback: delete the created client // Rollback: delete the created client
@ -379,6 +375,7 @@ func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateR
} }
_i.Log.Info().Interface("userId", createdUser.ID).Msg("Admin user created successfully") _i.Log.Info().Interface("userId", createdUser.ID).Msg("Admin user created successfully")
_i.Log.Info().Interface("createdClient", createdClient).Msg("Created Client")
// Step 3: Prepare response // Step 3: Prepare response
clientResponse := mapper.ClientsResponseMapper(createdClient) clientResponse := mapper.ClientsResponseMapper(createdClient)

View File

@ -5,6 +5,8 @@ import (
"netidhub-saas-be/utils/paginator" "netidhub-saas-be/utils/paginator"
"strconv" "strconv"
"time" "time"
"github.com/google/uuid"
) )
type UsersGeneric interface { type UsersGeneric interface {
@ -28,22 +30,23 @@ type UsersQueryRequest struct {
} }
type UsersCreateRequest struct { type UsersCreateRequest struct {
Username string `json:"username" validate:"required,lowercase"` Username string `json:"username" validate:"required,lowercase"`
Email string `json:"email" validate:"required,email"` Email string `json:"email" validate:"required,email"`
Fullname string `json:"fullname" validate:"required"` Fullname string `json:"fullname" validate:"required"`
UserLevelId uint `json:"userLevelId" validate:"required"` UserLevelId uint `json:"userLevelId" validate:"required"`
UserRoleId uint `json:"userRoleId" validate:"required"` UserRoleId uint `json:"userRoleId" validate:"required"`
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
PhoneNumber *string `json:"phoneNumber"` PhoneNumber *string `json:"phoneNumber"`
Address *string `json:"address"` Address *string `json:"address"`
WorkType *string `json:"workType"` WorkType *string `json:"workType"`
GenderType *string `json:"genderType"` GenderType *string `json:"genderType"`
IdentityType *string `json:"identityType"` IdentityType *string `json:"identityType"`
IdentityGroup *string `json:"identityGroup"` IdentityGroup *string `json:"identityGroup"`
IdentityGroupNumber *string `json:"identityGroupNumber"` IdentityGroupNumber *string `json:"identityGroupNumber"`
IdentityNumber *string `json:"identityNumber"` IdentityNumber *string `json:"identityNumber"`
DateOfBirth *string `json:"dateOfBirth"` DateOfBirth *string `json:"dateOfBirth"`
LastEducation *string `json:"lastEducation"` LastEducation *string `json:"lastEducation"`
ClientId *uuid.UUID `json:"clientId"`
} }
func (req UsersCreateRequest) ToEntity() *users.Users { func (req UsersCreateRequest) ToEntity() *users.Users {

View File

@ -153,6 +153,8 @@ func (_i *usersService) Save(authToken string, req request.UsersCreateRequest) (
clientId = user.ClientId clientId = user.ClientId
_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token") _i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
} }
} else {
clientId = req.ClientId
} }
_i.Log.Info().Interface("data", req).Msg("") _i.Log.Info().Interface("data", req).Msg("")

View File

@ -1,282 +1,326 @@
# API Create Client with User # API Create Client + User
## 🚀 **Overview** ## 🎯 **Overview**
API ini memungkinkan Anda untuk membuat client dan admin user dalam satu request. Sangat berguna untuk setup awal sistem atau ketika Anda perlu membuat client baru dengan admin user yang sudah siap. API ini memungkinkan pembuatan Client dan Admin User dalam satu panggilan API. **Endpoint ini bersifat PUBLIC** dan tidak memerlukan authentication. Sangat berguna untuk setup awal sistem multi-tenant atau ketika perlu membuat client baru dengan admin user secara bersamaan.
## 📋 **Endpoint** ## 🚀 **Endpoint**
``` ```
POST /api/clients/with-user POST /api/clients/with-user
``` ```
## 🔧 **Request Body** ## 📋 **Request Structure**
### **Headers**
```
Content-Type: application/json
```
### **Request Body**
```json ```json
{ {
"client": { "clientName": "string (required)",
"name": "Client Name", "clientDescription": "string (optional)",
"description": "Client description", "clientType": "string (required) - oneof: parent_client, sub_client, standalone",
"clientType": "standalone", "parentClientId": "string (optional) - UUID format",
"parentClientId": null, "maxUsers": "integer (optional)",
"maxUsers": 100, "maxStorage": "integer (optional) - in bytes",
"maxStorage": 1073741824,
"settings": "{\"theme\": \"dark\", \"language\": \"en\"}"
},
"adminUser": { "adminUser": {
"username": "admin", "username": "string (required)",
"email": "admin@client.com", "email": "string (required) - email format",
"fullname": "Admin User", "fullname": "string (required)",
"password": "SecurePassword123!", "password": "string (required) - min 8 characters",
"phoneNumber": "+6281234567890", "address": "string (optional)",
"address": "Jakarta, Indonesia", "phoneNumber": "string (optional)",
"workType": "fulltime", "workType": "string (optional)",
"genderType": "male", "genderType": "string (optional)",
"identityType": "ktp", "identityType": "string (optional)",
"identityGroup": "employee", "identityGroup": "string (optional)",
"identityGroupNumber": "EMP001", "identityGroupNumber": "string (optional)",
"identityNumber": "1234567890123456", "identityNumber": "string (optional)",
"dateOfBirth": "1990-01-01", "dateOfBirth": "string (optional)",
"lastEducation": "Bachelor" "lastEducation": "string (optional)",
"userRoleId": "integer (required)",
"userLevelId": "integer (required)"
} }
} }
``` ```
## 📊 **Response Structure**
### **Success Response (200)**
```json
{
"success": true,
"messages": ["Client and admin user created successfully"],
"data": {
"client": {
"id": "uuid",
"name": "string",
"description": "string",
"clientType": "string",
"parentClientId": "string",
"maxUsers": "integer",
"maxStorage": "integer",
"isActive": "boolean",
"createdAt": "datetime"
},
"adminUser": {
"id": "integer",
"username": "string",
"email": "string",
"fullname": "string",
"address": "string",
"phoneNumber": "string",
"workType": "string",
"genderType": "string",
"identityType": "string",
"identityGroup": "string",
"identityGroupNumber": "string",
"identityNumber": "string",
"dateOfBirth": "string",
"lastEducation": "string",
"userRoleId": "integer",
"userLevelId": "integer",
"clientId": "string",
"statusId": "integer",
"isActive": "boolean",
"createdAt": "datetime"
},
"message": "Client and admin user created successfully"
}
}
```
### **Error Response (400/500)**
```json
{
"success": false,
"messages": ["Error message"],
"code": 400
}
```
## 🔧 **Usage Examples**
### **1. Create Standalone Client with Admin User**
```bash
curl -X POST "http://localhost:8080/api/clients/with-user" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Acme Corporation",
"clientDescription": "A leading technology company",
"clientType": "standalone",
"maxUsers": 100,
"maxStorage": 1073741824,
"adminUser": {
"username": "admin_acme",
"email": "admin@acme.com",
"fullname": "John Doe",
"password": "SecurePass123",
"address": "123 Tech Street, Silicon Valley",
"phoneNumber": "+1-555-0123",
"workType": "Full-time",
"genderType": "Male",
"identityType": "Passport",
"identityNumber": "P123456789",
"dateOfBirth": "1985-06-15",
"lastEducation": "Master Degree",
"userRoleId": 1,
"userLevelId": 1
}
}'
```
### **2. Create Sub Client with Admin User**
```bash
curl -X POST "http://localhost:8080/api/clients/with-user" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Acme Branch Office",
"clientDescription": "Branch office in New York",
"clientType": "sub_client",
"parentClientId": "550e8400-e29b-41d4-a716-446655440000",
"maxUsers": 50,
"maxStorage": 536870912,
"adminUser": {
"username": "admin_branch",
"email": "admin@branch.acme.com",
"fullname": "Jane Smith",
"password": "BranchPass123",
"address": "456 Business Ave, New York",
"phoneNumber": "+1-555-0456",
"workType": "Full-time",
"genderType": "Female",
"identityType": "Driver License",
"identityNumber": "DL987654321",
"dateOfBirth": "1990-03-22",
"lastEducation": "Bachelor Degree",
"userRoleId": 2,
"userLevelId": 2
}
}'
```
### **3. Create Parent Client with Admin User**
```bash
curl -X POST "http://localhost:8080/api/clients/with-user" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Global Enterprise",
"clientDescription": "Global enterprise with multiple branches",
"clientType": "parent_client",
"maxUsers": 1000,
"maxStorage": 10737418240,
"adminUser": {
"username": "super_admin",
"email": "superadmin@global.com",
"fullname": "Robert Johnson",
"password": "SuperSecure123",
"address": "789 Corporate Blvd, Global City",
"phoneNumber": "+1-555-0789",
"workType": "Full-time",
"genderType": "Male",
"identityType": "Passport",
"identityNumber": "P987654321",
"dateOfBirth": "1980-12-10",
"lastEducation": "PhD",
"userRoleId": 1,
"userLevelId": 1
}
}'
```
## 📝 **Field Descriptions** ## 📝 **Field Descriptions**
### **Client Fields:** ### **Client Fields**
- `name` (required): Nama client | Field | Type | Required | Description |
- `description` (optional): Deskripsi client |-------|------|----------|-------------|
- `clientType` (required): Tipe client (`standalone`, `parent_client`, `sub_client`) | `clientName` | string | ✅ | Nama client |
- `parentClientId` (optional): ID parent client (untuk sub_client) | `clientDescription` | string | ❌ | Deskripsi client |
- `maxUsers` (optional): Maksimal jumlah user | `clientType` | string | ✅ | Tipe client: `parent_client`, `sub_client`, `standalone` |
- `maxStorage` (optional): Maksimal storage dalam bytes | `parentClientId` | string | ❌ | UUID parent client (untuk sub_client) |
- `settings` (optional): Settings dalam format JSON string | `maxUsers` | integer | ❌ | Maksimal jumlah user |
| `maxStorage` | integer | ❌ | Maksimal storage dalam bytes |
### **Admin User Fields:** ### **Admin User Fields**
- `username` (required): Username untuk login | Field | Type | Required | Description |
- `email` (required): Email address |-------|------|----------|-------------|
- `fullname` (required): Nama lengkap | `username` | string | ✅ | Username untuk login |
- `password` (required): Password untuk login | `email` | string | ✅ | Email address (format email) |
- `phoneNumber` (optional): Nomor telepon | `fullname` | string | ✅ | Nama lengkap |
- `address` (optional): Alamat | `password` | string | ✅ | Password (min 8 karakter) |
- `workType` (optional): Tipe pekerjaan | `address` | string | ❌ | Alamat |
- `genderType` (optional): Jenis kelamin | `phoneNumber` | string | ❌ | Nomor telepon |
- `identityType` (optional): Tipe identitas | `workType` | string | ❌ | Tipe pekerjaan |
- `identityGroup` (optional): Grup identitas | `genderType` | string | ❌ | Jenis kelamin |
- `identityGroupNumber` (optional): Nomor grup identitas | `identityType` | string | ❌ | Tipe identitas |
- `identityNumber` (optional): Nomor identitas | `identityGroup` | string | ❌ | Grup identitas |
- `dateOfBirth` (optional): Tanggal lahir (YYYY-MM-DD) | `identityGroupNumber` | string | ❌ | Nomor grup identitas |
- `lastEducation` (optional): Pendidikan terakhir | `identityNumber` | string | ❌ | Nomor identitas |
| `dateOfBirth` | string | ❌ | Tanggal lahir |
| `lastEducation` | string | ❌ | Pendidikan terakhir |
| `userRoleId` | integer | ✅ | ID role user |
| `userLevelId` | integer | ✅ | ID level user |
## 📤 **Response** ## 🔒 **Authentication & Authorization**
### **Success Response (200):** - **Required**: None (Public endpoint)
```json - **Permission**: No authentication required
{ - **Access**: Anyone can create a client and admin user
"success": true,
"messages": ["Client 'Client Name' and admin user 'admin' created successfully"],
"data": {
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Client Name",
"description": "Client description",
"clientType": "standalone",
"parentClientId": null,
"maxUsers": 100,
"maxStorage": 1073741824,
"currentUsers": 1,
"currentStorage": null,
"settings": "{\"theme\": \"dark\", \"language\": \"en\"}",
"createdById": 1,
"isActive": true,
"createdAt": "2025-01-01T12:00:00Z",
"updatedAt": "2025-01-01T12:00:00Z"
},
"adminUser": {
"id": 123,
"username": "admin",
"email": "admin@client.com",
"fullname": "Admin User",
"userLevelId": 1,
"userRoleId": 1,
"phoneNumber": "+6281234567890",
"address": "Jakarta, Indonesia",
"workType": "fulltime",
"genderType": "male",
"identityType": "ktp",
"identityGroup": "employee",
"identityGroupNumber": "EMP001",
"identityNumber": "1234567890123456",
"dateOfBirth": "1990-01-01",
"lastEducation": "Bachelor",
"keycloakId": "550e8400-e29b-41d4-a716-446655440001",
"clientId": "550e8400-e29b-41d4-a716-446655440000",
"isActive": true,
"createdAt": "2025-01-01T12:00:00Z",
"updatedAt": "2025-01-01T12:00:00Z"
},
"message": "Client 'Client Name' and admin user 'admin' created successfully"
}
}
```
### **Error Response (400):** ## ⚠️ **Error Handling**
```json
{
"success": false,
"messages": ["Validation failed: [Username is required, Email is required]"]
}
```
### **Error Response (500):** ### **Common Error Scenarios**
```json
{
"success": false,
"messages": ["Failed to create admin user: Keycloak user creation failed"]
}
```
## 🧪 **Curl Examples** 1. **Invalid Request Body (400)**
```json
{
"success": false,
"messages": ["Invalid request body"],
"code": 400
}
```
### **1. Create Standalone Client with Admin User:** 2. **Validation Failed (400)**
```bash ```json
curl -X POST "http://localhost:8080/api/clients/with-user" \ {
-H "Content-Type: application/json" \ "success": false,
-H "Authorization: Bearer YOUR_TOKEN" \ "messages": ["Key: 'ClientWithUserCreateRequest.AdminUser.Email' Error:Field validation for 'Email' failed on the 'email' tag"],
-d '{ "code": 400
"client": { }
"name": "PT. Example Company", ```
"description": "A technology company",
"clientType": "standalone",
"maxUsers": 50,
"maxStorage": 5368709120,
"settings": "{\"theme\": \"light\", \"language\": \"id\"}"
},
"adminUser": {
"username": "admin",
"email": "admin@example.com",
"fullname": "John Admin",
"password": "SecurePass123!",
"phoneNumber": "+6281234567890",
"address": "Jakarta, Indonesia",
"workType": "fulltime",
"genderType": "male"
}
}'
```
### **2. Create Sub Client with Admin User:** 3. **User Creation Failed (500)**
```bash ```json
curl -X POST "http://localhost:8080/api/clients/with-user" \ {
-H "Content-Type: application/json" \ "success": false,
-H "Authorization: Bearer YOUR_TOKEN" \ "messages": ["failed to create admin user: username already exists"],
-d '{ "code": 500
"client": { }
"name": "PT. Example Branch Office", ```
"description": "Branch office of main company",
"clientType": "sub_client",
"parentClientId": "550e8400-e29b-41d4-a716-446655440000",
"maxUsers": 25,
"maxStorage": 2684354560
},
"adminUser": {
"username": "branch_admin",
"email": "branch@example.com",
"fullname": "Jane Branch Admin",
"password": "BranchPass123!",
"phoneNumber": "+6289876543210",
"address": "Surabaya, Indonesia"
}
}'
```
### **3. Create Parent Client with Admin User:** 4. **Invalid Parent Client ID (500)**
```bash ```json
curl -X POST "http://localhost:8080/api/clients/with-user" \ {
-H "Content-Type: application/json" \ "success": false,
-H "Authorization: Bearer YOUR_TOKEN" \ "messages": ["invalid parent client ID: invalid UUID length: 5"],
-d '{ "code": 500
"client": { }
"name": "PT. Parent Company", ```
"description": "Parent company that can have sub-clients",
"clientType": "parent_client",
"maxUsers": 200,
"maxStorage": 10737418240,
"settings": "{\"allowSubClients\": true, \"maxSubClients\": 10}"
},
"adminUser": {
"username": "parent_admin",
"email": "parent@company.com",
"fullname": "Parent Admin User",
"password": "ParentPass123!",
"phoneNumber": "+6281111111111",
"address": "Bandung, Indonesia",
"workType": "fulltime",
"genderType": "female",
"identityType": "ktp",
"identityNumber": "1234567890123456"
}
}'
```
## 🔒 **Authentication** ## 🎯 **Business Logic**
API ini memerlukan authentication token. Token harus disertakan di header: ### **Process Flow**
1. **Validate Request** menggunakan struct validation
2. **Generate Client ID** menggunakan UUID
3. **Parse Parent Client ID** jika ada
4. **Create Client Entity** dengan data yang diberikan
5. **Create Admin User Entity** dengan client ID yang baru
6. **Save User** menggunakan existing repository
7. **Update Client** dengan created user ID
8. **Return Response** dengan data client dan user
``` ### **Data Relationships**
Authorization: Bearer YOUR_JWT_TOKEN - **Client****Admin User**: One-to-One relationship
``` - **Parent Client****Sub Client**: One-to-Many relationship
## ⚠️ **Important Notes** ## 🔧 **Implementation Notes**
1. **User Level & Role**: Admin user akan otomatis diberikan: ### **Current Limitations**
- `userLevelId`: 1 (Admin level) - **TODO**: Client repository belum diimplementasi (simulasi saja)
- `userRoleId`: 1 (Admin role) - **TODO**: Keycloak integration untuk user creation
- **TODO**: Transaction rollback jika user creation gagal
- **Public Endpoint**: Tidak ada authentication, semua orang bisa akses
2. **Keycloak Integration**: User akan otomatis dibuat di Keycloak dengan `keycloakId` yang di-generate. ### **Future Enhancements**
- Implementasi client repository yang sesungguhnya
- Integration dengan Keycloak untuk user management
- Transaction management untuk data consistency
- Email notification untuk admin user
- Bulk client creation
- Rate limiting untuk public endpoint
- CAPTCHA untuk mencegah abuse
3. **Transaction Safety**: Jika pembuatan user gagal, client yang sudah dibuat akan di-rollback (dihapus). ## 📚 **Related APIs**
4. **Password Requirements**: Password harus memenuhi policy keamanan Keycloak. - `POST /api/users` - Create individual user
- `POST /api/clients` - Create individual client
- `GET /api/clients` - List all clients
- `GET /api/users` - List all users
5. **Email Uniqueness**: Email harus unique di seluruh sistem. ## 🎉 **Summary**
6. **Username Uniqueness**: Username harus unique di seluruh sistem. API ini memberikan kemudahan untuk:
- ✅ **Single API Call**: Membuat client dan admin user sekaligus
- ✅ **Public Access**: Tidak memerlukan authentication
- ✅ **Data Consistency**: Memastikan relasi client-user terhubung dengan benar
- ✅ **Flexible Configuration**: Mendukung berbagai tipe client
- ✅ **Comprehensive Validation**: Validasi lengkap untuk semua field
- ✅ **Detailed Response**: Response yang informatif dengan data lengkap
## 🚨 **Error Handling** Perfect untuk setup awal sistem multi-tenant dengan akses public! 🚀
### **Common Errors:**
1. **Validation Error (400)**:
- Missing required fields
- Invalid email format
- Invalid client type
2. **Authentication Error (401)**:
- Invalid or missing token
- Expired token
3. **Server Error (500)**:
- Keycloak connection failed
- Database error
- User creation failed
## 🔄 **Workflow**
1. **Validate Request**: Cek semua field yang required
2. **Create Client**: Buat client di database
3. **Create User in Keycloak**: Buat user di Keycloak
4. **Create User in Database**: Simpan user info di database
5. **Return Response**: Return client dan user info
## 📊 **Use Cases**
1. **Initial Setup**: Setup client baru dengan admin user
2. **Branch Office**: Buat branch office dengan admin lokal
3. **Subsidiary**: Buat subsidiary company dengan admin sendiri
4. **Multi-tenant**: Setup tenant baru dalam sistem multi-tenant
---
**API ini sangat berguna untuk setup awal sistem atau ketika Anda perlu membuat client baru dengan admin user yang sudah siap!** 🚀

View File

@ -9576,24 +9576,12 @@ const docTemplate = `{
}, },
"/clients/with-user": { "/clients/with-user": {
"post": { "post": {
"security": [ "description": "API for creating a client and its admin user in a single request (Public endpoint)",
{
"Bearer": []
}
],
"description": "API for creating a client and its admin user in a single request",
"tags": [ "tags": [
"Clients" "Clients"
], ],
"summary": "Create client with admin user", "summary": "Create client with admin user",
"parameters": [ "parameters": [
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{ {
"description": "Required payload", "description": "Required payload",
"name": "payload", "name": "payload",
@ -9617,12 +9605,6 @@ const docTemplate = `{
"$ref": "#/definitions/response.BadRequestError" "$ref": "#/definitions/response.BadRequestError"
} }
}, },
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": { "500": {
"description": "Internal Server Error", "description": "Internal Server Error",
"schema": { "schema": {
@ -18275,6 +18257,9 @@ const docTemplate = `{
"address": { "address": {
"type": "string" "type": "string"
}, },
"clientId": {
"type": "string"
},
"dateOfBirth": { "dateOfBirth": {
"type": "string" "type": "string"
}, },

View File

@ -9565,24 +9565,12 @@
}, },
"/clients/with-user": { "/clients/with-user": {
"post": { "post": {
"security": [ "description": "API for creating a client and its admin user in a single request (Public endpoint)",
{
"Bearer": []
}
],
"description": "API for creating a client and its admin user in a single request",
"tags": [ "tags": [
"Clients" "Clients"
], ],
"summary": "Create client with admin user", "summary": "Create client with admin user",
"parameters": [ "parameters": [
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{ {
"description": "Required payload", "description": "Required payload",
"name": "payload", "name": "payload",
@ -9606,12 +9594,6 @@
"$ref": "#/definitions/response.BadRequestError" "$ref": "#/definitions/response.BadRequestError"
} }
}, },
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": { "500": {
"description": "Internal Server Error", "description": "Internal Server Error",
"schema": { "schema": {
@ -18264,6 +18246,9 @@
"address": { "address": {
"type": "string" "type": "string"
}, },
"clientId": {
"type": "string"
},
"dateOfBirth": { "dateOfBirth": {
"type": "string" "type": "string"
}, },

View File

@ -1463,6 +1463,8 @@ definitions:
properties: properties:
address: address:
type: string type: string
clientId:
type: string
dateOfBirth: dateOfBirth:
type: string type: string
email: email:
@ -7970,12 +7972,8 @@ paths:
/clients/with-user: /clients/with-user:
post: post:
description: API for creating a client and its admin user in a single request description: API for creating a client and its admin user in a single request
(Public endpoint)
parameters: parameters:
- default: Bearer <Add access token here>
description: Insert your access token
in: header
name: Authorization
type: string
- description: Required payload - description: Required payload
in: body in: body
name: payload name: payload
@ -7991,16 +7989,10 @@ paths:
description: Bad Request description: Bad Request
schema: schema:
$ref: '#/definitions/response.BadRequestError' $ref: '#/definitions/response.BadRequestError'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.UnauthorizedError'
"500": "500":
description: Internal Server Error description: Internal Server Error
schema: schema:
$ref: '#/definitions/response.InternalServerError' $ref: '#/definitions/response.InternalServerError'
security:
- Bearer: []
summary: Create client with admin user summary: Create client with admin user
tags: tags:
- Clients - Clients