add some changes

This commit is contained in:
2026-01-15 09:44:57 +00:00
parent 9b1f85479b
commit 1d9406c93a
19 changed files with 4922 additions and 887 deletions

View File

@@ -11,9 +11,9 @@ import (
// Handler handles HTTP requests for object storage
type Handler struct {
service *Service
service *Service
setupService *SetupService
logger *logger.Logger
logger *logger.Logger
}
// NewHandler creates a new object storage handler
@@ -283,3 +283,18 @@ func (h *Handler) DeleteServiceAccount(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "service account deleted successfully"})
}
// ListObjects lists objects in a bucket
func (h *Handler) ListObjects(c *gin.Context) {
bucketName := c.Param("name") // Changed from "bucket" to "name" to match route
prefix := c.DefaultQuery("prefix", "") // Optional prefix (folder path)
objects, err := h.service.ListObjects(c.Request.Context(), bucketName, prefix)
if err != nil {
h.logger.Error("Failed to list objects", "bucket", bucketName, "prefix", prefix, "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list objects: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"objects": objects})
}

View File

@@ -4,23 +4,24 @@ import (
"context"
"encoding/json"
"fmt"
"sort"
"strings"
"time"
"github.com/atlasos/calypso/internal/common/logger"
madmin "github.com/minio/madmin-go/v3"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
madmin "github.com/minio/madmin-go/v3"
)
// Service handles MinIO object storage operations
type Service struct {
client *minio.Client
client *minio.Client
adminClient *madmin.AdminClient
logger *logger.Logger
endpoint string
accessKey string
secretKey string
logger *logger.Logger
endpoint string
accessKey string
secretKey string
}
// NewService creates a new MinIO service
@@ -54,8 +55,8 @@ func NewService(endpoint, accessKey, secretKey string, log *logger.Logger) (*Ser
type Bucket struct {
Name string `json:"name"`
CreationDate time.Time `json:"creation_date"`
Size int64 `json:"size"` // Total size in bytes
Objects int64 `json:"objects"` // Number of objects
Size int64 `json:"size"` // Total size in bytes
Objects int64 `json:"objects"` // Number of objects
AccessPolicy string `json:"access_policy"` // private, public-read, public-read-write
}
@@ -153,7 +154,6 @@ func (s *Service) getBucketPolicy(ctx context.Context, bucketName string) string
return "private"
}
// CreateBucket creates a new bucket
func (s *Service) CreateBucket(ctx context.Context, bucketName string) error {
err := s.client.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{})
@@ -177,6 +177,82 @@ func (s *Service) GetBucketStats(ctx context.Context, bucketName string) (*Bucke
return s.getBucketInfo(ctx, bucketName)
}
// Object represents a MinIO object (file or folder)
type Object struct {
Name string `json:"name"`
Key string `json:"key"` // Full path/key
Size int64 `json:"size"` // Size in bytes (0 for folders)
LastModified time.Time `json:"last_modified"`
IsDir bool `json:"is_dir"` // True if this is a folder/prefix
ETag string `json:"etag,omitempty"`
}
// ListObjects lists objects in a bucket with optional prefix (folder path)
func (s *Service) ListObjects(ctx context.Context, bucketName, prefix string) ([]*Object, error) {
// Ensure prefix ends with / if it's not empty and doesn't already end with /
if prefix != "" && !strings.HasSuffix(prefix, "/") {
prefix += "/"
}
// List objects with prefix
objectCh := s.client.ListObjects(ctx, bucketName, minio.ListObjectsOptions{
Prefix: prefix,
Recursive: false, // Don't recurse, show folders as separate items
})
var objects []*Object
seenFolders := make(map[string]bool)
for object := range objectCh {
if object.Err != nil {
s.logger.Warn("Error listing object", "bucket", bucketName, "prefix", prefix, "error", object.Err)
continue
}
// Extract folder name from object key
relativeKey := strings.TrimPrefix(object.Key, prefix)
// Check if this is a folder (has / in relative path)
if strings.Contains(relativeKey, "/") {
// Extract folder name (first part before /)
folderName := strings.Split(relativeKey, "/")[0]
folderKey := prefix + folderName + "/"
// Only add folder once
if !seenFolders[folderKey] {
seenFolders[folderKey] = true
objects = append(objects, &Object{
Name: folderName,
Key: folderKey,
Size: 0,
LastModified: time.Time{},
IsDir: true,
})
}
} else {
// This is a file in the current directory
objects = append(objects, &Object{
Name: relativeKey,
Key: object.Key,
Size: object.Size,
LastModified: object.LastModified,
IsDir: false,
ETag: object.ETag,
})
}
}
// Sort: folders first, then files, both alphabetically
sort.Slice(objects, func(i, j int) bool {
if objects[i].IsDir != objects[j].IsDir {
return objects[i].IsDir // Folders first
}
return objects[i].Name < objects[j].Name
})
return objects, nil
}
// User represents a MinIO IAM user
type User struct {
AccessKey string `json:"access_key"`
@@ -229,11 +305,11 @@ func (s *Service) DeleteUser(ctx context.Context, accessKey string) error {
// ServiceAccount represents a MinIO service account (access key)
type ServiceAccount struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key,omitempty"` // Only returned on creation
ParentUser string `json:"parent_user"`
Expiration time.Time `json:"expiration,omitempty"`
CreatedAt time.Time `json:"created_at"`
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key,omitempty"` // Only returned on creation
ParentUser string `json:"parent_user"`
Expiration time.Time `json:"expiration,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// ListServiceAccounts lists all service accounts in MinIO