diff --git a/apps/core/lib/core/schema/course.ex b/apps/core/lib/core/schema/course.ex index 4a68295..142cee8 100644 --- a/apps/core/lib/core/schema/course.ex +++ b/apps/core/lib/core/schema/course.ex @@ -26,6 +26,8 @@ defmodule GoEscuelaLms.Core.Schema.Course do def find(uuid) do Repo.get(Course, uuid) + |> Repo.preload(:topics) + |> Repo.preload(:enrollments) end def create(attrs \\ %{}) do diff --git a/apps/core/lib/core/schema/topic.ex b/apps/core/lib/core/schema/topic.ex index 53967d0..c42e03d 100644 --- a/apps/core/lib/core/schema/topic.ex +++ b/apps/core/lib/core/schema/topic.ex @@ -5,6 +5,8 @@ defmodule GoEscuelaLms.Core.Schema.Topic do use Ecto.Schema import Ecto.Changeset + alias __MODULE__ + alias GoEscuelaLms.Core.Repo, as: Repo alias GoEscuelaLms.Core.Schema.{Course, Activity} @primary_key {:uuid, Ecto.UUID, autogenerate: true} @@ -19,6 +21,12 @@ defmodule GoEscuelaLms.Core.Schema.Topic do timestamps() end + def create(attrs \\ %{}) do + %Topic{} + |> Topic.changeset(attrs) + |> Repo.insert() + end + def changeset(course, attrs) do course |> cast(attrs, [:name, :course_id]) diff --git a/apps/core/priv/repo/migrations/20231214203342_create_course_index_topics.exs b/apps/core/priv/repo/migrations/20231214203342_create_course_index_topics.exs new file mode 100644 index 0000000..cac589a --- /dev/null +++ b/apps/core/priv/repo/migrations/20231214203342_create_course_index_topics.exs @@ -0,0 +1,8 @@ +defmodule GoEscuelaLms.Core.Repo.Migrations.CreateCourseIndexTopics do + use Ecto.Migration + + def change do + drop index(:topics, [:course_id]) + create index(:topics, [:course_id]) + end +end diff --git a/apps/web/lib/web/auth/authorized_plug.ex b/apps/web/lib/web/auth/authorized_plug.ex index f5fea1d..bf25d12 100644 --- a/apps/web/lib/web/auth/authorized_plug.ex +++ b/apps/web/lib/web/auth/authorized_plug.ex @@ -5,15 +5,7 @@ defmodule Web.Auth.AuthorizedPlug do import Plug.Conn alias GoEscuelaLms.Core.Schema.User - # def is_authorized(%{params: %{"id" => id}} = conn, _opts) do - # if conn.assigns.account.uuid == id do - # conn - # else - # Web.FallbackController.call(conn, {:error, :forbidden}) |> halt() - # end - # end - - def is_admin_authorized(conn, _) do + def is_organizer_authorized(conn, _) do case conn.assigns.account |> User.organizer?() do true -> conn @@ -32,4 +24,14 @@ defmodule Web.Auth.AuthorizedPlug do Web.FallbackController.call(conn, {:error, :forbidden}) |> halt() end end + + def is_permit_authorized(conn, _) do + case conn.assigns.account |> User.instructor?() || conn.assigns.account |> User.organizer?() do + true -> + conn + + _ -> + Web.FallbackController.call(conn, {:error, :forbidden}) |> halt() + end + end end diff --git a/apps/web/lib/web/controllers/courses/courses_controller.ex b/apps/web/lib/web/controllers/courses/courses_controller.ex index 2299e68..58b5e2e 100644 --- a/apps/web/lib/web/controllers/courses/courses_controller.ex +++ b/apps/web/lib/web/controllers/courses/courses_controller.ex @@ -7,7 +7,7 @@ defmodule Web.Courses.CoursesController do alias GoEscuelaLms.Core.Schema.Course - plug :is_admin_authorized when action in [:create] + plug :is_organizer_authorized when action in [:create] @create_params %{ name: [type: :string, required: true], diff --git a/apps/web/lib/web/controllers/enrollments/enrollments_controller.ex b/apps/web/lib/web/controllers/enrollments/enrollments_controller.ex index fab78ad..52ad0c8 100644 --- a/apps/web/lib/web/controllers/enrollments/enrollments_controller.ex +++ b/apps/web/lib/web/controllers/enrollments/enrollments_controller.ex @@ -7,13 +7,14 @@ defmodule Web.Enrollments.EnrollmentsController do alias GoEscuelaLms.Core.Schema.{Course, Enrollment, User} - plug :is_admin_authorized when action in [:create] + plug :is_organizer_authorized when action in [:create] def create(conn, params) do user_id = params["users_id"] course_id = params["courses_id"] - with :ok <- valid_uuids(user_id, course_id), + with :ok <- valid_uuids(user_id), + :ok <- valid_uuids(course_id), :ok <- valid_resources(user_id, course_id), {:ok, enrollment} <- create_enrollment(user_id, course_id) do render(conn, :create, %{enrollment: enrollment}) @@ -27,11 +28,11 @@ defmodule Web.Enrollments.EnrollmentsController do }) end - defp valid_uuids(user_id, course_id) do - with {:ok, _} <- Ecto.UUID.dump(user_id), - {:ok, _} <- Ecto.UUID.dump(course_id) do - :ok - else + defp valid_uuids(id) do + case Ecto.UUID.dump(id) do + {:ok, _} -> + :ok + _ -> {:error, "invalid params"} end diff --git a/apps/web/lib/web/controllers/onboarding/institution_info_controlller.ex b/apps/web/lib/web/controllers/onboarding/institution_info_controlller.ex index 666a655..29e0ef9 100644 --- a/apps/web/lib/web/controllers/onboarding/institution_info_controlller.ex +++ b/apps/web/lib/web/controllers/onboarding/institution_info_controlller.ex @@ -7,7 +7,7 @@ defmodule Web.Onboarding.InstitutionInfoController do alias GoEscuelaLms.Core.Schema.InstitutionInfo - plug :is_admin_authorized when action in [:show] + plug :is_organizer_authorized when action in [:show] def show(conn, _params) do institution_info = InstitutionInfo.get!() diff --git a/apps/web/lib/web/controllers/topics/topics_controller.ex b/apps/web/lib/web/controllers/topics/topics_controller.ex new file mode 100644 index 0000000..54cc392 --- /dev/null +++ b/apps/web/lib/web/controllers/topics/topics_controller.ex @@ -0,0 +1,35 @@ +defmodule Web.Topics.TopicsController do + use Web, :controller + + action_fallback Web.FallbackController + + import Web.Auth.AuthorizedPlug + import Web.Plug.CheckRequest + + alias GoEscuelaLms.Core.Schema.Topic + + plug :is_permit_authorized when action in [:create] + plug :load_course when action in [:create] + plug :load_course when action in [:create] + plug :check_enrollment when action in [:create] + + @create_params %{ + name: [type: :string, required: true] + } + + def create(conn, params) do + course = conn.assigns.course + + with {:ok, valid_params} <- Tarams.cast(params, @create_params), + {:ok, topic} <- create_topic(course, valid_params) do + render(conn, :create, %{topic: topic}) + end + end + + defp create_topic(course, params) do + Topic.create(%{ + name: params |> get_in([:name]), + course_id: course.uuid + }) + end +end diff --git a/apps/web/lib/web/controllers/topics/topics_json.ex b/apps/web/lib/web/controllers/topics/topics_json.ex new file mode 100644 index 0000000..6ba496b --- /dev/null +++ b/apps/web/lib/web/controllers/topics/topics_json.ex @@ -0,0 +1,9 @@ +defmodule Web.Topics.TopicsJSON do + @doc """ + Renders topic + """ + + def create(%{topic: topic}) do + %{data: %{name: topic.name}} + end +end diff --git a/apps/web/lib/web/controllers/users/users_controller.ex b/apps/web/lib/web/controllers/users/users_controller.ex index 4624847..863c3ef 100644 --- a/apps/web/lib/web/controllers/users/users_controller.ex +++ b/apps/web/lib/web/controllers/users/users_controller.ex @@ -7,7 +7,7 @@ defmodule Web.Users.UsersController do alias GoEscuelaLms.Core.Schema.User - plug :is_admin_authorized when action in [:create] + plug :is_organizer_authorized when action in [:create] @create_params %{ full_name: [type: :string, required: true], diff --git a/apps/web/lib/web/plug/check_request.ex b/apps/web/lib/web/plug/check_request.ex new file mode 100644 index 0000000..7a3d640 --- /dev/null +++ b/apps/web/lib/web/plug/check_request.ex @@ -0,0 +1,48 @@ +defmodule Web.Plug.CheckRequest do + @moduledoc """ + This module plug check request and load resource + """ + import Plug.Conn + alias GoEscuelaLms.Core.Schema.{Course} + + def load_course(conn, _) do + course_id = conn.params["courses_id"] + + with :ok <- valid_uuids(course_id), + course <- Course.find(course_id), + false <- is_nil(course) do + assign(conn, :course, course) + else + _ -> + Web.FallbackController.call(conn, {:error, "invalid params"}) |> halt() + end + end + + defp valid_uuids(id) do + case Ecto.UUID.dump(id) do + {:ok, _} -> + :ok + + _ -> + {:error, "invalid params"} + end + end + + def check_enrollment(%{assigns: %{account: %{role: :organizer}}} = conn, _), do: conn + + def check_enrollment(conn, _) do + user_id = conn.assigns.account.uuid + course = conn.assigns.course + + case is_nil( + course.enrollments + |> Enum.find(fn enrollment -> enrollment.user_id == user_id end) + ) do + false -> + conn + + _ -> + Web.FallbackController.call(conn, {:error, :forbidden}) |> halt() + end + end +end diff --git a/apps/web/lib/web/router.ex b/apps/web/lib/web/router.ex index 652498d..647e7eb 100644 --- a/apps/web/lib/web/router.ex +++ b/apps/web/lib/web/router.ex @@ -31,7 +31,9 @@ defmodule Web.Router do end end - resources "/courses", Courses.CoursesController, only: [:create] + resources "/courses", Courses.CoursesController, only: [:create] do + resources "/topics", Topics.TopicsController, only: [:create] + end get "/profile", Users.ProfileController, :show get "/auth/sessions", Auth.SessionController, :refresh_session