feat: wrap message by fluent ui toast
This commit is contained in:
		
							
								
								
									
										32
									
								
								internal/api/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								internal/api/api.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/handler"
 | 
			
		||||
	"github.com/loveuer/nf-disk/ndh"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	apis = make(map[string]ndh.Handler)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func register(path string, h ndh.Handler) {
 | 
			
		||||
	name := reflect.ValueOf(h).String()
 | 
			
		||||
	log.Info("app register: path = %s, name = %s", path, name)
 | 
			
		||||
	apis[path] = h
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Resolve(path string) (ndh.Handler, bool) {
 | 
			
		||||
	h, ok := apis[path]
 | 
			
		||||
	return h, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Init(ctx context.Context) error {
 | 
			
		||||
	register("/api/connection/test", handler.ConnectionTest)
 | 
			
		||||
	register("/api/connection/create", handler.ConnectionCreate)
 | 
			
		||||
	register("/api/connection/list", handler.ConnectionList)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
package controller
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"nf-disk/internal/handler"
 | 
			
		||||
	"nf-disk/internal/ndh"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (a *App) register(path string, handler ndh.Handler) {
 | 
			
		||||
	name := reflect.ValueOf(handler).String()
 | 
			
		||||
	log.Info("app register: path = %s, name = %s", path, name)
 | 
			
		||||
	a.handlers[path] = handler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initApi(a *App) {
 | 
			
		||||
	a.register("/api/connection/test", handler.ConnectionTest)
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
package controller
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/api"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/db"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/model"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/tool"
 | 
			
		||||
	"github.com/loveuer/nf-disk/ndh"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"nf-disk/internal/ndh"
 | 
			
		||||
	"nf-disk/internal/tool"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type App struct {
 | 
			
		||||
@@ -22,24 +22,11 @@ func NewApp() *App {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *App) Startup(ctx context.Context) {
 | 
			
		||||
	a.ctx = ctx
 | 
			
		||||
	log.Info("app startup!!!")
 | 
			
		||||
	initApi(a)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *App) Invoke(path string, req string) (res string) {
 | 
			
		||||
	log.Info("app invoke: path = %s, req = %s", path, req)
 | 
			
		||||
	handler, ok := a.handlers[path]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return `{"err": "handler not found", "status": 404}`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	ctx := ndh.NewCtx(tool.Timeout(), json.NewDecoder(strings.NewReader(req)), &buf)
 | 
			
		||||
 | 
			
		||||
	if err := handler(ctx); err != nil {
 | 
			
		||||
		return err.Error()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
 | 
			
		||||
	a.ctx = ctx
 | 
			
		||||
 | 
			
		||||
	tool.Must(db.Init(ctx, "sqlite::memory", db.OptSqliteByMem(nil)))
 | 
			
		||||
	tool.Must(model.Init(db.Default.Session()))
 | 
			
		||||
	tool.Must(api.Init(ctx))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								internal/controller/invoke.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								internal/controller/invoke.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package controller
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/api"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/opt"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/tool"
 | 
			
		||||
	"github.com/loveuer/nf-disk/ndh"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func handleError(err error) string {
 | 
			
		||||
	bs, _ := json.Marshal(map[string]any{
 | 
			
		||||
		"err":    err.Error(),
 | 
			
		||||
		"msg":    opt.Msg500,
 | 
			
		||||
		"status": 500,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return string(bs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleNotFound(path string) string {
 | 
			
		||||
	bs, _ := json.Marshal(map[string]any{
 | 
			
		||||
		"err":    fmt.Sprintf("path not found, path: %s", path),
 | 
			
		||||
		"msg":    opt.Msg500,
 | 
			
		||||
		"status": 404,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return string(bs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *App) Invoke(path string, req string) (res string) {
 | 
			
		||||
	log.Info("app invoke: path = %s, req = %s", path, req)
 | 
			
		||||
	handler, ok := api.Resolve(path)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		log.Warn("app invoke: path not found, path = %s", path)
 | 
			
		||||
		return handleNotFound(path)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	ctx := ndh.NewCtx(tool.TimeoutCtx(a.ctx), strings.NewReader(req), &buf)
 | 
			
		||||
 | 
			
		||||
	if err := handler(ctx); err != nil {
 | 
			
		||||
		return handleError(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								internal/db/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								internal/db/client.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/opt"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/tool"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	Default *Client
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Client struct {
 | 
			
		||||
	ctx       context.Context
 | 
			
		||||
	cli       *gorm.DB
 | 
			
		||||
	ttype     string
 | 
			
		||||
	cfgSqlite *cfgSqlite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Type() string {
 | 
			
		||||
	return c.ttype
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Session(ctxs ...context.Context) *gorm.DB {
 | 
			
		||||
	var ctx context.Context
 | 
			
		||||
	if len(ctxs) > 0 && ctxs[0] != nil {
 | 
			
		||||
		ctx = ctxs[0]
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx = tool.Timeout(30)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	session := c.cli.Session(&gorm.Session{Context: ctx})
 | 
			
		||||
 | 
			
		||||
	if opt.Debug {
 | 
			
		||||
		session = session.Debug()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return session
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Close() {
 | 
			
		||||
	d, _ := c.cli.DB()
 | 
			
		||||
	d.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dump
 | 
			
		||||
// Only for sqlite with mem mode to dump data to bytes(io.Reader)
 | 
			
		||||
func (c *Client) Dump() (reader io.ReadSeekCloser, ok bool) {
 | 
			
		||||
	if c.ttype != "sqlite" {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.cfgSqlite.fsType != "mem" {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.cfgSqlite.memDump.Dump(), true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								internal/db/db_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								internal/db/db_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestOpen(t *testing.T) {
 | 
			
		||||
	myClient, err := New(context.TODO(), "sqlite::", OptSqliteByMem())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("TestOpen: New err = %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type Start struct {
 | 
			
		||||
		Id   int     `json:"id" gorm:"column:id;primaryKey"`
 | 
			
		||||
		Name string  `json:"name" gorm:"column:name"`
 | 
			
		||||
		Dis  float64 `json:"dis" gorm:"column:dis"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = myClient.Session().AutoMigrate(&Start{}); err != nil {
 | 
			
		||||
		t.Fatalf("TestOpen: AutoMigrate err = %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = myClient.Session().Create(&Start{Name: "sun", Dis: 6631.76}).Error; err != nil {
 | 
			
		||||
		t.Fatalf("TestOpen: Create err = %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = myClient.Session().Create(&Start{Name: "mar", Dis: 786.35}).Error; err != nil {
 | 
			
		||||
		t.Fatalf("TestOpen: Create err = %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if reader, ok := myClient.Dump(); ok {
 | 
			
		||||
		bs, err := io.ReadAll(reader)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("TestOpen: ReadAll err = %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		os.WriteFile("dump.db", bs, 0644)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	myClient.Close()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								internal/db/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								internal/db/init.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gorm.io/driver/mysql"
 | 
			
		||||
	"gorm.io/driver/postgres"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func New(ctx context.Context, uri string, opts ...Option) (*Client, error) {
 | 
			
		||||
	strs := strings.Split(uri, "::")
 | 
			
		||||
 | 
			
		||||
	if len(strs) != 2 {
 | 
			
		||||
		return nil, fmt.Errorf("db.Init: opt db uri invalid: %s", uri)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c := &Client{ttype: strs[0], cfgSqlite: &cfgSqlite{fsType: "file"}}
 | 
			
		||||
	for _, f := range opts {
 | 
			
		||||
		f(c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		err error
 | 
			
		||||
		dsn = strs[1]
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	switch strs[0] {
 | 
			
		||||
	case "sqlite":
 | 
			
		||||
		err = openSqlite(c, dsn)
 | 
			
		||||
	case "mysql":
 | 
			
		||||
		c.cli, err = gorm.Open(mysql.Open(dsn))
 | 
			
		||||
	case "postgres":
 | 
			
		||||
		c.cli, err = gorm.Open(postgres.Open(dsn))
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("db type only support: [sqlite, mysql, postgres], unsupported db type: %s", strs[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("db.Init: open %s with dsn:%s, err: %w", strs[0], dsn, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Init(ctx context.Context, uri string, opts ...Option) (err error) {
 | 
			
		||||
	if Default, err = New(ctx, uri, opts...); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								internal/db/option.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								internal/db/option.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	_ "github.com/loveuer/go-sqlite3/embed"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Option func(c *Client)
 | 
			
		||||
 | 
			
		||||
func OptSqliteByUrl(address string) Option {
 | 
			
		||||
	return func(c *Client) {
 | 
			
		||||
		c.cfgSqlite.fsType = "url"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SqliteMemDumper interface {
 | 
			
		||||
	Dump() io.ReadSeekCloser
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 如果传 nil 则表示新生成一个 mem 的 sqlite
 | 
			
		||||
// 如果传了一个合法的 reader 则会从这个 reader 初始化 database
 | 
			
		||||
func OptSqliteByMem(reader io.ReadCloser) Option {
 | 
			
		||||
	return func(c *Client) {
 | 
			
		||||
		c.cfgSqlite.memReader = reader
 | 
			
		||||
		c.cfgSqlite.fsType = "mem"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								internal/db/sqlite.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								internal/db/sqlite.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/loveuer/go-sqlite3/embed"
 | 
			
		||||
	"github.com/loveuer/go-sqlite3/vfs/memdb"
 | 
			
		||||
	"github.com/loveuer/go-sqlite3/vfs/readervfs"
 | 
			
		||||
	"github.com/ncruces/go-sqlite3/gormlite"
 | 
			
		||||
	"github.com/psanford/httpreadat"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type cfgSqlite struct {
 | 
			
		||||
	fsType    string // file, mem(bytes), url
 | 
			
		||||
	memDump   *memdb.MemDB
 | 
			
		||||
	memReader io.ReadCloser
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func openSqlite(c *Client, dsn string) error {
 | 
			
		||||
	var (
 | 
			
		||||
		db  gorm.Dialector
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	switch c.cfgSqlite.fsType {
 | 
			
		||||
	case "file":
 | 
			
		||||
		db = gormlite.Open("file:" + dsn)
 | 
			
		||||
	case "url":
 | 
			
		||||
		name := fmt.Sprintf("%d.db", time.Now().UnixNano())
 | 
			
		||||
		readervfs.Create(name, httpreadat.New(dsn))
 | 
			
		||||
		uri := fmt.Sprintf("file:%s?vfs=reader", name)
 | 
			
		||||
		db = gormlite.Open(uri)
 | 
			
		||||
	case "mem":
 | 
			
		||||
		var (
 | 
			
		||||
			bs   []byte
 | 
			
		||||
			name = fmt.Sprintf("%d.db", time.Now().UnixNano())
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		if c.cfgSqlite.memReader == nil {
 | 
			
		||||
			bs = make([]byte, 0)
 | 
			
		||||
		} else {
 | 
			
		||||
			if bs, err = io.ReadAll(c.cfgSqlite.memReader); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memDump := memdb.Create(name, bs)
 | 
			
		||||
		c.cfgSqlite.memDump = memDump
 | 
			
		||||
		uri := fmt.Sprintf("file:/%s?vfs=memdb", name)
 | 
			
		||||
		db = gormlite.Open(uri)
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unsupported sqlite fs type: %s", c.cfgSqlite.fsType)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.cli, err = gorm.Open(db); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
package handler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"nf-disk/internal/ndh"
 | 
			
		||||
	"nf-disk/internal/s3"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/db"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/manager"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/model"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/s3"
 | 
			
		||||
	"github.com/loveuer/nf-disk/ndh"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ConnectionTest(c *ndh.Ctx) error {
 | 
			
		||||
@@ -30,5 +33,69 @@ func ConnectionTest(c *ndh.Ctx) error {
 | 
			
		||||
		return c.Send500(err.Error(), "连接失败")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send200("test success")
 | 
			
		||||
	return c.Send200("连接测试成功")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ConnectionCreate(c *ndh.Ctx) error {
 | 
			
		||||
	type Req struct {
 | 
			
		||||
		Name     string `json:"name"`
 | 
			
		||||
		Endpoint string `json:"endpoint"`
 | 
			
		||||
		Access   string `json:"access"`
 | 
			
		||||
		Key      string `json:"key"`
 | 
			
		||||
		Force    bool   `json:"force"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		err    error
 | 
			
		||||
		req    = new(Req)
 | 
			
		||||
		client *s3.Client
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err = c.ReqParse(req); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if req.Endpoint == "" || req.Access == "" || req.Key == "" {
 | 
			
		||||
		return c.Send400(nil, "endpoint, secret_access, secret_key 是必填项")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if client, err = s3.New(c.Context(), req.Endpoint, req.Access, req.Key); err != nil {
 | 
			
		||||
		return c.Send500(err.Error(), "连接失败")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if req.Name == "" {
 | 
			
		||||
		req.Name = req.Endpoint
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	connection := &model.Connection{
 | 
			
		||||
		Name:     req.Name,
 | 
			
		||||
		Endpoint: req.Endpoint,
 | 
			
		||||
		Access:   req.Access,
 | 
			
		||||
		Key:      req.Key,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = connection.Create(db.Default.Session()); err != nil {
 | 
			
		||||
		return c.Send500(err.Error(), "创建连接失败(1)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = manager.Register(connection, client); err != nil {
 | 
			
		||||
		return c.Send500(err.Error(), "创建连接失败(2)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send200(connection, "创建连接成功")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ConnectionList(c *ndh.Ctx) error {
 | 
			
		||||
	var (
 | 
			
		||||
		err  error
 | 
			
		||||
		list = make([]*model.Connection, 0)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err = db.Default.Session().Model(&model.Connection{}).
 | 
			
		||||
		Find(&list).
 | 
			
		||||
		Error; err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send200(map[string]any{"list": list})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								internal/manager/manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								internal/manager/manager.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/model"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/s3"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Init(ctx context.Context) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Register(m *model.Connection, c *s3.Client) error {
 | 
			
		||||
	log.Debug("manager: register connection-client: id = %d, name = %s", m.Id, m.Name)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								internal/model/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								internal/model/init.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
package model
 | 
			
		||||
 | 
			
		||||
import "gorm.io/gorm"
 | 
			
		||||
 | 
			
		||||
func Init(tx *gorm.DB) error {
 | 
			
		||||
	return tx.AutoMigrate(
 | 
			
		||||
		&Connection{},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								internal/model/s3.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								internal/model/s3.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package model
 | 
			
		||||
 | 
			
		||||
import "gorm.io/gorm"
 | 
			
		||||
 | 
			
		||||
type Connection struct {
 | 
			
		||||
	Id        uint64 `json:"id" gorm:"primaryKey;column:id"`
 | 
			
		||||
	CreatedAt int64  `json:"created_at" gorm:"column:created_at;autoCreateTime:milli"`
 | 
			
		||||
	UpdatedAt int64  `json:"updated_at" gorm:"column:updated_at;autoUpdateTime:milli"`
 | 
			
		||||
	DeletedAt int64  `json:"deleted_at" gorm:"index;column:deleted_at;default:0"`
 | 
			
		||||
	Name      string `json:"name" gorm:"unique;column:name"`
 | 
			
		||||
	Endpoint  string `json:"endpoint" gorm:"column:endpoint"`
 | 
			
		||||
	Access    string `json:"access" gorm:"column:access"`
 | 
			
		||||
	Key       string `json:"key" gorm:"column:key"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Connection) Create(tx *gorm.DB) error {
 | 
			
		||||
	return tx.Create(c).Error
 | 
			
		||||
}
 | 
			
		||||
@@ -1,72 +0,0 @@
 | 
			
		||||
package ndh
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Ctx struct {
 | 
			
		||||
	ctx context.Context
 | 
			
		||||
	req *json.Decoder
 | 
			
		||||
	res io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewCtx(ctx context.Context, req *json.Decoder, res io.Writer) *Ctx {
 | 
			
		||||
	return &Ctx{
 | 
			
		||||
		ctx: ctx,
 | 
			
		||||
		req: req,
 | 
			
		||||
		res: res,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Context() context.Context {
 | 
			
		||||
	return c.ctx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Write(bs []byte) (int, error) {
 | 
			
		||||
	return c.res.Write(bs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) ReqParse(req any) error {
 | 
			
		||||
	return c.req.Decode(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Send200(data any, msg ...string) error {
 | 
			
		||||
	m := "操作成功"
 | 
			
		||||
	if len(msg) > 0 && msg[0] != "" {
 | 
			
		||||
		m = msg[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send(200, m, "", data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Send400(data any, msg ...string) error {
 | 
			
		||||
	m := "参数错误"
 | 
			
		||||
	if len(msg) > 0 && msg[0] != "" {
 | 
			
		||||
		m = msg[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send(400, m, "", data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Send500(data any, msg ...string) error {
 | 
			
		||||
	m := "系统错误"
 | 
			
		||||
	if len(msg) > 0 && msg[0] != "" {
 | 
			
		||||
		m = msg[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Send(500, m, "", data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Ctx) Send(status uint32, msg, error string, data any) error {
 | 
			
		||||
	value := map[string]any{"status": status, "msg": msg, "err": error, "data": data}
 | 
			
		||||
	bs, err := json.Marshal(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = c.Write(bs)
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
package ndh
 | 
			
		||||
 | 
			
		||||
type Handler func(c *Ctx) error
 | 
			
		||||
@@ -1,5 +1,11 @@
 | 
			
		||||
package opt
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	Msg200 = "操作成功"
 | 
			
		||||
	Msg400 = "输入不正确"
 | 
			
		||||
	Msg500 = "发生错误"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	Debug bool
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@ import (
 | 
			
		||||
	"github.com/aws/aws-sdk-go-v2/credentials"
 | 
			
		||||
	"github.com/aws/aws-sdk-go-v2/service/s3"
 | 
			
		||||
	smithyendpoints "github.com/aws/smithy-go/endpoints"
 | 
			
		||||
	"github.com/loveuer/nf-disk/internal/tool"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"nf-disk/internal/tool"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type resolverV2 struct{}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								internal/tool/must.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								internal/tool/must.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package tool
 | 
			
		||||
 | 
			
		||||
import "github.com/loveuer/nf/nft/log"
 | 
			
		||||
 | 
			
		||||
func Must(errs ...error) {
 | 
			
		||||
	for _, err := range errs {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Panic(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user