
# 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:

```typescript
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):

```typescript
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:

```typescript
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:

```typescript
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

```typescript
// 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.

## Related

- [Storage & Files](/data/storage) — admin guide for configuring storage providers
- [SharePoint Templates](/data/sharepoint) — SharePoint-specific template configuration
