mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-08 04:30:46 -06:00
[server][core] store timestamp along with grants
This commit is contained in:
@@ -440,31 +440,3 @@ func (q *Queries) UpdateResourceParent(ctx context.Context, arg UpdateResourcePa
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateUserPermissionsForResource = `-- name: UpdateUserPermissionsForResource :exec
|
||||
INSERT INTO permissions(
|
||||
resource_id,
|
||||
username,
|
||||
modified,
|
||||
value
|
||||
) VALUES (
|
||||
$1::UUID,
|
||||
$2::TEXT,
|
||||
NOW(),
|
||||
$3::INT
|
||||
) ON CONFLICT(resource_id, username) DO UPDATE
|
||||
SET
|
||||
modified = CURRENT_TIMESTAMP,
|
||||
value = $3::INT
|
||||
`
|
||||
|
||||
type UpdateUserPermissionsForResourceParams struct {
|
||||
ResourceID uuid.UUID
|
||||
Username string
|
||||
Permission int32
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateUserPermissionsForResource(ctx context.Context, arg UpdateUserPermissionsForResourceParams) error {
|
||||
_, err := q.db.Exec(ctx, updateUserPermissionsForResource, arg.ResourceID, arg.Username, arg.Permission)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,15 +11,35 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const grantUserPermissionForResource = `-- name: GrantUserPermissionForResource :exec
|
||||
UPDATE resources
|
||||
SET
|
||||
grants[$1::text] = jsonb_build_object('p', $2::INT, 't', EXTRACT(EPOCH FROM NOW())::INTEGER),
|
||||
modified = NOW()
|
||||
WHERE id = $3::uuid
|
||||
RETURNING permissions
|
||||
`
|
||||
|
||||
type GrantUserPermissionForResourceParams struct {
|
||||
Username string
|
||||
Permission int32
|
||||
ResourceID uuid.UUID
|
||||
}
|
||||
|
||||
func (q *Queries) GrantUserPermissionForResource(ctx context.Context, arg GrantUserPermissionForResourceParams) error {
|
||||
_, err := q.db.Exec(ctx, grantUserPermissionForResource, arg.Username, arg.Permission, arg.ResourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
const recomputePermissions = `-- name: RecomputePermissions :exec
|
||||
WITH RECURSIVE nodes(id, parent, permissions) AS (
|
||||
SELECT r.id, r.parent, CASE WHEN r.parent IS NULL THEN r.grants ELSE jsonb_bitwise_or(p.permissions, r.grants) END
|
||||
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, jsonb_bitwise_or(n.permissions, r.grants)
|
||||
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
|
||||
@@ -32,3 +52,22 @@ func (q *Queries) RecomputePermissions(ctx context.Context, resourceID uuid.UUID
|
||||
_, err := q.db.Exec(ctx, recomputePermissions, resourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
const revokeUserPermissionForResource = `-- name: RevokeUserPermissionForResource :exec
|
||||
UPDATE resources
|
||||
SET
|
||||
grants = grants - $1::TEXT,
|
||||
modified = NOW()
|
||||
WHERE id = $2::uuid
|
||||
RETURNING permissions
|
||||
`
|
||||
|
||||
type RevokeUserPermissionForResourceParams struct {
|
||||
Username string
|
||||
ResourceID uuid.UUID
|
||||
}
|
||||
|
||||
func (q *Queries) RevokeUserPermissionForResource(ctx context.Context, arg RevokeUserPermissionForResourceParams) error {
|
||||
_, err := q.db.Exec(ctx, revokeUserPermissionForResource, arg.Username, arg.ResourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,31 +2,23 @@ ALTER TABLE resources ADD COLUMN permissions JSONB NOT NULL DEFAULT '{}';
|
||||
|
||||
ALTER TABLE resources ADD COLUMN grants JSONB NOT NULL DEFAULT '{}';
|
||||
|
||||
CREATE OR REPLACE FUNCTION jsonb_bitwise_or(a JSONB, b JSONB)
|
||||
CREATE OR REPLACE FUNCTION phylum_merge_permission_grants(a JSONB, b JSONB)
|
||||
RETURNS JSONB LANGUAGE SQL AS $$
|
||||
SELECT
|
||||
SELECT
|
||||
COALESCE(jsonb_object_agg(
|
||||
COALESCE(ka, kb),
|
||||
COALESCE(ka, kb),
|
||||
CASE
|
||||
WHEN va ISNULL THEN vb::integer
|
||||
WHEN vb ISNULL THEN va::integer
|
||||
ELSE va::integer | vb::integer
|
||||
WHEN vb ISNULL THEN va::integer
|
||||
WHEN va ISNULL THEN (vb -> 'p')::integer
|
||||
ELSE va::integer | (vb -> 'p')::integer
|
||||
END
|
||||
), '{}'::JSONB)
|
||||
FROM jsonb_each(a) e1(ka, va)
|
||||
FULL JOIN jsonb_each(b) e2(kb, vb) ON ka = kb
|
||||
$$;
|
||||
|
||||
CREATE AGGREGATE agg_jsonb_bitwise_or(JSONB) (
|
||||
SFUNC = jsonb_bitwise_or,
|
||||
STYPE = JSONB,
|
||||
INITCOND = '{}'
|
||||
);
|
||||
|
||||
---- create above / drop below ----
|
||||
DROP AGGREGATE agg_jsonb_bitwise_or(JSONB);
|
||||
|
||||
DROP FUNCTION jsonb_bitwise_or;
|
||||
DROP FUNCTION phylum_merge_permission_grants;
|
||||
|
||||
ALTER TABLE resources DROP COLUMN permissions;
|
||||
|
||||
|
||||
@@ -13,15 +13,31 @@ func (r Resource) UpdatePermissions(username string, permission Permission) (Res
|
||||
// Do not grant more than what you have
|
||||
permission = permission & r.userPermission
|
||||
|
||||
var err error
|
||||
err = r.f.db.UpdateUserPermissionsForResource(r.f.ctx, db.UpdateUserPermissionsForResourceParams{
|
||||
ResourceID: r.ID(),
|
||||
Username: username,
|
||||
Permission: permission,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
if err := dbh.RecomputePermissions(ctx, r.ID()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return Resource{}, err
|
||||
}
|
||||
p := make(map[string]Permission)
|
||||
if r.Info.permissions != nil {
|
||||
json.Unmarshal(r.Info.permissions, &p)
|
||||
|
||||
@@ -58,22 +58,6 @@ SET
|
||||
WHERE id = @id::uuid
|
||||
RETURNING name, parent, modified;
|
||||
|
||||
-- name: UpdateUserPermissionsForResource :exec
|
||||
INSERT INTO permissions(
|
||||
resource_id,
|
||||
username,
|
||||
modified,
|
||||
value
|
||||
) VALUES (
|
||||
@resource_id::UUID,
|
||||
@username::TEXT,
|
||||
NOW(),
|
||||
@permission::INT
|
||||
) ON CONFLICT(resource_id, username) DO UPDATE
|
||||
SET
|
||||
modified = CURRENT_TIMESTAMP,
|
||||
value = @permission::INT;
|
||||
|
||||
-- name: ChildResourceByName :one
|
||||
SELECT * FROM resources WHERE parent = @parent::uuid AND name = @name::text AND deleted IS NULL;
|
||||
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
-- name: GrantUserPermissionForResource :exec
|
||||
UPDATE resources
|
||||
SET
|
||||
grants[@username::text] = jsonb_build_object('p', @permission::INT, 't', EXTRACT(EPOCH FROM NOW())::INTEGER),
|
||||
modified = NOW()
|
||||
WHERE id = @resource_id::uuid
|
||||
RETURNING permissions;
|
||||
|
||||
-- name: RevokeUserPermissionForResource :exec
|
||||
UPDATE resources
|
||||
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, CASE WHEN r.parent IS NULL THEN r.grants ELSE jsonb_bitwise_or(p.permissions, r.grants) END
|
||||
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, jsonb_bitwise_or(n.permissions, r.grants)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user