Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change file uploads path, closes #1183 #1184

Merged
merged 6 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ RUN mix local.hex --force && \
# set build ENV
ENV MIX_ENV="prod"

# allow builds on apple silicon macs
ENV ERL_AFLAGS="+JMsingle true"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
Expand Down
2 changes: 2 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@ config :swoosh, Animina.Mailer, adapter: Swoosh.Adapters.Local
config :ash, :pub_sub, debug?: true

config :animina, :environment, :dev

config :animina, :uploads_directory, "priv/static/uploads"
2 changes: 2 additions & 0 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ config :animina, :number_of_days_to_filter_registered_users, 600

config :animina, :environment, :prod

config :animina, :uploads_directory, "/uploads"

# Runtime production configuration, including reading
# of environment variables, is done on config/runtime.exs.
4 changes: 3 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ config :animina, Animina.Repo,
hostname: "localhost",
database: "animina_test#{System.get_env("MIX_TEST_PARTITION")}",
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 10
pool_size: 20

# We don't run a server during test. If one is required,
# you can enable the server option below.
Expand Down Expand Up @@ -43,3 +43,5 @@ config :phoenix, :plug_init_mode, :runtime
config :animina, Oban, testing: :manual

config :animina, :environment, :test

config :animina, :uploads_directory, "priv/static/uploads"
34 changes: 24 additions & 10 deletions lib/animina/accounts/resources/photo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule Animina.Accounts.Photo do
alias Animina.ImageTagging
alias Animina.Narratives
alias Animina.Narratives.Story
alias Animina.PathHelper

alias Animina.Traits.Flag

Expand Down Expand Up @@ -288,7 +289,8 @@ defmodule Animina.Accounts.Photo do
end

defp delete_photo_from_filesystem(photo) do
file_path = "priv/static/uploads/#{photo.filename}"
uploads_path = PathHelper.uploads_path()
file_path = uploads_path <> "/#{photo.filename}"

if File.exists?(file_path) do
case File.rm(file_path) do
Expand All @@ -306,8 +308,10 @@ defmodule Animina.Accounts.Photo do
end

defp delete_optimized_photos(photo) do
uploads_path = PathHelper.uploads_path()

for type <- [:thumbnail, :normal, :big] do
optimized_photo_path = "priv/static/uploads/optimized/#{type}/#{photo.filename}"
optimized_photo_path = uploads_path <> "/optimized/#{type}/#{photo.filename}"

if File.exists?(optimized_photo_path) do
case File.rm(optimized_photo_path) do
Expand All @@ -329,7 +333,9 @@ defmodule Animina.Accounts.Photo do
end

def create_photo_flags(record) do
if File.exists?("priv/static/uploads/" <> record.filename) do
uploads_path = PathHelper.uploads_path()

if File.exists?(uploads_path <> "/#{record.filename}") do
{flags, description} =
ImageTagging.auto_tag_image("#{record.filename}")

Expand Down Expand Up @@ -490,8 +496,10 @@ defmodule Animina.Accounts.Photo do
end

defp create_optimized_folder_if_not_exists do
uploads_path = PathHelper.uploads_path()

for type <- ["thumbnail", "normal", "big"] do
case File.mkdir_p("priv/static/uploads/optimized/#{type}") do
case File.mkdir_p(uploads_path <> "/optimized/#{type}") do
:ok ->
:ok

Expand All @@ -513,10 +521,12 @@ defmodule Animina.Accounts.Photo do
end

defp copy_image(file_name, type) do
if File.exists?("priv/static/uploads/" <> file_name) do
uploads_path = PathHelper.uploads_path()

if File.exists?(uploads_path <> "/#{file_name}") do
case File.cp!(
"priv/static/uploads/" <> file_name,
"priv/static/uploads/optimized/#{type}/#{file_name}"
uploads_path <> "/#{file_name}",
uploads_path <> "/optimized/#{type}/#{file_name}"
) do
:ok ->
"/uploads/optimized/#{type}/#{file_name}"
Expand All @@ -532,6 +542,8 @@ defmodule Animina.Accounts.Photo do
end

defp resize_image(record) do
uploads_path = PathHelper.uploads_path()

