diff --git a/app/assets/stylesheets/components/base.css b/app/assets/stylesheets/components/base.css index b8fbc69..b4fa491 100644 --- a/app/assets/stylesheets/components/base.css +++ b/app/assets/stylesheets/components/base.css @@ -36,10 +36,18 @@ @apply mb-4 leading-6; } + main p:last-child { + @apply mb-0; + } + main ul { @apply mb-6; } + main ul:last-child { + @apply mb-0; + } + main ul li { @apply leading-6; } diff --git a/app/assets/stylesheets/components/buttons.css b/app/assets/stylesheets/components/buttons.css index da79cec..5da9116 100644 --- a/app/assets/stylesheets/components/buttons.css +++ b/app/assets/stylesheets/components/buttons.css @@ -1,6 +1,6 @@ @layer components { .btn { - @apply font-semibold rounded-md leading-none cursor-pointer text-center + @apply inline-block font-semibold rounded-md leading-none cursor-pointer text-center transition-colors duration-75 focus:outline-none focus:ring-4; } diff --git a/app/assets/stylesheets/components/tables.css b/app/assets/stylesheets/components/tables.css index 9b5e1fc..14fb4af 100644 --- a/app/assets/stylesheets/components/tables.css +++ b/app/assets/stylesheets/components/tables.css @@ -7,16 +7,30 @@ @apply text-left; } - table th { + table thead th { @apply pb-3.5 text-sm font-normal uppercase text-gray-500; } + table tbody th { + @apply text-left font-normal text-gray-500; + } + table th:not(:last-of-type), table td:not(:last-of-type) { @apply pr-2; } - table td { + table td, tbody th { @apply py-2; } + + table.divided { + @apply divide-y divide-gray-300; + } + table.divided tbody { + @apply divide-y divide-gray-200; + } + table.divided td, table.divided tbody th { + @apply py-3; + } } diff --git a/app/controllers/admin/ldap_users_controller.rb b/app/controllers/admin/ldap_users_controller.rb deleted file mode 100644 index 5109041..0000000 --- a/app/controllers/admin/ldap_users_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Admin::LdapUsersController < Admin::BaseController - before_action :set_current_section - - def index - ldap = LdapService.new - @ou = params[:ou] || "kosmos.org" - @orgs = ldap.fetch_organizations - @entries = ldap.fetch_users(ou: @ou) - @stats = { - users_confirmed: User.where(ou: @ou).confirmed.count, - users_pending: User.where(ou: @ou).pending.count - } - end - - private - - def set_current_section - @current_section = :ldap_users - end -end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb new file mode 100644 index 0000000..b23f468 --- /dev/null +++ b/app/controllers/admin/users_controller.rb @@ -0,0 +1,33 @@ +class Admin::UsersController < Admin::BaseController + before_action :set_user, only: [:show] + before_action :set_current_section + + def index + ldap = LdapService.new + @ou = params[:ou] || "kosmos.org" + @orgs = ldap.fetch_organizations + @users = User.where(ou: @ou).order(cn: :asc).to_a + + @stats = { + users_confirmed: User.where(ou: @ou).confirmed.count, + users_pending: User.where(ou: @ou).pending.count + } + end + + def show + if Setting.lndhub_admin_enabled? + @lndhub_user = @user.lndhub_user + end + end + + private + + def set_user + address = params[:address].split("@") + @user = User.where(cn: address.first, ou: address.last).first + end + + def set_current_section + @current_section = :users + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 248d897..037be7c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -10,5 +10,12 @@ module ApplicationHelper "text-gray-300 hover:bg-gray-900/30 hover:text-white active:bg-gray-900/30 active:text-white px-3 py-2 rounded-md font-medium text-base md:text-sm block md:inline-block" end end + + # Colors available: gray, red, yellow, green, blue, purple, pink + # (Add more colors by adding classes to the safelist in tailwind.config.js) + def badge(text, color) + tag.span text, class: "inline-flex items-center rounded-full bg-#{color}-100 px-2.5 py-0.5 text-xs font-medium text-#{color}-800" + end + end diff --git a/app/helpers/ldap_users_helper.rb b/app/helpers/ldap_users_helper.rb deleted file mode 100644 index 81e2eff..0000000 --- a/app/helpers/ldap_users_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module LdapUsersHelper -end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000..2310a24 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/models/invitation.rb b/app/models/invitation.rb index e4910a5..cfff859 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -1,6 +1,7 @@ class Invitation < ApplicationRecord # Relations belongs_to :user + belongs_to :invitee, class_name: "User", foreign_key: 'invited_user_id', optional: true # Validations validates_presence_of :user diff --git a/app/models/lndhub_user.rb b/app/models/lndhub_user.rb index e5645c5..f467089 100644 --- a/app/models/lndhub_user.rb +++ b/app/models/lndhub_user.rb @@ -10,6 +10,18 @@ class LndhubUser < LndhubBase foreign_key: "login" def balance - accounts.current.first.ledgers.sum("account_ledgers.amount") + accounts.current.first.ledgers.sum("account_ledgers.amount").to_i.abs + end + + def sum_outgoing + accounts.outgoing.first.ledgers.sum("account_ledgers.amount").to_i.abs + end + + def sum_incoming + accounts.incoming.first.ledgers.sum("account_ledgers.amount").to_i.abs + end + + def sum_fees + accounts.fees.first.ledgers.sum("account_ledgers.amount").to_i.abs end end diff --git a/app/models/user.rb b/app/models/user.rb index b8226ff..3c4be54 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,6 +3,10 @@ class User < ApplicationRecord # Relations has_many :invitations, dependent: :destroy + has_one :invitation, inverse_of: :invitee, foreign_key: 'invited_user_id' + has_one :inviter, through: :invitation, source: :user + has_many :invitees, through: :invitations + has_many :donations, dependent: :nullify has_one :lndhub_user, class_name: "LndhubUser", inverse_of: "user", @@ -66,6 +70,12 @@ class User < ApplicationRecord end end + def ldap_entry + return @ldap_entry if defined?(@ldap_entry) + ldap = LdapService.new + @ldap_entry = ldap.fetch_users(uid: self.cn, ou: self.ou).first + end + def address "#{self.cn}@#{self.ou}" end diff --git a/app/services/ldap_service.rb b/app/services/ldap_service.rb index d68b992..baff4c9 100644 --- a/app/services/ldap_service.rb +++ b/app/services/ldap_service.rb @@ -43,7 +43,7 @@ class LdapService < ApplicationService end attributes = %w{dn cn uid mail admin} - filter = Net::LDAP::Filter.eq("uid", "*") + filter = Net::LDAP::Filter.eq("uid", args[:uid] || "*") entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes) entries.sort_by! { |e| e.cn[0] } diff --git a/app/views/admin/donations/_form.html.erb b/app/views/admin/donations/_form.html.erb index 1405b08..0522cb0 100644 --- a/app/views/admin/donations/_form.html.erb +++ b/app/views/admin/donations/_form.html.erb @@ -10,46 +10,24 @@ <% end %> -
-

- <%= form.label :user_id %> - <%= form.collection_select :user_id, User.where(ou: "kosmos.org").order(:cn), :id, :cn %> -

-
+
+ <%= form.label :user_id %> + <%= form.collection_select :user_id, User.where(ou: "kosmos.org").order(:cn), :id, :cn, {} %> -
-

- <%= form.label :amount_sats, "Amount BTC (sats)" %> - <%= form.number_field :amount_sats %> -

-
+ <%= form.label :amount_sats, "Amount BTC (sats)" %> + <%= form.number_field :amount_sats %> -
-

- <%= form.label :amount_eur, "Amount EUR (cents)" %> - <%= form.number_field :amount_eur %> -

-
+ <%= form.label :amount_eur, "Amount EUR (cents)" %> + <%= form.number_field :amount_eur %> -
-

- <%= form.label :amount_usd, "Amount USD (cents)"%> - <%= form.number_field :amount_usd %> -

-
+ <%= form.label :amount_usd, "Amount USD (cents)"%> + <%= form.number_field :amount_usd %> -
-

- <%= form.label :public_name %> - <%= form.text_field :public_name %> -

-
+ <%= form.label :public_name %> + <%= form.text_field :public_name %> -
-

- <%= form.label :paid_at %> - <%= form.text_field :paid_at %> -

+ <%= form.label :paid_at %> + <%= form.text_field :paid_at %>

diff --git a/app/views/admin/donations/edit.html.erb b/app/views/admin/donations/edit.html.erb index ba590b2..27340f1 100644 --- a/app/views/admin/donations/edit.html.erb +++ b/app/views/admin/donations/edit.html.erb @@ -1,12 +1,9 @@ -<%= render HeaderComponent.new(title: "Donations") %> +<%= render HeaderComponent.new(title: "Donation ##{@donation.id}") %> <%= render MainSimpleComponent.new do %> -

Editing Donation

- <%= render 'form', donation: @donation, url: admin_donation_path(@donation) %>

- <%= link_to 'Show', admin_donation_path(@donation), class: 'ks-text-link' %> | - <%= link_to 'Back', admin_donations_path, class: 'ks-text-link' %> + <%= link_to 'Cancel', admin_donation_path(@donation), class: 'btn-sm btn-gray' %>

<% end %> diff --git a/app/views/admin/donations/index.html.erb b/app/views/admin/donations/index.html.erb index 0f57949..1074843 100644 --- a/app/views/admin/donations/index.html.erb +++ b/app/views/admin/donations/index.html.erb @@ -21,7 +21,7 @@

<% if @donations.any? %>

Recent Donations

- +
@@ -33,11 +33,10 @@ - <% @donations.each do |donation| %> - + diff --git a/app/views/admin/donations/new.html.erb b/app/views/admin/donations/new.html.erb index d831813..176b659 100644 --- a/app/views/admin/donations/new.html.erb +++ b/app/views/admin/donations/new.html.erb @@ -1,8 +1,6 @@ -<%= render HeaderComponent.new(title: "Donations") %> +<%= render HeaderComponent.new(title: "Add Donation") %> <%= render MainSimpleComponent.new do %> -

New Donation

- <%= render 'form', donation: @donation, url: admin_donations_path %>

diff --git a/app/views/admin/donations/show.html.erb b/app/views/admin/donations/show.html.erb index 0c1d54c..1526789 100644 --- a/app/views/admin/donations/show.html.erb +++ b/app/views/admin/donations/show.html.erb @@ -1,38 +1,41 @@ -<%= render HeaderComponent.new(title: "Donations") %> +<%= render HeaderComponent.new(title: "Donation ##{@donation.id}") %> <%= render MainSimpleComponent.new do %> -

- User: - <%= @donation.user.address %> -

+
+
User
<%= donation.user.address %><%= link_to donation.user.address, admin_user_path(donation.user.address), class: 'ks-text-link' %> <%= sats_to_btc donation.amount_sats %> <% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %> <% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %>
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
User<%= link_to @donation.user.address, admin_user_path(@donation.user.address), class: 'ks-text-link' %>
Amount sats<%= @donation.amount_sats %>
Amount EUR<%= @donation.amount_eur %>
Amount USD<%= @donation.amount_usd %>
Public name<%= @donation.public_name %>
Date<%= @donation.paid_at.strftime("%Y-%m-%d (%H:%M UTC)") %>
+
-

- Amount sats: - <%= @donation.amount_sats %> -

- -

- Amount eur: - <%= @donation.amount_eur %> -

- -

- Amount usd: - <%= @donation.amount_usd %> -

- -

- Public name: - <%= @donation.public_name %> -

- -

- Date: - <%= @donation.paid_at %> -

- -

- <%= link_to 'Edit', edit_admin_donation_path(@donation), class: 'ks-text-link' %> | - <%= link_to 'Back', admin_donations_path, class: 'ks-text-link' %> -

+
+

+ <%= link_to 'Edit', edit_admin_donation_path(@donation), class: 'btn-md btn-blue mr-1' %> + <%= link_to 'Back', admin_donations_path, class: 'btn-md btn-gray' %> +

+
<% end %> diff --git a/app/views/admin/invitations/index.html.erb b/app/views/admin/invitations/index.html.erb index 1bc5517..51905c0 100644 --- a/app/views/admin/invitations/index.html.erb +++ b/app/views/admin/invitations/index.html.erb @@ -24,7 +24,7 @@ <% if @invitations_used.any? %>

Recently Accepted

- +
@@ -38,8 +38,8 @@ - - + + <% end %> diff --git a/app/views/admin/lightning/index.html.erb b/app/views/admin/lightning/index.html.erb index 2c099cb..8cb0757 100644 --- a/app/views/admin/lightning/index.html.erb +++ b/app/views/admin/lightning/index.html.erb @@ -20,7 +20,7 @@

Accounts

-
Token
<%= invitation.token %> <%= invitation.used_at.strftime("%Y-%m-%d (%H:%M UTC)") %><%= invitation.user.address %><%= User.find(invitation.invited_user_id).address %><%= link_to invitation.user.address, admin_user_path(invitation.user.address), class: "ks-text-link" %><%= link_to invitation.invitee.address, admin_user_path(invitation.invitee.address), class: "ks-text-link" %>
+
@@ -36,7 +36,7 @@ diff --git a/app/views/admin/settings/registrations/index.html.erb b/app/views/admin/settings/registrations/index.html.erb index 2131e41..68e1827 100644 --- a/app/views/admin/settings/registrations/index.html.erb +++ b/app/views/admin/settings/registrations/index.html.erb @@ -22,14 +22,14 @@ <%= f.text_area :reserved_usernames, value: Setting.reserved_usernames.join("\n"), class: "h-44 mb-2" %> -

+

One username per line

-

+

<%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>

diff --git a/app/views/admin/settings/services/index.html.erb b/app/views/admin/settings/services/index.html.erb index c0dad64..a4a4fec 100644 --- a/app/views/admin/settings/services/index.html.erb +++ b/app/views/admin/settings/services/index.html.erb @@ -18,7 +18,7 @@
  • -

    LNDHub configuration present and wallet features enabled

    +

    LNDHub configuration present and wallet features enabled

    <%= f.check_box :lndhub_enabled, checked: Setting.lndhub_enabled?, disabled: true, @@ -27,7 +27,7 @@
  • -

    LNDHub database configuration present and admin panel enabled

    +

    LNDHub database configuration present and admin panel enabled

    <%= f.check_box :lndhub_admin_enabled, checked: Setting.lndhub_admin_enabled?, disabled: true, diff --git a/app/views/admin/ldap_users/index.html.erb b/app/views/admin/users/index.html.erb similarity index 64% rename from app/views/admin/ldap_users/index.html.erb rename to app/views/admin/users/index.html.erb index e39bd6f..9e60ac7 100644 --- a/app/views/admin/ldap_users/index.html.erb +++ b/app/views/admin/users/index.html.erb @@ -1,4 +1,4 @@ -<%= render HeaderComponent.new(title: "LDAP Users: #{@ou}") %> +<%= render HeaderComponent.new(title: "Users: #{@ou}") %> <%= render MainSimpleComponent.new do %>
    @@ -22,7 +22,7 @@
      <% @orgs.each do |org| %>
    • - <%= link_to org[:ou], admin_ldap_users_path(ou: org[:ou]), class: "ks-text-link" %> + <%= link_to org[:ou], admin_users_path(ou: org[:ou]), class: "ks-text-link" %>
    • <% end %>
    @@ -30,22 +30,21 @@ <% end %>
    -
  • LN Account <% if user = @users.find{ |u| u[2] == account.login } %> - <%= "#{user[0]}@#{user[1]}" %> + <%= link_to "#{user[0]}@#{user[1]}", admin_user_path("#{user[0]}@#{user[1]}"), class: "ks-text-link" %> <% end %> <%= number_with_delimiter account.balance.to_i.to_s %>
    +
    - - + + - <% @entries.each do |entry| %> + <% @users.each do |user| %> - - - - + + + <% end %> diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb new file mode 100644 index 0000000..126aed9 --- /dev/null +++ b/app/views/admin/users/show.html.erb @@ -0,0 +1,89 @@ +<%= render HeaderComponent.new(title: "User: #{@user.address}") %> + +<%= render MainSimpleComponent.new do %> +
    +

    Account

    +
    UIDE-MailAdminStatusRoles
    <%= entry[:uid] %><%= entry[:mail] %><%= entry[:admin] %><%= link_to(user.cn, admin_user_path(user.address), class: 'ks-text-link') %><%= user.confirmed_at.nil? ? badge("pending", :yellow) : "" %><%= user.is_admin? ? badge("admin", :red) : "" %>
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Created at<%= @user.created_at.strftime("%Y-%m-%d (%H:%M UTC)") %>
    Confirmed at + <% if @user.confirmed_at %> + <%= @user.confirmed_at.strftime("%Y-%m-%d (%H:%M UTC)") %> + <% else %> + <%= badge "pending", :yellow %> + <% end %> +
    Email<%= @user.email %>
    Roles<%= @user.is_admin? ? badge("admin", :red) : "—" %>
    Invited by + <% if @user.inviter %> + <%= link_to @user.inviter.address, admin_user_path(@user.inviter.address), class: 'ks-text-link' %> + <% else %>—<% end %> +
    Invitations available + <%= @user.invitations.count %> +
    Invited users + <% if @user.invitees.length > 0 %> +
      + <% @user.invitees.order(cn: :asc).each do |invitee| %> +
    • <%= link_to invitee.address, admin_user_path(invitee.address), class: 'ks-text-link' %>
    • + <% end %> +
    + <% else %>—<% end %> +
    +
    + + <% if Setting.lndhub_admin_enabled? %> +
    +

    LndHub

    + <% if @lndhub_user %> + + + + + + + + + + + + + + + + + + + +
    AccountBalanceIncomingOutgoingFees
    <%= @user.ln_account %><%= number_with_delimiter @lndhub_user.balance %> sats<%= number_with_delimiter @lndhub_user.sum_incoming %> sats<%= number_with_delimiter @lndhub_user.sum_outgoing %> sats<%= number_with_delimiter @lndhub_user.sum_fees %> sats
    + <% else %> +

    No LndHub user found for account <%= @user.ln_account %>. + <% end %> +

    + <% end %> +<% end %> diff --git a/app/views/shared/_admin_nav.html.erb b/app/views/shared/_admin_nav.html.erb index dd8c8b8..7762431 100644 --- a/app/views/shared/_admin_nav.html.erb +++ b/app/views/shared/_admin_nav.html.erb @@ -1,7 +1,7 @@ <%= link_to "Dashboard", admin_root_path, class: main_nav_class(@current_section, :dashboard) %> -<%= link_to "Users", admin_ldap_users_path, - class: main_nav_class(@current_section, :ldap_users) %> +<%= link_to "Users", admin_users_path, + class: main_nav_class(@current_section, :users) %> <%= link_to "Invitations", admin_invitations_path, class: main_nav_class(@current_section, :invitations) %> <%= link_to "Donations", admin_donations_path, diff --git a/config/routes.rb b/config/routes.rb index 7559393..ee16ee8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -39,7 +39,7 @@ Rails.application.routes.draw do namespace :admin do root to: 'dashboard#index' - get 'ldap_users', to: 'ldap_users#index' + resources 'users', param: 'address', only: ['index', 'show'], constraints: { address: /.*/ } get 'invitations', to: 'invitations#index' resources :donations get 'lightning', to: 'lightning#index' diff --git a/tailwind.config.js b/tailwind.config.js index 20a464f..a86d1b2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,6 +7,15 @@ module.exports = { './app/helpers/**/*.rb', './app/javascript/**/*.js' ], + safelist: [ + 'bg-gray-100', 'text-gray-800', + 'bg-red-100', 'text-red-800', + 'bg-yellow-100', 'text-yellow-800', + 'bg-green-100', 'text-green-800', + 'bg-blue-100', 'text-blue-800', + 'bg-purple-100', 'text-purple-800', + 'bg-pink-100', 'text-pink-800', + ], theme: { extend: { fontFamily: { @@ -16,5 +25,5 @@ module.exports = { }, plugins: [ require('@tailwindcss/forms') - ], + ] }