feat: update client-user
This commit is contained in:
parent
e1b11647c5
commit
adb0184035
|
|
@ -459,14 +459,11 @@ func (_i *clientsController) BulkCreateSubClients(c *fiber.Ctx) error {
|
|||
|
||||
// CreateClientWithUser creates a client and admin user in one request
|
||||
// @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
|
||||
// @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"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /clients/with-user [post]
|
||||
func (_i *clientsController) CreateClientWithUser(c *fiber.Ctx) error {
|
||||
|
|
@ -475,8 +472,7 @@ func (_i *clientsController) CreateClientWithUser(c *fiber.Ctx) error {
|
|||
return err
|
||||
}
|
||||
|
||||
authToken := c.Get("Authorization")
|
||||
result, err := _i.clientsService.CreateClientWithUser(*req, authToken)
|
||||
result, err := _i.clientsService.CreateClientWithUser(*req)
|
||||
if err != nil {
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: false,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ type ClientsService interface {
|
|||
BulkCreateSubClients(req request.BulkCreateSubClientsRequest) (*response.BulkOperationResponse, error)
|
||||
|
||||
// Client with user creation
|
||||
CreateClientWithUser(req request.ClientWithUserCreateRequest, authToken string) (*response.ClientWithUserResponse, error)
|
||||
CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error)
|
||||
}
|
||||
|
||||
// NewClientsService init ClientsService
|
||||
|
|
@ -310,8 +310,8 @@ func (_i *clientsService) BulkCreateSubClients(req request.BulkCreateSubClientsR
|
|||
}
|
||||
|
||||
// CreateClientWithUser creates a client and admin user in one transaction
|
||||
func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateRequest, authToken string) (*response.ClientWithUserResponse, error) {
|
||||
_i.Log.Info().Interface("data", req).Msg("Creating client with admin user")
|
||||
func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error) {
|
||||
_i.Log.Info().Interface("data", req).Msg("Creating client with admin user (Public endpoint)")
|
||||
|
||||
// Step 1: Create the client
|
||||
clientReq := req.Client
|
||||
|
|
@ -328,13 +328,8 @@ func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateR
|
|||
// Generate new UUID for client
|
||||
newClient.ID = uuid.New()
|
||||
|
||||
// Set created by if auth token provided
|
||||
if authToken != "" {
|
||||
createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
||||
if createdBy != nil {
|
||||
newClient.CreatedById = &createdBy.ID
|
||||
}
|
||||
}
|
||||
// For public endpoint, no created by user
|
||||
newClient.CreatedById = nil
|
||||
|
||||
// Create client
|
||||
createdClient, err := _i.Repo.Create(newClient)
|
||||
|
|
@ -364,13 +359,14 @@ func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateR
|
|||
IdentityNumber: adminUserReq.IdentityNumber,
|
||||
DateOfBirth: adminUserReq.DateOfBirth,
|
||||
LastEducation: adminUserReq.LastEducation,
|
||||
ClientId: &createdClient.ID,
|
||||
// Set default admin level and role (you may need to adjust these based on your system)
|
||||
UserLevelId: 1, // Assuming level 1 is admin level
|
||||
UserRoleId: 1, // Assuming role 1 is admin role
|
||||
}
|
||||
|
||||
// Create user with the new client ID
|
||||
createdUser, err := _i.UsersSvc.Save(authToken, userCreateReq)
|
||||
createdUser, err := _i.UsersSvc.Save("", userCreateReq)
|
||||
if err != nil {
|
||||
_i.Log.Error().Err(err).Msg("Failed to create admin user")
|
||||
// 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("createdClient", createdClient).Msg("Created Client")
|
||||
|
||||
// Step 3: Prepare response
|
||||
clientResponse := mapper.ClientsResponseMapper(createdClient)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import (
|
|||
"netidhub-saas-be/utils/paginator"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UsersGeneric interface {
|
||||
|
|
@ -28,22 +30,23 @@ type UsersQueryRequest struct {
|
|||
}
|
||||
|
||||
type UsersCreateRequest struct {
|
||||
Username string `json:"username" validate:"required,lowercase"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Fullname string `json:"fullname" validate:"required"`
|
||||
UserLevelId uint `json:"userLevelId" validate:"required"`
|
||||
UserRoleId uint `json:"userRoleId" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
PhoneNumber *string `json:"phoneNumber"`
|
||||
Address *string `json:"address"`
|
||||
WorkType *string `json:"workType"`
|
||||
GenderType *string `json:"genderType"`
|
||||
IdentityType *string `json:"identityType"`
|
||||
IdentityGroup *string `json:"identityGroup"`
|
||||
IdentityGroupNumber *string `json:"identityGroupNumber"`
|
||||
IdentityNumber *string `json:"identityNumber"`
|
||||
DateOfBirth *string `json:"dateOfBirth"`
|
||||
LastEducation *string `json:"lastEducation"`
|
||||
Username string `json:"username" validate:"required,lowercase"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Fullname string `json:"fullname" validate:"required"`
|
||||
UserLevelId uint `json:"userLevelId" validate:"required"`
|
||||
UserRoleId uint `json:"userRoleId" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
PhoneNumber *string `json:"phoneNumber"`
|
||||
Address *string `json:"address"`
|
||||
WorkType *string `json:"workType"`
|
||||
GenderType *string `json:"genderType"`
|
||||
IdentityType *string `json:"identityType"`
|
||||
IdentityGroup *string `json:"identityGroup"`
|
||||
IdentityGroupNumber *string `json:"identityGroupNumber"`
|
||||
IdentityNumber *string `json:"identityNumber"`
|
||||
DateOfBirth *string `json:"dateOfBirth"`
|
||||
LastEducation *string `json:"lastEducation"`
|
||||
ClientId *uuid.UUID `json:"clientId"`
|
||||
}
|
||||
|
||||
func (req UsersCreateRequest) ToEntity() *users.Users {
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@ func (_i *usersService) Save(authToken string, req request.UsersCreateRequest) (
|
|||
clientId = user.ClientId
|
||||
_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
|
||||
}
|
||||
} else {
|
||||
clientId = req.ClientId
|
||||
}
|
||||
|
||||
_i.Log.Info().Interface("data", req).Msg("")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
||||
## 🔧 **Request Body**
|
||||
## 📋 **Request Structure**
|
||||
|
||||
### **Headers**
|
||||
```
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
### **Request Body**
|
||||
```json
|
||||
{
|
||||
"client": {
|
||||
"name": "Client Name",
|
||||
"description": "Client description",
|
||||
"clientType": "standalone",
|
||||
"parentClientId": null,
|
||||
"maxUsers": 100,
|
||||
"maxStorage": 1073741824,
|
||||
"settings": "{\"theme\": \"dark\", \"language\": \"en\"}"
|
||||
},
|
||||
"clientName": "string (required)",
|
||||
"clientDescription": "string (optional)",
|
||||
"clientType": "string (required) - oneof: parent_client, sub_client, standalone",
|
||||
"parentClientId": "string (optional) - UUID format",
|
||||
"maxUsers": "integer (optional)",
|
||||
"maxStorage": "integer (optional) - in bytes",
|
||||
"adminUser": {
|
||||
"username": "admin",
|
||||
"email": "admin@client.com",
|
||||
"fullname": "Admin User",
|
||||
"password": "SecurePassword123!",
|
||||
"phoneNumber": "+6281234567890",
|
||||
"address": "Jakarta, Indonesia",
|
||||
"workType": "fulltime",
|
||||
"genderType": "male",
|
||||
"identityType": "ktp",
|
||||
"identityGroup": "employee",
|
||||
"identityGroupNumber": "EMP001",
|
||||
"identityNumber": "1234567890123456",
|
||||
"dateOfBirth": "1990-01-01",
|
||||
"lastEducation": "Bachelor"
|
||||
"username": "string (required)",
|
||||
"email": "string (required) - email format",
|
||||
"fullname": "string (required)",
|
||||
"password": "string (required) - min 8 characters",
|
||||
"address": "string (optional)",
|
||||
"phoneNumber": "string (optional)",
|
||||
"workType": "string (optional)",
|
||||
"genderType": "string (optional)",
|
||||
"identityType": "string (optional)",
|
||||
"identityGroup": "string (optional)",
|
||||
"identityGroupNumber": "string (optional)",
|
||||
"identityNumber": "string (optional)",
|
||||
"dateOfBirth": "string (optional)",
|
||||
"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**
|
||||
|
||||
### **Client Fields:**
|
||||
- `name` (required): Nama client
|
||||
- `description` (optional): Deskripsi client
|
||||
- `clientType` (required): Tipe client (`standalone`, `parent_client`, `sub_client`)
|
||||
- `parentClientId` (optional): ID parent client (untuk sub_client)
|
||||
- `maxUsers` (optional): Maksimal jumlah user
|
||||
- `maxStorage` (optional): Maksimal storage dalam bytes
|
||||
- `settings` (optional): Settings dalam format JSON string
|
||||
### **Client Fields**
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `clientName` | string | ✅ | Nama client |
|
||||
| `clientDescription` | string | ❌ | Deskripsi client |
|
||||
| `clientType` | string | ✅ | Tipe client: `parent_client`, `sub_client`, `standalone` |
|
||||
| `parentClientId` | string | ❌ | UUID parent client (untuk sub_client) |
|
||||
| `maxUsers` | integer | ❌ | Maksimal jumlah user |
|
||||
| `maxStorage` | integer | ❌ | Maksimal storage dalam bytes |
|
||||
|
||||
### **Admin User Fields:**
|
||||
- `username` (required): Username untuk login
|
||||
- `email` (required): Email address
|
||||
- `fullname` (required): Nama lengkap
|
||||
- `password` (required): Password untuk login
|
||||
- `phoneNumber` (optional): Nomor telepon
|
||||
- `address` (optional): Alamat
|
||||
- `workType` (optional): Tipe pekerjaan
|
||||
- `genderType` (optional): Jenis kelamin
|
||||
- `identityType` (optional): Tipe identitas
|
||||
- `identityGroup` (optional): Grup identitas
|
||||
- `identityGroupNumber` (optional): Nomor grup identitas
|
||||
- `identityNumber` (optional): Nomor identitas
|
||||
- `dateOfBirth` (optional): Tanggal lahir (YYYY-MM-DD)
|
||||
- `lastEducation` (optional): Pendidikan terakhir
|
||||
### **Admin User Fields**
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `username` | string | ✅ | Username untuk login |
|
||||
| `email` | string | ✅ | Email address (format email) |
|
||||
| `fullname` | string | ✅ | Nama lengkap |
|
||||
| `password` | string | ✅ | Password (min 8 karakter) |
|
||||
| `address` | string | ❌ | Alamat |
|
||||
| `phoneNumber` | string | ❌ | Nomor telepon |
|
||||
| `workType` | string | ❌ | Tipe pekerjaan |
|
||||
| `genderType` | string | ❌ | Jenis kelamin |
|
||||
| `identityType` | string | ❌ | Tipe identitas |
|
||||
| `identityGroup` | string | ❌ | Grup identitas |
|
||||
| `identityGroupNumber` | string | ❌ | Nomor grup identitas |
|
||||
| `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):**
|
||||
```json
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Required**: None (Public endpoint)
|
||||
- **Permission**: No authentication required
|
||||
- **Access**: Anyone can create a client and admin user
|
||||
|
||||
### **Error Response (400):**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["Validation failed: [Username is required, Email is required]"]
|
||||
}
|
||||
```
|
||||
## ⚠️ **Error Handling**
|
||||
|
||||
### **Error Response (500):**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["Failed to create admin user: Keycloak user creation failed"]
|
||||
}
|
||||
```
|
||||
### **Common Error Scenarios**
|
||||
|
||||
## 🧪 **Curl Examples**
|
||||
1. **Invalid Request Body (400)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["Invalid request body"],
|
||||
"code": 400
|
||||
}
|
||||
```
|
||||
|
||||
### **1. Create Standalone Client with Admin User:**
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/api/clients/with-user" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"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. **Validation Failed (400)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["Key: 'ClientWithUserCreateRequest.AdminUser.Email' Error:Field validation for 'Email' failed on the 'email' tag"],
|
||||
"code": 400
|
||||
}
|
||||
```
|
||||
|
||||
### **2. Create Sub Client with Admin User:**
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/api/clients/with-user" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"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. **User Creation Failed (500)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["failed to create admin user: username already exists"],
|
||||
"code": 500
|
||||
}
|
||||
```
|
||||
|
||||
### **3. Create Parent Client with Admin User:**
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/api/clients/with-user" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"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"
|
||||
}
|
||||
}'
|
||||
```
|
||||
4. **Invalid Parent Client ID (500)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"messages": ["invalid parent client ID: invalid UUID length: 5"],
|
||||
"code": 500
|
||||
}
|
||||
```
|
||||
|
||||
## 🔒 **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
|
||||
|
||||
```
|
||||
Authorization: Bearer YOUR_JWT_TOKEN
|
||||
```
|
||||
### **Data Relationships**
|
||||
- **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:
|
||||
- `userLevelId`: 1 (Admin level)
|
||||
- `userRoleId`: 1 (Admin role)
|
||||
### **Current Limitations**
|
||||
- **TODO**: Client repository belum diimplementasi (simulasi saja)
|
||||
- **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**
|
||||
|
||||
### **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!** 🚀
|
||||
Perfect untuk setup awal sistem multi-tenant dengan akses public! 🚀
|
||||
|
|
@ -9576,24 +9576,12 @@ const docTemplate = `{
|
|||
},
|
||||
"/clients/with-user": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"summary": "Create client with admin user",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"default": "Bearer \u003cAdd access token here\u003e",
|
||||
"description": "Insert your access token",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
{
|
||||
"description": "Required payload",
|
||||
"name": "payload",
|
||||
|
|
@ -9617,12 +9605,6 @@ const docTemplate = `{
|
|||
"$ref": "#/definitions/response.BadRequestError"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.UnauthorizedError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
|
|
@ -18275,6 +18257,9 @@ const docTemplate = `{
|
|||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
"dateOfBirth": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9565,24 +9565,12 @@
|
|||
},
|
||||
"/clients/with-user": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"summary": "Create client with admin user",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"default": "Bearer \u003cAdd access token here\u003e",
|
||||
"description": "Insert your access token",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
{
|
||||
"description": "Required payload",
|
||||
"name": "payload",
|
||||
|
|
@ -9606,12 +9594,6 @@
|
|||
"$ref": "#/definitions/response.BadRequestError"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.UnauthorizedError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
|
|
@ -18264,6 +18246,9 @@
|
|||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
"dateOfBirth": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1463,6 +1463,8 @@ definitions:
|
|||
properties:
|
||||
address:
|
||||
type: string
|
||||
clientId:
|
||||
type: string
|
||||
dateOfBirth:
|
||||
type: string
|
||||
email:
|
||||
|
|
@ -7970,12 +7972,8 @@ paths:
|
|||
/clients/with-user:
|
||||
post:
|
||||
description: API for creating a client and its admin user in a single request
|
||||
(Public endpoint)
|
||||
parameters:
|
||||
- default: Bearer <Add access token here>
|
||||
description: Insert your access token
|
||||
in: header
|
||||
name: Authorization
|
||||
type: string
|
||||
- description: Required payload
|
||||
in: body
|
||||
name: payload
|
||||
|
|
@ -7991,16 +7989,10 @@ paths:
|
|||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.BadRequestError'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.UnauthorizedError'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.InternalServerError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Create client with admin user
|
||||
tags:
|
||||
- Clients
|
||||
|
|
|
|||
Loading…
Reference in New Issue