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

Allow delete account & orga #275

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
22 changes: 21 additions & 1 deletion backend/lib/azimutt_web/controllers/user_settings_controller.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule AzimuttWeb.UserSettingsController do
use AzimuttWeb, :controller
alias Azimutt.Accounts
alias Azimutt.Organizations
alias Azimutt.Utils.Result
alias AzimuttWeb.UserAuth
action_fallback AzimuttWeb.FallbackController
Expand All @@ -11,6 +12,25 @@ defmodule AzimuttWeb.UserSettingsController do
conn |> show_html(current_user, now)
end

def auth(conn, _params) do
current_user = conn.assigns.current_user
now = DateTime.utc_now()
auth_token_changeset = Accounts.change_auth_token(current_user)
conn |> render("auth.html", auth_tokens: Accounts.list_auth_tokens(current_user, now), auth_token_changeset: auth_token_changeset)
end

def delete_account(conn, _params) do
current_user = conn.assigns.current_user
now = DateTime.utc_now()

# Accounts.delete_user(current_user, now)
# |> Result.fold(
# fn _ -> conn |> put_flash(:error, "Can't delete your account :/") end,
# fn _ -> conn |> put_flash(:info, "Account deleted") end
# ) |> redirect(to: Routes.page_path(conn, :index))
conn |> show_html(current_user, now)
end

