chore: add createclientbyadmin

This commit is contained in:
2026-03-13 21:44:15 +01:00
parent 9cb50bb625
commit a5f995cca9
11 changed files with 5046 additions and 13 deletions
+61
View File
@@ -274,6 +274,67 @@ func RegisterClient(c *gin.Context) {
})
}
// AdminCreateClient crée un client depuis l'interface admin (sans session ni token)
// POST /api/v2/admin/protected/clients
func AdminCreateClient(c *gin.Context) {
var req RegisterClientRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides"})
return
}
if !validatePhoneNumber(req.Telephone) {
c.JSON(http.StatusBadRequest, gin.H{"error": "Numéro de téléphone invalide"})
return
}
normalizedPhone := normalizePhoneNumber(req.Telephone)
database := c.MustGet("database").(*db.Database)
if existing, _ := database.GetClientByUsername(req.Username); existing != nil {
c.JSON(http.StatusConflict, gin.H{"error": "Nom d'utilisateur déjà utilisé"})
return
}
if existing, _ := database.GetClientByTelephone(normalizedPhone); existing != nil {
c.JSON(http.StatusConflict, gin.H{"error": "Ce numéro de téléphone est déjà utilisé"})
return
}
hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur traitement mot de passe"})
return
}
client := &models.Client{
Username: req.Username,
Password: string(hashed),
Nom: strings.TrimSpace(req.Nom),
Prenom: strings.TrimSpace(req.Prenom),
Telephone: normalizedPhone,
}
if err := database.CreateClient(client); err != nil {
log.Printf("❌ [ADMIN_CREATE_CLIENT] Erreur création: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur création client"})
return
}
log.Printf("✅ [ADMIN_CREATE_CLIENT] Client créé par admin: %s (ID=%d)", client.Username, client.ID)
c.JSON(http.StatusCreated, gin.H{
"message": "Client créé avec succès",
"client": gin.H{
"id": client.ID,
"username": client.Username,
"nom": client.Nom,
"prenom": client.Prenom,
"telephone": client.Telephone,
},
})
}
// LoginClient authentifie un client
// POST /api/v1/auth/login
func LoginClient(c *gin.Context) {
+1 -1
View File
@@ -32,7 +32,6 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
// ============================================
authGroupV1 := router.Group("/api/v1/auth")
{
authGroupV1.POST("/register", handlers.RegisterClient)
authGroupV1.POST("/login", handlers.LoginClient)
authGroupV1.POST("/logout", handlers.LogoutClient)
}
@@ -154,6 +153,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
// ⭐⭐ MODIFICATION DE PROFILS PAR ADMIN
adminGroupV2.PUT("/clients/:id", handlers.UpdateClientByAdmin) // ✅ Modifier un client
adminGroupV2.PUT("/users/:id", handlers.UpdateUserByAdmin) // ✅ Modifier un user
adminGroupV2.POST("/clients", handlers.AdminCreateClient)
adminGroupV2.DELETE("/clients/:id", handlers.DeleteClient)
adminGroupV2.DELETE("/users/:id", handlers.DeleteUser)
adminGroupV2.POST("/users", handlers.CreateUser)
+29
View File
@@ -0,0 +1,29 @@
const { getDefaultConfig } = require('expo/metro-config');
const IS_PROD = process.env.NODE_ENV === 'production';
const config = getDefaultConfig(__dirname);
if (IS_PROD) {
config.transformer = {
...config.transformer,
babelTransformerPath: require.resolve('react-native-obfuscating-transformer'),
obfuscatorOptions: {
compact: true,
identifierNamesGenerator: 'hexadecimal',
renameGlobals: false,
rotateStringArray: true,
stringArray: true,
stringArrayEncoding: ['base64'],
stringArrayThreshold: 0.75,
// Disabled: incompatible with Hermes
selfDefending: false,
controlFlowFlattening: false,
deadCodeInjection: false,
transformObjectKeys: false,
debugProtection: false,
},
};
}
module.exports = config;
+1639
View File
File diff suppressed because it is too large Load Diff
+1641
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -40,6 +40,8 @@
"devDependencies": {
"@expo/ngrok": "^4.1.3",
"@types/react": "~19.1.0",
"javascript-obfuscator": "^4.1.1",
"react-native-obfuscating-transformer": "^1.0.0",
"typescript": "~5.9.2"
},
"private": true
+2 -2
View File
@@ -427,13 +427,13 @@ export const createClientByAdmin = async (data: {
telephone: string;
}) => {
const { data: res } = await apiClient.post(
`https://uber-stup.club/api/v1/auth/register`,
`${V2}/admin/protected/clients`,
data,
);
return {
success: true,
message: res.message || "Client créé",
user: res.user,
client: res.client,
};
};
+29
View File
@@ -0,0 +1,29 @@
const { getDefaultConfig } = require('expo/metro-config');
const IS_PROD = process.env.NODE_ENV === 'production';
const config = getDefaultConfig(__dirname);
if (IS_PROD) {
config.transformer = {
...config.transformer,
babelTransformerPath: require.resolve('react-native-obfuscating-transformer'),
obfuscatorOptions: {
compact: true,
identifierNamesGenerator: 'hexadecimal',
renameGlobals: false,
rotateStringArray: true,
stringArray: true,
stringArrayEncoding: ['base64'],
stringArrayThreshold: 0.75,
// Disabled: incompatible with Hermes
selfDefending: false,
controlFlowFlattening: false,
deadCodeInjection: false,
transformObjectKeys: false,
debugProtection: false,
},
};
}
module.exports = config;
+1630
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -42,6 +42,8 @@
"devDependencies": {
"@expo/ngrok": "^4.1.3",
"@types/react": "~19.1.0",
"javascript-obfuscator": "^4.1.1",
"react-native-obfuscating-transformer": "^1.0.0",
"typescript": "~5.9.2"
},
"private": true,
+10 -10
View File
@@ -545,16 +545,16 @@ export default function CheckoutScreen() {
</Text>
</View>
)}
{confirmationData?.assigned_to && (
<View style={styles.confirmInfo}>
<Ionicons
name="bicycle-outline"
size={16}
color={colors.info}
/>
<Text style={styles.confirmInfoText}>Livreur</Text>
</View>
)}
<View style={styles.confirmInfo}>
<Ionicons
name="location-outline"
size={16}
color={colors.info}
/>
<Text style={styles.confirmInfoText}>
Suivez votre livraison en temps réel depuis la page Suivi
</Text>
</View>
<Button
title="Voir mes commandes"
onPress={handleConfirmClose}