Skip to content

Commit

Permalink
Publishing of assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
mellelieuwes committed Nov 21, 2023
1 parent 794b848 commit 2407fa8
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 10 deletions.
2 changes: 1 addition & 1 deletion core/bundles/next/lib/menu/items.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Next.Menu.Items do
@impl true
def values() do
%{
next: %{action: %{type: :http_get, to: ~p"/next"}, title: "Next"},
next: %{action: %{type: :http_get, to: ~p"/"}, title: "Next"},
admin: %{
action: %{type: :redirect, to: ~p"/admin/config"},
title: dgettext("eyra-ui", "menu.item.admin")
Expand Down
19 changes: 19 additions & 0 deletions core/lib/core/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ defmodule Core.Accounts do
|> Repo.all()
end

## External

def external?(%User{id: user_id}) do
external?(user_id)
end

def external?(user_id) do
from(ex in ExternalSignIn.User,
where: ex.user_id == ^user_id
)
|> Repo.exists?()
end

def internal?(nil), do: false

def internal?(user) do
not external?(user)
end

## Search

def search(query, preload \\ []) do
Expand Down
9 changes: 9 additions & 0 deletions core/lib/core_web/controllers/user_auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ defmodule CoreWeb.UserAuth do
|> redirect(to: redirect_to)
end

def log_in_user_without_redirect(conn, user) do
token = Accounts.generate_user_session_token(user)

conn
|> renew_session()
|> put_session(:user_token, token)
|> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}")
end

defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do
put_resp_cookie(conn, @remember_me_cookie, token, @remember_me_options)
end
Expand Down
2 changes: 1 addition & 1 deletion core/lib/core_web/live/menu/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule CoreWeb.Menu.Builder do
admin: Admin.Public.admin?(user),
support: Admin.Public.admin?(user),
debug: Admin.Public.admin?(user),
profile: not is_nil(user),
profile: Core.Accounts.internal?(user),
signout: not is_nil(user),
signin: is_nil(user)
}
Expand Down
59 changes: 59 additions & 0 deletions core/lib/external_sign_in.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule ExternalSignIn do
alias Core.Accounts
alias Core.Repo
import Ecto.Query, warn: false

def sign_in(conn, organisation, external_id) do
user =
if user = get_user_by_external_id(external_id) do
user
else
register_user(organisation, external_id)
end

CoreWeb.UserAuth.log_in_user_without_redirect(conn, user)
end

def get_user_by_external_id(external_id) do
external_user_query =
from(ex in ExternalSignIn.User,
where: ex.external_id == ^external_id,
select: ex.user_id
)

from(u in Accounts.User, where: u.id in subquery(external_user_query))
|> Repo.one()
end

def register_user(organisation, external_id) when is_atom(organisation) do
register_user(Atom.to_string(organisation), external_id)
end

def register_user(organisation, external_id) do
name = "#{organisation}_#{external_id}"

user =
Accounts.User.sso_changeset(%Accounts.User{}, %{
email: "external_#{name}@eyra.co",
researcher: false,
student: false,
displayname: name,
profile: %{
fullname: name
}
})

external_user =
ExternalSignIn.User.changeset(%ExternalSignIn.User{}, %{
external_id: external_id,
organisation: organisation
})

{:ok, result} =
external_user
|> Ecto.Changeset.put_assoc(:user, user)
|> Repo.insert()

result.user
end
end
21 changes: 21 additions & 0 deletions core/lib/external_sign_in/user.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule ExternalSignIn.User do
use Ecto.Schema
import Ecto.Changeset

@fields ~w(external_id organisation)a
@required_fields @fields

schema "external_users" do
belongs_to(:user, Core.Accounts.User)
field(:external_id, :string)
field(:organisation, :string)

timestamps()
end

def changeset(%ExternalSignIn.User{} = user, attrs) do
user
|> cast(attrs, @fields)
|> validate_required(@required_fields)
end
end
2 changes: 1 addition & 1 deletion core/priv/gettext/en/LC_MESSAGES/eyra-assignment.po
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ msgstr "Publish"

#, elixir-autogen, elixir-format, fuzzy
msgid "retract.button"
msgstr "Contact researcher"
msgstr "Take offline"

#, elixir-autogen, elixir-format
msgid "onboarding.consent.continue.button"
Expand Down
2 changes: 1 addition & 1 deletion core/priv/gettext/nl/LC_MESSAGES/eyra-assignment.po
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ msgstr "Publiceren"