def update_account(conn, %{"user" => user_params}) do
current_user = conn.assigns.current_user
now = DateTime.utc_now()
Expand Down Expand Up @@ -153,7 +173,7 @@ defmodule AzimuttWeb.UserSettingsController do
conn
|> render("show.html",
user: user,
auth_tokens: Accounts.list_auth_tokens(user, now),
organizations: Organizations.list_organizations(user),
infos_changeset: infos_changeset,
email_changeset: email_changeset,
password_changeset: password_changeset,
Expand Down
7 changes: 5 additions & 2 deletions backend/lib/azimutt_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,16 @@ defmodule AzimuttWeb.Router do
pipe_through([:user_settings_root_layout, :empty_layout])
get("/", UserSettingsController, :show)
put("/account", UserSettingsController, :update_account)
delete("/account", UserSettingsController, :delete_account)
put("/email", UserSettingsController, :update_email)
get("/email/:token", UserSettingsController, :confirm_update_email)
put("/password", UserSettingsController, :update_password)
post("/password", UserSettingsController, :set_password)
delete("/providers/:provider", UserSettingsController, :remove_provider)
post("/auth-tokens", UserSettingsController, :create_auth_token)
delete("/auth-tokens/:token_id", UserSettingsController, :delete_auth_token)

get("/auth", UserSettingsController, :auth)
post("/auth/tokens", UserSettingsController, :create_auth_token)
delete("/auth/tokens/:token_id", UserSettingsController, :delete_auth_token)
end

resources "/organizations", OrganizationController, param: "organization_id", except: [:index] do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<nav class="space-y-1">
<%= for {label, icon, url} <- [
{"Account", "user-circle", Routes.user_settings_path(@conn, :show)},
{"Auth", "key", Routes.user_settings_path(@conn, :auth)},
# {"Account", "cog", "#"},
# {"Password", "key", "#"},
# {"Notifications", "bell", "#"},
# {"Plan & Billing", "credit-card", "#"},
# {"Integrations", "squares-plus", "#"}
Expand Down
42 changes: 42 additions & 0 deletions backend/lib/azimutt_web/templates/user_settings/auth.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<section aria-labelledby="auth-tokens-social-heading">
<div class="shadow sm:overflow-hidden sm:rounded-md">
<div class="bg-white px-4 py-6 sm:p-6">
<h2 id="auth-tokens-social-heading" class="text-lg font-medium leading-6 text-gray-900">Your authentication tokens</h2>
<p class="text-sm text-gray-500">
Authentication tokens allows to identify you without a password.
This is useful for API calls to avoid the login/password flow, send them in your request in `auth-token` parameter, and it will grant you your accesses.
</p>
<div class="mt-3 -space-y-px">
<%= for {token, index} <- Enum.with_index(@auth_tokens) do %>
<div class={"#{if index == 0, do: "rounded-t-md"} border-gray-300 border flex items-center"}>
<div class="grow px-3 py-2">
<p class="text-gray-900 text-sm font-medium"><%= token.name %> (<%= if token.expire_at == nil do %>does not expire<% else %>expire on <%= format_datetime(token.expire_at) %><% end %>)</p>
<p class="mt-1 truncate text-xs leading-5 text-gray-500"><%= token.nb_access %> access since its creation on <%= format_datetime(token.created_at) %><%= if token.last_access != nil do %>, last accessed on <%= format_datetime(token.last_access) %><% end %>.</p>
</div>
<div>
<p class="px-2 py-1 border border-gray-300 shadow-sm rounded text-sm leading-relaxed overflow-auto bg-gray-100 text-gray-100 hover:text-gray-700"><%= token.id %></p>
</div>
<%= link(title: "Delete auth token", to: Routes.user_settings_path(@conn, :delete_auth_token, token.id), method: :delete) do %>
<Icon.trash class="mx-2 text-gray-300" />
<% end %>
</div>
<% end %>
<.form let={f} for={@auth_token_changeset} action={Routes.user_settings_path(@conn, :create_auth_token)}>
<div class="flex -space-x-px">
<div class="min-w-0 w-1/2 flex-1">
<%= label f, :name, "Token name", class: "sr-only" %>
<%= text_input f, :name, placeholder: "Token name", required: true, class: "#{if length(@auth_tokens) == 0, do: "rounded-tl-md"} rounded-bl-md relative block w-full border border-gray-300 bg-transparent focus:z-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
<%= error_tag f, :name %>
</div>
<div class="min-w-0">
<%= label f, :expire_at, "Expiration", class: "sr-only" %>
<%= select f, :expire_at, ["does not expire": "none", "expire in 1 hour": "hour", "expire in 1 day": "day", "expire in 1 month": "month"], class: "relative block w-full border border-gray-300 bg-transparent focus:z-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
<%= error_tag f, :expire_at %>
</div>
<%= submit "Create token", class: "#{if length(@auth_tokens) == 0, do: "rounded-tr-md"} rounded-br-md relative block border border-gray-300 px-4 py-2 text-sm font-medium bg-gray-50 text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 disabled:bg-gray-100 disabled:text-gray-400" %>
</div>
</.form>
</div>
</div>
</div>
</section>
70 changes: 27 additions & 43 deletions backend/lib/azimutt_web/templates/user_settings/show.html.heex
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@

<section aria-labelledby="delete-account-heading">
<div class="shadow sm:overflow-hidden sm:rounded-md">
<div class="bg-red-50 px-4 py-6 sm:p-6">
<h2 id="delete-account-heading" class="text-lg font-medium leading-6 text-red-900">Delete account</h2>
<div class="mt-1 text-sm text-gray-500">
<h3 class="block text-sm font-medium leading-6 text-gray-900">Your organizations</h3>
<ul class="list-disc list-inside">
<%= for orga <- @organizations |> Enum.sort_by(fn o -> o.name end) do %>
<li>
<a href={Routes.organization_path(@conn, :show, orga)} title={orga.id} class="underline"><%= orga.name %></a>
(<%= orga.members |> length() %> members, <%= orga.invitations |> length() %> invitations, <%= orga.projects |> length() %> projects)
</li>
<% end %>
</ul>
<p class="mt-1 text-sm text-gray-500">
You will be <span class="font-bold">removed</span> from all your organizations. If you are alone, the organization will be deleted and all its projects too.
</p>
</div>
</div>
<div class="bg-red-100 px-4 py-3 text-right sm:px-6">
<%= link "Delete account", to: Routes.user_settings_path(@conn, :delete_account), method: :delete, data: [confirm: "Are you sure?"], class: "inline-flex justify-center rounded-md bg-red-900 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-900" %>
</div>
</div>
</section>


<!-- General infos -->
<section aria-labelledby="account-heading">
<.form let={f} for={@infos_changeset} action={Routes.user_settings_path(@conn, :update_account)}>
Expand Down Expand Up @@ -178,46 +205,3 @@
</div>
</section>
<% end %>

<section aria-labelledby="auth-tokens-social-heading">
<div class="shadow sm:overflow-hidden sm:rounded-md">
<div class="bg-white px-4 py-6 sm:p-6">
<h2 id="auth-tokens-social-heading" class="text-lg font-medium leading-6 text-gray-900">Your authentication tokens</h2>
<p class="text-sm text-gray-500">
Authentication tokens allows to identify you without a password.
This is useful for API calls to avoid the login/password flow, send them in your request in `auth-token` parameter, and it will grant you your accesses.
</p>
<div class="mt-3 -space-y-px">
<%= for {token, index} <- Enum.with_index(@auth_tokens) do %>
<div class={"#{if index == 0, do: "rounded-t-md"} border-gray-300 border flex items-center"}>
<div class="grow px-3 py-2">
<p class="text-gray-900 text-sm font-medium"><%= token.name %> (<%= if token.expire_at == nil do %>does not expire<% else %>expire on <%= format_datetime(token.expire_at) %><% end %>)</p>
<p class="mt-1 truncate text-xs leading-5 text-gray-500"><%= token.nb_access %> access since its creation on <%= format_datetime(token.created_at) %><%= if token.last_access != nil do %>, last accessed on <%= format_datetime(token.last_access) %><% end %>.</p>
</div>
<div>
<p class="px-2 py-1 border border-gray-300 shadow-sm rounded text-sm leading-relaxed overflow-auto bg-gray-100 text-gray-100 hover:text-gray-700"><%= token.id %></p>
</div>
<%= link(title: "Delete auth token", to: Routes.user_settings_path(@conn, :delete_auth_token, token.id), method: :delete) do %>
<Icon.trash class="mx-2 text-gray-300" />
<% end %>
</div>
<% end %>
<.form let={f} for={@auth_token_changeset} action={Routes.user_settings_path(@conn, :create_auth_token)}>
<div class="flex -space-x-px">
<div class="min-w-0 w-1/2 flex-1">
<%= label f, :name, "Token name", class: "sr-only" %>
<%= text_input f, :name, placeholder: "Token name", required: true, class: "#{if length(@auth_tokens) == 0, do: "rounded-tl-md"} rounded-bl-md relative block w-full border border-gray-300 bg-transparent focus:z-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
<%= error_tag f, :name %>
</div>
<div class="min-w-0">
<%= label f, :expire_at, "Expiration", class: "sr-only" %>
<%= select f, :expire_at, ["does not expire": "none", "expire in 1 hour": "hour", "expire in 1 day": "day", "expire in 1 month": "month"], class: "relative block w-full border border-gray-300 bg-transparent focus:z-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
<%= error_tag f, :expire_at %>
</div>
<%= submit "Create token", class: "#{if length(@auth_tokens) == 0, do: "rounded-tr-md"} rounded-br-md relative block border border-gray-300 px-4 py-2 text-sm font-medium bg-gray-50 text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 disabled:bg-gray-100 disabled:text-gray-400" %>
</div>
</.form>
</div>
</div>
</div>
</section>
Loading