Add UserList in UI
This commit is contained in:
@@ -52,3 +52,7 @@ func (db *MockDataStore) Property() model.PropertyRepository {
|
||||
func (db *MockDataStore) WithTx(block func(db model.DataStore) error) error {
|
||||
return block(db)
|
||||
}
|
||||
|
||||
func (db *MockDataStore) Resource(m interface{}) model.ResourceRepository {
|
||||
return struct{ model.ResourceRepository }{}
|
||||
}
|
||||
|
||||
+28
-10
@@ -16,8 +16,9 @@ import (
|
||||
const batchSize = 100
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
driver = "sqlite3"
|
||||
once sync.Once
|
||||
driver = "sqlite3"
|
||||
mappedModels map[interface{}]interface{}
|
||||
)
|
||||
|
||||
type SQLStore struct {
|
||||
@@ -30,11 +31,12 @@ func New() model.DataStore {
|
||||
if dbPath == ":memory:" {
|
||||
dbPath = "file::memory:?cache=shared"
|
||||
}
|
||||
log.Debug("Opening DB from: "+dbPath, "driver", driver)
|
||||
|
||||
err := initORM(dbPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Debug("Opening DB from: "+dbPath, "driver", driver)
|
||||
})
|
||||
return &SQLStore{}
|
||||
}
|
||||
@@ -67,6 +69,10 @@ func (db *SQLStore) Property() model.PropertyRepository {
|
||||
return NewPropertyRepository(db.getOrmer())
|
||||
}
|
||||
|
||||
func (db *SQLStore) Resource(model interface{}) model.ResourceRepository {
|
||||
return NewResource(db.getOrmer(), model, mappedModels[model])
|
||||
}
|
||||
|
||||
func (db *SQLStore) WithTx(block func(tx model.DataStore) error) error {
|
||||
o := orm.NewOrm()
|
||||
err := o.Begin()
|
||||
@@ -102,13 +108,6 @@ func (db *SQLStore) getOrmer() orm.Ormer {
|
||||
func initORM(dbPath string) error {
|
||||
verbose := conf.Sonic.LogLevel == "trace"
|
||||
orm.Debug = verbose
|
||||
orm.RegisterModel(new(artist))
|
||||
orm.RegisterModel(new(album))
|
||||
orm.RegisterModel(new(mediaFile))
|
||||
orm.RegisterModel(new(checksum))
|
||||
orm.RegisterModel(new(property))
|
||||
orm.RegisterModel(new(playlist))
|
||||
orm.RegisterModel(new(Search))
|
||||
if strings.Contains(dbPath, "postgres") {
|
||||
driver = "postgres"
|
||||
}
|
||||
@@ -129,3 +128,22 @@ func collectField(collection interface{}, getValue func(item interface{}) string
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func registerModel(model interface{}, mappedModel interface{}) {
|
||||
mappedModels[model] = mappedModel
|
||||
orm.RegisterModel(mappedModel)
|
||||
}
|
||||
|
||||
func init() {
|
||||
mappedModels = map[interface{}]interface{}{}
|
||||
|
||||
registerModel(new(model.Artist), new(artist))
|
||||
registerModel(new(model.Album), new(album))
|
||||
registerModel(new(model.MediaFile), new(mediaFile))
|
||||
registerModel(new(model.Property), new(property))
|
||||
registerModel(new(model.Playlist), new(playlist))
|
||||
registerModel(model.User{}, new(user))
|
||||
|
||||
orm.RegisterModel(new(checksum))
|
||||
orm.RegisterModel(new(search))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package persistence
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/cloudsonic/sonic-server/model"
|
||||
"github.com/deluan/rest"
|
||||
)
|
||||
|
||||
type resourceRepository struct {
|
||||
model.ResourceRepository
|
||||
model interface{}
|
||||
mappedModel interface{}
|
||||
ormer orm.Ormer
|
||||
instanceType reflect.Type
|
||||
sliceType reflect.Type
|
||||
}
|
||||
|
||||
func NewResource(o orm.Ormer, model interface{}, mappedModel interface{}) model.ResourceRepository {
|
||||
r := &resourceRepository{model: model, mappedModel: mappedModel, ormer: o}
|
||||
r.instanceType = reflect.TypeOf(mappedModel)
|
||||
r.sliceType = reflect.SliceOf(r.instanceType)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *resourceRepository) newQuery() orm.QuerySeter {
|
||||
return r.ormer.QueryTable(r.mappedModel)
|
||||
}
|
||||
|
||||
func (r *resourceRepository) ReadAll(options ...rest.QueryOptions) (interface{}, error) {
|
||||
qs := r.newQuery()
|
||||
qs = r.addOptions(qs, options)
|
||||
//qs = r.addFilters(qs, r.buildFilters(qs, options), r.getRestriction())
|
||||
dataSet := r.NewSlice()
|
||||
_, err := qs.All(dataSet)
|
||||
if err == orm.ErrNoRows {
|
||||
return dataSet, rest.ErrNotFound
|
||||
}
|
||||
return dataSet, err
|
||||
}
|
||||
|
||||
func (r *resourceRepository) Count(options ...rest.QueryOptions) (int64, error) {
|
||||
qs := r.newQuery()
|
||||
//qs = r.addFilters(qs, r.buildFilters(qs, options), r.getRestriction())
|
||||
count, err := qs.Count()
|
||||
if err == orm.ErrNoRows {
|
||||
err = rest.ErrNotFound
|
||||
}
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (r *resourceRepository) NewSlice() interface{} {
|
||||
slice := reflect.MakeSlice(r.sliceType, 0, 0)
|
||||
x := reflect.New(slice.Type())
|
||||
x.Elem().Set(slice)
|
||||
return x.Interface()
|
||||
}
|
||||
|
||||
func (r *resourceRepository) addOptions(qs orm.QuerySeter, options []rest.QueryOptions) orm.QuerySeter {
|
||||
if len(options) == 0 {
|
||||
return qs
|
||||
}
|
||||
opt := options[0]
|
||||
sort := strings.Split(opt.Sort, ",")
|
||||
reverse := strings.ToLower(opt.Order) == "desc"
|
||||
for i, s := range sort {
|
||||
s = strings.TrimSpace(s)
|
||||
if reverse {
|
||||
if s[0] == '-' {
|
||||
s = strings.TrimPrefix(s, "-")
|
||||
} else {
|
||||
s = "-" + s
|
||||
}
|
||||
}
|
||||
sort[i] = strings.Replace(s, ".", "__", -1)
|
||||
}
|
||||
if opt.Sort != "" {
|
||||
qs = qs.OrderBy(sort...)
|
||||
}
|
||||
if opt.Max > 0 {
|
||||
qs = qs.Limit(opt.Max)
|
||||
}
|
||||
if opt.Offset > 0 {
|
||||
qs = qs.Offset(opt.Offset)
|
||||
}
|
||||
return qs
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/kennygrant/sanitize"
|
||||
)
|
||||
|
||||
type Search struct {
|
||||
type search struct {
|
||||
ID string `orm:"pk;column(id)"`
|
||||
Table string `orm:"index"`
|
||||
FullText string `orm:"index"`
|
||||
@@ -55,13 +55,13 @@ func (r *searchableRepository) purgeInactive(activeList interface{}, getId func(
|
||||
}
|
||||
|
||||
func (r *searchableRepository) addToIndex(table, id, text string) error {
|
||||
item := Search{ID: id, Table: table}
|
||||
item := search{ID: id, Table: table}
|
||||
err := r.ormer.Read(&item)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
sanitizedText := strings.TrimSpace(sanitize.Accents(strings.ToLower(text)))
|
||||
item = Search{ID: id, Table: table, FullText: sanitizedText}
|
||||
item = search{ID: id, Table: table, FullText: sanitizedText}
|
||||
if err == orm.ErrNoRows {
|
||||
err = r.insert(&item)
|
||||
} else {
|
||||
@@ -79,7 +79,7 @@ func (r *searchableRepository) removeFromIndex(table string, ids []string) error
|
||||
}
|
||||
log.Trace("Deleting searchable items", "table", table, "num", len(subset), "from", offset)
|
||||
offset += len(subset)
|
||||
_, err := r.ormer.QueryTable(&Search{}).Filter("table", table).Filter("id__in", subset).Delete()
|
||||
_, err := r.ormer.QueryTable(&search{}).Filter("table", table).Filter("id__in", subset).Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (r *searchableRepository) removeFromIndex(table string, ids []string) error
|
||||
}
|
||||
|
||||
func (r *searchableRepository) removeAllFromIndex(o orm.Ormer, table string) error {
|
||||
_, err := o.QueryTable(&Search{}).Filter("table", table).Delete()
|
||||
_, err := o.QueryTable(&search{}).Filter("table", table).Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package persistence
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cloudsonic/sonic-server/model"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
ID string `json:"id" orm:"pk;column(id)"`
|
||||
Name string `json:"name" orm:"index"`
|
||||
Password string `json:"-"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
LastLoginAt time.Time `json:"lastLoginAt"`
|
||||
LastAccessAt time.Time `json:"lastAccessAt"`
|
||||
CreatedAt time.Time `json:"createdAt" orm:"auto_now_add;type(datetime)"`
|
||||
UpdatedAt time.Time `json:"updatedAt" orm:"auto_now;type(datetime)"`
|
||||
}
|
||||
|
||||
var _ = model.User(user{})
|
||||
Reference in New Issue
Block a user