for type <- [
%{
width: 100,
Expand All @@ -548,7 +560,7 @@ defmodule Animina.Accounts.Photo do
type: :big
}
] do
if File.exists?("priv/static/uploads/" <> record.filename) do
if File.exists?(uploads_path <> "/#{record.filename}") do
OptimizedPhoto.create(%{
image_url: resize_image(record.filename, type.width, type.type),
type: type.type,
Expand All @@ -567,11 +579,13 @@ defmodule Animina.Accounts.Photo do
end

defp resize_image(image_path, width, type) do
uploads_path = PathHelper.uploads_path()

image =
Mogrify.open("priv/static/uploads/" <> image_path)
Mogrify.open(uploads_path <> "/#{image_path}")
|> Mogrify.resize("#{width}")
|> Mogrify.format("webp")
|> Mogrify.save(path: "priv/static/uploads/optimized/#{type}/#{image_path}")
|> Mogrify.save(path: uploads_path <> "/optimized/#{type}/#{image_path}")

image.path
end
Expand Down
6 changes: 2 additions & 4 deletions lib/animina/actions/process_photo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Animina.Actions.ProcessPhoto do
@moduledoc """
This is the Process Photo action module
"""
alias Animina.PathHelper
use Ash.Resource.ManualUpdate

require Logger
Expand Down Expand Up @@ -79,9 +80,6 @@ defmodule Animina.Actions.ProcessPhoto do
end

defp get_upload_dir(filename) do
Path.join(
Application.app_dir(:animina, "priv/static/uploads"),
Path.basename(filename)
)
PathHelper.uploads_path() |> Path.join(Path.basename(filename))
end
end
16 changes: 12 additions & 4 deletions lib/animina/image_tagging.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ defmodule Animina.ImageTagging do
@moduledoc """
This module is responsible for tagging images using the Llava model.
"""
alias Animina.PathHelper
alias Animina.Traits.Flag

def auto_tag_image(image) do
new_image = "priv/static/uploads/#{image}"
uploads_path = PathHelper.uploads_path()
new_image = uploads_path <> "/#{image}"

tmp_image_path = "/tmp/test-photo.jpg"
File.cp!(new_image, tmp_image_path)
# Create a temporary file with the same extension as the original image
extname = Path.extname(image)
{:ok, temp_file} = Briefly.create(extname: extname)

{:ok, binary} = File.read(tmp_image_path)
File.cp!(new_image, temp_file)

{:ok, binary} = File.read(temp_file)

photo = Base.encode64(binary)

Expand Down Expand Up @@ -50,6 +55,9 @@ defmodule Animina.ImageTagging do

{flag, description} = parse_response(response["message"]["content"])

# Ensure the temporary file is deleted
File.rm(temp_file)

{flag, description}
end

Expand Down
5 changes: 4 additions & 1 deletion lib/animina_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ defmodule AniminaWeb.Endpoint do
gzip: false,
only: AniminaWeb.static_paths()

plug Plug.Static, at: "/uploads", from: "priv/static/uploads", gzip: false
plug Plug.Static,
at: "/uploads",
from: Application.compile_env(:animina, :uploads_directory),
gzip: false

# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
Expand Down
4 changes: 3 additions & 1 deletion lib/animina_web/live/profile_photo_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule AniminaWeb.ProfilePhotoLive do
alias Animina.Accounts.Photo
alias Animina.Accounts.User
alias Animina.GenServers.ProfileViewCredits
alias Animina.PathHelper
alias Animina.Traits.UserFlags
alias AshPhoenix.Form
alias Phoenix.PubSub
Expand Down Expand Up @@ -94,7 +95,8 @@ defmodule AniminaWeb.ProfilePhotoLive do
filename = entry.uuid <> "." <> ext(entry)

dest =
Path.join(Application.app_dir(:animina, "priv/static/uploads"), Path.basename(filename))
PathHelper.uploads_path()
|> Path.join(Path.basename(filename))

File.cp!(path, dest)

Expand Down
4 changes: 3 additions & 1 deletion lib/animina_web/live/story_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule AniminaWeb.StoryLive do
alias Animina.Narratives
alias Animina.Narratives.Headline
alias Animina.Narratives.Story
alias Animina.PathHelper
alias AshPhoenix.Form
alias Phoenix.PubSub

Expand Down Expand Up @@ -403,7 +404,8 @@ defmodule AniminaWeb.StoryLive do
filename = entry.uuid <> "." <> ext(entry)

dest =
Path.join(Application.app_dir(:animina, "priv/static/uploads"), Path.basename(filename))
PathHelper.uploads_path()
|> Path.join(Path.basename(filename))

File.cp!(path, dest)

Expand Down
18 changes: 18 additions & 0 deletions lib/animina_web/path_helper.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Animina.PathHelper do
@moduledoc """
String helper functions.
"""

@doc """
Returns an upload path depending on the environment.
"""
def uploads_path do
uploads_directory = Application.get_env(:animina, :uploads_directory) || "/uploads"

case Application.get_env(:animina, :environment) do
:test -> Application.app_dir(:animina, uploads_directory)
:dev -> Application.app_dir(:animina, uploads_directory)
_ -> uploads_directory
end
end
end
5 changes: 4 additions & 1 deletion lib/mix/tasks/seed_demo_system.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ if Enum.member?([:dev, :test], Application.get_env(:animina, :environment)) do
alias Animina.Accounts.UserRole
alias Animina.Narratives.Headline
alias Animina.Narratives.Story
alias Animina.PathHelper
alias Animina.Traits.Flag
alias Animina.Traits.UserFlags

alias Faker.Phone

require Ash.Query
Expand Down Expand Up @@ -770,7 +772,8 @@ if Enum.member?([:dev, :test], Application.get_env(:animina, :environment)) do
HTTPoison.get!(url, [], timeout: 50_000, recv_timeout: 50_000)

dest =
Path.join(Application.app_dir(:animina, "priv/static/uploads"), Path.basename(filename))
PathHelper.uploads_path()
|> Path.join(Path.basename(filename))

File.write!(dest, body)
%{size: size} = File.stat!(dest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,51 @@ defmodule Animina.Repo.Migrations.AddIndexesToResourcesUsedInFastUser do
use Ecto.Migration

def up do
create index(:users, [:zip_code])
create_if_not_exists index(:users, [:zip_code])

create index(:users, [:is_private])
create_if_not_exists index(:users, [:is_private])

create index(:users, [:created_at])
create_if_not_exists index(:users, [:created_at])

create index(:users, [:gender])
create_if_not_exists index(:users, [:gender])

create index(:users, [:state])
create_if_not_exists index(:users, [:state])

create index(:users, [:registration_completed_at])
create_if_not_exists index(:users, [:registration_completed_at])

create index(:user_roles, [:user_id])
create_if_not_exists index(:user_roles, [:user_id])

create index(:user_roles, [:role_id])
create_if_not_exists index(:user_roles, [:role_id])

create index(:traits_flags, [:category_id])
create_if_not_exists index(:traits_flags, [:category_id])

create index(:stories, [:user_id])
create_if_not_exists index(:stories, [:user_id])

create index(:stories, [:headline_id])
create_if_not_exists index(:stories, [:headline_id])

create index(:reactions, [:receiver_id])
create_if_not_exists index(:reactions, [:receiver_id])

create index(:reactions, [:sender_id])
create_if_not_exists index(:reactions, [:sender_id])

create index(:photos, [:user_id])
create_if_not_exists index(:photos, [:user_id])

create index(:photos, [:story_id])
create_if_not_exists index(:photos, [:story_id])

create index(:photo_flags, [:flag_id])
create_if_not_exists index(:photo_flags, [:flag_id])

create index(:photo_flags, [:user_id])
create_if_not_exists index(:photo_flags, [:user_id])

create index(:photo_flags, [:photo_id])
create_if_not_exists index(:photo_flags, [:photo_id])

create index(:optimized_photos, [:user_id])
create_if_not_exists index(:optimized_photos, [:user_id])

create index(:optimized_photos, [:photo_id])
create_if_not_exists index(:optimized_photos, [:photo_id])

create index(:geo_data_cities, [:zip_code])
create_if_not_exists index(:geo_data_cities, [:zip_code])

create index(:credits, [:user_id])
create_if_not_exists index(:credits, [:user_id])

create index(:credits, [:donor_id])
create_if_not_exists index(:credits, [:donor_id])
end

def down do
Expand Down
Loading