Start on migrating database integration to gorm
This commit is contained in:
parent
8781ab3777
commit
27b2f95a7b
|
@ -11,7 +11,9 @@
|
|||
"mode": "auto",
|
||||
"program": "${workspaceRoot}/server.go",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"env": {},
|
||||
"env": {
|
||||
"PATH": "${env:PATH}:/Applications/darktable.app/Contents/MacOS/"
|
||||
},
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,27 +1,19 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
|
||||
// Load mysql driver
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database/mysql"
|
||||
|
||||
// Migrate from file
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// SetupDatabase connects to the database using environment variables
|
||||
func SetupDatabase() (*sql.DB, error) {
|
||||
func SetupDatabase() (*gorm.DB, error) {
|
||||
|
||||
address, err := url.Parse(os.Getenv("MYSQL_URL"))
|
||||
if err != nil {
|
||||
|
@ -40,62 +32,46 @@ func SetupDatabase() (*sql.DB, error) {
|
|||
|
||||
log.Printf("Connecting to database: %s", address)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
db, err = sql.Open("mysql", address.String())
|
||||
db, err := gorm.Open(mysql.Open(address.String()), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, errors.New("Could not connect to database, exiting")
|
||||
return nil, errors.Wrap(err, "could not connect to database")
|
||||
}
|
||||
|
||||
tryCount := 0
|
||||
// var db *sql.DB
|
||||
|
||||
for {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
// db, err = sql.Open("mysql", address.String())
|
||||
// if err != nil {
|
||||
// return nil, errors.New("Could not connect to database, exiting")
|
||||
// }
|
||||
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
if tryCount < 4 {
|
||||
tryCount++
|
||||
log.Printf("WARN: Could not ping database: %s, Will retry after 1 second", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "Could not ping database, exiting")
|
||||
}
|
||||
}
|
||||
// tryCount := 0
|
||||
|
||||
break
|
||||
}
|
||||
// for {
|
||||
// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
// defer cancel()
|
||||
|
||||
db.SetMaxOpenConns(80)
|
||||
// if err := db.PingContext(ctx); err != nil {
|
||||
// if tryCount < 4 {
|
||||
// tryCount++
|
||||
// log.Printf("WARN: Could not ping database: %s, Will retry after 1 second", err)
|
||||
// time.Sleep(time.Second)
|
||||
// continue
|
||||
// } else {
|
||||
// return nil, errors.Wrap(err, "Could not ping database, exiting")
|
||||
// }
|
||||
// }
|
||||
|
||||
// break
|
||||
// }
|
||||
|
||||
// db.SetMaxOpenConns(80)
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func MigrateDatabase(db *sql.DB) error {
|
||||
driver, err := mysql.WithInstance(db, &mysql.Config{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func MigrateDatabase(db *gorm.DB) error {
|
||||
|
||||
m, err := migrate.NewWithDatabaseInstance(
|
||||
"file://database/migrations",
|
||||
"mysql",
|
||||
driver,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.Up(); err != nil {
|
||||
if err.Error() == "no change" {
|
||||
log.Println("Database is up to date")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Println("Database migrated")
|
||||
}
|
||||
db.AutoMigrate(&models.User{}, &models.AccessToken{})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -31,4 +31,6 @@ require (
|
|||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd // indirect
|
||||
gopkg.in/vansante/go-ffprobe.v2 v2.0.2
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
gorm.io/driver/mysql v1.0.3
|
||||
gorm.io/gorm v1.20.7
|
||||
)
|
||||
|
|
|
@ -58,6 +58,10 @@ github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCO
|
|||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
|
@ -176,5 +180,10 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gorm.io/driver/mysql v1.0.3 h1:+JKBYPfn1tygR1/of/Fh2T8iwuVwzt+PEJmKaXzMQXg=
|
||||
gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI=
|
||||
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.7 h1:rMS4CL3pNmYq1V5/X+nHHjh1Dx6dnf27+Cai5zabo+M=
|
||||
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||
|
|
|
@ -2,7 +2,6 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
|
@ -10,6 +9,7 @@ import (
|
|||
|
||||
"github.com/99designs/gqlgen/handler"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var ErrUnauthorized = errors.New("unauthorized")
|
||||
|
@ -23,7 +23,7 @@ type contextKey struct {
|
|||
}
|
||||
|
||||
// Middleware decodes the share session cookie and packs the session into context
|
||||
func Middleware(db *sql.DB) func(http.Handler) http.Handler {
|
||||
func Middleware(db *gorm.DB) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
|
@ -66,7 +66,7 @@ func UserFromContext(ctx context.Context) *models.User {
|
|||
return raw
|
||||
}
|
||||
|
||||
func AuthWebsocketInit(db *sql.DB) func(context.Context, handler.InitPayload) (context.Context, error) {
|
||||
func AuthWebsocketInit(db *gorm.DB) func(context.Context, handler.InitPayload) (context.Context, error) {
|
||||
return func(ctx context.Context, initPayload handler.InitPayload) (context.Context, error) {
|
||||
|
||||
bearer, exists := initPayload["Authorization"].(string)
|
||||
|
|
|
@ -2,14 +2,14 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/viktorstrate/photoview/api/graphql/auth"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func IsAdmin(database *sql.DB) func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {
|
||||
func IsAdmin(database *gorm.DB) func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {
|
||||
return func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {
|
||||
|
||||
user := auth.UserFromContext(ctx)
|
||||
|
|
|
@ -1,48 +1,59 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func initializeSiteInfoRow(db *sql.DB) (*SiteInfo, error) {
|
||||
_, err := db.Exec("INSERT INTO site_info (initial_setup, periodic_scan_interval, concurrent_workers) VALUES (true, 0, 3)")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "initialize site_info row")
|
||||
}
|
||||
// func initializeSiteInfoRow(db *gorm.DB) (*SiteInfo, error) {
|
||||
// _, err := db.Exec("INSERT INTO site_info (initial_setup, periodic_scan_interval, concurrent_workers) VALUES (true, 0, 3)")
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "initialize site_info row")
|
||||
// }
|
||||
|
||||
siteInfo := &SiteInfo{}
|
||||
// siteInfo := &SiteInfo{}
|
||||
|
||||
row := db.QueryRow("SELECT * FROM site_info")
|
||||
if err := row.Scan(&siteInfo.InitialSetup, &siteInfo.PeriodicScanInterval, &siteInfo.ConcurrentWorkers); err != nil {
|
||||
return nil, errors.Wrap(err, "get site_info row after initialization")
|
||||
}
|
||||
// row := db.QueryRow("SELECT * FROM site_info")
|
||||
// if err := row.Scan(&siteInfo.InitialSetup, &siteInfo.PeriodicScanInterval, &siteInfo.ConcurrentWorkers); err != nil {
|
||||
// return nil, errors.Wrap(err, "get site_info row after initialization")
|
||||
// }
|
||||
|
||||
return siteInfo, nil
|
||||
}
|
||||
// return siteInfo, nil
|
||||
// }
|
||||
|
||||
// GetSiteInfo gets the site info row from the database, and creates it if it does not exist
|
||||
func GetSiteInfo(db *sql.DB) (*SiteInfo, error) {
|
||||
rows, err := db.Query("SELECT * FROM site_info")
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func GetSiteInfo(db *gorm.DB) (*SiteInfo, error) {
|
||||
|
||||
var siteInfo SiteInfo
|
||||
|
||||
result := db.FirstOrCreate(&siteInfo, SiteInfo{
|
||||
InitialSetup: true,
|
||||
PeriodicScanInterval: 0,
|
||||
ConcurrentWorkers: 3,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return nil, errors.Wrap(result.Error, "get site info from database")
|
||||
}
|
||||
|
||||
siteInfo := &SiteInfo{}
|
||||
// rows, err := db.Query("SELECT * FROM site_info")
|
||||
// defer rows.Close()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
if !rows.Next() {
|
||||
// Entry does not exist
|
||||
siteInfo, err = initializeSiteInfoRow(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := rows.Scan(&siteInfo.InitialSetup, &siteInfo.PeriodicScanInterval, &siteInfo.ConcurrentWorkers); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// siteInfo := &SiteInfo{}
|
||||
|
||||
return siteInfo, nil
|
||||
// if !rows.Next() {
|
||||
// // Entry does not exist
|
||||
// siteInfo, err = initializeSiteInfoRow(db)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else {
|
||||
// if err := rows.Scan(&siteInfo.InitialSetup, &siteInfo.PeriodicScanInterval, &siteInfo.ConcurrentWorkers); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// }
|
||||
|
||||
return &siteInfo, nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package models
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -10,63 +9,68 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
UserID int
|
||||
Username string
|
||||
Password *string
|
||||
RootPath string
|
||||
Admin bool
|
||||
gorm.Model
|
||||
Username string `gorm:"unique,size:128"`
|
||||
Password *string `gorm:"size:256`
|
||||
RootPath string `gorm:"size:512`
|
||||
Admin bool `gorm:"default:false"`
|
||||
}
|
||||
|
||||
func (u *User) ID() int {
|
||||
return u.UserID
|
||||
}
|
||||
// func (u *User) ID() int {
|
||||
// return u.UserID
|
||||
// }
|
||||
|
||||
type AccessToken struct {
|
||||
Value string
|
||||
gorm.Model
|
||||
UserID uint
|
||||
User User `gorm:"constraint:OnDelete:CASCADE;"`
|
||||
Value string `gorm:"size:24`
|
||||
Expire time.Time
|
||||
}
|
||||
|
||||
var ErrorInvalidUserCredentials = errors.New("invalid credentials")
|
||||
|
||||
func NewUserFromRow(row *sql.Row) (*User, error) {
|
||||
user := User{}
|
||||
// func NewUserFromRow(row *sql.Row) (*User, error) {
|
||||
// user := User{}
|
||||
|
||||
if err := row.Scan(&user.UserID, &user.Username, &user.Password, &user.RootPath, &user.Admin); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to scan user from database")
|
||||
}
|
||||
// if err := row.Scan(&user.UserID, &user.Username, &user.Password, &user.RootPath, &user.Admin); err != nil {
|
||||
// return nil, errors.Wrap(err, "failed to scan user from database")
|
||||
// }
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
// return &user, nil
|
||||
// }
|
||||
|
||||
func NewUsersFromRows(rows *sql.Rows) ([]*User, error) {
|
||||
users := make([]*User, 0)
|
||||
// func NewUsersFromRows(rows *sql.Rows) ([]*User, error) {
|
||||
// users := make([]*User, 0)
|
||||
|
||||
// for rows.Next() {
|
||||
// var user User
|
||||
// if err := rows.Scan(&user.UserID, &user.Username, &user.Password, &user.RootPath, &user.Admin); err != nil {
|
||||
// return nil, errors.Wrap(err, "failed to scan users from database")
|
||||
// }
|
||||
// users = append(users, &user)
|
||||
// }
|
||||
|
||||
// rows.Close()
|
||||
|
||||
// return users, nil
|
||||
// }
|
||||
|
||||
func AuthorizeUser(db *gorm.DB, username string, password string) (*User, error) {
|
||||
// row := database.QueryRow("SELECT * FROM user WHERE username = ?", username)
|
||||
|
||||
for rows.Next() {
|
||||
var user User
|
||||
if err := rows.Scan(&user.UserID, &user.Username, &user.Password, &user.RootPath, &user.Admin); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to scan users from database")
|
||||
}
|
||||
users = append(users, &user)
|
||||
}
|
||||
|
||||
rows.Close()
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func AuthorizeUser(database *sql.DB, username string, password string) (*User, error) {
|
||||
row := database.QueryRow("SELECT * FROM user WHERE username = ?", username)
|
||||
|
||||
user, err := NewUserFromRow(row)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
result := db.Where("username = ?", username).First(&user)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrorInvalidUserCredentials
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.Wrap(result.Error, "failed to get user by username when authorizing")
|
||||
}
|
||||
|
||||
if user.Password == nil {
|
||||
|
@ -81,7 +85,7 @@ func AuthorizeUser(database *sql.DB, username string, password string) (*User, e
|
|||
}
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
var ErrorInvalidRootPath = errors.New("invalid root path")
|
||||
|
@ -96,11 +100,17 @@ func ValidRootPath(rootPath string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func RegisterUser(database *sql.Tx, username string, password *string, rootPath string, admin bool) (*User, error) {
|
||||
func RegisterUser(db *gorm.DB, username string, password *string, rootPath string, admin bool) (*User, error) {
|
||||
if !ValidRootPath(rootPath) {
|
||||
return nil, ErrorInvalidRootPath
|
||||
}
|
||||
|
||||
user := User{
|
||||
Username: username,
|
||||
RootPath: rootPath,
|
||||
Admin: admin,
|
||||
}
|
||||
|
||||
if password != nil {
|
||||
hashedPassBytes, err := bcrypt.GenerateFromPassword([]byte(*password), 12)
|
||||
if err != nil {
|
||||
|
@ -108,29 +118,18 @@ func RegisterUser(database *sql.Tx, username string, password *string, rootPath
|
|||
}
|
||||
hashedPass := string(hashedPassBytes)
|
||||
|
||||
if _, err := database.Exec("INSERT INTO user (username, password, root_path, admin) VALUES (?, ?, ?, ?)", username, hashedPass, rootPath, admin); err != nil {
|
||||
return nil, errors.Wrap(err, "insert new user with password into database")
|
||||
}
|
||||
} else {
|
||||
if _, err := database.Exec("INSERT INTO user (username, root_path, admin) VALUES (?, ?, ?)", username, rootPath, admin); err != nil {
|
||||
return nil, errors.Wrap(err, "insert user without password into database")
|
||||
}
|
||||
user.Password = &hashedPass
|
||||
}
|
||||
|
||||
row := database.QueryRow("SELECT * FROM user WHERE username = ?", username)
|
||||
if row == nil {
|
||||
return nil, ErrorInvalidUserCredentials
|
||||
result := db.Create(&user)
|
||||
if result.Error != nil {
|
||||
return nil, errors.Wrap(result.Error, "insert new user with password into database")
|
||||
}
|
||||
|
||||
user, err := NewUserFromRow(row)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (user *User) GenerateAccessToken(database *sql.Tx) (*AccessToken, error) {
|
||||
func (user *User) GenerateAccessToken(db *gorm.DB) (*AccessToken, error) {
|
||||
bytes := make([]byte, 24)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("Could not generate token: %s\n", err.Error()))
|
||||
|
@ -142,38 +141,56 @@ func (user *User) GenerateAccessToken(database *sql.Tx) (*AccessToken, error) {
|
|||
|
||||
token_value := string(bytes)
|
||||
expire := time.Now().Add(14 * 24 * time.Hour)
|
||||
expireString := expire.UTC().Format("2006-01-02 15:04:05")
|
||||
// expireString := expire.UTC().Format("2006-01-02 15:04:05")
|
||||
|
||||
if _, err := database.Exec("INSERT INTO access_token (value, expire, user_id) VALUES (?, ?, ?)", token_value, expireString, user.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// if _, err := database.Exec("INSERT INTO access_token (value, expire, user_id) VALUES (?, ?, ?)", token_value, expireString, user.UserID); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
token := AccessToken{
|
||||
UserID: user.ID,
|
||||
Value: token_value,
|
||||
Expire: expire,
|
||||
}
|
||||
|
||||
result := db.Create(&token)
|
||||
if result.Error != nil {
|
||||
return nil, errors.Wrap(result.Error, "saving access token to database")
|
||||
}
|
||||
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func VerifyTokenAndGetUser(database *sql.DB, token string) (*User, error) {
|
||||
func VerifyTokenAndGetUser(db *gorm.DB, token string) (*User, error) {
|
||||
|
||||
now := time.Now().UTC().Format("2006-01-02 15:04:05")
|
||||
|
||||
row := database.QueryRow("SELECT (user_id) FROM access_token WHERE expire > ? AND value = ?", now, token)
|
||||
// row := database.QueryRow("SELECT (user_id) FROM access_token WHERE expire > ? AND value = ?", now, token)
|
||||
|
||||
var userId string
|
||||
|
||||
if err := row.Scan(&userId); err != nil {
|
||||
log.Println(err.Error())
|
||||
return nil, err
|
||||
var accessToken AccessToken
|
||||
result := db.Where("expire > ? AND value = ?", now, token).First(&accessToken)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
row = database.QueryRow("SELECT * FROM user WHERE user_id = ?", userId)
|
||||
user, err := NewUserFromRow(row)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// var userId string
|
||||
|
||||
// if err := row.Scan(&userId); err != nil {
|
||||
// log.Println(err.Error())
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// row = db.QueryRow("SELECT * FROM user WHERE user_id = ?", userId)
|
||||
// user, err := NewUserFromRow(row)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
var user User
|
||||
result = db.First(&user, accessToken.ID)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return &user, nil
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@ package resolvers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
api "github.com/viktorstrate/photoview/api/graphql"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/99designs/gqlgen
|
||||
|
||||
type Resolver struct {
|
||||
Database *sql.DB
|
||||
Database *gorm.DB
|
||||
}
|
||||
|
||||
func (r *Resolver) Mutation() api.MutationResolver {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
api "github.com/viktorstrate/photoview/api/graphql"
|
||||
"github.com/viktorstrate/photoview/api/graphql/auth"
|
||||
|
@ -261,7 +262,7 @@ func hashSharePassword(password *string) (*string, error) {
|
|||
return hashed_password, nil
|
||||
}
|
||||
|
||||
func getUserToken(db *sql.DB, user *models.User, tokenValue string) (*models.ShareToken, error) {
|
||||
func getUserToken(db *gorm.DB, user *models.User, tokenValue string) (*models.ShareToken, error) {
|
||||
row := db.QueryRow(`
|
||||
SELECT share_token.* FROM share_token, user WHERE
|
||||
share_token.value = ? AND
|
||||
|
|
|
@ -8,9 +8,10 @@ import (
|
|||
"github.com/viktorstrate/photoview/api/graphql/auth"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func authenticateMedia(media *models.Media, db *sql.DB, r *http.Request) (success bool, responseMessage string, responseStatus int, errorMessage error) {
|
||||
func authenticateMedia(media *models.Media, db *gorm.DB, r *http.Request) (success bool, responseMessage string, responseStatus int, errorMessage error) {
|
||||
user := auth.UserFromContext(r.Context())
|
||||
|
||||
if user != nil {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -9,12 +8,13 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"github.com/viktorstrate/photoview/api/scanner"
|
||||
)
|
||||
|
||||
func RegisterPhotoRoutes(db *sql.DB, router *mux.Router) {
|
||||
func RegisterPhotoRoutes(db *gorm.DB, router *mux.Router) {
|
||||
|
||||
router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||
media_name := mux.Vars(r)["name"]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -11,9 +10,10 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"github.com/viktorstrate/photoview/api/scanner"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func RegisterVideoRoutes(db *sql.DB, router *mux.Router) {
|
||||
func RegisterVideoRoutes(db *gorm.DB, router *mux.Router) {
|
||||
|
||||
router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||
media_name := mux.Vars(r)["name"]
|
||||
|
|
|
@ -9,9 +9,10 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CleanupMedia(db *sql.DB, albumId int, albumMedia []*models.Media) []error {
|
||||
func CleanupMedia(db *gorm.DB, albumId int, albumMedia []*models.Media) []error {
|
||||
albumMediaIds := make([]interface{}, len(albumMedia))
|
||||
for i, photo := range albumMedia {
|
||||
albumMediaIds[i] = photo.MediaID
|
||||
|
@ -72,7 +73,7 @@ func CleanupMedia(db *sql.DB, albumId int, albumMedia []*models.Media) []error {
|
|||
return deleteErrors
|
||||
}
|
||||
|
||||
func deleteOldUserAlbums(db *sql.DB, scannedAlbums []*models.Album, user *models.User) []error {
|
||||
func deleteOldUserAlbums(db *gorm.DB, scannedAlbums []*models.Album, user *models.User) []error {
|
||||
if len(scannedAlbums) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
package scanner
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type periodicScanner struct {
|
||||
ticker *time.Ticker
|
||||
ticker_changed chan bool
|
||||
mutex *sync.Mutex
|
||||
db *sql.DB
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
var mainPeriodicScanner *periodicScanner = nil
|
||||
|
||||
func getPeriodicScanInterval(db *sql.DB) (time.Duration, error) {
|
||||
func getPeriodicScanInterval(db *gorm.DB) (time.Duration, error) {
|
||||
row := db.QueryRow("SELECT periodic_scan_interval FROM site_info")
|
||||
var intervalSeconds int
|
||||
|
||||
|
@ -27,7 +28,7 @@ func getPeriodicScanInterval(db *sql.DB) (time.Duration, error) {
|
|||
return time.Duration(intervalSeconds) * time.Second, nil
|
||||
}
|
||||
|
||||
func InitializePeriodicScanner(db *sql.DB) error {
|
||||
func InitializePeriodicScanner(db *gorm.DB) error {
|
||||
if mainPeriodicScanner != nil {
|
||||
panic("periodic scanner has already been initialized")
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package scanner
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
@ -11,6 +10,7 @@ import (
|
|||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"github.com/viktorstrate/photoview/api/graphql/notification"
|
||||
"github.com/viktorstrate/photoview/api/utils"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ScannerJob struct {
|
||||
|
@ -18,7 +18,7 @@ type ScannerJob struct {
|
|||
cache *AlbumScannerCache
|
||||
}
|
||||
|
||||
func (job *ScannerJob) Run(db *sql.DB) {
|
||||
func (job *ScannerJob) Run(db *gorm.DB) {
|
||||
scanAlbum(job.album, job.cache, db)
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,13 @@ type ScannerQueue struct {
|
|||
idle_chan chan bool
|
||||
in_progress []ScannerJob
|
||||
up_next []ScannerJob
|
||||
db *sql.DB
|
||||
db *gorm.DB
|
||||
settings ScannerQueueSettings
|
||||
}
|
||||
|
||||
var global_scanner_queue ScannerQueue
|
||||
|
||||
func InitializeScannerQueue(db *sql.DB) error {
|
||||
func InitializeScannerQueue(db *gorm.DB) error {
|
||||
|
||||
var concurrentWorkers int
|
||||
{
|
||||
|
@ -146,14 +146,11 @@ func (queue *ScannerQueue) notify() bool {
|
|||
}
|
||||
|
||||
func AddAllToQueue() error {
|
||||
rows, err := global_scanner_queue.db.Query("SELECT * FROM user")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get all users from database")
|
||||
}
|
||||
|
||||
users, err := models.NewUsersFromRows(rows)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse all users from db")
|
||||
var users []*models.User
|
||||
result := global_scanner_queue.db.Find(&users)
|
||||
if result.Error != nil {
|
||||
return errors.Wrap(result.Error, "get all users from database")
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
|
@ -167,7 +164,7 @@ func AddUserToQueue(user *models.User) error {
|
|||
album_cache := MakeAlbumCache()
|
||||
albums, album_errors := findAlbumsForUser(global_scanner_queue.db, user, album_cache)
|
||||
for _, err := range album_errors {
|
||||
return errors.Wrapf(err, "find albums for user (user_id: %d)", user.UserID)
|
||||
return errors.Wrapf(err, "find albums for user (user_id: %d)", user.ID)
|
||||
}
|
||||
|
||||
global_scanner_queue.mutex.Lock()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package scanner
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
@ -10,9 +9,10 @@ import (
|
|||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"github.com/viktorstrate/photoview/api/graphql/notification"
|
||||
"github.com/viktorstrate/photoview/api/utils"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func scanAlbum(album *models.Album, cache *AlbumScannerCache, db *sql.DB) {
|
||||
func scanAlbum(album *models.Album, cache *AlbumScannerCache, db *gorm.DB) {
|
||||
|
||||
album_notify_key := utils.GenerateToken()
|
||||
notifyThrottle := utils.NewThrottle(500 * time.Millisecond)
|
||||
|
@ -85,7 +85,7 @@ func scanAlbum(album *models.Album, cache *AlbumScannerCache, db *sql.DB) {
|
|||
}
|
||||
}
|
||||
|
||||
func findMediaForAlbum(album *models.Album, cache *AlbumScannerCache, db *sql.DB, onScanPhoto func(photo *models.Media, newPhoto bool)) ([]*models.Media, error) {
|
||||
func findMediaForAlbum(album *models.Album, cache *AlbumScannerCache, db *gorm.DB, onScanPhoto func(photo *models.Media, newPhoto bool)) ([]*models.Media, error) {
|
||||
|
||||
albumPhotos := make([]*models.Media, 0)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package scanner
|
|||
|
||||
import (
|
||||
"container/list"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -13,9 +12,10 @@ import (
|
|||
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||
"github.com/viktorstrate/photoview/api/graphql/notification"
|
||||
"github.com/viktorstrate/photoview/api/utils"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func findAlbumsForUser(db *sql.DB, user *models.User, album_cache *AlbumScannerCache) ([]*models.Album, []error) {
|
||||
func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScannerCache) ([]*models.Album, []error) {
|
||||
|
||||
// Check if user directory exists on the file system
|
||||
if _, err := os.Stat(user.RootPath); err != nil {
|
||||
|
|
|
@ -35,7 +35,6 @@ func main() {
|
|||
if err != nil {
|
||||
log.Panicf("Could not connect to database: %s\n", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Migrate database
|
||||
if err := database.MigrateDatabase(db); err != nil {
|
||||
|
|
Loading…
Reference in New Issue