This repository has been archived on 2023-11-13. You can view files and clone it, but cannot push or open issues or pull requests.
imagini/internal/db/db.go
2021-02-08 19:42:20 -05:00

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