chore: clean .gitignore cache
This commit is contained in:
@@ -1,657 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/models"
|
||||
"github.com/Wikid82/charon/backend/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ManualChallengeServiceInterface defines the interface for manual challenge operations.
|
||||
// This allows for easier testing by enabling mock implementations.
|
||||
type ManualChallengeServiceInterface interface {
|
||||
CreateChallenge(ctx context.Context, req services.CreateChallengeRequest) (*models.ManualChallenge, error)
|
||||
GetChallengeForUser(ctx context.Context, challengeID string, userID uint) (*models.ManualChallenge, error)
|
||||
ListChallengesForProvider(ctx context.Context, providerID, userID uint) ([]models.ManualChallenge, error)
|
||||
VerifyChallenge(ctx context.Context, challengeID string, userID uint) (*services.VerifyResult, error)
|
||||
PollChallengeStatus(ctx context.Context, challengeID string, userID uint) (*services.ChallengeStatusResponse, error)
|
||||
DeleteChallenge(ctx context.Context, challengeID string, userID uint) error
|
||||
}
|
||||
|
||||
// DNSProviderServiceInterface defines the subset of DNSProviderService needed by ManualChallengeHandler.
|
||||
type DNSProviderServiceInterface interface {
|
||||
Get(ctx context.Context, id uint) (*models.DNSProvider, error)
|
||||
}
|
||||
|
||||
// ManualChallengeHandler handles manual DNS challenge API requests.
|
||||
type ManualChallengeHandler struct {
|
||||
challengeService ManualChallengeServiceInterface
|
||||
providerService DNSProviderServiceInterface
|
||||
}
|
||||
|
||||
// NewManualChallengeHandler creates a new manual challenge handler.
|
||||
func NewManualChallengeHandler(challengeService ManualChallengeServiceInterface, providerService DNSProviderServiceInterface) *ManualChallengeHandler {
|
||||
return &ManualChallengeHandler{
|
||||
challengeService: challengeService,
|
||||
providerService: providerService,
|
||||
}
|
||||
}
|
||||
|
||||
// ManualChallengeResponse represents the API response for a manual challenge.
|
||||
type ManualChallengeResponse struct {
|
||||
ID string `json:"id"`
|
||||
ProviderID uint `json:"provider_id"`
|
||||
FQDN string `json:"fqdn"`
|
||||
Value string `json:"value"`
|
||||
Status string `json:"status"`
|
||||
DNSPropagated bool `json:"dns_propagated"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
ExpiresAt string `json:"expires_at"`
|
||||
LastCheckAt string `json:"last_check_at,omitempty"`
|
||||
TimeRemainingSeconds int `json:"time_remaining_seconds"`
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
}
|
||||
|
||||
// ErrorResponse represents an error response with a code.
|
||||
type ErrorResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Error struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
// newErrorResponse creates a standardized error response.
|
||||
func newErrorResponse(code, message string, details map[string]interface{}) ErrorResponse {
|
||||
resp := ErrorResponse{Success: false}
|
||||
resp.Error.Code = code
|
||||
resp.Error.Message = message
|
||||
resp.Error.Details = details
|
||||
return resp
|
||||
}
|
||||
|
||||
// GetChallenge handles GET /api/v1/dns-providers/:id/manual-challenge/:challengeId
|
||||
// Returns the status and details of a manual DNS challenge.
|
||||
func (h *ManualChallengeHandler) GetChallenge(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challengeID := c.Param("challengeId")
|
||||
if challengeID == "" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_CHALLENGE_ID",
|
||||
"Challenge ID is required",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context (set by auth middleware)
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists and user has access
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Verify provider is manual type
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Get challenge
|
||||
challenge, err := h.challengeService.GetChallengeForUser(c.Request.Context(), challengeID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found",
|
||||
map[string]interface{}{"challenge_id": challengeID},
|
||||
))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrUnauthorized) {
|
||||
c.JSON(http.StatusForbidden, newErrorResponse(
|
||||
"UNAUTHORIZED",
|
||||
"You do not have access to this challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Verify challenge belongs to the specified provider
|
||||
if challenge.ProviderID != uint(providerID) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found for this provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, challengeToResponse(challenge))
|
||||
}
|
||||
|
||||
// VerifyChallenge handles POST /api/v1/dns-providers/:id/manual-challenge/:challengeId/verify
|
||||
// Triggers DNS verification for a challenge.
|
||||
func (h *ManualChallengeHandler) VerifyChallenge(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challengeID := c.Param("challengeId")
|
||||
if challengeID == "" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_CHALLENGE_ID",
|
||||
"Challenge ID is required",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists and is manual type
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Verify ownership before verification
|
||||
challenge, err := h.challengeService.GetChallengeForUser(c.Request.Context(), challengeID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found",
|
||||
map[string]interface{}{"challenge_id": challengeID},
|
||||
))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrUnauthorized) {
|
||||
c.JSON(http.StatusForbidden, newErrorResponse(
|
||||
"UNAUTHORIZED",
|
||||
"You do not have access to this challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if challenge.ProviderID != uint(providerID) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found for this provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Perform verification
|
||||
result, err := h.challengeService.VerifyChallenge(c.Request.Context(), challengeID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeExpired) {
|
||||
c.JSON(http.StatusGone, newErrorResponse(
|
||||
"CHALLENGE_EXPIRED",
|
||||
"Challenge has expired",
|
||||
map[string]interface{}{
|
||||
"challenge_id": challengeID,
|
||||
"expired_at": challenge.ExpiresAt.Format("2006-01-02T15:04:05Z"),
|
||||
},
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to verify challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// PollChallenge handles GET /api/v1/dns-providers/:id/manual-challenge/:challengeId/poll
|
||||
// Returns the current status for polling.
|
||||
func (h *ManualChallengeHandler) PollChallenge(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challengeID := c.Param("challengeId")
|
||||
if challengeID == "" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_CHALLENGE_ID",
|
||||
"Challenge ID is required",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Get challenge status
|
||||
status, err := h.challengeService.PollChallengeStatus(c.Request.Context(), challengeID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrUnauthorized) {
|
||||
c.JSON(http.StatusForbidden, newErrorResponse(
|
||||
"UNAUTHORIZED",
|
||||
"You do not have access to this challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to get challenge status",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, status)
|
||||
}
|
||||
|
||||
// ListChallenges handles GET /api/v1/dns-providers/:id/manual-challenges
|
||||
// Returns all challenges for a provider.
|
||||
func (h *ManualChallengeHandler) ListChallenges(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists and is manual type
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challenges, err := h.challengeService.ListChallengesForProvider(c.Request.Context(), uint(providerID), userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to list challenges",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
responses := make([]ManualChallengeResponse, len(challenges))
|
||||
for i, ch := range challenges {
|
||||
responses[i] = *challengeToResponse(&ch)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"challenges": responses,
|
||||
"total": len(responses),
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteChallenge handles DELETE /api/v1/dns-providers/:id/manual-challenge/:challengeId
|
||||
// Cancels/deletes a challenge.
|
||||
func (h *ManualChallengeHandler) DeleteChallenge(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challengeID := c.Param("challengeId")
|
||||
if challengeID == "" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_CHALLENGE_ID",
|
||||
"Challenge ID is required",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
err = h.challengeService.DeleteChallenge(c.Request.Context(), challengeID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"CHALLENGE_NOT_FOUND",
|
||||
"Challenge not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrUnauthorized) {
|
||||
c.JSON(http.StatusForbidden, newErrorResponse(
|
||||
"UNAUTHORIZED",
|
||||
"You do not have access to this challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to delete challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "Challenge deleted successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// CreateChallengeRequest represents the request to create a manual challenge.
|
||||
type CreateChallengeRequest struct {
|
||||
FQDN string `json:"fqdn" binding:"required"`
|
||||
Token string `json:"token"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
}
|
||||
|
||||
// CreateChallenge handles POST /api/v1/dns-providers/:id/manual-challenges
|
||||
// Creates a new manual DNS challenge.
|
||||
func (h *ManualChallengeHandler) CreateChallenge(c *gin.Context) {
|
||||
providerID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_ID",
|
||||
"Invalid provider ID",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateChallengeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_REQUEST",
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
userID := getUserIDFromContext(c)
|
||||
|
||||
// Verify provider exists and is manual type
|
||||
provider, err := h.providerService.Get(c.Request.Context(), uint(providerID))
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrDNSProviderNotFound) {
|
||||
c.JSON(http.StatusNotFound, newErrorResponse(
|
||||
"PROVIDER_NOT_FOUND",
|
||||
"DNS provider not found",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to retrieve DNS provider",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.ProviderType != "manual" {
|
||||
c.JSON(http.StatusBadRequest, newErrorResponse(
|
||||
"INVALID_PROVIDER_TYPE",
|
||||
"This endpoint is only available for manual DNS providers",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
challenge, err := h.challengeService.CreateChallenge(c.Request.Context(), services.CreateChallengeRequest{
|
||||
ProviderID: uint(providerID),
|
||||
UserID: userID,
|
||||
FQDN: req.FQDN,
|
||||
Token: req.Token,
|
||||
Value: req.Value,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrChallengeInProgress) {
|
||||
c.JSON(http.StatusConflict, newErrorResponse(
|
||||
"CHALLENGE_IN_PROGRESS",
|
||||
"Another challenge is already in progress for this domain",
|
||||
map[string]interface{}{"fqdn": req.FQDN},
|
||||
))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, newErrorResponse(
|
||||
"INTERNAL_ERROR",
|
||||
"Failed to create challenge",
|
||||
nil,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, challengeToResponse(challenge))
|
||||
}
|
||||
|
||||
// RegisterRoutes registers all manual challenge routes.
|
||||
func (h *ManualChallengeHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||
// Routes under /dns-providers/:id
|
||||
rg.GET("/dns-providers/:id/manual-challenges", h.ListChallenges)
|
||||
rg.POST("/dns-providers/:id/manual-challenges", h.CreateChallenge)
|
||||
rg.GET("/dns-providers/:id/manual-challenge/:challengeId", h.GetChallenge)
|
||||
rg.POST("/dns-providers/:id/manual-challenge/:challengeId/verify", h.VerifyChallenge)
|
||||
rg.GET("/dns-providers/:id/manual-challenge/:challengeId/poll", h.PollChallenge)
|
||||
rg.DELETE("/dns-providers/:id/manual-challenge/:challengeId", h.DeleteChallenge)
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
func challengeToResponse(ch *models.ManualChallenge) *ManualChallengeResponse {
|
||||
resp := &ManualChallengeResponse{
|
||||
ID: ch.ID,
|
||||
ProviderID: ch.ProviderID,
|
||||
FQDN: ch.FQDN,
|
||||
Value: ch.Value,
|
||||
Status: string(ch.Status),
|
||||
DNSPropagated: ch.DNSPropagated,
|
||||
CreatedAt: ch.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
||||
ExpiresAt: ch.ExpiresAt.Format("2006-01-02T15:04:05Z"),
|
||||
TimeRemainingSeconds: int(ch.TimeRemaining().Seconds()),
|
||||
ErrorMessage: ch.ErrorMessage,
|
||||
}
|
||||
|
||||
if ch.LastCheckAt != nil {
|
||||
resp.LastCheckAt = ch.LastCheckAt.Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// getUserIDFromContext extracts user ID from gin context.
|
||||
func getUserIDFromContext(c *gin.Context) uint {
|
||||
// Try to get user_id from context (set by auth middleware)
|
||||
if userID, exists := c.Get("user_id"); exists {
|
||||
switch v := userID.(type) {
|
||||
case uint:
|
||||
return v
|
||||
case int:
|
||||
return uint(v)
|
||||
case int64:
|
||||
return uint(v)
|
||||
case uint64:
|
||||
return uint(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user