package api import ( "encoding/json" "net/http" "strings" "crypto-miner-server/internal/erasure" ) type ErasureSwarmHandler struct { awsSettings func() erasure.AWSSwarmSettings objectStore func() erasure.ShardObjectStore } func NewErasureSwarmHandler(awsSettings func() erasure.AWSSwarmSettings, objectStore func() erasure.ShardObjectStore) *ErasureSwarmHandler { return &ErasureSwarmHandler{awsSettings: awsSettings, objectStore: objectStore} } type erasureSwarmTestResponse struct { OK bool `json:"ok"` CredentialsReady bool `json:"credentials_ready"` SigningReady bool `json:"signing_ready"` Error string `json:"error,omitempty"` S3Bucket string `json:"s3_bucket,omitempty"` CloudFrontDomain string `json:"cloudfront_domain,omitempty"` } func (h *ErasureSwarmHandler) PostTest(w http.ResponseWriter, r *http.Request) { cfg := h.cfg(r) resp := erasureSwarmTestResponse{S3Bucket: cfg.S3Bucket, CloudFrontDomain: cfg.CloudFrontDomain, CredentialsReady: cfg.CredentialsReady(), SigningReady: cfg.SigningReady()} if !cfg.Enabled() { resp.Error = "set aws_s3_shard_bucket and aws_cloudfront_domain" writeJSON(w, resp) return } if !cfg.CredentialsReady() { resp.Error = "set AF_AWS_ACCESS_KEY_ID and AF_AWS_SECRET_ACCESS_KEY" writeJSON(w, resp) return } if err := h.store().HeadBucket(r.Context(), cfg.S3Bucket); err != nil { resp.Error = err.Error() writeJSON(w, resp) return } resp.OK = true writeJSON(w, resp) } func (h *ErasureSwarmHandler) GetPolicyJSON(w http.ResponseWriter, r *http.Request) { cfg := h.cfg(r) bucket := strings.TrimSpace(r.URL.Query().Get("bucket")) if bucket == "" { bucket = cfg.S3Bucket } writeJSON(w, map[string]interface{}{ "iam_policy": erasure.MinimalIAMPolicyJSON(bucket), "bucket_policy": erasure.MinimalBucketPolicyJSON(bucket, r.URL.Query().Get("cloudfront_arn")), "env_keys": []string{"AF_AWS_ACCESS_KEY_ID", "AF_AWS_SECRET_ACCESS_KEY", "AF_AWS_REGION", "AF_CLOUDFRONT_KEY_PAIR_ID", "AF_CLOUDFRONT_PRIVATE_KEY"}, }) } func (h *ErasureSwarmHandler) cfg(r *http.Request) erasure.AWSSwarmSettings { cfg := erasure.AWSSwarmSettings{} if h != nil && h.awsSettings != nil { cfg = h.awsSettings() } if r != nil && r.Method == http.MethodPost { var body struct { S3Bucket string `json:"s3_bucket"` CloudFrontDomain string `json:"cloudfront_domain"` } if json.NewDecoder(r.Body).Decode(&body) == nil { if v := strings.TrimSpace(body.S3Bucket); v != "" { cfg.S3Bucket = v } if v := strings.TrimSpace(body.CloudFrontDomain); v != "" { cfg.CloudFrontDomain = v } } } return erasure.HydrateAWSSwarmFromEnv(cfg) } func (h *ErasureSwarmHandler) store() erasure.ShardObjectStore { if h != nil && h.objectStore != nil { return h.objectStore() } cfg := erasure.AWSSwarmSettings{} if h != nil && h.awsSettings != nil { cfg = erasure.HydrateAWSSwarmFromEnv(h.awsSettings()) } return &erasure.S3HTTPStore{Settings: cfg} }