Add functionality to download folders as ZIP archives for both org and user files
This commit is contained in:
@@ -373,6 +373,55 @@ func (db *DB) GetOrgFiles(ctx context.Context, orgID uuid.UUID, userID uuid.UUID
|
||||
return files, err
|
||||
}
|
||||
|
||||
// GetAllOrgFilesUnderPath returns all files recursively under the given path for an org
|
||||
func (db *DB) GetAllOrgFilesUnderPath(ctx context.Context, orgID uuid.UUID, userID uuid.UUID, path string) ([]File, error) {
|
||||
orgIDStr := orgID.String()
|
||||
userIDStr := userID.String()
|
||||
log.Printf("[DATA-ISOLATION] stage=before, action=list_recursive, orgId=%s, userId=%s, path=%s", orgIDStr, userIDStr, path)
|
||||
|
||||
rows, err := db.QueryContext(ctx, `
|
||||
SELECT f.id, f.org_id::text, f.user_id::text, f.name, f.path, f.type, f.size, f.last_modified, f.created_at
|
||||
FROM files f
|
||||
WHERE f.org_id = $1
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM memberships m
|
||||
WHERE m.org_id = $1 AND m.user_id = $2
|
||||
)
|
||||
AND f.path LIKE $3 || '%'
|
||||
AND f.path != $3
|
||||
ORDER BY f.path
|
||||
`, orgID, userID, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var files []File
|
||||
for rows.Next() {
|
||||
var f File
|
||||
var orgNull sql.NullString
|
||||
var userNull sql.NullString
|
||||
if err := rows.Scan(&f.ID, &orgNull, &userNull, &f.Name, &f.Path, &f.Type, &f.Size, &f.LastModified, &f.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if orgNull.Valid {
|
||||
oid, _ := uuid.Parse(orgNull.String)
|
||||
f.OrgID = &oid
|
||||
}
|
||||
if userNull.Valid {
|
||||
uid, _ := uuid.Parse(userNull.String)
|
||||
f.UserID = &uid
|
||||
}
|
||||
files = append(files, f)
|
||||
}
|
||||
err = rows.Err()
|
||||
if err == nil {
|
||||
log.Printf("[DATA-ISOLATION] stage=after, action=list_recursive, orgId=%s, userId=%s, fileCount=%d, path=%s", orgIDStr, userIDStr, len(files), path)
|
||||
}
|
||||
return files, err
|
||||
}
|
||||
|
||||
// GetUserFiles returns files for a user's personal workspace at a given path
|
||||
func (db *DB) GetUserFiles(ctx context.Context, userID uuid.UUID, path string, q string, page, pageSize int) ([]File, error) {
|
||||
if page <= 0 {
|
||||
@@ -429,6 +478,49 @@ func (db *DB) GetUserFiles(ctx context.Context, userID uuid.UUID, path string, q
|
||||
return files, err
|
||||
}
|
||||
|
||||
// GetAllUserFilesUnderPath returns all files recursively under the given path for a user
|
||||
func (db *DB) GetAllUserFilesUnderPath(ctx context.Context, userID uuid.UUID, path string) ([]File, error) {
|
||||
// Return all descendants of the given path
|
||||
log.Printf("[DATA-ISOLATION] stage=before, action=list_recursive, orgId=, userId=%s, path=%s", userID.String(), path)
|
||||
rows, err := db.QueryContext(ctx, `
|
||||
SELECT id, org_id::text, user_id::text, name, path, type, size, last_modified, created_at
|
||||
FROM files
|
||||
WHERE user_id = $1
|
||||
AND org_id IS NULL
|
||||
AND path LIKE $2 || '%'
|
||||
AND path != $2
|
||||
ORDER BY path
|
||||
`, userID, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var files []File
|
||||
for rows.Next() {
|
||||
var f File
|
||||
var orgNull sql.NullString
|
||||
var userNull sql.NullString
|
||||
if err := rows.Scan(&f.ID, &orgNull, &userNull, &f.Name, &f.Path, &f.Type, &f.Size, &f.LastModified, &f.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if orgNull.Valid {
|
||||
oid, _ := uuid.Parse(orgNull.String)
|
||||
f.OrgID = &oid
|
||||
}
|
||||
if userNull.Valid {
|
||||
uid, _ := uuid.Parse(userNull.String)
|
||||
f.UserID = &uid
|
||||
}
|
||||
files = append(files, f)
|
||||
}
|
||||
err = rows.Err()
|
||||
if err == nil {
|
||||
log.Printf("[DATA-ISOLATION] stage=after, action=list_recursive, orgId=, userId=%s, fileCount=%d, path=%s", userID.String(), len(files), path)
|
||||
}
|
||||
return files, err
|
||||
}
|
||||
|
||||
// CreateFile inserts a file or folder record. orgID or userID may be nil.
|
||||
func (db *DB) CreateFile(ctx context.Context, orgID *uuid.UUID, userID *uuid.UUID, name, path, fileType string, size int64) (*File, error) {
|
||||
var f File
|
||||
@@ -502,6 +594,94 @@ func (db *DB) GetFileByID(ctx context.Context, fileID uuid.UUID) (*File, error)
|
||||
return &f, nil
|
||||
}
|
||||
|
||||
// GetOrgFileByPath returns a file by path for an org
|
||||
func (db *DB) GetOrgFileByPath(ctx context.Context, orgID uuid.UUID, userID uuid.UUID, path string) (*File, error) {
|
||||
var f File
|
||||
var orgNull sql.NullString
|
||||
var userNull sql.NullString
|
||||
var modifiedByNull sql.NullString
|
||||
var modifiedByNameNull sql.NullString
|
||||
|
||||
err := db.QueryRowContext(ctx, `
|
||||
SELECT f.id, f.org_id::text, f.user_id::text, f.name, f.path, f.type, f.size, f.last_modified, f.created_at,
|
||||
f.modified_by::text, u.display_name
|
||||
FROM files f
|
||||
LEFT JOIN users u ON f.modified_by = u.id
|
||||
WHERE f.org_id = $1
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM memberships m
|
||||
WHERE m.org_id = $1 AND m.user_id = $2
|
||||
)
|
||||
AND f.path = $3
|
||||
`, orgID, userID, path).Scan(&f.ID, &orgNull, &userNull, &f.Name, &f.Path, &f.Type, &f.Size, &f.LastModified, &f.CreatedAt,
|
||||
&modifiedByNull, &modifiedByNameNull)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if orgNull.Valid {
|
||||
oid, _ := uuid.Parse(orgNull.String)
|
||||
f.OrgID = &oid
|
||||
}
|
||||
if userNull.Valid {
|
||||
uid, _ := uuid.Parse(userNull.String)
|
||||
f.UserID = &uid
|
||||
}
|
||||
if modifiedByNull.Valid {
|
||||
mid, _ := uuid.Parse(modifiedByNull.String)
|
||||
f.ModifiedBy = &mid
|
||||
}
|
||||
if modifiedByNameNull.Valid {
|
||||
f.ModifiedByName = modifiedByNameNull.String
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
||||
|
||||
// GetUserFileByPath returns a file by path for a user
|
||||
func (db *DB) GetUserFileByPath(ctx context.Context, userID uuid.UUID, path string) (*File, error) {
|
||||
var f File
|
||||
var orgNull sql.NullString
|
||||
var userNull sql.NullString
|
||||
var modifiedByNull sql.NullString
|
||||
var modifiedByNameNull sql.NullString
|
||||
|
||||
err := db.QueryRowContext(ctx, `
|
||||
SELECT f.id, f.org_id::text, f.user_id::text, f.name, f.path, f.type, f.size, f.last_modified, f.created_at,
|
||||
f.modified_by::text, u.display_name
|
||||
FROM files f
|
||||
LEFT JOIN users u ON f.modified_by = u.id
|
||||
WHERE f.user_id = $1
|
||||
AND f.org_id IS NULL
|
||||
AND f.path = $2
|
||||
`, userID, path).Scan(&f.ID, &orgNull, &userNull, &f.Name, &f.Path, &f.Type, &f.Size, &f.LastModified, &f.CreatedAt,
|
||||
&modifiedByNull, &modifiedByNameNull)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if orgNull.Valid {
|
||||
oid, _ := uuid.Parse(orgNull.String)
|
||||
f.OrgID = &oid
|
||||
}
|
||||
if userNull.Valid {
|
||||
uid, _ := uuid.Parse(userNull.String)
|
||||
f.UserID = &uid
|
||||
}
|
||||
if modifiedByNull.Valid {
|
||||
mid, _ := uuid.Parse(modifiedByNull.String)
|
||||
f.ModifiedBy = &mid
|
||||
}
|
||||
if modifiedByNameNull.Valid {
|
||||
f.ModifiedByName = modifiedByNameNull.String
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
||||
|
||||
// UpdateFileSize updates the size, modification time, and modifier of a file
|
||||
func (db *DB) UpdateFileSize(ctx context.Context, fileID uuid.UUID, size int64, modifiedBy *uuid.UUID) error {
|
||||
_, err := db.ExecContext(ctx, `
|
||||
|
||||
Reference in New Issue
Block a user