[server][core] Move context into db

This commit is contained in:
Abhishek Shroff
2025-04-04 23:22:28 +05:30
parent ba8cb6ecc1
commit 18715cf10d
44 changed files with 148 additions and 166 deletions

View File

@@ -34,7 +34,7 @@ func CreateHandler() func(c *gin.Context) {
}
func extractUserDetails(c *gin.Context) (user.User, error) {
userManager := user.CreateManager(c.Request.Context())
userManager := user.ManagerFromContext(c.Request.Context())
if header := c.Request.Header.Get("Authorization"); header == "" {
return user.User{}, errAuthRequired
} else if auth, ok := checkAuthHeader(header, "basic"); ok {

View File

@@ -35,7 +35,7 @@ func createLoginRouteHandler() func(c *gin.Context) {
panic(errors.NewError(http.StatusBadRequest, "missing_password", "Password Not Specified"))
}
userManager := user.CreateManager(c.Request.Context())
userManager := user.ManagerFromContext(c.Request.Context())
if user, err := userManager.VerifyUserPassword(email, password); err != nil {
panic(err)
} else {

View File

@@ -23,7 +23,7 @@ func setupBookmarksRoutes(r *gin.RouterGroup) {
func handleBookmarksGetRoute(c *gin.Context) {
u := auth.GetUser(c)
bookmarks, err := user.CreateManager(c.Request.Context()).ListBookmarks(u)
bookmarks, err := user.ManagerFromContext(c.Request.Context()).ListBookmarks(u)
if err != nil {
panic(err)
}
@@ -46,7 +46,7 @@ func handleBookmarksAddRoute(c *gin.Context) {
if err != nil {
panic(err)
}
b, err := user.CreateManager(c.Request.Context()).AddBookmark(u, r, name)
b, err := user.ManagerFromContext(c.Request.Context()).AddBookmark(u, r, name)
if err != nil {
panic(err)
}
@@ -61,7 +61,7 @@ func handleBookmarksRemoveRoute(c *gin.Context) {
id := uuid.MustParse(idStr)
u := auth.GetUser(c)
if err := user.CreateManager(c.Request.Context()).RemoveBookmark(u, id); err != nil {
if err := user.ManagerFromContext(c.Request.Context()).RemoveBookmark(u, id); err != nil {
panic(err)
}
c.JSON(200, gin.H{})

View File

@@ -29,7 +29,7 @@ func handleUsersListRoute(c *gin.Context) {
t := time.UnixMilli(sinceInt - 1000).UTC()
since = &t
}
users, err := user.CreateManager(c.Request.Context()).ListUsers(since)
users, err := user.ManagerFromContext(c.Request.Context()).ListUsers(since)
if err != nil {
panic(err)
}

View File

@@ -15,7 +15,7 @@ func createBasicAuthHandler() func(c *gin.Context) {
authSuccess := false
if username, pass, ok := c.Request.BasicAuth(); ok {
ctx := c.Request.Context()
if u, err := user.CreateManager(ctx).VerifyUserPassword(username, pass); err == nil {
if u, err := user.ManagerFromContext(ctx).VerifyUserPassword(username, pass); err == nil {
c.Set(keyFileSystem, u.OpenFileSystem(ctx))
authSuccess = true
} else if !errors.Is(err, user.ErrCredentialsInvalid) {

View File

@@ -16,7 +16,7 @@ var f fs.FileSystem
func RootFileSystem() fs.FileSystem {
var rootUser user.User
if user, err := user.CreateManager(context.Background()).UserByEmail(db.DefaultUserUsername); err != nil {
if user, err := user.ManagerFromContext(context.Background()).UserByEmail(db.DefaultUserUsername); err != nil {
fmt.Println("unable to find root user: " + err.Error())
os.Exit(1)
} else {
@@ -32,7 +32,7 @@ func User(cmd *cobra.Command) user.User {
fmt.Println("could not read user: " + err.Error())
os.Exit(1)
} else {
if user, err := user.CreateManager(context.Background()).UserByEmail(value); err != nil {
if user, err := user.ManagerFromContext(context.Background()).UserByEmail(value); err != nil {
fmt.Println("could not find user '" + value + "': " + err.Error())
os.Exit(1)
} else {

View File

@@ -27,7 +27,7 @@ func setupChpermCommand() *cobra.Command {
}
username := args[1]
if _, err := user.CreateManager(context.Background()).UserByEmail(username); err != nil {
if _, err := user.ManagerFromContext(context.Background()).UserByEmail(username); err != nil {
fmt.Println("cannot update permissions for user '" + username + "': " + err.Error())
os.Exit(1)
}

View File

@@ -50,7 +50,7 @@ func setupSchemaMigrateCommand() *cobra.Command {
ctx := context.Background()
if args[0] == "auto" || args[0] == "latest" {
db.AutoMigrate = true
db.Get()
db.Get(ctx)
} else {
db.AutoMigrate = false
if v, err := strconv.Atoi(args[0]); err != nil {

View File

@@ -1,6 +1,7 @@
package serve
import (
"context"
"time"
"github.com/fvbock/endless"
@@ -70,8 +71,8 @@ func setupTrashCompactor() {
go func() {
for {
<-ticker.C
fs.TrashCompact(trashRetainDuration)
fs.TrashCompact(context.Background(), trashRetainDuration)
}
}()
fs.TrashCompact(trashRetainDuration)
fs.TrashCompact(context.Background(), trashRetainDuration)
}

View File

@@ -2,7 +2,6 @@ package storage
import (
"bufio"
"context"
"fmt"
"os"
"strings"
@@ -59,7 +58,7 @@ func setupStorageCreateCommand() *cobra.Command {
params[paramName] = val
}
if err := storage.Get().CreateBackend(context.Background(), name, driver, params); err != nil {
if err := storage.Get().CreateBackend(name, driver, params); err != nil {
logrus.Fatal(err)
}

View File

@@ -91,9 +91,8 @@ func setupUserAddCommand() *cobra.Command {
}
}
ctx := context.Background()
err = db.Get().RunInTx(ctx, func(db db.Handler) error {
userManager := user.CreateManager(ctx).WithDb(db)
err = db.Get(context.Background()).RunInTx(func(db db.Handler) error {
userManager := user.ManagerFromDB(db)
var u user.User
if user, err := userManager.CreateUser(username, displayName, password, root); err != nil {
return err

View File

@@ -32,7 +32,7 @@ func setupBookmarksListCommand() *cobra.Command {
Short: "List Bookmarks",
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
if bookmarks, err := user.CreateManager(context.Background()).ListBookmarks(common.User(cmd)); err != nil {
if bookmarks, err := user.ManagerFromContext(context.Background()).ListBookmarks(common.User(cmd)); err != nil {
fmt.Println("unable to list bookmark: " + err.Error())
os.Exit(1)
} else {
@@ -57,7 +57,7 @@ func setupBookmarksRemoveCommand() *cobra.Command {
os.Exit(1)
}
if err := user.CreateManager(context.Background()).RemoveBookmark(common.User(cmd), r.ID()); err != nil {
if err := user.ManagerFromContext(context.Background()).RemoveBookmark(common.User(cmd), r.ID()); err != nil {
fmt.Println("unable to remove bookmark: " + err.Error())
os.Exit(1)
}
@@ -82,7 +82,7 @@ func setupBookmarksAddCommand() *cobra.Command {
name = args[1]
}
if _, err := user.CreateManager(context.Background()).AddBookmark(common.User(cmd), r, name); err != nil {
if _, err := user.ManagerFromContext(context.Background()).AddBookmark(common.User(cmd), r, name); err != nil {
fmt.Println("unable to add bookmark: " + err.Error())
os.Exit(1)
}

View File

@@ -39,7 +39,7 @@ func setupUserChrootCommand() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
email := args[0]
idOrPath := args[1]
userManager := user.CreateManager(context.Background())
userManager := user.ManagerFromContext(context.Background())
if user, err := userManager.UserByEmail(email); err != nil {
logrus.Fatal(err)
} else {
@@ -59,7 +59,7 @@ func setupUserListCommand() *cobra.Command {
Use: "list",
Short: "List Users",
Run: func(cmd *cobra.Command, args []string) {
users, err := user.CreateManager(context.Background()).ListUsers(nil)
users, err := user.ManagerFromContext(context.Background()).ListUsers(nil)
if err != nil {
logrus.Fatal(err)
}

View File

@@ -19,7 +19,7 @@ func setupUserModCommand() *cobra.Command {
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
username := args[0]
u, err := user.CreateManager(context.Background()).UserByEmail(username)
u, err := user.ManagerFromContext(context.Background()).UserByEmail(username)
if err != nil {
fmt.Println("could not update user '" + username + "': " + err.Error())
os.Exit(1)
@@ -54,9 +54,8 @@ func setupUserModCommand() *cobra.Command {
}
}
ctx := context.Background()
err = db.Get().RunInTx(ctx, func(db db.Handler) error {
m := user.CreateManager(ctx).WithDb(db)
err = db.Get(context.Background()).RunInTx(func(db db.Handler) error {
m := user.ManagerFromDB(db)
if displayName != "" {
if err := m.UpdateUserDisplayName(u, displayName); err != nil {
return err

View File

@@ -13,41 +13,11 @@ const DefaultUserDisplayName = "Phylum"
func BootstrapData(ctx context.Context) error {
const q = "SELECT username FROM users WHERE username = $1::TEXT"
d := Get()
row := d.QueryRow(ctx, q, DefaultUserUsername)
d := Get(ctx)
row := d.QueryRow(q, DefaultUserUsername)
if err := row.Scan(nil); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
err = d.RunInTx(ctx, func(d Handler) error {
const createDir = `INSERT INTO resources(id, parent, name, dir, content_length, content_type, content_sha256)
VALUES ($1::UUID, $2::UUID, $3::TEXT, TRUE, 0, '', '')`
// Create root folder
rootID, _ := uuid.NewV7()
if _, err := d.Exec(ctx, createDir, rootID, nil, ""); err != nil {
return err
}
// Create home folder
homeID, _ := uuid.NewV7()
if _, err := d.Exec(ctx, createDir, homeID, rootID, "home"); err != nil {
return err
}
// Create user home folder
userHomeID, _ := uuid.NewV7()
if _, err := d.Exec(ctx, createDir, userHomeID, homeID, DefaultUserUsername); err != nil {
return err
}
const createRootUser = `INSERT INTO users(username, display_name, password_hash, root, home, permissions)
VALUES ($1::TEXT, $2::TEXT, '', $3::UUID, $4::UUID, -1)`
if _, err := d.Exec(ctx, createRootUser, DefaultUserUsername, DefaultUserDisplayName, rootID, userHomeID); err != nil {
return err
}
return nil
})
err = d.RunInTx(insertData)
}
if err != nil {
return err
@@ -56,3 +26,35 @@ VALUES ($1::TEXT, $2::TEXT, '', $3::UUID, $4::UUID, -1)`
return nil
}
func insertData(d Handler) error {
const createDir = `INSERT INTO resources(id, parent, name, dir, content_length, content_type, content_sha256)
VALUES ($1::UUID, $2::UUID, $3::TEXT, TRUE, 0, '', '')`
// Create root folder
rootID, _ := uuid.NewV7()
if _, err := d.Exec(createDir, rootID, nil, ""); err != nil {
return err
}
// Create home folder
homeID, _ := uuid.NewV7()
if _, err := d.Exec(createDir, homeID, rootID, "home"); err != nil {
return err
}
// Create user home folder
userHomeID, _ := uuid.NewV7()
if _, err := d.Exec(createDir, userHomeID, homeID, DefaultUserUsername); err != nil {
return err
}
const createRootUser = `INSERT INTO users(username, display_name, password_hash, root, home, permissions)
VALUES ($1::TEXT, $2::TEXT, '', $3::UUID, $4::UUID, -1)`
if _, err := d.Exec(createRootUser, DefaultUserUsername, DefaultUserDisplayName, rootID, userHomeID); err != nil {
return err
}
return nil
}

View File

@@ -15,7 +15,7 @@ var AutoMigrate bool
var pool *pgxpool.Pool
func Get() Handler {
func Get(ctx context.Context) Handler {
if pool == nil {
if p, err := createPool(context.Background(), DatabaseURL, TraceSQL, AutoMigrate); err != nil {
logrus.Fatal(err)
@@ -23,7 +23,10 @@ func Get() Handler {
pool = p
}
}
return Handler{tx: pool}
return Handler{
ctx: ctx,
tx: pool,
}
}
func Close() {
if pool != nil {

View File

@@ -8,7 +8,8 @@ import (
)
type Handler struct {
tx interface {
ctx context.Context
tx interface {
Begin(context.Context) (pgx.Tx, error)
SendBatch(context.Context, *pgx.Batch) pgx.BatchResults
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
@@ -18,31 +19,32 @@ type Handler struct {
}
}
func (h Handler) RunInTx(ctx context.Context, fn func(Handler) error) error {
return pgx.BeginFunc(ctx, h.tx, func(tx pgx.Tx) error {
func (h Handler) RunInTx(fn func(Handler) error) error {
return pgx.BeginFunc(h.ctx, h.tx, func(tx pgx.Tx) error {
h := Handler{
tx: tx,
ctx: h.ctx,
tx: tx,
}
return fn(h)
})
}
func (h Handler) Exec(ctx context.Context, stmt string, args ...interface{}) (pgconn.CommandTag, error) {
return h.tx.Exec(ctx, stmt, args...)
func (h Handler) Exec(stmt string, args ...interface{}) (pgconn.CommandTag, error) {
return h.tx.Exec(h.ctx, stmt, args...)
}
func (h Handler) Query(ctx context.Context, stmt string, args ...interface{}) (pgx.Rows, error) {
return h.tx.Query(ctx, stmt, args...)
func (h Handler) Query(stmt string, args ...interface{}) (pgx.Rows, error) {
return h.tx.Query(h.ctx, stmt, args...)
}
func (h Handler) QueryRow(ctx context.Context, stmt string, args ...interface{}) pgx.Row {
return h.tx.QueryRow(ctx, stmt, args...)
func (h Handler) QueryRow(stmt string, args ...interface{}) pgx.Row {
return h.tx.QueryRow(h.ctx, stmt, args...)
}
func (h Handler) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) {
return h.tx.CopyFrom(ctx, tableName, columnNames, rowSrc)
func (h Handler) CopyFrom(tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) {
return h.tx.CopyFrom(h.ctx, tableName, columnNames, rowSrc)
}
func (h Handler) SendBatch(ctx context.Context, batch *pgx.Batch) pgx.BatchResults {
return h.tx.SendBatch(ctx, batch)
func (h Handler) SendBatch(batch *pgx.Batch) pgx.BatchResults {
return h.tx.SendBatch(h.ctx, batch)
}

View File

@@ -55,7 +55,7 @@ func checkVersion(ctx context.Context, autoMigrate bool) error {
}
func Migrate(ctx context.Context, version int) error {
Get() // Initialize the pool, just in case
Get(ctx) // Initialize the pool, just in case
conn, err := pool.Acquire(ctx)
if err != nil {
return err
@@ -92,22 +92,22 @@ func Migrate(ctx context.Context, version int) error {
}
func DeleteSchema(ctx context.Context) error {
h := Get()
h := Get(ctx)
user := pool.Config().ConnConfig.User
return h.RunInTx(ctx, func(d Handler) (err error) {
if _, err = d.Exec(ctx, "DROP SCHEMA public CASCADE"); err != nil {
return h.RunInTx(func(d Handler) (err error) {
if _, err = d.Exec("DROP SCHEMA public CASCADE"); err != nil {
return
}
if _, err = d.Exec(ctx, "CREATE SCHEMA public"); err != nil {
if _, err = d.Exec("CREATE SCHEMA public"); err != nil {
return
}
if _, err = d.Exec(ctx, "GRANT ALL ON SCHEMA public TO "+user); err != nil {
if _, err = d.Exec("GRANT ALL ON SCHEMA public TO " + user); err != nil {
return
}
if _, err = d.Exec(ctx, "GRANT ALL ON SCHEMA public TO public"); err != nil {
if _, err = d.Exec("GRANT ALL ON SCHEMA public TO public"); err != nil {
return
}
_, err = d.Exec(ctx, "COMMENT ON SCHEMA public IS 'standard public schema'")
_, err = d.Exec("COMMENT ON SCHEMA public IS 'standard public schema'")
return
})
}

View File

@@ -37,7 +37,7 @@ const ancestorsQuery = `WITH RECURSIVE nodes(id, name, parent, permissions) AS (
SELECT id, name, parent, permissions FROM nodes`
func (r Resource) GetAncestors() ([]ResourceAncestor, error) {
if rows, err := r.f.db.Query(r.f.ctx, ancestorsQuery, r.parentID); err != nil {
if rows, err := r.f.db.Query(ancestorsQuery, r.parentID); err != nil {
return nil, err
} else {
return pgx.CollectRows(rows, r.f.scanResourceAncestor)

View File

@@ -98,7 +98,7 @@ func (f filesystem) updateResourceNameParent(id uuid.UUID, name string, parent u
}
q, args, _ := pg.Update("resources").Where(goqu.C("id").Eq(id)).Set(updates).ToSQL()
if _, err := f.db.Exec(f.ctx, q, args...); err != nil {
if _, err := f.db.Exec(q, args...); err != nil {
if strings.Contains(err.Error(), "unique_member_resource_name") {
return ErrResourceNameConflict
}

View File

@@ -226,7 +226,7 @@ func (f filesystem) insertResource(id, parent uuid.UUID, name string, dir bool,
}).
Returning("*").
ToSQL()
if rows, err := f.db.Query(f.ctx, query, args...); err != nil {
if rows, err := f.db.Query(query, args...); err != nil {
return Resource{}, err
} else {
return f.collectResource(rows)

View File

@@ -49,5 +49,5 @@ func (r iteratorForCreateResources) Err() error {
}
func (f filesystem) CreateResources(arg []CreateResourcesParams) (int64, error) {
return f.db.CopyFrom(f.ctx, []string{"resources"}, []string{"id", "parent", "name", "dir", "content_length", "content_type", "content_sha256"}, &iteratorForCreateResources{rows: arg})
return f.db.CopyFrom([]string{"resources"}, []string{"id", "parent", "name", "dir", "content_length", "content_type", "content_sha256"}, &iteratorForCreateResources{rows: arg})
}

View File

@@ -24,7 +24,7 @@ func (r Resource) DiskUsage() (DiskUsageInfo, error) {
query, args, _ := q.ToSQL()
row := r.f.db.QueryRow(r.f.ctx, query, args...)
row := r.f.db.QueryRow(query, args...)
var size, count, dirs int64
err := row.Scan(&size, &count, &dirs)
return DiskUsageInfo{

View File

@@ -1,15 +1,12 @@
package fs
import (
"context"
"github.com/google/uuid"
"github.com/shroff/phylum/server/internal/core/db"
"github.com/shroff/phylum/server/internal/core/storage"
)
type filesystem struct {
ctx context.Context
db db.Handler
cs storage.Storage
rootID uuid.UUID
@@ -27,7 +24,6 @@ func (f filesystem) WithRoot(id uuid.UUID) FileSystem {
func (f filesystem) withRoot(id uuid.UUID) filesystem {
return filesystem{
ctx: f.ctx,
db: f.db,
cs: f.cs,
rootID: id,
@@ -42,7 +38,6 @@ func (f filesystem) WithDb(db db.Handler) FileSystem {
func (f filesystem) withDb(db db.Handler) filesystem {
return filesystem{
ctx: f.ctx,
db: db,
cs: f.cs,
rootID: f.rootID,
@@ -52,13 +47,13 @@ func (f filesystem) withDb(db db.Handler) filesystem {
}
func (f filesystem) RunInTx(fn func(FileSystem) error) error {
return f.db.RunInTx(f.ctx, func(db db.Handler) error {
return f.db.RunInTx(func(db db.Handler) error {
return fn(f.WithDb(db))
})
}
func (f filesystem) runInTx(fn func(filesystem) error) error {
return f.db.RunInTx(f.ctx, func(db db.Handler) error {
return f.db.RunInTx(func(db db.Handler) error {
return fn(f.withDb(db))
})
}

View File

@@ -31,7 +31,7 @@ func (f filesystem) ResourceByPath(path string) (Resource, error) {
query, args, _ := q.ToSQL()
if rows, err := f.db.Query(f.ctx, query, args...); err != nil {
if rows, err := f.db.Query(query, args...); err != nil {
return Resource{}, err
} else {
return f.collectResource(rows)
@@ -40,7 +40,7 @@ func (f filesystem) ResourceByPath(path string) (Resource, error) {
func (f filesystem) ResourceByID(id uuid.UUID) (Resource, error) {
const query = "SELECT * FROM resources WHERE id = $1::UUID"
if rows, err := f.db.Query(f.ctx, query, id); err != nil {
if rows, err := f.db.Query(query, id); err != nil {
return Resource{}, err
} else {
return f.collectResource(rows)
@@ -49,7 +49,7 @@ func (f filesystem) ResourceByID(id uuid.UUID) (Resource, error) {
func (f filesystem) ChildResourceByName(parentID uuid.UUID, name string) (Resource, error) {
const query = "SELECT * FROM resources WHERE parent = $1::UUID AND name = $2::TEXT AND deleted IS NULL"
if rows, err := f.db.Query(f.ctx, query, parentID, name); err != nil {
if rows, err := f.db.Query(query, parentID, name); err != nil {
return Resource{}, err
} else {
return f.collectResource(rows)

View File

@@ -62,8 +62,7 @@ type FileSystem interface {
func Open(ctx context.Context, username string, root uuid.UUID, fullAccess bool) FileSystem {
return filesystem{
ctx: ctx,
db: db.Get(),
db: db.Get(ctx),
cs: storage.Get(),
username: username,
rootID: root,
@@ -72,7 +71,7 @@ func Open(ctx context.Context, username string, root uuid.UUID, fullAccess bool)
}
func OpenFromPublink(ctx context.Context, name string, password string, path string) (Resource, error) {
d := db.Get()
d := db.Get(ctx)
link, err := getPublink(d, ctx, name)
if err != nil {
return Resource{}, err
@@ -101,12 +100,11 @@ func OpenFromPublink(ctx context.Context, name string, password string, path str
}
const q = "UPDATE publinks SET accessed = accessed + 1 WHERE id = $1"
if _, err := d.Exec(ctx, q, link.ID); err != nil {
if _, err := d.Exec(q, link.ID); err != nil {
return Resource{}, err
}
f := filesystem{
ctx: ctx,
db: d,
cs: storage.Get(),
rootID: link.Root,
@@ -118,7 +116,7 @@ func OpenFromPublink(ctx context.Context, name string, password string, path str
func getPublink(d db.Handler, ctx context.Context, name string) (Publink, error) {
q := "SELECT FROM publinks p WHERE name = $1::TEXT AND deleted IS NULL"
if rows, err := d.Query(ctx, q, name); err != nil {
if rows, err := d.Query(q, name); err != nil {
return Publink{}, err
} else if link, err := pgx.CollectExactlyOneRow(rows, scanPublink); err != nil {
if errors.Is(err, pgx.ErrNoRows) {

View File

@@ -44,7 +44,7 @@ func (r Resource) ReadDirDeleted(recursive, includeDeleted bool) ([]Resource, er
}
query, args, _ := q.ToSQL()
if rows, err := r.f.db.Query(r.f.ctx, query, args...); err != nil {
if rows, err := r.f.db.Query(query, args...); err != nil {
return nil, err
} else {
return pgx.CollectRows(rows, r.f.scanResource)

View File

@@ -31,7 +31,7 @@ UPDATE resources SET
WHERE id = @resource_id::UUID`
err := r.f.runInTx(func(f filesystem) error {
if _, err := f.db.Exec(f.ctx, q, pgx.NamedArgs{
if _, err := f.db.Exec(q, pgx.NamedArgs{
"resource_id": r.id,
"username": username,
"permission": permission,
@@ -81,6 +81,6 @@ UPDATE resources
FROM nodes
WHERE resources.id = nodes.id`
_, err := f.db.Exec(f.ctx, q, id)
_, err := f.db.Exec(q, id)
return err
}

View File

@@ -67,13 +67,13 @@ func (r Resource) CreatePublink(name, password string, duration time.Duration, a
const q = `INSERT INTO publinks(name, created_by, root, password_hash, expires, max_accesses) VALUES
($1::text, $2::text, $3::uuid, $4::text, $5::timestamp, $6::int)`
_, err := r.f.db.Exec(r.f.ctx, q, name, r.f.username, r.ID(), passwordHash, expires, accesses)
_, err := r.f.db.Exec(q, name, r.f.username, r.ID(), passwordHash, expires, accesses)
return err
}
func (r Resource) ListPublinks() ([]Publink, error) {
const q = "SELECT * FROM publinks WHERE root = $1::UUID"
if rows, err := r.f.db.Query(r.f.ctx, q, r.id); err != nil {
if rows, err := r.f.db.Query(q, r.id); err != nil {
return nil, err
} else if links, err := pgx.CollectRows(rows, scanPublink); err != nil {
return nil, err

View File

@@ -176,7 +176,7 @@ func (f filesystem) markDeleted(id uuid.UUID, softDelete, excludeRoot bool) (int
ToSQL()
}
return collectNonDirResourceIDs(f.db.Query(f.ctx, query, params...))
return collectNonDirResourceIDs(f.db.Query(query, params...))
}
func (f filesystem) markNotDeleted(id uuid.UUID) ([]int64, error) {
@@ -190,7 +190,7 @@ func (f filesystem) markNotDeleted(id uuid.UUID) ([]int64, error) {
query, params, _ := q.ToSQL()
rows, err := f.db.Query(f.ctx, query, params...)
rows, err := f.db.Query(query, params...)
if err != nil {
return nil, err
}

View File

@@ -23,7 +23,7 @@ WHERE f_prepare_search(name) %> @query::TEXT`)
"username": f.username,
}
if rows, err := f.db.Query(f.ctx, qb.String(), args); err != nil {
if rows, err := f.db.Query(qb.String(), args); err != nil {
return nil, err
} else {
return pgx.CollectRows(rows, f.scanResource)

View File

@@ -9,7 +9,7 @@ AND id <> $2::UUID
AND deleted IS NULL
AND grants -> $1::TEXT -> 'p' <> 0
ORDER BY grants -> $1::TEXT -> 't' DESC`
if rows, err := f.db.Query(f.ctx, q, f.username); err != nil {
if rows, err := f.db.Query(q, f.username); err != nil {
return nil, err
} else {
return pgx.CollectRows(rows, f.scanResource)

View File

@@ -11,23 +11,23 @@ import (
"github.com/sirupsen/logrus"
)
func TrashCompact(duration time.Duration) {
func TrashCompact(ctx context.Context, duration time.Duration) {
t := time.Now().Add(-duration)
if d, err := hardDeleteOldResources(t); err != nil {
if d, err := hardDeleteOldResources(ctx, t); err != nil {
logrus.Error(err)
} else {
logrus.Info(fmt.Sprintf("Removed %d files deleted before %s", d, t.Format(time.RFC1123)))
}
}
func hardDeleteOldResources(t time.Time) (int, error) {
func hardDeleteOldResources(ctx context.Context, t time.Time) (int, error) {
q := pg.
From("resources").
Where(goqu.C("deleted").Lt(goqu.V(t.UTC()))).
Delete().
Returning("id", "dir")
query, args, _ := q.ToSQL()
count, ids, err := collectNonDirResourceIDs(db.Get().Query(context.Background(), query, args...))
count, ids, err := collectNonDirResourceIDs(db.Get(ctx).Query(query, args...))
if err != nil {
return 0, err
}

View File

@@ -42,7 +42,7 @@ func (f filesystem) TrashList(cursor string, n uint) ([]Resource, string, error)
Limit(n).
ToSQL()
if rows, err := f.db.Query(f.ctx, query, params...); err != nil {
if rows, err := f.db.Query(query, params...); err != nil {
return nil, "", err
} else if res, err := pgx.CollectRows(rows, f.scanResource); err != nil {
return nil, "", err

View File

@@ -22,7 +22,7 @@ func (f filesystem) TrashSummary() (int, int, error) {
goqu.COUNT("*"))
query, args, _ := q.ToSQL()
row := f.db.QueryRow(f.ctx, query, args...)
row := f.db.QueryRow(query, args...)
var size int
var items int
err := row.Scan(&size, &items)
@@ -34,7 +34,7 @@ func (f filesystem) TrashEmpty() (int, error) {
Delete().
Returning("id", "dir")
query, args, _ := q.ToSQL()
count, ids, err := collectNonDirResourceIDs(f.db.Query(f.ctx, query, args...))
count, ids, err := collectNonDirResourceIDs(f.db.Query(query, args...))
storage.Get().DeleteAll(ids)
return count, err
}

View File

@@ -6,7 +6,7 @@ import (
func (f filesystem) updateResourceModified(id uuid.UUID) error {
const q = "UPDATE resources SET modified = NOW() WHERE id = $1"
_, err := f.db.Exec(f.ctx, q, id)
_, err := f.db.Exec(q, id)
return err
}
func (f filesystem) updateResourceContents(id uuid.UUID, contentLength int, contentType, contentSHA256 string) error {
@@ -17,6 +17,6 @@ func (f filesystem) updateResourceContents(id uuid.UUID, contentLength int, cont
modified = NOW()
WHERE id = $1::UUID
`
_, err := f.db.Exec(f.ctx, q, id, contentLength, contentType, contentSHA256)
_, err := f.db.Exec(q, id, contentLength, contentType, contentSHA256)
return err
}

View File

@@ -1,7 +1,6 @@
package storage
import (
"context"
"encoding/hex"
"encoding/json"
"errors"
@@ -15,7 +14,7 @@ import (
)
type Storage interface {
CreateBackend(ctx context.Context, name string, driver string, params map[string]string) error
CreateBackend(name string, driver string, params map[string]string) error
ListBackends() map[string]Backend
OpenRead(id uuid.UUID, start, length int) (io.ReadCloser, error)
OpenWrite(id uuid.UUID, h func() hash.Hash, callback func(int, string, string) error) (io.WriteCloser, error)
@@ -35,7 +34,7 @@ var DefaultStorageDir string
func Get() Storage {
if s == nil {
if storage, err := create(context.Background(), db.Get(), DefaultStorageDir); err != nil {
if storage, err := create(db.Get(), DefaultStorageDir); err != nil {
logrus.Fatal(err)
} else {
s = storage
@@ -44,8 +43,8 @@ func Get() Storage {
return s
}
func create(ctx context.Context, db db.Handler, defaultStorageDir string) (Storage, error) {
if backends, err := restoreBackends(db, ctx); err != nil {
func create(db db.Handler, defaultStorageDir string) (Storage, error) {
if backends, err := restoreBackends(db); err != nil {
return nil, err
} else if defaultBackend, err := newLocalStorage("<default>", defaultStorageDir); err != nil {
return nil, err
@@ -123,7 +122,7 @@ func (s *storage) findStorageBackend(id uuid.UUID) (Backend, error) {
return s.defaultBackend, nil
}
func (s storage) CreateBackend(ctx context.Context, name string, driver string, params map[string]string) error {
func (s storage) CreateBackend(name string, driver string, params map[string]string) error {
backend, err := openBackend(name, driver, params)
if err != nil {
return nil
@@ -133,7 +132,7 @@ func (s storage) CreateBackend(ctx context.Context, name string, driver string,
if err != nil {
return err
}
if _, err := s.db.Exec(ctx, q, name, driver, p); err != nil {
if _, err := s.db.Exec(q, name, driver, p); err != nil {
return err
}
s.backends[name] = backend
@@ -144,9 +143,9 @@ func (s storage) ListBackends() map[string]Backend {
return s.backends
}
func restoreBackends(db db.Handler, ctx context.Context) (map[string]Backend, error) {
func restoreBackends(db db.Handler) (map[string]Backend, error) {
const q = "SELECT name, driver, params from storage_backends"
if rows, err := db.Query(ctx, q); err != nil {
if rows, err := db.Query(q); err != nil {
return nil, err
} else if backends, err := pgx.CollectRows(rows, func(row pgx.CollectableRow) (Backend, error) {
var name, driver string

View File

@@ -41,7 +41,7 @@ func (m manager) VerifyUserPassword(email, password string) (User, error) {
func (m manager) CreateAccessToken(username string) (string, error) {
const q = `INSERT INTO access_tokens(id, expires, username) VALUES ($1::text, NOW() + $2::interval, $3::text)`
id := GenerateRandomString(accessTokenLength)
if _, err := m.db.Exec(m.ctx, q, id, accessTokenValidity, username); err != nil {
if _, err := m.db.Exec(q, id, accessTokenValidity, username); err != nil {
return "", err
} else {
return id, nil
@@ -50,7 +50,7 @@ func (m manager) CreateAccessToken(username string) (string, error) {
func (m manager) ReadAccessToken(accessToken string) (User, error) {
const q = `SELECT t.expires, u.username, u.display_name, u.permissions, u.root, u.home FROM access_tokens t JOIN users u ON t.username = u.username WHERE t.id = $1; `
row := m.db.QueryRow(m.ctx, q, accessToken)
row := m.db.QueryRow(q, accessToken)
var expires pgtype.Timestamp
var username string

View File

@@ -44,7 +44,7 @@ SET
name = $3::TEXT
RETURNING resource_id, name, dir, created`
if rows, err := m.db.Query(m.ctx, q, u.Username); err != nil {
if rows, err := m.db.Query(q, u.Username); err != nil {
return Bookmark{}, err
} else if bookmark, err := pgx.CollectExactlyOneRow(rows, scanBookmark); err != nil {
return Bookmark{}, err
@@ -55,7 +55,7 @@ RETURNING resource_id, name, dir, created`
func (m manager) RemoveBookmark(u User, id uuid.UUID) error {
const q = "DELETE FROM bookmarks WHERE username = $1::TEXT AND resource_id = $2::UUID"
_, err := m.db.Exec(m.ctx, q, u.Username, id)
_, err := m.db.Exec(q, u.Username, id)
return err
}
@@ -66,7 +66,7 @@ WHERE username = $1::TEXT
AND deleted IS NULL
ORDER BY modified DESC`
if rows, err := m.db.Query(m.ctx, q, u.Username); err != nil {
if rows, err := m.db.Query(q, u.Username); err != nil {
return nil, err
} else if bookmarks, err := pgx.CollectRows(rows, scanBookmark); err != nil {
return nil, err

View File

@@ -19,7 +19,7 @@ RETURNING username, display_name, password_hash, root, home, permissions`
if hash, err := crypt.GenerateArgon2EncodedHash(password); err != nil {
return User{}, err
} else if rows, err := m.db.Query(m.ctx, q, username, displayName, hash, root, root); err != nil {
} else if rows, err := m.db.Query(q, username, displayName, hash, root, root); err != nil {
if strings.Contains(err.Error(), "users_pkey") {
err = ErrUserExists
}

View File

@@ -7,24 +7,13 @@ import (
)
type manager struct {
db db.Handler
ctx context.Context
db db.Handler
}
func CreateManager(ctx context.Context) Manager {
return &manager{
ctx: ctx,
db: db.Get(),
}
func ManagerFromContext(ctx context.Context) Manager {
return manager{db: db.Get(ctx)}
}
func (m manager) WithDb(db db.Handler) Manager {
return m.withDb(db)
}
func (m manager) withDb(db db.Handler) manager {
return manager{
ctx: m.ctx,
db: db,
}
func ManagerFromDB(db db.Handler) Manager {
return manager{db: db}
}

View File

@@ -19,7 +19,7 @@ func (m manager) ListUsers(since *time.Time) ([]BasicUser, error) {
s.Time = *since
}
const q = "SELECT username, display_name FROM users WHERE modified > $1::TIMESTAMP"
if rows, err := m.db.Query(m.ctx, q, s); err != nil {
if rows, err := m.db.Query(q, s); err != nil {
return nil, err
} else {
return pgx.CollectRows(rows, scanBasicUser)
@@ -28,7 +28,7 @@ func (m manager) ListUsers(since *time.Time) ([]BasicUser, error) {
func (m manager) UserByEmail(email string) (User, error) {
const q = "SELECT username, display_name, password_hash, root, home, permissions FROM users WHERE username = $1"
if rows, err := m.db.Query(m.ctx, q, email); err != nil {
if rows, err := m.db.Query(q, email); err != nil {
return User{}, err
} else if u, err := pgx.CollectExactlyOneRow(rows, scanUser); err != nil {
if errors.Is(err, pgx.ErrNoRows) {

View File

@@ -6,7 +6,7 @@ import (
func (m manager) UpdateUserRoot(user User, root uuid.UUID) error {
const q = "UPDATE users SET root = $2::UUID, modified = NOW() WHERE username = $1::TEXT"
if _, err := m.db.Exec(m.ctx, q, user.Username, root); err != nil {
if _, err := m.db.Exec(q, user.Username, root); err != nil {
return err
}
return nil
@@ -14,7 +14,7 @@ func (m manager) UpdateUserRoot(user User, root uuid.UUID) error {
func (m manager) UpdateUserHome(user User, home uuid.UUID) error {
const q = "UPDATE users SET home = $2::UUID, modified = NOW() WHERE username = $1::TEXT"
if _, err := m.db.Exec(m.ctx, q, user.Username, home); err != nil {
if _, err := m.db.Exec(q, user.Username, home); err != nil {
return err
}
return nil
@@ -22,7 +22,7 @@ func (m manager) UpdateUserHome(user User, home uuid.UUID) error {
func (m manager) UpdateUserDisplayName(user User, displayName string) error {
const q = "UPDATE users SET display_name = $2::UUID, modified = NOW() WHERE username = $1::TEXT"
if _, err := m.db.Exec(m.ctx, q, user.Username, displayName); err != nil {
if _, err := m.db.Exec(q, user.Username, displayName); err != nil {
return err
}
return nil
@@ -30,7 +30,7 @@ func (m manager) UpdateUserDisplayName(user User, displayName string) error {
func (m manager) UpdateUserPasswordHash(user User, passwordHash string) error {
const q = "UPDATE users SET password_hash = $2::TEXT, modified = NOW() WHERE username = $1::TEXT"
if _, err := m.db.Exec(m.ctx, q, user.Username, passwordHash); err != nil {
if _, err := m.db.Exec(q, user.Username, passwordHash); err != nil {
return err
}
return nil
@@ -38,7 +38,7 @@ func (m manager) UpdateUserPasswordHash(user User, passwordHash string) error {
func (m manager) GrantUserPermissions(user User, permissions int) error {
const q = "UPDATE users SET permissions = permissions | $2::INTEGER, modified = NOW() WHERE username = $1::UUID"
if _, err := m.db.Exec(m.ctx, q, user.Username, permissions); err != nil {
if _, err := m.db.Exec(q, user.Username, permissions); err != nil {
return err
}
return nil
@@ -46,7 +46,7 @@ func (m manager) GrantUserPermissions(user User, permissions int) error {
func (m manager) RevokeUserPermissions(user User, permissions int) error {
const q = "UPDATE users SET permissions = permissions & ~ $2::INTEGER, modified = NOW() WHERE username = $1::UUID"
if _, err := m.db.Exec(m.ctx, q, user.Username, permissions); err != nil {
if _, err := m.db.Exec(q, user.Username, permissions); err != nil {
return err
}
return nil

View File

@@ -6,7 +6,6 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/shroff/phylum/server/internal/core/db"
"github.com/shroff/phylum/server/internal/core/fs"
)
@@ -50,9 +49,6 @@ func (u User) OpenFileSystem(ctx context.Context) fs.FileSystem {
}
type Manager interface {
// manager.go
WithDb(db db.Handler) Manager
// create.go
CreateUser(username, displayName, password string, root uuid.UUID) (User, error)