diff options
Diffstat (limited to 'weed/admin/handlers/policy_handlers.go')
| -rw-r--r-- | weed/admin/handlers/policy_handlers.go | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/weed/admin/handlers/policy_handlers.go b/weed/admin/handlers/policy_handlers.go new file mode 100644 index 000000000..8f5cc91b1 --- /dev/null +++ b/weed/admin/handlers/policy_handlers.go @@ -0,0 +1,273 @@ +package handlers + +import ( + "fmt" + "net/http" + "time" + + "github.com/gin-gonic/gin" + "github.com/seaweedfs/seaweedfs/weed/admin/dash" + "github.com/seaweedfs/seaweedfs/weed/admin/view/app" + "github.com/seaweedfs/seaweedfs/weed/admin/view/layout" + "github.com/seaweedfs/seaweedfs/weed/credential" + "github.com/seaweedfs/seaweedfs/weed/glog" +) + +// PolicyHandlers contains all the HTTP handlers for policy management +type PolicyHandlers struct { + adminServer *dash.AdminServer +} + +// NewPolicyHandlers creates a new instance of PolicyHandlers +func NewPolicyHandlers(adminServer *dash.AdminServer) *PolicyHandlers { + return &PolicyHandlers{ + adminServer: adminServer, + } +} + +// ShowPolicies renders the policies management page +func (h *PolicyHandlers) ShowPolicies(c *gin.Context) { + // Get policies data from the server + policiesData := h.getPoliciesData(c) + + // Render HTML template + c.Header("Content-Type", "text/html") + policiesComponent := app.Policies(policiesData) + layoutComponent := layout.Layout(c, policiesComponent) + err := layoutComponent.Render(c.Request.Context(), c.Writer) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render template: " + err.Error()}) + return + } +} + +// GetPolicies returns the list of policies as JSON +func (h *PolicyHandlers) GetPolicies(c *gin.Context) { + policies, err := h.adminServer.GetPolicies() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get policies: " + err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"policies": policies}) +} + +// CreatePolicy handles policy creation +func (h *PolicyHandlers) CreatePolicy(c *gin.Context) { + var req dash.CreatePolicyRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request: " + err.Error()}) + return + } + + // Validate policy name + if req.Name == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy name is required"}) + return + } + + // Check if policy already exists + existingPolicy, err := h.adminServer.GetPolicy(req.Name) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check existing policy: " + err.Error()}) + return + } + if existingPolicy != nil { + c.JSON(http.StatusConflict, gin.H{"error": "Policy with this name already exists"}) + return + } + + // Create the policy + err = h.adminServer.CreatePolicy(req.Name, req.Document) + if err != nil { + glog.Errorf("Failed to create policy %s: %v", req.Name, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create policy: " + err.Error()}) + return + } + + c.JSON(http.StatusCreated, gin.H{ + "success": true, + "message": "Policy created successfully", + "policy": req.Name, + }) +} + +// GetPolicy returns a specific policy +func (h *PolicyHandlers) GetPolicy(c *gin.Context) { + policyName := c.Param("name") + if policyName == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy name is required"}) + return + } + + policy, err := h.adminServer.GetPolicy(policyName) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get policy: " + err.Error()}) + return + } + + if policy == nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Policy not found"}) + return + } + + c.JSON(http.StatusOK, policy) +} + +// UpdatePolicy handles policy updates +func (h *PolicyHandlers) UpdatePolicy(c *gin.Context) { + policyName := c.Param("name") + if policyName == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy name is required"}) + return + } + + var req dash.UpdatePolicyRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request: " + err.Error()}) + return + } + + // Check if policy exists + existingPolicy, err := h.adminServer.GetPolicy(policyName) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check existing policy: " + err.Error()}) + return + } + if existingPolicy == nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Policy not found"}) + return + } + + // Update the policy + err = h.adminServer.UpdatePolicy(policyName, req.Document) + if err != nil { + glog.Errorf("Failed to update policy %s: %v", policyName, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update policy: " + err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "Policy updated successfully", + "policy": policyName, + }) +} + +// DeletePolicy handles policy deletion +func (h *PolicyHandlers) DeletePolicy(c *gin.Context) { + policyName := c.Param("name") + if policyName == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy name is required"}) + return + } + + // Check if policy exists + existingPolicy, err := h.adminServer.GetPolicy(policyName) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check existing policy: " + err.Error()}) + return + } + if existingPolicy == nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Policy not found"}) + return + } + + // Delete the policy + err = h.adminServer.DeletePolicy(policyName) + if err != nil { + glog.Errorf("Failed to delete policy %s: %v", policyName, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete policy: " + err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "Policy deleted successfully", + "policy": policyName, + }) +} + +// ValidatePolicy validates a policy document without saving it +func (h *PolicyHandlers) ValidatePolicy(c *gin.Context) { + var req struct { + Document credential.PolicyDocument `json:"document" binding:"required"` + } + + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request: " + err.Error()}) + return + } + + // Basic validation + if req.Document.Version == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy version is required"}) + return + } + + if len(req.Document.Statement) == 0 { + c.JSON(http.StatusBadRequest, gin.H{"error": "Policy must have at least one statement"}) + return + } + + // Validate each statement + for i, statement := range req.Document.Statement { + if statement.Effect != "Allow" && statement.Effect != "Deny" { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Statement %d: Effect must be 'Allow' or 'Deny'", i+1), + }) + return + } + + if len(statement.Action) == 0 { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Statement %d: Action is required", i+1), + }) + return + } + + if len(statement.Resource) == 0 { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Statement %d: Resource is required", i+1), + }) + return + } + } + + c.JSON(http.StatusOK, gin.H{ + "valid": true, + "message": "Policy document is valid", + }) +} + +// getPoliciesData retrieves policies data from the server +func (h *PolicyHandlers) getPoliciesData(c *gin.Context) dash.PoliciesData { + username := c.GetString("username") + if username == "" { + username = "admin" + } + + // Get policies + policies, err := h.adminServer.GetPolicies() + if err != nil { + glog.Errorf("Failed to get policies: %v", err) + // Return empty data on error + return dash.PoliciesData{ + Username: username, + Policies: []dash.IAMPolicy{}, + TotalPolicies: 0, + LastUpdated: time.Now(), + } + } + + // Ensure policies is never nil + if policies == nil { + policies = []dash.IAMPolicy{} + } + + return dash.PoliciesData{ + Username: username, + Policies: policies, + TotalPolicies: len(policies), + LastUpdated: time.Now(), + } +} |
