Storage Permissions

Developer reference for the dual permission model on storage entities — managing storage configuration vs file operations

storagepermissionsanonymousdeveloper

Storage Permissions

Storage entities use a dual permission model: one permission set controls the storage configuration (who can edit or delete the storage itself), and a separate permission set controls file operations (who can upload, download, or delete files within the storage).

This separation allows you to have, for example, admin-only storage management while allowing anonymous file uploads.

Permission fields

The Storage interface has two independent permission fields:

interface Storage extends TenantEntity {
  name: string;
  type: StorageProviderType;
  configuration?: StorageConfiguration;
  isDefault?: boolean;
  quotaBytes?: number;
  usedBytes?: number;
  access?: EntityAccess;       // Storage management permissions
  fileAccess?: CrdPermissions; // File operation permissions
}

Both fields are optional. When not set, both default to project-level permissions.

access — storage management permissions

Controls CRUD operations on the Storage entity itself: who can view, edit, or delete the storage configuration.

Uses the EntityAccess interface with Row Level Security (RLS).

Default (when not set): project-level read/update/delete permissions.

fileAccess — file operation permissions

Controls operations on files within the storage: upload (create), download (read), delete.

Uses the CrdPermissions interface. Update is not supported — files are immutable once uploaded.

Default (when not set):

  • Create: project update permission
  • Read: project read permission
  • Delete: project update permission

Permission checking order

For file operations:

  1. Storage-specific file permissions (fileAccess) take precedence
  2. Falls back to project permissions if fileAccess is not set
  3. Anonymous access is only allowed if explicitly set in fileAccess

For storage management:

  1. Storage-specific management permissions (access) take precedence
  2. Falls back to project permissions if access is not set

Examples

Anonymous upload storage

Allow anyone to upload and view files (e.g., event photo collection):

const anonymousStorage: Storage = {
  name: "Event Photo Uploads",
  type: "s3",
  configuration: { /* S3 config */ },
  fileAccess: {
    create: { permission: "anonymous" },
    read: { permission: "anonymous" }
    // delete not set — defaults to project update permission
  }
  // access not set — storage management defaults to project permissions
};

Private storage with admin management

Project members can upload, but only admins can manage the storage configuration:

const privateStorage: Storage = {
  name: "Private Documents",
  type: "s3",
  configuration: { /* S3 config */ },
  access: {
    rls: {
      read: { userIds: ["admin1"] },
      update: { userIds: ["admin1"] },
      delete: { userIds: ["admin1"] }
    }
  }
  // fileAccess not set — defaults to project read/update permissions
};

Per-user file access

Different users get different file operation permissions:

const teamStorage: Storage = {
  name: "Team Shared Storage",
  type: "s3",
  configuration: { /* S3 config */ },
  fileAccess: {
    create: { userIds: ["user1", "user2"] },
    read: { userIds: ["user1", "user2", "user3"] },
    delete: { userIds: ["user1"] }
  },
  access: {
    rls: {
      read: { userIds: ["user1", "user2", "user3", "admin"] },
      update: { userIds: ["admin"] },
      delete: { userIds: ["admin"] }
    }
  }
};

Utility functions

// Check if a user can perform storage management operations
hasStoragePermission(user, storage, project, operation)

// Check if a user can upload files
hasStorageFileUploadPermission(user, storage)

// Check if anonymous file access is allowed for a given operation
isAnonymousStorageAccessAllowed(storage, operation)

// Get the default file access permissions for new storages
getDefaultStorageFileAccess()

Security rules

  • Anonymous file access must be explicitly configured in fileAccess — it is off by default
  • Only create and read operations in fileAccess can be set to anonymous
  • delete should require authentication for anonymous storages in most cases
  • Storage management (access field) should not allow anonymous access
  • The access and fileAccess fields are completely independent — configuring one does not affect the other

Backward compatibility

Existing storages without access or fileAccess fields continue to work unchanged. Both fields are optional and fall back to project-level permissions when absent.