From 80d6a244cf678abb45d3462397c6e1ac5ad3a527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=91=D0=BE=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Thu, 5 Mar 2026 11:32:32 +0200 Subject: [PATCH] splitted one operator module to file, account, image operators; splitted operator functions; etc --- Makefile.am | 2 - Makefile.in | 38 +-- app/accoper/createacc.go | 70 +++++ app/accoper/creategrant.go | 98 ++++++ app/accoper/delacc.go | 72 +++++ app/accoper/delgrant.go | 41 +++ app/accoper/getacc.go | 84 ++++++ app/accoper/getgrant.go | 40 +++ app/accoper/listacc.go | 50 +++ app/accoper/listgrant.go | 56 ++++ app/{operator => accoper}/operator.go | 4 +- app/accoper/updacc.go | 86 ++++++ app/accoper/updgrant.go | 52 ++++ app/config/variant.go | 10 + .../fileop_delcats.go => fileoper/delcats.go} | 7 +- .../fileop_delfile.go => fileoper/delfile.go} | 3 +- .../fileinfo.go} | 3 +- .../fileop_getfile.go => fileoper/getfile.go} | 3 +- .../listcats.go} | 3 +- .../listfiles.go} | 2 +- app/fileoper/operator.go | 42 +++ .../fileop_putfile.go => fileoper/putfile.go} | 3 +- app/handler/aaafunc.go | 4 +- app/handler/account.go | 22 +- app/handler/blob.go | 28 +- app/handler/file.go | 30 +- app/handler/grant.go | 22 +- app/handler/handler.go | 20 +- app/handler/manifest.go | 30 +- app/handler/service.go | 6 +- app/handler/version.go | 6 +- app/{operator => imageoper}/blob.go | 2 +- app/{operator => imageoper}/imgaux.go | 2 +- app/{operator => imageoper}/manifest.go | 2 +- app/{operator => imageoper}/ociaux.go | 2 +- app/imageoper/operator.go | 42 +++ app/{operator => imageoper}/service.go | 2 +- app/{operator => imageoper}/version.go | 2 +- app/operator/account.go | 284 ------------------ app/operator/grant.go | 254 ---------------- app/router/context.go | 2 +- app/server/server.go | 44 ++- cmd/mstorectl/filecmd/delcoll.go | 4 +- cmd/mstorectl/filecmd/impfiles.go | 14 +- cmd/mstorectl/filecmd/listcolls.go | 2 +- cmd/mstorectl/filecmd/listfiles.go | 22 +- pkg/client/imageinfo.go | 1 - pkg/descr/file.go | 37 +-- pkg/filecli/client.go | 16 +- pkg/filecli/fileinfo.go | 2 +- pkg/filecli/repo.go | 24 +- pkg/repocli/client.go | 8 +- pkg/repocli/mimetyp.go | 4 +- test/file_test.go | 166 +++++----- 54 files changed, 1049 insertions(+), 826 deletions(-) create mode 100644 app/accoper/createacc.go create mode 100644 app/accoper/creategrant.go create mode 100644 app/accoper/delacc.go create mode 100644 app/accoper/delgrant.go create mode 100644 app/accoper/getacc.go create mode 100644 app/accoper/getgrant.go create mode 100644 app/accoper/listacc.go create mode 100644 app/accoper/listgrant.go rename app/{operator => accoper}/operator.go (92%) create mode 100644 app/accoper/updacc.go create mode 100644 app/accoper/updgrant.go create mode 100644 app/config/variant.go rename app/{operator/fileop_delcats.go => fileoper/delcats.go} (96%) rename app/{operator/fileop_delfile.go => fileoper/delfile.go} (98%) rename app/{operator/fileop_fileinfo.go => fileoper/fileinfo.go} (99%) rename app/{operator/fileop_getfile.go => fileoper/getfile.go} (99%) rename app/{operator/fileop_listcats.go => fileoper/listcats.go} (99%) rename app/{operator/fileop_listfiles.go => fileoper/listfiles.go} (99%) create mode 100644 app/fileoper/operator.go rename app/{operator/fileop_putfile.go => fileoper/putfile.go} (99%) rename app/{operator => imageoper}/blob.go (99%) rename app/{operator => imageoper}/imgaux.go (98%) rename app/{operator => imageoper}/manifest.go (99%) rename app/{operator => imageoper}/ociaux.go (99%) create mode 100644 app/imageoper/operator.go rename app/{operator => imageoper}/service.go (96%) rename app/{operator => imageoper}/version.go (97%) delete mode 100644 app/operator/account.go delete mode 100644 app/operator/grant.go diff --git a/Makefile.am b/Makefile.am index 65f22d8..c447e8f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,7 +68,6 @@ EXTRA_mstored_SOURCES += \ \ app/operator/account.go \ app/operator/blob.go \ - app/operator/file.go \ app/operator/grant.go \ app/operator/imgaux.go \ app/operator/manifest.go \ @@ -103,7 +102,6 @@ EXTRA_mstored_SOURCES += \ pkg/client/account.go \ pkg/client/client.go \ pkg/client/fileaux.go \ - pkg/client/file.go \ pkg/client/grant.go \ pkg/client/httpcall.go \ pkg/client/imageaux.go \ diff --git a/Makefile.in b/Makefile.in index 4206a84..fdd80ad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -376,26 +376,26 @@ EXTRA_mstored_SOURCES = cmd/mstored/starter/starter.go \ app/maindb/grant.go app/maindb/init.go app/maindb/maindb.go \ app/maindb/manifest.go app/maindb/scheme.go \ app/operator/account.go app/operator/blob.go \ - app/operator/file.go app/operator/grant.go \ - app/operator/imgaux.go app/operator/manifest.go \ - app/operator/ociaux.go app/operator/operator.go \ - app/operator/service.go app/operator/version.go \ - app/router/bindobj.go app/router/context.go \ - app/router/corsmw.go app/router/loggingmw.go \ - app/router/pathc.go app/router/recovermw.go \ - app/router/router.go app/server/server.go \ - app/service/service.go app/storage/storage.go \ - pkg/auxhttp/basic.go pkg/auxhttp/crange.go \ - pkg/auxoci/ociaux.go pkg/auxpwd/passwd.go \ - pkg/auxtool/cleandir.go pkg/auxtool/fileex.go \ - pkg/auxtool/randstr.go pkg/auxtool/tmpfile.go \ - pkg/auxtool/unixnow.go pkg/auxutar/utar.go pkg/auxuuid/uuid.go \ + app/operator/grant.go app/operator/imgaux.go \ + app/operator/manifest.go app/operator/ociaux.go \ + app/operator/operator.go app/operator/service.go \ + app/operator/version.go app/router/bindobj.go \ + app/router/context.go app/router/corsmw.go \ + app/router/loggingmw.go app/router/pathc.go \ + app/router/recovermw.go app/router/router.go \ + app/server/server.go app/service/service.go \ + app/storage/storage.go pkg/auxhttp/basic.go \ + pkg/auxhttp/crange.go pkg/auxoci/ociaux.go \ + pkg/auxpwd/passwd.go pkg/auxtool/cleandir.go \ + pkg/auxtool/fileex.go pkg/auxtool/randstr.go \ + pkg/auxtool/tmpfile.go pkg/auxtool/unixnow.go \ + pkg/auxutar/utar.go pkg/auxuuid/uuid.go \ pkg/auxx509/x509cert.go pkg/client/account.go \ - pkg/client/client.go pkg/client/fileaux.go pkg/client/file.go \ - pkg/client/grant.go pkg/client/httpcall.go \ - pkg/client/imageaux.go pkg/client/imagedelete.go \ - pkg/client/imageinfo.go pkg/client/imagepull.go \ - pkg/client/imagepush.go pkg/client/service.go + pkg/client/client.go pkg/client/fileaux.go pkg/client/grant.go \ + pkg/client/httpcall.go pkg/client/imageaux.go \ + pkg/client/imagedelete.go pkg/client/imageinfo.go \ + pkg/client/imagepull.go pkg/client/imagepush.go \ + pkg/client/service.go CWD = $(shell pwd) EXTRA_DIST = vendor/ \ \ diff --git a/app/accoper/createacc.go b/app/accoper/createacc.go new file mode 100644 index 0000000..e81f786 --- /dev/null +++ b/app/accoper/createacc.go @@ -0,0 +1,70 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/auxpwd" + "mstore/pkg/auxtool" + "mstore/pkg/auxuuid" + "mstore/pkg/descr" +) + +type CreateAccountParams struct { + Username string `json:"username"` + Password string `json:"password"` +} +type CreateAccountResult struct { + AccountID string `json:"accountId"` +} + +func (oper *Operator) CreateAccount(ctx context.Context, operatorID string, params *CreateAccountParams) (*CreateAccountResult, error) { + var err error + res := &CreateAccountResult{} + + if params.Username == "" { + err := fmt.Errorf("Empty username parameters") + return res, err + } + + if params.Password == "" { + err := fmt.Errorf("Empty password parameter") + return res, err + } + + accountExists, _, err := oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if accountExists { + err := fmt.Errorf("Account with thist name already exists") + return res, err + } + now := auxtool.TimeNow() + passhash := auxpwd.MakeSHA256Hash([]byte(params.Password)) + accountDescr := &descr.Account{ + ID: auxuuid.NewUUID(), + Username: params.Username, + Passhash: passhash, + Disabled: false, + CreatedAt: now, + UpdatedAt: now, + CreatedBy: operatorID, + UpdatedBy: operatorID, + } + err = oper.mdb.InsertAccount(ctx, accountDescr) + if err != nil { + return res, err + } + res.AccountID = accountDescr.ID + return res, err +} diff --git a/app/accoper/creategrant.go b/app/accoper/creategrant.go new file mode 100644 index 0000000..985ecad --- /dev/null +++ b/app/accoper/creategrant.go @@ -0,0 +1,98 @@ +package accoper + +import ( + "context" + "fmt" + "regexp" + + "mstore/pkg/auxtool" + "mstore/pkg/auxuuid" + "mstore/pkg/descr" +) + +// CreateGrant +type CreateGrantParams struct { + AccountID string `json:"accountID"` + Username string `json:"username"` + Right string `json:"operation"` + Pattern string `json:"pattern"` +} +type CreateGrantResult struct { + GrantID string `json:"grantId"` +} + +func (oper *Operator) CreateGrant(ctx context.Context, operatorID string, params *CreateGrantParams) (*CreateGrantResult, error) { + var err error + res := &CreateGrantResult{} + + if params.AccountID == "" { + err := fmt.Errorf("Empty accountId parameters") + return res, err + } + if params.Right == "" { + err := fmt.Errorf("Empty operation parameter") + return res, err + } + if params.Pattern == "" { + err := fmt.Errorf("Empty pattern parameter") + return res, err + } + + _, err = regexp.Compile(params.Pattern) + if err != nil { + err := fmt.Errorf("Cannot compile regexp %s: %v", err) + return res, err + } + + var accountDescr *descr.Account + var accountExists bool + switch { + case params.AccountID != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) + return res, err + } + case params.Username != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with name %s dont exists", params.Username) + return res, err + } + default: + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + grantExists, _, err := oper.mdb.GetGrantByAccoundIDRightPattern(ctx, params.AccountID, params.Right, params.Pattern) + if err != nil { + return res, err + } + if grantExists { + err := fmt.Errorf("Grant with this right already exists") + return res, err + } + oper.logg.Debugf("Call CreateGrant") + now := auxtool.TimeNow() + grantDescr := &descr.Grant{ + ID: auxuuid.NewUUID(), + AccountID: accountDescr.ID, + Right: params.Right, + Pattern: params.Pattern, + CreatedAt: now, + UpdatedAt: now, + CreatedBy: operatorID, + UpdatedBy: operatorID, + } + err = oper.mdb.InsertGrant(ctx, grantDescr) + if err != nil { + return res, err + } + res.GrantID = grantDescr.ID + return res, err +} diff --git a/app/accoper/delacc.go b/app/accoper/delacc.go new file mode 100644 index 0000000..860dd7e --- /dev/null +++ b/app/accoper/delacc.go @@ -0,0 +1,72 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/descr" +) + +type DeleteAccountParams struct { + Username string `json:"username"` + AccountID string `json:"accountId"` +} +type DeleteAccountResult struct{} + +func (oper *Operator) DeleteAccount(ctx context.Context, operatorID string, params *DeleteAccountParams) (*DeleteAccountResult, error) { + var err error + res := &DeleteAccountResult{} + + if params.Username == "" && params.AccountID == "" { + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + + var accountDescr *descr.Account + var accountExists bool + switch { + case params.AccountID != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) + return res, err + } + case params.Username != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with name %s dont exists", params.Username) + return res, err + } + default: + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + if accountDescr == nil { + err := fmt.Errorf("Null account desriptor") + return res, err + } + err = oper.mdb.DeleteAllGrantsForAccountID(ctx, accountDescr.ID) + if err != nil { + return res, err + } + err = oper.mdb.DeleteAccountByID(ctx, accountDescr.ID) + if err != nil { + return res, err + } + return res, err +} diff --git a/app/accoper/delgrant.go b/app/accoper/delgrant.go new file mode 100644 index 0000000..d660159 --- /dev/null +++ b/app/accoper/delgrant.go @@ -0,0 +1,41 @@ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/descr" +) + +// DeleteGrant +type DeleteGrantParams struct { + GrantID string `json:"grantId"` +} +type DeleteGrantResult struct{} + +func (oper *Operator) DeleteGrant(ctx context.Context, operatorID string, params *DeleteGrantParams) (*DeleteGrantResult, error) { + var err error + res := &DeleteGrantResult{} + + if params.GrantID == "" { + err := fmt.Errorf("Empty grantId parameter") + return res, err + } + + var grantDescr *descr.Grant + var grantExists bool + + grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) + if err != nil { + return res, err + } + if !grantExists { + err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) + return res, err + } + err = oper.mdb.DeleteGrantByID(ctx, grantDescr.ID) + if err != nil { + return res, err + } + return res, err +} diff --git a/app/accoper/getacc.go b/app/accoper/getacc.go new file mode 100644 index 0000000..1cb77fc --- /dev/null +++ b/app/accoper/getacc.go @@ -0,0 +1,84 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/descr" +) + +// GetAccount +type GetAccountParams struct { + Username string `json:"username"` + AccountID string `json:"accountId"` +} +type GetAccountResult struct { + Account *descr.AccountShort `json:"account"` +} + +func (oper *Operator) GetAccount(ctx context.Context, operatorID string, params *GetAccountParams) (*GetAccountResult, error) { + var err error + res := &GetAccountResult{} + + if params.Username == "" && params.AccountID == "" { + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + + var accountDescr *descr.Account + var accountExists bool + switch { + case params.AccountID != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) + return res, err + } + case params.Username != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with name %s dont exists", params.Username) + return res, err + } + default: + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + if accountDescr == nil { + err := fmt.Errorf("Null account desriptor") + return res, err + } + accountShort := &descr.AccountShort{ + ID: accountDescr.ID, + Username: accountDescr.Username, + CreatedAt: accountDescr.CreatedAt, + UpdatedAt: accountDescr.UpdatedAt, + CreatedBy: accountDescr.CreatedBy, + UpdatedBy: accountDescr.UpdatedBy, + Disabled: accountDescr.Disabled, + Grants: make([]descr.Grant, 0), + } + grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID) + if err != nil { + return res, err + } + accountShort.Grants = grantDescrs + + res.Account = accountShort + return res, err +} diff --git a/app/accoper/getgrant.go b/app/accoper/getgrant.go new file mode 100644 index 0000000..483eda2 --- /dev/null +++ b/app/accoper/getgrant.go @@ -0,0 +1,40 @@ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/descr" +) + +// Get Grants +type GetGrantParams struct { + GrantID string `json:"grantId"` +} +type GetGrantResult struct { + Grant *descr.Grant `json:"grant"` +} + +func (oper *Operator) GetGrant(ctx context.Context, operatorID string, params *GetGrantParams) (*GetGrantResult, error) { + var err error + res := &GetGrantResult{} + + if params.GrantID == "" { + err := fmt.Errorf("Empty grantId parameter") + return res, err + } + + var grantDescr *descr.Grant + var grantExists bool + grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) + if err != nil { + return res, err + } + if !grantExists { + err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) + return res, err + } + + res.Grant = grantDescr + return res, err +} diff --git a/app/accoper/listacc.go b/app/accoper/listacc.go new file mode 100644 index 0000000..c2241fb --- /dev/null +++ b/app/accoper/listacc.go @@ -0,0 +1,50 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package accoper + +import ( + "context" + + "mstore/pkg/descr" +) + +type ListAccountsParams struct{} +type ListAccountsResult struct { + Accounts []descr.AccountShort `json:"accounts"` +} + +func (oper *Operator) ListAccounts(ctx context.Context, params *ListAccountsParams) (*ListAccountsResult, error) { + var err error + res := &ListAccountsResult{} + + accountDescrs, err := oper.mdb.ReducedListAccounts(ctx) + if err != nil { + return res, err + } + for _, accountDescr := range accountDescrs { + accountShort := descr.AccountShort{ + ID: accountDescr.ID, + Username: accountDescr.Username, + Disabled: accountDescr.Disabled, + CreatedAt: accountDescr.CreatedAt, + UpdatedAt: accountDescr.UpdatedAt, + CreatedBy: accountDescr.CreatedBy, + UpdatedBy: accountDescr.UpdatedBy, + Grants: make([]descr.Grant, 0), + } + grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID) + if err != nil { + return res, err + } + accountShort.Grants = grantDescrs + res.Accounts = append(res.Accounts, accountShort) + } + return res, err +} diff --git a/app/accoper/listgrant.go b/app/accoper/listgrant.go new file mode 100644 index 0000000..dac4c0e --- /dev/null +++ b/app/accoper/listgrant.go @@ -0,0 +1,56 @@ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/descr" +) + +// ListGrants +type ListGrantsParams struct { + Username string + AccountID string +} +type ListGrantsResult struct { + Grants []descr.Grant `json:"grants"` +} + +func (oper *Operator) ListGrants(ctx context.Context, operatorID string, params *ListGrantsParams) (*ListGrantsResult, error) { + var err error + res := &ListGrantsResult{ + Grants: make([]descr.Grant, 0), + } + var accountDescr *descr.Account + var accountExists bool + switch { + case params.AccountID != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) + return res, err + } + case params.Username != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with name %s dont exists", params.Username) + return res, err + } + default: + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + accountID := accountDescr.ID + grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountID) + if err != nil { + return res, err + } + res.Grants = grantDescrs + return res, err +} diff --git a/app/operator/operator.go b/app/accoper/operator.go similarity index 92% rename from app/operator/operator.go rename to app/accoper/operator.go index 34537ec..5a2310c 100644 --- a/app/operator/operator.go +++ b/app/accoper/operator.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package accoper import ( "mstore/app/locker" @@ -37,6 +37,6 @@ func NewOperator(params *OperatorParams) (*Operator, error) { } oper.iLock = locker.NewLocker() oper.fLock = locker.NewLocker() - oper.logg = logger.NewLoggerWithSubject("operator") + oper.logg = logger.NewLoggerWithSubject("imageoper") return oper, err } diff --git a/app/accoper/updacc.go b/app/accoper/updacc.go new file mode 100644 index 0000000..0a0bcab --- /dev/null +++ b/app/accoper/updacc.go @@ -0,0 +1,86 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/auxpwd" + "mstore/pkg/auxtool" + "mstore/pkg/descr" +) + +type UpdateAccountParams struct { + Username string `json:"username"` + AccountID string `json:"accountId"` + NewUsername string `json:"newUsername"` + NewPassword string `json:"newPassword"` + Disabled bool `json:"disabled"` +} +type UpdateAccountResult struct{} + +func (oper *Operator) UpdateAccount(ctx context.Context, operatorID string, params *UpdateAccountParams) (*UpdateAccountResult, error) { + var err error + res := &UpdateAccountResult{} + if params.Username == "" && params.AccountID == "" { + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + var accountDescr *descr.Account + var accountExists bool + switch { + case params.AccountID != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) + return res, err + } + case params.Username != "": + accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) + if err != nil { + return res, err + } + if !accountExists { + err := fmt.Errorf("Account with name %s dont exists", params.Username) + return res, err + } + default: + err := fmt.Errorf("Empty username and accountId parameter") + return res, err + } + if accountDescr == nil { + err := fmt.Errorf("Null account desriptor") + return res, err + } + now := auxtool.TimeNow() + if params.NewUsername != "" { + accountDescr.UpdatedAt = now + accountDescr.Username = params.NewUsername + } + if params.NewPassword != "" { + accountDescr.UpdatedAt = now + passhash := auxpwd.MakeSHA256Hash([]byte(params.NewPassword)) + accountDescr.Passhash = passhash + } + if params.Disabled != accountDescr.Disabled { + accountDescr.UpdatedAt = now + accountDescr.Disabled = params.Disabled + } + + err = oper.mdb.UpdateAccountByID(ctx, accountDescr.ID, accountDescr) + if err != nil { + return res, err + } + return res, err +} diff --git a/app/accoper/updgrant.go b/app/accoper/updgrant.go new file mode 100644 index 0000000..d66c857 --- /dev/null +++ b/app/accoper/updgrant.go @@ -0,0 +1,52 @@ +package accoper + +import ( + "context" + "fmt" + + "mstore/pkg/auxtool" + "mstore/pkg/descr" +) + +// UpdateGrant +type UpdateGrantParams struct { + GrantID string + NewPattern string +} +type UpdateGrantResult struct{} + +func (oper *Operator) UpdateGrant(ctx context.Context, operatorID string, params *UpdateGrantParams) (*UpdateGrantResult, error) { + var err error + res := &UpdateGrantResult{} + + if params.NewPattern == "" { + err := fmt.Errorf("Empty newPattern parameter") + return res, err + } + if params.GrantID == "" { + err := fmt.Errorf("Empty grantId parameter") + return res, err + } + var grantDescr *descr.Grant + var grantExists bool + + grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) + if err != nil { + return res, err + } + if !grantExists { + err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) + return res, err + } + now := auxtool.TimeNow() + if params.NewPattern != "" { + grantDescr.UpdatedAt = now + grantDescr.UpdatedBy = operatorID + grantDescr.Pattern = params.NewPattern + } + err = oper.mdb.UpdateGrantByID(ctx, grantDescr.ID, grantDescr) + if err != nil { + return res, err + } + return res, err +} diff --git a/app/config/variant.go b/app/config/variant.go new file mode 100644 index 0000000..6cf7189 --- /dev/null +++ b/app/config/variant.go @@ -0,0 +1,10 @@ +package config + +const ( + confdir = "/home/ziggi/Projects/mstore/etc/mstore" + rundir = "/home/ziggi/Projects/mstore/tmp/run" + logdir = "/home/ziggi/Projects/mstore/tmp/log" + datadir = "/home/ziggi/Projects/mstore/tmp/data" + version = "0.2.0" + srvname = "mstored" +) diff --git a/app/operator/fileop_delcats.go b/app/fileoper/delcats.go similarity index 96% rename from app/operator/fileop_delcats.go rename to app/fileoper/delcats.go index b2931fe..4ded91c 100644 --- a/app/operator/fileop_delcats.go +++ b/app/fileoper/delcats.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -17,7 +17,6 @@ import ( "mstore/pkg/filecli" ) - // DeleteColletion type DeleteColletionParams struct { Path string @@ -100,7 +99,7 @@ func (oper *Operator) deleteFilesInCollection(ctx context.Context, collection st } for _, file := range files { if !dryRun { - oper.logg.Debugf("Delete file %s/%s", file.Collection, file.Name) + oper.logg.Debugf("Delete file %s/%s", file.Collection, file.Name) err = oper.store.DeleteFile(file.Collection, file.Name) if err != nil { oper.logg.Warningf("%v", err) @@ -116,5 +115,3 @@ func (oper *Operator) deleteFilesInCollection(ctx context.Context, collection st } return res, err } - - diff --git a/app/operator/fileop_delfile.go b/app/fileoper/delfile.go similarity index 98% rename from app/operator/fileop_delfile.go rename to app/fileoper/delfile.go index a317300..906316a 100644 --- a/app/operator/fileop_delfile.go +++ b/app/fileoper/delfile.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -15,7 +15,6 @@ import ( "path" ) - // DeleteFile type DeleteFileParams struct { Filepath string diff --git a/app/operator/fileop_fileinfo.go b/app/fileoper/fileinfo.go similarity index 99% rename from app/operator/fileop_fileinfo.go rename to app/fileoper/fileinfo.go index 9421d25..b54baf0 100644 --- a/app/operator/fileop_fileinfo.go +++ b/app/fileoper/fileinfo.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -81,4 +81,3 @@ func (oper *Operator) FileInfo(ctx context.Context, operatorID string, params *F } return code, res, err } - diff --git a/app/operator/fileop_getfile.go b/app/fileoper/getfile.go similarity index 99% rename from app/operator/fileop_getfile.go rename to app/fileoper/getfile.go index 18ed602..9bb9414 100644 --- a/app/operator/fileop_getfile.go +++ b/app/fileoper/getfile.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -77,4 +77,3 @@ func (oper *Operator) GetFile(ctx context.Context, operatorID string, params *Ge code := http.StatusOK return code, res, err } - diff --git a/app/operator/fileop_listcats.go b/app/fileoper/listcats.go similarity index 99% rename from app/operator/fileop_listcats.go rename to app/fileoper/listcats.go index 14831c8..02074d2 100644 --- a/app/operator/fileop_listcats.go +++ b/app/fileoper/listcats.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -150,4 +150,3 @@ func (oper *Operator) listAllCollections(ctx context.Context) ([]string, error) slices.Sort(res) return res, err } - diff --git a/app/operator/fileop_listfiles.go b/app/fileoper/listfiles.go similarity index 99% rename from app/operator/fileop_listfiles.go rename to app/fileoper/listfiles.go index e0f28ae..b05b391 100644 --- a/app/operator/fileop_listfiles.go +++ b/app/fileoper/listfiles.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" diff --git a/app/fileoper/operator.go b/app/fileoper/operator.go new file mode 100644 index 0000000..236586c --- /dev/null +++ b/app/fileoper/operator.go @@ -0,0 +1,42 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package fileoper + +import ( + "mstore/app/locker" + "mstore/app/logger" + "mstore/app/maindb" + "mstore/app/storage" +) + +type OperatorParams struct { + MainDB *maindb.Database + Store *storage.Storage +} + +type Operator struct { + mdb *maindb.Database + store *storage.Storage + logg *logger.Logger + iLock *locker.Locker + fLock *locker.Locker +} + +func NewOperator(params *OperatorParams) (*Operator, error) { + var err error + oper := &Operator{ + mdb: params.MainDB, + store: params.Store, + } + oper.iLock = locker.NewLocker() + oper.fLock = locker.NewLocker() + oper.logg = logger.NewLoggerWithSubject("fileoper") + return oper, err +} diff --git a/app/operator/fileop_putfile.go b/app/fileoper/putfile.go similarity index 99% rename from app/operator/fileop_putfile.go rename to app/fileoper/putfile.go index 552e29c..9d5cff2 100644 --- a/app/operator/fileop_putfile.go +++ b/app/fileoper/putfile.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package fileoper import ( "context" @@ -118,4 +118,3 @@ func (oper *Operator) PutFile(ctx context.Context, operatorID string, params *Pu code := http.StatusOK return code, res, err } - diff --git a/app/handler/aaafunc.go b/app/handler/aaafunc.go index 0d2a6f9..c3bff77 100644 --- a/app/handler/aaafunc.go +++ b/app/handler/aaafunc.go @@ -52,9 +52,9 @@ func (hand *Handler) CheckAccess(rctx *router.Context) (bool, string, error) { accountID = terms.AnonymousID - hand.logg.Debugf("URL: %s", rctx.URL().String()) + hand.logg.Debugf("URL: %s", rctx.URL().String()) authHeader := rctx.GetHeader("Authorization") - hand.logg.Debugf("Authorization: %s", authHeader) + hand.logg.Debugf("Authorization: %s", authHeader) if authHeader != "" { username, password, err = auxhttp.ParseBasicAuth(authHeader) if err != nil { diff --git a/app/handler/account.go b/app/handler/account.go index 9f2e6a3..73e72e2 100644 --- a/app/handler/account.go +++ b/app/handler/account.go @@ -12,7 +12,7 @@ package handler import ( "fmt" - "mstore/app/operator" + "mstore/app/accoper" "mstore/app/router" "mstore/pkg/terms" ) @@ -21,7 +21,7 @@ import ( func (hand *Handler) CreateAccount(rctx *router.Context) { var err error - params := &operator.CreateAccountParams{} + params := &accoper.CreateAccountParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -41,7 +41,7 @@ func (hand *Handler) CreateAccount(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.CreateAccount(rctx.Ctx, operatorID, params) + res, err := hand.acop.CreateAccount(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("Operation error: %v", err) hand.SendError(rctx, err) @@ -54,7 +54,7 @@ func (hand *Handler) CreateAccount(rctx *router.Context) { func (hand *Handler) GetAccount(rctx *router.Context) { var err error - params := &operator.GetAccountParams{} + params := &accoper.GetAccountParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -74,7 +74,7 @@ func (hand *Handler) GetAccount(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.GetAccount(rctx.Ctx, operatorID, params) + res, err := hand.acop.GetAccount(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("Operation error: %v", err) hand.SendError(rctx, err) @@ -87,7 +87,7 @@ func (hand *Handler) GetAccount(rctx *router.Context) { func (hand *Handler) ListAccounts(rctx *router.Context) { var err error - params := &operator.ListAccountsParams{} + params := &accoper.ListAccountsParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -107,7 +107,7 @@ func (hand *Handler) ListAccounts(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.ListAccounts(rctx.Ctx, params) + res, err := hand.acop.ListAccounts(rctx.Ctx, params) if err != nil { hand.logg.Errorf("ListAccounts error: %v", err) hand.SendError(rctx, err) @@ -120,7 +120,7 @@ func (hand *Handler) ListAccounts(rctx *router.Context) { func (hand *Handler) UpdateAccount(rctx *router.Context) { var err error - params := &operator.UpdateAccountParams{} + params := &accoper.UpdateAccountParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -140,7 +140,7 @@ func (hand *Handler) UpdateAccount(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.UpdateAccount(rctx.Ctx, operatorID, params) + res, err := hand.acop.UpdateAccount(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("UpdateAccount error: %v", err) hand.SendError(rctx, err) @@ -153,7 +153,7 @@ func (hand *Handler) UpdateAccount(rctx *router.Context) { func (hand *Handler) DeleteAccount(rctx *router.Context) { var err error - params := &operator.DeleteAccountParams{} + params := &accoper.DeleteAccountParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -173,7 +173,7 @@ func (hand *Handler) DeleteAccount(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.DeleteAccount(rctx.Ctx, operatorID, params) + res, err := hand.acop.DeleteAccount(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteAccount error: %v", err) hand.SendError(rctx, err) diff --git a/app/handler/blob.go b/app/handler/blob.go index 1972514..cd89b66 100644 --- a/app/handler/blob.go +++ b/app/handler/blob.go @@ -14,7 +14,7 @@ import ( "io" "net/http" - "mstore/app/operator" + "mstore/app/imageoper" "mstore/app/router" "mstore/pkg/terms" ) @@ -26,7 +26,7 @@ func (hand *Handler) BlobExists(rctx *router.Context) { //hand.DumpHeaders("BlobExists", rctx) - params := &operator.BlobExistsParams{ + params := &imageoper.BlobExistsParams{ Name: name, Digest: digest, } @@ -43,7 +43,7 @@ func (hand *Handler) BlobExists(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.BlobExists(ctx, operatorID, params) + res, code, err := hand.imop.BlobExists(ctx, operatorID, params) if err != nil { hand.logg.Errorf("BlobExist error: %v", err) } @@ -75,7 +75,7 @@ func (hand *Handler) PostUpload(rctx *router.Context) { mount := rctx.GetQuery("mount") from := rctx.GetQuery("from") - params := &operator.PostUploadParams{ + params := &imageoper.PostUploadParams{ Name: name, Digest: digest, Mount: mount, @@ -93,7 +93,7 @@ func (hand *Handler) PostUpload(rctx *router.Context) { return } // Execution of the operation - res, code, err := hand.oper.PostUpload(rctx.Ctx, operatorID, params) + res, code, err := hand.imop.PostUpload(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("PostUpload error: %v", err) } else { @@ -104,8 +104,6 @@ func (hand *Handler) PostUpload(rctx *router.Context) { rctx.SetStatus(code) } - - // PATCH /v2//blobs/uploads/ 202 404/416 func (hand *Handler) PatchUpload(rctx *router.Context) { @@ -117,7 +115,7 @@ func (hand *Handler) PatchUpload(rctx *router.Context) { reference, _ := rctx.GetSubpath("reference") reader := rctx.Request.Body - params := &operator.PatchUploadParams{ + params := &imageoper.PatchUploadParams{ ContentLength: contentLength, ContentType: contentType, ContentRange: contentRange, @@ -138,7 +136,7 @@ func (hand *Handler) PatchUpload(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.PatchUpload(ctx, operatorID, params) + res, code, err := hand.imop.PatchUpload(ctx, operatorID, params) if err != nil { hand.logg.Errorf("PatchUpload error: %v", err) } @@ -162,7 +160,7 @@ func (hand *Handler) PutUpload(rctx *router.Context) { digest := rctx.GetQuery("digest") reader := rctx.Request.Body - params := &operator.PutUploadParams{ + params := &imageoper.PutUploadParams{ ContentLength: contentLength, ContentType: contentType, ContentRange: contentRange, @@ -183,7 +181,7 @@ func (hand *Handler) PutUpload(rctx *router.Context) { return } // Execution of the operation - res, code, err := hand.oper.PutUpload(rctx.Ctx, operatorID, params) + res, code, err := hand.imop.PutUpload(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("PutUpload error: %v", err) } @@ -197,7 +195,7 @@ func (hand *Handler) GetBlob(rctx *router.Context) { name, _ := rctx.GetSubpath("name") digest, _ := rctx.GetSubpath("digest") - params := &operator.GetBlobParams{ + params := &imageoper.GetBlobParams{ Name: name, Digest: digest, } @@ -214,7 +212,7 @@ func (hand *Handler) GetBlob(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.GetBlob(ctx, operatorID, params) + res, code, err := hand.imop.GetBlob(ctx, operatorID, params) if err != nil { hand.logg.Errorf("GetBlob error: %v", err) } @@ -243,7 +241,7 @@ func (hand *Handler) DeleteBlob(rctx *router.Context) { name, _ := rctx.GetSubpath("name") digest, _ := rctx.GetSubpath("digest") - params := &operator.DeleteBlobParams{ + params := &imageoper.DeleteBlobParams{ Name: name, Digest: digest, } @@ -260,7 +258,7 @@ func (hand *Handler) DeleteBlob(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - _, code, err := hand.oper.DeleteBlob(ctx, operatorID, params) + _, code, err := hand.imop.DeleteBlob(ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteBlob error: %v", err) } diff --git a/app/handler/file.go b/app/handler/file.go index 2430145..ec1c651 100644 --- a/app/handler/file.go +++ b/app/handler/file.go @@ -13,7 +13,7 @@ import ( "io" "net/http" - "mstore/app/operator" + "mstore/app/fileoper" "mstore/app/router" "mstore/pkg/terms" ) @@ -23,7 +23,7 @@ const zeroContentLength = "0" func (hand *Handler) FileInfo(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") - params := &operator.FileInfoParams{ + params := &fileoper.FileInfoParams{ Filepath: filepath, } // Rigth checking @@ -39,7 +39,7 @@ func (hand *Handler) FileInfo(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, res, err := hand.oper.FileInfo(ctx, operatorID, params) + code, res, err := hand.fiop.FileInfo(ctx, operatorID, params) if err != nil { hand.logg.Errorf("FileInfo error: %v", err) rctx.SetStatus(code) @@ -65,7 +65,7 @@ func (hand *Handler) PutFile(rctx *router.Context) { contentType := rctx.GetHeader("Content-Type") filepath, _ := rctx.GetSubpath("filepath") - params := &operator.PutFileParams{ + params := &fileoper.PutFileParams{ Filepath: filepath, ContentType: contentType, ContentSize: contentSize, @@ -84,7 +84,7 @@ func (hand *Handler) PutFile(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, _, err := hand.oper.PutFile(ctx, operatorID, params) + code, _, err := hand.fiop.PutFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) @@ -96,7 +96,7 @@ func (hand *Handler) PutFile(rctx *router.Context) { func (hand *Handler) GetFile(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") - params := &operator.GetFileParams{ + params := &fileoper.GetFileParams{ Filepath: filepath, } // Rigth checking @@ -112,7 +112,7 @@ func (hand *Handler) GetFile(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, res, err := hand.oper.GetFile(ctx, operatorID, params) + code, res, err := hand.fiop.GetFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) @@ -144,7 +144,7 @@ func (hand *Handler) GetFile(rctx *router.Context) { func (hand *Handler) DeleteFile(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") - params := &operator.DeleteFileParams{ + params := &fileoper.DeleteFileParams{ Filepath: filepath, } // Rigth checking @@ -160,7 +160,7 @@ func (hand *Handler) DeleteFile(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, _, err := hand.oper.DeleteFile(ctx, operatorID, params) + code, _, err := hand.fiop.DeleteFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteFIle error: %v", err) } @@ -174,7 +174,7 @@ func (hand *Handler) ListFiles(rctx *router.Context) { if filepath == "" { filepath = "/" } - params := &operator.ListFilesParams{ + params := &fileoper.ListFilesParams{ Filepath: filepath, } err := rctx.BindQuery(params) @@ -197,7 +197,7 @@ func (hand *Handler) ListFiles(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, res, err := hand.oper.ListFiles(ctx, operatorID, params) + code, res, err := hand.fiop.ListFiles(ctx, operatorID, params) if err != nil { hand.logg.Errorf("ListFiles error: %v", err) rctx.SetStatus(code) @@ -212,7 +212,7 @@ func (hand *Handler) ListCollections(rctx *router.Context) { if cpath == "" { cpath = "/" } - params := &operator.ListCollectionsParams{ + params := &fileoper.ListCollectionsParams{ Path: cpath, } err := rctx.BindQuery(params) @@ -234,7 +234,7 @@ func (hand *Handler) ListCollections(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, res, err := hand.oper.ListCollections(ctx, operatorID, params) + code, res, err := hand.fiop.ListCollections(ctx, operatorID, params) if err != nil { hand.logg.Errorf("ListCollections error: %v", err) rctx.SetStatus(code) @@ -249,7 +249,7 @@ func (hand *Handler) DeleteCollection(rctx *router.Context) { if cpath == "" { cpath = "/" } - params := &operator.DeleteColletionParams{ + params := &fileoper.DeleteColletionParams{ Path: cpath, } err := rctx.BindQuery(params) @@ -272,7 +272,7 @@ func (hand *Handler) DeleteCollection(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - code, res, err := hand.oper.DeleteColletion(ctx, operatorID, params) + code, res, err := hand.fiop.DeleteColletion(ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteColletion error: %v", err) rctx.SetStatus(code) diff --git a/app/handler/grant.go b/app/handler/grant.go index 7445c0a..cdf8f36 100644 --- a/app/handler/grant.go +++ b/app/handler/grant.go @@ -12,7 +12,7 @@ package handler import ( "fmt" - "mstore/app/operator" + "mstore/app/accoper" "mstore/app/router" "mstore/pkg/terms" ) @@ -21,7 +21,7 @@ import ( func (hand *Handler) CreateGrant(rctx *router.Context) { var err error - params := &operator.CreateGrantParams{} + params := &accoper.CreateGrantParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -41,7 +41,7 @@ func (hand *Handler) CreateGrant(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.CreateGrant(rctx.Ctx, operatorID, params) + res, err := hand.acop.CreateGrant(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("CreateGrant error: %v", err) hand.SendError(rctx, err) @@ -54,7 +54,7 @@ func (hand *Handler) CreateGrant(rctx *router.Context) { func (hand *Handler) GetGrant(rctx *router.Context) { var err error - params := &operator.GetGrantParams{} + params := &accoper.GetGrantParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -74,7 +74,7 @@ func (hand *Handler) GetGrant(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.GetGrant(rctx.Ctx, operatorID, params) + res, err := hand.acop.GetGrant(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("CreateGrant error: %v", err) hand.SendError(rctx, err) @@ -87,7 +87,7 @@ func (hand *Handler) GetGrant(rctx *router.Context) { func (hand *Handler) ListGrants(rctx *router.Context) { var err error - params := &operator.ListGrantsParams{} + params := &accoper.ListGrantsParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -107,7 +107,7 @@ func (hand *Handler) ListGrants(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.ListGrants(rctx.Ctx, operatorID, params) + res, err := hand.acop.ListGrants(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("ListGrants error: %v", err) hand.SendError(rctx, err) @@ -120,7 +120,7 @@ func (hand *Handler) ListGrants(rctx *router.Context) { func (hand *Handler) UpdateGrant(rctx *router.Context) { var err error - params := &operator.UpdateGrantParams{} + params := &accoper.UpdateGrantParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -140,7 +140,7 @@ func (hand *Handler) UpdateGrant(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.UpdateGrant(rctx.Ctx, operatorID, params) + res, err := hand.acop.UpdateGrant(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("UpdateGrant error: %v", err) hand.SendError(rctx, err) @@ -153,7 +153,7 @@ func (hand *Handler) UpdateGrant(rctx *router.Context) { func (hand *Handler) DeleteGrant(rctx *router.Context) { var err error - params := &operator.DeleteGrantParams{} + params := &accoper.DeleteGrantParams{} err = rctx.BindJSON(params) if err != nil { hand.SendError(rctx, err) @@ -173,7 +173,7 @@ func (hand *Handler) DeleteGrant(rctx *router.Context) { return } // Execution of the operation - res, err := hand.oper.DeleteGrant(rctx.Ctx, operatorID, params) + res, err := hand.acop.DeleteGrant(rctx.Ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteGrant error: %v", err) hand.SendError(rctx, err) diff --git a/app/handler/handler.go b/app/handler/handler.go index aab7435..cc80470 100644 --- a/app/handler/handler.go +++ b/app/handler/handler.go @@ -12,28 +12,38 @@ package handler import ( "mstore/app/logger" "mstore/app/maindb" - "mstore/app/operator" "mstore/app/router" + "mstore/app/accoper" + "mstore/app/fileoper" + "mstore/app/imageoper" + yaml "go.yaml.in/yaml/v4" ) type HandlerParams struct { - Operator *operator.Operator - MainDB *maindb.Database + MainDB *maindb.Database + FileOper *fileoper.Operator + AccOper *accoper.Operator + ImageOper *imageoper.Operator } type Handler struct { - oper *operator.Operator mdb *maindb.Database logg *logger.Logger + + fiop *fileoper.Operator + acop *accoper.Operator + imop *imageoper.Operator } func NewHandler(params *HandlerParams) (*Handler, error) { var err error hand := &Handler{ - oper: params.Operator, mdb: params.MainDB, + fiop: params.FileOper, + acop: params.AccOper, + imop: params.ImageOper, } hand.logg = logger.NewLoggerWithSubject("handler") return hand, err diff --git a/app/handler/manifest.go b/app/handler/manifest.go index 0117f95..6b34f0d 100644 --- a/app/handler/manifest.go +++ b/app/handler/manifest.go @@ -12,7 +12,7 @@ package handler import ( "net/http" - "mstore/app/operator" + "mstore/app/imageoper" "mstore/app/router" "mstore/pkg/terms" ) @@ -23,7 +23,7 @@ func (hand *Handler) ManifestExists(rctx *router.Context) { //hand.DumpHeaders("ManigestExists:\n", rctx) - params := &operator.ManifestExistsParams{ + params := &imageoper.ManifestExistsParams{ Name: name, Reference: reference, } @@ -40,7 +40,7 @@ func (hand *Handler) ManifestExists(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.ManifestExists(ctx, params) + res, code, err := hand.imop.ManifestExists(ctx, params) if err != nil { hand.logg.Errorf("ManifestExist error: %v", err) } else if code == http.StatusOK { @@ -62,7 +62,7 @@ func (hand *Handler) PutManifest(rctx *router.Context) { name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") - params := &operator.PutManifestParams{ + params := &imageoper.PutManifestParams{ ContentType: contentType, ContentLength: contentLength, Name: name, @@ -82,7 +82,7 @@ func (hand *Handler) PutManifest(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.PutManifest(ctx, params) + res, code, err := hand.imop.PutManifest(ctx, params) if err != nil { hand.logg.Errorf("PutManifest error: %v", err) } else { @@ -98,7 +98,7 @@ func (hand *Handler) GetManifest(rctx *router.Context) { //hand.DumpHeaders("GetManigest", rctx) - params := &operator.GetManifestParams{ + params := &imageoper.GetManifestParams{ Name: name, Reference: reference, } @@ -115,7 +115,7 @@ func (hand *Handler) GetManifest(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.GetManifest(ctx, params) + res, code, err := hand.imop.GetManifest(ctx, params) if err != nil { hand.logg.Errorf("GetManifest error: %v", err) rctx.SetStatus(code) @@ -138,7 +138,7 @@ func (hand *Handler) DeleteManifest(rctx *router.Context) { name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") - params := &operator.DeleteManifestParams{ + params := &imageoper.DeleteManifestParams{ Name: name, Reference: reference, } @@ -155,7 +155,7 @@ func (hand *Handler) DeleteManifest(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - _, code, err := hand.oper.DeleteManifest(ctx, params) + _, code, err := hand.imop.DeleteManifest(ctx, params) if err != nil { hand.logg.Errorf("DeleteManifest error: %v", err) } @@ -167,7 +167,7 @@ func (hand *Handler) DeleteManifest(rctx *router.Context) { func (hand *Handler) GetReferer(rctx *router.Context) { name, _ := rctx.GetSubpath("name") digest, _ := rctx.GetSubpath("digest") - params := &operator.GetRefererParams{ + params := &imageoper.GetRefererParams{ Name: name, Digest: digest, } @@ -183,7 +183,7 @@ func (hand *Handler) GetReferer(rctx *router.Context) { return } // Execution of the operation - res, code, err := hand.oper.GetReferer(rctx.Ctx, params) + res, code, err := hand.imop.GetReferer(rctx.Ctx, params) if err != nil { hand.logg.Errorf("GetReferer error: %v", err) } @@ -194,7 +194,7 @@ func (hand *Handler) GetReferer(rctx *router.Context) { // GET /v2//tags/list?n=&last= func (hand *Handler) GetTags(rctx *router.Context) { name, _ := rctx.GetSubpath("name") - params := &operator.GetTagsParams{ + params := &imageoper.GetTagsParams{ Name: name, } // Rigth checking @@ -210,7 +210,7 @@ func (hand *Handler) GetTags(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.GetTags(ctx, params) + res, code, err := hand.imop.GetTags(ctx, params) if err != nil { hand.logg.Errorf("GetTags error: %v", err) } @@ -219,7 +219,7 @@ func (hand *Handler) GetTags(rctx *router.Context) { // GET /v2/_catalog?n=1000 200 404 func (hand *Handler) ListManifests(rctx *router.Context) { - params := &operator.ListManifestsParams{} + params := &imageoper.ListManifestsParams{} // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadImages, "_catalog") @@ -233,7 +233,7 @@ func (hand *Handler) ListManifests(rctx *router.Context) { } // Execution of the operation ctx := rctx.GetContext() - res, code, err := hand.oper.ListManifests(ctx, params) + res, code, err := hand.imop.ListManifests(ctx, params) if err != nil { hand.logg.Errorf("ListManifests error: %v", err) } diff --git a/app/handler/service.go b/app/handler/service.go index 5cbf222..2f41a08 100644 --- a/app/handler/service.go +++ b/app/handler/service.go @@ -10,12 +10,12 @@ package handler import ( - "mstore/app/operator" + "mstore/app/imageoper" "mstore/app/router" ) func (hand *Handler) SendHello(rctx *router.Context) { - params := &operator.SendHelloParams{} - res, _ := hand.oper.SendHello(params) + params := &imageoper.SendHelloParams{} + res, _ := hand.imop.SendHello(params) hand.SendResult(rctx, res) } diff --git a/app/handler/version.go b/app/handler/version.go index ae7ec78..429901a 100644 --- a/app/handler/version.go +++ b/app/handler/version.go @@ -12,13 +12,13 @@ package handler import ( "net/http" - "mstore/app/operator" + "mstore/app/imageoper" "mstore/app/router" ) // GET /v2/ 200 404/401 func (hand *Handler) GetVersion(rctx *router.Context) { - params := &operator.GetVersionParams{} + params := &imageoper.GetVersionParams{} //hand.DumpHeaders("GetVersion", rctx) authorization := rctx.GetHeader("Authorization") @@ -28,7 +28,7 @@ func (hand *Handler) GetVersion(rctx *router.Context) { return } ctx := rctx.GetContext() - _, code, err := hand.oper.GetVersion(ctx, params) + _, code, err := hand.imop.GetVersion(ctx, params) if err != nil { hand.logg.Errorf("GetVersion error: %v", err) } diff --git a/app/operator/blob.go b/app/imageoper/blob.go similarity index 99% rename from app/operator/blob.go rename to app/imageoper/blob.go index 1db3cb3..3e59ba0 100644 --- a/app/operator/blob.go +++ b/app/imageoper/blob.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper import ( "context" diff --git a/app/operator/imgaux.go b/app/imageoper/imgaux.go similarity index 98% rename from app/operator/imgaux.go rename to app/imageoper/imgaux.go index de760a9..b9070f0 100644 --- a/app/operator/imgaux.go +++ b/app/imageoper/imgaux.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper import ( "encoding/hex" diff --git a/app/operator/manifest.go b/app/imageoper/manifest.go similarity index 99% rename from app/operator/manifest.go rename to app/imageoper/manifest.go index c9683c8..5a788a9 100644 --- a/app/operator/manifest.go +++ b/app/imageoper/manifest.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper import ( "bytes" diff --git a/app/operator/ociaux.go b/app/imageoper/ociaux.go similarity index 99% rename from app/operator/ociaux.go rename to app/imageoper/ociaux.go index 3edd8e0..c5c9c14 100644 --- a/app/operator/ociaux.go +++ b/app/imageoper/ociaux.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper import ( "encoding/json" diff --git a/app/imageoper/operator.go b/app/imageoper/operator.go new file mode 100644 index 0000000..f45606b --- /dev/null +++ b/app/imageoper/operator.go @@ -0,0 +1,42 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package imageoper + +import ( + "mstore/app/locker" + "mstore/app/logger" + "mstore/app/maindb" + "mstore/app/storage" +) + +type OperatorParams struct { + MainDB *maindb.Database + Store *storage.Storage +} + +type Operator struct { + mdb *maindb.Database + store *storage.Storage + logg *logger.Logger + iLock *locker.Locker + fLock *locker.Locker +} + +func NewOperator(params *OperatorParams) (*Operator, error) { + var err error + oper := &Operator{ + mdb: params.MainDB, + store: params.Store, + } + oper.iLock = locker.NewLocker() + oper.fLock = locker.NewLocker() + oper.logg = logger.NewLoggerWithSubject("imageoper") + return oper, err +} diff --git a/app/operator/service.go b/app/imageoper/service.go similarity index 96% rename from app/operator/service.go rename to app/imageoper/service.go index f791edb..7a183ee 100644 --- a/app/operator/service.go +++ b/app/imageoper/service.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper type SendHelloParams struct{} diff --git a/app/operator/version.go b/app/imageoper/version.go similarity index 97% rename from app/operator/version.go rename to app/imageoper/version.go index f2b9e75..6695548 100644 --- a/app/operator/version.go +++ b/app/imageoper/version.go @@ -7,7 +7,7 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package operator +package imageoper import ( "context" diff --git a/app/operator/account.go b/app/operator/account.go deleted file mode 100644 index 71af671..0000000 --- a/app/operator/account.go +++ /dev/null @@ -1,284 +0,0 @@ -package operator - -import ( - "context" - "fmt" - - "mstore/pkg/auxpwd" - "mstore/pkg/auxtool" - "mstore/pkg/auxuuid" - "mstore/pkg/descr" -) - -type CreateAccountParams struct { - Username string `json:"username"` - Password string `json:"password"` -} -type CreateAccountResult struct { - AccountID string `json:"accountId"` -} - -func (oper *Operator) CreateAccount(ctx context.Context, operatorID string, params *CreateAccountParams) (*CreateAccountResult, error) { - var err error - res := &CreateAccountResult{} - - if params.Username == "" { - err := fmt.Errorf("Empty username parameters") - return res, err - } - - if params.Password == "" { - err := fmt.Errorf("Empty password parameter") - return res, err - } - - accountExists, _, err := oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if accountExists { - err := fmt.Errorf("Account with thist name already exists") - return res, err - } - now := auxtool.TimeNow() - passhash := auxpwd.MakeSHA256Hash([]byte(params.Password)) - accountDescr := &descr.Account{ - ID: auxuuid.NewUUID(), - Username: params.Username, - Passhash: passhash, - Disabled: false, - CreatedAt: now, - UpdatedAt: now, - CreatedBy: operatorID, - UpdatedBy: operatorID, - } - err = oper.mdb.InsertAccount(ctx, accountDescr) - if err != nil { - return res, err - } - res.AccountID = accountDescr.ID - return res, err -} - -// GetAccount -type GetAccountParams struct { - Username string `json:"username"` - AccountID string `json:"accountId"` -} -type GetAccountResult struct { - Account *descr.AccountShort `json:"account"` -} - -func (oper *Operator) GetAccount(ctx context.Context, operatorID string, params *GetAccountParams) (*GetAccountResult, error) { - var err error - res := &GetAccountResult{} - - if params.Username == "" && params.AccountID == "" { - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - - var accountDescr *descr.Account - var accountExists bool - switch { - case params.AccountID != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) - return res, err - } - case params.Username != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with name %s dont exists", params.Username) - return res, err - } - default: - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - if accountDescr == nil { - err := fmt.Errorf("Null account desriptor") - return res, err - } - accountShort := &descr.AccountShort{ - ID: accountDescr.ID, - Username: accountDescr.Username, - CreatedAt: accountDescr.CreatedAt, - UpdatedAt: accountDescr.UpdatedAt, - CreatedBy: accountDescr.CreatedBy, - UpdatedBy: accountDescr.UpdatedBy, - Disabled: accountDescr.Disabled, - Grants: make([]descr.Grant, 0), - } - grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID) - if err != nil { - return res, err - } - accountShort.Grants = grantDescrs - - res.Account = accountShort - return res, err -} - -type UpdateAccountParams struct { - Username string `json:"username"` - AccountID string `json:"accountId"` - NewUsername string `json:"newUsername"` - NewPassword string `json:"newPassword"` - Disabled bool `json:"disabled"` -} -type UpdateAccountResult struct{} - -func (oper *Operator) UpdateAccount(ctx context.Context, operatorID string, params *UpdateAccountParams) (*UpdateAccountResult, error) { - var err error - res := &UpdateAccountResult{} - if params.Username == "" && params.AccountID == "" { - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - var accountDescr *descr.Account - var accountExists bool - switch { - case params.AccountID != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) - return res, err - } - case params.Username != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with name %s dont exists", params.Username) - return res, err - } - default: - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - if accountDescr == nil { - err := fmt.Errorf("Null account desriptor") - return res, err - } - now := auxtool.TimeNow() - if params.NewUsername != "" { - accountDescr.UpdatedAt = now - accountDescr.Username = params.NewUsername - } - if params.NewPassword != "" { - accountDescr.UpdatedAt = now - passhash := auxpwd.MakeSHA256Hash([]byte(params.NewPassword)) - accountDescr.Passhash = passhash - } - if params.Disabled != accountDescr.Disabled { - accountDescr.UpdatedAt = now - accountDescr.Disabled = params.Disabled - } - - err = oper.mdb.UpdateAccountByID(ctx, accountDescr.ID, accountDescr) - if err != nil { - return res, err - } - return res, err -} - -type DeleteAccountParams struct { - Username string `json:"username"` - AccountID string `json:"accountId"` -} -type DeleteAccountResult struct{} - -func (oper *Operator) DeleteAccount(ctx context.Context, operatorID string, params *DeleteAccountParams) (*DeleteAccountResult, error) { - var err error - res := &DeleteAccountResult{} - - if params.Username == "" && params.AccountID == "" { - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - - var accountDescr *descr.Account - var accountExists bool - switch { - case params.AccountID != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) - return res, err - } - case params.Username != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with name %s dont exists", params.Username) - return res, err - } - default: - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - if accountDescr == nil { - err := fmt.Errorf("Null account desriptor") - return res, err - } - err = oper.mdb.DeleteAllGrantsForAccountID(ctx, accountDescr.ID) - if err != nil { - return res, err - } - err = oper.mdb.DeleteAccountByID(ctx, accountDescr.ID) - if err != nil { - return res, err - } - return res, err -} - -type ListAccountsParams struct{} -type ListAccountsResult struct { - Accounts []descr.AccountShort `json:"accounts"` -} - -func (oper *Operator) ListAccounts(ctx context.Context, params *ListAccountsParams) (*ListAccountsResult, error) { - var err error - res := &ListAccountsResult{} - - accountDescrs, err := oper.mdb.ReducedListAccounts(ctx) - if err != nil { - return res, err - } - for _, accountDescr := range accountDescrs { - accountShort := descr.AccountShort{ - ID: accountDescr.ID, - Username: accountDescr.Username, - Disabled: accountDescr.Disabled, - CreatedAt: accountDescr.CreatedAt, - UpdatedAt: accountDescr.UpdatedAt, - CreatedBy: accountDescr.CreatedBy, - UpdatedBy: accountDescr.UpdatedBy, - Grants: make([]descr.Grant, 0), - } - grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID) - if err != nil { - return res, err - } - accountShort.Grants = grantDescrs - res.Accounts = append(res.Accounts, accountShort) - } - return res, err -} diff --git a/app/operator/grant.go b/app/operator/grant.go deleted file mode 100644 index e8b1188..0000000 --- a/app/operator/grant.go +++ /dev/null @@ -1,254 +0,0 @@ -package operator - -import ( - "context" - "fmt" - "regexp" - - "mstore/pkg/auxtool" - "mstore/pkg/auxuuid" - "mstore/pkg/descr" -) - -// CreateGrant -type CreateGrantParams struct { - AccountID string `json:"accountID"` - Username string `json:"username"` - Right string `json:"operation"` - Pattern string `json:"pattern"` -} -type CreateGrantResult struct { - GrantID string `json:"grantId"` -} - -func (oper *Operator) CreateGrant(ctx context.Context, operatorID string, params *CreateGrantParams) (*CreateGrantResult, error) { - var err error - res := &CreateGrantResult{} - - if params.AccountID == "" { - err := fmt.Errorf("Empty accountId parameters") - return res, err - } - if params.Right == "" { - err := fmt.Errorf("Empty operation parameter") - return res, err - } - if params.Pattern == "" { - err := fmt.Errorf("Empty pattern parameter") - return res, err - } - - _, err = regexp.Compile(params.Pattern) - if err != nil { - err := fmt.Errorf("Cannot compile regexp %s: %v", err) - return res, err - } - - var accountDescr *descr.Account - var accountExists bool - switch { - case params.AccountID != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) - return res, err - } - case params.Username != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with name %s dont exists", params.Username) - return res, err - } - default: - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - grantExists, _, err := oper.mdb.GetGrantByAccoundIDRightPattern(ctx, params.AccountID, params.Right, params.Pattern) - if err != nil { - return res, err - } - if grantExists { - err := fmt.Errorf("Grant with this right already exists") - return res, err - } - oper.logg.Debugf("Call CreateGrant") - now := auxtool.TimeNow() - grantDescr := &descr.Grant{ - ID: auxuuid.NewUUID(), - AccountID: accountDescr.ID, - Right: params.Right, - Pattern: params.Pattern, - CreatedAt: now, - UpdatedAt: now, - CreatedBy: operatorID, - UpdatedBy: operatorID, - } - err = oper.mdb.InsertGrant(ctx, grantDescr) - if err != nil { - return res, err - } - res.GrantID = grantDescr.ID - return res, err -} - -// UpdateGrant -type UpdateGrantParams struct { - GrantID string - NewPattern string -} -type UpdateGrantResult struct{} - -func (oper *Operator) UpdateGrant(ctx context.Context, operatorID string, params *UpdateGrantParams) (*UpdateGrantResult, error) { - var err error - res := &UpdateGrantResult{} - - if params.NewPattern == "" { - err := fmt.Errorf("Empty newPattern parameter") - return res, err - } - if params.GrantID == "" { - err := fmt.Errorf("Empty grantId parameter") - return res, err - } - var grantDescr *descr.Grant - var grantExists bool - - grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) - if err != nil { - return res, err - } - if !grantExists { - err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) - return res, err - } - now := auxtool.TimeNow() - if params.NewPattern != "" { - grantDescr.UpdatedAt = now - grantDescr.UpdatedBy = operatorID - grantDescr.Pattern = params.NewPattern - } - err = oper.mdb.UpdateGrantByID(ctx, grantDescr.ID, grantDescr) - if err != nil { - return res, err - } - return res, err -} - -// DeleteGrant -type DeleteGrantParams struct { - GrantID string `json:"grantId"` -} -type DeleteGrantResult struct{} - -func (oper *Operator) DeleteGrant(ctx context.Context, operatorID string, params *DeleteGrantParams) (*DeleteGrantResult, error) { - var err error - res := &DeleteGrantResult{} - - if params.GrantID == "" { - err := fmt.Errorf("Empty grantId parameter") - return res, err - } - - var grantDescr *descr.Grant - var grantExists bool - - grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) - if err != nil { - return res, err - } - if !grantExists { - err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) - return res, err - } - err = oper.mdb.DeleteGrantByID(ctx, grantDescr.ID) - if err != nil { - return res, err - } - return res, err -} - -// ListGrants -type ListGrantsParams struct { - Username string - AccountID string -} -type ListGrantsResult struct { - Grants []descr.Grant `json:"grants"` -} - -func (oper *Operator) ListGrants(ctx context.Context, operatorID string, params *ListGrantsParams) (*ListGrantsResult, error) { - var err error - res := &ListGrantsResult{ - Grants: make([]descr.Grant, 0), - } - var accountDescr *descr.Account - var accountExists bool - switch { - case params.AccountID != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByID(ctx, params.AccountID) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with ID %s dont exists", params.AccountID) - return res, err - } - case params.Username != "": - accountExists, accountDescr, err = oper.mdb.GetAccountByUsername(ctx, params.Username) - if err != nil { - return res, err - } - if !accountExists { - err := fmt.Errorf("Account with name %s dont exists", params.Username) - return res, err - } - default: - err := fmt.Errorf("Empty username and accountId parameter") - return res, err - } - accountID := accountDescr.ID - grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountID) - if err != nil { - return res, err - } - res.Grants = grantDescrs - return res, err -} - -// Get Grants -type GetGrantParams struct { - GrantID string `json:"grantId"` -} -type GetGrantResult struct { - Grant *descr.Grant `json:"grant"` -} - -func (oper *Operator) GetGrant(ctx context.Context, operatorID string, params *GetGrantParams) (*GetGrantResult, error) { - var err error - res := &GetGrantResult{} - - if params.GrantID == "" { - err := fmt.Errorf("Empty grantId parameter") - return res, err - } - - var grantDescr *descr.Grant - var grantExists bool - grantExists, grantDescr, err = oper.mdb.GetGrantByID(ctx, params.GrantID) - if err != nil { - return res, err - } - if !grantExists { - err := fmt.Errorf("Grant with ID %s dont exists", params.GrantID) - return res, err - } - - res.Grant = grantDescr - return res, err -} diff --git a/app/router/context.go b/app/router/context.go index acdb814..4023115 100644 --- a/app/router/context.go +++ b/app/router/context.go @@ -15,7 +15,7 @@ import ( "encoding/json" "io" "net/http" - "net/url" + "net/url" "strconv" ) diff --git a/app/server/server.go b/app/server/server.go index 2e4766a..3929a20 100644 --- a/app/server/server.go +++ b/app/server/server.go @@ -25,18 +25,23 @@ import ( "mstore/app/handler" "mstore/app/logger" "mstore/app/maindb" - "mstore/app/operator" "mstore/app/service" "mstore/app/storage" "mstore/pkg/auxtool" "mstore/pkg/descr" + "mstore/app/accoper" + "mstore/app/fileoper" + "mstore/app/imageoper" + yaml "go.yaml.in/yaml/v4" ) type Server struct { conf *config.Config - oper *operator.Operator + fiop *fileoper.Operator + acop *accoper.Operator + imop *imageoper.Operator svc *service.Service mdb *maindb.Database hand *handler.Handler @@ -248,21 +253,44 @@ func (srv *Server) Build() error { store := storage.NewStorage(datadir) srv.stor = store - // Creating operator - srv.logg.Infof("Creating operator") - operatorParams := &operator.OperatorParams{ + // Creating account operator + srv.logg.Infof("Creating account operator") + accoperParams := &accoper.OperatorParams{ MainDB: srv.mdb, Store: srv.stor, } - srv.oper, err = operator.NewOperator(operatorParams) + srv.acop, err = accoper.NewOperator(accoperParams) if err != nil { return err } + // Creating file operator + srv.logg.Infof("Creating file operator") + fileoperParams := &fileoper.OperatorParams{ + MainDB: srv.mdb, + Store: srv.stor, + } + srv.fiop, err = fileoper.NewOperator(fileoperParams) + if err != nil { + return err + } + // Creating operator + srv.logg.Infof("Creating operator") + imageoperParams := &imageoper.OperatorParams{ + MainDB: srv.mdb, + Store: srv.stor, + } + srv.imop, err = imageoper.NewOperator(imageoperParams) + if err != nil { + return err + } + // Creating handler srv.logg.Infof("Creating handler") handlerParams := &handler.HandlerParams{ - Operator: srv.oper, - MainDB: srv.mdb, + MainDB: srv.mdb, + FileOper: srv.fiop, + AccOper: srv.acop, + ImageOper: srv.imop, } srv.hand, err = handler.NewHandler(handlerParams) if err != nil { diff --git a/cmd/mstorectl/filecmd/delcoll.go b/cmd/mstorectl/filecmd/delcoll.go index 51f81ad..33e1cae 100644 --- a/cmd/mstorectl/filecmd/delcoll.go +++ b/cmd/mstorectl/filecmd/delcoll.go @@ -54,8 +54,8 @@ func (util *FileUtil) deleteCollection(common *CommonFileParams, params *DeleteC } ref.SetUserinfo(common.Username, common.Password) mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - ref.PathType(pathType(params.Regexp, params.Prefix)) - ref.DryRun(params.DryRun) + ref.PathType(pathType(params.Regexp, params.Prefix)) + ref.DryRun(params.DryRun) cli := filecli.NewClient(nil, mw) list, err := cli.DeleteCollection(ctx, ref.Raw()) if err != nil { diff --git a/cmd/mstorectl/filecmd/impfiles.go b/cmd/mstorectl/filecmd/impfiles.go index 38900a1..5ee3528 100644 --- a/cmd/mstorectl/filecmd/impfiles.go +++ b/cmd/mstorectl/filecmd/impfiles.go @@ -68,9 +68,9 @@ func (util *FileUtil) importFiles(common *CommonFileParams, params *ImportFilesP putErrors = append(putErrors, err) return nil } - ref.JoinResource(relpath) - //fmt.Printf("====%s %s\n", relpath, ref.Raw()) - //return nil + ref.JoinResource(relpath) + //fmt.Printf("====%s %s\n", relpath, ref.Raw()) + //return nil file, err := os.OpenFile(walkpath, os.O_RDONLY, 0) if err != nil { putErrors = append(putErrors, err) @@ -100,10 +100,10 @@ func (util *FileUtil) importFiles(common *CommonFileParams, params *ImportFilesP } return nil } - err = filepath.Walk(params.Source, walcFunc) - if err != nil { - return res, err - } + err = filepath.Walk(params.Source, walcFunc) + if err != nil { + return res, err + } for _, item := range putErrors { err = errors.Join(err, item) diff --git a/cmd/mstorectl/filecmd/listcolls.go b/cmd/mstorectl/filecmd/listcolls.go index 91230f0..2330e7c 100644 --- a/cmd/mstorectl/filecmd/listcolls.go +++ b/cmd/mstorectl/filecmd/listcolls.go @@ -49,7 +49,7 @@ func (util *FileUtil) listCollections(common *CommonFileParams, params *ListColl return res, err } ref.SetUserinfo(common.Username, common.Password) - ref.PathType(pathType(params.Regexp, params.Prefix)) + ref.PathType(pathType(params.Regexp, params.Prefix)) mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) cli := filecli.NewClient(nil, mw) list, err := cli.ListCollections(ctx, ref.Raw()) diff --git a/cmd/mstorectl/filecmd/listfiles.go b/cmd/mstorectl/filecmd/listfiles.go index 4f399e4..d707269 100644 --- a/cmd/mstorectl/filecmd/listfiles.go +++ b/cmd/mstorectl/filecmd/listfiles.go @@ -12,8 +12,8 @@ package filecmd import ( "context" "encoding/json" + "fmt" "time" - "fmt" "github.com/spf13/cobra" @@ -50,7 +50,7 @@ func (util *FileUtil) listFiles(common *CommonFileParams, params *ListFilesParam return res, err } ref.SetUserinfo(common.Username, common.Password) - ref.PathType(pathType(params.Regexp, params.Prefix)) + ref.PathType(pathType(params.Regexp, params.Prefix)) mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) cli := filecli.NewClient(nil, mw) @@ -58,7 +58,7 @@ func (util *FileUtil) listFiles(common *CommonFileParams, params *ListFilesParam if err != nil { return res, err } - fmt.Printf("====%s\n", list) + fmt.Printf("====%s\n", list) files := descr.NewFiles() err = json.Unmarshal(list, files.ArrayPtr()) if err != nil { @@ -73,12 +73,12 @@ func (util *FileUtil) listFiles(common *CommonFileParams, params *ListFilesParam } func pathType(regex, prefix bool) string { - switch { - case regex: - return filecli.PathTypeRegexp - case prefix: - return filecli.PathTypePrefix - default: - } - return filecli.PathTypeIdentic + switch { + case regex: + return filecli.PathTypeRegexp + case prefix: + return filecli.PathTypePrefix + default: + } + return filecli.PathTypeIdentic } diff --git a/pkg/client/imageinfo.go b/pkg/client/imageinfo.go index 1d39197..4889c1f 100644 --- a/pkg/client/imageinfo.go +++ b/pkg/client/imageinfo.go @@ -26,7 +26,6 @@ import ( const ( indexMediaType = "application/vnd.oci.image.index.v1+json" manifestMediaType = "application/vnd.oci.image.manifest.v1+json" - ) func (cli *Client) ImageManifest(ctx context.Context, imagepath string) (any, error) { diff --git a/pkg/descr/file.go b/pkg/descr/file.go index b8498ef..ecf6711 100644 --- a/pkg/descr/file.go +++ b/pkg/descr/file.go @@ -10,7 +10,7 @@ package descr import ( - "path" + "path" ) type File struct { @@ -26,43 +26,38 @@ type File struct { UpdatedBy string `db:"updated_by" json:"updatedBy,omitempty" yaml:"updatedBy,omitempty"` } - - type Files struct { - files []File + files []File } func NewFiles() *Files { - return &Files{ - files: make([]File, 0), - } + return &Files{ + files: make([]File, 0), + } } func xxxNewFiles(files []File) *Files { - return &Files{ - files: files, - } + return &Files{ + files: files, + } } func (fi *Files) Set(files []File) { - fi.files = files + fi.files = files } func (fi *Files) ArrayPtr() *[]File { - return &fi.files + return &fi.files } func (fi *Files) Array() []File { - return fi.files + return fi.files } - - func (fi *Files) List() []string { - list := make([]string, 0) - for _, file := range fi.files { - list = append(list, path.Join(file.Collection, file.Name)) - } - return list + list := make([]string, 0) + for _, file := range fi.files { + list = append(list, path.Join(file.Collection, file.Name)) + } + return list } - diff --git a/pkg/filecli/client.go b/pkg/filecli/client.go index 645a554..c92eaec 100644 --- a/pkg/filecli/client.go +++ b/pkg/filecli/client.go @@ -15,9 +15,9 @@ func NewClient(transport http.RoundTripper, mwFuncs ...MiddlewareFunc) *Client { if transport == nil { transport = NewDefaultTransport() } - for _, mwFunc := range mwFuncs { - transport = mwFunc(transport) - } + for _, mwFunc := range mwFuncs { + transport = mwFunc(transport) + } httpClient := &http.Client{ Transport: transport, } @@ -38,7 +38,6 @@ func (cli *Client) UseMiddleware(mwFunc MiddlewareFunc) { cli.httpClient.Transport = mwFunc(cli.httpClient.Transport) } - // BasicAuthMiddleware func NewBasicAuthMiddleware(user, pass string) MiddlewareFunc { return func(next http.RoundTripper) http.RoundTripper { @@ -60,10 +59,10 @@ func newBasicAuthMW(next http.RoundTripper, user, pass string) *BasicAuthMW { } func (tran BasicAuthMW) RoundTrip(req *http.Request) (*http.Response, error) { - if tran.user != "" && tran.pass != "" { - pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass)) - req.Header.Set("Authorization", "Basic "+pair) - } + if tran.user != "" && tran.pass != "" { + pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass)) + req.Header.Set("Authorization", "Basic "+pair) + } return tran.next.RoundTrip(req) } @@ -110,7 +109,6 @@ func (wrap *DefaultTransport) RoundTrip(req *http.Request) (*http.Response, erro return wrap.transport.RoundTrip(req) } - // ExampleMiddleware func NewExampleMiddleware() MiddlewareFunc { return func(next http.RoundTripper) http.RoundTripper { diff --git a/pkg/filecli/fileinfo.go b/pkg/filecli/fileinfo.go index ef27c6f..a9dc768 100644 --- a/pkg/filecli/fileinfo.go +++ b/pkg/filecli/fileinfo.go @@ -11,7 +11,7 @@ func (cli *Client) FileInfo(ctx context.Context, rawpath string) (bool, int64, s var err error var exist bool var size int64 - var digest string + var digest string ref, err := ParsePath(rawpath) if err != nil { diff --git a/pkg/filecli/repo.go b/pkg/filecli/repo.go index 44c6654..e2235ee 100644 --- a/pkg/filecli/repo.go +++ b/pkg/filecli/repo.go @@ -3,8 +3,8 @@ package filecli import ( "net/url" "path" + "strconv" "strings" - "strconv" ) const ( @@ -17,13 +17,13 @@ type Repository struct { urlobj *url.URL user, pass string resource string - values url.Values + values url.Values } func ParsePath(rawpath string) (*Repository, error) { repo := &Repository{ - values: url.Values{}, - } + values: url.Values{}, + } if !strings.Contains(rawpath, "://") { rawpath = "https://" + rawpath } @@ -39,17 +39,17 @@ func ParsePath(rawpath string) (*Repository, error) { repo.resource = path.Join("/", urlobj.Path) urlobj.Path = "/" repo.urlobj = urlobj - repo.values = urlobj.Query() + repo.values = urlobj.Query() return repo, err } func (repo *Repository) Raw() string { res := path.Join(repo.urlobj.Host, repo.resource) - query := repo.values.Encode() - if query != "" { - return res + "?" + query - } - return res + query := repo.values.Encode() + if query != "" { + return res + "?" + query + } + return res } func (repo *Repository) SetResource(resource string) { @@ -61,11 +61,11 @@ func (repo *Repository) JoinResource(resource string) { } func (repo *Repository) PathType(typ string) { - repo.values.Set("pathType", typ) + repo.values.Set("pathType", typ) } func (repo *Repository) DryRun(yesno bool) { - repo.values.Set("dryRun", strconv.FormatBool(yesno)) + repo.values.Set("dryRun", strconv.FormatBool(yesno)) } func (repo *Repository) File() string { diff --git a/pkg/repocli/client.go b/pkg/repocli/client.go index 795aff9..eeea8f0 100644 --- a/pkg/repocli/client.go +++ b/pkg/repocli/client.go @@ -87,10 +87,10 @@ func newBasicAuthMW(next http.RoundTripper, user, pass string) *BasicAuthMW { } func (tran BasicAuthMW) RoundTrip(req *http.Request) (*http.Response, error) { - if tran.user != "" && tran.pass != "" { - pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass)) - req.Header.Set("Authorization", "Basic "+pair) - } + if tran.user != "" && tran.pass != "" { + pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass)) + req.Header.Set("Authorization", "Basic "+pair) + } return tran.next.RoundTrip(req) } diff --git a/pkg/repocli/mimetyp.go b/pkg/repocli/mimetyp.go index 83b12fa..0a0f941 100644 --- a/pkg/repocli/mimetyp.go +++ b/pkg/repocli/mimetyp.go @@ -1,6 +1,6 @@ package repocli const ( - //MediaTypeDDMLv2 = "application/vnd.docker.distribution.manifest.list.v2+json" - //MediaTypeDDMv2 = "application/vnd.docker.distribution.manifest.v2+json" +// MediaTypeDDMLv2 = "application/vnd.docker.distribution.manifest.list.v2+json" +// MediaTypeDDMv2 = "application/vnd.docker.distribution.manifest.v2+json" ) diff --git a/test/file_test.go b/test/file_test.go index 8cbffdc..34c6c32 100644 --- a/test/file_test.go +++ b/test/file_test.go @@ -15,14 +15,14 @@ import ( //"math/rand" //"os" //"path/filepath" + "bytes" "sync" "testing" "time" - "bytes" "mstore/app/server" "mstore/pkg/client" - "mstore/pkg/filecli" + "mstore/pkg/filecli" "github.com/stretchr/testify/require" ) @@ -79,114 +79,114 @@ func TestFileLife(t *testing.T) { require.NoError(t, err) require.True(t, helloRes) } - fileaddr := srvaddr+"/foo2/bare.bin" - filedata := []byte("Hello, World") - filesize := int64(len(filedata)) - user, pass := "mstore", "mstore" - diraddr := srvaddr+"/foo" + fileaddr := srvaddr + "/foo2/bare.bin" + filedata := []byte("Hello, World") + filesize := int64(len(filedata)) + user, pass := "mstore", "mstore" + diraddr := srvaddr + "/foo" { // PutFile - file := bytes.NewReader(filedata) - size := int64(len(filedata)) + file := bytes.NewReader(filedata) + size := int64(len(filedata)) fmt.Printf("=== PutFile ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(fileaddr) - require.NoError(t, err) - fmt.Printf("Raw: %s\n", ref.Raw()) - ref.SetUserinfo(user, pass) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(fileaddr) + require.NoError(t, err) + fmt.Printf("Raw: %s\n", ref.Raw()) + ref.SetUserinfo(user, pass) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - err = cli.PutFile(ctx, ref.Raw(), file, size) - require.NoError(t, err) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + err = cli.PutFile(ctx, ref.Raw(), file, size) + require.NoError(t, err) } { // GetFile - file := bytes.NewBuffer(nil) + file := bytes.NewBuffer(nil) fmt.Printf("=== GetFile ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(fileaddr) - require.NoError(t, err) - fmt.Printf("Raw: %s\n", ref.Raw()) - ref.SetUserinfo(user, pass) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(fileaddr) + require.NoError(t, err) + fmt.Printf("Raw: %s\n", ref.Raw()) + ref.SetUserinfo(user, pass) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - exist, err := cli.GetFile(ctx, ref.Raw(), file) - require.NoError(t, err) - require.True(t, exist) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + exist, err := cli.GetFile(ctx, ref.Raw(), file) + require.NoError(t, err) + require.True(t, exist) } { // FileInfo fmt.Printf("=== FileInfo ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(fileaddr) - require.NoError(t, err) - fmt.Printf("Raw: %s\n", ref.Raw()) - ref.SetUserinfo(user, pass) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(fileaddr) + require.NoError(t, err) + fmt.Printf("Raw: %s\n", ref.Raw()) + ref.SetUserinfo(user, pass) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - exist, size, digest, err := cli.FileInfo(ctx, ref.Raw()) - require.NoError(t, err) - require.True(t, exist) - require.Equal(t, size, filesize) - fmt.Printf("Digest: %s\n", digest) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + exist, size, digest, err := cli.FileInfo(ctx, ref.Raw()) + require.NoError(t, err) + require.True(t, exist) + require.Equal(t, size, filesize) + fmt.Printf("Digest: %s\n", digest) } { // FileList fmt.Printf("=== FileList ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(diraddr) - require.NoError(t, err) - ref.SetUserinfo(user, pass) - ref.PathType(filecli.PathTypePrefix) - fmt.Printf("Raw: %s\n", ref.Raw()) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(diraddr) + require.NoError(t, err) + ref.SetUserinfo(user, pass) + ref.PathType(filecli.PathTypePrefix) + fmt.Printf("Raw: %s\n", ref.Raw()) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - list, err := cli.ListFiles(ctx, ref.Raw()) - require.NoError(t, err) - fmt.Printf("List: %s\n", list) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + list, err := cli.ListFiles(ctx, ref.Raw()) + require.NoError(t, err) + fmt.Printf("List: %s\n", list) } { // DeleteFile fmt.Printf("=== FileList ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(fileaddr) - require.NoError(t, err) - ref.SetUserinfo(user, pass) - //ref.PathType(filecli.PathTypePrefix) - fmt.Printf("Raw: %s\n", ref.Raw()) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(fileaddr) + require.NoError(t, err) + ref.SetUserinfo(user, pass) + //ref.PathType(filecli.PathTypePrefix) + fmt.Printf("Raw: %s\n", ref.Raw()) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - exist, err := cli.DeleteFile(ctx, ref.Raw()) - require.NoError(t, err) - fmt.Printf("Exist: %v\n", exist) - require.True(t, exist) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + exist, err := cli.DeleteFile(ctx, ref.Raw()) + require.NoError(t, err) + fmt.Printf("Exist: %v\n", exist) + require.True(t, exist) } - { + { // DeleteFile fmt.Printf("=== FileList ===\n") - timeout := 10 * time.Second - ctx, _ := context.WithTimeout(context.Background(), timeout) - ref, err := filecli.ParsePath(fileaddr) - require.NoError(t, err) - ref.SetUserinfo(user, pass) - //ref.PathType(filecli.PathTypePrefix) - fmt.Printf("Raw: %s\n", ref.Raw()) + timeout := 10 * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + ref, err := filecli.ParsePath(fileaddr) + require.NoError(t, err) + ref.SetUserinfo(user, pass) + //ref.PathType(filecli.PathTypePrefix) + fmt.Printf("Raw: %s\n", ref.Raw()) - mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) - cli := filecli.NewClient(nil, mw) - exist, err := cli.DeleteFile(ctx, ref.Raw()) - require.NoError(t, err) - fmt.Printf("Exist: %v\n", exist) - require.False(t, exist) + mw := filecli.NewBasicAuthMiddleware(ref.Userinfo()) + cli := filecli.NewClient(nil, mw) + exist, err := cli.DeleteFile(ctx, ref.Raw()) + require.NoError(t, err) + fmt.Printf("Exist: %v\n", exist) + require.False(t, exist) } }