Compare commits
6 Commits
feature/ld
...
4ee6bfddfa
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ee6bfddfa | |||
|
8b60890061
|
|||
|
0367450c4b
|
|||
|
e6f5623c7f
|
|||
| 367f566ccb | |||
|
80e69df75c
|
@@ -1,7 +1,7 @@
|
|||||||
class CreateLdapUserJob < ApplicationJob
|
class CreateLdapUserJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(username, domain, email, hashed_pw)
|
def perform(username:, domain:, email:, hashed_pw:, confirmed: false)
|
||||||
dn = "cn=#{username},ou=#{domain},cn=users,dc=kosmos,dc=org"
|
dn = "cn=#{username},ou=#{domain},cn=users,dc=kosmos,dc=org"
|
||||||
attr = {
|
attr = {
|
||||||
objectclass: ["top", "account", "person", "extensibleObject"],
|
objectclass: ["top", "account", "person", "extensibleObject"],
|
||||||
@@ -12,6 +12,10 @@ class CreateLdapUserJob < ApplicationJob
|
|||||||
userPassword: hashed_pw
|
userPassword: hashed_pw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if confirmed
|
||||||
|
attr[:serviceEnabled] = Setting.default_services
|
||||||
|
end
|
||||||
|
|
||||||
ldap_client.add(dn: dn, attributes: attr)
|
ldap_client.add(dn: dn, attributes: attr)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -206,4 +206,9 @@ class Setting < RailsSettings::Base
|
|||||||
#
|
#
|
||||||
# field :email_imap_port, type: :string,
|
# field :email_imap_port, type: :string,
|
||||||
# default: ENV["EMAIL_IMAP_PORT"].presence || 993
|
# default: ENV["EMAIL_IMAP_PORT"].presence || 993
|
||||||
|
|
||||||
|
def self.default_services
|
||||||
|
# TODO Make configurable from respective service settings page
|
||||||
|
%w[ discourse gitea mastodon mediawiki xmpp ]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -93,9 +93,7 @@ class User < ApplicationRecord
|
|||||||
LdapManager::UpdateEmail.call(dn: self.dn, address: self.email)
|
LdapManager::UpdateEmail.call(dn: self.dn, address: self.email)
|
||||||
else
|
else
|
||||||
# E-Mail from signup confirmed (i.e. account activation)
|
# E-Mail from signup confirmed (i.e. account activation)
|
||||||
|
enable_default_services
|
||||||
# TODO Make configurable, only activate globally enabled services
|
|
||||||
enable_service %w[ discourse gitea mediawiki xmpp ]
|
|
||||||
|
|
||||||
# TODO enable in development when we have easy setup of ejabberd etc.
|
# TODO enable in development when we have easy setup of ejabberd etc.
|
||||||
return if Rails.env.development? || !Setting.ejabberd_enabled?
|
return if Rails.env.development? || !Setting.ejabberd_enabled?
|
||||||
@@ -133,7 +131,7 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
def mastodon_address
|
def mastodon_address
|
||||||
return nil unless Setting.mastodon_enabled?
|
return nil unless Setting.mastodon_enabled?
|
||||||
"#{self.cn}@#{Setting.mastodon_address_domain}"
|
"#{self.cn.gsub("-", "_")}@#{Setting.mastodon_address_domain}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_attribute?(attribute_name)
|
def valid_attribute?(attribute_name)
|
||||||
@@ -141,6 +139,10 @@ class User < ApplicationRecord
|
|||||||
self.errors[attribute_name].blank?
|
self.errors[attribute_name].blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def enable_default_services
|
||||||
|
enable_service Setting.default_services
|
||||||
|
end
|
||||||
|
|
||||||
def ln_create_invoice(payload)
|
def ln_create_invoice(payload)
|
||||||
lndhub = Lndhub.new
|
lndhub = Lndhub.new
|
||||||
lndhub.authenticate self
|
lndhub.authenticate self
|
||||||
|
|||||||
@@ -35,11 +35,15 @@ class CreateAccount < ApplicationService
|
|||||||
@invitation.update! invited_user_id: user_id, used_at: DateTime.now
|
@invitation.update! invited_user_id: user_id, used_at: DateTime.now
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO move to confirmation
|
|
||||||
# (and/or add email_confirmed to entry and use in login filter)
|
|
||||||
def add_ldap_document
|
def add_ldap_document
|
||||||
hashed_pw = Devise.ldap_auth_password_builder.call(@password)
|
hashed_pw = Devise.ldap_auth_password_builder.call(@password)
|
||||||
CreateLdapUserJob.perform_later(@username, @domain, @email, hashed_pw)
|
CreateLdapUserJob.perform_later(
|
||||||
|
username: @username,
|
||||||
|
domain: @domain,
|
||||||
|
email: @email,
|
||||||
|
hashed_pw: hashed_pw,
|
||||||
|
confirmed: @confirmed
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_lndhub_account(user)
|
def create_lndhub_account(user)
|
||||||
|
|||||||
@@ -98,7 +98,17 @@
|
|||||||
description: "The official Web app",
|
description: "The official Web app",
|
||||||
icon_path: "/img/logos/icon_mastodon-2.svg",
|
icon_path: "/img/logos/icon_mastodon-2.svg",
|
||||||
links: [
|
links: [
|
||||||
["Launch", "https://kosmos.social"]
|
["Launch", "https://kosmos.social"],
|
||||||
|
["GitHub", "https://github.com/mastodon/mastodon"]
|
||||||
|
]
|
||||||
|
) %>
|
||||||
|
<%= render AppInfoComponent.new(
|
||||||
|
name: "Phanpy",
|
||||||
|
description: " A slick, feature-rich Web app for mobile and desktop",
|
||||||
|
icon_path: "/img/logos/icon_phanpy.svg",
|
||||||
|
links: [
|
||||||
|
["Launch", "https://phanpy.social"],
|
||||||
|
["GitHub", "https://github.com/cheeaun/phanpy"]
|
||||||
]
|
]
|
||||||
) %>
|
) %>
|
||||||
<%= render AppInfoComponent.new(
|
<%= render AppInfoComponent.new(
|
||||||
@@ -150,6 +160,15 @@
|
|||||||
["Google Play", "https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"]
|
["Google Play", "https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"]
|
||||||
]
|
]
|
||||||
) %>
|
) %>
|
||||||
|
<%= render AppInfoComponent.new(
|
||||||
|
name: "Phanpy",
|
||||||
|
description: " A slick, feature-rich Web app for mobile and desktop",
|
||||||
|
icon_path: "/img/logos/icon_phanpy.svg",
|
||||||
|
links: [
|
||||||
|
["Launch", "https://phanpy.social"],
|
||||||
|
["GitHub", "https://github.com/cheeaun/phanpy"]
|
||||||
|
]
|
||||||
|
) %>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
|
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
|
||||||
<%= render AppInfoComponent.new(
|
<%= render AppInfoComponent.new(
|
||||||
@@ -180,6 +199,15 @@
|
|||||||
["App Store", "https://apps.apple.com/app/mammoth-for-mastodon/id1667573899"]
|
["App Store", "https://apps.apple.com/app/mammoth-for-mastodon/id1667573899"]
|
||||||
]
|
]
|
||||||
) %>
|
) %>
|
||||||
|
<%= render AppInfoComponent.new(
|
||||||
|
name: "Phanpy",
|
||||||
|
description: " A slick, feature-rich Web app for mobile and desktop",
|
||||||
|
icon_path: "/img/logos/icon_phanpy.svg",
|
||||||
|
links: [
|
||||||
|
["Launch", "https://phanpy.social"],
|
||||||
|
["GitHub", "https://github.com/cheeaun/phanpy"]
|
||||||
|
]
|
||||||
|
) %>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
|
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
|
||||||
<%= render AppInfoComponent.new(
|
<%= render AppInfoComponent.new(
|
||||||
|
|||||||
67
public/img/logos/icon_phanpy.svg
Normal file
67
public/img/logos/icon_phanpy.svg
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="54"
|
||||||
|
height="54"
|
||||||
|
viewBox="0 0 54 54"
|
||||||
|
version="1.1"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="icon_phanpy.svg"
|
||||||
|
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:serif="http://www.serif.com/"><defs
|
||||||
|
id="defs4" /><sodipodi:namedview
|
||||||
|
id="namedview4"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="16.359375"
|
||||||
|
inkscape:cx="26.192932"
|
||||||
|
inkscape:cy="24.542502"
|
||||||
|
inkscape:window-width="2160"
|
||||||
|
inkscape:window-height="1281"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<rect
|
||||||
|
id="Logo-simple"
|
||||||
|
serif:id="Logo simple"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="63.993999"
|
||||||
|
height="63.993999"
|
||||||
|
style="fill:none" />
|
||||||
|
<g
|
||||||
|
id="Logo-simple1"
|
||||||
|
serif:id="Logo simple"
|
||||||
|
transform="translate(-5.123639,-4.9968626)">
|
||||||
|
<g
|
||||||
|
id="g4">
|
||||||
|
<path
|
||||||
|
d="m 37.774,11.471 c 14.639,3.752 19.034,16.557 15.889,31.304 -0.696,3.261 -2.563,6.661 -6.356,8.693 -3.204,1.717 -8.07,2.537 -15.338,0.55 0,0 -9.634,-2.404 -9.634,-2.404 C 11.651,46.992 8.378,38.733 10.027,31.823 13.654,16.622 25.57,8.343 37.774,11.471 Z"
|
||||||
|
style="fill:#a4bff7"
|
||||||
|
id="path1" />
|
||||||
|
<path
|
||||||
|
d="m 36.76,15.429 c 12.289,3.15 15.547,14.114 12.907,26.493 -0.947,4.44 -4.937,9.365 -16.664,6.143 L 23.319,45.648 C 15.465,43.725 12.789,37.848 14.001,32.771 17.017,20.132 26.612,12.828 36.76,15.429 Z"
|
||||||
|
style="fill:#d8e7fe"
|
||||||
|
id="path2" />
|
||||||
|
<path
|
||||||
|
d="m 27.471,24.991 c -1.457,-0.698 -7.229,3.213 -7.663,8.926 -0.182,2.39 4.55,3.237 5.071,-0.169 0.725,-4.743 3.715,-8.218 2.592,-8.757 z"
|
||||||
|
style="fill:#6081e6"
|
||||||
|
id="path3" />
|
||||||
|
<path
|
||||||
|
d="m 38.217,26.996 c -2.083,0.327 -0.382,5.901 -0.595,10.727 -0.123,2.8 4.388,3.464 4.703,2.011 1.098,-5.073 -2.066,-13.058 -4.108,-12.738 z"
|
||||||
|
style="fill:#6081e6"
|
||||||
|
id="path4" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -3,12 +3,24 @@ require 'rails_helper'
|
|||||||
RSpec.describe CreateLdapUserJob, type: :job do
|
RSpec.describe CreateLdapUserJob, type: :job do
|
||||||
let(:ldap_client_mock) { instance_double(Net::LDAP) }
|
let(:ldap_client_mock) { instance_double(Net::LDAP) }
|
||||||
|
|
||||||
subject(:job) {
|
before do
|
||||||
allow_any_instance_of(described_class).to receive(:ldap_client).and_return(ldap_client_mock)
|
allow_any_instance_of(described_class).to receive(:ldap_client).and_return(ldap_client_mock)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject(:job) {
|
||||||
described_class.perform_later(
|
described_class.perform_later(
|
||||||
'halfinney', 'kosmos.org', 'halfinney@example.com',
|
username: 'halfinney', domain: 'kosmos.org',
|
||||||
'remember-remember-the-5th-of-november'
|
email: 'halfinney@example.com',
|
||||||
|
hashed_pw: 'remember-remember-the-5th-of-november'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject(:job_for_preconfirmed_account) {
|
||||||
|
described_class.perform_later(
|
||||||
|
username: 'halfinney', domain: 'kosmos.org',
|
||||||
|
email: 'halfinney@example.com',
|
||||||
|
hashed_pw: 'remember-remember-the-5th-of-november',
|
||||||
|
confirmed: true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +42,26 @@ RSpec.describe CreateLdapUserJob, type: :job do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "adds default services for pre-confirmed accounts" do
|
||||||
|
allow(ldap_client_mock).to receive(:add) # spy on mock
|
||||||
|
allow(Setting).to receive(:default_services).and_return(["xmpp", "discourse"])
|
||||||
|
|
||||||
|
perform_enqueued_jobs { job_for_preconfirmed_account }
|
||||||
|
|
||||||
|
expect(ldap_client_mock).to have_received(:add).with(
|
||||||
|
dn: "cn=halfinney,ou=kosmos.org,cn=users,dc=kosmos,dc=org",
|
||||||
|
attributes: {
|
||||||
|
objectclass: ["top", "account", "person", "extensibleObject"],
|
||||||
|
cn: "halfinney",
|
||||||
|
sn: "halfinney",
|
||||||
|
uid: "halfinney",
|
||||||
|
mail: "halfinney@example.com",
|
||||||
|
serviceEnabled: ["xmpp", "discourse"],
|
||||||
|
userPassword: "remember-remember-the-5th-of-november"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
clear_enqueued_jobs
|
clear_enqueued_jobs
|
||||||
clear_performed_jobs
|
clear_performed_jobs
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ RSpec.describe User, type: :model do
|
|||||||
expect(user.mastodon_address).to eq("jimmy@kosmos.social")
|
expect(user.mastodon_address).to eq("jimmy@kosmos.social")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "username contains hyphen/dash" do
|
||||||
|
let(:jammy) { build :user, cn: "jammy-jellyfish", ou: "kosmos.org" }
|
||||||
|
|
||||||
|
it "returns the user address" do
|
||||||
|
expect(jammy.mastodon_address).to eq("jammy_jellyfish@kosmos.org")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -147,7 +155,7 @@ RSpec.describe User, type: :model do
|
|||||||
after { clear_enqueued_jobs }
|
after { clear_enqueued_jobs }
|
||||||
|
|
||||||
it "enables default services" do
|
it "enables default services" do
|
||||||
expect(user).to receive(:enable_service).with(%w[ discourse gitea mediawiki xmpp ])
|
expect(user).to receive(:enable_service).with(%w[ discourse gitea mastodon mediawiki xmpp ])
|
||||||
user.send :devise_after_confirmation
|
user.send :devise_after_confirmation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -53,11 +53,32 @@ RSpec.describe CreateAccount, type: :model do
|
|||||||
|
|
||||||
expect(enqueued_jobs.size).to eq(1)
|
expect(enqueued_jobs.size).to eq(1)
|
||||||
|
|
||||||
args = enqueued_jobs.first['arguments']
|
args = enqueued_jobs.first['arguments'][0]
|
||||||
expect(args[0]).to eq('halfinney')
|
expect(args["username"]).to eq('halfinney')
|
||||||
expect(args[1]).to eq('kosmos.org')
|
expect(args["domain"]).to eq('kosmos.org')
|
||||||
expect(args[2]).to eq('halfinney@example.com')
|
expect(args["email"]).to eq('halfinney@example.com')
|
||||||
expect(args[3]).to match(/^{SSHA512}.{171}=/)
|
expect(args["hashed_pw"]).to match(/^{SSHA512}.{171}=/)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
clear_enqueued_jobs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#add_ldap_document for pre-confirmed account" do
|
||||||
|
include ActiveJob::TestHelper
|
||||||
|
|
||||||
|
let(:service) { CreateAccount.new(account: {
|
||||||
|
username: 'halfinney',
|
||||||
|
email: 'halfinney@example.com',
|
||||||
|
password: 'remember-remember-the-5th-of-november',
|
||||||
|
confirmed: true
|
||||||
|
})}
|
||||||
|
|
||||||
|
it "enqueues a job to create the LDAP user document" do
|
||||||
|
service.send(:add_ldap_document)
|
||||||
|
args = enqueued_jobs.first['arguments'][0]
|
||||||
|
expect(args["confirmed"]).to be(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
|||||||
Reference in New Issue
Block a user