diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 2081e7a..7544f55 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -18,6 +18,8 @@ class Admin::UsersController < Admin::BaseController
if Setting.lndhub_admin_enabled?
@lndhub_user = @user.lndhub_user
end
+
+ @services_enabled = @user.services_enabled
end
private
diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb
new file mode 100644
index 0000000..340b538
--- /dev/null
+++ b/app/controllers/users/confirmations_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Users::ConfirmationsController < Devise::ConfirmationsController
+ # GET /resource/confirmation?confirmation_token=abcdef
+ def show
+ self.resource = resource_class.confirm_by_token(params[:confirmation_token])
+ yield resource if block_given?
+
+ if resource.errors.empty?
+ set_flash_message!(:success, :confirmed)
+ resource.devise_after_confirmation
+ respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
+ else
+ respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
+ end
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 3c4be54..31599c4 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -42,9 +42,9 @@ class User < ApplicationRecord
def ldap_before_save
self.email = Devise::LDAP::Adapter.get_ldap_param(self.cn, "mail").first
-
- dn = Devise::LDAP::Adapter.get_ldap_param(self.cn, "dn")
- self.ou = dn.split(',').select{|e| e[0..1] == "ou"}.first.delete_prefix("ou=")
+ self.ou = dn.split(',')
+ .select{|e| e[0..1] == "ou"}.first
+ .delete_prefix("ou=")
if self.confirmed_at.blank? && self.confirmation_token.blank?
# User had an account with a trusted email address before akkounts was a thing
@@ -52,6 +52,10 @@ class User < ApplicationRecord
end
end
+ def devise_after_confirmation
+ enable_service %w[discourse gitea wiki xmpp]
+ end
+
def reset_password(new_password, new_password_confirmation)
self.password = new_password
self.password_confirmation = new_password_confirmation
@@ -70,12 +74,6 @@ 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
@@ -90,4 +88,42 @@ class User < ApplicationRecord
lndhub.authenticate self
lndhub.addinvoice payload
end
+
+ def dn
+ return @dn if defined?(@dn)
+ @dn = Devise::LDAP::Adapter.get_dn(self.cn)
+ end
+
+ def ldap_entry
+ ldap.fetch_users(uid: self.cn, ou: self.ou).first
+ end
+
+ def services_enabled
+ ldap_entry[:service] || []
+ end
+
+ def enable_service(service)
+ current_services = services_enabled
+ new_services = Array(service).map(&:to_s)
+ services = (current_services + new_services).uniq
+ ldap.replace_attribute(dn, :service, services)
+ end
+
+ def disable_service(service)
+ current_services = services_enabled
+ disabled_services = Array(service).map(&:to_s)
+ services = (current_services - disabled_services).uniq
+ ldap.replace_attribute(dn, :service, services)
+ end
+
+ def disable_all_services
+ ldap.delete_attribute(dn,:service)
+ end
+
+ private
+
+ def ldap
+ return @ldap_service if defined?(@ldap_service)
+ @ldap_service = LdapService.new
+ end
end
diff --git a/app/services/ldap_service.rb b/app/services/ldap_service.rb
index baff4c9..5a572c5 100644
--- a/app/services/ldap_service.rb
+++ b/app/services/ldap_service.rb
@@ -3,6 +3,18 @@ class LdapService < ApplicationService
@suffix = ENV["LDAP_SUFFIX"] || "dc=kosmos,dc=org"
end
+ def add_attribute(dn, attr, values)
+ ldap_client.add_attribute dn, attr, values
+ end
+
+ def replace_attribute(dn, attr, values)
+ ldap_client.replace_attribute dn, attr, values
+ end
+
+ def delete_attribute(dn, attr)
+ ldap_client.delete_attribute dn, attr
+ end
+
def add_entry(dn, attrs, interactive=false)
puts "Adding entry: #{dn}" if interactive
res = ldap_client.add dn: dn, attributes: attrs
@@ -10,10 +22,6 @@ class LdapService < ApplicationService
res
end
- def add_attribute(dn, attr, value)
- ldap_client.add_attribute dn, attr, value
- end
-
def delete_entry(dn, interactive=false)
puts "Deleting entry: #{dn}" if interactive
res = ldap_client.delete dn: dn
@@ -42,18 +50,17 @@ class LdapService < ApplicationService
treebase = ldap_config["base"]
end
- attributes = %w{dn cn uid mail admin}
+ attributes = %w{dn cn uid mail admin service}
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] }
-
entries = entries.collect do |e|
{
uid: e.uid.first,
mail: e.try(:mail) ? e.mail.first : nil,
- admin: e.try(:admin) ? 'admin' : nil
- # password: e.userpassword.first
+ admin: e.try(:admin) ? 'admin' : nil,
+ service: e.try(:service)
}
end
end
@@ -131,5 +138,4 @@ class LdapService < ApplicationService
def ldap_config
ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env]
end
-
end
diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb
index 126aed9..4679e6f 100644
--- a/app/views/admin/users/show.html.erb
+++ b/app/views/admin/users/show.html.erb
@@ -1,63 +1,97 @@
<%= render HeaderComponent.new(title: "User: #{@user.address}") %>
<%= render MainSimpleComponent.new do %>
+
+
+ Account
+
+
+
+ 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 %>
+ |
+
+
+
+
+
+
+
+
- Account
-
+ Services
+
- Created at |
- <%= @user.created_at.strftime("%Y-%m-%d (%H:%M UTC)") %> |
+ Discourse |
+ <%= check_box_tag 'service_discourse', 'enabled', @services_enabled.include?("discourse"), disabled: true %> |
- Confirmed at |
-
- <% if @user.confirmed_at %>
- <%= @user.confirmed_at.strftime("%Y-%m-%d (%H:%M UTC)") %>
- <% else %>
- <%= badge "pending", :yellow %>
- <% end %>
- |
+ Gitea |
+ <%= check_box_tag 'service_gitea', 'enabled', @services_enabled.include?("gitea"), disabled: true %> |
- Email |
- <%= @user.email %> |
+ Mastodon |
+ <%= check_box_tag 'service_mastodon', 'enabled', @services_enabled.include?("mastodon"), disabled: true %> |
- Roles |
- <%= @user.is_admin? ? badge("admin", :red) : "—" %> |
+ Wiki |
+ <%= check_box_tag 'service_wiki', 'enabled', @services_enabled.include?("wiki"), disabled: true %> |
- 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 %>
- |
+ XMPP |
+ <%= check_box_tag 'service_xmpp', 'enabled', @services_enabled.include?("xmpp"), disabled: true %> |
- <% if Setting.lndhub_admin_enabled? %>
+ <% if Setting.lndhub_admin_enabled? && @user.confirmed? %>
LndHub
<% if @lndhub_user %>
diff --git a/config/routes.rb b/config/routes.rb
index ee16ee8..e137a92 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,7 @@
require 'sidekiq/web'
Rails.application.routes.draw do
- devise_for :users
+ devise_for :users, :controllers => { :confirmations => "users/confirmations" }
get 'welcome', to: 'welcome#index'
get 'check_your_email', to: 'welcome#check_your_email'
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index ed135d9..b1724f1 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1,7 +1,16 @@
require 'rails_helper'
RSpec.describe User, type: :model do
- let(:user) { create :user }
+ let(:user) { create :user, cn: "philipp" }
+ let(:dn) { "cn=philipp,ou=kosmos.org,cn=users,dc=kosmos,dc=org" }
+
+ describe "#address" do
+ let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
+
+ it "returns the user address" do
+ expect(user.address).to eq("jimmy@kosmos.org")
+ end
+ end
describe "#is_admin?" do
it "returns true when admin flag is set in LDAP" do
@@ -21,11 +30,75 @@ RSpec.describe User, type: :model do
end
end
- describe "#address" do
- let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
-
- it "returns the user address" do
- expect(user.address).to eq("jimmy@kosmos.org")
+ describe "#services_enabled" do
+ it "returns the entries from the LDAP service attribute" do
+ expect(user).to receive(:ldap_entry).and_return({
+ uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
+ service: ["discourse", "gitea", "wiki", "xmpp"]
+ })
+ expect(user.services_enabled).to eq(["discourse", "gitea", "wiki", "xmpp"])
end
end
+
+ describe "#enable_service" do
+ before do
+ allow(user).to receive(:ldap_entry).and_return({
+ uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
+ service: ["discourse", "gitea"]
+ })
+ allow(user).to receive(:dn).and_return(dn)
+ end
+
+ it "adds the service to the LDAP entry" do
+ expect_any_instance_of(LdapService).to receive(:replace_attribute)
+ .with(dn, :service, ["discourse", "gitea", "wiki"]).and_return(true)
+
+ user.enable_service(:wiki)
+ end
+
+ it "adds multiple service to the LDAP entry" do
+ expect_any_instance_of(LdapService).to receive(:replace_attribute)
+ .with(dn, :service, ["discourse", "gitea", "wiki", "xmpp"]).and_return(true)
+
+ user.enable_service([:wiki, :xmpp])
+ end
+ end
+
+ describe "#disable_service" do
+ before do
+ allow(user).to receive(:ldap_entry).and_return({
+ uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
+ service: ["discourse", "gitea", "xmpp"]
+ })
+ allow(user).to receive(:dn).and_return(dn)
+ end
+
+ it "removes the service from the LDAP entry" do
+ expect_any_instance_of(LdapService).to receive(:replace_attribute)
+ .with(dn, :service, ["discourse", "gitea"]).and_return(true)
+
+ user.disable_service(:xmpp)
+ end
+
+ it "removes multiple services from the LDAP entry" do
+ expect_any_instance_of(LdapService).to receive(:replace_attribute)
+ .with(dn, :service, ["discourse"]).and_return(true)
+
+ user.disable_service([:xmpp, "gitea"])
+ end
+ end
+
+ describe "#disable_all_services" do
+ before do
+ allow(user).to receive(:dn).and_return(dn)
+ end
+
+ it "removes all services from the LDAP entry" do
+ expect_any_instance_of(LdapService).to receive(:delete_attribute)
+ .with(dn, :service).and_return(true)
+
+ user.disable_all_services
+ end
+ end
+
end