defmodule GitGudWeb.AuditLive.Org do
@moduledoc """
`/orgs/:handle/settings/audit[/:category[/before|after/:id]]` — who
changed what in an organization and its repositories
(`GitGud.Audit`).
For the org's admins and instance admins, in sudo mode: the log is
read-only, but it maps out the org's security posture. Both are
checked again on every `handle_params`, so a tab left open by someone
who has since been demoted, or whose sudo window lapsed, stops paging.
The client address and user agent recorded with each entry are not
shown here; only the instance view shows them.
"""
use GitGudWeb, :live_view
alias GitGud.Organizations
alias GitGudWeb.AuditLive.Page
# What an org's log can contain; instance and account entries never
# belong to an org.
@categories ~w(secrets members settings repositories branch_protection deploy_keys
webhooks credentials runners ci moderation)
@impl true
def mount(%{"handle" => handle}, _session, socket) do
org = Organizations.get_organization_by_handle!(handle)
if allowed?(org, socket.assigns.current_scope.user) do
{:ok,
socket
|> assign(:org, org)
|> assign(:page_title, "Audit log — #{handle}")
|> Page.setup(@categories, refines: [:actor, :repo], repos: repo_names(org))}
else
{:ok, deny(socket, org)}
end
end
@impl true
def handle_params(params, uri, socket) do
%{org: org, current_scope: %{user: user}} = socket.assigns
if allowed?(org, user),
do: Page.params(socket, params, uri, ~p"/orgs/#{org.handle}/settings/audit", {:org, org}),
else: {:noreply, deny(socket, org)}
end
@impl true
def handle_event("filter", %{"filter" => params}, socket), do: Page.filter(socket, params)
def handle_event(_event, _params, socket), do: {:noreply, socket}
@impl true
def handle_info({:audit, id}, socket) do
%{org: org, current_scope: %{user: user}} = socket.assigns
Page.live(socket, id, allowed?(org, user))
end
# Every repository the org has, including any gone since: a deleted
# one's entries are still in the log, under its old name.
defp repo_names(org) do
live = GitGud.Repositories.list_repositories_for(org) |> Enum.map(& &1.name)
(live ++ GitGud.Audit.deleted_repository_names(org)) |> Enum.uniq() |> Enum.sort()
end
defp allowed?(org, user), do: GitGud.Audit.readable?(user, {:org, org})
defp deny(socket, org) do
socket
|> put_flash(:error, "Org admin only.")
|> redirect(to: ~p"/orgs/#{org.handle}")
end
@impl true
def render(assigns) do
~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}>
<div class="space-y-6">
<.org_settings_header org={@org} current={:audit} />
<Page.body
base={@base}
filters={@filters}
filter_form={@filter_form}
categories={@categories}
refines={@refines}
repo_options={@repo_options}
entries={@streams.entries}
older={@older}
newer={@newer}
/>
</div>
</Layouts.app>
"""
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
3.1 KiB · text
History
b868907