diaspora-vines 0.1.22 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/conf/config.rb +3 -5
- data/lib/vines.rb +14 -12
- data/lib/vines/cli.rb +5 -34
- data/lib/vines/command/start.rb +1 -1
- data/lib/vines/config.rb +7 -16
- data/lib/vines/config/diaspora.rb +35 -0
- data/lib/vines/config/host.rb +8 -5
- data/lib/vines/config/port.rb +6 -6
- data/lib/vines/stanza/iq/offline.rb +54 -0
- data/lib/vines/storage.rb +133 -121
- data/lib/vines/storage/sql.rb +7 -5
- data/lib/vines/store.rb +19 -7
- data/lib/vines/stream.rb +81 -14
- data/lib/vines/stream/client.rb +10 -6
- data/lib/vines/stream/component.rb +3 -3
- data/lib/vines/stream/http.rb +35 -9
- data/lib/vines/stream/http/request.rb +26 -5
- data/lib/vines/stream/http/session.rb +8 -0
- data/lib/vines/stream/server.rb +13 -7
- data/lib/vines/version.rb +2 -2
- data/test/config/host_test.rb +26 -37
- data/test/config_test.rb +14 -0
- data/test/storage/sql_schema.rb +5 -2
- data/test/storage/{sql.rb → sql_test.rb} +72 -36
- data/test/stream/http/request_test.rb +45 -60
- metadata +8 -30
- data/lib/vines/command/bcrypt.rb +0 -12
- data/lib/vines/command/init.rb +0 -68
- data/lib/vines/command/ldap.rb +0 -38
- data/lib/vines/command/schema.rb +0 -24
- data/lib/vines/storage/ldap.rb +0 -71
- data/test/storage/ldap_test.rb +0 -201
- data/test/storage_test.rb +0 -85
- data/vines.gemspec +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33f5f3afd1563cc0deb0d6c01e2e4e106c080c1c
|
4
|
+
data.tar.gz: c9efd2b5249a1bae0c7b778b8c8450f4b77fa508
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28a8475282ff632df35a67467eb2650c38d7e91d8cf0fb952b151ee94e6d3372e298c20f5d459a57626d2cd105b6fd87789a0a7dcee7803b1146a016ab005a7
|
7
|
+
data.tar.gz: e4334b4750a2858ddc01c82be62a9a6d4af7036ca2e212d861d85fbffb280fe3c3c61844653cb693fd2cb65af72ffc077163d04931f0831b07d9bf754afaeff6
|
data/conf/config.rb
CHANGED
@@ -12,11 +12,9 @@ Vines::Config.configure do
|
|
12
12
|
# `vines init`.
|
13
13
|
certs 'conf/certs'
|
14
14
|
|
15
|
-
# Setup a pepper to generate the encrypted password.
|
16
|
-
pepper "065eb8798b181ff0ea2c5c16aee0ff8b70e04e2ee6bd6e08b49da46924223e39127d5335e466207d42bf2a045c12be5f90e92012a4f05f7fc6d9f3c875f4c95b"
|
17
|
-
|
18
15
|
host 'diaspora' do
|
19
16
|
cross_domain_messages true
|
17
|
+
accept_self_signed false
|
20
18
|
storage 'sql'
|
21
19
|
end
|
22
20
|
|
@@ -31,14 +29,14 @@ Vines::Config.configure do
|
|
31
29
|
# much larger than the setting for client-to-server.
|
32
30
|
server '0.0.0.0', 5269 do
|
33
31
|
max_stanza_size 131072
|
34
|
-
|
32
|
+
blacklist []
|
35
33
|
end
|
36
34
|
|
37
35
|
# Configure the built-in HTTP server that serves static files and responds to
|
38
36
|
# XEP-0124 BOSH requests. This allows HTTP clients to connect to
|
39
37
|
# the XMPP server.
|
40
38
|
http '0.0.0.0', 5280 do
|
41
|
-
bind '/
|
39
|
+
bind '/http-bind'
|
42
40
|
max_stanza_size 65536
|
43
41
|
max_resources_per_account 5
|
44
42
|
root 'public'
|
data/lib/vines.rb
CHANGED
@@ -54,12 +54,6 @@ module Vines
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
begin
|
58
|
-
# try to initialize diaspora configuration
|
59
|
-
require "#{Dir.pwd}/config/application.rb"
|
60
|
-
require "#{Dir.pwd}/config/load_config.rb"
|
61
|
-
rescue LoadError; end
|
62
|
-
|
63
57
|
%w[
|
64
58
|
active_record
|
65
59
|
base64
|
@@ -72,13 +66,13 @@ rescue LoadError; end
|
|
72
66
|
http/parser
|
73
67
|
json
|
74
68
|
logger
|
75
|
-
net/ldap
|
76
69
|
nokogiri
|
77
70
|
openssl
|
78
71
|
optparse
|
79
72
|
resolv
|
80
73
|
set
|
81
74
|
socket
|
75
|
+
uri
|
82
76
|
yaml
|
83
77
|
|
84
78
|
vines/cli
|
@@ -116,7 +110,6 @@ rescue LoadError; end
|
|
116
110
|
vines/stanza/pubsub/unsubscribe
|
117
111
|
|
118
112
|
vines/storage
|
119
|
-
vines/storage/ldap
|
120
113
|
vines/storage/local
|
121
114
|
vines/storage/sql
|
122
115
|
vines/storage/null
|
@@ -192,12 +185,21 @@ rescue LoadError; end
|
|
192
185
|
vines/stream/server/outbound/final_restart
|
193
186
|
vines/stream/server/outbound/final_features
|
194
187
|
|
195
|
-
vines/command/bcrypt
|
196
188
|
vines/command/cert
|
197
|
-
vines/command/init
|
198
|
-
vines/command/ldap
|
199
189
|
vines/command/restart
|
200
|
-
vines/command/schema
|
201
190
|
vines/command/start
|
202
191
|
vines/command/stop
|
203
192
|
].each {|f| require f }
|
193
|
+
|
194
|
+
# Try loading diaspora configuration
|
195
|
+
%w[
|
196
|
+
config/application.rb
|
197
|
+
config/load_config.rb
|
198
|
+
config/initializers/devise.rb
|
199
|
+
].each {|c|
|
200
|
+
begin
|
201
|
+
require "#{Dir.pwd}/#{c}"
|
202
|
+
rescue LoadError
|
203
|
+
puts "Was not able to load #{c}! This not a standalone version. You should use it only in a diaspora environment."
|
204
|
+
end
|
205
|
+
}
|
data/lib/vines/cli.rb
CHANGED
@@ -3,7 +3,7 @@ module Vines
|
|
3
3
|
# in the gem. Parses the command line arguments to create a new server
|
4
4
|
# directory, and starts and stops the server.
|
5
5
|
class CLI
|
6
|
-
COMMANDS = %w[start stop restart
|
6
|
+
COMMANDS = %w[start stop restart cert]
|
7
7
|
|
8
8
|
def self.start
|
9
9
|
self.new.start
|
@@ -14,36 +14,17 @@ module Vines
|
|
14
14
|
#
|
15
15
|
# Returns nothing.
|
16
16
|
def start
|
17
|
-
register_storage
|
18
17
|
opts = parse(ARGV)
|
19
|
-
check_config(opts)
|
20
18
|
command = Command.const_get(opts[:command].capitalize).new
|
21
19
|
begin
|
22
20
|
command.run(opts)
|
23
21
|
rescue SystemExit
|
24
22
|
# do nothing
|
25
|
-
rescue Exception => e
|
26
|
-
puts e.message
|
27
|
-
exit(1)
|
28
23
|
end
|
29
24
|
end
|
30
25
|
|
31
26
|
private
|
32
27
|
|
33
|
-
# Try to load various storage backends provided by vines-* gems and register
|
34
|
-
# them with the storage system for the config file to use.
|
35
|
-
#
|
36
|
-
# Returns nothing.
|
37
|
-
def register_storage
|
38
|
-
%w[couchdb mongodb redis sql].each do |backend|
|
39
|
-
begin
|
40
|
-
require 'vines/storage/%s' % backend
|
41
|
-
rescue LoadError
|
42
|
-
# do nothing
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
28
|
# Parse the command line arguments and run the matching sub-command
|
48
29
|
# (e.g. init, start, stop, etc).
|
49
30
|
#
|
@@ -110,22 +91,12 @@ module Vines
|
|
110
91
|
options.tap do |opts|
|
111
92
|
opts[:args] = args
|
112
93
|
opts[:command] = command
|
113
|
-
opts[:config] = File.expand_path("
|
94
|
+
opts[:config] = File.expand_path("conf/config.rb")
|
114
95
|
opts[:pid] = File.expand_path(opts[:pid])
|
115
96
|
opts[:log] = File.expand_path(opts[:log])
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# Many commands must be run in the context of a vines server directory
|
120
|
-
# created with `vines init`. If the command can't find the server's config
|
121
|
-
# file, print an error message and exit.
|
122
|
-
#
|
123
|
-
# Returns nothing.
|
124
|
-
def check_config(opts)
|
125
|
-
return if %w[bcrypt init].include?(opts[:command])
|
126
|
-
unless File.exists?(opts[:config])
|
127
|
-
puts "No config file found at #{opts[:config]}"
|
128
|
-
exit(1)
|
97
|
+
if defined? AppConfig
|
98
|
+
opts[:config] = "vines/config/diaspora"
|
99
|
+
end
|
129
100
|
end
|
130
101
|
end
|
131
102
|
end
|
data/lib/vines/command/start.rb
CHANGED
data/lib/vines/config.rb
CHANGED
@@ -21,7 +21,6 @@ module Vines
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def initialize(&block)
|
24
|
-
@pepper = "" # no pepper set
|
25
24
|
@certs = File.expand_path('conf/certs')
|
26
25
|
@vhosts, @ports, @cluster = {}, {}, nil
|
27
26
|
@null = Storage::Null.new
|
@@ -39,19 +38,11 @@ module Vines
|
|
39
38
|
dupes = names.uniq.size != names.size || (@vhosts.keys & names).any?
|
40
39
|
raise "one host definition per domain allowed" if dupes
|
41
40
|
names.each do |name|
|
42
|
-
|
43
|
-
@vhosts[domain_name] = Host.new(self, domain_name, &block)
|
44
|
-
else
|
45
|
-
@vhosts[name] = Host.new(self, name, &block)
|
46
|
-
end
|
41
|
+
@vhosts[name] = Host.new(self, name, &block)
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
50
|
-
def
|
51
|
-
pepper ? @pepper = pepper : @pepper
|
52
|
-
end
|
53
|
-
|
54
|
-
def domain_name
|
45
|
+
def diaspora_domain
|
55
46
|
AppConfig.environment.url
|
56
47
|
.gsub(/^http(s){0,1}:\/\/|\/$/, '')
|
57
48
|
.to_s rescue "localhost"
|
@@ -78,7 +69,7 @@ module Vines
|
|
78
69
|
unless File.exists?(file)
|
79
70
|
File.new(file, 'w') rescue raise "log directory doesn't exists"
|
80
71
|
end
|
81
|
-
|
72
|
+
|
82
73
|
if File.exists?(file)
|
83
74
|
Vines::Log.set_log_file(file)
|
84
75
|
end
|
@@ -158,10 +149,10 @@ module Vines
|
|
158
149
|
# Returns true if server-to-server connections are allowed with the
|
159
150
|
# given domain.
|
160
151
|
def s2s?(domain)
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
@ports[:server]
|
152
|
+
# Disabled whitelisting to allow anonymous hosts,
|
153
|
+
# otherwise everyone has to add manually all hosts.
|
154
|
+
# Using blacklist in case we have to block a malicious host.
|
155
|
+
@ports[:server] && !@ports[:server].blacklist.include?(domain.to_s)
|
165
156
|
end
|
166
157
|
|
167
158
|
# Return true if the server is a member of a cluster, serving the same
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# ############################################################## #
|
2
|
+
# Do NOT touch this file you'll find the options in diaspora.yml #
|
3
|
+
# ############################################################## #
|
4
|
+
|
5
|
+
Vines::Config.configure do
|
6
|
+
log AppConfig.chat.server.log.file.to_s do
|
7
|
+
level AppConfig.chat.server.log.level.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
certs AppConfig.chat.server.certs.to_s
|
11
|
+
|
12
|
+
host diaspora_domain do
|
13
|
+
cross_domain_messages AppConfig.chat.server.cross_domain_messages
|
14
|
+
accept_self_signed AppConfig.chat.server.accept_self_signed
|
15
|
+
storage 'sql'
|
16
|
+
end
|
17
|
+
|
18
|
+
client AppConfig.chat.server.c2s.address.to_s, AppConfig.chat.server.c2s.port.to_i do
|
19
|
+
max_stanza_size AppConfig.chat.server.c2s.max_stanza_size.to_i
|
20
|
+
max_resources_per_account AppConfig.chat.server.c2s.max_resources_per_account.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
server AppConfig.chat.server.s2s.address.to_s, AppConfig.chat.server.s2s.port.to_i do
|
24
|
+
max_stanza_size AppConfig.chat.server.s2s.max_stanza_size.to_i
|
25
|
+
blacklist AppConfig.chat.server.s2s.blacklist.get
|
26
|
+
end
|
27
|
+
|
28
|
+
http AppConfig.chat.server.bosh.address.to_s, AppConfig.chat.server.bosh.port.to_i do
|
29
|
+
bind AppConfig.chat.server.bosh.bind.to_s
|
30
|
+
max_stanza_size AppConfig.chat.server.bosh.max_stanza_size.to_i
|
31
|
+
max_resources_per_account AppConfig.chat.server.bosh.max_resources_per_account.to_i
|
32
|
+
root 'public'
|
33
|
+
vroute ''
|
34
|
+
end
|
35
|
+
end
|
data/lib/vines/config/host.rb
CHANGED
@@ -11,9 +11,10 @@ module Vines
|
|
11
11
|
|
12
12
|
def initialize(config, name, &block)
|
13
13
|
@config, @name = config, name.downcase
|
14
|
-
@storage
|
14
|
+
@storage = nil
|
15
15
|
@cross_domain_messages = false
|
16
16
|
@private_storage = false
|
17
|
+
@accept_self_signed = false
|
17
18
|
@components, @pubsubs = {}, {}
|
18
19
|
validate_domain(@name)
|
19
20
|
instance_eval(&block)
|
@@ -24,15 +25,17 @@ module Vines
|
|
24
25
|
if name
|
25
26
|
raise "one storage mechanism per host allowed" if @storage
|
26
27
|
@storage = Storage.from_name(name, &block)
|
27
|
-
@storage.ldap = @ldap
|
28
28
|
else
|
29
29
|
@storage
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
@
|
35
|
-
|
33
|
+
def accept_self_signed(enabled)
|
34
|
+
@accept_self_signed = !!enabled
|
35
|
+
end
|
36
|
+
|
37
|
+
def accept_self_signed?
|
38
|
+
@accept_self_signed
|
36
39
|
end
|
37
40
|
|
38
41
|
def cross_domain_messages(enabled)
|
data/lib/vines/config/port.rb
CHANGED
@@ -59,16 +59,16 @@ module Vines
|
|
59
59
|
|
60
60
|
class ServerPort < Port
|
61
61
|
def initialize(config, host='0.0.0.0', port=5269, &block)
|
62
|
-
@
|
62
|
+
@blacklist, @stream = [], Vines::Stream::Server
|
63
63
|
super(config, host, port, &block)
|
64
64
|
end
|
65
65
|
|
66
|
-
def
|
67
|
-
if
|
68
|
-
@
|
69
|
-
@
|
66
|
+
def blacklist(*blacklist)
|
67
|
+
if blacklist.any?
|
68
|
+
@blacklist << blacklist
|
69
|
+
@blacklist.flatten!
|
70
70
|
else
|
71
|
-
@
|
71
|
+
@blacklist
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
class Stanza
|
5
|
+
class Iq
|
6
|
+
class Ping < Iq
|
7
|
+
include Vines::Log
|
8
|
+
|
9
|
+
NS = NAMESPACES[:disco_info]
|
10
|
+
NODE = NAMESPACES[:offline]
|
11
|
+
|
12
|
+
register "/iq[@id and @type='get']/ns:offline", 'ns' => NODE
|
13
|
+
|
14
|
+
def process
|
15
|
+
log.debug("heelo world::#{to_result.to_yaml}")
|
16
|
+
#return if route_iq || !allowed?
|
17
|
+
#stream.write(to_result)
|
18
|
+
result = to_result.tap do |el|
|
19
|
+
el << el.document.create_element('query') do |query|
|
20
|
+
query.default_namespace = NS
|
21
|
+
query['node'] = NODE
|
22
|
+
items = [
|
23
|
+
[
|
24
|
+
:jid => 'romeo@montague.net',
|
25
|
+
:node => '2003-02-27T22:49:17.008Z',
|
26
|
+
:name => 'mercutio@shakespeare.lit/pda'
|
27
|
+
],
|
28
|
+
[
|
29
|
+
:jid => 'romeo@montague.net',
|
30
|
+
:node => '2003-02-27T22:52:51.270Z',
|
31
|
+
:name => 'juliet@capulet.com/balcony'
|
32
|
+
]
|
33
|
+
]
|
34
|
+
items(query, items)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
stream.write(result)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def items(query, *items)
|
43
|
+
items.flatten.each do |item|
|
44
|
+
query << query.document.create_element(
|
45
|
+
'item',
|
46
|
+
'jid' => item[:jid],
|
47
|
+
'node' => item[:node],
|
48
|
+
'name'=> item[:name])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/vines/storage.rb
CHANGED
@@ -4,12 +4,14 @@ module Vines
|
|
4
4
|
class Storage
|
5
5
|
include Vines::Log
|
6
6
|
|
7
|
-
attr_accessor :ldap
|
8
|
-
|
9
7
|
@@nicks = {}
|
10
8
|
|
11
9
|
# Register a nickname that can be used in the config file to specify this
|
12
10
|
# storage implementation.
|
11
|
+
#
|
12
|
+
# name - The String name for this storage backend.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
13
15
|
def self.register(name)
|
14
16
|
@@nicks[name.to_sym] = self
|
15
17
|
end
|
@@ -25,15 +27,18 @@ module Vines
|
|
25
27
|
# with blocking IO don't need to worry about threading or blocking the
|
26
28
|
# EventMachine reactor thread if they wrap their methods with this one.
|
27
29
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
30
|
+
# Examples
|
31
|
+
#
|
32
|
+
# def find_user(jid)
|
33
|
+
# some_blocking_lookup(jid)
|
34
|
+
# end
|
35
|
+
# defer :find_user
|
33
36
|
#
|
34
37
|
# Storage classes that use asynchronous IO (through an EventMachine
|
35
38
|
# enabled library like em-http-request or em-redis) don't need any special
|
36
39
|
# consideration and must not use this method.
|
40
|
+
#
|
41
|
+
# Returns nothing.
|
37
42
|
def self.defer(method)
|
38
43
|
old = instance_method(method)
|
39
44
|
define_method method do |*args|
|
@@ -45,40 +50,26 @@ module Vines
|
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
|
-
# Wrap an authenticate method with a new method that uses LDAP if it's
|
49
|
-
# enabled in the config file. If LDAP is not enabled, invoke the original
|
50
|
-
# authenticate method as usual. This allows storage classes to implement
|
51
|
-
# their native authentication logic and not worry about handling LDAP.
|
52
|
-
#
|
53
|
-
# For example:
|
54
|
-
# def authenticate(username, password)
|
55
|
-
# some_user_lookup_by_password(username, password)
|
56
|
-
# end
|
57
|
-
# wrap_ldap :authenticate
|
58
|
-
def self.wrap_ldap(method)
|
59
|
-
old = instance_method(method)
|
60
|
-
define_method method do |*args|
|
61
|
-
ldap? ? authenticate_with_ldap(*args) : old.bind(self).call(*args)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
53
|
# Wrap a method with Fiber yield and resume logic. The method must yield
|
66
54
|
# its result to a block. This makes it easier to write asynchronous
|
67
|
-
# implementations of
|
55
|
+
# implementations of `authenticate`, `find_user`, and `save_user` that
|
68
56
|
# block and return a result rather than yielding.
|
69
57
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
58
|
+
# Examples
|
59
|
+
#
|
60
|
+
# def find_user(jid)
|
61
|
+
# http = EM::HttpRequest.new(url).get
|
62
|
+
# http.callback { yield build_user_from_http_response(http) }
|
63
|
+
# end
|
64
|
+
# fiber :find_user
|
76
65
|
#
|
77
|
-
# Because
|
66
|
+
# Because `find_user` has been wrapped in Fiber logic, we can call it
|
78
67
|
# synchronously even though it uses asynchronous EventMachine calls.
|
79
68
|
#
|
80
|
-
#
|
81
|
-
#
|
69
|
+
# user = storage.find_user('alice@wonderland.lit')
|
70
|
+
# puts user.nil?
|
71
|
+
#
|
72
|
+
# Returns nothing.
|
82
73
|
def self.fiber(method)
|
83
74
|
old = instance_method(method)
|
84
75
|
define_method method do |*args|
|
@@ -90,114 +81,162 @@ module Vines
|
|
90
81
|
end
|
91
82
|
end
|
92
83
|
|
93
|
-
#
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
# Validate the username and password pair and return a +Vines::User+ object
|
99
|
-
# on success. Return +nil+ on failure.
|
84
|
+
# Validate the username and password pair.
|
85
|
+
#
|
86
|
+
# username - The String login JID to verify.
|
87
|
+
# password - The String password the user presented to the server.
|
100
88
|
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
89
|
+
# Examples
|
90
|
+
#
|
91
|
+
# user = storage.authenticate('alice@wonderland.lit', 'secr3t')
|
92
|
+
# puts user.nil?
|
104
93
|
#
|
105
94
|
# This default implementation validates the password against a bcrypt hash
|
106
95
|
# of the password stored in the database. Sub-classes not using bcrypt
|
107
96
|
# passwords must override this method.
|
97
|
+
#
|
98
|
+
# Returns a Vines::User object on success, nil on failure.
|
108
99
|
def authenticate(username, password)
|
109
100
|
user = find_user(username)
|
110
101
|
hash = BCrypt::Password.new(user.password) rescue nil
|
111
102
|
(hash && hash == password) ? user : nil
|
112
103
|
end
|
113
|
-
wrap_ldap :authenticate
|
114
104
|
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
# database.
|
105
|
+
# Find the user in the storage database by their unique JID.
|
106
|
+
#
|
107
|
+
# jid - The String or JID of the user, possibly nil. This may be either a
|
108
|
+
# bare JID or full JID. Implementations of this method must convert
|
109
|
+
# the JID to a bare JID before searching for the user in the database.
|
120
110
|
#
|
121
|
-
#
|
122
|
-
#
|
111
|
+
# Examples
|
112
|
+
#
|
113
|
+
# # Bare JID lookup.
|
114
|
+
# user = storage.find_user('alice@wonderland.lit')
|
115
|
+
# puts user.nil?
|
116
|
+
#
|
117
|
+
# # Full JID lookup.
|
118
|
+
# user = storage.find_user('alice@wonderland.lit/tea')
|
119
|
+
# puts user.nil?
|
120
|
+
#
|
121
|
+
# Returns the User identified by the JID, nil if not found.
|
123
122
|
def find_user(jid)
|
124
123
|
raise 'subclass must implement'
|
125
124
|
end
|
126
125
|
|
127
|
-
# Persist the
|
128
|
-
#
|
126
|
+
# Persist the user to the database, and return when the save is complete.
|
127
|
+
#
|
128
|
+
# user - The User to persist.
|
129
|
+
#
|
130
|
+
# Examples
|
131
|
+
#
|
132
|
+
# alice = Vines::User.new(jid: 'alice@wonderland.lit')
|
133
|
+
# storage.save_user(alice)
|
134
|
+
# puts 'saved'
|
129
135
|
#
|
130
|
-
#
|
131
|
-
# storage.save_user(alice)
|
132
|
-
# puts 'saved'
|
136
|
+
# Returns nothing.
|
133
137
|
def save_user(user)
|
134
138
|
raise 'subclass must implement'
|
135
139
|
end
|
136
140
|
|
137
|
-
#
|
138
|
-
# nil if the vcard could not be found. JID may be +nil+, a +String+, or a
|
139
|
-
# +Vines::JID+ object. It may be a bare JID or a full JID. Implementations
|
140
|
-
# of this method must convert the JID to a bare JID before searching for the
|
141
|
-
# vcard in the database.
|
141
|
+
# Find the user's vcard by their unique JID.
|
142
142
|
#
|
143
|
-
#
|
144
|
-
#
|
143
|
+
# jid - The String or JID of the user, possibly nil. This may be either a
|
144
|
+
# bare JID or full JID. Implementations of this method must convert
|
145
|
+
# the JID to a bare JID before searching for the vcard in the database.
|
146
|
+
#
|
147
|
+
# Examples
|
148
|
+
#
|
149
|
+
# card = storage.find_vcard('alice@wonderland.lit')
|
150
|
+
# puts card.nil?
|
151
|
+
#
|
152
|
+
# Returns the vcard's Nokogiri::XML::Node, nil if not found.
|
145
153
|
def find_vcard(jid)
|
146
154
|
raise 'subclass must implement'
|
147
155
|
end
|
148
156
|
|
149
|
-
# Save the vcard to the database and return when the save is complete.
|
150
|
-
#
|
151
|
-
#
|
152
|
-
# JID
|
157
|
+
# Save the vcard to the database, and return when the save is complete.
|
158
|
+
#
|
159
|
+
# jid - The String or JID of the user, possibly nil. This may be either a
|
160
|
+
# bare JID or full JID. Implementations of this method must convert
|
161
|
+
# the JID to a bare JID before saving the vcard.
|
162
|
+
# card - The vcard's Nokogiri::XML::Node.
|
163
|
+
#
|
164
|
+
# Examples
|
165
|
+
#
|
166
|
+
# card = Nokogiri::XML('<vCard>...</vCard>').root
|
167
|
+
# storage.save_vcard('alice@wonderland.lit', card)
|
168
|
+
# puts 'saved'
|
153
169
|
#
|
154
|
-
#
|
155
|
-
# storage.save_vcard('alice@wonderland.lit', card)
|
156
|
-
# puts 'saved'
|
170
|
+
# Returns nothing.
|
157
171
|
def save_vcard(jid, card)
|
158
172
|
raise 'subclass must implement'
|
159
173
|
end
|
160
174
|
|
161
|
-
#
|
162
|
-
#
|
163
|
-
# +String+, or a +Vines::JID+ object. It may be a bare JID or a full JID.
|
164
|
-
# Implementations of this method must convert the JID to a bare JID before
|
165
|
-
# searching for the fragment in the database.
|
166
|
-
#
|
167
|
-
# Private XML storage uniquely identifies fragments by JID, root element name,
|
175
|
+
# Find the private XML fragment previously stored by the user. Private
|
176
|
+
# XML storage uniquely identifies fragments by JID, root element name,
|
168
177
|
# and root element namespace.
|
169
178
|
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
179
|
+
# jid - The String or JID of the user, possibly nil. This may be either a
|
180
|
+
# bare JID or full JID. Implementations of this method must convert
|
181
|
+
# the JID to a bare JID before searching for the fragment in the database.
|
182
|
+
# node - The XML::Node that uniquely identifies the fragment by element
|
183
|
+
# name and namespace.
|
184
|
+
#
|
185
|
+
# Examples
|
186
|
+
#
|
187
|
+
# root = Nokogiri::XML('<custom xmlns="urn:custom:ns"/>').root
|
188
|
+
# fragment = storage.find_fragment('alice@wonderland.lit', root)
|
189
|
+
# puts fragment.nil?
|
190
|
+
#
|
191
|
+
# Returns the fragment's Nokogiri::XML::Node or nil if not found.
|
173
192
|
def find_fragment(jid, node)
|
174
193
|
raise 'subclass must implement'
|
175
194
|
end
|
176
195
|
|
177
|
-
# Save the XML fragment to the database and return when the save is complete.
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# JID
|
196
|
+
# Save the XML fragment to the database, and return when the save is complete.
|
197
|
+
#
|
198
|
+
# jid - The String or JID of the user, possibly nil. This may be
|
199
|
+
# either a bare JID or full JID. Implementations of this method
|
200
|
+
# must convert the JID to a bare JID before searching for the
|
201
|
+
# fragment.
|
202
|
+
# fragment - The XML::Node to save.
|
203
|
+
#
|
204
|
+
# Examples
|
181
205
|
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
206
|
+
# fragment = Nokogiri::XML('<custom xmlns="urn:custom:ns">some data</custom>').root
|
207
|
+
# storage.save_fragment('alice@wonderland.lit', fragment)
|
208
|
+
# puts 'saved'
|
209
|
+
#
|
210
|
+
# Returns nothing.
|
185
211
|
def save_fragment(jid, fragment)
|
186
212
|
raise 'subclass must implement'
|
187
213
|
end
|
188
214
|
|
189
215
|
private
|
190
216
|
|
191
|
-
#
|
192
|
-
#
|
193
|
-
#
|
194
|
-
#
|
217
|
+
# Determine if any of the arguments are nil or empty strings.
|
218
|
+
#
|
219
|
+
# Examples
|
220
|
+
#
|
221
|
+
# username, password = 'alice@wonderland.lit', ''
|
222
|
+
# empty?(username, password) #=> true
|
223
|
+
#
|
224
|
+
# Returns true if any of the arguments are nil or empty strings.
|
195
225
|
def empty?(*args)
|
196
226
|
args.flatten.any? {|arg| (arg || '').strip.empty? }
|
197
227
|
end
|
198
228
|
|
199
|
-
#
|
200
|
-
# and logs any errors thrown by the provided block.
|
229
|
+
# Create a proc suitable for running on the EM.defer thread pool, that
|
230
|
+
# traps and logs any errors thrown by the provided block.
|
231
|
+
#
|
232
|
+
# block - The block to wrap in error handling.
|
233
|
+
#
|
234
|
+
# Examples
|
235
|
+
#
|
236
|
+
# op = operation { do_something_on_thread_pool() }
|
237
|
+
# EM.defer(op)
|
238
|
+
#
|
239
|
+
# Returns a Proc.
|
201
240
|
def operation
|
202
241
|
proc do
|
203
242
|
begin
|
@@ -208,32 +247,5 @@ module Vines
|
|
208
247
|
end
|
209
248
|
end
|
210
249
|
end
|
211
|
-
|
212
|
-
# Return a +Vines::User+ object if we are able to bind to the LDAP server
|
213
|
-
# using the username and password. Return +nil+ if authentication failed. If
|
214
|
-
# authentication succeeds, but the user is not yet stored in our database,
|
215
|
-
# save the user to the database.
|
216
|
-
def authenticate_with_ldap(username, password, &block)
|
217
|
-
op = operation { ldap.authenticate(username, password) }
|
218
|
-
cb = proc {|user| save_ldap_user(user, &block) }
|
219
|
-
EM.defer(op, cb)
|
220
|
-
end
|
221
|
-
fiber :authenticate_with_ldap
|
222
|
-
|
223
|
-
# Save missing users to the storage database after they're authenticated with
|
224
|
-
# LDAP. This allows admins to define users once in LDAP and have them sync
|
225
|
-
# to the chat database the first time they successfully sign in.
|
226
|
-
def save_ldap_user(user, &block)
|
227
|
-
Fiber.new do
|
228
|
-
if user.nil?
|
229
|
-
block.call
|
230
|
-
elsif found = find_user(user.jid)
|
231
|
-
block.call(found)
|
232
|
-
else
|
233
|
-
save_user(user)
|
234
|
-
block.call(user)
|
235
|
-
end
|
236
|
-
end.resume
|
237
|
-
end
|
238
250
|
end
|
239
251
|
end
|