Add creator and modifier fields

This commit is contained in:
cuigh 2021-12-16 16:11:16 +08:00
parent bd7b8364d9
commit c3115b952c
48 changed files with 668 additions and 544 deletions

View File

@ -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 {

View File

@ -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
)

View File

@ -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)
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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,
}
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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
//}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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{}, &registries)
return

View File

@ -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)

View File

@ -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)
}

View File

@ -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)

View File

@ -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) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 KiB

After

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -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 {

View File

@ -22,6 +22,14 @@ export interface Chart {
};
createdAt: string;
updatedAt: string;
createdBy: {
id: string;
name: string;
};
updatedBy: {
id: string;
name: string;
};
}
export interface Dashboard {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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() {

View File

@ -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",

View File

@ -61,6 +61,8 @@ export default {
"username": "用户名",
"created_at": "创建时间",
"updated_at": "更新时间",
"created_by": "创建人",
"updated_by": "更新人",
"started_at": "启动时间",
"action": "操作",
"actions": "操作",

View File

@ -54,7 +54,13 @@
</x-description-item>
<x-description-item :label="t('fields.dashboard')">{{ model.dashboard }}</x-description-item>
<x-description-item :label="t('fields.type')">{{ model.type }}</x-description-item>
<x-description-item :label="t('fields.created_by')">
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
<x-description-item :label="t('fields.updated_by')">
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
</x-description>
<x-panel :title="t('fields.metrics')">
@ -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";

View File

@ -22,7 +22,13 @@
<x-description-item :label="t('fields.name')">{{ model.name }}</x-description-item>
<x-description-item :label="t('fields.url')">{{ model.url }}</x-description-item>
<x-description-item :label="t('fields.login_name')">{{ model.username }}</x-description-item>
<x-description-item :label="t('fields.created_by')">
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
<x-description-item :label="t('fields.updated_by')">
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
</x-description>
</n-space>
@ -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";

View File

@ -22,6 +22,7 @@
<th>{{ t('fields.id') }}</th>
<th>{{ t('fields.name') }}</th>
<th>{{ t('fields.desc') }}</th>
<th>{{ t('fields.updated_at') }}</th>
<th>{{ t('fields.actions') }}</th>
</tr>
</thead>
@ -32,6 +33,7 @@
</td>
<td>{{ r.name }}</td>
<td>{{ r.desc }}</td>
<td>{{ r.updatedAt }}</td>
<td>
<n-popconfirm :show-icon="false" @positive-click="deleteRole(r, index)">
<template #trigger>

View File

@ -21,6 +21,14 @@
<x-description-item :label="t('fields.id')">{{ model.id }}</x-description-item>
<x-description-item :label="t('fields.name')">{{ model.name }}</x-description-item>
<x-description-item :span="2" :label="t('fields.desc')">{{ model.desc }}</x-description-item>
<x-description-item :label="t('fields.created_by')">
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
<x-description-item :label="t('fields.updated_by')">
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
<x-description-item :span="2" :label="t('fields.perms')">
<n-grid cols="1 480:2 960:3 1440:4" x-gap="6">
<n-gi span="1" v-for="g in ps">
@ -45,6 +53,7 @@ import { useRoute } from "vue-router";
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
import XPageHeader from "@/components/PageHeader.vue";
import XPairTag from "@/components/PairTag.vue";
import XAnchor from "@/components/Anchor.vue";
import { XDescription, XDescriptionItem } from "@/components/description";
import roleApi from "@/api/role";
import type { Role } from "@/api/role";

View File

@ -9,14 +9,24 @@
</template>
{{ t('buttons.return') }}
</n-button>
<n-button secondary size="small" @click="$router.push(`/swarm/stacks/${model.name}/edit`)">{{ t('buttons.edit') }}</n-button>
<n-button
secondary
size="small"
@click="$router.push(`/swarm/stacks/${model.name}/edit`)"
>{{ t('buttons.edit') }}</n-button>
</template>
</x-page-header>
<div class="page-body">
<n-space vertical :size="16">
<x-description :label-width="90">
<x-description-item :label="t('fields.name')" :span="2">{{ model.name }}</x-description-item>
<x-description-item :label="t('fields.created_by')">
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
<x-description-item :label="t('fields.updated_by')">
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
</x-description>
<x-panel :title="t('fields.content')">
@ -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";

View File

@ -111,6 +111,10 @@ const columns = [
row.status ? "success" : "warning"
),
},
{
title: t('fields.updated_at'),
key: "updatedAt",
},
{
title: t('fields.actions'),
key: "actions",

View File

@ -19,6 +19,9 @@
<n-space class="page-body" vertical :size="16">
<x-description cols="1 640:2" label-position="left" label-align="right" :label-width="100">
<x-description-item :label="t('fields.id')">{{ model.user.id }}</x-description-item>
<x-description-item :label="t('fields.email')">{{ model.user.email }}</x-description-item>
<x-description-item :label="t('fields.username')">{{ model.user.name }}</x-description-item>
<x-description-item :label="t('fields.login_name')">{{ model.user.loginName }}</x-description-item>
<x-description-item :label="t('fields.status')">
<n-tag
round
@ -26,16 +29,6 @@
:type="model.user.status ? 'primary' : 'warning'"
>{{ t(model.user.status ? 'enums.normal' : 'enums.blocked') }}</n-tag>
</x-description-item>
<x-description-item :label="t('fields.username')">{{ model.user.name }}</x-description-item>
<x-description-item :label="t('fields.login_name')">{{ model.user.loginName }}</x-description-item>
<x-description-item :label="t('fields.email')">{{ model.user.email }}</x-description-item>
<x-description-item :label="t('fields.type')">
<n-tag
size="small"
round
:type="model.user.type === 'internal' ? 'default' : 'warning'"
>{{ model.user.type }}</n-tag>
</x-description-item>
<x-description-item :label="t('fields.admin')">
<n-tag
size="small"
@ -43,7 +36,24 @@
:type="model.user.admin ? 'success' : 'default'"
>{{ t(model.user.admin ? "enums.yes" : "enums.no") }}</n-tag>
</x-description-item>
<x-description-item :label="t('fields.type')" :span="2">
<n-tag
size="small"
round
:type="model.user.type === 'internal' ? 'default' : 'warning'"
>{{ model.user.type }}</n-tag>
</x-description-item>
<x-description-item :label="t('fields.created_by')">
<x-anchor
:url="`/system/users/${model.user.createdBy?.id}`"
>{{ model.user.createdBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.created_at')">{{ model.user.createdAt }}</x-description-item>
<x-description-item :label="t('fields.updated_by')">
<x-anchor
:url="`/system/users/${model.user.updatedBy?.id}`"
>{{ model.user.updatedBy?.name }}</x-anchor>
</x-description-item>
<x-description-item :label="t('fields.updated_at')">{{ model.user.updatedAt }}</x-description-item>
<x-description-item
:label="t('objects.role', 2)"
@ -74,6 +84,7 @@ import {
import { useRoute } from "vue-router";
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 userApi from "@/api/user";
import roleApi from "@/api/role";