240 lines
6.9 KiB
Go
240 lines
6.9 KiB
Go
package handlers
|
|
|
|
import (
|
|
"aggios-app/backend/internal/domain"
|
|
"aggios-app/backend/internal/repository"
|
|
"aggios-app/backend/internal/service"
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type AgencyTemplateHandler struct {
|
|
templateRepo *repository.AgencyTemplateRepository
|
|
agencyService *service.AgencyService
|
|
userRepo *repository.UserRepository
|
|
tenantRepo *repository.TenantRepository
|
|
}
|
|
|
|
func NewAgencyTemplateHandler(
|
|
templateRepo *repository.AgencyTemplateRepository,
|
|
agencyService *service.AgencyService,
|
|
userRepo *repository.UserRepository,
|
|
tenantRepo *repository.TenantRepository,
|
|
) *AgencyTemplateHandler {
|
|
return &AgencyTemplateHandler{
|
|
templateRepo: templateRepo,
|
|
agencyService: agencyService,
|
|
userRepo: userRepo,
|
|
tenantRepo: tenantRepo,
|
|
}
|
|
}
|
|
|
|
// GetTemplateBySlug - Public endpoint to get template details
|
|
func (h *AgencyTemplateHandler) GetTemplateBySlug(w http.ResponseWriter, r *http.Request) {
|
|
slug := r.URL.Query().Get("slug")
|
|
if slug == "" {
|
|
http.Error(w, "Missing slug parameter", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
template, err := h.templateRepo.FindBySlug(slug)
|
|
if err != nil {
|
|
log.Printf("Template not found: %v", err)
|
|
http.Error(w, "Template not found or expired", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(template)
|
|
}
|
|
|
|
// PublicRegisterAgency - Public endpoint for agency registration via template
|
|
func (h *AgencyTemplateHandler) PublicRegisterAgency(w http.ResponseWriter, r *http.Request) {
|
|
var req domain.AgencyRegistrationViaTemplate
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 1. Validar template
|
|
template, err := h.templateRepo.FindBySlug(req.TemplateSlug)
|
|
if err != nil {
|
|
log.Printf("Template error: %v", err)
|
|
http.Error(w, "Invalid or expired template", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 2. Validar campos obrigatórios
|
|
if req.AgencyName == "" || req.Subdomain == "" || req.AdminEmail == "" || req.AdminPassword == "" {
|
|
http.Error(w, "Missing required fields", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 3. Validar senha
|
|
if len(req.AdminPassword) < 8 {
|
|
http.Error(w, "Password must be at least 8 characters", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 4. Verificar se email já existe
|
|
existingUser, _ := h.userRepo.FindByEmail(req.AdminEmail)
|
|
if existingUser != nil {
|
|
http.Error(w, "Email already registered", http.StatusConflict)
|
|
return
|
|
}
|
|
|
|
// 5. Verificar se subdomain já existe
|
|
existingTenant, _ := h.tenantRepo.FindBySubdomain(req.Subdomain)
|
|
if existingTenant != nil {
|
|
http.Error(w, "Subdomain already taken", http.StatusConflict)
|
|
return
|
|
}
|
|
|
|
// 6. Hash da senha
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.AdminPassword), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
log.Printf("Error hashing password: %v", err)
|
|
http.Error(w, "Error processing password", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// 7. Criar tenant (agência)
|
|
tenant := &domain.Tenant{
|
|
Name: req.AgencyName,
|
|
Domain: req.Subdomain + ".aggios.app",
|
|
Subdomain: req.Subdomain,
|
|
CNPJ: req.CNPJ,
|
|
RazaoSocial: req.RazaoSocial,
|
|
Website: req.Website,
|
|
Phone: req.Phone,
|
|
Description: req.Description,
|
|
Industry: req.Industry,
|
|
TeamSize: req.TeamSize,
|
|
}
|
|
|
|
// Endereço (se fornecido)
|
|
if req.Address != nil {
|
|
tenant.Address = req.Address["street"]
|
|
tenant.Number = req.Address["number"]
|
|
tenant.Complement = req.Address["complement"]
|
|
tenant.Neighborhood = req.Address["neighborhood"]
|
|
tenant.City = req.Address["city"]
|
|
tenant.State = req.Address["state"]
|
|
tenant.Zip = req.Address["cep"]
|
|
}
|
|
|
|
// Personalização do template
|
|
if template.CustomPrimaryColor.Valid {
|
|
tenant.PrimaryColor = template.CustomPrimaryColor.String
|
|
}
|
|
if template.CustomLogoURL.Valid {
|
|
tenant.LogoURL = template.CustomLogoURL.String
|
|
}
|
|
|
|
if err := h.tenantRepo.Create(tenant); err != nil {
|
|
log.Printf("Error creating tenant: %v", err)
|
|
http.Error(w, "Error creating agency", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// 8. Criar usuário admin da agência
|
|
user := &domain.User{
|
|
Email: req.AdminEmail,
|
|
Password: string(hashedPassword),
|
|
Name: req.AdminName,
|
|
Role: "ADMIN_AGENCIA",
|
|
TenantID: &tenant.ID,
|
|
}
|
|
|
|
if err := h.userRepo.Create(user); err != nil {
|
|
log.Printf("Error creating user: %v", err)
|
|
http.Error(w, "Error creating admin user", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// 9. Incrementar contador de uso do template
|
|
if err := h.templateRepo.IncrementUsageCount(template.ID.String()); err != nil {
|
|
log.Printf("Warning: failed to increment usage count: %v", err)
|
|
}
|
|
|
|
// 10. Preparar resposta com redirect
|
|
redirectURL := template.RedirectURL.String
|
|
if redirectURL == "" {
|
|
redirectURL = "http://" + req.Subdomain + ".localhost/login"
|
|
}
|
|
|
|
response := map[string]interface{}{
|
|
"success": true,
|
|
"message": template.SuccessMessage.String,
|
|
"tenant_id": tenant.ID,
|
|
"user_id": user.ID,
|
|
"redirect_url": redirectURL,
|
|
"subdomain": req.Subdomain,
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// CreateTemplate - SUPERADMIN only
|
|
func (h *AgencyTemplateHandler) CreateTemplate(w http.ResponseWriter, r *http.Request) {
|
|
var req domain.CreateAgencyTemplateRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
formFieldsJSON, _ := repository.FormFieldsToJSON(req.FormFields)
|
|
modulesJSON, _ := json.Marshal(req.AvailableModules)
|
|
|
|
template := &domain.AgencySignupTemplate{
|
|
Name: req.Name,
|
|
Slug: req.Slug,
|
|
Description: req.Description,
|
|
FormFields: formFieldsJSON,
|
|
AvailableModules: modulesJSON,
|
|
IsActive: true,
|
|
}
|
|
|
|
if req.CustomPrimaryColor != "" {
|
|
template.CustomPrimaryColor.Valid = true
|
|
template.CustomPrimaryColor.String = req.CustomPrimaryColor
|
|
}
|
|
if req.CustomLogoURL != "" {
|
|
template.CustomLogoURL.Valid = true
|
|
template.CustomLogoURL.String = req.CustomLogoURL
|
|
}
|
|
if req.RedirectURL != "" {
|
|
template.RedirectURL.Valid = true
|
|
template.RedirectURL.String = req.RedirectURL
|
|
}
|
|
if req.SuccessMessage != "" {
|
|
template.SuccessMessage.Valid = true
|
|
template.SuccessMessage.String = req.SuccessMessage
|
|
}
|
|
|
|
if err := h.templateRepo.Create(template); err != nil {
|
|
log.Printf("Error creating template: %v", err)
|
|
http.Error(w, "Error creating template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(template)
|
|
}
|
|
|
|
// ListTemplates - SUPERADMIN only
|
|
func (h *AgencyTemplateHandler) ListTemplates(w http.ResponseWriter, r *http.Request) {
|
|
templates, err := h.templateRepo.List()
|
|
if err != nil {
|
|
http.Error(w, "Error fetching templates", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(templates)
|
|
}
|