[server][core][db] Inline fs_permissions.sql

This commit is contained in:
Abhishek Shroff
2025-03-30 00:03:01 +05:30
parent 8b8085d778
commit e9f4fc3f0b
7 changed files with 95 additions and 95 deletions

View File

@@ -62,13 +62,13 @@ func (r Resource) Move(target string, conflictResolution ResourceBindConflictRes
return err
}
}
if result, err := f.db.UpdateResourceNameParent(f.ctx, db.UpdateResourceNameParentParams{ID: r.ID(), Name: destName, Parent: destParent.ID()}); err != nil {
if result, err := f.db.UpdateResourceNameParent(f.ctx, db.UpdateResourceNameParentParams{ID: r.id, Name: destName, Parent: destParent.ID()}); err != nil {
if strings.Contains(err.Error(), "unique_member_resource_name") {
return ErrResourceNameConflict
}
return err
} else {
if err := f.db.RecomputePermissions(r.f.ctx, r.ID()); err != nil {
if err := f.recomputePermissions(r.id); err != nil {
return err
}
res = ResourceFromDB(result)
@@ -167,7 +167,7 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive bool, conflictReso
if _, err := f.db.CreateResources(f.ctx, children); err != nil {
return err
}
if err := f.db.RecomputePermissions(r.f.ctx, id); err != nil {
if err := f.recomputePermissions(id); err != nil {
return err
}
if created {

View File

@@ -57,7 +57,7 @@ func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool, conf
if res, created, _, err = f.createResource(id, r.id, name, dir, 0, emptyContentType, emptyContentSHA256, conflictResolution, r.permissions); err != nil {
return err
} else if created {
if err := f.db.RecomputePermissions(f.ctx, id); err != nil {
if err := f.recomputePermissions(r.id); err != nil {
return err
}
return f.db.UpdateResourceModified(f.ctx, r.id)

View File

@@ -1,11 +0,0 @@
package fs
type Permission = int32
const (
PermissionNone = Permission(0)
PermissionRead = Permission(4)
PermissionWrite = Permission(32)
PermissionShare = Permission(128)
PermissionSU = Permission(-1)
)

View File

@@ -0,0 +1,86 @@
package fs
import (
"encoding/json"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
)
type Permission = int32
const (
PermissionNone = Permission(0)
PermissionRead = Permission(4)
PermissionWrite = Permission(32)
PermissionShare = Permission(128)
PermissionSU = Permission(-1)
)
func (r Resource) UpdatePermissions(username string, permission Permission) (Resource, error) {
if !r.hasPermission(PermissionShare) {
return Resource{}, ErrInsufficientPermissions
}
// Do not grant more than what you have
permission = permission & r.userPermission
const q = `
UPDATE resources SET
grants[@username::TEXT] = jsonb_build_object('p', @permission::INT, 't', EXTRACT(EPOCH FROM NOW())::INTEGER)"
grants = (CASE permissions WHEN 0 THEN grants - @username::TEXT ELSE grants END)
modified = NOW()
WHERE id = @resource_id::UUID`
err := r.f.runInTx(func(f filesystem) error {
if _, err := f.db.Exec(f.ctx, q, pgx.NamedArgs{
"resource_id": r.id,
"username": username,
"permission": permission,
}); err != nil {
return err
}
return f.recomputePermissions(r.id)
})
if err != nil {
return Resource{}, err
}
p := make(map[string]Permission)
if r.permissions != nil {
if err := json.Unmarshal(r.permissions, &p); err != nil {
return Resource{}, err
}
}
if permission == 0 {
delete(p, username)
} else {
p[username] = permission
}
res, err := json.Marshal(p)
if err != nil {
return Resource{}, err
}
r.permissions = res
return r, nil
}
func (f filesystem) recomputePermissions(id uuid.UUID) error {
const q = `
WITH RECURSIVE nodes(id, parent, permissions) AS (
SELECT r.id, r.parent, phylum_merge_permission_grants(COALESCE(p.permissions, '{}'::JSONB), r.grants) END
FROM resources r
LEFT JOIN resources p
ON r.parent = p.id
WHERE r.id = $1::UUID
UNION ALL
SELECT r.id, r.parent, phylum_merge_permission_grants(n.permissions, r.grants)
FROM resources r JOIN nodes n on r.parent = n.id
)
UPDATE resources
SET permissions = nodes.permissions
FROM nodes
WHERE resources.id = nodes.id`
_, err := f.db.Exec(f.ctx, q, id)
return err
}

View File

@@ -1,7 +1,6 @@
package fs
import (
"context"
"errors"
"fmt"
"path"
@@ -118,7 +117,7 @@ func (r Resource) RestoreDeleted(parentPathOrUUID string, name string, autoRenam
r.parentID = update.Parent
}
}
if del, err := f.markNotDeleted(f.ctx, r.id); err != nil {
if del, err := f.markNotDeleted(r.id); err != nil {
return err
} else {
count = len(del)
@@ -127,7 +126,7 @@ func (r Resource) RestoreDeleted(parentPathOrUUID string, name string, autoRenam
}
}
return f.db.RecomputePermissions(f.ctx, r.ID())
return f.recomputePermissions(r.id)
})
res = r
return
@@ -180,7 +179,7 @@ func (f filesystem) markDeleted(id uuid.UUID, softDelete, excludeRoot bool) (int
return collectNonDirResourceIDs(f.db.Query(f.ctx, query, params...))
}
func (f filesystem) markNotDeleted(ctx context.Context, id uuid.UUID) ([]int64, error) {
func (f filesystem) markNotDeleted(id uuid.UUID) ([]int64, error) {
r, _, s := selectResourceTree(id, false, false)
q := s.Update().Set(
goqu.Record{
@@ -191,7 +190,7 @@ func (f filesystem) markNotDeleted(ctx context.Context, id uuid.UUID) ([]int64,
query, params, _ := q.ToSQL()
rows, err := f.db.Query(ctx, query, params...)
rows, err := f.db.Query(f.ctx, query, params...)
if err != nil {
return nil, err
}

View File

@@ -1,58 +0,0 @@
package fs
import (
"encoding/json"
"github.com/shroff/phylum/server/internal/core/db"
)
func (r Resource) UpdatePermissions(username string, permission Permission) (Resource, error) {
if !r.hasPermission(PermissionShare) {
return Resource{}, ErrInsufficientPermissions
}
// Do not grant more than what you have
permission = permission & r.userPermission
ctx := r.f.ctx
err := r.f.db.WithTx(ctx, func(dbh *db.DbHandler) error {
if permission == PermissionNone {
if err := dbh.RevokeUserPermissionForResource(ctx, db.RevokeUserPermissionForResourceParams{
ResourceID: r.ID(),
Username: username,
}); err != nil {
return err
}
} else {
if err := dbh.GrantUserPermissionForResource(ctx, db.GrantUserPermissionForResourceParams{
ResourceID: r.ID(),
Username: username,
Permission: permission,
}); err != nil {
return err
}
}
return dbh.RecomputePermissions(ctx, r.ID())
})
if err != nil {
return Resource{}, err
}
p := make(map[string]Permission)
if r.permissions != nil {
if err := json.Unmarshal(r.permissions, &p); err != nil {
return Resource{}, err
}
}
if permission == 0 {
delete(p, username)
} else {
p[username] = permission
}
res, err := json.Marshal(p)
if err != nil {
return Resource{}, err
}
r.permissions = res
return r, nil
}

View File

@@ -12,20 +12,4 @@ SET
grants = grants - @username::TEXT,
modified = NOW()
WHERE id = @resource_id::uuid
RETURNING permissions;
-- name: RecomputePermissions :exec
WITH RECURSIVE nodes(id, parent, permissions) AS (
SELECT r.id, r.parent, phylum_merge_permission_grants(COALESCE(p.permissions, '{}'::JSONB), r.grants) END
FROM resources r
LEFT JOIN resources p
ON r.parent = p.id
WHERE r.id = @resource_id::uuid
UNION ALL
SELECT r.id, r.parent, phylum_merge_permission_grants(n.permissions, r.grants)
FROM resources r JOIN nodes n on r.parent = n.id
)
UPDATE resources
SET permissions = nodes.permissions
FROM nodes
WHERE resources.id = nodes.id;
RETURNING permissions;