350 lines
12 KiB
Plaintext
350 lines
12 KiB
Plaintext
<%= render HeaderComponent.new(title: "User: #{@user.cn}") %>
|
|
|
|
<%= render MainSimpleComponent.new do %>
|
|
<div class="mb-12 sm:flex sm:flex-row sm:gap-x-8">
|
|
<section class="sm:flex-1">
|
|
<h3>Account</h3>
|
|
<table class="divided">
|
|
<tbody>
|
|
<tr>
|
|
<th>ID</th>
|
|
<td><%= @user.id %></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Created at</th>
|
|
<td><%= @user.created_at.strftime("%Y-%m-%d (%H:%M UTC)") %></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Confirmed at</th>
|
|
<td>
|
|
<% if @user.confirmed_at %>
|
|
<%= @user.confirmed_at.strftime("%Y-%m-%d (%H:%M UTC)") %>
|
|
<% else %>
|
|
<%= badge "pending", :yellow %>
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Email</th>
|
|
<td><%= @user.email %></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Roles</th>
|
|
<td><%= @user.is_admin? ? badge("admin", :red) : "—" %></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Status</th>
|
|
<td>
|
|
<% if @user.is_contributing_member? || @user.is_paying_member? %>
|
|
<%= @user.is_contributing_member? ? badge("contributor", :green) : "" %>
|
|
<%= @user.is_paying_member? ? badge("sustainer", :green) : "" %>
|
|
<% else %>
|
|
—
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Donations</th>
|
|
<td>
|
|
<% if @user.donations.any? %>
|
|
<%= link_to admin_donations_path(username: @user.cn), class: "ks-text-link" do %>
|
|
<%= @user.donations.completed.count %> for
|
|
<%= number_with_delimiter @user.donations.completed.sum("amount_sats") %> sats
|
|
<% end %>
|
|
<% else %>
|
|
—
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Invited by</th>
|
|
<td>
|
|
<% if @user.inviter %>
|
|
<%= link_to @user.inviter.cn, admin_user_path(@user.inviter.cn), class: 'ks-text-link' %>
|
|
<% else %>—<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Invitations available</th>
|
|
<td data-controller="modal" data-action="keydown.esc->modal#close">
|
|
<div class="flex justify-between">
|
|
<span>
|
|
<%= @user.invitations.unused.count %>
|
|
</span>
|
|
<span>
|
|
<button id="add-invitations" data-action="click->modal#open">
|
|
<%= render partial: "icons/plus-circle", locals: {
|
|
custom_class: "text-green-600 hover:text-green-500 -mt-2 -mb-1 h-6 w-6 inline-block"
|
|
} %>
|
|
</button>
|
|
<% if @user.invitations.unused.count > 0 %>
|
|
<%= link_to invitations_admin_user_path(@user.cn),
|
|
id: "remove-invitations", data: {
|
|
turbo_method: :delete,
|
|
turbo_confirm: "Delete all of #{@user.cn}'s available invitations?"
|
|
} do %>
|
|
<%= render partial: "icons/x-circle", locals: {
|
|
custom_class: "text-red-600 hover:text-red-500 -mt-2 -mb-1 h-6 w-6 inline-block"
|
|
} %>
|
|
<% end %>
|
|
<% end %>
|
|
</span>
|
|
</div>
|
|
<%= render ModalComponent.new(show_close_button: false) do %>
|
|
<%= render partial: "admin/users/create_invitations",
|
|
locals: { user: @user } %>
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th class="align-top">Invited users</th>
|
|
<td class="align-top">
|
|
<% if @invitees.any? %>
|
|
<ul class="mb-0">
|
|
<% @recent_invitees.each do |invitee| %>
|
|
<li class="leading-none mb-2 last:mb-0"><%= link_to invitee.cn, admin_user_path(invitee.cn), class: "ks-text-link" %></li>
|
|
<% end %>
|
|
<% if @more_invitees > 0 %>
|
|
<li>and <%= link_to "#{@more_invitees} more", admin_invitations_path(username: @user.cn), class: "ks-text-link" %></li>
|
|
<% end %>
|
|
</ul>
|
|
<% else %>—<% end %>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<section class="sm:flex-1 sm:pt-0">
|
|
<h3>Avatar</h3>
|
|
<% if @user.avatar.attached? %>
|
|
<table class="divided">
|
|
<tbody>
|
|
<tr>
|
|
<th class="align-top">Image</th>
|
|
<td class="align-top">
|
|
<%= image_tag image_url_for(@user.avatar), class: "h-20 w-20 rounded-lg" %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Content type</th>
|
|
<td>
|
|
<%= @user.avatar.content_type %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Size</th>
|
|
<td>
|
|
<%= number_to_human_size(@user.avatar.blob.byte_size) %>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<% else %>
|
|
<p class="text-gray-500">No avatar uploaded</p>
|
|
<% end %>
|
|
|
|
<h3 class="mt-12">LDAP</h3>
|
|
<table class="divided">
|
|
<tbody>
|
|
<tr>
|
|
<th>Avatar</th>
|
|
<td>
|
|
<% if @ldap_avatar.present? %>
|
|
JPEG size: <%= number_to_human_size(@ldap_avatar.size) %>
|
|
<% else %>
|
|
—
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Display name</th>
|
|
<td><%= @user.display_name || "—" %></td>
|
|
</tr>
|
|
<tr>
|
|
<th class="align-top">PGP key</th>
|
|
<td class="align-top leading-5">
|
|
<% if @user.pgp_pubkey.present? %>
|
|
<span class="font-mono" title="<%= @user.pgp_fpr %>">
|
|
<% if @user.pgp_pubkey_contains_user_address? %>
|
|
<%= link_to wkd_key_url(hashed_username: @user.wkd_hash, l: @user.cn, format: :txt),
|
|
class: "ks-text-link", target: "_blank" do %>
|
|
<%= "#{@user.pgp_fpr[0, 8]}…#{@user.pgp_fpr[-8..-1]}" %>
|
|
<% end %>
|
|
<% else %>
|
|
<%= "#{@user.pgp_fpr[0, 8]}…#{@user.pgp_fpr[-8..-1]}" %>
|
|
<% end %>
|
|
</span><br />
|
|
<% @user.gnupg_key.uids.each do |uid| %>
|
|
<%= uid.uid %><br />
|
|
<% end %>
|
|
<% else %>
|
|
—
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
</div>
|
|
|
|
<section>
|
|
<h3>Services</h3>
|
|
<table class="divided">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Enabled</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% if Setting.discourse_enabled %>
|
|
<tr>
|
|
<td>Discourse</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @services_enabled.include?("discourse"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<%= link_to "Open profile", "#{Setting.discourse_public_url}/u/#{@user.cn}/summary", class: "btn-sm btn-gray" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.email_enabled %>
|
|
<tr>
|
|
<td>E-Mail</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: Flipper.enabled?(:email, current_user),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.gitea_enabled %>
|
|
<tr>
|
|
<td>Gitea</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @services_enabled.include?("gitea"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<%= link_to "Open profile", "#{Setting.gitea_public_url}/#{@user.cn}", class: "btn-sm btn-gray" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.mastodon_enabled %>
|
|
<tr>
|
|
<td>Mastodon</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @services_enabled.include?("mastodon"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<%= link_to "Open profile", "#{Setting.mastodon_public_url}/@#{@user.cn}", class: "btn-sm btn-gray" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.mediawiki_enabled %>
|
|
<tr>
|
|
<td>MediaWiki</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @services_enabled.include?("mediawiki"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<%= link_to "Open profile", "#{Setting.mediawiki_public_url}/Special:Contributions/#{@user.cn}", class: "btn-sm btn-gray" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.ejabberd_enabled %>
|
|
<tr>
|
|
<td>XMPP (ejabberd)</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @services_enabled.include?("ejabberd"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<% if Setting.ejabberd_admin_url.present? %>
|
|
<%= link_to "Open profile", "#{Setting.ejabberd_admin_url}/server/#{@user.ou}/user/#{@user.cn}/", class: "btn-sm btn-gray" %>
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.nostr_enabled %>
|
|
<tr>
|
|
<td>Nostr</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: @user.nostr_pubkey.present?,
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
<% if @user.nostr_pubkey.present? %>
|
|
<%= link_to "Open profile", "https://njump.me/#{@user.nostr_pubkey_bech32}", class: "btn-sm btn-gray" %>
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
<% if Setting.remotestorage_enabled %>
|
|
<tr>
|
|
<td>remoteStorage</td>
|
|
<td>
|
|
<%= render FormElements::ToggleComponent.new(
|
|
enabled: Flipper.enabled?(:remotestorage, current_user) && @services_enabled.include?("remotestorage"),
|
|
input_enabled: false
|
|
) %>
|
|
</td>
|
|
<td class="text-right">
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<% if Setting.lndhub_admin_enabled? && @user.confirmed? %>
|
|
<section>
|
|
<h3>LndHub</h3>
|
|
<% if @lndhub_user %>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Account</th>
|
|
<th>Balance</th>
|
|
<th>Incoming</th>
|
|
<th>Outgoing</th>
|
|
<th>Fees</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><%= @user.lndhub_username %></td>
|
|
<td><%= number_with_delimiter @lndhub_user.balance %> sats</td>
|
|
<td><%= number_with_delimiter @lndhub_user.sum_incoming %> sats</td>
|
|
<td><%= number_with_delimiter @lndhub_user.sum_outgoing %> sats</td>
|
|
<td><%= number_with_delimiter @lndhub_user.sum_fees %> sats</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<% else %>
|
|
<p>No LndHub user found for account <strong class="font-mono"><%= @user.lndhub_username %></strong>.
|
|
<% end %>
|
|
</section>
|
|
<% end %>
|
|
<% end %>
|