mirror of
https://github.com/versity/versitygw.git
synced 2026-01-06 03:44:51 +00:00
feat: implements advanced routing for the admin apis. Adds the debug logging and quite mode for the separate admin server.
Adjusts the admin apis to the new advanced routing changes. Enables debug logging for the separate admin server(when a separate server is run for the admin apis). Adds the quiet mode for the separate admin server.
This commit is contained in:
@@ -621,30 +621,6 @@ func runGateway(ctx context.Context, be backend.Backend) error {
|
|||||||
opts = append(opts, s3api.WithHostStyle(virtualDomain))
|
opts = append(opts, s3api.WithHostStyle(virtualDomain))
|
||||||
}
|
}
|
||||||
|
|
||||||
admApp := fiber.New(fiber.Config{
|
|
||||||
AppName: "versitygw",
|
|
||||||
ServerHeader: "VERSITYGW",
|
|
||||||
Network: fiber.NetworkTCP,
|
|
||||||
DisableStartupMessage: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
var admOpts []s3api.AdminOpt
|
|
||||||
|
|
||||||
if admCertFile != "" || admKeyFile != "" {
|
|
||||||
if admCertFile == "" {
|
|
||||||
return fmt.Errorf("TLS key specified without cert file")
|
|
||||||
}
|
|
||||||
if admKeyFile == "" {
|
|
||||||
return fmt.Errorf("TLS cert specified without key file")
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, err := tls.LoadX509KeyPair(admCertFile, admKeyFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("tls: load certs: %v", err)
|
|
||||||
}
|
|
||||||
admOpts = append(admOpts, s3api.WithAdminSrvTLS(cert))
|
|
||||||
}
|
|
||||||
|
|
||||||
iam, err := auth.New(&auth.Opts{
|
iam, err := auth.New(&auth.Opts{
|
||||||
RootAccount: auth.Account{
|
RootAccount: auth.Account{
|
||||||
Access: rootUserAccess,
|
Access: rootUserAccess,
|
||||||
@@ -732,7 +708,41 @@ func runGateway(ctx context.Context, be backend.Backend) error {
|
|||||||
return fmt.Errorf("init gateway: %v", err)
|
return fmt.Errorf("init gateway: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
admSrv := s3api.NewAdminServer(admApp, be, middlewares.RootUserConfig{Access: rootUserAccess, Secret: rootUserSecret}, admPort, region, iam, loggers.AdminLogger, admOpts...)
|
var admSrv *s3api.S3AdminServer
|
||||||
|
|
||||||
|
if admPort != "" {
|
||||||
|
admApp := fiber.New(fiber.Config{
|
||||||
|
AppName: "versitygw",
|
||||||
|
ServerHeader: "VERSITYGW",
|
||||||
|
Network: fiber.NetworkTCP,
|
||||||
|
DisableStartupMessage: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
var opts []s3api.AdminOpt
|
||||||
|
|
||||||
|
if admCertFile != "" || admKeyFile != "" {
|
||||||
|
if admCertFile == "" {
|
||||||
|
return fmt.Errorf("TLS key specified without cert file")
|
||||||
|
}
|
||||||
|
if admKeyFile == "" {
|
||||||
|
return fmt.Errorf("TLS cert specified without key file")
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := tls.LoadX509KeyPair(admCertFile, admKeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("tls: load certs: %v", err)
|
||||||
|
}
|
||||||
|
opts = append(opts, s3api.WithAdminSrvTLS(cert))
|
||||||
|
}
|
||||||
|
if quiet {
|
||||||
|
opts = append(opts, s3api.WithAdminQuiet())
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
opts = append(opts, s3api.WithAdminDebug())
|
||||||
|
}
|
||||||
|
|
||||||
|
admSrv = s3api.NewAdminServer(admApp, be, middlewares.RootUserConfig{Access: rootUserAccess, Secret: rootUserSecret}, admPort, region, iam, loggers.AdminLogger, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
if !quiet {
|
if !quiet {
|
||||||
printBanner(port, admPort, certFile != "", admCertFile != "")
|
printBanner(port, admPort, certFile != "", admCertFile != "")
|
||||||
@@ -977,10 +987,7 @@ func getMatchingIPs(spec string) ([]string, error) {
|
|||||||
const columnWidth = 70
|
const columnWidth = 70
|
||||||
|
|
||||||
func centerText(text string) string {
|
func centerText(text string) string {
|
||||||
padding := (columnWidth - 2 - len(text)) / 2
|
padding := max((columnWidth-2-len(text))/2, 0)
|
||||||
if padding < 0 {
|
|
||||||
padding = 0
|
|
||||||
}
|
|
||||||
return strings.Repeat(" ", padding) + text
|
return strings.Repeat(" ", padding) + text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,23 +25,23 @@ import (
|
|||||||
type S3AdminRouter struct{}
|
type S3AdminRouter struct{}
|
||||||
|
|
||||||
func (ar *S3AdminRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger) {
|
func (ar *S3AdminRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger) {
|
||||||
controller := controllers.NewAdminController(iam, be, logger)
|
ctrl := controllers.NewAdminController(iam, be, logger)
|
||||||
|
|
||||||
// CreateUser admin api
|
// CreateUser admin api
|
||||||
app.Patch("/create-user", controller.CreateUser)
|
app.Patch("/create-user", controllers.ProcessResponse(ctrl.CreateUser, logger, nil, nil))
|
||||||
|
|
||||||
// DeleteUsers admin api
|
// DeleteUsers admin api
|
||||||
app.Patch("/delete-user", controller.DeleteUser)
|
app.Patch("/delete-user", controllers.ProcessResponse(ctrl.DeleteUser, logger, nil, nil))
|
||||||
|
|
||||||
// UpdateUser admin api
|
// UpdateUser admin api
|
||||||
app.Patch("/update-user", controller.UpdateUser)
|
app.Patch("/update-user", controllers.ProcessResponse(ctrl.UpdateUser, logger, nil, nil))
|
||||||
|
|
||||||
// ListUsers admin api
|
// ListUsers admin api
|
||||||
app.Patch("/list-users", controller.ListUsers)
|
app.Patch("/list-users", controllers.ProcessResponse(ctrl.ListUsers, logger, nil, nil))
|
||||||
|
|
||||||
// ChangeBucketOwner admin api
|
// ChangeBucketOwner admin api
|
||||||
app.Patch("/change-bucket-owner", controller.ChangeBucketOwner)
|
app.Patch("/change-bucket-owner", controllers.ProcessResponse(ctrl.ChangeBucketOwner, logger, nil, nil))
|
||||||
|
|
||||||
// ListBucketsAndOwners admin api
|
// ListBucketsAndOwners admin api
|
||||||
app.Patch("/list-buckets", controller.ListBuckets)
|
app.Patch("/list-buckets", controllers.ProcessResponse(ctrl.ListBuckets, logger, nil, nil))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ type S3AdminServer struct {
|
|||||||
router *S3AdminRouter
|
router *S3AdminRouter
|
||||||
port string
|
port string
|
||||||
cert *tls.Certificate
|
cert *tls.Certificate
|
||||||
|
quiet bool
|
||||||
|
debug bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAdminServer(app *fiber.App, be backend.Backend, root middlewares.RootUserConfig, port, region string, iam auth.IAMService, l s3log.AuditLogger, opts ...AdminOpt) *S3AdminServer {
|
func NewAdminServer(app *fiber.App, be backend.Backend, root middlewares.RootUserConfig, port, region string, iam auth.IAMService, l s3log.AuditLogger, opts ...AdminOpt) *S3AdminServer {
|
||||||
@@ -46,8 +48,13 @@ func NewAdminServer(app *fiber.App, be backend.Backend, root middlewares.RootUse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Logging middlewares
|
// Logging middlewares
|
||||||
app.Use(logger.New())
|
if !server.quiet {
|
||||||
|
app.Use(logger.New(logger.Config{
|
||||||
|
Format: "${time} | ${status} | ${latency} | ${ip} | ${method} | ${path} | ${error} | ${queryParams}\n",
|
||||||
|
}))
|
||||||
|
}
|
||||||
app.Use(middlewares.DecodeURL(l, nil))
|
app.Use(middlewares.DecodeURL(l, nil))
|
||||||
|
app.Use(middlewares.DebugLogger())
|
||||||
|
|
||||||
// Authentication middlewares
|
// Authentication middlewares
|
||||||
app.Use(middlewares.VerifyV4Signature(root, iam, l, nil, region, false))
|
app.Use(middlewares.VerifyV4Signature(root, iam, l, nil, region, false))
|
||||||
@@ -67,6 +74,16 @@ func WithAdminSrvTLS(cert tls.Certificate) AdminOpt {
|
|||||||
return func(s *S3AdminServer) { s.cert = &cert }
|
return func(s *S3AdminServer) { s.cert = &cert }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithQuiet silences default logging output
|
||||||
|
func WithAdminQuiet() AdminOpt {
|
||||||
|
return func(s *S3AdminServer) { s.quiet = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAdminDebug enables the debug logging
|
||||||
|
func WithAdminDebug() AdminOpt {
|
||||||
|
return func(s *S3AdminServer) { s.debug = true }
|
||||||
|
}
|
||||||
|
|
||||||
func (sa *S3AdminServer) Serve() (err error) {
|
func (sa *S3AdminServer) Serve() (err error) {
|
||||||
if sa.cert != nil {
|
if sa.cert != nil {
|
||||||
return sa.app.ListenTLSWithCertificate(sa.port, *sa.cert)
|
return sa.app.ListenTLSWithCertificate(sa.port, *sa.cert)
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/versity/versitygw/auth"
|
"github.com/versity/versitygw/auth"
|
||||||
"github.com/versity/versitygw/backend"
|
"github.com/versity/versitygw/backend"
|
||||||
@@ -38,23 +41,23 @@ func NewAdminController(iam auth.IAMService, be backend.Backend, l s3log.AuditLo
|
|||||||
return AdminController{iam: iam, be: be, l: l}
|
return AdminController{iam: iam, be: be, l: l}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) CreateUser(ctx *fiber.Ctx) error {
|
func (c AdminController) CreateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||||
var usr auth.Account
|
var usr auth.Account
|
||||||
err := xml.Unmarshal(ctx.Body(), &usr)
|
err := xml.Unmarshal(ctx.Body(), &usr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrMalformedXML),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminCreateUser,
|
Action: metrics.ActionAdminCreateUser,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !usr.Role.IsValid() {
|
if !usr.Role.IsValid() {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrAdminInvalidUserRole),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminCreateUser,
|
Action: metrics.ActionAdminCreateUser,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrAdminInvalidUserRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.iam.CreateAccount(usr)
|
err = c.iam.CreateAccount(usr)
|
||||||
@@ -63,47 +66,47 @@ func (c AdminController) CreateUser(ctx *fiber.Ctx) error {
|
|||||||
err = s3err.GetAPIError(s3err.ErrAdminUserExists)
|
err = s3err.GetAPIError(s3err.ErrAdminUserExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendResponse(ctx, err,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminCreateUser,
|
Action: metrics.ActionAdminCreateUser,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendResponse(ctx, nil,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminCreateUser,
|
Action: metrics.ActionAdminCreateUser,
|
||||||
Status: http.StatusCreated,
|
Status: http.StatusCreated,
|
||||||
})
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) UpdateUser(ctx *fiber.Ctx) error {
|
func (c AdminController) UpdateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||||
access := ctx.Query("access")
|
access := ctx.Query("access")
|
||||||
if access == "" {
|
if access == "" {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrAdminMissingUserAcess),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminUpdateUser,
|
Action: metrics.ActionAdminUpdateUser,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrAdminMissingUserAcess)
|
||||||
}
|
}
|
||||||
|
|
||||||
var props auth.MutableProps
|
var props auth.MutableProps
|
||||||
if err := xml.Unmarshal(ctx.Body(), &props); err != nil {
|
if err := xml.Unmarshal(ctx.Body(), &props); err != nil {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrMalformedXML),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminUpdateUser,
|
Action: metrics.ActionAdminUpdateUser,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := props.Validate()
|
err := props.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrAdminInvalidUserRole),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminUpdateUser,
|
Action: metrics.ActionAdminUpdateUser,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrAdminInvalidUserRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.iam.UpdateUserAccount(access, props)
|
err = c.iam.UpdateUserAccount(access, props)
|
||||||
@@ -112,78 +115,97 @@ func (c AdminController) UpdateUser(ctx *fiber.Ctx) error {
|
|||||||
err = s3err.GetAPIError(s3err.ErrAdminUserNotFound)
|
err = s3err.GetAPIError(s3err.ErrAdminUserNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendResponse(ctx, err,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminUpdateUser,
|
Action: metrics.ActionAdminUpdateUser,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendResponse(ctx, nil,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminUpdateUser,
|
Action: metrics.ActionAdminUpdateUser,
|
||||||
})
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) DeleteUser(ctx *fiber.Ctx) error {
|
func (c AdminController) DeleteUser(ctx *fiber.Ctx) (*Response, error) {
|
||||||
access := ctx.Query("access")
|
access := ctx.Query("access")
|
||||||
|
|
||||||
err := c.iam.DeleteUserAccount(access)
|
err := c.iam.DeleteUserAccount(access)
|
||||||
return SendResponse(ctx, err,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminDeleteUser,
|
Action: metrics.ActionAdminDeleteUser,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) ListUsers(ctx *fiber.Ctx) error {
|
func (c AdminController) ListUsers(ctx *fiber.Ctx) (*Response, error) {
|
||||||
accs, err := c.iam.ListUserAccounts()
|
accs, err := c.iam.ListUserAccounts()
|
||||||
return SendXMLResponse(ctx,
|
return &Response{
|
||||||
auth.ListUserAccountsResult{
|
Data: auth.ListUserAccountsResult{Accounts: accs},
|
||||||
Accounts: accs,
|
MetaOpts: &MetaOptions{
|
||||||
}, err,
|
|
||||||
&MetaOpts{
|
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminListUsers,
|
Action: metrics.ActionAdminListUsers,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) error {
|
func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) (*Response, error) {
|
||||||
owner := ctx.Query("owner")
|
owner := ctx.Query("owner")
|
||||||
bucket := ctx.Query("bucket")
|
bucket := ctx.Query("bucket")
|
||||||
|
|
||||||
accs, err := auth.CheckIfAccountsExist([]string{owner}, c.iam)
|
accs, err := auth.CheckIfAccountsExist([]string{owner}, c.iam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendResponse(ctx, err,
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminChangeBucketOwner,
|
Action: metrics.ActionAdminChangeBucketOwner,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
if len(accs) > 0 {
|
if len(accs) > 0 {
|
||||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrAdminUserNotFound),
|
return &Response{
|
||||||
&MetaOpts{
|
MetaOpts: &MetaOptions{
|
||||||
Logger: c.l,
|
|
||||||
Action: metrics.ActionAdminChangeBucketOwner,
|
Action: metrics.ActionAdminChangeBucketOwner,
|
||||||
})
|
},
|
||||||
|
}, s3err.GetAPIError(s3err.ErrAdminUserNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.be.ChangeBucketOwner(ctx.Context(), bucket, owner)
|
acl := auth.ACL{
|
||||||
return SendResponse(ctx, err,
|
Owner: owner,
|
||||||
&MetaOpts{
|
Grantees: []auth.Grantee{
|
||||||
Logger: c.l,
|
{
|
||||||
|
Permission: auth.PermissionFullControl,
|
||||||
|
Access: owner,
|
||||||
|
Type: types.TypeCanonicalUser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
aclParsed, err := json.Marshal(acl)
|
||||||
|
if err != nil {
|
||||||
|
return &Response{
|
||||||
|
MetaOpts: &MetaOptions{
|
||||||
|
Action: metrics.ActionAdminChangeBucketOwner,
|
||||||
|
},
|
||||||
|
}, fmt.Errorf("failed to marshal the bucket acl: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.be.ChangeBucketOwner(ctx.Context(), bucket, aclParsed)
|
||||||
|
return &Response{
|
||||||
|
MetaOpts: &MetaOptions{
|
||||||
Action: metrics.ActionAdminChangeBucketOwner,
|
Action: metrics.ActionAdminChangeBucketOwner,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminController) ListBuckets(ctx *fiber.Ctx) error {
|
func (c AdminController) ListBuckets(ctx *fiber.Ctx) (*Response, error) {
|
||||||
buckets, err := c.be.ListBucketsAndOwners(ctx.Context())
|
buckets, err := c.be.ListBucketsAndOwners(ctx.Context())
|
||||||
return SendXMLResponse(ctx,
|
return &Response{
|
||||||
s3response.ListBucketsResult{
|
Data: s3response.ListBucketsResult{
|
||||||
Buckets: buckets,
|
Buckets: buckets,
|
||||||
}, err, &MetaOpts{
|
},
|
||||||
Logger: c.l,
|
MetaOpts: &MetaOptions{
|
||||||
Action: metrics.ActionAdminListBuckets,
|
Action: metrics.ActionAdminListBuckets,
|
||||||
})
|
},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,454 +0,0 @@
|
|||||||
// Copyright 2023 Versity Software
|
|
||||||
// This file is licensed under the Apache License, Version 2.0
|
|
||||||
// (the "License"); you may not use this file except in compliance
|
|
||||||
// with the License. You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing,
|
|
||||||
// software distributed under the License is distributed on an
|
|
||||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
// KIND, either express or implied. See the License for the
|
|
||||||
// specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/versity/versitygw/auth"
|
|
||||||
"github.com/versity/versitygw/s3response"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAdminController_CreateUser(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
adminController := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
CreateAccountFunc: func(account auth.Account) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app := fiber.New()
|
|
||||||
|
|
||||||
app.Patch("/create-user", adminController.CreateUser)
|
|
||||||
|
|
||||||
succUser := `
|
|
||||||
<Account>
|
|
||||||
<Access>access</Access>
|
|
||||||
<Secret>secret</Secret>
|
|
||||||
<Role>admin</Role>
|
|
||||||
<UserID>0</UserID>
|
|
||||||
<GroupID>0</GroupID>
|
|
||||||
</Account>
|
|
||||||
`
|
|
||||||
invuser := `
|
|
||||||
<Account>
|
|
||||||
<Access>access</Access>
|
|
||||||
<Secret>secret</Secret>
|
|
||||||
<Role>invalid_role</Role>
|
|
||||||
<UserID>0</UserID>
|
|
||||||
<GroupID>0</GroupID>
|
|
||||||
</Account>
|
|
||||||
`
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Admin-create-user-malformed-body",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/create-user", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-create-user-invalid-requester-role",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/create-user", strings.NewReader(invuser)),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-create-user-success",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/create-user", strings.NewReader(succUser)),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 201,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.CreateUser() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.CreateUser() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdminController_UpdateUser(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
adminController := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
UpdateUserAccountFunc: func(access string, props auth.MutableProps) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app := fiber.New()
|
|
||||||
|
|
||||||
app.Patch("/update-user", adminController.UpdateUser)
|
|
||||||
|
|
||||||
adminControllerErr := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
UpdateUserAccountFunc: func(access string, props auth.MutableProps) error {
|
|
||||||
return auth.ErrNoSuchUser
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
appNotFound := fiber.New()
|
|
||||||
|
|
||||||
appNotFound.Patch("/update-user", adminControllerErr.UpdateUser)
|
|
||||||
|
|
||||||
succUser := `
|
|
||||||
<Account>
|
|
||||||
<Secret>secret</Secret>
|
|
||||||
<UserID>0</UserID>
|
|
||||||
<GroupID>0</GroupID>
|
|
||||||
</Account>
|
|
||||||
`
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Admin-update-user-success",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/update-user?access=access", strings.NewReader(succUser)),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-update-user-missing-access",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/update-user", strings.NewReader(succUser)),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 404,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-update-user-invalid-request-body",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/update-user?access=access", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-update-user-not-found",
|
|
||||||
app: appNotFound,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/update-user?access=access", strings.NewReader(succUser)),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 404,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.UpdateUser() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.UpdateUser() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdminController_DeleteUser(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
adminController := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
DeleteUserAccountFunc: func(access string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app := fiber.New()
|
|
||||||
|
|
||||||
app.Patch("/delete-user", adminController.DeleteUser)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Admin-delete-user-success",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/delete-user?access=test", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 200,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.DeleteUser() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.DeleteUser() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdminController_ListUsers(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
adminController := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
ListUserAccountsFunc: func() ([]auth.Account, error) {
|
|
||||||
return []auth.Account{}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
adminControllerErr := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
ListUserAccountsFunc: func() ([]auth.Account, error) {
|
|
||||||
return []auth.Account{}, fmt.Errorf("server error")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
appErr := fiber.New()
|
|
||||||
appErr.Patch("/list-users", adminControllerErr.ListUsers)
|
|
||||||
|
|
||||||
appSucc := fiber.New()
|
|
||||||
appSucc.Patch("/list-users", adminController.ListUsers)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Admin-list-users-iam-error",
|
|
||||||
app: appErr,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/list-users", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin-list-users-success",
|
|
||||||
app: appSucc,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/list-users", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 200,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.ListUsers() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.ListUsers() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdminController_ChangeBucketOwner(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
adminController := AdminController{
|
|
||||||
be: &BackendMock{
|
|
||||||
ChangeBucketOwnerFunc: func(contextMoqParam context.Context, bucket, owner string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
GetUserAccountFunc: func(access string) (auth.Account, error) {
|
|
||||||
return auth.Account{}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
adminControllerIamErr := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
GetUserAccountFunc: func(access string) (auth.Account, error) {
|
|
||||||
return auth.Account{}, fmt.Errorf("unknown server error")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
adminControllerIamAccDoesNotExist := AdminController{
|
|
||||||
iam: &IAMServiceMock{
|
|
||||||
GetUserAccountFunc: func(access string) (auth.Account, error) {
|
|
||||||
return auth.Account{}, auth.ErrNoSuchUser
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app := fiber.New()
|
|
||||||
app.Patch("/change-bucket-owner", adminController.ChangeBucketOwner)
|
|
||||||
|
|
||||||
appIamErr := fiber.New()
|
|
||||||
appIamErr.Patch("/change-bucket-owner", adminControllerIamErr.ChangeBucketOwner)
|
|
||||||
|
|
||||||
appIamNoSuchUser := fiber.New()
|
|
||||||
appIamNoSuchUser.Patch("/change-bucket-owner", adminControllerIamAccDoesNotExist.ChangeBucketOwner)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Change-bucket-owner-check-account-server-error",
|
|
||||||
app: appIamErr,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/change-bucket-owner", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Change-bucket-owner-acc-does-not-exist",
|
|
||||||
app: appIamNoSuchUser,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/change-bucket-owner", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 404,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Change-bucket-owner-success",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/change-bucket-owner?bucket=bucket&owner=owner", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 200,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.ChangeBucketOwner() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.ChangeBucketOwner() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdminController_ListBuckets(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
adminController := AdminController{
|
|
||||||
be: &BackendMock{
|
|
||||||
ListBucketsAndOwnersFunc: func(contextMoqParam context.Context) ([]s3response.Bucket, error) {
|
|
||||||
return []s3response.Bucket{}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app := fiber.New()
|
|
||||||
app.Patch("/list-buckets", adminController.ListBuckets)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
app *fiber.App
|
|
||||||
args args
|
|
||||||
wantErr bool
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "List-buckets-success",
|
|
||||||
app: app,
|
|
||||||
args: args{
|
|
||||||
req: httptest.NewRequest(http.MethodPatch, "/list-buckets", nil),
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
statusCode: 200,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
resp, err := tt.app.Test(tt.args.req)
|
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("AdminController.ListBuckets() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != tt.statusCode {
|
|
||||||
t.Errorf("AdminController.ListBuckets() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1991,93 +1991,3 @@ func SendResponse(ctx *fiber.Ctx, err error, l *MetaOpts) error {
|
|||||||
ctx.Status(l.Status)
|
ctx.Status(l.Status)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendXMLResponse(ctx *fiber.Ctx, resp any, err error, l *MetaOpts) error {
|
|
||||||
if l.MetricsMng != nil {
|
|
||||||
if l.ObjectCount > 0 {
|
|
||||||
l.MetricsMng.Send(ctx, err, l.Action, l.ObjectCount, l.Status)
|
|
||||||
} else {
|
|
||||||
l.MetricsMng.Send(ctx, err, l.Action, l.ContentLength, l.Status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if l.Logger != nil {
|
|
||||||
l.Logger.Log(ctx, err, nil, s3log.LogMeta{
|
|
||||||
Action: l.Action,
|
|
||||||
BucketOwner: l.BucketOwner,
|
|
||||||
ObjectSize: l.ObjectSize,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
serr, ok := err.(s3err.APIError)
|
|
||||||
if ok {
|
|
||||||
ctx.Status(serr.HTTPStatusCode)
|
|
||||||
return ctx.Send(s3err.GetAPIErrorResponse(serr, "", "", ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "Internal Error, %v\n", err)
|
|
||||||
ctx.Status(http.StatusInternalServerError)
|
|
||||||
|
|
||||||
return ctx.Send(s3err.GetAPIErrorResponse(
|
|
||||||
s3err.GetAPIError(s3err.ErrInternalError), "", "", ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
var b []byte
|
|
||||||
|
|
||||||
// Handle already encoded responses(text, json...)
|
|
||||||
encodedResp, ok := resp.([]byte)
|
|
||||||
if ok {
|
|
||||||
b = encodedResp
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp != nil && !ok {
|
|
||||||
if b, err = xml.Marshal(resp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(b) > 0 {
|
|
||||||
ctx.Response().Header.Set("Content-Length", fmt.Sprint(len(b)))
|
|
||||||
ctx.Response().Header.SetContentType(fiber.MIMEApplicationXML)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.Logger != nil {
|
|
||||||
l.Logger.Log(ctx, nil, b, s3log.LogMeta{
|
|
||||||
Action: l.Action,
|
|
||||||
BucketOwner: l.BucketOwner,
|
|
||||||
ObjectSize: l.ObjectSize,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.EvSender != nil {
|
|
||||||
l.EvSender.SendEvent(ctx, s3event.EventMeta{
|
|
||||||
BucketOwner: l.BucketOwner,
|
|
||||||
ObjectSize: l.ObjectSize,
|
|
||||||
ObjectETag: l.ObjectETag,
|
|
||||||
VersionId: l.VersionId,
|
|
||||||
EventName: l.EventName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
if len(b) > 0 {
|
|
||||||
ctx.Response().Header.Set("Content-Length", fmt.Sprint(len(b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Send(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
msglen := len(xmlhdr) + len(b)
|
|
||||||
if msglen > maxXMLBodyLen {
|
|
||||||
debuglogger.Logf("XML encoded body len %v exceeds max len %v",
|
|
||||||
msglen, maxXMLBodyLen)
|
|
||||||
ctx.Status(http.StatusInternalServerError)
|
|
||||||
|
|
||||||
return ctx.Send(s3err.GetAPIErrorResponse(
|
|
||||||
s3err.GetAPIError(s3err.ErrInternalError), "", "", ""))
|
|
||||||
}
|
|
||||||
res := make([]byte, 0, msglen)
|
|
||||||
res = append(res, xmlhdr...)
|
|
||||||
res = append(res, b...)
|
|
||||||
|
|
||||||
return ctx.Send(res)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -55,10 +55,10 @@ func AclParser(be backend.Backend, logger s3log.AuditLogger, readonly bool) fibe
|
|||||||
!ctx.Request().URI().QueryArgs().Has("cors") {
|
!ctx.Request().URI().QueryArgs().Has("cors") {
|
||||||
isRoot, acct := utils.ContextKeyIsRoot.Get(ctx).(bool), utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
isRoot, acct := utils.ContextKeyIsRoot.Get(ctx).(bool), utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||||
if err := auth.MayCreateBucket(acct, isRoot); err != nil {
|
if err := auth.MayCreateBucket(acct, isRoot); err != nil {
|
||||||
return controllers.SendXMLResponse(ctx, nil, err, &controllers.MetaOpts{Logger: logger, Action: "CreateBucket"})
|
return controllers.SendResponse(ctx, err, &controllers.MetaOpts{Logger: logger, Action: "CreateBucket"})
|
||||||
}
|
}
|
||||||
if readonly {
|
if readonly {
|
||||||
return controllers.SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrAccessDenied),
|
return controllers.SendResponse(ctx, s3err.GetAPIError(s3err.ErrAccessDenied),
|
||||||
&controllers.MetaOpts{
|
&controllers.MetaOpts{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
Action: "CreateBucket",
|
Action: "CreateBucket",
|
||||||
|
|||||||
@@ -36,22 +36,22 @@ func (sa *S3ApiRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMServ
|
|||||||
adminController := controllers.NewAdminController(iam, be, aLogger)
|
adminController := controllers.NewAdminController(iam, be, aLogger)
|
||||||
|
|
||||||
// CreateUser admin api
|
// CreateUser admin api
|
||||||
app.Patch("/create-user", middlewares.IsAdmin(logger), adminController.CreateUser)
|
app.Patch("/create-user", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.CreateUser, aLogger, nil, nil))
|
||||||
|
|
||||||
// DeleteUsers admin api
|
// DeleteUsers admin api
|
||||||
app.Patch("/delete-user", middlewares.IsAdmin(logger), adminController.DeleteUser)
|
app.Patch("/delete-user", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.DeleteUser, aLogger, nil, nil))
|
||||||
|
|
||||||
// UpdateUser admin api
|
// UpdateUser admin api
|
||||||
app.Patch("/update-user", middlewares.IsAdmin(logger), adminController.UpdateUser)
|
app.Patch("/update-user", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.UpdateUser, aLogger, nil, nil))
|
||||||
|
|
||||||
// ListUsers admin api
|
// ListUsers admin api
|
||||||
app.Patch("/list-users", middlewares.IsAdmin(logger), adminController.ListUsers)
|
app.Patch("/list-users", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.ListUsers, aLogger, nil, nil))
|
||||||
|
|
||||||
// ChangeBucketOwner admin api
|
// ChangeBucketOwner admin api
|
||||||
app.Patch("/change-bucket-owner", middlewares.IsAdmin(logger), adminController.ChangeBucketOwner)
|
app.Patch("/change-bucket-owner", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.ChangeBucketOwner, aLogger, nil, nil))
|
||||||
|
|
||||||
// ListBucketsAndOwners admin api
|
// ListBucketsAndOwners admin api
|
||||||
app.Patch("/list-buckets", middlewares.IsAdmin(logger), adminController.ListBuckets)
|
app.Patch("/list-buckets", middlewares.IsAdmin(logger), controllers.ProcessResponse(adminController.ListBuckets, aLogger, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBuckets action
|
// ListBuckets action
|
||||||
|
|||||||
Reference in New Issue
Block a user