From 5dfd272fde45b74882032cd617c2b591e0668803 Mon Sep 17 00:00:00 2001 From: Abhishek Shroff Date: Sun, 4 Aug 2024 17:37:43 +0530 Subject: [PATCH] Grant Permissions --- server/internal/api/routes/resources.go | 6 ++-- server/internal/app/core/resource.go | 34 ++++++++++++++----- server/internal/app/core/silo.go | 4 +-- server/internal/app/silos.go | 11 ++++-- .../migrations/data/001_resources.sql | 2 +- server/internal/sql/models.go | 2 +- server/internal/sql/permissions.sql.go | 17 ++++++++++ server/internal/sql/resources.sql.go | 6 ++-- server/sql/queries/permissions.sql | 6 ++++ 9 files changed, 67 insertions(+), 21 deletions(-) diff --git a/server/internal/api/routes/resources.go b/server/internal/api/routes/resources.go index 131f3927..9f707e32 100644 --- a/server/internal/api/routes/resources.go +++ b/server/internal/api/routes/resources.go @@ -25,7 +25,7 @@ type resourceResponse struct { Created time.Time `json:"created"` Modified time.Time `json:"modified"` Deleted *time.Time `json:"deleted,omitempty"` - Size int `json:"size"` + Size int64 `json:"size"` Etag string `json:"etag"` } @@ -62,7 +62,7 @@ func createResourceMetadataRouteHandler(a *app.App) func(c *gin.Context) { Created: resource.Created.Time, Modified: resource.Modified.Time, Deleted: deleted, - Size: int(resource.Size.Int32), + Size: resource.Size.Int64, Etag: resource.Etag.String, } c.JSON(200, response) @@ -98,7 +98,7 @@ func createResourceLsRouteHandler(a *app.App) func(c *gin.Context) { Dir: c.Dir, Created: c.Created.Time, Modified: c.Modified.Time, - Size: int(c.Size.Int32), + Size: c.Size.Int64, Etag: c.Etag.String, } } diff --git a/server/internal/app/core/resource.go b/server/internal/app/core/resource.go index 0266e619..8017d793 100644 --- a/server/internal/app/core/resource.go +++ b/server/internal/app/core/resource.go @@ -24,15 +24,16 @@ const ( ) var ( - ErrInsufficientPermissions = errors.New("insufficient permissions") - ErrResourceNotCollection = errors.New("cannot add member to non-collection resource") + ErrInsufficientPermissions = errors.New("insufficient permissions") + ErrCannotGrantOwnerPermission = errors.New("cannot grant owner permission") + ErrResourceNotCollection = errors.New("cannot add member to non-collection resource") ) type ResourceInfo interface { ID() uuid.UUID Name() string Size() int64 - Permission() int + Permission() int32 ModTime() time.Time IsDir() bool ETag() string @@ -56,7 +57,7 @@ type resource struct { name string size int64 userID int32 - permission int + permission int32 collection bool modTime time.Time etag string @@ -64,7 +65,7 @@ type resource struct { func (r resource) ID() uuid.UUID { return r.id } -func (r resource) Permission() int { return r.permission } +func (r resource) Permission() int32 { return r.permission } func (r resource) ParentID() *uuid.UUID { return r.parentID } @@ -107,7 +108,7 @@ func (r resource) OpenWrite(ctx context.Context) (io.WriteCloser, error) { return r.storage.OpenWrite(r.id, func(len int, etag string) error { return r.db.Queries().UpdateResourceContents(ctx, sql.UpdateResourceContentsParams{ ID: r.id, - Size: pgtype.Int4{Int32: int32(len), Valid: true}, + Size: pgtype.Int8{Int64: int64(len), Valid: true}, Etag: pgtype.Text{String: etag, Valid: true}, }) }) @@ -125,8 +126,8 @@ func (r resource) ReadDir(ctx context.Context) ([]Resource, error) { result := make([]Resource, len(children)) for i, c := range children { permission := r.Permission() - if c.Permission.Valid && int(c.Permission.Int32) > permission { - permission = int(c.Permission.Int32) + if c.Permission.Valid && c.Permission.Int32 > permission { + permission = c.Permission.Int32 } result[i] = resource{ @@ -137,7 +138,7 @@ func (r resource) ReadDir(ctx context.Context) ([]Resource, error) { permission: permission, parentID: &r.id, name: c.Name, - size: int64(c.Size.Int32), + size: c.Size.Int64, modTime: c.Modified.Time, collection: c.Dir, etag: c.Etag.String, @@ -206,3 +207,18 @@ func (r resource) DeleteRecursive(ctx context.Context, hardDelete bool) error { return nil }) } + +func (r resource) UpdatePermissions(ctx context.Context, userID int32, permission int32) error { + if r.permission < PermissionAdmin { + return ErrInsufficientPermissions + } + if permission > PermissionAdmin { + return ErrCannotGrantOwnerPermission + } + + return r.db.Queries().UpdatePermissionsForResource(ctx, sql.UpdatePermissionsForResourceParams{ + ResourceID: r.id, + UserID: userID, + Permission: permission, + }) +} diff --git a/server/internal/app/core/silo.go b/server/internal/app/core/silo.go index 4e5accc0..0dbde288 100644 --- a/server/internal/app/core/silo.go +++ b/server/internal/app/core/silo.go @@ -79,10 +79,10 @@ func (s *silo) ResourceByPath(ctx context.Context, path string, userID int32) (R storage: s.storage, id: res.ID, userID: userID, - permission: int(res.Permission.Int32), + permission: res.Permission.Int32, parentID: res.Parent, name: res.Name, - size: int64(res.Size.Int32), + size: res.Size.Int64, collection: res.Dir, modTime: res.Modified.Time, etag: res.Etag.String, diff --git a/server/internal/app/silos.go b/server/internal/app/silos.go index 02fb10c6..79b66a86 100644 --- a/server/internal/app/silos.go +++ b/server/internal/app/silos.go @@ -19,13 +19,20 @@ func (a App) CreateSilo(ctx context.Context, id uuid.UUID, owner int32, storage, }); err != nil { return err } - _, err := q.CreateResource(ctx, sql.CreateResourceParams{ + if _, err := q.CreateResource(ctx, sql.CreateResourceParams{ ID: id, Parent: nil, Name: id.String(), Dir: true, + }); err != nil { + return err + } + + err := q.UpdatePermissionsForResource(ctx, sql.UpdatePermissionsForResourceParams{ + ResourceID: id, + UserID: owner, + Permission: core.PermissionOwner, }) - // TODO: insert permissions return err }) diff --git a/server/internal/migrations/data/001_resources.sql b/server/internal/migrations/data/001_resources.sql index 6a3d30ad..e7018ed5 100644 --- a/server/internal/migrations/data/001_resources.sql +++ b/server/internal/migrations/data/001_resources.sql @@ -6,7 +6,7 @@ CREATE TABLE resources ( created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, deleted TIMESTAMP, - size INT, + size BIGINT, etag TEXT -- CONSTRAINT resource_parent FOREIGN KEY REFERENCES resources(id) ON UPDATE CASCADE ON DELETE CASCADE; ); diff --git a/server/internal/sql/models.go b/server/internal/sql/models.go index 1318de53..0722807b 100644 --- a/server/internal/sql/models.go +++ b/server/internal/sql/models.go @@ -30,7 +30,7 @@ type Resource struct { Created pgtype.Timestamp Modified pgtype.Timestamp Deleted pgtype.Timestamp - Size pgtype.Int4 + Size pgtype.Int8 Etag pgtype.Text } diff --git a/server/internal/sql/permissions.sql.go b/server/internal/sql/permissions.sql.go index 01fe45fa..b4a39d40 100644 --- a/server/internal/sql/permissions.sql.go +++ b/server/internal/sql/permissions.sql.go @@ -40,3 +40,20 @@ func (q *Queries) PermissionsForResource(ctx context.Context, arg PermissionsFor err := row.Scan(&i.ID, &i.Parent, &i.Permission) return i, err } + +const updatePermissionsForResource = `-- name: UpdatePermissionsForResource :exec +INSERT INTO permissions(resource_id, user_id, permission) + VALUES($1::uuid, $2::int, $3::int) + ON CONFLICT(resource_id, user_id) DO UPDATE SET permission = $3::int +` + +type UpdatePermissionsForResourceParams struct { + ResourceID uuid.UUID + UserID int32 + Permission int32 +} + +func (q *Queries) UpdatePermissionsForResource(ctx context.Context, arg UpdatePermissionsForResourceParams) error { + _, err := q.db.Exec(ctx, updatePermissionsForResource, arg.ResourceID, arg.UserID, arg.Permission) + return err +} diff --git a/server/internal/sql/resources.sql.go b/server/internal/sql/resources.sql.go index 9cc75591..c59c3854 100644 --- a/server/internal/sql/resources.sql.go +++ b/server/internal/sql/resources.sql.go @@ -142,7 +142,7 @@ type ReadDirRow struct { Dir bool Created pgtype.Timestamp Modified pgtype.Timestamp - Size pgtype.Int4 + Size pgtype.Int8 Etag pgtype.Text Depth int32 Path string @@ -261,7 +261,7 @@ type ResourceByPathRow struct { Dir bool Created pgtype.Timestamp Modified pgtype.Timestamp - Size pgtype.Int4 + Size pgtype.Int8 Etag pgtype.Text Depth int32 Path string @@ -299,7 +299,7 @@ WHERE id = $3 ` type UpdateResourceContentsParams struct { - Size pgtype.Int4 + Size pgtype.Int8 Etag pgtype.Text ID uuid.UUID } diff --git a/server/sql/queries/permissions.sql b/server/sql/queries/permissions.sql index e54dc8fb..0a3300e4 100644 --- a/server/sql/queries/permissions.sql +++ b/server/sql/queries/permissions.sql @@ -8,3 +8,9 @@ WITH RECURSIVE nodes(id, parent, permission) AS ( FROM resources r JOIN nodes n ON r.id = n.parent LEFT JOIN permissions p ON r.id = p.resource_id AND p.user_id = @user_id::int ) SELECT * FROM nodes WHERE parent IS NULL; + +-- name: UpdatePermissionsForResource :exec +INSERT INTO permissions(resource_id, user_id, permission) + VALUES(@resource_id::uuid, @user_id::int, @permission::int) + ON CONFLICT(resource_id, user_id) DO UPDATE SET permission = @permission::int; +