mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-05-08 05:10:29 -05:00
[server] Split fs.ResourceInfo out of fs.Resource
This commit is contained in:
@@ -16,7 +16,7 @@ func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
|
||||
}
|
||||
|
||||
// Check source directory permissions
|
||||
parent, err := r.f.ResourceByID(*r.ParentID)
|
||||
parent, err := r.f.ResourceByID(*r.ParentID())
|
||||
if err != nil {
|
||||
return Resource{}, false, err
|
||||
}
|
||||
@@ -35,8 +35,14 @@ func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
|
||||
if !destParent.hasPermission(PermissionWrite) {
|
||||
return Resource{}, false, ErrInsufficientPermissions
|
||||
}
|
||||
if res, err := r.f.db.ResourceByID(r.f.ctx, db.ResourceByIDParams{Root: r.ID, ResourceID: destParent.ID, Username: r.f.username}); err != nil || res.Found {
|
||||
return Resource{}, false, ErrResourceMoveTargetSubdirectory
|
||||
if res, err := r.f.db.ResourceByID(r.f.ctx, destParent.ID()); err != nil {
|
||||
return Resource{}, false, err
|
||||
} else {
|
||||
for i := 1; i < len(res); i++ {
|
||||
if res[i].ID == r.ID() {
|
||||
return Resource{}, false, ErrResourceMoveTargetSubdirectory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var deleted = false
|
||||
@@ -49,14 +55,14 @@ func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if nameParent, err := f.db.UpdateResourceNameParent(f.ctx, db.UpdateResourceNameParentParams{ID: r.ID, Name: destName, Parent: destParent.ID}); err != nil {
|
||||
if nameParent, 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 {
|
||||
r.Name = nameParent.Name
|
||||
r.ParentID = nameParent.Parent
|
||||
r.Ancestry[0].Name = nameParent.Name
|
||||
r.Ancestry[0].ParentID = nameParent.Parent
|
||||
return nil
|
||||
}
|
||||
})
|
||||
@@ -76,7 +82,7 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
|
||||
}
|
||||
return Resource{}, false, err
|
||||
}
|
||||
if !destParent.Dir {
|
||||
if !destParent.FSDir() {
|
||||
return Resource{}, false, ErrResourceNotCollection
|
||||
|
||||
}
|
||||
@@ -84,35 +90,35 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
|
||||
return Resource{}, false, ErrInsufficientPermissions
|
||||
}
|
||||
|
||||
var tree []db.ResourceResult
|
||||
if recursive && r.Dir {
|
||||
var tree []db.PublinkedResource
|
||||
if recursive && r.FSDir() {
|
||||
var err error
|
||||
tree, err = r.f.db.ReadDir(r.f.ctx, db.ReadDirParams{ResourceID: r.ID, Path: r.Path, MinDepth: 1, MaxDepth: 1000})
|
||||
tree, err = r.f.db.ReadDir(r.f.ctx, db.ReadDirParams{ResourceID: r.ID(), MinDepth: 1, MaxDepth: 1000})
|
||||
if err != nil {
|
||||
return Resource{}, false, err
|
||||
}
|
||||
}
|
||||
create := make([]db.CreateResourcesParams, 0, len(tree)+1)
|
||||
copy := make(map[uuid.UUID]uuid.UUID)
|
||||
ids := make(map[string]uuid.UUID)
|
||||
if r.Dir {
|
||||
ids[""] = id
|
||||
contents := make(map[uuid.UUID]uuid.UUID)
|
||||
ids := make(map[uuid.UUID]uuid.UUID)
|
||||
if r.FSDir() {
|
||||
ids[r.ID()] = id
|
||||
} else {
|
||||
copy[r.ID] = id
|
||||
contents[r.ID()] = id
|
||||
}
|
||||
|
||||
create = append(create, db.CreateResourcesParams{
|
||||
ID: id,
|
||||
Parent: destParent.ID,
|
||||
Parent: destParent.ID(),
|
||||
Name: destName,
|
||||
Dir: r.Dir,
|
||||
ContentSize: r.ContentSize,
|
||||
ContentType: r.ContentType,
|
||||
ContentSha256: r.ContentSHA256,
|
||||
Dir: r.FSDir(),
|
||||
ContentSize: r.FSContentSize(),
|
||||
ContentType: r.FSContentType(),
|
||||
ContentSha256: r.FSContentSHA256(),
|
||||
})
|
||||
for _, src := range tree {
|
||||
id, _ := uuid.NewUUID()
|
||||
parent := ids[src.Path[0:strings.LastIndex(src.Path, "/")]]
|
||||
parent := ids[*src.Parent]
|
||||
|
||||
create = append(create, db.CreateResourcesParams{
|
||||
ID: id,
|
||||
@@ -125,9 +131,9 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
|
||||
})
|
||||
|
||||
if src.Dir {
|
||||
ids[src.Path] = id
|
||||
ids[src.ID] = id
|
||||
} else {
|
||||
copy[src.ID] = id
|
||||
contents[src.ID] = id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,12 +153,12 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
|
||||
}
|
||||
return err
|
||||
}
|
||||
return dbh.UpdateResourceModified(f.ctx, destParent.ID)
|
||||
return dbh.UpdateResourceModified(f.ctx, destParent.ID())
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
func() {
|
||||
for k, v := range copy {
|
||||
for k, v := range contents {
|
||||
if err := r.f.cs.CopyContents(k, v); err != nil {
|
||||
logrus.Warn("unable to copy " + k.String() + " to " + v.String() + ": " + err.Error())
|
||||
}
|
||||
@@ -161,25 +167,36 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
|
||||
}()
|
||||
}
|
||||
|
||||
var dest = Resource{
|
||||
f: r.f,
|
||||
parentID := destParent.ID()
|
||||
var info = ResourceInfo{
|
||||
ID: id,
|
||||
ParentID: &destParent.ID,
|
||||
ParentID: &parentID,
|
||||
Name: destName,
|
||||
Dir: r.Dir,
|
||||
Dir: r.FSDir(),
|
||||
Created: time.Now(),
|
||||
Modified: time.Now(),
|
||||
Deleted: nil,
|
||||
ContentSize: r.ContentSize,
|
||||
ContentType: r.ContentType,
|
||||
ContentSHA256: r.ContentSHA256,
|
||||
ContentSize: r.FSContentSize(),
|
||||
ContentType: r.FSContentType(),
|
||||
ContentSHA256: r.FSContentSHA256(),
|
||||
Permissions: "{}",
|
||||
// Not Needed
|
||||
// UserPermissions: ??
|
||||
// InheritedPermissions: ??
|
||||
// Path: destParent.Path + "/" + destName,
|
||||
Publinks: 0,
|
||||
}
|
||||
return dest, deleted, err
|
||||
if destParent.FSPath() == "/" {
|
||||
info.Path = "/" + info.Name
|
||||
} else {
|
||||
info.Path = destParent.FSPath() + "/" + info.Name
|
||||
}
|
||||
|
||||
ancestry := make([]ResourceInfo, len(destParent.Ancestry)+1)
|
||||
copy(ancestry, destParent.Ancestry)
|
||||
ancestry = append(ancestry, info)
|
||||
created := Resource{
|
||||
f: r.f,
|
||||
Ancestry: ancestry,
|
||||
UserPermission: destParent.UserPermission,
|
||||
}
|
||||
return created, deleted, err
|
||||
}
|
||||
|
||||
// targetByPathOrUUID splits a target path or uuid into its constituent components
|
||||
@@ -231,7 +248,7 @@ func (f filesystem) targetByPathOrUUID(src Resource, pathOrUUID string) (Resourc
|
||||
|
||||
name := pathOrUUID[index+1:]
|
||||
if name == "" {
|
||||
name = src.Name
|
||||
name = src.FSName()
|
||||
} else if CheckNameInvalid(name) {
|
||||
return Resource{}, "", ErrResourceNameInvalid
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (f filesystem) CreateResourceByPath(path string, dir, recursive bool) (Reso
|
||||
}
|
||||
|
||||
func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool) (Resource, error) {
|
||||
if !r.Dir {
|
||||
if !r.FSDir() {
|
||||
return Resource{}, ErrResourceNotCollection
|
||||
}
|
||||
if !r.hasPermission(PermissionWrite) {
|
||||
@@ -47,7 +47,7 @@ func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool) (Res
|
||||
var result db.Resource
|
||||
err := r.f.db.WithTx(r.f.ctx, func(d *db.DbHandler) error {
|
||||
var err error
|
||||
parent := r.ID
|
||||
parent := r.ID()
|
||||
if result, err = d.CreateResource(r.f.ctx, db.CreateResourceParams{ID: id, Parent: &parent, Name: name, Dir: dir}); err != nil {
|
||||
if strings.Contains(err.Error(), "unique_member_resource_name") {
|
||||
return ErrResourceNameConflict
|
||||
@@ -62,7 +62,7 @@ func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool) (Res
|
||||
if err != nil {
|
||||
return Resource{}, err
|
||||
}
|
||||
if !r.Dir {
|
||||
if !r.FSDir() {
|
||||
out, err := r.f.cs.OpenWrite(id, nil, nil)
|
||||
if err == nil {
|
||||
err = out.Close()
|
||||
@@ -72,34 +72,54 @@ func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool) (Res
|
||||
}
|
||||
}
|
||||
|
||||
p, err := MergePermissionStrings(r.InheritedPermissions, r.Permissions)
|
||||
if err != nil {
|
||||
return Resource{}, err
|
||||
}
|
||||
var deleted *time.Time
|
||||
if result.Deleted.Valid {
|
||||
deleted = &result.Deleted.Time
|
||||
}
|
||||
path := r.Path + "/" + result.Name
|
||||
if r.Path == "/" {
|
||||
path = result.Name
|
||||
// return Resource{
|
||||
// f: r.f,
|
||||
// ID: result.ID,
|
||||
// ParentID: result.Parent,
|
||||
// Name: result.Name,
|
||||
// Created: result.Created.Time,
|
||||
// Modified: result.Modified.Time,
|
||||
// Deleted: deleted,
|
||||
// Dir: result.Dir,
|
||||
// ContentSize: result.ContentSize,
|
||||
// ContentType: result.ContentType,
|
||||
// ContentSHA256: result.ContentSha256,
|
||||
// Permissions: string(result.Permissions),
|
||||
// Path: path,
|
||||
// UserPermission: r.UserPermission,
|
||||
// }, nil
|
||||
info := resourceInfoFromDBResource(result)
|
||||
if r.FSPath() == "/" {
|
||||
info.Path = "/" + info.Name
|
||||
} else {
|
||||
info.Path = r.FSPath() + "/" + info.Name
|
||||
}
|
||||
ancestry := make([]ResourceInfo, len(r.Ancestry)+1)
|
||||
copy(ancestry, r.Ancestry)
|
||||
ancestry = append(ancestry, info)
|
||||
return Resource{
|
||||
f: r.f,
|
||||
ID: result.ID,
|
||||
ParentID: result.Parent,
|
||||
Name: result.Name,
|
||||
Created: result.Created.Time,
|
||||
Modified: result.Modified.Time,
|
||||
Deleted: deleted,
|
||||
Dir: result.Dir,
|
||||
ContentSize: result.ContentSize,
|
||||
ContentType: result.ContentType,
|
||||
ContentSHA256: result.ContentSha256,
|
||||
Permissions: string(result.Permissions),
|
||||
Path: path,
|
||||
UserPermission: r.UserPermission,
|
||||
InheritedPermissions: p,
|
||||
Publinks: 0,
|
||||
f: r.f,
|
||||
Ancestry: ancestry,
|
||||
UserPermission: r.UserPermission,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func resourceInfoFromDBResource(r db.Resource) ResourceInfo {
|
||||
var delTime *time.Time
|
||||
if r.Deleted.Valid {
|
||||
delTime = &r.Deleted.Time
|
||||
}
|
||||
return ResourceInfo{
|
||||
ID: r.ID,
|
||||
ParentID: r.Parent,
|
||||
Name: r.Name,
|
||||
Dir: r.Dir,
|
||||
Created: r.Created.Time,
|
||||
Modified: r.Modified.Time,
|
||||
Deleted: delTime,
|
||||
ContentSize: r.ContentSize,
|
||||
ContentType: r.ContentType,
|
||||
ContentSHA256: r.ContentSha256,
|
||||
Permissions: string(r.Permissions),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,28 @@ func (r Resource) DeleteChildRecursive(name string, hardDelete bool) error {
|
||||
return ErrInsufficientPermissions
|
||||
}
|
||||
|
||||
id, err := r.f.db.ChildResourceIDByName(r.f.ctx, db.ChildResourceIDByNameParams{Parent: r.ID, Name: name})
|
||||
id, err := r.f.db.ChildResourceIDByName(r.f.ctx, db.ChildResourceIDByNameParams{Parent: r.ID(), Name: name})
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
return r.f.deleteRecursive(id, r.ID, hardDelete)
|
||||
return r.f.deleteRecursive(id, r.ID(), hardDelete)
|
||||
}
|
||||
|
||||
func (r Resource) DeleteRecursive(hardDelete bool) error {
|
||||
if r.ParentID == nil {
|
||||
if r.ParentID() == nil {
|
||||
return ErrInsufficientPermissions
|
||||
}
|
||||
parent, err := r.f.ResourceByID(*r.ParentID)
|
||||
parent, err := r.f.ResourceByID(*r.ParentID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !parent.hasPermission(PermissionWrite) {
|
||||
return ErrInsufficientPermissions
|
||||
}
|
||||
return r.f.deleteRecursive(r.ID, parent.ID, hardDelete)
|
||||
return r.f.deleteRecursive(r.ID(), parent.ID(), hardDelete)
|
||||
}
|
||||
|
||||
func (f filesystem) deleteRecursive(id, parent uuid.UUID, hardDelete bool) error {
|
||||
|
||||
@@ -8,7 +8,7 @@ type DiskUsageInfo struct {
|
||||
}
|
||||
|
||||
func (r Resource) DiskUsage() (DiskUsageInfo, error) {
|
||||
if info, err := r.f.db.DiskUsage(r.f.ctx, r.ID); err != nil {
|
||||
if info, err := r.f.db.DiskUsage(r.f.ctx, r.ID()); err != nil {
|
||||
return DiskUsageInfo{}, err
|
||||
} else {
|
||||
return DiskUsageInfo{
|
||||
|
||||
@@ -1,35 +1,86 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/shroff/phylum/server/internal/core/db"
|
||||
)
|
||||
|
||||
func (f filesystem) ResourceByPath(path string) (Resource, error) {
|
||||
return f.resourceFromResult(f.db.ResourceByPath(f.ctx, db.ResourceByPathParams{Root: f.rootID, Path: path, Username: f.username}))
|
||||
return f.resourceFromResult(f.db.ResourceByPath(f.ctx, db.ResourceByPathParams{Root: &f.rootID, Path: path}))
|
||||
}
|
||||
|
||||
func (f filesystem) ResourceByID(id uuid.UUID) (Resource, error) {
|
||||
return f.resourceFromResult(f.db.ResourceByID(f.ctx, db.ResourceByIDParams{Root: f.rootID, ResourceID: id, Username: f.username}))
|
||||
return f.resourceFromResult(f.db.ResourceByID(f.ctx, id))
|
||||
}
|
||||
|
||||
func (f filesystem) resourceFromResult(r db.ResourceResult, err error) (Resource, error) {
|
||||
if err == pgx.ErrNoRows || !r.Found || (r.UserPermission&PermissionRead == 0) {
|
||||
func (f filesystem) resourceFromResult(e []db.PublinkedResource, err error) (Resource, error) {
|
||||
if len(e) == 0 {
|
||||
err = ErrResourceNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return Resource{}, err
|
||||
}
|
||||
var b strings.Builder
|
||||
found := false
|
||||
permission := Permission(0)
|
||||
ancestry := make([]ResourceInfo, len(e))
|
||||
for i := len(e) - 1; i >= 0; i-- {
|
||||
if i != len(e)-1 {
|
||||
b.WriteByte('/')
|
||||
b.WriteString(e[i].Name)
|
||||
}
|
||||
info := resourceInfoFromDBPublinkedResource(e[i])
|
||||
if b.Len() == 0 {
|
||||
info.Path = "/"
|
||||
} else {
|
||||
info.Path = b.String()
|
||||
}
|
||||
ancestry[len(e)-i-1] = info
|
||||
|
||||
if e[i].ID == f.rootID {
|
||||
found = true
|
||||
}
|
||||
if p, err := readPermissionFromJson(e[i].Permissions, f.username); err != nil {
|
||||
return Resource{}, err
|
||||
} else {
|
||||
permission = permission | p
|
||||
}
|
||||
}
|
||||
if !found || permission&PermissionRead == 0 {
|
||||
return Resource{}, err
|
||||
}
|
||||
return Resource{
|
||||
f: f,
|
||||
Ancestry: ancestry,
|
||||
UserPermission: permission,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func readPermissionFromJson(j []byte, username string) (Permission, error) {
|
||||
if len(j) == 2 {
|
||||
return PermissionNone, nil
|
||||
}
|
||||
p := make(map[string]Permission)
|
||||
err := json.Unmarshal(j, &p)
|
||||
if err != nil {
|
||||
return PermissionNone, err
|
||||
}
|
||||
if p, ok := p[username]; ok {
|
||||
return p, nil
|
||||
}
|
||||
return PermissionNone, nil
|
||||
}
|
||||
|
||||
func resourceInfoFromDBPublinkedResource(r db.PublinkedResource) ResourceInfo {
|
||||
var delTime *time.Time
|
||||
if r.Deleted.Valid {
|
||||
delTime = &r.Deleted.Time
|
||||
}
|
||||
return Resource{
|
||||
f: f,
|
||||
return ResourceInfo{
|
||||
ID: r.ID,
|
||||
ParentID: r.Parent,
|
||||
Name: r.Name,
|
||||
@@ -42,11 +93,7 @@ func (f filesystem) resourceFromResult(r db.ResourceResult, err error) (Resource
|
||||
ContentSHA256: r.ContentSha256,
|
||||
Permissions: string(r.Permissions),
|
||||
Publinks: int(r.Publinks),
|
||||
// Definitely Needed
|
||||
Path: r.Path,
|
||||
UserPermission: r.UserPermission,
|
||||
InheritedPermissions: string(r.InheritedPermissions),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (f filesystem) ResourceByPathOrUUID(pathOrUUID string) (Resource, error) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shroff/phylum/server/internal/api/serve"
|
||||
"github.com/shroff/phylum/server/internal/core/db"
|
||||
)
|
||||
@@ -12,16 +13,16 @@ func (r Resource) OpenRead(start, length int64) (io.ReadCloser, error) {
|
||||
if !r.hasPermission(PermissionRead) {
|
||||
return nil, ErrInsufficientPermissions
|
||||
}
|
||||
return r.f.cs.OpenRead(r.ID, start, length)
|
||||
return r.f.cs.OpenRead(r.ID(), start, length)
|
||||
}
|
||||
|
||||
func (r Resource) OpenWrite() (io.WriteCloser, error) {
|
||||
if !r.hasPermission(PermissionWrite) {
|
||||
return nil, ErrInsufficientPermissions
|
||||
}
|
||||
return r.f.cs.OpenWrite(r.ID, sha256.New, func(len int, sum, mime string) error {
|
||||
return r.f.cs.OpenWrite(r.ID(), sha256.New, func(len int, sum, mime string) error {
|
||||
return r.f.db.UpdateResourceContents(r.f.ctx, db.UpdateResourceContentsParams{
|
||||
ID: r.ID,
|
||||
ID: r.ID(),
|
||||
ContentType: mime,
|
||||
ContentSize: int64(len),
|
||||
ContentSha256: sum,
|
||||
@@ -29,11 +30,11 @@ func (r Resource) OpenWrite() (io.WriteCloser, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (r Resource) ReadDir(recursive bool) ([]serve.Resource, error) {
|
||||
func (r Resource) ReadDir(recursive bool) ([]serve.ResourceInfo, error) {
|
||||
if !r.hasPermission(PermissionRead) {
|
||||
return nil, ErrInsufficientPermissions
|
||||
}
|
||||
if !r.Dir {
|
||||
if !r.FSDir() {
|
||||
return nil, ErrResourceNotCollection
|
||||
}
|
||||
maxDepth := 1
|
||||
@@ -41,43 +42,30 @@ func (r Resource) ReadDir(recursive bool) ([]serve.Resource, error) {
|
||||
maxDepth = 1000
|
||||
}
|
||||
children, err := r.f.db.ReadDir(r.f.ctx, db.ReadDirParams{
|
||||
ResourceID: r.ID,
|
||||
InheritedPermissions: []byte(r.InheritedPermissions),
|
||||
Path: r.Path,
|
||||
Username: r.f.username,
|
||||
MinDepth: 1,
|
||||
MaxDepth: int32(maxDepth),
|
||||
ResourceID: r.ID(),
|
||||
MinDepth: 1,
|
||||
MaxDepth: int32(maxDepth),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]serve.Resource, len(children))
|
||||
|
||||
result := make([]serve.ResourceInfo, len(children))
|
||||
path := make(map[uuid.UUID]string)
|
||||
path[r.ID()] = r.FSPath()
|
||||
if r.FSPath() == "/" {
|
||||
path[r.ID()] = ""
|
||||
}
|
||||
for i, c := range children {
|
||||
result[i] = Resource{
|
||||
f: r.f,
|
||||
ID: c.ID,
|
||||
ParentID: c.Parent,
|
||||
Name: c.Name,
|
||||
Created: c.Created.Time,
|
||||
Modified: c.Modified.Time,
|
||||
Deleted: nil, // Query will not return deleted results
|
||||
Dir: c.Dir,
|
||||
ContentSize: c.ContentSize,
|
||||
ContentType: c.ContentType,
|
||||
ContentSHA256: c.ContentSha256,
|
||||
Permissions: string(c.Permissions),
|
||||
Publinks: int(c.Publinks),
|
||||
Path: c.Path,
|
||||
UserPermission: c.UserPermission,
|
||||
InheritedPermissions: string(c.InheritedPermissions),
|
||||
}
|
||||
info := resourceInfoFromDBPublinkedResource(c)
|
||||
info.Path = path[*info.ParentID] + "/" + info.Name
|
||||
path[info.ID] = info.Path
|
||||
result[i] = info
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r Resource) Walk(depth int, fn func(serve.Resource) error) error {
|
||||
func (r Resource) Walk(depth int, fn func(serve.ResourceInfo) error) error {
|
||||
err := fn(r)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -22,10 +22,27 @@ func (r Resource) hasPermission(p Permission) bool {
|
||||
}
|
||||
|
||||
func (r Resource) PermissionsString() string {
|
||||
return r.Ancestry[0].PermissionsString()
|
||||
}
|
||||
|
||||
func (r ResourceInfo) PermissionsString() string {
|
||||
return permissionJsonString(r.Permissions)
|
||||
}
|
||||
func (r Resource) InheritedPermissionsString() string {
|
||||
return permissionJsonString(r.InheritedPermissions)
|
||||
|
||||
func (r Resource) FullPermissionsString() string {
|
||||
result := make(map[string]Permission)
|
||||
for _, i := range r.Ancestry {
|
||||
p := make(map[string]Permission)
|
||||
json.Unmarshal([]byte(i.Permissions), &p)
|
||||
for k, v := range p {
|
||||
result[k] = result[k] | v
|
||||
}
|
||||
}
|
||||
res, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return permissionJsonString(string(res))
|
||||
}
|
||||
|
||||
func permissionJsonString(j string) string {
|
||||
|
||||
@@ -35,7 +35,7 @@ func (r Resource) CreatePublink(name, password string, duration time.Duration, a
|
||||
return r.f.db.CreatePublink(r.f.ctx, db.CreatePublinkParams{
|
||||
Name: name,
|
||||
CreatedBy: r.f.username,
|
||||
Root: r.ID,
|
||||
Root: r.ID(),
|
||||
PasswordHash: passwordHash,
|
||||
Expires: expires,
|
||||
MaxAccesses: int32(accesses),
|
||||
@@ -43,7 +43,7 @@ func (r Resource) CreatePublink(name, password string, duration time.Duration, a
|
||||
}
|
||||
|
||||
func (r Resource) ListPublinks() ([]publink.Info, error) {
|
||||
res, err := r.f.db.PublinksByRoot(r.f.ctx, r.ID)
|
||||
res, err := r.f.db.PublinksByRoot(r.f.ctx, r.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -7,29 +7,46 @@ import (
|
||||
)
|
||||
|
||||
type Resource struct {
|
||||
f filesystem
|
||||
ID uuid.UUID `json:"id"`
|
||||
ParentID *uuid.UUID `json:"parent"`
|
||||
Name string `json:"name"`
|
||||
Dir bool `json:"dir"`
|
||||
Created time.Time `json:"created"`
|
||||
Modified time.Time `json:"modified"`
|
||||
Deleted *time.Time `json:"deleted"`
|
||||
ContentSize int64 `json:"csize"`
|
||||
ContentType string `json:"ctype"`
|
||||
ContentSHA256 string `json:"csha256"`
|
||||
Permissions string `json:"permissions"`
|
||||
Publinks int `json:"publinks"`
|
||||
Path string `json:"path"`
|
||||
UserPermission Permission `json:"perm"`
|
||||
InheritedPermissions string `json:"inherited"`
|
||||
f filesystem
|
||||
Ancestry []ResourceInfo `json:"ancestry"`
|
||||
UserPermission Permission `json:"perm"`
|
||||
}
|
||||
|
||||
func (r Resource) FSName() string { return r.Name }
|
||||
func (r Resource) FSPath() string { return r.Path }
|
||||
func (r Resource) FSDir() bool { return r.Dir }
|
||||
func (r Resource) FSCreated() time.Time { return r.Created }
|
||||
func (r Resource) FSModified() time.Time { return r.Modified }
|
||||
func (r Resource) FSContentSize() int64 { return r.ContentSize }
|
||||
func (r Resource) FSContentSHA256() string { return r.ContentSHA256 }
|
||||
func (r Resource) FSContentType() string { return r.ContentType }
|
||||
type ResourceInfo struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ParentID *uuid.UUID `json:"parent"`
|
||||
Name string `json:"name"`
|
||||
Dir bool `json:"dir"`
|
||||
Created time.Time `json:"created"`
|
||||
Modified time.Time `json:"modified"`
|
||||
Deleted *time.Time `json:"deleted"`
|
||||
ContentSize int64 `json:"csize"`
|
||||
ContentType string `json:"ctype"`
|
||||
ContentSHA256 string `json:"csha256"`
|
||||
Permissions string `json:"permissions"`
|
||||
Publinks int `json:"publinks"`
|
||||
Path string `json:"-"`
|
||||
}
|
||||
|
||||
func (r Resource) Info() ResourceInfo { return r.Ancestry[len(r.Ancestry)-1] }
|
||||
func (r Resource) ID() uuid.UUID { return r.Info().ID }
|
||||
func (r Resource) ParentID() *uuid.UUID { return r.Info().ParentID }
|
||||
func (r Resource) FSName() string { return r.Info().Name }
|
||||
func (r Resource) FSDir() bool { return r.Info().Dir }
|
||||
func (r Resource) FSCreated() time.Time { return r.Info().Created }
|
||||
func (r Resource) FSModified() time.Time { return r.Info().Modified }
|
||||
func (r Resource) Deleted() *time.Time { return r.Info().Deleted }
|
||||
func (r Resource) FSContentSize() int64 { return r.Info().ContentSize }
|
||||
func (r Resource) FSContentSHA256() string { return r.Info().ContentSHA256 }
|
||||
func (r Resource) FSContentType() string { return r.Info().ContentType }
|
||||
func (r Resource) Publinks() int { return r.Info().Publinks }
|
||||
func (r Resource) FSPath() string { return r.Info().Path }
|
||||
|
||||
func (r ResourceInfo) FSName() string { return r.Name }
|
||||
func (r ResourceInfo) FSDir() bool { return r.Dir }
|
||||
func (r ResourceInfo) FSCreated() time.Time { return r.Created }
|
||||
func (r ResourceInfo) FSModified() time.Time { return r.Modified }
|
||||
func (r ResourceInfo) FSContentSize() int64 { return r.ContentSize }
|
||||
func (r ResourceInfo) FSContentSHA256() string { return r.ContentSHA256 }
|
||||
func (r ResourceInfo) FSContentType() string { return r.ContentType }
|
||||
func (r ResourceInfo) FSPath() string { return r.Path }
|
||||
|
||||
@@ -15,12 +15,12 @@ func (r Resource) UpdatePermissions(username string, permission Permission) (Res
|
||||
var err error
|
||||
if permission == 0 {
|
||||
p, err = r.f.db.RemoveUserPermissionForResource(r.f.ctx, db.RemoveUserPermissionForResourceParams{
|
||||
ResourceID: r.ID,
|
||||
ResourceID: r.ID(),
|
||||
Username: username,
|
||||
})
|
||||
} else {
|
||||
p, err = r.f.db.UpdateUserPermissionsForResource(r.f.ctx, db.UpdateUserPermissionsForResourceParams{
|
||||
ResourceID: r.ID,
|
||||
ResourceID: r.ID(),
|
||||
Username: username,
|
||||
Permission: permission,
|
||||
})
|
||||
@@ -28,6 +28,6 @@ func (r Resource) UpdatePermissions(username string, permission Permission) (Res
|
||||
if err != nil {
|
||||
return Resource{}, err
|
||||
}
|
||||
r.Permissions = string(p)
|
||||
r.Ancestry[0].Permissions = string(p)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type filesystem struct {
|
||||
}
|
||||
|
||||
func (f filesystem) resourceByPath(search string) (Resource, error) {
|
||||
e, err := f.db.ResourceByPath(f.ctx, db.ResourceByPathParams{Path: search})
|
||||
e, err := f.db.ResourceByPath(f.ctx, db.ResourceByPathParams{Path: search, Root: &f.root})
|
||||
if len(e) == 0 {
|
||||
err = ErrNotFound
|
||||
}
|
||||
@@ -30,14 +30,18 @@ func (f filesystem) resourceByPath(search string) (Resource, error) {
|
||||
if e[i].ID == f.root {
|
||||
found = true
|
||||
}
|
||||
if b.Len() != 0 {
|
||||
if i != len(e)-i {
|
||||
b.WriteByte('/')
|
||||
b.WriteString(e[i].Name)
|
||||
}
|
||||
b.WriteString(e[i].Name)
|
||||
}
|
||||
if !found {
|
||||
return Resource{}, err
|
||||
}
|
||||
path := b.String()
|
||||
if b.Len() == 0 {
|
||||
path = "/"
|
||||
}
|
||||
|
||||
r := e[0]
|
||||
return Resource{
|
||||
@@ -45,7 +49,7 @@ func (f filesystem) resourceByPath(search string) (Resource, error) {
|
||||
id: r.ID,
|
||||
name: r.Name,
|
||||
dir: r.Dir,
|
||||
path: b.String(),
|
||||
path: path,
|
||||
created: r.Created.Time,
|
||||
modified: r.Modified.Time,
|
||||
contentSize: r.ContentSize,
|
||||
|
||||
@@ -37,7 +37,7 @@ func (r Resource) OpenRead(start, length int64) (io.ReadCloser, error) {
|
||||
return r.f.cs.OpenRead(r.id, start, length)
|
||||
}
|
||||
|
||||
func (r Resource) ReadDir(recursive bool) ([]serve.Resource, error) {
|
||||
func (r Resource) ReadDir(recursive bool) ([]serve.ResourceInfo, error) {
|
||||
if !r.dir {
|
||||
return nil, errors.New("resource is not a collection")
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func (r Resource) ReadDir(recursive bool) ([]serve.Resource, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]serve.Resource, len(children))
|
||||
result := make([]serve.ResourceInfo, len(children))
|
||||
|
||||
parentPath := r.path
|
||||
if parentPath == "/" {
|
||||
|
||||
@@ -41,8 +41,8 @@ type Manager interface {
|
||||
ReadAccessToken(accessToken string) (User, error)
|
||||
|
||||
// user_lists.go
|
||||
SharedResources(u User) (result []fs.Resource, err error)
|
||||
Bookmarks(u User) ([]fs.Resource, error)
|
||||
SharedResources(u User) (result []fs.ResourceInfo, err error)
|
||||
Bookmarks(u User) ([]fs.ResourceInfo, error)
|
||||
AddBookmark(u User, resource fs.Resource) error
|
||||
RemoveBookmark(u User, id uuid.UUID) error
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"github.com/shroff/phylum/server/internal/core/fs"
|
||||
)
|
||||
|
||||
func (m manager) SharedResources(u User) ([]fs.Resource, error) {
|
||||
func (m manager) SharedResources(u User) ([]fs.ResourceInfo, error) {
|
||||
// TODO: #permissions This doesn't take permissions into account. is this okay?
|
||||
res, err := m.db.Queries.SharedResources(m.ctx, db.SharedResourcesParams{Username: u.Username, UserHome: u.Home})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]fs.Resource, len(res))
|
||||
result := make([]fs.ResourceInfo, len(res))
|
||||
for i, r := range res {
|
||||
result[i] = resourceFromDB(r)
|
||||
}
|
||||
@@ -23,33 +23,33 @@ func (m manager) SharedResources(u User) ([]fs.Resource, error) {
|
||||
}
|
||||
|
||||
func (m manager) AddBookmark(u User, resource fs.Resource) error {
|
||||
return m.db.Queries.AddBookmark(m.ctx, db.AddBookmarkParams{Username: u.Username, ID: resource.ID})
|
||||
return m.db.Queries.AddBookmark(m.ctx, db.AddBookmarkParams{Username: u.Username, ID: resource.ID()})
|
||||
}
|
||||
|
||||
func (m manager) RemoveBookmark(u User, id uuid.UUID) error {
|
||||
return m.db.Queries.RemoveBookmark(m.ctx, db.RemoveBookmarkParams{Username: u.Username, ID: id})
|
||||
}
|
||||
|
||||
func (m manager) Bookmarks(u User) ([]fs.Resource, error) {
|
||||
func (m manager) Bookmarks(u User) ([]fs.ResourceInfo, error) {
|
||||
// TODO: #permissions This doesn't take permissions into account. is this okay?
|
||||
res, err := m.db.Queries.ListBookmarks(m.ctx, u.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]fs.Resource, len(res))
|
||||
result := make([]fs.ResourceInfo, len(res))
|
||||
for i, r := range res {
|
||||
result[i] = resourceFromDB(r)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func resourceFromDB(r db.Resource) fs.Resource {
|
||||
func resourceFromDB(r db.Resource) fs.ResourceInfo {
|
||||
var deleted *time.Time
|
||||
if r.Deleted.Valid {
|
||||
deleted = &r.Deleted.Time
|
||||
}
|
||||
return fs.Resource{
|
||||
return fs.ResourceInfo{
|
||||
ID: r.ID,
|
||||
ParentID: r.Parent,
|
||||
Name: r.Name,
|
||||
|
||||
Reference in New Issue
Block a user