Packages
phoenix_kit
1.6.5
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
Current section
Files
lib/modules/storage/storage.ex
defmodule PhoenixKit.Modules.Storage do
@moduledoc """
Storage Module for PhoenixKit.
This module provides a distributed file storage system with redundancy support.
Files can be stored across multiple locations (local, S3, remote servers) with
automatic failover if a storage location becomes unavailable.
## Features
- **Multi-location storage**: Store files in 1-5 redundant locations
- **Automatic failover**: If one location fails, automatically use another
- **Local storage**: Default storage to `priv/uploads`
- **S3 support**: Optional AWS S3 integration (future)
- **Remote servers**: Support for distributed storage across multiple servers (future)
## Module Status
This module is **always enabled** and cannot be disabled. It provides core
functionality for file management across PhoenixKit.
## Configuration
The module uses the following settings stored in the database:
- `storage_default_path` - Default local storage path (default: "priv/uploads")
## Usage
# Get storage configuration
config = PhoenixKit.Modules.Storage.get_config()
# => %{default_path: "priv/uploads"}
# Get default storage path
path = PhoenixKit.Modules.Storage.get_default_path()
# => "priv/uploads"
"""
alias PhoenixKit.Settings
@default_path "priv/uploads"
@doc """
Checks if the Storage module is enabled.
This module is always enabled and cannot be disabled.
## Examples
iex> PhoenixKit.Modules.Storage.module_enabled?()
true
"""
def module_enabled?, do: true
@doc """
Gets the default storage path for local file uploads (relative path).
Returns the configured relative path or the default "priv/uploads" if not set.
## Examples
iex> PhoenixKit.Modules.Storage.get_default_path()
"priv/uploads"
"""
def get_default_path do
Settings.get_setting("storage_default_path", @default_path)
end
@doc """
Gets the absolute storage path for local file uploads.
Expands the relative path from settings to an absolute path.
## Examples
iex> PhoenixKit.Modules.Storage.get_absolute_path()
"/Users/don/Projects/pk/phoenix_kit/priv/uploads"
"""
def get_absolute_path do
relative_path = get_default_path()
Path.expand(relative_path, File.cwd!())
end
@doc """
Validates and normalizes a storage path.
Takes a path (absolute or relative), validates it exists and is writable,
and returns the relative path for storage.
## Examples
iex> PhoenixKit.Modules.Storage.validate_and_normalize_path("/full/path/to/storage")
{:ok, "relative/path/to/storage"}
iex> PhoenixKit.Modules.Storage.validate_and_normalize_path("/nonexistent")
{:error, "Directory does not exist: /nonexistent"}
"""
def validate_and_normalize_path(path) when is_binary(path) do
# Expand to absolute path for validation
absolute_path = Path.expand(path, File.cwd!())
cond do
not File.exists?(absolute_path) ->
# Return special tuple to indicate directory can be created
{:error, :does_not_exist, absolute_path}
not File.dir?(absolute_path) ->
{:error, "Path is not a directory: #{absolute_path}"}
not writable?(absolute_path) ->
{:error, "Directory is not writable: #{absolute_path}"}
true ->
# Convert to relative path for storage
relative_path = Path.relative_to(absolute_path, File.cwd!())
{:ok, relative_path}
end
end
@doc """
Creates a directory at the specified path.
Creates all parent directories if they don't exist (mkdir -p behavior).
## Examples
iex> PhoenixKit.Modules.Storage.create_directory("/path/to/new/dir")
{:ok, "/path/to/new/dir"}
iex> PhoenixKit.Modules.Storage.create_directory("/invalid/path")
{:error, "Failed to create directory: eacces"}
"""
def create_directory(path) when is_binary(path) do
absolute_path = Path.expand(path, File.cwd!())
case File.mkdir_p(absolute_path) do
:ok -> {:ok, absolute_path}
{:error, reason} -> {:error, "Failed to create directory: #{reason}"}
end
end
@doc """
Updates the default storage path (stores relative path).
## Examples
iex> PhoenixKit.Modules.Storage.update_default_path("uploads")
{:ok, %PhoenixKit.Settings.Setting{}}
"""
def update_default_path(path) when is_binary(path) do
Settings.update_setting("storage_default_path", path)
end
@doc """
Gets the configuration for the Storage module.
Returns a map with:
- `module_enabled` - Always true (non-disablable module)
- `default_path` - Default local storage path
## Examples
iex> PhoenixKit.Modules.Storage.get_config()
%{
module_enabled: true,
default_path: "priv/uploads"
}
"""
def get_config do
buckets = PhoenixKit.Storage.list_buckets()
active_count = Enum.count(buckets, & &1.enabled)
%{
module_enabled: true,
buckets_count: length(buckets),
active_buckets_count: active_count
}
end
# Private helper to check if directory is writable
defp writable?(path) do
test_file = Path.join(path, ".phoenix_kit_write_test")
case File.write(test_file, "test") do
:ok ->
File.rm(test_file)
true
{:error, _} ->
false
end
end
end