diff --git a/lib/sanbase/insight/post_image.ex b/lib/sanbase/insight/post_image.ex index 93148145aa..adc3fa7bb4 100644 --- a/lib/sanbase/insight/post_image.ex +++ b/lib/sanbase/insight/post_image.ex @@ -2,11 +2,13 @@ defmodule Sanbase.Insight.PostImage do use Ecto.Schema import Ecto.Changeset - alias Sanbase.Insight.Post alias __MODULE__ + alias Sanbase.Insight.Post + alias Sanbase.Accounts.User schema "post_images" do belongs_to(:post, Post) + belongs_to(:user, User) field(:file_name, :string) field(:image_url, :string) @@ -16,7 +18,7 @@ defmodule Sanbase.Insight.PostImage do def changeset(%PostImage{} = post_image, attrs \\ %{}) do post_image - |> cast(attrs, [:post_id, :file_name, :image_url, :content_hash, :hash_algorithm]) + |> cast(attrs, [:post_id, :user_id, :file_name, :image_url, :content_hash, :hash_algorithm]) |> validate_required([:image_url, :content_hash, :hash_algorithm]) |> update_change(:image_url, &String.downcase/1) |> unique_constraint(:image_url, name: :image_url_index) diff --git a/lib/sanbase_web/graphql/resolvers/file_resolver.ex b/lib/sanbase_web/graphql/resolvers/file_resolver.ex index 14ff82f41d..d8d6ba29d3 100644 --- a/lib/sanbase_web/graphql/resolvers/file_resolver.ex +++ b/lib/sanbase_web/graphql/resolvers/file_resolver.ex @@ -10,7 +10,7 @@ defmodule SanbaseWeb.Graphql.Resolvers.FileResolver do The files are first uploaded to an AWS S3 bucket and then then the image url, the content hash and used hash algorithm are stored in postgres. """ - def upload_image(_root, %{images: images}, _resolution) do + def upload_image(_root, %{images: images}, %{context: %{auth: %{current_user: current_user}}}) do # In S3 there are no folders so the file name just contains some random text # and a slash in it. Locally (in test and dev mode) the files are treated as if # they are located in a folder called `scope` @@ -21,7 +21,7 @@ defmodule SanbaseWeb.Graphql.Resolvers.FileResolver do # Prepend the timestamp in milliseconds to the name to avoid name collision # when uploading images with the same hash and name arg = %{arg | filename: milliseconds_str() <> "_" <> file_name} - save_image_content(arg) + save_image_content(arg, current_user.id) end) :ok = save_image_meta_data(image_data) @@ -31,7 +31,7 @@ defmodule SanbaseWeb.Graphql.Resolvers.FileResolver do # Helper functions - defp save_image_content(%Plug.Upload{filename: file_name} = arg) do + defp save_image_content(%Plug.Upload{filename: file_name} = arg, user_id) do with {:ok, content_hash} <- FileHash.calculate(arg.path), {:ok, file_name} <- FileStore.store({arg, content_hash}) do image_url = FileStore.url({file_name, content_hash}) @@ -40,7 +40,8 @@ defmodule SanbaseWeb.Graphql.Resolvers.FileResolver do file_name: file_name, image_url: image_url, content_hash: content_hash, - hash_algorithm: FileHash.algorithm() |> Atom.to_string() + hash_algorithm: FileHash.algorithm() |> Atom.to_string(), + user_id: user_id } else {:error, error} -> diff --git a/priv/repo/migrations/20250630112632_add_post_image_owner.exs b/priv/repo/migrations/20250630112632_add_post_image_owner.exs new file mode 100644 index 0000000000..be7662f739 --- /dev/null +++ b/priv/repo/migrations/20250630112632_add_post_image_owner.exs @@ -0,0 +1,9 @@ +defmodule Sanbase.Repo.Migrations.AddPostImageOwner do + use Ecto.Migration + + def change do + alter table(:post_images) do + add(:user_id, references(:users, on_delete: :nothing), null: true) + end + end +end diff --git a/priv/repo/structure.sql b/priv/repo/structure.sql index 03401b98b0..4ca97e6f7b 100644 --- a/priv/repo/structure.sql +++ b/priv/repo/structure.sql @@ -2659,7 +2659,8 @@ CREATE TABLE public.post_images ( image_url text NOT NULL, content_hash text NOT NULL, hash_algorithm text NOT NULL, - post_id bigint + post_id bigint, + user_id bigint ); @@ -9149,6 +9150,14 @@ ALTER TABLE ONLY public.post_images ADD CONSTRAINT post_images_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +-- +-- Name: post_images post_images_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_images + ADD CONSTRAINT post_images_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); + + -- -- Name: posts posts_chart_configuration_for_event_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -10393,3 +10402,4 @@ INSERT INTO public."schema_migrations" (version) VALUES (20250611104342); INSERT INTO public."schema_migrations" (version) VALUES (20250612090655); INSERT INTO public."schema_migrations" (version) VALUES (20250612131900); INSERT INTO public."schema_migrations" (version) VALUES (20250612133320); +INSERT INTO public."schema_migrations" (version) VALUES (20250630112632); diff --git a/test/sanbase_web/graphql/file_upload_test.exs b/test/sanbase_web/graphql/file_upload_test.exs index 96d56773b7..51be9ec9ae 100644 --- a/test/sanbase_web/graphql/file_upload_test.exs +++ b/test/sanbase_web/graphql/file_upload_test.exs @@ -66,8 +66,8 @@ defmodule SanbaseWeb.Graphql.FileUploadTest do mutation { uploadImage(images: ["img"]){ fileName - contentHash, - imageUrl, + contentHash + imageUrl error } }