#, elixir-autogen, elixir-format, fuzzy
msgid "retract.button"
msgstr "Intrekken"
msgstr "Offline halen"

#, elixir-autogen, elixir-format
msgid "onboarding.consent.continue.button"
Expand Down
20 changes: 20 additions & 0 deletions core/priv/repo/migrations/20231120165201_add_external_user.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Core.Repo.Migrations.AddExternalUser do
use Ecto.Migration

def up do
create table(:external_users) do
add(:user_id, references(:users, on_delete: :delete_all), null: false)
add(:organisation, :string)
add(:external_id, :string)

timestamps()
end

create(unique_index(:external_users, [:organisation, :external_id]))
end

def down do
drop(index(:external_users, [:organisation, :external_id]))
drop(table(:external_users))
end
end
7 changes: 7 additions & 0 deletions core/systems/assignment/_public.ex
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ defmodule Systems.Assignment.Public do
Core.Persister.save(assignment, changeset)
end

def update!(assignment, %{} = attrs) do
case __MODULE__.update(assignment, attrs) do
{:ok, assignment} -> assignment
_ -> nil
end
end

def update_budget(assignment, budget) do
changeset =
Assignment.Model.changeset(assignment, %{})
Expand Down
13 changes: 9 additions & 4 deletions core/systems/assignment/content_page_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,24 @@ defmodule Systems.Assignment.ContentPageBuilder do
do: [publish: publish, preview: preview]

defp handle_publish(socket) do
socket
socket |> set_status(:online)
end

defp handle_retract(socket) do
socket
socket |> set_status(:offline)
end

defp handle_close(socket) do
socket
socket |> set_status(:idle)
end

defp handle_open(socket) do
socket
socket |> set_status(:concept)
end

defp set_status(%{assigns: %{model: assignment}} = socket, status) do
assignment = Assignment.Public.update!(assignment, %{status: status})
socket |> Phoenix.Component.assign(model: assignment)
end

defp create_tabs(assignment, show_errors, assigns) do
Expand Down
2 changes: 1 addition & 1 deletion core/systems/assignment/crew_page_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ defmodule Systems.Assignment.CrewPageBuilder do
defp consent_view(%{consent_agreement: nil}, _), do: nil

defp consent_view(%{consent_agreement: consent_agreement}, %{current_user: user, fabric: fabric}) do
revision = Consent.Public.latest_revision(consent_agreement)
revision = Consent.Public.latest_revision(consent_agreement, [:signatures])

Fabric.prepare_child(fabric, :onboarding_view, Assignment.OnboardingConsentView, %{
revision: revision,
Expand Down
50 changes: 49 additions & 1 deletion core/systems/assignment/external_panel_controller.ex
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
defmodule Systems.Assignment.ExternalPanelController do
use CoreWeb, :controller

def create(conn, %{"id" => _id, "panel" => _panel} = params) do
alias Systems.Assignment
alias Systems.Crew

def create(conn, %{"id" => id, "panel" => _} = params) do
assignment = Assignment.Public.get!(id, [:crew, :auth_node])

cond do
has_no_access?(assignment, params) -> forbidden(conn)
is_offline?(assignment) -> service_unavailable(conn)
true -> start(assignment, conn, params)
end
end

defp is_offline?(%{status: status}) do
status != :online
end

defp has_no_access?(%{external_panel: external_panel}, %{"panel" => panel}) do
external_panel = Atom.to_string(external_panel)
external_panel != panel
end

defp start(%{external_panel: panel} = assignment, conn, params) do
participant_id = get_participant(params)

conn
|> ExternalSignIn.sign_in(panel, participant_id)
|> authorize_user(assignment)
|> add_panel_info(params)
|> redirect(to: path(params))
end

defp forbidden(conn) do
conn
|> put_status(:forbidden)
|> put_view(html: CoreWeb.ErrorHTML)
|> render(:"403")
end

defp service_unavailable(conn) do
conn
|> put_status(:service_unavailable)
|> put_view(html: CoreWeb.ErrorHTML)
|> render(:"503")
end

defp authorize_user(%{assigns: %{current_user: user}} = conn, %{crew: crew}) do
if not Crew.Public.member?(crew, user) do
Crew.Public.apply_member_with_role(crew, user, :participant)
end

conn
end

defp add_panel_info(conn, params) do
panel_info = %{
participant: get_participant(params),
Expand Down

0 comments on commit 2407fa8

Please sign in to comment.