Packages

phoenix_kit

1.7.206
1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules storage schemas bucket.ex
Raw

lib/modules/storage/schemas/bucket.ex

defmodule PhoenixKit.Modules.Storage.Bucket do
@moduledoc """
Schema for storage provider configurations.
Buckets represent storage locations where files can be stored. They can be:
- **Local** filesystem storage
- **AWS S3** buckets
- **Backblaze B2** buckets
- **Cloudflare R2** buckets
## Priority System
- `priority = 0` (default): Random selection, prefer most empty drive
- `priority > 0`: Specific priority (1 = highest, 2 = second, etc.)
## Fields
- `name` - Display name for the bucket
- `provider` - Storage provider: "local", "s3", "b2", "r2"
- `region` - AWS region or equivalent (nullable)
- `endpoint` - Custom S3-compatible endpoint (nullable)
- `bucket_name` - S3 bucket name (nullable)
- `access_key_id` - Encrypted credentials (nullable)
- `secret_access_key` - Encrypted credentials (nullable)
- `cdn_url` - CDN endpoint for file serving (nullable)
- `access_type` - How files are served: "public", "private", "signed" (default: "public")
- `enabled` - Whether bucket is active
- `priority` - Selection priority (0 = random/emptiest)
- `max_size_mb` - Maximum storage capacity in MB (nullable = unlimited)
## Access Types
- `public` - Redirect to public URL (default, fastest, uses CDN)
- `private` - Proxy files through server (for ACL-protected buckets)
- `signed` - Use presigned URLs (future implementation)
## Examples
# Local storage bucket
%Bucket{
name: "Local SSD",
provider: "local",
enabled: true,
priority: 0,
max_size_mb: 512_000 # 500 GB
}
# AWS S3 bucket
%Bucket{
name: "Production S3",
provider: "s3",
region: "us-east-1",
bucket_name: "my-app-files",
access_key_id: "AKIA...",
secret_access_key: "...",
cdn_url: "https://cdn.example.com",
enabled: true,
priority: 1 # Highest priority
}
# Backblaze B2 bucket
%Bucket{
name: "Backup B2",
provider: "b2",
endpoint: "s3.us-west-002.backblazeb2.com",
bucket_name: "my-backup-bucket",
access_key_id: "...",
secret_access_key: "...",
enabled: true,
priority: 2
}
"""
use Ecto.Schema
use PhoenixKit.SchemaPrefix
import Ecto.Changeset
@primary_key {:uuid, UUIDv7, autogenerate: true}
@foreign_key_type UUIDv7
@type t :: %__MODULE__{
uuid: UUIDv7.t() | nil,
name: String.t(),
provider: String.t(),
region: String.t() | nil,
endpoint: String.t() | nil,
bucket_name: String.t() | nil,
access_key_id: String.t() | nil,
secret_access_key: String.t() | nil,
cdn_url: String.t() | nil,
access_type: String.t(),
enabled: boolean(),
priority: integer(),
max_size_mb: integer() | nil,
file_locations:
[PhoenixKit.Modules.Storage.FileLocation.t()] | Ecto.Association.NotLoaded.t(),
inserted_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil
}
schema "phoenix_kit_buckets" do
field :name, :string
field :provider, :string
field :region, :string
field :endpoint, :string
field :bucket_name, :string
field :access_key_id, :string
field :secret_access_key, :string
field :cdn_url, :string
field :access_type, :string, default: "public"
field :enabled, :boolean, default: true
field :priority, :integer, default: 0
field :max_size_mb, :integer
has_many :file_locations, PhoenixKit.Modules.Storage.FileLocation, foreign_key: :bucket_uuid
timestamps(type: :utc_datetime)
end
@doc """
Changeset for creating or updating a bucket.
## Required Fields
- `name`
- `provider` (must be one of: "local", "s3", "b2", "r2")
## Validation Rules
- Provider must be valid
- Priority must be >= 0
- Quality must be between 1-100 (if provided)
- S3/B2/R2 buckets require credentials
"""
def changeset(bucket, attrs) do
bucket
|> cast(attrs, [
:name,
:provider,
:region,
:endpoint,
:bucket_name,
:access_key_id,
:secret_access_key,
:cdn_url,
:access_type,
:enabled,
:priority,
:max_size_mb
])
|> validate_required([:name, :provider])
|> validate_inclusion(:provider, ["local", "s3", "b2", "r2", "tigris"])
|> validate_inclusion(:access_type, ["public", "private", "signed"])
|> validate_number(:priority, greater_than_or_equal_to: 0)
|> validate_number(:max_size_mb, greater_than: 0)
|> validate_cloud_credentials()
end
defp validate_cloud_credentials(changeset) do
provider = get_field(changeset, :provider)
if provider in ["s3", "b2", "r2"] do
changeset
|> validate_required([:bucket_name, :access_key_id, :secret_access_key])
else
changeset
end
end
@doc """
Returns whether this bucket is a local storage bucket.
"""
def local?(%__MODULE__{provider: "local"}), do: true
def local?(_), do: false
@doc """
Returns whether this bucket is a cloud storage bucket (S3, B2, R2).
"""
def cloud?(%__MODULE__{provider: provider}) when provider in ["s3", "b2", "r2"], do: true
def cloud?(_), do: false
end