diff --git a/api/chart.go b/api/chart.go index a2c8c60..158c2c4 100644 --- a/api/chart.go +++ b/api/chart.go @@ -36,21 +36,15 @@ func NewChart(b biz.ChartBiz) *ChartHandler { } func chartSearch(b biz.ChartBiz) web.HandlerFunc { - type Args struct { - Name string `json:"name" bind:"name"` - Dashboard string `json:"dashboard" bind:"dashboard"` - PageIndex int `json:"pageIndex" bind:"pageIndex"` - PageSize int `json:"pageSize" bind:"pageSize"` - } return func(ctx web.Context) (err error) { var ( - args = &Args{} + args = &model.ChartSearchArgs{} charts []*biz.Chart total int ) if err = ctx.Bind(args); err == nil { - charts, total, err = b.Search(args.Name, args.Dashboard, args.PageIndex, args.PageSize) + charts, total, err = b.Search(args) } if err != nil { diff --git a/api/event.go b/api/event.go index 5291814..a79d6c7 100644 --- a/api/event.go +++ b/api/event.go @@ -25,7 +25,7 @@ func NewEvent(b biz.EventBiz) *EventHandler { func eventSearch(b biz.EventBiz) web.HandlerFunc { return func(ctx web.Context) (err error) { var ( - args = &model.EventListArgs{} + args = &model.EventSearchArgs{} events []*biz.Event total int ) diff --git a/api/user.go b/api/user.go index 89ba38e..357614c 100644 --- a/api/user.go +++ b/api/user.go @@ -147,7 +147,7 @@ func userSetStatus(b biz.UserBiz) web.HandlerFunc { args := &Args{} err := ctx.Bind(args) if err == nil { - err = b.SetStatus(args.ID, args.Status) + err = b.SetStatus(args.ID, args.Status, ctx.User()) } return ajax(ctx, err) } @@ -163,7 +163,7 @@ func userModifyPassword(b biz.UserBiz) web.HandlerFunc { args := &Args{} err := ctx.Bind(args) if err == nil { - err = b.ModifyPassword(ctx.User().ID(), args.OldPassword, args.NewPassword) + err = b.ModifyPassword(args.OldPassword, args.NewPassword, ctx.User()) } return ajax(ctx, err) } @@ -174,8 +174,7 @@ func userModifyProfile(b biz.UserBiz) web.HandlerFunc { u := &biz.User{} err := ctx.Bind(u, true) if err == nil { - u.ID = ctx.User().ID() - err = b.ModifyProfile(u) + err = b.ModifyProfile(u, ctx.User()) } return ajax(ctx, err) } diff --git a/biz/chart.go b/biz/chart.go index f7dffe8..3d9d872 100644 --- a/biz/chart.go +++ b/biz/chart.go @@ -15,7 +15,7 @@ import ( ) type ChartBiz interface { - Search(title, dashboard string, pageIndex, pageSize int) (charts []*Chart, total int, err error) + Search(args *model.ChartSearchArgs) (charts []*Chart, total int, err error) Delete(id, title string, user web.User) (err error) Find(id string) (chart *Chart, err error) Batch(ids ...string) (charts []*model.Chart, err error) @@ -47,9 +47,9 @@ type chartBiz struct { eb EventBiz } -func (b *chartBiz) Search(title, dashboard string, pageIndex, pageSize int) (charts []*Chart, total int, err error) { +func (b *chartBiz) Search(args *model.ChartSearchArgs) (charts []*Chart, total int, err error) { var list []*model.Chart - list, total, err = b.d.ChartList(context.TODO(), title, dashboard, pageIndex, pageSize) + list, total, err = b.d.ChartSearch(context.TODO(), args) if err == nil { charts = make([]*Chart, len(list)) for i, c := range list { @@ -63,6 +63,7 @@ func (b *chartBiz) Create(chart *Chart, user web.User) (err error) { c := &model.Chart{ ID: createId(), CreatedAt: time.Now(), + CreatedBy: model.Operator{ID: user.ID(), Name: user.Name()}, } c.UpdatedAt = c.CreatedAt if err = copier.CopyWithOption(c, chart, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil { @@ -94,7 +95,7 @@ func (b *chartBiz) Find(id string) (chart *Chart, err error) { } func (b *chartBiz) Batch(ids ...string) (charts []*model.Chart, err error) { - charts, err = b.d.ChartBatch(context.TODO(), ids...) + charts, err = b.d.ChartGetBatch(context.TODO(), ids...) return } @@ -105,6 +106,8 @@ func (b *chartBiz) Update(chart *Chart, user web.User) (err error) { if err = copier.CopyWithOption(c, chart, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil { return err } + c.UpdatedBy.ID = user.ID() + c.UpdatedBy.Name = user.Name() err = b.d.ChartUpdate(context.TODO(), c) if err == nil { @@ -130,6 +133,9 @@ func (b *chartBiz) FindDashboard(name, key string) (dashboard *Dashboard, err er } func (b *chartBiz) UpdateDashboard(dashboard *model.Dashboard, user web.User) (err error) { + dashboard.UpdatedAt = time.Now() + dashboard.UpdatedBy.ID = user.ID() + dashboard.UpdatedBy.Name = user.Name() return b.d.DashboardUpdate(context.TODO(), dashboard) } @@ -360,6 +366,8 @@ type Chart struct { Options data.Map `json:"options,omitempty"` CreatedAt string `json:"createdAt,omitempty" copier:"-"` UpdatedAt string `json:"updatedAt,omitempty" copier:"-"` + CreatedBy model.Operator `json:"createdBy"` + UpdatedBy model.Operator `json:"updatedBy"` } func newChart(c *model.Chart) *Chart { diff --git a/biz/event.go b/biz/event.go index bc28a64..c84d9c8 100644 --- a/biz/event.go +++ b/biz/event.go @@ -67,7 +67,7 @@ func newEvent(e *model.Event) *Event { } type EventBiz interface { - Search(args *model.EventListArgs) (events []*Event, total int, err error) + Search(args *model.EventSearchArgs) (events []*Event, total int, err error) CreateRegistry(action EventAction, id, name string, user web.User) CreateNode(action EventAction, id, name string, user web.User) CreateNetwork(action EventAction, id, name string, user web.User) @@ -91,9 +91,9 @@ type eventBiz struct { d dao.Interface } -func (b *eventBiz) Search(args *model.EventListArgs) (events []*Event, total int, err error) { +func (b *eventBiz) Search(args *model.EventSearchArgs) (events []*Event, total int, err error) { var list []*model.Event - list, total, err = b.d.EventList(context.TODO(), args) + list, total, err = b.d.EventSearch(context.TODO(), args) if err == nil && len(list) > 0 { events = make([]*Event, len(list)) for i, e := range list { diff --git a/biz/registry.go b/biz/registry.go index 94ebb9b..bc03976 100644 --- a/biz/registry.go +++ b/biz/registry.go @@ -12,42 +12,6 @@ import ( "github.com/docker/docker/api/types" ) -type Registry struct { - ID string `json:"id,omitempty"` - Name string `json:"name" valid:"required"` - URL string `json:"url" valid:"required,url"` - Username string `json:"username" valid:"required"` - Password string `json:"password"` - CreatedAt string `json:"createdAt,omitempty"` - UpdatedAt string `json:"updatedAt,omitempty"` -} - -func newRegistry(r *model.Registry) *Registry { - if r == nil { - return nil - } - - return &Registry{ - ID: r.ID, - Name: r.Name, - URL: r.URL, - Username: r.Username, - CreatedAt: formatTime(r.CreatedAt), - UpdatedAt: formatTime(r.UpdatedAt), - //Password: r.Password, // omit password - } -} - -func (r *Registry) Convert() *model.Registry { - return &model.Registry{ - ID: r.ID, - Name: r.Name, - URL: r.URL, - Username: r.Username, - Password: r.Password, - } -} - type RegistryBiz interface { Search() ([]*Registry, error) Find(id string) (*Registry, error) @@ -71,6 +35,9 @@ func (b *registryBiz) Create(registry *Registry, user web.User) (err error) { r.ID = createId() r.CreatedAt = time.Now() r.UpdatedAt = r.CreatedAt + r.CreatedBy.ID = user.ID() + r.CreatedBy.Name = user.Name() + r.UpdatedBy = r.CreatedBy err = b.d.RegistryCreate(context.TODO(), r) if err == nil { @@ -80,7 +47,11 @@ func (b *registryBiz) Create(registry *Registry, user web.User) (err error) { } func (b *registryBiz) Update(registry *Registry, user web.User) (err error) { - err = b.d.RegistryUpdate(context.TODO(), registry.Convert()) + r := registry.Convert() + r.UpdatedAt = time.Now() + r.UpdatedBy.ID = user.ID() + r.UpdatedBy.Name = user.Name() + err = b.d.RegistryUpdate(context.TODO(), r) if err == nil { b.eb.CreateRegistry(EventActionUpdate, registry.ID, registry.Name, user) } @@ -89,7 +60,7 @@ func (b *registryBiz) Update(registry *Registry, user web.User) (err error) { func (b *registryBiz) Search() (registries []*Registry, err error) { var list []*model.Registry - if list, err = b.d.RegistryList(context.TODO()); err == nil { + if list, err = b.d.RegistryGetAll(context.TODO()); err == nil { for _, r := range list { registries = append(registries, newRegistry(r)) } @@ -130,3 +101,43 @@ func (b *registryBiz) Delete(id, name string, user web.User) (err error) { } return } + +type Registry struct { + ID string `json:"id,omitempty"` + Name string `json:"name" valid:"required"` + URL string `json:"url" valid:"required,url"` + Username string `json:"username" valid:"required"` + Password string `json:"password" copier:"-"` + CreatedAt string `json:"createdAt,omitempty" copier:"-"` + UpdatedAt string `json:"updatedAt,omitempty" copier:"-"` + CreatedBy model.Operator `json:"createdBy" bson:"created_by"` + UpdatedBy model.Operator `json:"updatedBy" bson:"updated_by"` +} + +func newRegistry(r *model.Registry) *Registry { + if r == nil { + return nil + } + + return &Registry{ + ID: r.ID, + Name: r.Name, + URL: r.URL, + Username: r.Username, + CreatedAt: formatTime(r.CreatedAt), + UpdatedAt: formatTime(r.UpdatedAt), + CreatedBy: r.CreatedBy, + UpdatedBy: r.UpdatedBy, + //Password: r.Password, // omit password + } +} + +func (r *Registry) Convert() *model.Registry { + return &model.Registry{ + ID: r.ID, + Name: r.Name, + URL: r.URL, + Username: r.Username, + Password: r.Password, + } +} diff --git a/biz/role.go b/biz/role.go index c1e1d35..fa61210 100644 --- a/biz/role.go +++ b/biz/role.go @@ -10,12 +10,14 @@ import ( ) type Role struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty" valid:"required"` - Description string `json:"desc,omitempty"` - Perms []string `json:"perms,omitempty"` - CreatedAt string `json:"createdAt,omitempty"` - UpdatedAt string `json:"updatedAt,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty" valid:"required"` + Description string `json:"desc,omitempty"` + Perms []string `json:"perms,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` + CreatedBy model.Operator `json:"createdBy" bson:"created_by"` + UpdatedBy model.Operator `json:"updatedBy" bson:"updated_by"` } func newRole(r *model.Role) *Role { @@ -26,6 +28,8 @@ func newRole(r *model.Role) *Role { Perms: r.Perms, CreatedAt: formatTime(r.CreatedAt), UpdatedAt: formatTime(r.UpdatedAt), + CreatedBy: r.CreatedBy, + UpdatedBy: r.UpdatedBy, } } @@ -48,7 +52,7 @@ type roleBiz struct { func (b *roleBiz) Search(name string) (roles []*Role, err error) { var list []*model.Role - list, err = b.d.RoleList(context.TODO(), name) + list, err = b.d.RoleSearch(context.TODO(), name) if err == nil { for _, r := range list { roles = append(roles, newRole(r)) @@ -98,6 +102,8 @@ func (b *roleBiz) Update(role *Role, user web.User) (err error) { Perms: role.Perms, UpdatedAt: time.Now(), } + r.UpdatedBy.ID = user.ID() + r.UpdatedBy.Name = user.Name() err = b.d.RoleUpdate(context.TODO(), r) if err == nil { b.eb.CreateRole(EventActionUpdate, role.ID, role.Name, user) diff --git a/biz/setting.go b/biz/setting.go index f68dc06..e4423b1 100644 --- a/biz/setting.go +++ b/biz/setting.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "strconv" + "time" "github.com/cuigh/auxo/data" "github.com/cuigh/auxo/net/web" @@ -45,7 +46,7 @@ func (b *settingBiz) Find(id string) (options data.Map, err error) { // Load returns settings of swirl. If not found, default settings will be returned. func (b *settingBiz) Load() (options data.Map, err error) { var settings []*model.Setting - settings, err = b.d.SettingList(context.TODO()) + settings, err = b.d.SettingGetAll(context.TODO()) if err != nil { return } @@ -58,7 +59,13 @@ func (b *settingBiz) Load() (options data.Map, err error) { } func (b *settingBiz) Save(id string, options data.Map, user web.User) (err error) { - err = b.d.SettingUpdate(context.TODO(), id, b.toOptions(options)) + setting := &model.Setting{ + ID: id, + Options: b.toOptions(options), + UpdatedAt: time.Now(), + UpdatedBy: model.Operator{ID: user.ID(), Name: user.Name()}, + } + err = b.d.SettingUpdate(context.TODO(), setting) if err == nil && user != nil { b.eb.CreateSetting(EventActionUpdate, user) } diff --git a/biz/stack.go b/biz/stack.go index 70f72aa..5431aaf 100644 --- a/biz/stack.go +++ b/biz/stack.go @@ -3,6 +3,7 @@ package biz import ( "context" "strings" + "time" "github.com/cuigh/auxo/errors" "github.com/cuigh/auxo/net/web" @@ -46,7 +47,7 @@ func (b *stackBiz) Search(name, filter string) (stacks []*Stack, err error) { } // load stack definitions - internalStacks, err = b.s.StackList(context.TODO()) + internalStacks, err = b.s.StackGetAll(context.TODO()) if err != nil { return } @@ -110,9 +111,14 @@ func (b *stackBiz) Create(s *Stack, user web.User) (err error) { stack := &model.Stack{ Name: s.Name, Content: s.Content, - CreatedBy: user.ID(), - UpdatedBy: user.ID(), + CreatedAt: time.Now(), + CreatedBy: model.Operator{ + ID: user.ID(), + Name: user.Name(), + }, } + stack.UpdatedAt = stack.CreatedAt + stack.UpdatedBy = stack.CreatedBy err = b.s.StackCreate(context.TODO(), stack) if err == nil { b.eb.CreateStack(EventActionCreate, stack.Name, user) @@ -128,8 +134,10 @@ func (b *stackBiz) Update(s *Stack, user web.User) (err error) { stack := &model.Stack{ Name: s.Name, Content: s.Content, - UpdatedBy: user.ID(), + UpdatedAt: time.Now(), } + stack.UpdatedBy.ID = user.ID() + stack.UpdatedBy.Name = user.Name() err = b.s.StackUpdate(context.TODO(), stack) if err == nil { b.eb.CreateStack(EventActionUpdate, stack.Name, user) @@ -169,7 +177,7 @@ func (b *stackBiz) Deploy(name string, user web.User) (err error) { return err } - registries, err := b.s.RegistryList(context.TODO()) + registries, err := b.s.RegistryGetAll(context.TODO()) if err != nil { return err } @@ -194,15 +202,15 @@ func (b *stackBiz) Deploy(name string, user web.User) (err error) { } type Stack struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Content string `json:"content,omitempty"` - CreatedBy string `json:"createdBy,omitempty"` - CreatedAt string `json:"createdAt,omitempty"` - UpdatedBy string `json:"updatedBy,omitempty"` - UpdatedAt string `json:"updatedAt,omitempty"` - Services []string `json:"services,omitempty"` - Internal bool `json:"internal"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Content string `json:"content,omitempty"` + Services []string `json:"services,omitempty"` + Internal bool `json:"internal"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` + CreatedBy model.Operator `json:"createdBy,omitempty"` + UpdatedBy model.Operator `json:"updatedBy,omitempty"` } func newStack(s *model.Stack) *Stack { @@ -210,10 +218,10 @@ func newStack(s *model.Stack) *Stack { ID: s.Name, Name: s.Name, Content: s.Content, - CreatedBy: s.CreatedBy, - CreatedAt: formatTime(s.CreatedAt), - UpdatedBy: s.UpdatedBy, - UpdatedAt: formatTime(s.UpdatedAt), Internal: true, + CreatedAt: formatTime(s.CreatedAt), + UpdatedAt: formatTime(s.UpdatedAt), + CreatedBy: s.CreatedBy, + UpdatedBy: s.UpdatedBy, } } diff --git a/biz/user.go b/biz/user.go index 26425be..4198bfc 100644 --- a/biz/user.go +++ b/biz/user.go @@ -28,38 +28,6 @@ const ( UserStatusActive = 1 ) -type User struct { - ID string `json:"id"` - Name string `json:"name" valid:"required"` - LoginName string `json:"loginName" valid:"required"` - Password string `json:"password,omitempty"` - Email string `json:"email" valid:"required"` - Admin bool `json:"admin"` - Type string `json:"type"` - Status int32 `json:"status,omitempty"` - Roles []string `json:"roles,omitempty"` - CreatedAt string `bson:"created_at" json:"createdAt,omitempty"` - UpdatedAt string `bson:"updated_at" json:"updatedAt,omitempty"` -} - -type UserPrivacy struct { - ID string - Name string - Password string - Salt string - Type string - Status int32 -} - -func newUser(u *model.User) *User { - user := &User{ - CreatedAt: formatTime(u.CreatedAt), - UpdatedAt: formatTime(u.UpdatedAt), - } - _ = copier.CopyWithOption(user, u, copier.Option{IgnoreEmpty: true, DeepCopy: true}) - return user -} - type UserBiz interface { Search(name, loginName, filter string, pageIndex, pageSize int) (users []*User, total int, err error) Create(user *User, ctxUser web.User) (id string, err error) @@ -69,9 +37,9 @@ type UserBiz interface { FindPrivacy(loginName string) (privacy *UserPrivacy, err error) Count() (count int, err error) Delete(id, name string, user web.User) (err error) - SetStatus(id string, status int32) (err error) - ModifyPassword(id, pwd, salt string) (err error) - ModifyProfile(user *User) (err error) + SetStatus(id string, status int32, user web.User) (err error) + ModifyPassword(oldPwd, newPwd string, user web.User) (err error) + ModifyProfile(user *User, ctxUser web.User) (err error) } func NewUser(d dao.Interface, eb EventBiz) UserBiz { @@ -104,7 +72,7 @@ func (b *userBiz) Search(name, loginName, filter string, pageIndex, pageSize int args.Status = UserStatusBlocked } - list, total, err = b.d.UserList(context.TODO(), args) + list, total, err = b.d.UserSearch(context.TODO(), args) if err == nil { for _, u := range list { users = append(users, newUser(u)) @@ -115,7 +83,7 @@ func (b *userBiz) Search(name, loginName, filter string, pageIndex, pageSize int func (b *userBiz) FindByID(id string) (user *User, err error) { var u *model.User - u, err = b.d.UserGetByID(context.TODO(), id) + u, err = b.d.UserGet(context.TODO(), id) if u != nil { user = newUser(u) } @@ -158,8 +126,10 @@ func (b *userBiz) Create(u *User, ctxUser web.User) (id string, err error) { Status: UserStatusActive, Roles: u.Roles, CreatedAt: time.Now(), + CreatedBy: model.Operator{ID: ctxUser.ID(), Name: ctxUser.Name()}, } user.UpdatedAt = user.CreatedAt + user.UpdatedBy = user.CreatedBy if user.Type == UserTypeInternal { user.Password, user.Salt, err = passwd.Generate(u.Password) if err != nil { @@ -185,14 +155,22 @@ func (b *userBiz) Update(u *User, ctxUser web.User) (err error) { Roles: u.Roles, UpdatedAt: time.Now(), } + user.UpdatedBy.ID = ctxUser.ID() + user.UpdatedBy.Name = ctxUser.Name() if err = b.d.UserUpdate(context.TODO(), user); err == nil { b.eb.CreateUser(EventActionUpdate, u.LoginName, u.Name, ctxUser) } return } -func (b *userBiz) SetStatus(id string, status int32) (err error) { - return b.d.UserSetStatus(context.TODO(), id, status) +func (b *userBiz) SetStatus(id string, status int32, user web.User) (err error) { + u := &model.User{ + ID: id, + Status: status, + UpdatedAt: time.Now(), + UpdatedBy: model.Operator{ID: user.ID(), Name: user.Name()}, + } + return b.d.UserUpdateStatus(context.TODO(), u) } func (b *userBiz) Delete(id, name string, user web.User) (err error) { @@ -203,38 +181,39 @@ func (b *userBiz) Delete(id, name string, user web.User) (err error) { return } -func (b *userBiz) ModifyPassword(id, oldPwd, newPwd string) (err error) { - var ( - user *model.User - pwd, salt string - ) - - user, err = b.d.UserGetByID(context.TODO(), id) +func (b *userBiz) ModifyPassword(oldPwd, newPwd string, user web.User) (err error) { + var u *model.User + u, err = b.d.UserGet(context.TODO(), user.ID()) if err != nil { return err - } else if user == nil { - return errors.Format("user not found: %s", id) + } else if u == nil { + return errors.Format("user not found: %s", user.ID()) } - if !passwd.Validate(oldPwd, user.Password, user.Salt) { + if !passwd.Validate(oldPwd, u.Password, u.Salt) { return errors.Coded(misc.ErrOldPasswordIncorrect, "current password is incorrect") } - pwd, salt, err = passwd.Generate(newPwd) + u.Password, u.Salt, err = passwd.Generate(newPwd) if err != nil { return } - err = b.d.UserModifyPassword(context.TODO(), id, pwd, salt) + u.UpdatedAt = time.Now() + u.UpdatedBy.ID = user.ID() + u.UpdatedBy.Name = user.Name() + err = b.d.UserUpdatePassword(context.TODO(), u) return } -func (b *userBiz) ModifyProfile(user *User) (err error) { - return b.d.UserModifyProfile(context.TODO(), &model.User{ - ID: user.ID, - Name: user.Name, - LoginName: user.LoginName, - Email: user.Email, +func (b *userBiz) ModifyProfile(u *User, user web.User) (err error) { + return b.d.UserUpdateProfile(context.TODO(), &model.User{ + ID: user.ID(), + Name: u.Name, + LoginName: u.LoginName, + Email: u.Email, + UpdatedAt: time.Now(), + UpdatedBy: model.Operator{ID: user.ID(), Name: user.Name()}, }) } @@ -259,3 +238,37 @@ func (b *userBiz) UpdateSession(id string) (token string, err error) { func (b *userBiz) GetSession(token string) (session *model.Session, err error) { return b.d.SessionGet(context.TODO(), token) } + +type User struct { + ID string `json:"id"` + Name string `json:"name" valid:"required"` + LoginName string `json:"loginName" valid:"required"` + Password string `json:"password,omitempty"` + Email string `json:"email" valid:"required"` + Admin bool `json:"admin"` + Type string `json:"type"` + Status int32 `json:"status,omitempty"` + Roles []string `json:"roles,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` + CreatedBy model.Operator `json:"createdBy"` + UpdatedBy model.Operator `json:"updatedBy"` +} + +type UserPrivacy struct { + ID string + Name string + Password string + Salt string + Type string + Status int32 +} + +func newUser(u *model.User) *User { + user := &User{ + CreatedAt: formatTime(u.CreatedAt), + UpdatedAt: formatTime(u.UpdatedAt), + } + _ = copier.CopyWithOption(user, u, copier.Option{IgnoreEmpty: true, DeepCopy: true}) + return user +} diff --git a/dao/bolt/bolt.go b/dao/bolt/bolt.go index 1d6ab1b..4355fc1 100644 --- a/dao/bolt/bolt.go +++ b/dao/bolt/bolt.go @@ -1,19 +1,23 @@ package bolt import ( - "encoding/json" "path/filepath" "strings" "github.com/boltdb/bolt" "github.com/cuigh/auxo/errors" "github.com/cuigh/auxo/log" + "go.mongodb.org/mongo-driver/bson" ) -type Value []byte +var ErrNoRecords = errors.New("no records") -func (v Value) Unmarshal(i interface{}) error { - return json.Unmarshal([]byte(v), i) +func encode(v interface{}) ([]byte, error) { + return bson.Marshal(v) +} + +func decode(d []byte, v interface{}) error { + return bson.Unmarshal(d, v) } // Dao implements dao.Interface interface. @@ -52,13 +56,9 @@ func (d *Dao) Init() error { }) } -func (d *Dao) Close() { - d.db.Close() -} - -func (d *Dao) update(bucket, key string, value interface{}) error { +func (d *Dao) replace(bucket, key string, value interface{}) error { return d.db.Update(func(tx *bolt.Tx) error { - buf, err := json.Marshal(value) + buf, err := encode(value) if err != nil { return err } @@ -68,6 +68,26 @@ func (d *Dao) update(bucket, key string, value interface{}) error { }) } +func (d *Dao) update(bucket, key string, oldValue interface{}, newValue func() interface{}) error { + return d.db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(bucket)) + data := b.Get([]byte(key)) + if data == nil { + return ErrNoRecords + } + + if err := decode(data, oldValue); err != nil { + return err + } + + buf, err := encode(newValue()) + if err != nil { + return err + } + return b.Put([]byte(key), buf) + }) +} + func (d *Dao) delete(bucket, key string) error { return d.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(bucket)) @@ -75,12 +95,28 @@ func (d *Dao) delete(bucket, key string) error { }) } -func (d *Dao) get(bucket, key string) (val Value, err error) { +func (d *Dao) get(bucket, key string, value interface{}) error { + return d.db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(bucket)) + if b != nil { + if data := b.Get([]byte(key)); data != nil { + return decode(data, value) + } + } + return ErrNoRecords + }) +} + +func (d Dao) find(bucket string, value interface{}, matcher func() bool) (found bool, err error) { err = d.db.View(func(tx *bolt.Tx) error { - if b := tx.Bucket([]byte(bucket)); b != nil { - v := b.Get([]byte(key)) - if v != nil { - val = Value(v) + c := tx.Bucket([]byte(bucket)).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if err = decode(v, value); err != nil { + return err + } + if matcher() { + found = true + return nil } } return nil @@ -98,21 +134,21 @@ func (d *Dao) count(bucket string) (count int, err error) { return } -func (d *Dao) each(bucket string, fn func(v Value) error) (err error) { +func (d *Dao) each(bucket string, fn func(v []byte) error) (err error) { return d.db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(bucket)) return b.ForEach(func(k, v []byte) error { - return fn(Value(v)) + return fn(v) }) }) } -func (d *Dao) slice(bucket string, fn func(v Value) error, keys ...string) (err error) { +func (d *Dao) slice(bucket string, fn func(v []byte) error, keys ...string) (err error) { return d.db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(bucket)) for _, key := range keys { if data := b.Get([]byte(key)); data != nil { - if err = fn(Value(data)); err != nil { + if err = fn(data); err != nil { return err } } @@ -121,13 +157,6 @@ func (d *Dao) slice(bucket string, fn func(v Value) error, keys ...string) (err }) } -func (d *Dao) batch(bucket string, fn func(b *bolt.Bucket) error) (err error) { - return d.db.Batch(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(bucket)) - return fn(b) - }) -} - func matchAny(s string, list ...string) bool { s = strings.ToLower(s) for _, v := range list { @@ -137,10 +166,3 @@ func matchAny(s string, list ...string) bool { } return false } - -// itob returns an 8-byte big endian representation of v. -//func itob(i uint64) []byte { -// b := make([]byte, 8) -// binary.BigEndian.PutUint64(b, i) -// return b -//} diff --git a/dao/bolt/chart.go b/dao/bolt/chart.go index 2b94446..21fca69 100644 --- a/dao/bolt/chart.go +++ b/dao/bolt/chart.go @@ -8,17 +8,21 @@ import ( "github.com/cuigh/swirl/model" ) -func (d *Dao) ChartList(ctx context.Context, title, dashboard string, pageIndex, pageSize int) (charts []*model.Chart, count int, err error) { - err = d.each("chart", func(v Value) error { +const ( + Chart = "chart" + Dashboard = "dashboard" +) + +func (d *Dao) ChartSearch(ctx context.Context, args *model.ChartSearchArgs) (charts []*model.Chart, count int, err error) { + err = d.each(Chart, func(v []byte) error { chart := &model.Chart{} - err = v.Unmarshal(chart) - if err == nil { + if err = decode(v, chart); err == nil { match := true - if title != "" { - match = matchAny(title, chart.Title) + if args.Title != "" { + match = matchAny(args.Title, chart.Title) } - if match && dashboard != "" { - match = matchAny(chart.Dashboard, dashboard, "") + if match && args.Dashboard != "" { + match = matchAny(chart.Dashboard, args.Dashboard, "") } if match { charts = append(charts, chart) @@ -31,62 +35,65 @@ func (d *Dao) ChartList(ctx context.Context, title, dashboard string, pageIndex, sort.Slice(charts, func(i, j int) bool { return charts[i].CreatedAt.After(charts[j].UpdatedAt) }) - start, end := misc.Page(count, pageIndex, pageSize) + start, end := misc.Page(count, args.PageIndex, args.PageSize) charts = charts[start:end] } return } func (d *Dao) ChartCreate(ctx context.Context, chart *model.Chart) (err error) { - return d.update("chart", chart.ID, chart) + return d.replace(Chart, chart.ID, chart) } func (d *Dao) ChartGet(ctx context.Context, name string) (chart *model.Chart, err error) { - var v Value - v, err = d.get("chart", name) - if err == nil && v != nil { - chart = &model.Chart{} - err = v.Unmarshal(chart) + chart = &model.Chart{} + err = d.get(Chart, name, chart) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + chart = nil } return } -func (d *Dao) ChartBatch(ctx context.Context, names ...string) (charts []*model.Chart, err error) { - err = d.slice("chart", func(v Value) error { +func (d *Dao) ChartGetBatch(ctx context.Context, ids ...string) (charts []*model.Chart, err error) { + err = d.slice(Chart, func(v []byte) error { chart := &model.Chart{} - err = v.Unmarshal(chart) - if err == nil { + if err = decode(v, chart); err == nil { charts = append(charts, chart) } return err - }, names...) + }, ids...) return } func (d *Dao) ChartUpdate(ctx context.Context, chart *model.Chart) (err error) { - return d.update("chart", chart.ID, chart) + old := &model.Chart{} + return d.update(Chart, chart.ID, old, func() interface{} { + chart.CreatedAt = old.CreatedAt + chart.CreatedBy = old.CreatedBy + return chart + }) } func (d *Dao) ChartDelete(ctx context.Context, name string) (err error) { - return d.delete("chart", name) + return d.delete(Chart, name) } func (d *Dao) DashboardGet(ctx context.Context, name, key string) (dashboard *model.Dashboard, err error) { - cd := &model.Dashboard{ + dashboard = &model.Dashboard{ Name: name, Key: key, } - - var v Value - v, err = d.get("dashboard", cd.ID()) - if v != nil { - if err = v.Unmarshal(cd); err == nil { - return cd, nil - } + err = d.get(Dashboard, dashboard.ID(), dashboard) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + dashboard = nil } - return nil, err + return } func (d *Dao) DashboardUpdate(ctx context.Context, dashboard *model.Dashboard) (err error) { - return d.update("dashboard", dashboard.ID(), dashboard) + return d.replace(Dashboard, dashboard.ID(), dashboard) } diff --git a/dao/bolt/event.go b/dao/bolt/event.go index 8a0002c..199a095 100644 --- a/dao/bolt/event.go +++ b/dao/bolt/event.go @@ -8,10 +8,12 @@ import ( "github.com/cuigh/swirl/model" ) -func (d *Dao) EventList(ctx context.Context, args *model.EventListArgs) (events []*model.Event, count int, err error) { - err = d.each("event", func(v Value) error { +const Event = "event" + +func (d *Dao) EventSearch(ctx context.Context, args *model.EventSearchArgs) (events []*model.Event, count int, err error) { + err = d.each(Event, func(v []byte) error { event := &model.Event{} - err = v.Unmarshal(event) + err = decode(v, event) if err != nil { return err } @@ -21,7 +23,7 @@ func (d *Dao) EventList(ctx context.Context, args *model.EventListArgs) (events match = matchAny(args.Name, event.Name) } if match && args.Type != "" { - match = string(event.Type) == args.Type + match = event.Type == args.Type } if match { @@ -41,5 +43,5 @@ func (d *Dao) EventList(ctx context.Context, args *model.EventListArgs) (events } func (d *Dao) EventCreate(ctx context.Context, event *model.Event) (err error) { - return d.update("event", event.ID.Hex(), event) + return d.replace(Event, event.ID.Hex(), event) } diff --git a/dao/bolt/registry.go b/dao/bolt/registry.go index 11f8061..24f16c3 100644 --- a/dao/bolt/registry.go +++ b/dao/bolt/registry.go @@ -2,51 +2,32 @@ package bolt import ( "context" - "encoding/json" - "time" - "github.com/boltdb/bolt" - "github.com/cuigh/auxo/errors" "github.com/cuigh/swirl/model" ) +const Registry = "registry" + func (d *Dao) RegistryCreate(ctx context.Context, registry *model.Registry) (err error) { - return d.update("registry", registry.ID, registry) + return d.replace(Registry, registry.ID, registry) } func (d *Dao) RegistryUpdate(ctx context.Context, registry *model.Registry) (err error) { - return d.batch("registry", func(b *bolt.Bucket) error { - data := b.Get([]byte(registry.ID)) - if data == nil { - return errors.New("registry not found: " + registry.ID) + old := &model.Registry{} + return d.update(Registry, registry.ID, old, func() interface{} { + registry.CreatedAt = old.CreatedAt + registry.CreatedBy = old.CreatedBy + if registry.Password == "" { + registry.Password = old.Password } - - r := &model.Registry{} - err = json.Unmarshal(data, r) - if err != nil { - return err - } - - r.Name = registry.Name - r.URL = registry.URL - r.Username = registry.Username - if registry.Password != "" { - r.Password = registry.Password - } - r.UpdatedAt = time.Now() - data, err = json.Marshal(r) - if err != nil { - return err - } - - return b.Put([]byte(registry.ID), data) + return registry }) } -func (d *Dao) RegistryList(ctx context.Context) (registries []*model.Registry, err error) { - err = d.each("registry", func(v Value) error { +func (d *Dao) RegistryGetAll(ctx context.Context) (registries []*model.Registry, err error) { + err = d.each(Registry, func(v []byte) error { r := &model.Registry{} - err = v.Unmarshal(r) + err = decode(v, r) if err != nil { return err } @@ -57,37 +38,25 @@ func (d *Dao) RegistryList(ctx context.Context) (registries []*model.Registry, e } func (d *Dao) RegistryGet(ctx context.Context, id string) (registry *model.Registry, err error) { - var v Value - v, err = d.get("registry", id) - if err == nil { - if v != nil { - registry = &model.Registry{} - err = v.Unmarshal(registry) - } + registry = &model.Registry{} + err = d.get(Registry, id, registry) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + registry = nil } return } func (d *Dao) RegistryGetByURL(ctx context.Context, url string) (registry *model.Registry, err error) { - err = d.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte("registry")) - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - r := &model.Registry{} - err = json.Unmarshal(v, r) - if err != nil { - return err - } - if r.URL == url { - registry = r - return nil - } - } - return nil - }) - return + r := &model.Registry{} + found, err := d.find(Registry, r, func() bool { return r.URL == url }) + if found { + return r, nil + } + return nil, err } func (d *Dao) RegistryDelete(ctx context.Context, id string) (err error) { - return d.delete("registry", id) + return d.delete(Registry, id) } diff --git a/dao/bolt/role.go b/dao/bolt/role.go index 6c42961..1f47414 100644 --- a/dao/bolt/role.go +++ b/dao/bolt/role.go @@ -2,18 +2,16 @@ package bolt import ( "context" - "encoding/json" - "time" - "github.com/boltdb/bolt" - "github.com/cuigh/auxo/errors" "github.com/cuigh/swirl/model" ) -func (d *Dao) RoleList(ctx context.Context, name string) (roles []*model.Role, err error) { - err = d.each("role", func(v Value) error { +const Role = "role" + +func (d *Dao) RoleSearch(ctx context.Context, name string) (roles []*model.Role, err error) { + err = d.each(Role, func(v []byte) error { role := &model.Role{} - err = v.Unmarshal(role) + err = decode(v, role) if err != nil { return err } @@ -27,47 +25,29 @@ func (d *Dao) RoleList(ctx context.Context, name string) (roles []*model.Role, e } func (d *Dao) RoleCreate(ctx context.Context, role *model.Role) (err error) { - return d.update("role", role.ID, role) + return d.replace(Role, role.ID, role) } func (d *Dao) RoleGet(ctx context.Context, id string) (role *model.Role, err error) { - var v Value - v, err = d.get("role", id) - if err == nil { - if v != nil { - role = &model.Role{} - err = v.Unmarshal(role) - } + role = &model.Role{} + err = d.get(Role, id, role) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + role = nil } return } func (d *Dao) RoleUpdate(ctx context.Context, role *model.Role) (err error) { - return d.batch("role", func(b *bolt.Bucket) error { - data := b.Get([]byte(role.ID)) - if data == nil { - return errors.New("role not found: " + role.ID) - } - - r := &model.Role{} - err = json.Unmarshal(data, r) - if err != nil { - return err - } - - r.Name = role.Name - r.Description = role.Description - r.Perms = role.Perms - r.UpdatedAt = time.Now() - data, err = json.Marshal(r) - if err != nil { - return err - } - - return b.Put([]byte(role.ID), data) + old := &model.Registry{} + return d.update(Role, role.ID, old, func() interface{} { + role.CreatedAt = old.CreatedAt + role.CreatedBy = old.CreatedBy + return role }) } func (d *Dao) RoleDelete(ctx context.Context, id string) (err error) { - return d.delete("role", id) + return d.delete(Role, id) } diff --git a/dao/bolt/setting.go b/dao/bolt/setting.go index 5872c68..7c2ef61 100644 --- a/dao/bolt/setting.go +++ b/dao/bolt/setting.go @@ -2,15 +2,16 @@ package bolt import ( "context" - "time" "github.com/cuigh/swirl/model" ) -func (d *Dao) SettingList(ctx context.Context) (settings []*model.Setting, err error) { - err = d.each("setting", func(v Value) error { +const Setting = "setting" + +func (d *Dao) SettingGetAll(ctx context.Context) (settings []*model.Setting, err error) { + err = d.each(Setting, func(v []byte) error { s := &model.Setting{} - err = v.Unmarshal(s) + err = decode(v, s) if err != nil { return err } @@ -22,20 +23,16 @@ func (d *Dao) SettingList(ctx context.Context) (settings []*model.Setting, err e } func (d *Dao) SettingGet(ctx context.Context, id string) (setting *model.Setting, err error) { - var v Value - v, err = d.get("setting", id) - if err == nil && v != nil { - setting = &model.Setting{} - err = v.Unmarshal(setting) + setting = &model.Setting{} + err = d.get(Setting, id, setting) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + setting = nil } return } -func (d *Dao) SettingUpdate(ctx context.Context, id string, options []*model.SettingOption) (err error) { - setting := &model.Setting{ - ID: id, - Options: options, - UpdatedAt: time.Now(), - } - return d.update("setting", id, setting) +func (d *Dao) SettingUpdate(ctx context.Context, setting *model.Setting) (err error) { + return d.replace(Setting, setting.ID, setting) } diff --git a/dao/bolt/stack.go b/dao/bolt/stack.go index 6f508e3..d2a212a 100644 --- a/dao/bolt/stack.go +++ b/dao/bolt/stack.go @@ -2,18 +2,16 @@ package bolt import ( "context" - "encoding/json" - "time" - "github.com/boltdb/bolt" - "github.com/cuigh/auxo/errors" "github.com/cuigh/swirl/model" ) -func (d *Dao) StackList(ctx context.Context) (stacks []*model.Stack, err error) { - err = d.each("stack", func(v Value) error { +const Stack = "stack" + +func (d *Dao) StackGetAll(ctx context.Context) (stacks []*model.Stack, err error) { + err = d.each(Stack, func(v []byte) error { stack := &model.Stack{} - err = v.Unmarshal(stack) + err = decode(v, stack) if err == nil { stacks = append(stacks, stack) } @@ -23,48 +21,29 @@ func (d *Dao) StackList(ctx context.Context) (stacks []*model.Stack, err error) } func (d *Dao) StackCreate(ctx context.Context, stack *model.Stack) (err error) { - stack.CreatedAt = time.Now() - stack.UpdatedAt = stack.CreatedAt - return d.update("stack", stack.Name, stack) + return d.replace(Stack, stack.Name, stack) } func (d *Dao) StackGet(ctx context.Context, name string) (stack *model.Stack, err error) { - var v Value - v, err = d.get("stack", name) - if err == nil { - if v != nil { - stack = &model.Stack{} - err = v.Unmarshal(stack) - } + stack = &model.Stack{} + err = d.get(Stack, name, stack) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + stack = nil } return } func (d *Dao) StackUpdate(ctx context.Context, stack *model.Stack) (err error) { - return d.batch("stack", func(b *bolt.Bucket) error { - data := b.Get([]byte(stack.Name)) - if data == nil { - return errors.New("stack not found: " + stack.Name) - } - - s := &model.Stack{} - err = json.Unmarshal(data, s) - if err != nil { - return err - } - - s.Content = stack.Content - s.UpdatedBy = stack.UpdatedBy - s.UpdatedAt = time.Now() - data, err = json.Marshal(s) - if err != nil { - return err - } - - return b.Put([]byte(stack.Name), data) + old := &model.Stack{} + return d.update(Role, stack.Name, old, func() interface{} { + stack.CreatedAt = old.CreatedAt + stack.CreatedBy = old.CreatedBy + return stack }) } func (d *Dao) StackDelete(ctx context.Context, name string) (err error) { - return d.delete("stack", name) + return d.delete(Stack, name) } diff --git a/dao/bolt/user.go b/dao/bolt/user.go index 47bde48..aa15267 100644 --- a/dao/bolt/user.go +++ b/dao/bolt/user.go @@ -2,48 +2,55 @@ package bolt import ( "context" - "encoding/json" - "time" - "github.com/boltdb/bolt" - "github.com/cuigh/auxo/errors" "github.com/cuigh/swirl/misc" "github.com/cuigh/swirl/model" ) +const User = "user" +const Session = "session" + func (d *Dao) UserCount(ctx context.Context) (count int, err error) { - return d.count("user") + return d.count(User) } func (d *Dao) UserCreate(ctx context.Context, user *model.User) (err error) { - return d.update("user", user.ID, user) + return d.replace(User, user.ID, user) } func (d *Dao) UserUpdate(ctx context.Context, user *model.User) (err error) { - return d.userUpdate(user.ID, func(u *model.User) { - u.Name = user.Name - u.LoginName = user.LoginName - u.Email = user.Email - u.Admin = user.Admin - u.Type = user.Type - u.Roles = user.Roles + old := &model.User{} + return d.update(User, user.ID, old, func() interface{} { + old.Name = user.Name + old.LoginName = user.LoginName + old.Email = user.Email + old.Admin = user.Admin + old.Type = user.Type + old.Roles = user.Roles + old.UpdatedAt = user.UpdatedAt + old.UpdatedBy = user.UpdatedBy + return old }) } -func (d *Dao) UserSetStatus(ctx context.Context, id string, status int32) (err error) { - return d.userUpdate(id, func(u *model.User) { - u.Status = status +func (d *Dao) UserUpdateStatus(ctx context.Context, user *model.User) (err error) { + old := &model.User{} + return d.update(User, user.ID, old, func() interface{} { + old.Status = user.Status + old.UpdatedAt = user.UpdatedAt + old.UpdatedBy = user.UpdatedBy + return old }) } func (d *Dao) UserDelete(ctx context.Context, id string) (err error) { - return d.delete("user", id) + return d.delete(User, id) } -func (d *Dao) UserList(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) { - err = d.each("user", func(v Value) error { +func (d *Dao) UserSearch(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) { + err = d.each(User, func(v []byte) error { user := &model.User{} - err = v.Unmarshal(user) + err = decode(v, user) if err != nil { return err } @@ -75,97 +82,58 @@ func (d *Dao) UserList(ctx context.Context, args *model.UserSearchArgs) (users [ return } -func (d *Dao) UserGetByID(ctx context.Context, id string) (user *model.User, err error) { - var v Value - v, err = d.get("user", id) - if err == nil { - if v != nil { - user = &model.User{} - err = v.Unmarshal(user) - } +func (d *Dao) UserGet(ctx context.Context, id string) (user *model.User, err error) { + user = &model.User{} + err = d.get(User, id, user) + if err == ErrNoRecords { + return nil, nil + } else if err != nil { + user = nil } return } func (d *Dao) UserGetByName(ctx context.Context, loginName string) (user *model.User, err error) { - err = d.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte("user")) - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - u := &model.User{} - err = json.Unmarshal(v, u) - if err != nil { - return err - } - if u.LoginName == loginName { - user = u - return nil - } - } - return nil - }) - return + u := &model.User{} + found, err := d.find(User, u, func() bool { return u.LoginName == loginName }) + if found { + return u, nil + } + return nil, err } -func (d *Dao) UserModifyProfile(ctx context.Context, user *model.User) (err error) { - return d.userUpdate(user.ID, func(u *model.User) { - u.Name = user.Name - u.LoginName = user.LoginName - u.Email = user.Email +func (d *Dao) UserUpdateProfile(ctx context.Context, user *model.User) (err error) { + old := &model.User{} + return d.update(User, user.ID, old, func() interface{} { + old.Name = user.Name + old.LoginName = user.LoginName + old.Email = user.Email + old.UpdatedAt = user.UpdatedAt + old.UpdatedBy = user.UpdatedBy + return old }) } -func (d *Dao) UserModifyPassword(ctx context.Context, id, pwd, salt string) (err error) { - return d.userUpdate(id, func(u *model.User) { - u.Password = pwd - u.Salt = salt - }) -} - -func (d *Dao) userUpdate(id string, decorator func(u *model.User)) (err error) { - return d.batch("user", func(b *bolt.Bucket) error { - data := b.Get([]byte(id)) - if data == nil { - return errors.New("user not found: " + id) - } - - u := &model.User{} - err = json.Unmarshal(data, u) - if err != nil { - return err - } - - decorator(u) - u.UpdatedAt = time.Now() - data, err = json.Marshal(u) - if err != nil { - return err - } - - return b.Put([]byte(id), data) +func (d *Dao) UserUpdatePassword(ctx context.Context, user *model.User) (err error) { + old := &model.User{} + return d.update(User, user.ID, old, func() interface{} { + old.Password = user.Password + old.Salt = user.Salt + old.UpdatedAt = user.UpdatedAt + old.UpdatedBy = user.UpdatedBy + return old }) } func (d *Dao) SessionGet(ctx context.Context, token string) (session *model.Session, err error) { - err = d.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte("session")) - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - s := &model.Session{} - err = json.Unmarshal(v, s) - if err != nil { - return err - } - if s.Token == token { - session = s - return nil - } - } - return nil - }) - return + s := &model.Session{} + found, err := d.find(Session, s, func() bool { return s.Token == token }) + if found { + return s, nil + } + return nil, err } func (d *Dao) SessionUpdate(ctx context.Context, session *model.Session) (err error) { - return d.update("session", session.UserID, session) + return d.replace(Session, session.UserID, session) } diff --git a/dao/dao.go b/dao/dao.go index c492711..1aa9130 100644 --- a/dao/dao.go +++ b/dao/dao.go @@ -14,51 +14,50 @@ import ( // Interface is the interface that wraps all dao methods. type Interface interface { Init() error - Close() RoleGet(ctx context.Context, id string) (*model.Role, error) - RoleList(ctx context.Context, name string) (roles []*model.Role, err error) + RoleSearch(ctx context.Context, name string) (roles []*model.Role, err error) RoleCreate(ctx context.Context, role *model.Role) error RoleUpdate(ctx context.Context, role *model.Role) error RoleDelete(ctx context.Context, id string) error + UserGet(ctx context.Context, id string) (*model.User, error) + UserGetByName(ctx context.Context, loginName string) (*model.User, error) + UserSearch(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) + UserCount(ctx context.Context) (int, error) UserCreate(ctx context.Context, user *model.User) error UserUpdate(ctx context.Context, user *model.User) error - UserList(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) - UserCount(ctx context.Context) (int, error) - UserGetByID(ctx context.Context, id string) (*model.User, error) - UserGetByName(ctx context.Context, loginName string) (*model.User, error) - UserSetStatus(ctx context.Context, id string, status int32) error + UserUpdateStatus(ctx context.Context, user *model.User) error + UserUpdateProfile(ctx context.Context, user *model.User) error + UserUpdatePassword(ctx context.Context, user *model.User) error UserDelete(ctx context.Context, id string) error - UserModifyProfile(ctx context.Context, user *model.User) error - UserModifyPassword(ctx context.Context, id, pwd, salt string) error - SessionUpdate(ctx context.Context, session *model.Session) error SessionGet(ctx context.Context, token string) (*model.Session, error) + SessionUpdate(ctx context.Context, session *model.Session) error - RegistryCreate(ctx context.Context, registry *model.Registry) error - RegistryUpdate(ctx context.Context, registry *model.Registry) error RegistryGet(ctx context.Context, id string) (*model.Registry, error) RegistryGetByURL(ctx context.Context, url string) (registry *model.Registry, err error) - RegistryList(ctx context.Context) (registries []*model.Registry, err error) + RegistryGetAll(ctx context.Context) (registries []*model.Registry, err error) + RegistryCreate(ctx context.Context, registry *model.Registry) error + RegistryUpdate(ctx context.Context, registry *model.Registry) error RegistryDelete(ctx context.Context, id string) error - StackList(ctx context.Context) (stacks []*model.Stack, err error) StackGet(ctx context.Context, name string) (*model.Stack, error) + StackGetAll(ctx context.Context) (stacks []*model.Stack, err error) StackCreate(ctx context.Context, stack *model.Stack) error StackUpdate(ctx context.Context, stack *model.Stack) error StackDelete(ctx context.Context, name string) error + EventSearch(ctx context.Context, args *model.EventSearchArgs) (events []*model.Event, count int, err error) EventCreate(ctx context.Context, event *model.Event) error - EventList(ctx context.Context, args *model.EventListArgs) (events []*model.Event, count int, err error) - SettingList(ctx context.Context) (settings []*model.Setting, err error) SettingGet(ctx context.Context, id string) (*model.Setting, error) - SettingUpdate(ctx context.Context, id string, opts []*model.SettingOption) error + SettingGetAll(ctx context.Context) (settings []*model.Setting, err error) + SettingUpdate(ctx context.Context, setting *model.Setting) error ChartGet(ctx context.Context, id string) (*model.Chart, error) - ChartBatch(ctx context.Context, ids ...string) ([]*model.Chart, error) - ChartList(ctx context.Context, title, dashboard string, pageIndex, pageSize int) (charts []*model.Chart, count int, err error) + ChartGetBatch(ctx context.Context, ids ...string) ([]*model.Chart, error) + ChartSearch(ctx context.Context, args *model.ChartSearchArgs) (charts []*model.Chart, count int, err error) ChartCreate(ctx context.Context, chart *model.Chart) error ChartUpdate(ctx context.Context, chart *model.Chart) error ChartDelete(ctx context.Context, id string) error diff --git a/dao/mongo/chart.go b/dao/mongo/chart.go index 0554e6d..e3058dd 100644 --- a/dao/mongo/chart.go +++ b/dao/mongo/chart.go @@ -12,15 +12,15 @@ const ( Dashboard = "dashboard" ) -func (d *Dao) ChartList(ctx context.Context, title, dashboard string, pageIndex, pageSize int) (charts []*model.Chart, count int, err error) { +func (d *Dao) ChartSearch(ctx context.Context, args *model.ChartSearchArgs) (charts []*model.Chart, count int, err error) { filter := bson.M{} - if title != "" { - filter["title"] = title + if args.Title != "" { + filter["title"] = args.Title } - if dashboard != "" { - filter["dashboard"] = bson.M{"$in": []string{"", dashboard}} + if args.Dashboard != "" { + filter["dashboard"] = bson.M{"$in": []string{"", args.Dashboard}} } - opts := searchOptions{filter: filter, sorter: bson.M{"updated_at": -1}, pageIndex: pageIndex, pageSize: pageSize} + opts := searchOptions{filter: filter, sorter: bson.M{"updated_at": -1}, pageIndex: args.PageIndex, pageSize: args.PageSize} charts = []*model.Chart{} count, err = d.search(ctx, Chart, opts, &charts) return @@ -39,7 +39,7 @@ func (d *Dao) ChartGet(ctx context.Context, id string) (chart *model.Chart, err return } -func (d *Dao) ChartBatch(ctx context.Context, names ...string) (charts []*model.Chart, err error) { +func (d *Dao) ChartGetBatch(ctx context.Context, names ...string) (charts []*model.Chart, err error) { charts = []*model.Chart{} err = d.fetch(ctx, Chart, bson.M{"_id": bson.M{"$in": names}}, &charts) return @@ -58,6 +58,7 @@ func (d *Dao) ChartUpdate(ctx context.Context, chart *model.Chart) (err error) { "margin": chart.Margin, "metrics": chart.Metrics, "updated_at": chart.UpdatedAt, + "updated_by": chart.UpdatedBy, }, } return d.update(ctx, Chart, chart.ID, update) diff --git a/dao/mongo/event.go b/dao/mongo/event.go index 3095f82..dd45066 100644 --- a/dao/mongo/event.go +++ b/dao/mongo/event.go @@ -9,7 +9,7 @@ import ( const Event = "event" -func (d *Dao) EventList(ctx context.Context, args *model.EventListArgs) (events []*model.Event, count int, err error) { +func (d *Dao) EventSearch(ctx context.Context, args *model.EventSearchArgs) (events []*model.Event, count int, err error) { filter := bson.M{} if args.Type != "" { filter["type"] = args.Type diff --git a/dao/mongo/mongo.go b/dao/mongo/mongo.go index f6ca45b..d240f86 100644 --- a/dao/mongo/mongo.go +++ b/dao/mongo/mongo.go @@ -98,9 +98,6 @@ func (d *Dao) Init() (err error) { return } -func (d *Dao) Close() { -} - func (d *Dao) find(ctx context.Context, coll string, id interface{}, v interface{}) (found bool, err error) { err = d.db.Collection(coll).FindOne(ctx, bson.M{"_id": id}).Decode(v) if err == nil { diff --git a/dao/mongo/registry.go b/dao/mongo/registry.go index eb94cc8..cec0d06 100644 --- a/dao/mongo/registry.go +++ b/dao/mongo/registry.go @@ -2,7 +2,6 @@ package mongo import ( "context" - "time" "github.com/cuigh/swirl/model" "go.mongodb.org/mongo-driver/bson" @@ -20,7 +19,8 @@ func (d *Dao) RegistryUpdate(ctx context.Context, registry *model.Registry) (err "name": registry.Name, "url": registry.URL, "username": registry.Username, - "updated_at": time.Now(), + "updated_at": registry.UpdatedAt, + "updated_by": registry.UpdatedBy, } if registry.Password != "" { update["password"] = registry.Password @@ -28,7 +28,7 @@ func (d *Dao) RegistryUpdate(ctx context.Context, registry *model.Registry) (err return d.update(ctx, Registry, registry.ID, bson.M{"$set": update}) } -func (d *Dao) RegistryList(ctx context.Context) (registries []*model.Registry, err error) { +func (d *Dao) RegistryGetAll(ctx context.Context) (registries []*model.Registry, err error) { registries = []*model.Registry{} err = d.fetch(ctx, Registry, bson.M{}, ®istries) return diff --git a/dao/mongo/role.go b/dao/mongo/role.go index 5c2a30f..a276b9e 100644 --- a/dao/mongo/role.go +++ b/dao/mongo/role.go @@ -9,7 +9,7 @@ import ( const Role = "role" -func (d *Dao) RoleList(ctx context.Context, name string) (roles []*model.Role, err error) { +func (d *Dao) RoleSearch(ctx context.Context, name string) (roles []*model.Role, err error) { filter := bson.M{} if name != "" { filter["name"] = name @@ -39,6 +39,7 @@ func (d *Dao) RoleUpdate(ctx context.Context, role *model.Role) (err error) { "desc": role.Description, "perms": role.Perms, "updated_at": role.UpdatedAt, + "updated_by": role.UpdatedBy, }, } return d.update(ctx, Role, role.ID, update) diff --git a/dao/mongo/setting.go b/dao/mongo/setting.go index 18481aa..7b85c5a 100644 --- a/dao/mongo/setting.go +++ b/dao/mongo/setting.go @@ -2,7 +2,6 @@ package mongo import ( "context" - "time" "github.com/cuigh/swirl/model" "go.mongodb.org/mongo-driver/bson" @@ -10,7 +9,7 @@ import ( const Setting = "setting" -func (d *Dao) SettingList(ctx context.Context) (settings []*model.Setting, err error) { +func (d *Dao) SettingGetAll(ctx context.Context) (settings []*model.Setting, err error) { settings = []*model.Setting{} err = d.fetch(ctx, Setting, bson.M{}, &settings) return @@ -25,12 +24,13 @@ func (d *Dao) SettingGet(ctx context.Context, id string) (setting *model.Setting return } -func (d *Dao) SettingUpdate(ctx context.Context, id string, options []*model.SettingOption) (err error) { +func (d *Dao) SettingUpdate(ctx context.Context, setting *model.Setting) (err error) { update := bson.M{ "$set": bson.M{ - "options": options, - "updated_at": time.Now(), + "options": setting.Options, + "updated_at": setting.UpdatedAt, + "updated_by": setting.UpdatedBy, }, } - return d.upsert(ctx, Setting, id, update) + return d.upsert(ctx, Setting, setting.ID, update) } diff --git a/dao/mongo/stack.go b/dao/mongo/stack.go index 1079389..6144028 100644 --- a/dao/mongo/stack.go +++ b/dao/mongo/stack.go @@ -2,7 +2,6 @@ package mongo import ( "context" - "time" "github.com/cuigh/swirl/model" "go.mongodb.org/mongo-driver/bson" @@ -10,15 +9,13 @@ import ( const Stack = "stack" -func (d *Dao) StackList(ctx context.Context) (stacks []*model.Stack, err error) { +func (d *Dao) StackGetAll(ctx context.Context) (stacks []*model.Stack, err error) { stacks = []*model.Stack{} err = d.fetch(ctx, Stack, bson.M{}, &stacks) return } func (d *Dao) StackCreate(ctx context.Context, stack *model.Stack) (err error) { - stack.CreatedAt = time.Now() - stack.UpdatedAt = stack.CreatedAt return d.create(ctx, Stack, stack) } @@ -36,7 +33,7 @@ func (d *Dao) StackUpdate(ctx context.Context, stack *model.Stack) (err error) { "$set": bson.M{ "content": stack.Content, "updated_by": stack.UpdatedBy, - "updated_at": time.Now(), + "updated_at": stack.UpdatedAt, }, } return d.update(ctx, Stack, stack.Name, update) diff --git a/dao/mongo/user.go b/dao/mongo/user.go index f9675ec..495fa8f 100644 --- a/dao/mongo/user.go +++ b/dao/mongo/user.go @@ -2,7 +2,6 @@ package mongo import ( "context" - "time" "github.com/cuigh/swirl/model" "go.mongodb.org/mongo-driver/bson" @@ -34,26 +33,28 @@ func (d *Dao) UserUpdate(ctx context.Context, user *model.User) (err error) { "type": user.Type, "roles": user.Roles, "updated_at": user.UpdatedAt, + "updated_by": user.UpdatedBy, }, } return d.update(ctx, User, user.ID, update) } -func (d *Dao) UserSetStatus(ctx context.Context, id string, status int32) (err error) { +func (d *Dao) UserUpdateStatus(ctx context.Context, user *model.User) (err error) { update := bson.M{ "$set": bson.M{ - "status": status, - "updated_at": time.Now(), + "status": user.Status, + "updated_at": user.UpdatedAt, + "updated_by": user.UpdatedBy, }, } - return d.update(ctx, User, id, update) + return d.update(ctx, User, user.ID, update) } func (d *Dao) UserDelete(ctx context.Context, id string) (err error) { return d.delete(ctx, User, id) } -func (d *Dao) UserList(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) { +func (d *Dao) UserSearch(ctx context.Context, args *model.UserSearchArgs) (users []*model.User, count int, err error) { filter := bson.M{} if args.Name != "" { filter["name"] = args.Name @@ -73,7 +74,7 @@ func (d *Dao) UserList(ctx context.Context, args *model.UserSearchArgs) (users [ return } -func (d *Dao) UserGetByID(ctx context.Context, id string) (user *model.User, err error) { +func (d *Dao) UserGet(ctx context.Context, id string) (user *model.User, err error) { user = &model.User{} found, err := d.find(ctx, User, id, user) if !found { @@ -93,27 +94,29 @@ func (d *Dao) UserGetByName(ctx context.Context, loginName string) (user *model. return } -func (d *Dao) UserModifyProfile(ctx context.Context, user *model.User) (err error) { +func (d *Dao) UserUpdateProfile(ctx context.Context, user *model.User) (err error) { update := bson.M{ "$set": bson.M{ "name": user.Name, "login_name": user.LoginName, "email": user.Email, - "updated_at": time.Now(), + "updated_at": user.UpdatedAt, + "updated_by": user.UpdatedBy, }, } return d.update(ctx, User, user.ID, update) } -func (d *Dao) UserModifyPassword(ctx context.Context, id, pwd, salt string) (err error) { +func (d *Dao) UserUpdatePassword(ctx context.Context, user *model.User) (err error) { update := bson.M{ "$set": bson.M{ - "password": pwd, - "salt": salt, - "updated_at": time.Now(), + "password": user.Password, + "salt": user.Salt, + "updated_at": user.UpdatedAt, + "updated_by": user.UpdatedBy, }, } - return d.update(ctx, User, id, update) + return d.update(ctx, User, user.ID, update) } func (d *Dao) SessionGet(ctx context.Context, token string) (session *model.Session, err error) { diff --git a/docs/images/home.png b/docs/images/home.png index 6c045c9..1088ac6 100644 Binary files a/docs/images/home.png and b/docs/images/home.png differ diff --git a/docs/images/service-stats.png b/docs/images/service-stats.png index d09c834..d30a7f0 100644 Binary files a/docs/images/service-stats.png and b/docs/images/service-stats.png differ diff --git a/docs/images/services.png b/docs/images/services.png index e63c583..c9880f1 100644 Binary files a/docs/images/services.png and b/docs/images/services.png differ diff --git a/docs/images/settings.png b/docs/images/settings.png index 25e4547..753b009 100644 Binary files a/docs/images/settings.png and b/docs/images/settings.png differ diff --git a/docs/images/stacks.png b/docs/images/stacks.png index 9232a77..a0fd020 100644 Binary files a/docs/images/stacks.png and b/docs/images/stacks.png differ diff --git a/model/model.go b/model/model.go index 0e7dbde..5ec7ce2 100644 --- a/model/model.go +++ b/model/model.go @@ -3,19 +3,65 @@ package model import ( "encoding/base64" "encoding/json" + "strconv" "strings" "time" "github.com/cuigh/auxo/data" + "github.com/cuigh/auxo/errors" + "github.com/cuigh/auxo/ext/times" "github.com/docker/docker/api/types" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) +type Time time.Time + +func (t Time) MarshalBSONValue() (bsontype.Type, []byte, error) { + return bson.MarshalValue(time.Time(t)) +} + +func (t *Time) UnmarshalBSONValue(bt bsontype.Type, data []byte) error { + if v, _, valid := bsoncore.ReadValue(data, bt); valid { + *t = Time(v.Time()) + return nil + } + return errors.Format("unmarshal failed, type: %s, data:%s", bt, data) +} + +func (t Time) MarshalJSON() (b []byte, err error) { + return strconv.AppendInt(b, times.ToUnixMilli(time.Time(t)), 10), nil +} + +func (t *Time) UnmarshalJSON(data []byte) (err error) { + i, err := strconv.ParseInt(string(data), 10, 64) + if err == nil { + *t = Time(times.FromUnixMilli(i)) + } + return err +} + +func (t Time) String() string { + return time.Time(t).String() +} + +func (t Time) Format(layout string) string { + return time.Time(t).Format(layout) +} + +type Operator struct { + ID string `json:"id,omitempty" bson:"_id,omitempty"` + Name string `json:"name,omitempty" bson:"name,omitempty"` +} + // Setting represents the options of swirl. type Setting struct { ID string `json:"id" bson:"_id"` Options []*SettingOption `json:"options" bson:"options,omitempty"` UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } type SettingOption struct { @@ -31,6 +77,8 @@ type Role struct { Perms []string `bson:"perms" json:"perms,omitempty"` CreatedAt time.Time `bson:"created_at" json:"created_at,omitempty"` UpdatedAt time.Time `bson:"updated_at" json:"updated_at,omitempty"` + CreatedBy Operator `json:"createdBy" bson:"created_by"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } type User struct { @@ -46,6 +94,8 @@ type User struct { Roles []string `bson:"roles" json:"roles,omitempty"` CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"` UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + CreatedBy Operator `json:"createdBy" bson:"created_by"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } type UserSearchArgs struct { @@ -65,6 +115,8 @@ type Registry struct { Password string `bson:"password" json:"-"` CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"` UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + CreatedBy Operator `json:"createdBy" bson:"created_by"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } func (r *Registry) Match(image string) bool { @@ -86,12 +138,12 @@ func (r *Registry) GetEncodedAuth() string { type Stack struct { Name string `bson:"_id" json:"name,omitempty"` Content string `bson:"content" json:"content,omitempty" bind:"content=form,content=file"` - CreatedBy string `bson:"created_by" json:"createdBy,omitempty"` - CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"` - UpdatedBy string `bson:"updated_by" json:"updatedBy,omitempty"` - UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` Services []string `bson:"-" json:"services,omitempty"` Internal bool `bson:"-" json:"internal"` + CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"` + UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + CreatedBy Operator `json:"createdBy" bson:"created_by"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } type Event struct { @@ -105,7 +157,7 @@ type Event struct { Time time.Time `bson:"time"` } -type EventListArgs struct { +type EventSearchArgs struct { Type string `bind:"type"` Name string `bind:"name"` PageIndex int `bind:"pageIndex"` @@ -133,6 +185,8 @@ type Chart struct { //Colors []string `json:"colors"` CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"` UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + CreatedBy Operator `json:"createdBy" bson:"created_by"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } func NewChart(dashboard, id, title, legend, query, unit string, left int32) *Chart { @@ -158,12 +212,21 @@ type ChartMetric struct { Query string `json:"query"` } +type ChartSearchArgs struct { + Title string `bind:"title"` + Dashboard string `bind:"dashboard"` + PageIndex int `bind:"pageIndex"` + PageSize int `bind:"pageSize"` +} + type Dashboard struct { - Name string `json:"name"` - Key string `json:"key,omitempty"` - Period int32 `json:"period,omitempty"` // data range in minutes - Interval int32 `json:"interval,omitempty"` // refresh interval in seconds, 0 means disabled. - Charts []ChartInfo `json:"charts,omitempty"` + Name string `json:"name"` + Key string `json:"key,omitempty"` + Period int32 `json:"period,omitempty"` // data range in minutes + Interval int32 `json:"interval,omitempty"` // refresh interval in seconds, 0 means disabled. + Charts []ChartInfo `json:"charts,omitempty"` + UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"` + UpdatedBy Operator `json:"updatedBy" bson:"updated_by"` } type ChartInfo struct { diff --git a/ui/src/api/chart.ts b/ui/src/api/chart.ts index 55cf6d3..9d4990a 100644 --- a/ui/src/api/chart.ts +++ b/ui/src/api/chart.ts @@ -22,6 +22,14 @@ export interface Chart { }; createdAt: string; updatedAt: string; + createdBy: { + id: string; + name: string; + }; + updatedBy: { + id: string; + name: string; + }; } export interface Dashboard { diff --git a/ui/src/api/registry.ts b/ui/src/api/registry.ts index bdaa530..a058ba4 100644 --- a/ui/src/api/registry.ts +++ b/ui/src/api/registry.ts @@ -6,8 +6,16 @@ export interface Registry { url: string; username: string; password: string; - createdAt: number; - updatedAt: number; + createdAt: string; + updatedAt: string; + createdBy: { + id: string; + name: string; + }; + updatedBy: { + id: string; + name: string; + }; } export class RegistryApi { diff --git a/ui/src/api/role.ts b/ui/src/api/role.ts index a4413a4..69f38a4 100644 --- a/ui/src/api/role.ts +++ b/ui/src/api/role.ts @@ -7,6 +7,14 @@ export interface Role { perms: string[]; createdAt: string; updatedAt: string; + createdBy: { + id: string; + name: string; + }; + updatedBy: { + id: string; + name: string; + }; } export class RoleApi { diff --git a/ui/src/api/stack.ts b/ui/src/api/stack.ts index d82847c..0e3dc1f 100644 --- a/ui/src/api/stack.ts +++ b/ui/src/api/stack.ts @@ -7,9 +7,15 @@ export interface Stack { services?: string[]; internal: boolean; createdAt: string; - createdBy: string; updatedAt: string; - updatedBy: string; + createdBy: { + id: string; + name: string; + }; + updatedBy: { + id: string; + name: string; + }; } export interface SearchArgs { diff --git a/ui/src/api/user.ts b/ui/src/api/user.ts index 2bfdaf0..f8f98a3 100644 --- a/ui/src/api/user.ts +++ b/ui/src/api/user.ts @@ -16,9 +16,17 @@ export interface User { type: string; status: number; email: string; + roles: string[]; createdAt: string; updatedAt: string; - roles: string[]; + createdBy: { + id: string; + name: string; + }; + updatedBy: { + id: string; + name: string; + }; } export interface LoginArgs { diff --git a/ui/src/components/Dashboard.vue b/ui/src/components/Dashboard.vue index 404d4c2..d6f1ae1 100644 --- a/ui/src/components/Dashboard.vue +++ b/ui/src/components/Dashboard.vue @@ -171,7 +171,7 @@ var stop: () => void async function saveDashboard() { await chartApi.saveDashboard(dashboard.value); - window.message.success('保存成功') + window.message.success(t('texts.action_success')) } function showDlg() { diff --git a/ui/src/locales/en.ts b/ui/src/locales/en.ts index ac8727f..f7ae89c 100644 --- a/ui/src/locales/en.ts +++ b/ui/src/locales/en.ts @@ -61,6 +61,8 @@ export default { "username": "Username", "created_at": "Created at", "updated_at": "Updated at", + "created_by": "Created by", + "updated_by": "Updated by", "started_at": "Started at", "action": "Action", "actions": "Actions", diff --git a/ui/src/locales/zh.ts b/ui/src/locales/zh.ts index 08cd661..cf03d6c 100644 --- a/ui/src/locales/zh.ts +++ b/ui/src/locales/zh.ts @@ -61,6 +61,8 @@ export default { "username": "用户名", "created_at": "创建时间", "updated_at": "更新时间", + "created_by": "创建人", + "updated_by": "更新人", "started_at": "启动时间", "action": "操作", "actions": "操作", diff --git a/ui/src/pages/chart/View.vue b/ui/src/pages/chart/View.vue index 191bc7a..7e0748e 100644 --- a/ui/src/pages/chart/View.vue +++ b/ui/src/pages/chart/View.vue @@ -54,7 +54,13 @@ {{ model.dashboard }} {{ model.type }} + + {{ model.createdBy?.name }} + {{ model.createdAt }} + + {{ model.updatedBy?.name }} + {{ model.updatedAt }} @@ -88,6 +94,7 @@ import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5"; import XPageHeader from "@/components/PageHeader.vue"; import XPairTag from "@/components/PairTag.vue"; import XPanel from "@/components/Panel.vue"; +import XAnchor from "@/components/Anchor.vue"; import chartApi from "@/api/chart"; import type { Chart } from "@/api/chart"; import { useRoute } from "vue-router"; diff --git a/ui/src/pages/registry/View.vue b/ui/src/pages/registry/View.vue index 8100529..2291dd2 100644 --- a/ui/src/pages/registry/View.vue +++ b/ui/src/pages/registry/View.vue @@ -22,7 +22,13 @@ {{ model.name }} {{ model.url }} {{ model.username }} + + {{ model.createdBy?.name }} + {{ model.createdAt }} + + {{ model.updatedBy?.name }} + {{ model.updatedAt }} @@ -37,6 +43,7 @@ import { } from "naive-ui"; import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5"; import XPageHeader from "@/components/PageHeader.vue"; +import XAnchor from "@/components/Anchor.vue"; import { XDescription, XDescriptionItem } from "@/components/description"; import registryApi from "@/api/registry"; import type { Registry } from "@/api/registry"; diff --git a/ui/src/pages/role/List.vue b/ui/src/pages/role/List.vue index ce46a6a..d4d07c8 100644 --- a/ui/src/pages/role/List.vue +++ b/ui/src/pages/role/List.vue @@ -22,6 +22,7 @@ {{ t('fields.id') }} {{ t('fields.name') }} {{ t('fields.desc') }} + {{ t('fields.updated_at') }} {{ t('fields.actions') }} @@ -32,6 +33,7 @@ {{ r.name }} {{ r.desc }} + {{ r.updatedAt }} {{ t('buttons.return') }} - {{ t('buttons.edit') }} + {{ t('buttons.edit') }}
{{ model.name }} + + {{ model.createdBy?.name }} + {{ model.createdAt }} + + {{ model.updatedBy?.name }} + {{ model.updatedAt }} @@ -37,6 +47,7 @@ import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5"; import XPageHeader from "@/components/PageHeader.vue"; import XCode from "@/components/Code.vue"; import XPanel from "@/components/Panel.vue"; +import XAnchor from "@/components/Anchor.vue"; import { XDescription, XDescriptionItem } from "@/components/description"; import stackApi from "@/api/stack"; import type { Stack } from "@/api/stack"; diff --git a/ui/src/pages/user/List.vue b/ui/src/pages/user/List.vue index 03a5060..88b85d4 100644 --- a/ui/src/pages/user/List.vue +++ b/ui/src/pages/user/List.vue @@ -111,6 +111,10 @@ const columns = [ row.status ? "success" : "warning" ), }, + { + title: t('fields.updated_at'), + key: "updatedAt", + }, { title: t('fields.actions'), key: "actions", diff --git a/ui/src/pages/user/View.vue b/ui/src/pages/user/View.vue index b987e05..af5be69 100644 --- a/ui/src/pages/user/View.vue +++ b/ui/src/pages/user/View.vue @@ -19,6 +19,9 @@ {{ model.user.id }} + {{ model.user.email }} + {{ model.user.name }} + {{ model.user.loginName }} {{ t(model.user.status ? 'enums.normal' : 'enums.blocked') }} - {{ model.user.name }} - {{ model.user.loginName }} - {{ model.user.email }} - - {{ model.user.type }} - {{ t(model.user.admin ? "enums.yes" : "enums.no") }} + + {{ model.user.type }} + + + {{ model.user.createdBy?.name }} + {{ model.user.createdAt }} + + {{ model.user.updatedBy?.name }} + {{ model.user.updatedAt }}