diff --git a/lib/atomic/accounts.ex b/lib/atomic/accounts.ex
index 0fd35f28e..4ef52b75d 100644
--- a/lib/atomic/accounts.ex
+++ b/lib/atomic/accounts.ex
@@ -266,7 +266,9 @@ defmodule Atomic.Accounts do
"""
def get_user_by_session_token(token) do
{:ok, query} = UserToken.verify_session_token_query(token)
+
Repo.one(query)
+ |> Repo.preload(:organizations)
end
@doc """
@@ -424,4 +426,11 @@ defmodule Atomic.Accounts do
|> Course.changeset(attrs)
|> Repo.insert()
end
+
+ @doc """
+ Gets the user's organizations
+ """
+ def get_user_organizations(user) do
+ Repo.all(Ecto.assoc(user, :organizations))
+ end
end
diff --git a/lib/atomic/accounts/user.ex b/lib/atomic/accounts/user.ex
index b99913821..bce8add2c 100644
--- a/lib/atomic/accounts/user.ex
+++ b/lib/atomic/accounts/user.ex
@@ -10,7 +10,7 @@ defmodule Atomic.Accounts.User do
alias Atomic.Uploaders.ProfilePicture
@required_fields ~w(email password role name)a
- @optional_fields ~w(course_id)a
+ @optional_fields ~w(course_id default_organization_id)a
@roles ~w(admin student)a
@@ -20,6 +20,7 @@ defmodule Atomic.Accounts.User do
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime
+ belongs_to :default_organization, Organization
belongs_to :course, Course
field :profile_picture, ProfilePicture.Type
diff --git a/lib/atomic/activities.ex b/lib/atomic/activities.ex
index bc9dc1222..29295f958 100644
--- a/lib/atomic/activities.ex
+++ b/lib/atomic/activities.ex
@@ -22,6 +22,15 @@ defmodule Atomic.Activities do
|> Repo.all()
end
+ def list_activities_by_organization_id(organization_id, opts) do
+ Activity
+ |> apply_filters(opts)
+ |> join(:inner, [a], d in assoc(a, :departments))
+ |> where([a, d], d.organization_id == ^organization_id)
+ |> select([a, _d], a)
+ |> Repo.all()
+ end
+
@doc """
Gets a single activity.
@@ -41,6 +50,12 @@ defmodule Atomic.Activities do
|> Repo.preload(preloads)
end
+ def get_activity_organizations!(activity, _preloads \\ []) do
+ departments = Map.get(activity, :departments, [])
+
+ Enum.map(departments, & &1.organization_id)
+ end
+
alias Atomic.Activities.Enrollment
def is_participating?(activity_id, user_id) do
@@ -389,6 +404,19 @@ defmodule Atomic.Activities do
Repo.all(Speaker)
end
+ @doc """
+ Returns the list of speakers belonging to an organization.
+
+ ## Examples
+
+ iex> list_speakers_by_organization_id(99d7c9e5-4212-4f59-a097-28aaa33c2621)
+ [%Speaker{}, ...]
+
+ """
+ def list_speakers_by_organization_id(id) do
+ Repo.all(from s in Speaker, where: s.organization_id == ^id)
+ end
+
def get_speakers(nil), do: []
def get_speakers(ids) do
diff --git a/lib/atomic/activities/speaker.ex b/lib/atomic/activities/speaker.ex
index 20e9da4b9..3dba380c4 100644
--- a/lib/atomic/activities/speaker.ex
+++ b/lib/atomic/activities/speaker.ex
@@ -5,18 +5,25 @@ defmodule Atomic.Activities.Speaker do
use Atomic.Schema
alias Atomic.Activities.Activity
alias Atomic.Activities.ActivitySpeaker
+ alias Atomic.Organizations.Organization
+
+ @required_fields ~w(name bio organization_id)a
schema "speakers" do
field :bio, :string
field :name, :string
+
many_to_many :activities, Activity, join_through: ActivitySpeaker, on_replace: :delete
+
+ belongs_to :organization, Organization, on_replace: :delete_if_exists
+
timestamps()
end
@doc false
def changeset(speaker, attrs) do
speaker
- |> cast(attrs, [:name, :bio])
- |> validate_required([:name, :bio])
+ |> cast(attrs, @required_fields)
+ |> validate_required(@required_fields)
end
end
diff --git a/lib/atomic/departments.ex b/lib/atomic/departments.ex
index 74237c80c..024435cb4 100644
--- a/lib/atomic/departments.ex
+++ b/lib/atomic/departments.ex
@@ -21,6 +21,19 @@ defmodule Atomic.Departments do
Repo.all(Department)
end
+ @doc """
+ Returns the list of departments belonging to an organization.
+
+ ## Examples
+
+ iex> list_departments_by_organization_id(99d7c9e5-4212-4f59-a097-28aaa33c2621)
+ [%Department{}, ...]
+
+ """
+ def list_departments_by_organization_id(id) do
+ Repo.all(from d in Department, where: d.organization_id == ^id)
+ end
+
def get_departments(nil), do: []
def get_departments(ids) do
diff --git a/lib/atomic/organizations.ex b/lib/atomic/organizations.ex
index 26bb50761..a24c6b883 100644
--- a/lib/atomic/organizations.ex
+++ b/lib/atomic/organizations.ex
@@ -168,6 +168,15 @@ defmodule Atomic.Organizations do
|> Repo.exists?()
end
+ def get_role(user_id, organization_id) do
+ membership =
+ Membership
+ |> where([m], m.user_id == ^user_id and m.organization_id == ^organization_id)
+ |> Repo.one()
+
+ membership[:role]
+ end
+
@doc """
Gets a single membership.
@@ -247,12 +256,22 @@ defmodule Atomic.Organizations do
"""
def roles_less_than_or_equal(role) do
- case role do
- :follower -> []
- :member -> [:member]
- :admin -> [:member, :admin]
- :owner -> [:member, :admin, :owner]
- end
+ list = [:follower, :member, :admin, :owner]
+ Enum.drop_while(list, fn elem -> elem != role end)
+ end
+
+ @doc """
+ Returns all roles bigger or equal to the given role.
+
+ ## Examples
+
+ iex> roles_bigger_than_or_equal(:member)
+ [:member, :admin, :owner]
+
+ """
+ def roles_bigger_than_or_equal(role) do
+ list = [:follower, :member, :admin, :owner]
+ Enum.drop_while(list, fn elem -> elem != role end)
end
@doc """
diff --git a/lib/atomic/partnerships.ex b/lib/atomic/partnerships.ex
index 0f66f4738..0b9521db6 100644
--- a/lib/atomic/partnerships.ex
+++ b/lib/atomic/partnerships.ex
@@ -21,6 +21,19 @@ defmodule Atomic.Partnerships do
Repo.all(Partner)
end
+ @doc """
+ Returns the list of partnerships belonging to an organization.
+
+ ## Examples
+
+ iex> list_partnerships_by_organization_id(99d7c9e5-4212-4f59-a097-28aaa33c2621)
+ [%Partner{}, ...]
+
+ """
+ def list_partnerships_by_organization_id(id) do
+ Repo.all(from p in Partner, where: p.organization_id == ^id)
+ end
+
@doc """
Gets a single partner.
diff --git a/lib/atomic/partnerships/partner.ex b/lib/atomic/partnerships/partner.ex
index 4c5b8be49..e907f6858 100644
--- a/lib/atomic/partnerships/partner.ex
+++ b/lib/atomic/partnerships/partner.ex
@@ -7,7 +7,7 @@ defmodule Atomic.Partnerships.Partner do
alias Atomic.Organizations.Organization
alias Atomic.Uploaders
- @required_fields ~w(name description)a
+ @required_fields ~w(name description organization_id)a
@optional_fields []
diff --git a/lib/atomic_web/controllers/user_auth.ex b/lib/atomic_web/controllers/user_auth.ex
index 134b17634..acae72d8a 100644
--- a/lib/atomic_web/controllers/user_auth.ex
+++ b/lib/atomic_web/controllers/user_auth.ex
@@ -6,6 +6,7 @@ defmodule AtomicWeb.UserAuth do
import Phoenix.Controller
alias Atomic.Accounts
+ alias Atomic.Organizations
alias AtomicWeb.Router.Helpers, as: Routes
# Make the remember me cookie valid for 60 days.
@@ -31,12 +32,27 @@ defmodule AtomicWeb.UserAuth do
token = Accounts.generate_user_session_token(user)
user_return_to = get_session(conn, :user_return_to)
- conn
- |> renew_session()
- |> put_session(:user_token, token)
- |> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}")
- |> maybe_write_remember_me_cookie(token, params)
- |> redirect(to: user_return_to || signed_in_path(conn))
+ case user.default_organization_id do
+ nil ->
+ conn
+ |> renew_session()
+ |> put_session(:user_token, token)
+ |> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}")
+ |> maybe_write_remember_me_cookie(token, params)
+ |> redirect(to: user_return_to || signed_in_path(conn))
+
+ _ ->
+ conn
+ |> renew_session()
+ |> put_session(:user_token, token)
+ |> put_session(
+ :current_organization,
+ Organizations.get_organization!(user.default_organization_id)
+ )
+ |> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}")
+ |> maybe_write_remember_me_cookie(token, params)
+ |> redirect(to: user_return_to || signed_in_path(conn))
+ end
end
defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do
@@ -94,7 +110,9 @@ defmodule AtomicWeb.UserAuth do
def fetch_current_user(conn, _opts) do
{user_token, conn} = ensure_user_token(conn)
user = user_token && Accounts.get_user_by_session_token(user_token)
- assign(conn, :current_user, user)
+
+ conn
+ |> assign(:current_user, user)
end
defp ensure_user_token(conn) do
diff --git a/lib/atomic_web/exceptions.ex b/lib/atomic_web/exceptions.ex
new file mode 100644
index 000000000..f5d0f032b
--- /dev/null
+++ b/lib/atomic_web/exceptions.ex
@@ -0,0 +1,4 @@
+defmodule AtomicWeb.MismatchError do
+ defexception message: "The provided parameters have no relation in the database.",
+ plug_status: 404
+end
diff --git a/lib/atomic_web/live/activity_live/edit.ex b/lib/atomic_web/live/activity_live/edit.ex
index 8f63b4003..3d99ded7b 100644
--- a/lib/atomic_web/live/activity_live/edit.ex
+++ b/lib/atomic_web/live/activity_live/edit.ex
@@ -10,13 +10,19 @@ defmodule AtomicWeb.ActivityLive.Edit do
end
@impl true
- def handle_params(%{"id" => id} = _params, _url, socket) do
- {:noreply,
- socket
- |> assign(:page_title, gettext("Edit Activity"))
- |> assign(
- :activity,
- Activities.get_activity!(id, [:activity_sessions, :speakers, :departments])
- )}
+ def handle_params(%{"organization_id" => organization_id, "id" => id} = _params, _url, socket) do
+ activity =
+ Activities.get_activity!(id, preloads: [:activity_sessions, :departments, :speakers])
+
+ organizations = Activities.get_activity_organizations!(activity)
+
+ if organization_id in organizations do
+ {:noreply,
+ socket
+ |> assign(:page_title, gettext("Edit Activity"))
+ |> assign(:activity, activity)}
+ else
+ raise AtomicWeb.MismatchError
+ end
end
end
diff --git a/lib/atomic_web/live/activity_live/edit.html.heex b/lib/atomic_web/live/activity_live/edit.html.heex
index 76dc631a2..598333bc2 100644
--- a/lib/atomic_web/live/activity_live/edit.html.heex
+++ b/lib/atomic_web/live/activity_live/edit.html.heex
@@ -1,3 +1,3 @@
- <.live_component module={AtomicWeb.ActivityLive.FormComponent} id={@activity.id} title={@page_title} action={@live_action} activity={@activity} return_to={Routes.activity_show_path(@socket, :show, @activity)} />
+ <.live_component module={AtomicWeb.ActivityLive.FormComponent} id={@activity.id} organization={@current_organization} title={@page_title} action={@live_action} activity={@activity} return_to={Routes.activity_show_path(@socket, :show, @current_organization, @activity)} />
diff --git a/lib/atomic_web/live/activity_live/form_component.ex b/lib/atomic_web/live/activity_live/form_component.ex
index 2c246194b..a237b7d20 100644
--- a/lib/atomic_web/live/activity_live/form_component.ex
+++ b/lib/atomic_web/live/activity_live/form_component.ex
@@ -7,25 +7,35 @@ defmodule AtomicWeb.ActivityLive.FormComponent do
@impl true
def mount(socket) do
- departments = Departments.list_departments()
- speakers = Activities.list_speakers()
-
{:ok,
socket
- |> assign(:departments, departments)
- |> assign(:speakers, speakers)}
+ |> assign(:departments, [])
+ |> assign(:speakers, [])}
end
@impl true
def update(%{activity: activity} = assigns, socket) do
+ departments = Departments.list_departments_by_organization_id(assigns.organization.id)
+ speakers = Activities.list_speakers_by_organization_id(assigns.organization.id)
changeset = Activities.change_activity(activity)
{:ok,
socket
|> assign(assigns)
+ |> assign(:departments, departments)
+ |> assign(:speakers, speakers)
|> assign(:changeset, changeset)}
end
+ @impl true
+ def update(%{"organization_id" => organization_id}, socket) do
+ departments = Departments.list_departments_by_organization_id(organization_id)
+
+ {:ok,
+ socket
+ |> assign(:departments, departments)}
+ end
+
@impl true
def handle_event("validate", %{"activity" => activity_params}, socket) do
changeset =
diff --git a/lib/atomic_web/live/activity_live/index.ex b/lib/atomic_web/live/activity_live/index.ex
index 3dcf0321e..341a2abb9 100644
--- a/lib/atomic_web/live/activity_live/index.ex
+++ b/lib/atomic_web/live/activity_live/index.ex
@@ -5,8 +5,8 @@ defmodule AtomicWeb.ActivityLive.Index do
alias Atomic.Activities.Activity
@impl true
- def mount(_params, _session, socket) do
- {:ok, assign(socket, :activities, list_activities())}
+ def mount(params, _session, socket) do
+ {:ok, assign(socket, :activities, list_activities(params["organization_id"]))}
end
@impl true
@@ -37,10 +37,10 @@ defmodule AtomicWeb.ActivityLive.Index do
activity = Activities.get_activity!(id)
{:ok, _} = Activities.delete_activity(activity)
- {:noreply, assign(socket, :activies, list_activities())}
+ {:noreply, assign(socket, :activies, list_activities(socket.assigns.current_organization.id))}
end
- defp list_activities do
- Activities.list_activities(preloads: [:activity_sessions])
+ defp list_activities(organization_id) do
+ Activities.list_activities_by_organization_id(organization_id, preloads: [:activity_sessions])
end
end
diff --git a/lib/atomic_web/live/activity_live/index.html.heex b/lib/atomic_web/live/activity_live/index.html.heex
index 2b959a11f..6cdc03b3f 100644
--- a/lib/atomic_web/live/activity_live/index.html.heex
+++ b/lib/atomic_web/live/activity_live/index.html.heex
@@ -22,11 +22,11 @@
- <.live_component module={AtomicWeb.ActivityLive.FormComponent} id={:new} title={@page_title} action={@live_action} activity={@activity} return_to={Routes.activity_index_path(@socket, :index)} />
+ <.live_component module={AtomicWeb.ActivityLive.FormComponent} id={:new} organization={@current_organization} title={@page_title} action={@live_action} activity={@activity} return_to={Routes.activity_index_path(@socket, :index, @current_organization)} />
diff --git a/lib/atomic_web/live/activity_live/show.ex b/lib/atomic_web/live/activity_live/show.ex
index 7f2b21ccc..78b6ca9e5 100644
--- a/lib/atomic_web/live/activity_live/show.ex
+++ b/lib/atomic_web/live/activity_live/show.ex
@@ -14,14 +14,19 @@ defmodule AtomicWeb.ActivityLive.Show do
end
@impl true
- def handle_params(%{"id" => id}, _, socket) do
+ def handle_params(%{"organization_id" => organization_id, "id" => id}, _, socket) do
activity = Activities.get_activity!(id, [:activity_sessions, :departments, :speakers])
+ organizations = Activities.get_activity_organizations!(activity)
- {:noreply,
- socket
- |> assign(:enrolled?, Activities.is_user_enrolled?(activity, socket.assigns.current_user))
- |> assign(:page_title, page_title(socket.assigns.live_action))
- |> assign(:activity, %{activity | enrolled: Activities.get_total_enrolled(activity)})}
+ if organization_id in organizations do
+ {:noreply,
+ socket
+ |> assign(:enrolled?, Activities.is_user_enrolled?(activity, socket.assigns.current_user))
+ |> assign(:page_title, page_title(socket.assigns.live_action))
+ |> assign(:activity, %{activity | enrolled: Activities.get_total_enrolled(activity)})}
+ else
+ raise AtomicWeb.MismatchError
+ end
end
@impl true
@@ -68,7 +73,10 @@ defmodule AtomicWeb.ActivityLive.Show do
def handle_event("delete", _payload, socket) do
{:ok, _} = Activities.delete_activity(socket.assigns.activity)
- {:noreply, push_redirect(socket, to: Routes.activity_index_path(socket, :index))}
+ {:noreply,
+ push_redirect(socket,
+ to: Routes.activity_index_path(socket, :index, socket.assigns.current_organization)
+ )}
end
@impl true
diff --git a/lib/atomic_web/live/activity_live/show.html.heex b/lib/atomic_web/live/activity_live/show.html.heex
index bef7e0824..2648b0ff8 100644
--- a/lib/atomic_web/live/activity_live/show.html.heex
+++ b/lib/atomic_web/live/activity_live/show.html.heex
@@ -1,8 +1,8 @@
+
Save
<% end %>
diff --git a/lib/atomic_web/live/partner_live/index.ex b/lib/atomic_web/live/partner_live/index.ex
index 01b517731..b1937ef67 100644
--- a/lib/atomic_web/live/partner_live/index.ex
+++ b/lib/atomic_web/live/partner_live/index.ex
@@ -5,8 +5,8 @@ defmodule AtomicWeb.PartnerLive.Index do
alias Atomic.Partnerships.Partner
@impl true
- def mount(_params, _session, socket) do
- {:ok, assign(socket, :partnerships, list_partnerships())}
+ def mount(%{"organization_id" => organization_id}, _session, socket) do
+ {:ok, assign(socket, :partnerships, list_partnerships(organization_id))}
end
@impl true
@@ -14,10 +14,16 @@ defmodule AtomicWeb.PartnerLive.Index do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
- defp apply_action(socket, :edit, %{"id" => id}) do
- socket
- |> assign(:page_title, "Edit Partner")
- |> assign(:partner, Partnerships.get_partner!(id))
+ defp apply_action(socket, :edit, %{"organization_id" => organization_id, "id" => id}) do
+ partner = Partnerships.get_partner!(id)
+
+ if partner.organization_id == organization_id do
+ socket
+ |> assign(:page_title, "Edit Partner")
+ |> assign(:partner, Partnerships.get_partner!(id))
+ else
+ raise AtomicWeb.MismatchError
+ end
end
defp apply_action(socket, :new, _params) do
@@ -37,10 +43,11 @@ defmodule AtomicWeb.PartnerLive.Index do
partner = Partnerships.get_partner!(id)
{:ok, _} = Partnerships.delete_partner(partner)
- {:noreply, assign(socket, :partnerships, list_partnerships())}
+ {:noreply,
+ assign(socket, :partnerships, list_partnerships(socket.assigns.current_organization.id))}
end
- defp list_partnerships do
- Partnerships.list_partnerships()
+ defp list_partnerships(id) do
+ Partnerships.list_partnerships_by_organization_id(id)
end
end
diff --git a/lib/atomic_web/live/partner_live/index.html.heex b/lib/atomic_web/live/partner_live/index.html.heex
index 7ab2cf743..7f892ded7 100644
--- a/lib/atomic_web/live/partner_live/index.html.heex
+++ b/lib/atomic_web/live/partner_live/index.html.heex
@@ -1,8 +1,8 @@
Listing Partnerships
<%= if @live_action in [:new, :edit] do %>
- <.modal return_to={Routes.partner_index_path(@socket, :index)}>
- <.live_component module={AtomicWeb.PartnerLive.FormComponent} id={@partner.id || :new} title={@page_title} action={@live_action} partner={@partner} return_to={Routes.partner_index_path(@socket, :index)} />
+ <.modal return_to={Routes.partner_index_path(@socket, :index, @current_organization)}>
+ <.live_component module={AtomicWeb.PartnerLive.FormComponent} id={@partner.id || :new} organization={@current_organization} title={@page_title} action={@live_action} partner={@partner} return_to={Routes.partner_index_path(@socket, :index, @current_organization)} />
<% end %>
@@ -22,8 +22,8 @@
<%= partner.description %> |
- <%= live_redirect("Show", to: Routes.partner_show_path(@socket, :show, partner)) %>
- <%= live_patch("Edit", to: Routes.partner_index_path(@socket, :edit, partner)) %>
+ <%= live_redirect("Show", to: Routes.partner_show_path(@socket, :show, @current_organization, partner)) %>
+ <%= live_patch("Edit", to: Routes.partner_index_path(@socket, :edit, @current_organization, partner)) %>
<%= link("Delete", to: "#", phx_click: "delete", phx_value_id: partner.id, data: [confirm: "Are you sure?"]) %>
|
@@ -31,4 +31,4 @@
-
<%= live_patch("New Partner", to: Routes.partner_index_path(@socket, :new)) %>
+
<%= live_patch("New Partner", to: Routes.partner_index_path(@socket, :new, @current_organization)) %>
diff --git a/lib/atomic_web/live/partner_live/show.ex b/lib/atomic_web/live/partner_live/show.ex
index 182ad97b5..b8a4701f9 100644
--- a/lib/atomic_web/live/partner_live/show.ex
+++ b/lib/atomic_web/live/partner_live/show.ex
@@ -10,11 +10,17 @@ defmodule AtomicWeb.PartnerLive.Show do
end
@impl true
- def handle_params(%{"id" => id}, _, socket) do
- {:noreply,
- socket
- |> assign(:page_title, page_title(socket.assigns.live_action))
- |> assign(:partner, Partnerships.get_partner!(id))}
+ def handle_params(%{"organization_id" => organization_id, "id" => id}, _, socket) do
+ partner = Partnerships.get_partner!(id)
+
+ if partner.organization_id == organization_id do
+ {:noreply,
+ socket
+ |> assign(:page_title, page_title(socket.assigns.live_action))
+ |> assign(:partner, partner)}
+ else
+ raise AtomicWeb.MismatchError
+ end
end
defp page_title(:show), do: "Show Partner"
diff --git a/lib/atomic_web/live/partner_live/show.html.heex b/lib/atomic_web/live/partner_live/show.html.heex
index 4f5f51268..daff0ce2e 100644
--- a/lib/atomic_web/live/partner_live/show.html.heex
+++ b/lib/atomic_web/live/partner_live/show.html.heex
@@ -1,8 +1,8 @@
Show Partner
<%= if @live_action in [:edit] do %>
- <.modal return_to={Routes.partner_show_path(@socket, :show, @partner)}>
- <.live_component module={AtomicWeb.PartnerLive.FormComponent} id={@partner.id} title={@page_title} action={@live_action} partner={@partner} return_to={Routes.partner_show_path(@socket, :show, @partner)} />
+ <.modal return_to={Routes.partner_show_path(@socket, :show, @current_organization, @partner)}>
+ <.live_component module={AtomicWeb.PartnerLive.FormComponent} id={@partner.id} title={@page_title} action={@live_action} partner={@partner} return_to={Routes.partner_show_path(@socket, :show, @current_organization, @partner)} />
<% end %>
@@ -24,5 +24,5 @@
<% end %>
-
<%= live_patch("Edit", to: Routes.partner_show_path(@socket, :edit, @partner), class: "button") %> |
-
<%= live_redirect("Back", to: Routes.partner_index_path(@socket, :index)) %>
+
<%= live_patch("Edit", to: Routes.partner_show_path(@socket, :edit, @current_organization, @partner), class: "button") %> |
+
<%= live_redirect("Back", to: Routes.partner_index_path(@socket, :index, @current_organization)) %>
diff --git a/lib/atomic_web/live/speaker_live/form_component.ex b/lib/atomic_web/live/speaker_live/form_component.ex
index ef8bdeab0..144e7a59d 100644
--- a/lib/atomic_web/live/speaker_live/form_component.ex
+++ b/lib/atomic_web/live/speaker_live/form_component.ex
@@ -41,6 +41,8 @@ defmodule AtomicWeb.SpeakerLive.FormComponent do
end
defp save_speaker(socket, :new, speaker_params) do
+ speaker_params = Map.put(speaker_params, "organization_id", socket.assigns.organization.id)
+
case Activities.create_speaker(speaker_params) do
{:ok, _speaker} ->
{:noreply,
diff --git a/lib/atomic_web/live/speaker_live/index.ex b/lib/atomic_web/live/speaker_live/index.ex
index 2157c7bfe..d161ad039 100644
--- a/lib/atomic_web/live/speaker_live/index.ex
+++ b/lib/atomic_web/live/speaker_live/index.ex
@@ -5,8 +5,8 @@ defmodule AtomicWeb.SpeakerLive.Index do
alias Atomic.Activities.Speaker
@impl true
- def mount(_params, _session, socket) do
- {:ok, assign(socket, :speakers, list_speakers())}
+ def mount(%{"organization_id" => organization_id}, _session, socket) do
+ {:ok, assign(socket, :speakers, list_speakers(organization_id))}
end
@impl true
@@ -14,10 +14,16 @@ defmodule AtomicWeb.SpeakerLive.Index do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
- defp apply_action(socket, :edit, %{"id" => id}) do
- socket
- |> assign(:page_title, "Edit Speaker")
- |> assign(:speaker, Activities.get_speaker!(id))
+ defp apply_action(socket, :edit, %{"organization_id" => organization_id, "id" => id}) do
+ speaker = Activities.get_speaker!(id)
+
+ if speaker.organization_id == organization_id do
+ socket
+ |> assign(:page_title, "Edit Speaker")
+ |> assign(:speaker, speaker)
+ else
+ raise AtomicWeb.MismatchError
+ end
end
defp apply_action(socket, :new, _params) do
@@ -37,10 +43,10 @@ defmodule AtomicWeb.SpeakerLive.Index do
speaker = Activities.get_speaker!(id)
{:ok, _} = Activities.delete_speaker(speaker)
- {:noreply, assign(socket, :speakers, list_speakers())}
+ {:noreply, assign(socket, :speakers, list_speakers(socket.assigns.current_organization.id))}
end
- defp list_speakers do
- Activities.list_speakers()
+ defp list_speakers(organization_id) do
+ Activities.list_speakers_by_organization_id(organization_id)
end
end
diff --git a/lib/atomic_web/live/speaker_live/index.html.heex b/lib/atomic_web/live/speaker_live/index.html.heex
index 17ffbc9c9..ed87b8f1b 100644
--- a/lib/atomic_web/live/speaker_live/index.html.heex
+++ b/lib/atomic_web/live/speaker_live/index.html.heex
@@ -1,8 +1,8 @@
Listing Speakers
<%= if @live_action in [:new, :edit] do %>
- <.modal return_to={Routes.speaker_index_path(@socket, :index)}>
- <.live_component module={AtomicWeb.SpeakerLive.FormComponent} id={@speaker.id || :new} title={@page_title} action={@live_action} speaker={@speaker} return_to={Routes.speaker_index_path(@socket, :index)} />
+ <.modal return_to={Routes.speaker_index_path(@socket, :index, @current_organization)}>
+ <.live_component module={AtomicWeb.SpeakerLive.FormComponent} id={@speaker.id || :new} organization={@current_organization} title={@page_title} action={@live_action} speaker={@speaker} return_to={Routes.speaker_index_path(@socket, :index, @current_organization)} />
<% end %>
@@ -22,8 +22,8 @@
<%= speaker.bio %> |
- <%= live_redirect("Show", to: Routes.speaker_show_path(@socket, :show, speaker)) %>
- <%= live_patch("Edit", to: Routes.speaker_index_path(@socket, :edit, speaker)) %>
+ <%= live_redirect("Show", to: Routes.speaker_show_path(@socket, :show, @current_organization, speaker)) %>
+ <%= live_patch("Edit", to: Routes.speaker_index_path(@socket, :edit, @current_organization, speaker)) %>
<%= link("Delete", to: "#", phx_click: "delete", phx_value_id: speaker.id, data: [confirm: "Are you sure?"]) %>
|
@@ -31,4 +31,4 @@
-
<%= live_patch("New Speaker", to: Routes.speaker_index_path(@socket, :new)) %>
+
<%= live_patch("New Speaker", to: Routes.speaker_index_path(@socket, :new, @current_organization)) %>
diff --git a/lib/atomic_web/live/speaker_live/show.ex b/lib/atomic_web/live/speaker_live/show.ex
index c134819c2..167bb5ded 100644
--- a/lib/atomic_web/live/speaker_live/show.ex
+++ b/lib/atomic_web/live/speaker_live/show.ex
@@ -9,11 +9,17 @@ defmodule AtomicWeb.SpeakerLive.Show do
end
@impl true
- def handle_params(%{"id" => id}, _, socket) do
- {:noreply,
- socket
- |> assign(:page_title, page_title(socket.assigns.live_action))
- |> assign(:speaker, Activities.get_speaker!(id))}
+ def handle_params(%{"organization_id" => organization_id, "id" => id}, _, socket) do
+ speaker = Activities.get_speaker!(id)
+
+ if speaker.organization_id == organization_id do
+ {:noreply,
+ socket
+ |> assign(:page_title, page_title(socket.assigns.live_action))
+ |> assign(:speaker, speaker)}
+ else
+ raise AtomicWeb.MismatchError
+ end
end
defp page_title(:show), do: "Show Speaker"
diff --git a/lib/atomic_web/live/speaker_live/show.html.heex b/lib/atomic_web/live/speaker_live/show.html.heex
index 73999d02c..b108acb76 100644
--- a/lib/atomic_web/live/speaker_live/show.html.heex
+++ b/lib/atomic_web/live/speaker_live/show.html.heex
@@ -1,8 +1,8 @@
Show Speaker
<%= if @live_action in [:edit] do %>
- <.modal return_to={Routes.speaker_show_path(@socket, :show, @speaker)}>
- <.live_component module={AtomicWeb.SpeakerLive.FormComponent} id={@speaker.id} title={@page_title} action={@live_action} speaker={@speaker} return_to={Routes.speaker_show_path(@socket, :show, @speaker)} />
+ <.modal return_to={Routes.speaker_show_path(@socket, :show, @current_organization, @speaker)}>
+ <.live_component module={AtomicWeb.SpeakerLive.FormComponent} id={@speaker.id} organization={@current_organization} title={@page_title} action={@live_action} speaker={@speaker} return_to={Routes.speaker_show_path(@socket, :show, @current_organization, @speaker)} />
<% end %>
@@ -18,5 +18,5 @@
-
<%= live_patch("Edit", to: Routes.speaker_show_path(@socket, :edit, @speaker), class: "button") %> |
-
<%= live_redirect("Back", to: Routes.speaker_index_path(@socket, :index)) %>
+
<%= live_patch("Edit", to: Routes.speaker_show_path(@socket, :edit, @current_organization, @speaker), class: "button") %> |
+
<%= live_redirect("Back", to: Routes.speaker_index_path(@socket, :index, @current_organization)) %>
diff --git a/lib/atomic_web/live/user_live/edit.html.heex b/lib/atomic_web/live/user_live/edit.html.heex
index dffb93cee..4896ca8b5 100644
--- a/lib/atomic_web/live/user_live/edit.html.heex
+++ b/lib/atomic_web/live/user_live/edit.html.heex
@@ -1 +1 @@
-<.live_component module={AtomicWeb.UserLive.FormComponent} user={@user} id={@current_user.id} courses={@courses} title={@page_title} action={@live_action} return_to={Routes.activity_index_path(@socket, :index)} />
+<.live_component module={AtomicWeb.UserLive.FormComponent} user={@user} id={@current_user.id} courses={@courses} title={@page_title} action={@live_action} return_to={Routes.home_index_path(@conn, :index)} />
diff --git a/lib/atomic_web/plugs/authorize.ex b/lib/atomic_web/plugs/authorize.ex
new file mode 100644
index 000000000..133332837
--- /dev/null
+++ b/lib/atomic_web/plugs/authorize.ex
@@ -0,0 +1,47 @@
+defmodule AtomicWeb.Plugs.Authorize do
+ @moduledoc false
+ import Plug.Conn
+ import Atomic.Organizations
+
+ def init(opts), do: opts
+
+ def call(conn, minimum_authorized_role) do
+ if authorized?(conn, minimum_authorized_role) do
+ conn
+ else
+ conn
+ |> send_resp(:not_found, "")
+ |> halt()
+ end
+ end
+
+ defp authorized?(conn, minimum_authorized_role) do
+ organization_id = get_organization_id(conn)
+
+ case {organization_id, conn.assigns.current_user} do
+ {nil, _} ->
+ false
+
+ {id, user} ->
+ user_authorized?(user, id, minimum_authorized_role)
+ end
+ end
+
+ defp get_organization_id(conn) do
+ case conn.params["organization_id"] do
+ organization_id when is_binary(organization_id) ->
+ organization_id
+
+ _ ->
+ nil
+ end
+ end
+
+ defp user_authorized?(user, organization_id, minimum_authorized_role) do
+ user_organizations = Enum.map(user.organizations, & &1.id)
+ role = get_role(user.id, organization_id)
+ allowed_roles = roles_bigger_than_or_equal(minimum_authorized_role)
+
+ organization_id in user_organizations && role in allowed_roles
+ end
+end
diff --git a/lib/atomic_web/router.ex b/lib/atomic_web/router.ex
index 5313a2eb0..7760747cc 100644
--- a/lib/atomic_web/router.ex
+++ b/lib/atomic_web/router.ex
@@ -17,64 +17,91 @@ defmodule AtomicWeb.Router do
plug :accepts, ["json"]
end
+ pipeline :admin do
+ plug AtomicWeb.Plugs.Authorize, :admin
+ end
+
+ pipeline :member do
+ plug AtomicWeb.Plugs.Authorize, :member
+ end
+
+ pipeline :follower do
+ plug AtomicWeb.Plugs.Authorize, :follower
+ end
+
scope "/", AtomicWeb do
pipe_through :browser
- live "/", ActivityLive.Index, :index
+ live_session :general, on_mount: [{AtomicWeb.Hooks, :general_user_state}] do
+ live "/", HomeLive.Index, :index
+
+ live "/organizations", OrganizationLive.Index, :index
+
+ scope "/organizations/:organization_id" do
+ live "/board/", BoardLive.Index, :index
+ live "/board/:id", BoardLive.Show, :show
+ end
+ end
end
scope "/", AtomicWeb do
pipe_through [:browser, :require_authenticated_user]
- live_session :logged_in, on_mount: [{AtomicWeb.Hooks, :current_user}] do
+ live_session :logged_in, on_mount: [{AtomicWeb.Hooks, :authenticated_user_state}] do
live "/scanner", ScannerLive.Index, :index
- live "/activities", ActivityLive.Index, :index
- live "/activities/new", ActivityLive.New, :new
- live "/activities/:id/edit", ActivityLive.Edit, :edit
- live "/activities/:id", ActivityLive.Show, :show
-
- live "/departments/:org", DepartmentLive.Index, :index
- live "/departments/:org/new", DepartmentLive.Index, :new
- live "/departments/:org/:id/edit", DepartmentLive.Index, :edit
- live "/departments/:org/:id", DepartmentLive.Show, :show
- live "/departments/:org/:id/show/edit", DepartmentLive.Show, :edit
-
- live "/partners", PartnerLive.Index, :index
- live "/partners/new", PartnerLive.Index, :new
- live "/partners/:id/edit", PartnerLive.Index, :edit
- live "/partners/:id", PartnerLive.Show, :show
- live "/partners/:id/show/edit", PartnerLive.Show, :edit
-
- live "/speakers", SpeakerLive.Index, :index
- live "/speakers/new", SpeakerLive.Index, :new
- live "/speakers/:id/edit", SpeakerLive.Index, :edit
- live "/speakers/:id", SpeakerLive.Show, :show
- live "/speakers/:id/show/edit", SpeakerLive.Show, :edit
+ scope "/organizations/:organization_id" do
+ live "/", OrganizationLive.Show, :show
- live "/organizations", OrganizationLive.Index, :index
- live "/organizations/new", OrganizationLive.Index, :new
- live "/organizations/:id/edit", OrganizationLive.Index, :edit
- live "/organizations/:id", OrganizationLive.Show, :show
- live "/organizations/:id/show/edit", OrganizationLive.Show, :edit
+ pipe_through :admin
+ live "/edit", OrganizationLive.Index, :edit
+ live "/show/edit", OrganizationLive.Show, :edit
- live "/membership/:org", MembershipLive.Index, :index
- live "/membership/:org/new", MembershipLive.New, :new
- live "/membership/:org/:id", MembershipLive.Show, :show
- live "/membership/:org/:id/edit", MembershipLive.Edit, :edit
+ live "/activities/new", ActivityLive.New, :new
+ live "/activities/:id/edit", ActivityLive.Edit, :edit
- live "/card/:membership_id", CardLive.Show, :show
+ live "/departments/new", DepartmentLive.Index, :new
+ live "/departments/:id/edit", DepartmentLive.Index, :edit
+ live "/departments/:id/show/edit", DepartmentLive.Show, :edit
+
+ live "/partners/new", PartnerLive.Index, :new
+ live "/partners/:id/edit", PartnerLive.Index, :edit
+ live "/partners/:id/show/edit", PartnerLive.Show, :edit
+
+ live "/speakers/new", SpeakerLive.Index, :new
+ live "/speakers/:id/edit", SpeakerLive.Index, :edit
+ live "/speakers/:id/show/edit", SpeakerLive.Show, :edit
+
+ live "/board/new", BoardLive.New, :new
+ live "/board/:id/edit", BoardLive.Edit, :edit
+
+ live "/memberships", MembershipLive.Index, :index
+ live "/memberships/new", MembershipLive.New, :new
+ live "/memberships/:id", MembershipLive.Show, :show
+ live "/memberships/:id/edit", MembershipLive.Edit, :edit
+ end
+
+ scope "/organizations/:organization_id" do
+ pipe_through :follower
+ live "/activities", ActivityLive.Index, :index
+ live "/activities/:id", ActivityLive.Show, :show
- live "/board/:org", BoardLive.Index, :index
- live "/board/:org/new", BoardLive.New, :new
- live "/board/:org/:id", BoardLive.Show, :show
- live "/board/:org/:id/edit", BoardLive.Edit, :edit
- live "/memberships/:org", MembershipLive.Index, :index
- live "/memberships/:org/new", MembershipLive.New, :new
- live "/memberships/:org/:id", MembershipLive.Show, :show
- live "/memberships/:org/:id/edit", MembershipLive.Edit, :edit
+ live "/departments", DepartmentLive.Index, :index
+ live "/departments/:id", DepartmentLive.Show, :show
+
+ live "/partners", PartnerLive.Index, :index
+ live "/partners/:id", PartnerLive.Show, :show
+
+ live "/speakers", SpeakerLive.Index, :index
+ live "/speakers/:id", SpeakerLive.Show, :show
+ end
+
+ live "/organizations/new", OrganizationLive.Index, :new
live "/user/edit", UserLive.Edit, :edit
+
+ pipe_through :member
+ live "/card/:membership_id", CardLive.Show, :show
end
end
diff --git a/lib/atomic_web/templates/layout/root.html.heex b/lib/atomic_web/templates/layout/root.html.heex
index c03c73b66..494fe0a67 100644
--- a/lib/atomic_web/templates/layout/root.html.heex
+++ b/lib/atomic_web/templates/layout/root.html.heex
@@ -15,11 +15,19 @@
diff --git a/priv/repo/migrations/2022000000000_create_organizations.exs b/priv/repo/migrations/2022000000000_create_organizations.exs
index 5f3d4de0e..43c8bf23e 100644
--- a/priv/repo/migrations/2022000000000_create_organizations.exs
+++ b/priv/repo/migrations/2022000000000_create_organizations.exs
@@ -6,6 +6,7 @@ defmodule Atomic.Repo.Migrations.CreateOrganizations do
add :id, :binary_id, primary_key: true
add :name, :string, null: false
add :description, :text, null: false
+ add :organization_id, references(:organizations, type: :binary_id)
add :location, :map
timestamps()
diff --git a/priv/repo/migrations/20221014155230_create_users_auth_tables.exs b/priv/repo/migrations/20221014155230_create_users_auth_tables.exs
index 4e7eeb3f4..8b1353678 100644
--- a/priv/repo/migrations/20221014155230_create_users_auth_tables.exs
+++ b/priv/repo/migrations/20221014155230_create_users_auth_tables.exs
@@ -9,6 +9,10 @@ defmodule Atomic.Repo.Migrations.CreateUsersAuthTables do
add :email, :citext, null: false
add :hashed_password, :string, null: false
add :confirmed_at, :naive_datetime
+
+ add :default_organization_id,
+ references(:organizations, type: :binary_id, on_delete: :delete_all)
+
add :role, :string, null: false
timestamps()
end
diff --git a/priv/repo/migrations/20221129000955_create_speakers.exs b/priv/repo/migrations/20221129000955_create_speakers.exs
index 651bd875f..7a35092c8 100644
--- a/priv/repo/migrations/20221129000955_create_speakers.exs
+++ b/priv/repo/migrations/20221129000955_create_speakers.exs
@@ -7,6 +7,7 @@ defmodule Atomic.Repo.Migrations.CreateSpeakers do
add :name, :string
add :bio, :text
+ add :organization_id, references(:organizations, on_delete: :delete_all, type: :binary_id)
timestamps()
end
end
diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs
index 41a3d7fed..60f8ef497 100644
--- a/priv/repo/seeds.exs
+++ b/priv/repo/seeds.exs
@@ -7,11 +7,12 @@ defmodule Atomic.Repo.Seeds do
def run do
[
+ "organizations.exs",
"courses.exs",
"accounts.exs",
- "organizations.exs",
"departments.exs",
- "activities.exs"
+ "activities.exs",
+ "memberships.exs"
]
|> Enum.each(fn file ->
Code.require_file("#{@seeds_dir}/#{file}")
diff --git a/priv/repo/seeds/accounts.exs b/priv/repo/seeds/accounts.exs
index 58a9c04f1..544f0679c 100644
--- a/priv/repo/seeds/accounts.exs
+++ b/priv/repo/seeds/accounts.exs
@@ -2,6 +2,7 @@ defmodule Atomic.Repo.Seeds.Accounts do
alias Atomic.Accounts
alias Atomic.Accounts.{Course, User}
alias Atomic.Repo
+ alias Atomic.Organizations.Organization
def run do
case Repo.all(User) do
@@ -106,6 +107,7 @@ defmodule Atomic.Repo.Seeds.Accounts do
def create_users(characters, role) do
courses = Repo.all(Course)
+ organizations = Repo.all(Organization)
for character <- characters do
email = (character |> String.downcase() |> String.replace(~r/\s*/, "")) <> "@mail.pt"
@@ -115,7 +117,8 @@ defmodule Atomic.Repo.Seeds.Accounts do
"email" => email,
"password" => "password1234",
"role" => role,
- "course_id" => Enum.random(courses).id
+ "course_id" => Enum.random(courses).id,
+ "default_organization_id" => Enum.random(organizations).id
}
case Accounts.register_user(user) do
diff --git a/priv/repo/seeds/activities.exs b/priv/repo/seeds/activities.exs
index 5316b8318..795dcf6b4 100644
--- a/priv/repo/seeds/activities.exs
+++ b/priv/repo/seeds/activities.exs
@@ -1,4 +1,5 @@
defmodule Atomic.Repo.Seeds.Activities do
+ alias Atomic.Activities.ActivityDepartment
alias Atomic.Repo
alias Atomic.Accounts.User
@@ -8,6 +9,7 @@ defmodule Atomic.Repo.Seeds.Activities do
def run do
seed_activities()
+ seed_activities_departments()
seed_enrollments()
end
@@ -36,10 +38,7 @@ defmodule Atomic.Repo.Seeds.Activities do
location: location
}
],
- enrolled: 0,
- departments: [
- Repo.get_by(Department, name: "Merchandise and Partnerships") |> Map.get(:id)
- ]
+ enrolled: 0
}
)
|> Repo.insert!()
@@ -59,13 +58,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-01 12:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "Marketing and Content") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -85,13 +78,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-01 12:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "Recreative") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -111,13 +98,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-01 12:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "Pedagogical") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -136,13 +117,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-01 12:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "CAOS") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -162,10 +137,7 @@ defmodule Atomic.Repo.Seeds.Activities do
location: location
}
],
- enrolled: 0,
- departments: [
- Repo.get_by(Department, name: "Merchandise and Partnerships") |> Map.get(:id)
- ]
+ enrolled: 0
}
)
|> Repo.insert!()
@@ -185,13 +157,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-05 13:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "Marketing and Content") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -211,13 +177,7 @@ defmodule Atomic.Repo.Seeds.Activities do
finish: DateTime.from_naive!(~N[2023-04-06 17:00:00], "Etc/UTC"),
location: location
}
- ],
- enrollments: [
- %{
- user_id: 1
- }
- ],
- departments: [Repo.get_by(Department, name: "Recreative") |> Map.get(:id)]
+ ]
}
)
|> Repo.insert!()
@@ -227,6 +187,22 @@ defmodule Atomic.Repo.Seeds.Activities do
end
end
+ def seed_activities_departments() do
+ department = Repo.get_by(Department, name: "Merchandise and Partnerships")
+
+ case Repo.all(ActivityDepartment) do
+ [] ->
+ for activity <- Repo.all(Activity) do
+ %ActivityDepartment{}
+ |> ActivityDepartment.changeset(%{
+ activity_id: activity.id,
+ department_id: department.id
+ })
+ |> Repo.insert!()
+ end
+ end
+ end
+
def seed_enrollments() do
case Repo.all(Enrollment) do
[] ->
diff --git a/priv/repo/seeds/memberships.exs b/priv/repo/seeds/memberships.exs
new file mode 100644
index 000000000..d6d16fd75
--- /dev/null
+++ b/priv/repo/seeds/memberships.exs
@@ -0,0 +1,69 @@
+defmodule Atomic.Repo.Seeds.Memberships do
+ alias Atomic.Organizations.Organization
+ alias Atomic.Organizations.Membership
+ alias Atomic.Accounts.User
+ alias Atomic.Organizations
+ alias Atomic.Repo
+
+ def run do
+ seed_memberships()
+ seed_users_organizations()
+ end
+
+ def seed_memberships() do
+ users = Repo.all(User)
+ organizations = Repo.all(Organization)
+
+ for user <- users do
+ for organization <- organizations do
+ prob = 50
+ random_number = :rand.uniform(100)
+
+ if random_number < prob do
+ %Membership{}
+ |> Membership.changeset(%{
+ "user_id" => user.id,
+ "organization_id" => organization.id,
+ "created_by_id" => Enum.random(users).id,
+ "role" => Enum.random([:follower, :member, :admin, :owner])
+ })
+ |> Repo.insert!()
+ end
+ end
+ end
+ end
+
+ def seed_users_organizations() do
+ years = ["2019/2020", "2020/2021", "2021/2022", "2022/2023", "2023/2024"]
+ organizations = Repo.all(Organization)
+ users = Repo.all(User)
+
+ titles = [
+ "Presidente",
+ "Vice-Presidente",
+ "Tesoureiro",
+ "Secretário",
+ "Presidente da MAG",
+ "Secretário da MAG",
+ "Presidente do CF",
+ "Secretário do CF"
+ ]
+
+ len_titles = length(titles)
+
+ for year <- years do
+ for org <- organizations do
+ for {user, title} <- Enum.zip(Enum.take_random(users, len_titles), titles) do
+ Organizations.create_user_organization(%{
+ "year" => year,
+ "organization_id" => org.id,
+ "user_id" => user.id,
+ "title" => title
+ })
+ end
+ end
+ end
+ end
+end
+
+Atomic.Repo.Seeds.Memberships.run()
diff --git a/priv/repo/seeds/organizations.exs b/priv/repo/seeds/organizations.exs
index eea6bcee9..88f9d5d5a 100644
--- a/priv/repo/seeds/organizations.exs
+++ b/priv/repo/seeds/organizations.exs
@@ -9,8 +9,6 @@ defmodule Atomic.Repo.Seeds.Organizations do
def run do
seed_organizations()
- seed_users_organizations()
- seed_memberships()
end
def seed_organizations() do
@@ -102,61 +100,6 @@ defmodule Atomic.Repo.Seeds.Organizations do
:ok
end
end
-
- def seed_memberships() do
- users = Repo.all(User)
- organizations = Repo.all(Organization)
-
- for user <- users do
- for organization <- organizations do
- prob = 50
- random_number = :rand.uniform(100)
-
- if random_number < prob do
- %Membership{}
- |> Membership.changeset(%{
- "user_id" => user.id,
- "organization_id" => organization.id,
- "created_by_id" => Enum.random(users).id,
- "role" => Enum.random([:follower, :member, :admin, :owner])
- })
- |> Repo.insert!()
- end
- end
- end
- end
-
- def seed_users_organizations() do
- years = ["2019/2020", "2020/2021", "2021/2022", "2022/2023", "2023/2024"]
- organizations = Repo.all(Organization)
- users = Repo.all(User)
-
- titles = [
- "Presidente",
- "Vice-Presidente",
- "Tesoureiro",
- "Secretário",
- "Presidente da MAG",
- "Secretário da MAG",
- "Presidente do CF",
- "Secretário do CF"
- ]
-
- len_titles = length(titles)
-
- for year <- years do
- for org <- organizations do
- for {user, title} <- Enum.zip(Enum.take_random(users, len_titles), titles) do
- Organizations.create_user_organization(%{
- "year" => year,
- "organization_id" => org.id,
- "user_id" => user.id,
- "title" => title
- })
- end
- end
- end
- end
end
Atomic.Repo.Seeds.Organizations.run()
diff --git a/test/atomic/activities_test.exs b/test/atomic/activities_test.exs
index dc3d22898..d4f20a8b0 100644
--- a/test/atomic/activities_test.exs
+++ b/test/atomic/activities_test.exs
@@ -4,6 +4,7 @@ defmodule Atomic.ActivitiesTest do
alias Atomic.Activities
import Atomic.Factory
import Atomic.ActivitiesFixtures
+ alias Atomic.OrganizationsFixtures
describe "activities" do
alias Atomic.Activities.Activity
@@ -178,7 +179,11 @@ defmodule Atomic.ActivitiesTest do
end
test "create_speaker/1 with valid data creates a speaker" do
- valid_attrs = %{bio: "some bio", name: "some name"}
+ valid_attrs = %{
+ bio: "some bio",
+ name: "some name",
+ organization_id: OrganizationsFixtures.organization_fixture().id
+ }
assert {:ok, %Speaker{} = speaker} = Activities.create_speaker(valid_attrs)
assert speaker.bio == "some bio"
diff --git a/test/atomic/partnerships_test.exs b/test/atomic/partnerships_test.exs
index 49f09b749..9066440e2 100644
--- a/test/atomic/partnerships_test.exs
+++ b/test/atomic/partnerships_test.exs
@@ -4,8 +4,8 @@ defmodule Atomic.PartnershipsTest do
alias Atomic.Partnerships
describe "partnerships" do
+ alias Atomic.OrganizationsFixtures
alias Atomic.Partnerships.Partner
-
import Atomic.PartnershipsFixtures
@invalid_attrs %{description: nil, name: nil}
@@ -21,9 +21,14 @@ defmodule Atomic.PartnershipsTest do
end
test "create_partner/1 with valid data creates a partner" do
- valid_attrs = %{description: "some description", name: "some name"}
+ valid_attrs = %{
+ description: "some description",
+ name: "some name",
+ organization_id: OrganizationsFixtures.organization_fixture().id
+ }
assert {:ok, %Partner{} = partner} = Partnerships.create_partner(valid_attrs)
+
assert partner.description == "some description"
assert partner.name == "some name"
end
diff --git a/test/atomic_web/controllers/page_controller_test.exs b/test/atomic_web/controllers/page_controller_test.exs
index ee513681a..e1a26847e 100644
--- a/test/atomic_web/controllers/page_controller_test.exs
+++ b/test/atomic_web/controllers/page_controller_test.exs
@@ -1,8 +1,9 @@
defmodule AtomicWeb.PageControllerTest do
use AtomicWeb.ConnCase
+ setup [:register_and_log_in_user]
test "GET /", %{conn: conn} do
conn = get(conn, "/")
- assert html_response(conn, 200) =~ "Listing Activities"
+ assert html_response(conn, 200) =~ "Home"
end
end
diff --git a/test/atomic_web/controllers/user_registration_controller_test.exs b/test/atomic_web/controllers/user_registration_controller_test.exs
index 1b520f7c9..e83058dcc 100644
--- a/test/atomic_web/controllers/user_registration_controller_test.exs
+++ b/test/atomic_web/controllers/user_registration_controller_test.exs
@@ -19,11 +19,14 @@ defmodule AtomicWeb.UserRegistrationControllerTest do
describe "POST /users/register" do
@tag :capture_log
test "creates account and logs the user in", %{conn: conn} do
+ organization = insert(:organization)
+
user_attrs = %{
name: Faker.Person.name(),
email: Faker.Internet.email(),
role: "student",
- password: "password1234"
+ password: "password1234",
+ default_organization_id: organization.id
}
conn =
diff --git a/test/atomic_web/controllers/user_session_controller_test.exs b/test/atomic_web/controllers/user_session_controller_test.exs
index d79e729ed..e9bc5dea7 100644
--- a/test/atomic_web/controllers/user_session_controller_test.exs
+++ b/test/atomic_web/controllers/user_session_controller_test.exs
@@ -4,7 +4,8 @@ defmodule AtomicWeb.UserSessionControllerTest do
import Atomic.AccountsFixtures
setup do
- %{user: insert(:user)}
+ organization = insert(:organization)
+ %{user: insert(:user, default_organization_id: organization.id)}
end
describe "GET /users/log_in" do
diff --git a/test/atomic_web/live/department_live_test.exs b/test/atomic_web/live/department_live_test.exs
deleted file mode 100644
index bda3e7a91..000000000
--- a/test/atomic_web/live/department_live_test.exs
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AtomicWeb.DepartmentLiveTest do
- use AtomicWeb.ConnCase
-end
diff --git a/test/atomic_web/live/organization_live_test.exs b/test/atomic_web/live/organization_live_test.exs
deleted file mode 100644
index 125a7d4ae..000000000
--- a/test/atomic_web/live/organization_live_test.exs
+++ /dev/null
@@ -1,117 +0,0 @@
-defmodule AtomicWeb.OrganizationLiveTest do
- use AtomicWeb.ConnCase
-
- import Phoenix.LiveViewTest
- import Atomic.OrganizationsFixtures
-
- @create_attrs %{description: "some description", name: "some name"}
- @update_attrs %{description: "some updated description", name: "some updated name"}
- @invalid_attrs %{description: nil, name: nil}
-
- defp create_organization(_) do
- organization = organization_fixture()
- %{organization: organization}
- end
-
- describe "Index" do
- setup [:create_organization]
- setup [:register_and_log_in_user]
-
- test "lists all organizations", %{conn: conn, organization: organization} do
- {:ok, _index_live, html} = live(conn, Routes.organization_index_path(conn, :index))
-
- assert html =~ "Listing Organizations"
- assert html =~ organization.description
- end
-
- test "saves new organization", %{conn: conn} do
- {:ok, index_live, _html} = live(conn, Routes.organization_index_path(conn, :index))
-
- assert index_live |> element("a", "New Organization") |> render_click() =~
- "New Organization"
-
- assert_patch(index_live, Routes.organization_index_path(conn, :new))
-
- assert index_live
- |> form("#organization-form", organization: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#organization-form", organization: @create_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.organization_index_path(conn, :index))
-
- assert html =~ "Organization created successfully"
- assert html =~ "some description"
- end
-
- test "updates organization in listing", %{conn: conn, organization: organization} do
- {:ok, index_live, _html} = live(conn, Routes.organization_index_path(conn, :index))
-
- assert index_live |> element("#organization-#{organization.id} a", "Edit") |> render_click() =~
- "Edit Organization"
-
- assert_patch(index_live, Routes.organization_index_path(conn, :edit, organization))
-
- assert index_live
- |> form("#organization-form", organization: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#organization-form", organization: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.organization_index_path(conn, :index))
-
- assert html =~ "Organization updated successfully"
- assert html =~ "some updated description"
- end
-
- test "deletes organization in listing", %{conn: conn, organization: organization} do
- {:ok, index_live, _html} = live(conn, Routes.organization_index_path(conn, :index))
-
- assert index_live
- |> element("#organization-#{organization.id} a", "Delete")
- |> render_click()
-
- refute has_element?(index_live, "#organization-#{organization.id}")
- end
- end
-
- describe "Show" do
- setup [:create_organization]
- setup [:register_and_log_in_user]
-
- test "displays organization", %{conn: conn, organization: organization} do
- {:ok, _show_live, html} =
- live(conn, Routes.organization_show_path(conn, :show, organization))
-
- assert html =~ "Show Organization"
- assert html =~ organization.description
- end
-
- test "updates organization within modal", %{conn: conn, organization: organization} do
- {:ok, show_live, _html} =
- live(conn, Routes.organization_show_path(conn, :show, organization))
-
- assert show_live |> element("a", "Edit") |> render_click() =~
- "Edit Organization"
-
- assert_patch(show_live, Routes.organization_show_path(conn, :edit, organization))
-
- assert show_live
- |> form("#organization-form", organization: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- show_live
- |> form("#organization-form", organization: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.organization_show_path(conn, :show, organization))
-
- assert html =~ "Organization updated successfully"
- assert html =~ "some updated description"
- end
- end
-end
diff --git a/test/atomic_web/live/partner_live_test.exs b/test/atomic_web/live/partner_live_test.exs
deleted file mode 100644
index 342cec686..000000000
--- a/test/atomic_web/live/partner_live_test.exs
+++ /dev/null
@@ -1,109 +0,0 @@
-defmodule AtomicWeb.PartnerLiveTest do
- use AtomicWeb.ConnCase
-
- import Phoenix.LiveViewTest
- import Atomic.PartnershipsFixtures
-
- @create_attrs %{description: "some description", name: "some name"}
- @update_attrs %{description: "some updated description", name: "some updated name"}
- @invalid_attrs %{description: nil, name: nil}
-
- defp create_partner(_) do
- partner = partner_fixture()
- %{partner: partner}
- end
-
- describe "Index" do
- setup [:create_partner]
- setup [:register_and_log_in_user]
-
- test "lists all partnerships", %{conn: conn, partner: partner} do
- {:ok, _index_live, html} = live(conn, Routes.partner_index_path(conn, :index))
-
- assert html =~ "Listing Partnerships"
- assert html =~ partner.description
- end
-
- test "saves new partner", %{conn: conn} do
- {:ok, index_live, _html} = live(conn, Routes.partner_index_path(conn, :index))
-
- assert index_live |> element("a", "New Partner") |> render_click() =~
- "New Partner"
-
- assert_patch(index_live, Routes.partner_index_path(conn, :new))
-
- assert index_live
- |> form("#partner-form", partner: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#partner-form", partner: @create_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.partner_index_path(conn, :index))
-
- assert html =~ "some description"
- end
-
- test "updates partner in listing", %{conn: conn, partner: partner} do
- {:ok, index_live, _html} = live(conn, Routes.partner_index_path(conn, :index))
-
- assert index_live |> element("#partner-#{partner.id} a", "Edit") |> render_click() =~
- "Edit Partner"
-
- assert_patch(index_live, Routes.partner_index_path(conn, :edit, partner))
-
- assert index_live
- |> form("#partner-form", partner: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#partner-form", partner: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.partner_index_path(conn, :index))
-
- assert html =~ "some updated description"
- end
-
- test "deletes partner in listing", %{conn: conn, partner: partner} do
- {:ok, index_live, _html} = live(conn, Routes.partner_index_path(conn, :index))
-
- assert index_live |> element("#partner-#{partner.id} a", "Delete") |> render_click()
- refute has_element?(index_live, "#partner-#{partner.id}")
- end
- end
-
- describe "Show" do
- setup [:create_partner]
- setup [:register_and_log_in_user]
-
- test "displays partner", %{conn: conn, partner: partner} do
- {:ok, _show_live, html} = live(conn, Routes.partner_show_path(conn, :show, partner))
-
- assert html =~ "Show Partner"
- assert html =~ partner.description
- end
-
- test "updates partner within modal", %{conn: conn, partner: partner} do
- {:ok, show_live, _html} = live(conn, Routes.partner_show_path(conn, :show, partner))
-
- assert show_live |> element("a", "Edit") |> render_click() =~
- "Edit Partner"
-
- assert_patch(show_live, Routes.partner_show_path(conn, :edit, partner))
-
- assert show_live
- |> form("#partner-form", partner: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- show_live
- |> form("#partner-form", partner: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.partner_show_path(conn, :show, partner))
-
- assert html =~ "some updated description"
- end
- end
-end
diff --git a/test/atomic_web/live/speaker_live_test.exs b/test/atomic_web/live/speaker_live_test.exs
deleted file mode 100644
index 46a5f6200..000000000
--- a/test/atomic_web/live/speaker_live_test.exs
+++ /dev/null
@@ -1,112 +0,0 @@
-defmodule AtomicWeb.SpeakerLiveTest do
- use AtomicWeb.ConnCase
-
- import Phoenix.LiveViewTest
- import Atomic.ActivitiesFixtures
-
- @create_attrs %{bio: "some bio", name: "some name"}
- @update_attrs %{bio: "some updated bio", name: "some updated name"}
- @invalid_attrs %{bio: nil, name: nil}
-
- defp create_speaker(_) do
- speaker = speaker_fixture()
- %{speaker: speaker}
- end
-
- describe "Index" do
- setup [:create_speaker]
- setup [:register_and_log_in_user]
-
- test "lists all speakers", %{conn: conn, speaker: speaker} do
- {:ok, _index_live, html} = live(conn, Routes.speaker_index_path(conn, :index))
-
- assert html =~ "Listing Speakers"
- assert html =~ speaker.bio
- end
-
- test "saves new speaker", %{conn: conn} do
- {:ok, index_live, _html} = live(conn, Routes.speaker_index_path(conn, :index))
-
- assert index_live |> element("a", "New Speaker") |> render_click() =~
- "New Speaker"
-
- assert_patch(index_live, Routes.speaker_index_path(conn, :new))
-
- assert index_live
- |> form("#speaker-form", speaker: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#speaker-form", speaker: @create_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.speaker_index_path(conn, :index))
-
- assert html =~ "Speaker created successfully"
- assert html =~ "some bio"
- end
-
- test "updates speaker in listing", %{conn: conn, speaker: speaker} do
- {:ok, index_live, _html} = live(conn, Routes.speaker_index_path(conn, :index))
-
- assert index_live |> element("#speaker-#{speaker.id} a", "Edit") |> render_click() =~
- "Edit Speaker"
-
- assert_patch(index_live, Routes.speaker_index_path(conn, :edit, speaker))
-
- assert index_live
- |> form("#speaker-form", speaker: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- index_live
- |> form("#speaker-form", speaker: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.speaker_index_path(conn, :index))
-
- assert html =~ "Speaker updated successfully"
- assert html =~ "some updated bio"
- end
-
- test "deletes speaker in listing", %{conn: conn, speaker: speaker} do
- {:ok, index_live, _html} = live(conn, Routes.speaker_index_path(conn, :index))
-
- assert index_live |> element("#speaker-#{speaker.id} a", "Delete") |> render_click()
- refute has_element?(index_live, "#speaker-#{speaker.id}")
- end
- end
-
- describe "Show" do
- setup [:create_speaker]
- setup [:register_and_log_in_user]
-
- test "displays speaker", %{conn: conn, speaker: speaker} do
- {:ok, _show_live, html} = live(conn, Routes.speaker_show_path(conn, :show, speaker))
-
- assert html =~ "Show Speaker"
- assert html =~ speaker.bio
- end
-
- test "updates speaker within modal", %{conn: conn, speaker: speaker} do
- {:ok, show_live, _html} = live(conn, Routes.speaker_show_path(conn, :show, speaker))
-
- assert show_live |> element("a", "Edit") |> render_click() =~
- "Edit Speaker"
-
- assert_patch(show_live, Routes.speaker_show_path(conn, :edit, speaker))
-
- assert show_live
- |> form("#speaker-form", speaker: @invalid_attrs)
- |> render_change() =~ "can't be blank"
-
- {:ok, _, html} =
- show_live
- |> form("#speaker-form", speaker: @update_attrs)
- |> render_submit()
- |> follow_redirect(conn, Routes.speaker_show_path(conn, :show, speaker))
-
- assert html =~ "Speaker updated successfully"
- assert html =~ "some updated bio"
- end
- end
-end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 83c71d0dd..4b06d4e08 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -47,7 +47,8 @@ defmodule AtomicWeb.ConnCase do
test context.
"""
def register_and_log_in_user(%{conn: conn}) do
- user = insert(:user)
+ organization = insert(:organization)
+ user = insert(:user, %{default_organization_id: organization.id})
%{conn: log_in_user(conn, user), user: user}
end
diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex
index 672b55cc9..1c23208c6 100644
--- a/test/support/fixtures/accounts_fixtures.ex
+++ b/test/support/fixtures/accounts_fixtures.ex
@@ -4,13 +4,15 @@ defmodule Atomic.AccountsFixtures do
entities via the `Atomic.Accounts` context.
"""
+ alias Atomic.OrganizationsFixtures
def unique_user_email, do: "user#{System.unique_integer()}@example.com"
def valid_user_password, do: "password1234"
def valid_user_attributes(attrs \\ %{}) do
Enum.into(attrs, %{
email: unique_user_email(),
- password: valid_user_password()
+ password: valid_user_password(),
+ default_organization_id: OrganizationsFixtures.organization_fixture().id
})
end
diff --git a/test/support/fixtures/activities_fixtures.ex b/test/support/fixtures/activities_fixtures.ex
index 07b548f16..bfe520fc9 100644
--- a/test/support/fixtures/activities_fixtures.ex
+++ b/test/support/fixtures/activities_fixtures.ex
@@ -4,6 +4,8 @@ defmodule Atomic.ActivitiesFixtures do
entities via the `Atomic.Activities` context.
"""
+ alias Atomic.OrganizationsFixtures
+
@doc """
Generate a activity.
"""
@@ -44,7 +46,8 @@ defmodule Atomic.ActivitiesFixtures do
attrs
|> Enum.into(%{
bio: "some bio",
- name: "some name"
+ name: "some name",
+ organization_id: OrganizationsFixtures.organization_fixture().id
})
|> Atomic.Activities.create_speaker()
diff --git a/test/support/fixtures/partnerships_fixtures.ex b/test/support/fixtures/partnerships_fixtures.ex
index b76159664..8bf2a45c1 100644
--- a/test/support/fixtures/partnerships_fixtures.ex
+++ b/test/support/fixtures/partnerships_fixtures.ex
@@ -4,6 +4,8 @@ defmodule Atomic.PartnershipsFixtures do
entities via the `Atomic.Partnerships` context.
"""
+ alias Atomic.OrganizationsFixtures
+
@doc """
Generate a partner.
"""
@@ -12,7 +14,8 @@ defmodule Atomic.PartnershipsFixtures do
attrs
|> Enum.into(%{
description: "some description",
- name: "some name"
+ name: "some name",
+ organization_id: OrganizationsFixtures.organization_fixture().id
})
|> Atomic.Partnerships.create_partner()