mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-07-26 07:48:13 +00:00
refactor: streamline object key handling and improve app name format
Signed-off-by: Noooste <83548733+Noooste@users.noreply.github.com>
This commit is contained in:
@@ -12,48 +12,11 @@ type GrantBucketPermissionRequest struct {
|
||||
Permissions BucketKeyPermission `json:"permissions" validate:"required"`
|
||||
}
|
||||
|
||||
// DeleteBucketRequest represents a request to delete a bucket
|
||||
type DeleteBucketRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
// ListObjectsRequest represents a request to list objects in a bucket
|
||||
type ListObjectsRequest struct {
|
||||
Bucket string `json:"bucket" validate:"required"`
|
||||
Prefix string `json:"prefix,omitempty"`
|
||||
MaxKeys int `json:"max_keys,omitempty"`
|
||||
Marker string `json:"marker,omitempty"`
|
||||
}
|
||||
|
||||
// UploadObjectRequest represents metadata for an object upload
|
||||
type UploadObjectRequest struct {
|
||||
Bucket string `json:"bucket" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
ContentType string `json:"content_type,omitempty"`
|
||||
}
|
||||
|
||||
// DeleteObjectRequest represents a request to delete an object
|
||||
type DeleteObjectRequest struct {
|
||||
Bucket string `json:"bucket" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
}
|
||||
|
||||
// GetObjectRequest represents a request to get/download an object
|
||||
type GetObjectRequest struct {
|
||||
Bucket string `json:"bucket" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
}
|
||||
|
||||
// CreateUserRequest represents a request to create a new user/key
|
||||
type CreateUserRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// DeleteUserRequest represents a request to delete a user/key
|
||||
type DeleteUserRequest struct {
|
||||
AccessKey string `json:"access_key" validate:"required"`
|
||||
}
|
||||
|
||||
// UpdateUserRequest represents a request to update user permissions
|
||||
type UpdateUserRequest struct {
|
||||
Status *string `json:"status,omitempty"` // "active" or "inactive"
|
||||
|
||||
@@ -138,13 +138,6 @@ type BucketPermission struct {
|
||||
Owner bool `json:"owner"`
|
||||
}
|
||||
|
||||
// Permission represents a permission entry for access control (legacy/deprecated)
|
||||
type Permission struct {
|
||||
Resource string `json:"resource"`
|
||||
Actions []string `json:"actions"`
|
||||
Effect string `json:"effect"` // "Allow" or "Deny"
|
||||
}
|
||||
|
||||
type PresignedURLResponse struct {
|
||||
URL string `json:"url"`
|
||||
ExpiresIn int64 `json:"expires_in"` // in seconds
|
||||
|
||||
@@ -72,64 +72,38 @@ func SetupRoutes(
|
||||
objects.Post("/delete-multiple", objectHandler.DeleteMultipleObjects) // Delete multiple objects
|
||||
}
|
||||
|
||||
// Object-specific routes with wildcard key parameter (supports paths with slashes)
|
||||
// These need to be registered on the main app with auth middleware applied
|
||||
// Fiber v3 does not auto-decode wildcard params; fall back to the raw
|
||||
// value when QueryUnescape fails.
|
||||
decodeObjectKey := func(c fiber.Ctx) string {
|
||||
raw := c.Params("*")
|
||||
if decoded, err := url.QueryUnescape(raw); err == nil {
|
||||
return decoded
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
objectWildcardHandler := func(c fiber.Ctx) error {
|
||||
// Get the full path from wildcard parameter
|
||||
// Note: Fiber v3 does NOT automatically decode params, we need to do it manually
|
||||
path := c.Params("*")
|
||||
|
||||
// Decode the full path using QueryUnescape (handles %20, %2F, etc.)
|
||||
decodedPath, err := url.QueryUnescape(path)
|
||||
if err != nil {
|
||||
// If decoding fails, use the original path
|
||||
decodedPath = path
|
||||
}
|
||||
|
||||
// Check if it's a metadata request
|
||||
if strings.HasSuffix(decodedPath, "/metadata") {
|
||||
// Remove /metadata suffix to get the actual key
|
||||
key := strings.TrimSuffix(decodedPath, "/metadata")
|
||||
c.Locals("objectKey", key)
|
||||
path := decodeObjectKey(c)
|
||||
switch {
|
||||
case strings.HasSuffix(path, "/metadata"):
|
||||
c.Locals("objectKey", strings.TrimSuffix(path, "/metadata"))
|
||||
return objectHandler.GetObjectMetadata(c)
|
||||
}
|
||||
// Check if it's a presign request
|
||||
if strings.HasSuffix(decodedPath, "/presign") {
|
||||
// Remove /presign suffix to get the actual key
|
||||
key := strings.TrimSuffix(decodedPath, "/presign")
|
||||
c.Locals("objectKey", key)
|
||||
case strings.HasSuffix(path, "/presign"):
|
||||
c.Locals("objectKey", strings.TrimSuffix(path, "/presign"))
|
||||
return objectHandler.GetPresignedURL(c)
|
||||
}
|
||||
// Otherwise, it's a regular object download
|
||||
c.Locals("objectKey", decodedPath)
|
||||
default:
|
||||
c.Locals("objectKey", path)
|
||||
return objectHandler.GetObject(c)
|
||||
}
|
||||
}
|
||||
|
||||
objectDeleteHandler := func(c fiber.Ctx) error {
|
||||
path := c.Params("*")
|
||||
|
||||
// Decode the full path using QueryUnescape
|
||||
key, err := url.QueryUnescape(path)
|
||||
if err != nil {
|
||||
// If decoding fails, use the original path
|
||||
key = path
|
||||
}
|
||||
|
||||
c.Locals("objectKey", key)
|
||||
c.Locals("objectKey", decodeObjectKey(c))
|
||||
return objectHandler.DeleteObject(c)
|
||||
}
|
||||
|
||||
objectHeadHandler := func(c fiber.Ctx) error {
|
||||
path := c.Params("*")
|
||||
|
||||
// Decode the full path using QueryUnescape
|
||||
key, err := url.QueryUnescape(path)
|
||||
if err != nil {
|
||||
// If decoding fails, use the original path
|
||||
key = path
|
||||
}
|
||||
|
||||
c.Locals("objectKey", key)
|
||||
c.Locals("objectKey", decodeObjectKey(c))
|
||||
return objectHandler.GetObjectMetadata(c)
|
||||
}
|
||||
|
||||
@@ -226,6 +200,11 @@ func SetupRoutes(
|
||||
})
|
||||
}
|
||||
|
||||
logger.Debug().
|
||||
Str("access_token", token.AccessToken).
|
||||
Interface("token", token).
|
||||
Msg("Exchanged authorization code for token")
|
||||
|
||||
// Extract ID token from OAuth2 token
|
||||
rawIDToken, ok := token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
@@ -253,10 +232,8 @@ func SetupRoutes(
|
||||
}
|
||||
}
|
||||
if !authService.IsAdmin(userInfo) {
|
||||
if uiFromUserinfo, uiErr := authService.GetUserInfo(ctx, token); uiErr == nil {
|
||||
if len(uiFromUserinfo.Roles) > 0 {
|
||||
userInfo.Roles = uiFromUserinfo.Roles
|
||||
}
|
||||
if ui, err := authService.GetUserInfo(ctx, token); err == nil && len(ui.Roles) > 0 {
|
||||
userInfo.Roles = ui.Roles
|
||||
}
|
||||
}
|
||||
if !authService.IsAdmin(userInfo) {
|
||||
|
||||
@@ -37,7 +37,6 @@ func NewS3Service(cfg *config.GarageConfig, adminService *GarageAdminService) *S
|
||||
}
|
||||
|
||||
client, err := minio.New(cfg.Endpoint, &minio.Options{
|
||||
//Creds: credentials.NewStaticV4(cfg.AccessKey, cfg.SecretKey, ""),
|
||||
Secure: cfg.UseSSL,
|
||||
Region: cfg.Region,
|
||||
})
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ func main() {
|
||||
|
||||
// Create Fiber app with configuration
|
||||
app := fiber.New(fiber.Config{
|
||||
AppName: "Garage UI Backend v" + version,
|
||||
AppName: "Garage UI Backend | Version: " + version,
|
||||
BodyLimit: int(maxBodySize),
|
||||
ReadBufferSize: readBufferSize,
|
||||
WriteBufferSize: writeBufferSize,
|
||||
|
||||
Reference in New Issue
Block a user