package handler import ( "encoding/json" "net/http" "time" "freeleaps.com/gitea-webhook-ambassador/internal/auth" "freeleaps.com/gitea-webhook-ambassador/internal/config" "freeleaps.com/gitea-webhook-ambassador/internal/database" "freeleaps.com/gitea-webhook-ambassador/internal/logger" ) // ProjectHandler handles project mapping API endpoints type ProjectHandler struct { db *database.DB config *config.Configuration auth *auth.Middleware } // NewProjectHandler creates a new project handler func NewProjectHandler(db *database.DB, config *config.Configuration) *ProjectHandler { return &ProjectHandler{ db: db, config: config, auth: auth.NewMiddleware(config.Server.SecretKey), } } // ProjectMappingRequest represents a request to create/update a project mapping type ProjectMappingRequest struct { RepositoryName string `json:"repository_name"` DefaultJob string `json:"default_job"` BranchJobs []struct { BranchName string `json:"branch_name"` JobName string `json:"job_name"` } `json:"branch_jobs"` BranchPatterns []struct { Pattern string `json:"pattern"` JobName string `json:"job_name"` } `json:"branch_patterns"` } // ProjectMappingResponse represents a project mapping response type ProjectMappingResponse struct { ID int64 `json:"id"` RepositoryName string `json:"repository_name"` DefaultJob string `json:"default_job"` BranchJobs []struct { ID int64 `json:"id"` BranchName string `json:"branch_name"` JobName string `json:"job_name"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } `json:"branch_jobs"` BranchPatterns []struct { ID int64 `json:"id"` Pattern string `json:"pattern"` JobName string `json:"job_name"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } `json:"branch_patterns"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // verifyAuth verifies the JWT token in the request func (h *ProjectHandler) verifyAuth(r *http.Request) error { return h.auth.VerifyToken(r) } // HandleCreateProjectMapping handles the creation of project mappings func (h *ProjectHandler) HandleCreateProjectMapping(w http.ResponseWriter, r *http.Request) { // Verify JWT token if err := h.verifyAuth(r); err != nil { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Parse request var req ProjectMappingRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return } // Validate request if req.RepositoryName == "" { http.Error(w, "Repository name is required", http.StatusBadRequest) return } // Create project mapping project := &database.ProjectMapping{ RepositoryName: req.RepositoryName, DefaultJob: req.DefaultJob, } // Add branch jobs for _, job := range req.BranchJobs { project.BranchJobs = append(project.BranchJobs, database.BranchJob{ BranchName: job.BranchName, JobName: job.JobName, }) } // Add branch patterns for _, pattern := range req.BranchPatterns { project.BranchPatterns = append(project.BranchPatterns, database.BranchPattern{ Pattern: pattern.Pattern, JobName: pattern.JobName, }) } if err := h.db.CreateProjectMapping(project); err != nil { logger.Error("Failed to create project mapping: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) } // HandleGetProjectMapping handles retrieving project mappings func (h *ProjectHandler) HandleGetProjectMapping(w http.ResponseWriter, r *http.Request) { // Verify JWT token if err := h.verifyAuth(r); err != nil { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Get repository name from URL repoName := r.URL.Query().Get("repository") if repoName == "" { http.Error(w, "Repository name is required", http.StatusBadRequest) return } // Get project mapping project, err := h.db.GetProjectMapping(repoName) if err != nil { logger.Error("Failed to get project mapping: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } if project == nil { http.Error(w, "Project mapping not found", http.StatusNotFound) return } // Convert to response format response := ProjectMappingResponse{ ID: project.ID, RepositoryName: project.RepositoryName, DefaultJob: project.DefaultJob, CreatedAt: project.CreatedAt, UpdatedAt: project.UpdatedAt, } for _, job := range project.BranchJobs { response.BranchJobs = append(response.BranchJobs, struct { ID int64 `json:"id"` BranchName string `json:"branch_name"` JobName string `json:"job_name"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` }{ ID: job.ID, BranchName: job.BranchName, JobName: job.JobName, CreatedAt: job.CreatedAt, UpdatedAt: job.UpdatedAt, }) } for _, pattern := range project.BranchPatterns { response.BranchPatterns = append(response.BranchPatterns, struct { ID int64 `json:"id"` Pattern string `json:"pattern"` JobName string `json:"job_name"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` }{ ID: pattern.ID, Pattern: pattern.Pattern, JobName: pattern.JobName, CreatedAt: pattern.CreatedAt, UpdatedAt: pattern.UpdatedAt, }) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) }