Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
commit
af6077b9c3
455 changed files with 78366 additions and 0 deletions
82
lib/tarakan_web/controllers/github_auth_controller.ex
Normal file
82
lib/tarakan_web/controllers/github_auth_controller.ex
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
defmodule TarakanWeb.GitHubAuthController do
|
||||
use TarakanWeb, :controller
|
||||
|
||||
alias Tarakan.Accounts
|
||||
alias Tarakan.GitHub.OAuth
|
||||
alias TarakanWeb.AccountAuth
|
||||
alias TarakanWeb.SafeRedirect
|
||||
|
||||
def request(conn, params) do
|
||||
return_to = safe_return_to(params["return_to"])
|
||||
|
||||
if OAuth.configured?() do
|
||||
state = OAuth.generate_state()
|
||||
{verifier, challenge} = OAuth.generate_pkce()
|
||||
redirect_uri = url(~p"/auth/github/callback")
|
||||
|
||||
conn
|
||||
|> put_session(:github_oauth_state, state)
|
||||
|> put_session(:github_oauth_verifier, verifier)
|
||||
|> put_session(:github_oauth_return_to, return_to)
|
||||
|> redirect(external: OAuth.authorize_url(state, challenge, redirect_uri))
|
||||
else
|
||||
conn
|
||||
|> put_flash(:error, "GitHub login has not been configured yet.")
|
||||
|> redirect(to: return_to)
|
||||
end
|
||||
end
|
||||
|
||||
def callback(conn, %{"code" => code, "state" => state}) do
|
||||
expected_state = get_session(conn, :github_oauth_state)
|
||||
verifier = get_session(conn, :github_oauth_verifier)
|
||||
return_to = safe_return_to(get_session(conn, :github_oauth_return_to))
|
||||
redirect_uri = url(~p"/auth/github/callback")
|
||||
current_account = conn.assigns.current_scope && conn.assigns.current_scope.account
|
||||
|
||||
with true <- OAuth.valid_state?(expected_state, state),
|
||||
true <- is_binary(verifier),
|
||||
:ok <- authorize_identity_link(current_account),
|
||||
{:ok, token} <- OAuth.exchange_code(code, verifier, redirect_uri),
|
||||
{:ok, profile} <- OAuth.fetch_user(token),
|
||||
{:ok, account} <- Accounts.upsert_external_identity(:github, profile, current_account),
|
||||
true <- Accounts.access_allowed?(account) do
|
||||
conn
|
||||
|> clear_oauth_session()
|
||||
|> put_session(:account_return_to, return_to)
|
||||
|> put_flash(:info, "Signed in as @#{account.handle}.")
|
||||
|> AccountAuth.log_in_account(account)
|
||||
else
|
||||
_error -> authorization_failed(conn, return_to)
|
||||
end
|
||||
end
|
||||
|
||||
def callback(conn, _params) do
|
||||
authorization_failed(conn, safe_return_to(get_session(conn, :github_oauth_return_to)))
|
||||
end
|
||||
|
||||
defp authorization_failed(conn, return_to) do
|
||||
conn
|
||||
|> clear_oauth_session()
|
||||
|> put_flash(:error, "GitHub authentication failed. Please try again.")
|
||||
|> redirect(to: return_to)
|
||||
end
|
||||
|
||||
defp clear_oauth_session(conn) do
|
||||
conn
|
||||
|> delete_session(:github_oauth_state)
|
||||
|> delete_session(:github_oauth_verifier)
|
||||
|> delete_session(:github_oauth_return_to)
|
||||
end
|
||||
|
||||
defp safe_return_to(path) when is_binary(path) do
|
||||
SafeRedirect.local_path(path)
|
||||
end
|
||||
|
||||
defp safe_return_to(_path), do: "/"
|
||||
|
||||
defp authorize_identity_link(nil), do: :ok
|
||||
|
||||
defp authorize_identity_link(account) do
|
||||
if Accounts.sudo_mode?(account), do: :ok, else: {:error, :recent_authentication_required}
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue