156 lines
3.1 KiB
Go
156 lines
3.1 KiB
Go
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"reflect"
|
|
|
|
"github.com/iancoleman/strcase"
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
// "gorm.io/gorm/logger"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"reichard.io/imagini/graph/model"
|
|
"reichard.io/imagini/internal/config"
|
|
)
|
|
|
|
type DBManager struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewMgr(c *config.Config) *DBManager {
|
|
gormConfig := &gorm.Config{
|
|
PrepareStmt: true,
|
|
// Logger: logger.Default.LogMode(logger.Silent),
|
|
}
|
|
|
|
// Create manager
|
|
dbm := &DBManager{}
|
|
|
|
if c.DBType == "SQLite" {
|
|
dbLocation := path.Join(c.ConfigPath, "imagini.db")
|
|
dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig)
|
|
dbm.db = dbm.db.Debug()
|
|
} else {
|
|
log.Fatal("Unsupported Database")
|
|
}
|
|
|
|
// Initialize database
|
|
dbm.db.AutoMigrate(&model.Device{})
|
|
dbm.db.AutoMigrate(&model.User{})
|
|
dbm.db.AutoMigrate(&model.MediaItem{})
|
|
dbm.db.AutoMigrate(&model.Tag{})
|
|
dbm.db.AutoMigrate(&model.Album{})
|
|
|
|
// Determine whether to bootstrap
|
|
var count int64
|
|
dbm.db.Model(&model.User{}).Count(&count)
|
|
if count == 0 {
|
|
dbm.bootstrapDatabase()
|
|
}
|
|
|
|
return dbm
|
|
}
|
|
|
|
func (dbm *DBManager) bootstrapDatabase() {
|
|
log.Info("[query] Bootstrapping database.")
|
|
|
|
password := "admin"
|
|
user := &model.User{
|
|
Username: "admin",
|
|
AuthType: "Local",
|
|
Password: &password,
|
|
Role: model.RoleAdmin,
|
|
}
|
|
|
|
err := dbm.CreateUser(user)
|
|
|
|
if err != nil {
|
|
log.Fatal("[query] Unable to bootstrap database.")
|
|
}
|
|
}
|
|
|
|
func (dbm *DBManager) generateBaseQuery(tx *gorm.DB, filter interface{}, page *model.Page, order *model.Order) (*gorm.DB, model.PageResponse) {
|
|
tx = dbm.generateFilter(tx, filter)
|
|
tx = dbm.generateOrder(tx, order, filter)
|
|
tx, pageResponse := dbm.generatePage(tx, page)
|
|
return tx, pageResponse
|
|
}
|
|
|
|
func (dbm *DBManager) generateOrder(tx *gorm.DB, order *model.Order, filter interface{}) *gorm.DB {
|
|
// Set Defaults
|
|
orderBy := "created_at"
|
|
orderDirection := model.OrderDirectionDesc
|
|
|
|
if order == nil {
|
|
order = &model.Order{
|
|
By: &orderBy,
|
|
Direction: &orderDirection,
|
|
}
|
|
}
|
|
|
|
if order.By == nil {
|
|
order.By = &orderBy
|
|
}
|
|
|
|
if order.Direction == nil {
|
|
order.Direction = &orderDirection
|
|
}
|
|
|
|
// Get Possible Values
|
|
ptr := reflect.New(reflect.TypeOf(filter).Elem())
|
|
v := reflect.Indirect(ptr)
|
|
|
|
isValid := false
|
|
for i := 0; i < v.NumField(); i++ {
|
|
fieldName := v.Type().Field(i).Name
|
|
if strcase.ToSnake(*order.By) == strcase.ToSnake(fieldName) {
|
|
isValid = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if isValid {
|
|
tx = tx.Order(fmt.Sprintf("%s %s", strcase.ToSnake(*order.By), order.Direction.String()))
|
|
}
|
|
|
|
return tx
|
|
}
|
|
|
|
func (dbm *DBManager) generatePage(tx *gorm.DB, page *model.Page) (*gorm.DB, model.PageResponse) {
|
|
// Set Defaults
|
|
var count int64
|
|
pageSize := 50
|
|
pageNum := 1
|
|
|
|
if page == nil {
|
|
page = &model.Page{
|
|
Size: &pageSize,
|
|
Page: &pageNum,
|
|
}
|
|
}
|
|
|
|
if page.Size == nil {
|
|
page.Size = &pageSize
|
|
}
|
|
|
|
if page.Page == nil {
|
|
page.Page = &pageNum
|
|
}
|
|
|
|
// Acquire Counts Before Pagination
|
|
tx.Count(&count)
|
|
|
|
// Calculate Offset
|
|
calculatedOffset := (*page.Page - 1) * *page.Size
|
|
tx = tx.Limit(*page.Size).Offset(calculatedOffset)
|
|
|
|
return tx, model.PageResponse{
|
|
Page: *page.Page,
|
|
Size: *page.Size,
|
|
Total: int(count),
|
|
}
|
|
}
|