mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-04-28 16:20:29 -05:00
168 lines
4.0 KiB
Go
168 lines
4.0 KiB
Go
package core
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
type Resource struct {
|
|
id uuid.UUID
|
|
parentID pgtype.UUID
|
|
name string
|
|
dir bool
|
|
created time.Time
|
|
modified time.Time
|
|
deleted pgtype.Timestamp
|
|
permissions []byte
|
|
grants []byte
|
|
versions []byte
|
|
links []byte
|
|
inheritedPermissions []byte
|
|
visibleParent pgtype.UUID
|
|
userPermission Permission
|
|
latestVersionInfo VersionInfo
|
|
}
|
|
|
|
func (r Resource) ID() uuid.UUID { return r.id }
|
|
func (r Resource) Name() string { return r.name }
|
|
func (r Resource) Dir() bool { return r.dir }
|
|
func (r Resource) Created() time.Time { return r.created }
|
|
func (r Resource) Modified() time.Time { return r.modified }
|
|
func (r Resource) Deleted() pgtype.Timestamp { return r.deleted }
|
|
func (r Resource) Grants() []byte { return r.grants }
|
|
func (r Resource) Versions() []byte { return r.versions }
|
|
func (r Resource) Links() []byte { return r.links }
|
|
func (r Resource) VisibleParentID() pgtype.UUID { return r.visibleParent }
|
|
func (r Resource) InheritedPermissions() []byte { return r.inheritedPermissions }
|
|
func (r Resource) LatestVersion() VersionInfo { return r.latestVersionInfo }
|
|
|
|
func (r Resource) hasPermission(p Permission) bool {
|
|
return r.userPermission&p != 0
|
|
}
|
|
|
|
func (f filesystem) collectFullResource(rows pgx.Rows) (Resource, error) {
|
|
if r, err := pgx.CollectExactlyOneRow(rows, f.scanFullResource); err == nil {
|
|
return r, nil
|
|
} else {
|
|
if err == pgx.ErrNoRows {
|
|
err = ErrResourceNotFound
|
|
}
|
|
return r, err
|
|
}
|
|
|
|
}
|
|
|
|
func (f filesystem) scanFullResource(row pgx.CollectableRow) (Resource, error) {
|
|
var r Resource
|
|
err := row.Scan(
|
|
&r.id,
|
|
&r.name,
|
|
&r.parentID,
|
|
&r.dir,
|
|
&r.created,
|
|
&r.modified,
|
|
&r.deleted,
|
|
&r.permissions,
|
|
&r.grants,
|
|
&r.versions,
|
|
&r.links,
|
|
&r.visibleParent,
|
|
&r.inheritedPermissions,
|
|
)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
permission := Permission(0)
|
|
if f.fullAccess {
|
|
permission = -1
|
|
} else if p, err := readPermissionFromJson(r.permissions, f.userID); err != nil {
|
|
return Resource{}, err
|
|
} else {
|
|
permission = p
|
|
}
|
|
if permission&PermissionRead == 0 {
|
|
return Resource{}, ErrResourceNotFound
|
|
}
|
|
r.userPermission = permission
|
|
return r, err
|
|
}
|
|
|
|
func (f filesystem) scanResourceWithoutParent(row pgx.CollectableRow) (Resource, error) {
|
|
var r Resource
|
|
err := row.Scan(
|
|
&r.id,
|
|
&r.name,
|
|
&r.parentID,
|
|
&r.dir,
|
|
&r.created,
|
|
&r.modified,
|
|
&r.deleted,
|
|
&r.permissions,
|
|
&r.grants,
|
|
&r.versions,
|
|
&r.links,
|
|
)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
permission := Permission(0)
|
|
if f.fullAccess {
|
|
permission = -1
|
|
} else if p, err := readPermissionFromJson(r.permissions, f.userID); err != nil {
|
|
return Resource{}, err
|
|
} else {
|
|
permission = p
|
|
}
|
|
if permission&PermissionRead == 0 {
|
|
return Resource{}, ErrResourceNotFound
|
|
}
|
|
|
|
if v, err := latestVersion(r.versions); err != nil {
|
|
return Resource{}, err
|
|
} else {
|
|
r.latestVersionInfo = v
|
|
}
|
|
|
|
r.userPermission = permission
|
|
return r, err
|
|
}
|
|
|
|
func latestVersion(versionsJSON []byte) (VersionInfo, error) {
|
|
versions := make([]VersionInfo, 0, 1)
|
|
err := json.Unmarshal(versionsJSON, &versions)
|
|
if err != nil {
|
|
return VersionInfo{}, err
|
|
}
|
|
if len(versions) == 0 {
|
|
return VersionInfo{
|
|
ID: uuid.Nil,
|
|
Created: 0,
|
|
Size: 0,
|
|
MimeType: "text/plain",
|
|
SHA256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
}, nil
|
|
}
|
|
// TODO: add `ORDER BY` clause to queries to ensure correctness
|
|
return versions[0], nil
|
|
}
|
|
|
|
func readPermissionFromJson(j []byte, userID int32) (Permission, error) {
|
|
if j == nil {
|
|
return PermissionNone, nil
|
|
}
|
|
p := make(map[int32]Permission)
|
|
err := json.Unmarshal(j, &p)
|
|
if err != nil {
|
|
return PermissionNone, err
|
|
}
|
|
if p, ok := p[userID]; ok {
|
|
return p, nil
|
|
}
|
|
return PermissionNone, nil
|
|
}
|