refactor: account model overhaul

This commit is contained in:
2026-01-01 18:29:52 +00:00
parent ad7d7c6a1b
commit 88492dd876
49 changed files with 1559 additions and 573 deletions

View File

@@ -29,7 +29,7 @@ func (r *HierarchicalKeyResolver) Resolve(ctx context.Context, db bun.IDB, node
return "", err
}
return blob.Key(fmt.Sprintf("%s/%s", node.AccountID, path)), nil
return blob.Key(fmt.Sprintf("%s/%s", node.DriveID, path)), nil
}
func (r *HierarchicalKeyResolver) ResolveDeletionKeys(ctx context.Context, node *Node, allKeys []blob.Key) (*DeletionPlan, error) {
@@ -37,7 +37,7 @@ func (r *HierarchicalKeyResolver) ResolveDeletionKeys(ctx context.Context, node
if err != nil {
return nil, err
}
return &DeletionPlan{Prefix: blob.Key(fmt.Sprintf("%s/%s", node.AccountID, path))}, nil
return &DeletionPlan{Prefix: blob.Key(fmt.Sprintf("%s/%s", node.DriveID, path))}, nil
}
// ResolveBulkMoveOps computes blob move operations for nodes being moved to a new parent.
@@ -48,7 +48,7 @@ func (r *HierarchicalKeyResolver) ResolveBulkMoveOps(ctx context.Context, db bun
return nil, nil
}
accountID := nodes[0].AccountID
driveID := nodes[0].DriveID
oldParentID := nodes[0].ParentID
for _, node := range nodes[1:] {
@@ -70,8 +70,8 @@ func (r *HierarchicalKeyResolver) ResolveBulkMoveOps(ctx context.Context, db bun
// For each node, construct old and new keys using the precomputed parent paths
ops := make([]BlobMoveOp, len(nodes))
for i, node := range nodes {
oldKey := blob.Key(fmt.Sprintf("%s/%s/%s", accountID, oldParentPath, node.Name))
newKey := blob.Key(fmt.Sprintf("%s/%s/%s", accountID, newParentPath, node.Name))
oldKey := blob.Key(fmt.Sprintf("%s/%s/%s", driveID, oldParentPath, node.Name))
newKey := blob.Key(fmt.Sprintf("%s/%s/%s", driveID, newParentPath, node.Name))
ops[i] = BlobMoveOp{Node: node, OldKey: oldKey, NewKey: newKey}
}

View File

@@ -25,13 +25,13 @@ const (
type Node struct {
bun.BaseModel `bun:"vfs_nodes"`
ID uuid.UUID `bun:",pk,type:uuid"`
PublicID string `bun:"public_id,notnull"`
AccountID uuid.UUID `bun:"account_id,notnull,type:uuid"`
ParentID uuid.UUID `bun:"parent_id,nullzero"`
Kind NodeKind `bun:"kind,notnull"`
Status NodeStatus `bun:"status,notnull"`
Name string `bun:"name,notnull"`
ID uuid.UUID `bun:",pk,type:uuid"`
PublicID string `bun:"public_id,notnull"`
DriveID uuid.UUID `bun:"drive_id,notnull,type:uuid"`
ParentID uuid.UUID `bun:"parent_id,nullzero"`
Kind NodeKind `bun:"kind,notnull"`
Status NodeStatus `bun:"status,notnull"`
Name string `bun:"name,notnull"`
BlobKey blob.Key `bun:"blob_key,nullzero"`
Size int64 `bun:"size"`

View File

@@ -5,8 +5,8 @@ import "github.com/google/uuid"
// Scope defines the bounded view of the virtual filesystem that a caller is allowed to operate on.
// It is populated by higher layers (account/share middleware) and enforced by VFS methods.
type Scope struct {
// AccountID is the owner of the storage. It stays constant even when a share actor accesses it.
AccountID uuid.UUID
// DriveID is the owner of the storage (the tenant). It stays constant even when a share actor accesses it.
DriveID uuid.UUID
// RootNodeID is the top-most node the caller is allowed to traverse; all accesses must stay under it.
// It must be set for all VFS access operations.

View File

@@ -81,7 +81,7 @@ FROM node_paths
WHERE id = ?;`
func isScopeSet(scope *Scope) bool {
return scope != nil && scope.AccountID != uuid.Nil && scope.RootNodeID != uuid.Nil
return scope != nil && scope.DriveID != uuid.Nil && scope.RootNodeID != uuid.Nil
}
// canAccessNode checks if the scope permits the operation and allows access to the node.

View File

@@ -6,7 +6,7 @@ import "github.com/gofiber/fiber/v2"
// returns a valid *Scope for all registered routes.
//
// This is the base type for routers that provide VFS access scope.
// More specific router types (like account.ScopedRouter) may embed this
// More specific router types may embed this
// to provide additional guarantees.
type ScopedRouter struct {
fiber.Router

View File

@@ -94,7 +94,7 @@ func (vfs *VirtualFS) FindNode(ctx context.Context, db bun.IDB, fileID string, s
var node Node
err := db.NewSelect().Model(&node).
Where("account_id = ?", scope.AccountID).
Where("drive_id = ?", scope.DriveID).
Where("id = ?", fileID).
Where("status = ?", NodeStatusReady).
Where("deleted_at IS NULL").
@@ -135,7 +135,7 @@ func (vfs *VirtualFS) FindNodesByPublicID(ctx context.Context, db bun.IDB, publi
var nodes []*Node
err := db.NewSelect().Model(&nodes).
Where("account_id = ?", scope.AccountID).
Where("drive_id = ?", scope.DriveID).
Where("public_id IN (?)", bun.In(publicIDs)).
Where("status = ?", NodeStatusReady).
Scan(ctx)
@@ -146,11 +146,11 @@ func (vfs *VirtualFS) FindNodesByPublicID(ctx context.Context, db bun.IDB, publi
return vfs.filterNodesByScope(ctx, db, scope, nodes)
}
func (vfs *VirtualFS) FindRootDirectory(ctx context.Context, db bun.IDB, accountID uuid.UUID) (*Node, error) {
func (vfs *VirtualFS) FindRootDirectory(ctx context.Context, db bun.IDB, driveID uuid.UUID) (*Node, error) {
root := new(Node)
err := db.NewSelect().Model(root).
Where("account_id = ?", accountID).
Where("drive_id = ?", driveID).
Where("parent_id IS NULL").
Where("status = ?", NodeStatusReady).
Where("deleted_at IS NULL").
@@ -166,8 +166,8 @@ func (vfs *VirtualFS) FindRootDirectory(ctx context.Context, db bun.IDB, account
return root, nil
}
// CreateRootDirectory creates the account root directory node.
func (vfs *VirtualFS) CreateRootDirectory(ctx context.Context, db bun.IDB, accountID uuid.UUID) (*Node, error) {
// CreateRootDirectory creates the drive root directory node.
func (vfs *VirtualFS) CreateRootDirectory(ctx context.Context, db bun.IDB, driveID uuid.UUID) (*Node, error) {
pid, err := vfs.generatePublicID()
if err != nil {
return nil, err
@@ -181,7 +181,7 @@ func (vfs *VirtualFS) CreateRootDirectory(ctx context.Context, db bun.IDB, accou
node := &Node{
ID: id,
PublicID: pid,
AccountID: accountID,
DriveID: driveID,
ParentID: uuid.Nil,
Kind: NodeKindDirectory,
Status: NodeStatusReady,
@@ -212,7 +212,7 @@ func (vfs *VirtualFS) ListChildren(ctx context.Context, db bun.IDB, node *Node,
var nodes []*Node
q := db.NewSelect().Model(&nodes).
Where("account_id = ?", node.AccountID).
Where("drive_id = ?", node.DriveID).
Where("parent_id = ?", node.ID).
Where("status = ?", NodeStatusReady).
Where("deleted_at IS NULL")
@@ -326,13 +326,13 @@ func (vfs *VirtualFS) CreateFile(ctx context.Context, db bun.IDB, opts CreateFil
}
node := Node{
ID: id,
PublicID: pid,
AccountID: scope.AccountID,
ParentID: opts.ParentID,
Kind: NodeKindFile,
Status: NodeStatusPending,
Name: opts.Name,
ID: id,
PublicID: pid,
DriveID: scope.DriveID,
ParentID: opts.ParentID,
Kind: NodeKindFile,
Status: NodeStatusPending,
Name: opts.Name,
}
if vfs.keyResolver.ShouldPersistKey() {
@@ -492,13 +492,13 @@ func (vfs *VirtualFS) CreateDirectory(ctx context.Context, db bun.IDB, parentID
}
node := &Node{
ID: id,
PublicID: pid,
AccountID: scope.AccountID,
ParentID: parentID,
Kind: NodeKindDirectory,
Status: NodeStatusReady,
Name: name,
ID: id,
PublicID: pid,
DriveID: scope.DriveID,
ParentID: parentID,
Kind: NodeKindDirectory,
Status: NodeStatusReady,
Name: name,
}
_, err = db.NewInsert().Model(node).Exec(ctx)
@@ -739,13 +739,13 @@ func (vfs *VirtualFS) MoveNodesInSameDirectory(ctx context.Context, db bun.IDB,
nodeNames[i] = node.Name
}
var destinationConflicts []*Node
err = db.NewSelect().Model(&destinationConflicts).
Where("account_id = ?", allowedNodes[0].AccountID).
Where("parent_id = ?", newParentID).
Where("deleted_at IS NULL").
Where("name IN (?)", bun.In(nodeNames)).
Scan(ctx)
var destinationConflicts []*Node
err = db.NewSelect().Model(&destinationConflicts).
Where("drive_id = ?", allowedNodes[0].DriveID).
Where("parent_id = ?", newParentID).
Where("deleted_at IS NULL").
Where("name IN (?)", bun.In(nodeNames)).
Scan(ctx)
if err != nil {
return nil, err
}