working commit
This commit is contained in:
+57
-57
@@ -77,6 +77,63 @@ func (oper *Operator) CreateAccount(ctx context.Context, params *CreateAccountPa
|
||||
return res, err
|
||||
}
|
||||
|
||||
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, params *GetAccountParams) (*GetAccountResult, error) {
|
||||
var err error
|
||||
res := &GetAccountResult{}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
accountShort := &descr.AccountShort{
|
||||
Username: accountDescr.Username,
|
||||
Disabled: accountDescr.Disabled,
|
||||
CreatedAt: accountDescr.CreatedAt,
|
||||
UpdatedAt: accountDescr.UpdatedAt,
|
||||
Grants: make([]descr.GrantShort, 0),
|
||||
}
|
||||
grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
for _, grantDescrs := range grantDescrs {
|
||||
grantShorts := descr.GrantShort{
|
||||
Operation: grantDescrs.Operation,
|
||||
CreatedAt: grantDescrs.CreatedAt,
|
||||
}
|
||||
accountShort.Grants = append(accountShort.Grants, grantShorts)
|
||||
}
|
||||
|
||||
res.Account = accountShort
|
||||
return res, err
|
||||
}
|
||||
|
||||
type UpdateAccountParams struct {
|
||||
Username string `json:"username"`
|
||||
AccountID string `json:"accountId"`
|
||||
@@ -216,60 +273,3 @@ func (oper *Operator) ListAccounts(ctx context.Context, params *ListAccountsPara
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
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, params *GetAccountParams) (*GetAccountResult, error) {
|
||||
var err error
|
||||
res := &GetAccountResult{}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
accountShort := &descr.AccountShort{
|
||||
Username: accountDescr.Username,
|
||||
Disabled: accountDescr.Disabled,
|
||||
CreatedAt: accountDescr.CreatedAt,
|
||||
UpdatedAt: accountDescr.UpdatedAt,
|
||||
Grants: make([]descr.GrantShort, 0),
|
||||
}
|
||||
grantDescrs, err := oper.mdb.ListGrantsByAccountID(ctx, accountDescr.ID)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
for _, grantDescrs := range grantDescrs {
|
||||
grantShorts := descr.GrantShort{
|
||||
Operation: grantDescrs.Operation,
|
||||
CreatedAt: grantDescrs.CreatedAt,
|
||||
}
|
||||
accountShort.Grants = append(accountShort.Grants, grantShorts)
|
||||
}
|
||||
|
||||
res.Account = accountShort
|
||||
return res, err
|
||||
}
|
||||
|
||||
+10
-10
@@ -99,17 +99,17 @@ func (svc *Service) Build() error {
|
||||
svc.rout.Get(`/v2/{name}/tags/list`, svc.hand.GetTags)
|
||||
svc.rout.Get(`/v2/{name}/referrers/{digest}`, svc.hand.GetReferer)
|
||||
|
||||
svc.rout.Post(`/v3/account/create`, svc.hand.CreateAccount)
|
||||
svc.rout.Post(`/v3/account/get`, svc.hand.GetAccount)
|
||||
svc.rout.Post(`/v3/account/update`, svc.hand.UpdateAccount)
|
||||
svc.rout.Post(`/v3/account/delete`, svc.hand.DeleteAccount)
|
||||
svc.rout.Post(`/v3/accounts/list`, svc.hand.ListAccounts)
|
||||
svc.rout.Post(`/v3/api/account/create`, svc.hand.CreateAccount)
|
||||
svc.rout.Post(`/v3/api/account/get`, svc.hand.GetAccount)
|
||||
svc.rout.Post(`/v3/api/account/update`, svc.hand.UpdateAccount)
|
||||
svc.rout.Post(`/v3/api/account/delete`, svc.hand.DeleteAccount)
|
||||
svc.rout.Post(`/v3/api/accounts/list`, svc.hand.ListAccounts)
|
||||
|
||||
svc.rout.Post(`/v3/grant/create`, svc.hand.CreateGrant)
|
||||
svc.rout.Post(`/v3/grant/get`, svc.hand.GetGrant)
|
||||
svc.rout.Post(`/v3/grant/update`, svc.hand.UpdateGrant)
|
||||
svc.rout.Post(`/v3/grant/delete`, svc.hand.DeleteGrant)
|
||||
svc.rout.Post(`/v3/grants/list`, svc.hand.ListGrants)
|
||||
svc.rout.Post(`/v3/api/grant/create`, svc.hand.CreateGrant)
|
||||
svc.rout.Post(`/v3/api/grant/get`, svc.hand.GetGrant)
|
||||
svc.rout.Post(`/v3/api/grant/update`, svc.hand.UpdateGrant)
|
||||
svc.rout.Post(`/v3/api/grant/delete`, svc.hand.DeleteGrant)
|
||||
svc.rout.Post(`/v3/api/grants/list`, svc.hand.ListGrants)
|
||||
|
||||
svc.rout.NotFound(svc.hand.NotFound)
|
||||
|
||||
|
||||
+50
-15
@@ -15,16 +15,18 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"mstore/app/descr"
|
||||
"mstore/app/handler"
|
||||
"mstore/app/operator"
|
||||
)
|
||||
|
||||
func (cli *Client) CreateAccount(ctx context.Context, hosturi, username, password string) error {
|
||||
func (cli *Client) CreateAccount(ctx context.Context, hosturi, username, password string) (string, error) {
|
||||
var err error
|
||||
var res string
|
||||
|
||||
apiuri, err := url.JoinPath(hosturi, "/v3/api/account/create")
|
||||
apiuri, err := setApiPath(hosturi, "/v3/api/account/create")
|
||||
if err != nil {
|
||||
return err
|
||||
return res, err
|
||||
}
|
||||
operParams := operator.CreateAccountParams{
|
||||
Username: username,
|
||||
@@ -32,26 +34,60 @@ func (cli *Client) CreateAccount(ctx context.Context, hosturi, username, passwor
|
||||
}
|
||||
paramsJson, err := json.Marshal(operParams)
|
||||
if err != nil {
|
||||
return err
|
||||
return res, err
|
||||
}
|
||||
respBytes, err := doHTTPCall(ctx, apiuri, paramsJson)
|
||||
if err != nil {
|
||||
return err
|
||||
return res, err
|
||||
}
|
||||
|
||||
operRes := handler.NewResponse[operator.CreateAccountResult]()
|
||||
err = json.Unmarshal(respBytes, operRes)
|
||||
if err != nil {
|
||||
return err
|
||||
return res, err
|
||||
}
|
||||
if !operRes.Error {
|
||||
if operRes.Error {
|
||||
err = fmt.Errorf("%s", operRes.Message)
|
||||
return err
|
||||
return res, err
|
||||
}
|
||||
return err
|
||||
res = operRes.Result.AccountID
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (cli *Client) GetAccount(ctx context.Context, hosturi, id, username string) error {
|
||||
func (cli *Client) GetAccountByID(ctx context.Context, hosturi, id string) (descr.AccountShort, error) {
|
||||
var err error
|
||||
var res descr.AccountShort
|
||||
|
||||
apipath, err := setApiPath(hosturi, "/v3/api/account/get")
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
operParams := operator.GetAccountParams{
|
||||
AccountID: id,
|
||||
}
|
||||
paramsJson, err := json.Marshal(operParams)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
respBytes, err := doHTTPCall(ctx, apipath, paramsJson)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
operRes := handler.NewResponse[operator.GetAccountResult]()
|
||||
err = json.Unmarshal(respBytes, operRes)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if operRes.Error {
|
||||
err = fmt.Errorf("%s", operRes.Message)
|
||||
return res, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (cli *Client) GetAccountByName(ctx context.Context, hosturi, username string) error {
|
||||
var err error
|
||||
|
||||
apipath, err := url.JoinPath(hosturi, "/v3/api/account/get")
|
||||
@@ -59,8 +95,7 @@ func (cli *Client) GetAccount(ctx context.Context, hosturi, id, username string)
|
||||
return err
|
||||
}
|
||||
operParams := operator.GetAccountParams{
|
||||
Username: username,
|
||||
AccountID: id,
|
||||
Username: username,
|
||||
}
|
||||
paramsJson, err := json.Marshal(operParams)
|
||||
if err != nil {
|
||||
@@ -76,7 +111,7 @@ func (cli *Client) GetAccount(ctx context.Context, hosturi, id, username string)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !operRes.Error {
|
||||
if operRes.Error {
|
||||
err = fmt.Errorf("%s", operRes.Message)
|
||||
return err
|
||||
}
|
||||
@@ -109,7 +144,7 @@ func (cli *Client) UpdateAccount(ctx context.Context, hosturi, id, username, new
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !operRes.Error {
|
||||
if operRes.Error {
|
||||
err = fmt.Errorf("%s", operRes.Message)
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +176,7 @@ func (cli *Client) DeleteAccount(ctx context.Context, hosturi, id, username stri
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !operRes.Error {
|
||||
if operRes.Error {
|
||||
err = fmt.Errorf("%s", operRes.Message)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
* 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 client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
//"math/rand"
|
||||
//"os"
|
||||
//"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"mstore/app/server"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAccountLife(t *testing.T) {
|
||||
var srvport int64 = 10250
|
||||
srvdir := t.TempDir()
|
||||
srvaddr := fmt.Sprintf("foouser:foopass@127.0.0.1:%d", srvport)
|
||||
|
||||
srv, err := server.NewServer()
|
||||
require.NoError(t, err)
|
||||
{
|
||||
err = srv.Configure()
|
||||
require.NoError(t, err)
|
||||
|
||||
srv.SetDatadir(srvdir)
|
||||
srv.SetLogdir(srvdir)
|
||||
srv.SetRundir(srvdir)
|
||||
srv.SetPort(srvport)
|
||||
|
||||
err = srv.Build()
|
||||
require.NoError(t, err)
|
||||
|
||||
var svcWG sync.WaitGroup
|
||||
errPipe := make(chan error, 5)
|
||||
|
||||
startFunc := func() {
|
||||
err := srv.Service().Run()
|
||||
errPipe <- err
|
||||
svcWG.Done()
|
||||
}
|
||||
|
||||
stopFunc := func() {
|
||||
srv.Service().Stop()
|
||||
svcWG.Wait()
|
||||
err = <-errPipe
|
||||
require.NoError(t, err)
|
||||
}
|
||||
defer stopFunc()
|
||||
|
||||
svcWG.Add(1)
|
||||
go startFunc()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
{
|
||||
// ServiceHello
|
||||
fmt.Printf("=== ServiceHello ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
helloRes, err := cli.ServiceHello(ctx, srvaddr+"/hello", 1*time.Second)
|
||||
require.NoError(t, err)
|
||||
require.True(t, helloRes)
|
||||
}
|
||||
|
||||
username := "testuser"
|
||||
password := "testpass"
|
||||
|
||||
var accountID string
|
||||
{
|
||||
// CreateAccount
|
||||
fmt.Printf("=== CreateAccount ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
|
||||
accountID, err = cli.CreateAccount(ctx, srvaddr, username, password)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
{
|
||||
// GetAccount
|
||||
fmt.Printf("=== GetAccount ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
|
||||
_, err = cli.GetAccountByID(ctx, srvaddr, accountID)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
/*
|
||||
{
|
||||
// ListAccounts
|
||||
fmt.Printf("=== ListAccounts ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
|
||||
files, err := cli.ListAccounts(ctx, srvaddr+"/")
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, len(files))
|
||||
}
|
||||
|
||||
{
|
||||
// DeleteAccount
|
||||
fmt.Printf("=== DeleteAccount ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
|
||||
err = cli.DeleteAccount(ctx, srvaddr+"/foo.bin")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
{
|
||||
// !AccountExists
|
||||
fmt.Printf("=== AccountExists ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
|
||||
exists, _, err := cli.AccountInfo(ctx, srvaddr+"/foo.bin")
|
||||
require.NoError(t, err)
|
||||
require.False(t, exists)
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFileLife(t *testing.T) {
|
||||
func xxxTestFileLife(t *testing.T) {
|
||||
var srvport int64 = 10250
|
||||
srvdir := t.TempDir()
|
||||
srvaddr := fmt.Sprintf("testuser:testpass@127.0.0.1:%d", srvport)
|
||||
@@ -74,8 +74,6 @@ func TestFileLife(t *testing.T) {
|
||||
require.True(t, helloRes)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
filesize := 32
|
||||
{
|
||||
// PutFile
|
||||
@@ -98,8 +96,8 @@ func TestFileLife(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
{
|
||||
// FileExists
|
||||
fmt.Printf("=== FileExists ===\n")
|
||||
// FileInfo
|
||||
fmt.Printf("=== FileInfo ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
@@ -146,8 +144,8 @@ func TestFileLife(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
{
|
||||
// !FileExists
|
||||
fmt.Printf("=== FileExists ===\n")
|
||||
// !FileInfo
|
||||
fmt.Printf("=== FileInfo ===\n")
|
||||
cli := NewClient()
|
||||
ctx := context.Background()
|
||||
ctx, _ = context.WithTimeout(ctx, 1*time.Second)
|
||||
+21
-4
@@ -13,17 +13,34 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
//"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
//"net/url"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
//"mstore/app/handler"
|
||||
//"mstore/app/operator"
|
||||
"mstore/pkg/auxhttp"
|
||||
)
|
||||
|
||||
func setApiPath(base, apipath string) (string, error) {
|
||||
var res string
|
||||
if !strings.Contains(base, "://") {
|
||||
base = "https://" + base
|
||||
}
|
||||
uri, err := url.Parse(base)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
uri.Path = "/"
|
||||
uri.Path, err = url.JoinPath(uri.Path, apipath)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res = uri.String()
|
||||
return res, nil
|
||||
|
||||
}
|
||||
|
||||
func doHTTPCall(ctx context.Context, apiuri string, reqBytes []byte) ([]byte, error) {
|
||||
var err error
|
||||
respBytes := make([]byte, 0)
|
||||
|
||||
Reference in New Issue
Block a user