diaspora-vines 0.1.2
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 +7 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +7 -0
- data/Rakefile +23 -0
- data/bin/vines +4 -0
- data/conf/certs/README +39 -0
- data/conf/certs/ca-bundle.crt +3895 -0
- data/conf/config.rb +42 -0
- data/lib/vines/cli.rb +132 -0
- data/lib/vines/cluster/connection.rb +26 -0
- data/lib/vines/cluster/publisher.rb +55 -0
- data/lib/vines/cluster/pubsub.rb +92 -0
- data/lib/vines/cluster/sessions.rb +125 -0
- data/lib/vines/cluster/subscriber.rb +108 -0
- data/lib/vines/cluster.rb +246 -0
- data/lib/vines/command/bcrypt.rb +12 -0
- data/lib/vines/command/cert.rb +50 -0
- data/lib/vines/command/init.rb +68 -0
- data/lib/vines/command/ldap.rb +38 -0
- data/lib/vines/command/restart.rb +12 -0
- data/lib/vines/command/schema.rb +24 -0
- data/lib/vines/command/start.rb +28 -0
- data/lib/vines/command/stop.rb +18 -0
- data/lib/vines/config/host.rb +125 -0
- data/lib/vines/config/port.rb +132 -0
- data/lib/vines/config/pubsub.rb +108 -0
- data/lib/vines/config.rb +223 -0
- data/lib/vines/contact.rb +111 -0
- data/lib/vines/daemon.rb +78 -0
- data/lib/vines/error.rb +150 -0
- data/lib/vines/jid.rb +95 -0
- data/lib/vines/kit.rb +23 -0
- data/lib/vines/log.rb +24 -0
- data/lib/vines/router.rb +179 -0
- data/lib/vines/stanza/iq/auth.rb +18 -0
- data/lib/vines/stanza/iq/disco_info.rb +45 -0
- data/lib/vines/stanza/iq/disco_items.rb +29 -0
- data/lib/vines/stanza/iq/error.rb +16 -0
- data/lib/vines/stanza/iq/ping.rb +16 -0
- data/lib/vines/stanza/iq/private_storage.rb +83 -0
- data/lib/vines/stanza/iq/query.rb +10 -0
- data/lib/vines/stanza/iq/result.rb +16 -0
- data/lib/vines/stanza/iq/roster.rb +140 -0
- data/lib/vines/stanza/iq/session.rb +17 -0
- data/lib/vines/stanza/iq/vcard.rb +56 -0
- data/lib/vines/stanza/iq/version.rb +25 -0
- data/lib/vines/stanza/iq.rb +48 -0
- data/lib/vines/stanza/message.rb +40 -0
- data/lib/vines/stanza/presence/error.rb +23 -0
- data/lib/vines/stanza/presence/probe.rb +37 -0
- data/lib/vines/stanza/presence/subscribe.rb +42 -0
- data/lib/vines/stanza/presence/subscribed.rb +51 -0
- data/lib/vines/stanza/presence/unavailable.rb +15 -0
- data/lib/vines/stanza/presence/unsubscribe.rb +38 -0
- data/lib/vines/stanza/presence/unsubscribed.rb +38 -0
- data/lib/vines/stanza/presence.rb +141 -0
- data/lib/vines/stanza/pubsub/create.rb +39 -0
- data/lib/vines/stanza/pubsub/delete.rb +41 -0
- data/lib/vines/stanza/pubsub/publish.rb +66 -0
- data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
- data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
- data/lib/vines/stanza/pubsub.rb +22 -0
- data/lib/vines/stanza.rb +175 -0
- data/lib/vines/storage/ldap.rb +71 -0
- data/lib/vines/storage/local.rb +139 -0
- data/lib/vines/storage/null.rb +39 -0
- data/lib/vines/storage/sql.rb +138 -0
- data/lib/vines/storage.rb +239 -0
- data/lib/vines/store.rb +110 -0
- data/lib/vines/stream/client/auth.rb +74 -0
- data/lib/vines/stream/client/auth_restart.rb +29 -0
- data/lib/vines/stream/client/bind.rb +72 -0
- data/lib/vines/stream/client/bind_restart.rb +24 -0
- data/lib/vines/stream/client/closed.rb +13 -0
- data/lib/vines/stream/client/ready.rb +17 -0
- data/lib/vines/stream/client/session.rb +210 -0
- data/lib/vines/stream/client/start.rb +27 -0
- data/lib/vines/stream/client/tls.rb +38 -0
- data/lib/vines/stream/client.rb +84 -0
- data/lib/vines/stream/component/handshake.rb +26 -0
- data/lib/vines/stream/component/ready.rb +23 -0
- data/lib/vines/stream/component/start.rb +19 -0
- data/lib/vines/stream/component.rb +58 -0
- data/lib/vines/stream/http/auth.rb +22 -0
- data/lib/vines/stream/http/bind.rb +32 -0
- data/lib/vines/stream/http/bind_restart.rb +37 -0
- data/lib/vines/stream/http/ready.rb +29 -0
- data/lib/vines/stream/http/request.rb +172 -0
- data/lib/vines/stream/http/session.rb +120 -0
- data/lib/vines/stream/http/sessions.rb +65 -0
- data/lib/vines/stream/http/start.rb +23 -0
- data/lib/vines/stream/http.rb +157 -0
- data/lib/vines/stream/parser.rb +79 -0
- data/lib/vines/stream/sasl.rb +128 -0
- data/lib/vines/stream/server/auth.rb +13 -0
- data/lib/vines/stream/server/auth_restart.rb +13 -0
- data/lib/vines/stream/server/final_restart.rb +21 -0
- data/lib/vines/stream/server/outbound/auth.rb +31 -0
- data/lib/vines/stream/server/outbound/auth_restart.rb +20 -0
- data/lib/vines/stream/server/outbound/auth_result.rb +32 -0
- data/lib/vines/stream/server/outbound/final_features.rb +28 -0
- data/lib/vines/stream/server/outbound/final_restart.rb +20 -0
- data/lib/vines/stream/server/outbound/start.rb +20 -0
- data/lib/vines/stream/server/outbound/tls.rb +30 -0
- data/lib/vines/stream/server/outbound/tls_result.rb +34 -0
- data/lib/vines/stream/server/ready.rb +24 -0
- data/lib/vines/stream/server/start.rb +13 -0
- data/lib/vines/stream/server/tls.rb +13 -0
- data/lib/vines/stream/server.rb +150 -0
- data/lib/vines/stream/state.rb +60 -0
- data/lib/vines/stream.rb +247 -0
- data/lib/vines/token_bucket.rb +55 -0
- data/lib/vines/user.rb +123 -0
- data/lib/vines/version.rb +6 -0
- data/lib/vines/xmpp_server.rb +25 -0
- data/lib/vines.rb +203 -0
- data/test/cluster/publisher_test.rb +57 -0
- data/test/cluster/sessions_test.rb +47 -0
- data/test/cluster/subscriber_test.rb +109 -0
- data/test/config/host_test.rb +369 -0
- data/test/config/pubsub_test.rb +187 -0
- data/test/config_test.rb +732 -0
- data/test/contact_test.rb +102 -0
- data/test/error_test.rb +58 -0
- data/test/ext/nokogiri.rb +14 -0
- data/test/jid_test.rb +147 -0
- data/test/kit_test.rb +31 -0
- data/test/router_test.rb +243 -0
- data/test/stanza/iq/disco_info_test.rb +78 -0
- data/test/stanza/iq/disco_items_test.rb +49 -0
- data/test/stanza/iq/private_storage_test.rb +184 -0
- data/test/stanza/iq/roster_test.rb +229 -0
- data/test/stanza/iq/session_test.rb +25 -0
- data/test/stanza/iq/vcard_test.rb +146 -0
- data/test/stanza/iq/version_test.rb +64 -0
- data/test/stanza/iq_test.rb +70 -0
- data/test/stanza/message_test.rb +126 -0
- data/test/stanza/presence/probe_test.rb +50 -0
- data/test/stanza/presence/subscribe_test.rb +83 -0
- data/test/stanza/pubsub/create_test.rb +116 -0
- data/test/stanza/pubsub/delete_test.rb +169 -0
- data/test/stanza/pubsub/publish_test.rb +309 -0
- data/test/stanza/pubsub/subscribe_test.rb +205 -0
- data/test/stanza/pubsub/unsubscribe_test.rb +148 -0
- data/test/stanza_test.rb +85 -0
- data/test/storage/ldap_test.rb +201 -0
- data/test/storage/local_test.rb +59 -0
- data/test/storage/mock_redis.rb +97 -0
- data/test/storage/null_test.rb +29 -0
- data/test/storage/storage_tests.rb +182 -0
- data/test/storage_test.rb +85 -0
- data/test/store_test.rb +130 -0
- data/test/stream/client/auth_test.rb +137 -0
- data/test/stream/client/ready_test.rb +47 -0
- data/test/stream/client/session_test.rb +27 -0
- data/test/stream/component/handshake_test.rb +52 -0
- data/test/stream/component/ready_test.rb +103 -0
- data/test/stream/component/start_test.rb +39 -0
- data/test/stream/http/auth_test.rb +70 -0
- data/test/stream/http/ready_test.rb +86 -0
- data/test/stream/http/request_test.rb +209 -0
- data/test/stream/http/sessions_test.rb +49 -0
- data/test/stream/http/start_test.rb +50 -0
- data/test/stream/parser_test.rb +122 -0
- data/test/stream/sasl_test.rb +195 -0
- data/test/stream/server/auth_test.rb +61 -0
- data/test/stream/server/outbound/auth_test.rb +75 -0
- data/test/stream/server/ready_test.rb +98 -0
- data/test/test_helper.rb +42 -0
- data/test/token_bucket_test.rb +44 -0
- data/test/user_test.rb +96 -0
- data/vines.gemspec +30 -0
- metadata +387 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::DiscoItems do
|
6
|
+
subject { Vines::Stanza::Iq::DiscoItems.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/home') }
|
9
|
+
let(:config) do
|
10
|
+
Vines::Config.new do
|
11
|
+
host 'wonderland.lit' do
|
12
|
+
storage(:fs) { dir Dir.tmpdir }
|
13
|
+
components 'tea' => 'secr3t', 'cake' => 'passw0rd'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
class << stream
|
20
|
+
attr_accessor :config, :user
|
21
|
+
end
|
22
|
+
stream.config = config
|
23
|
+
stream.user = alice
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'when querying server items' do
|
27
|
+
let(:xml) do
|
28
|
+
query = %q{<query xmlns="http://jabber.org/protocol/disco#items"/>}
|
29
|
+
node(%Q{<iq id="42" to="wonderland.lit" type="get">#{query}</iq>})
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:result) do
|
33
|
+
node(%q{
|
34
|
+
<iq from="wonderland.lit" id="42" to="alice@wonderland.lit/home" type="result">
|
35
|
+
<query xmlns="http://jabber.org/protocol/disco#items">
|
36
|
+
<item jid="cake.wonderland.lit"/>
|
37
|
+
<item jid="tea.wonderland.lit"/>
|
38
|
+
</query>
|
39
|
+
</iq>
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'includes component domains in output' do
|
44
|
+
stream.expect :write, nil, [result]
|
45
|
+
subject.process
|
46
|
+
stream.verify
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::PrivateStorage do
|
6
|
+
subject { Vines::Stanza::Iq::PrivateStorage.new(xml, stream) }
|
7
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
8
|
+
let(:storage) { MiniTest::Mock.new }
|
9
|
+
let(:stream) { MiniTest::Mock.new }
|
10
|
+
let(:config) do
|
11
|
+
Vines::Config.new do
|
12
|
+
host 'wonderland.lit' do
|
13
|
+
storage(:fs) { dir Dir.tmpdir }
|
14
|
+
private_storage true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
class << stream
|
21
|
+
attr_accessor :config, :domain, :user
|
22
|
+
end
|
23
|
+
stream.config = config
|
24
|
+
stream.user = alice
|
25
|
+
stream.domain = 'wonderland.lit'
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'when private storage feature is disabled' do
|
29
|
+
let(:xml) do
|
30
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/></query>}
|
31
|
+
node(%Q{<iq id="42" type="get">#{query}</iq>})
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
config.vhost('wonderland.lit').private_storage false
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises a service-unavailable stanza error' do
|
39
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::ServiceUnavailable
|
40
|
+
stream.verify
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'when retrieving a fragment for another user jid' do
|
45
|
+
let(:xml) do
|
46
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/></query>}
|
47
|
+
node(%Q{<iq id="42" to="hatter@wonderland.lit" type="get">#{query}</iq>})
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises a forbidden stanza error' do
|
51
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
|
52
|
+
stream.verify
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'when get stanza contains zero child elements' do
|
57
|
+
let(:xml) do
|
58
|
+
query = %q{<query xmlns="jabber:iq:private"></query>}
|
59
|
+
node(%Q{<iq id="42" type="get">#{query}</iq>})
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises a not-acceptable stanza error' do
|
63
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
|
64
|
+
stream.verify
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'when get stanza contains more than one child element' do
|
69
|
+
let(:xml) do
|
70
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/><two xmlns="b"/></query>}
|
71
|
+
node(%Q{<iq id="42" type="get">#{query}</iq>})
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'raises a not-acceptable stanza error' do
|
75
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
|
76
|
+
stream.verify
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'when get stanza is missing a namespace' do
|
81
|
+
let(:xml) do
|
82
|
+
query = %q{<query xmlns="jabber:iq:private"><one/></query>}
|
83
|
+
node = node(%Q{<iq id="42" type="get">#{query}</iq>})
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'raises a not-acceptable stanza error' do
|
87
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
|
88
|
+
stream.verify
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'when get stanza is missing fragment' do
|
93
|
+
let(:xml) do
|
94
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/></query>}
|
95
|
+
node(%Q{<iq id="42" type="get">#{query}</iq>})
|
96
|
+
end
|
97
|
+
|
98
|
+
before do
|
99
|
+
storage.expect :find_fragment, nil, [alice.jid, xml.elements[0].elements[0]]
|
100
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'raises an item-not-found stanza error' do
|
104
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
|
105
|
+
stream.verify
|
106
|
+
storage.verify
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'when get finds fragment successfully' do
|
111
|
+
let(:xml) do
|
112
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/></query>}
|
113
|
+
node = node(%Q{<iq id="42" type="get">#{query}</iq>})
|
114
|
+
end
|
115
|
+
|
116
|
+
before do
|
117
|
+
data = %q{<one xmlns="a"><child>data</child></one>}
|
118
|
+
query = %Q{<query xmlns="jabber:iq:private">#{data}</query>}
|
119
|
+
expected = node(%Q{<iq from="#{alice.jid}" id="42" to="#{alice.jid}" type="result">#{query}</iq>})
|
120
|
+
|
121
|
+
storage.expect :find_fragment, node(data), [alice.jid, xml.elements[0].elements[0]]
|
122
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
123
|
+
stream.expect :write, nil, [expected]
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'writes a response to the stream' do
|
127
|
+
subject.process
|
128
|
+
stream.verify
|
129
|
+
storage.verify
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'when saving a fragment' do
|
134
|
+
let(:result) { node(%Q{<iq from="#{alice.jid}" id="42" to="#{alice.jid}" type="result"/>}) }
|
135
|
+
|
136
|
+
before do
|
137
|
+
storage.expect :save_fragment, nil, [alice.jid, xml.elements[0].elements[0]]
|
138
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
139
|
+
stream.expect :write, nil, [result]
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'and stanza contains zero child elements' do
|
143
|
+
let(:xml) do
|
144
|
+
query = %q{<query xmlns="jabber:iq:private"></query>}
|
145
|
+
node(%Q{<iq id="42" type="set">#{query}</iq>})
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'raises a not-acceptable stanza error' do
|
149
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'and a single single fragment saves successfully' do
|
154
|
+
let(:xml) do
|
155
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/></query>}
|
156
|
+
node(%Q{<iq id="42" type="set">#{query}</iq>})
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'writes a result to the stream' do
|
160
|
+
subject.process
|
161
|
+
stream.verify
|
162
|
+
storage.verify
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'and two fragments save successfully' do
|
167
|
+
let(:xml) do
|
168
|
+
query = %q{<query xmlns="jabber:iq:private"><one xmlns="a"/><two xmlns="a"/></query>}
|
169
|
+
node(%Q{<iq id="42" type="set">#{query}</iq>})
|
170
|
+
end
|
171
|
+
|
172
|
+
before do
|
173
|
+
storage.expect :save_fragment, nil, [alice.jid, xml.elements[0].elements[1]]
|
174
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'writes a result to the stream' do
|
178
|
+
subject.process
|
179
|
+
stream.verify
|
180
|
+
storage.verify
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::Roster do
|
6
|
+
subject { Vines::Stanza::Iq::Roster.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
9
|
+
|
10
|
+
before do
|
11
|
+
class << stream
|
12
|
+
attr_accessor :domain, :user
|
13
|
+
end
|
14
|
+
stream.user = alice
|
15
|
+
stream.domain = 'wonderland.lit'
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'when retrieving an empty roster' do
|
19
|
+
let(:xml) { node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>}) }
|
20
|
+
let(:expected) { node(%q{<iq id="42" type="result"><query xmlns="jabber:iq:roster"/></iq>}) }
|
21
|
+
|
22
|
+
before do
|
23
|
+
stream.expect :write, nil, [expected]
|
24
|
+
stream.expect :requested_roster!, nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns an empty stanza' do
|
28
|
+
subject.process
|
29
|
+
stream.verify
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'when retrieving a non-empty roster' do
|
34
|
+
let(:xml) { node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>}) }
|
35
|
+
let(:expected) do
|
36
|
+
node(%q{
|
37
|
+
<iq id="42" type="result">
|
38
|
+
<query xmlns="jabber:iq:roster">
|
39
|
+
<item jid="cat@wonderland.lit" subscription="none">
|
40
|
+
<group>Cats</group>
|
41
|
+
<group>Friends</group>
|
42
|
+
</item>
|
43
|
+
<item jid="hatter@wonderland.lit" subscription="none"/>
|
44
|
+
</query>
|
45
|
+
</iq>})
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
alice.roster << Vines::Contact.new(jid: 'hatter@wonderland.lit')
|
50
|
+
alice.roster << Vines::Contact.new(jid: 'cat@wonderland.lit', :groups => ['Friends', 'Cats'])
|
51
|
+
|
52
|
+
stream.expect :write, nil, [expected]
|
53
|
+
stream.expect :requested_roster!, nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'sorts groups alphabetically' do
|
57
|
+
subject.process
|
58
|
+
stream.verify
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'when requesting a roster for another user' do
|
63
|
+
let(:xml) do
|
64
|
+
node(%q{
|
65
|
+
<iq id="42" type="get" to="romeo@verona.lit">
|
66
|
+
<query xmlns="jabber:iq:roster"/>
|
67
|
+
</iq>})
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises a forbidden stanza error' do
|
71
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
|
72
|
+
stream.verify
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'when saving a roster for another user' do
|
77
|
+
let(:xml) do
|
78
|
+
node(%q{
|
79
|
+
<iq id="42" type="set" to="romeo@verona.lit">
|
80
|
+
<query xmlns="jabber:iq:roster"/>
|
81
|
+
</iq>})
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'raises a forbidden stanza error' do
|
85
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
|
86
|
+
stream.verify
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'when saving a roster with no items' do
|
91
|
+
let(:xml) do
|
92
|
+
node(%q{
|
93
|
+
<iq id="42" type="set">
|
94
|
+
<query xmlns="jabber:iq:roster"/>
|
95
|
+
</iq>})
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'raises a bad-request stanza error' do
|
99
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
100
|
+
stream.verify
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'when updating a roster with more than one item' do
|
105
|
+
let(:xml) do
|
106
|
+
node(%q{
|
107
|
+
<iq id="42" type="set">
|
108
|
+
<query xmlns="jabber:iq:roster">
|
109
|
+
<item jid="hatter@wonderland.lit"/>
|
110
|
+
<item jid="cat@wonderland.lit"/>
|
111
|
+
</query>
|
112
|
+
</iq>})
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'raises a bad-request stanza error' do
|
116
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
117
|
+
stream.verify
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'when adding a roster item without a jid attribute' do
|
122
|
+
let(:xml) do
|
123
|
+
node(%q{
|
124
|
+
<iq id="42" type="set">
|
125
|
+
<query xmlns="jabber:iq:roster">
|
126
|
+
<item name="Mad Hatter"/>
|
127
|
+
</query>
|
128
|
+
</iq>})
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'raises a bad-request stanza error' do
|
132
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
133
|
+
stream.verify
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'when adding a roster item with duplicate groups' do
|
138
|
+
let(:xml) do
|
139
|
+
node(%q{
|
140
|
+
<iq id="42" type="set">
|
141
|
+
<query xmlns="jabber:iq:roster">
|
142
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
143
|
+
<group>Friends</group>
|
144
|
+
<group>Friends</group>
|
145
|
+
</item>
|
146
|
+
</query>
|
147
|
+
</iq>})
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'raises a bad-request stanza error' do
|
151
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
152
|
+
stream.verify
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe 'when adding a roster item with an empty group name' do
|
157
|
+
let(:xml) do
|
158
|
+
node(%q{
|
159
|
+
<iq id="42" type="set">
|
160
|
+
<query xmlns="jabber:iq:roster">
|
161
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
162
|
+
<group></group>
|
163
|
+
</item>
|
164
|
+
</query>
|
165
|
+
</iq>})
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'raises a not-acceptable stanza error' do
|
169
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
|
170
|
+
stream.verify
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe 'when saving a roster successfully' do
|
175
|
+
let(:xml) do
|
176
|
+
node(%q{
|
177
|
+
<iq id="42" type="set">
|
178
|
+
<query xmlns="jabber:iq:roster">
|
179
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
180
|
+
<group>Friends</group>
|
181
|
+
</item>
|
182
|
+
</query>
|
183
|
+
</iq>})
|
184
|
+
end
|
185
|
+
|
186
|
+
let(:expected) do
|
187
|
+
node(%q{
|
188
|
+
<iq to="alice@wonderland.lit/tea" type="set">
|
189
|
+
<query xmlns="jabber:iq:roster">
|
190
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter" subscription="none">
|
191
|
+
<group>Friends</group>
|
192
|
+
</item>
|
193
|
+
</query>
|
194
|
+
</iq>})
|
195
|
+
end
|
196
|
+
|
197
|
+
let(:storage) { MiniTest::Mock.new }
|
198
|
+
let(:recipient) { MiniTest::Mock.new }
|
199
|
+
let(:result) { node(%Q{<iq id="42" to="#{alice.jid}" type="result"/>}) }
|
200
|
+
|
201
|
+
before do
|
202
|
+
storage.expect :save_user, nil, [alice]
|
203
|
+
|
204
|
+
recipient.expect :user, alice
|
205
|
+
def recipient.nodes; @nodes; end
|
206
|
+
def recipient.write(node)
|
207
|
+
@nodes ||= []
|
208
|
+
@nodes << node
|
209
|
+
end
|
210
|
+
|
211
|
+
stream.expect :interested_resources, [recipient], [alice.jid]
|
212
|
+
stream.expect :update_user_streams, nil, [alice]
|
213
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
214
|
+
stream.expect :write, nil, [result]
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'sends a result to the sender' do
|
218
|
+
subject.process
|
219
|
+
stream.verify
|
220
|
+
storage.verify
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'sends the new roster item to the interested streams' do
|
224
|
+
subject.process
|
225
|
+
recipient.nodes.first.remove_attribute('id') # id is random
|
226
|
+
recipient.nodes.first.must_equal expected
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::Session do
|
6
|
+
subject { Vines::Stanza::Iq::Session.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
9
|
+
|
10
|
+
describe 'when session initiation is requested' do
|
11
|
+
let(:xml) { node(%q{<iq id="42" type="set"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>}) }
|
12
|
+
let(:result) { node(%q{<iq from="wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>}) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
stream.expect :domain, 'wonderland.lit'
|
16
|
+
stream.expect :user, alice
|
17
|
+
stream.expect :write, nil, [result]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'just returns a result to satisy older clients' do
|
21
|
+
subject.process
|
22
|
+
stream.verify
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::Vcard do
|
6
|
+
subject { Vines::Stanza::Iq::Vcard.new(xml, stream) }
|
7
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
8
|
+
let(:stream) { MiniTest::Mock.new }
|
9
|
+
let(:storage) { MiniTest::Mock.new }
|
10
|
+
let(:config) do
|
11
|
+
Vines::Config.new do
|
12
|
+
host 'wonderland.lit' do
|
13
|
+
cross_domain_messages true
|
14
|
+
storage(:fs) { dir Dir.tmpdir }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
class << stream
|
21
|
+
attr_accessor :config, :domain, :user
|
22
|
+
end
|
23
|
+
stream.config = config
|
24
|
+
stream.domain = 'wonderland.lit'
|
25
|
+
stream.user = alice
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'when getting vcard' do
|
29
|
+
describe 'and addressed to a remote jid' do
|
30
|
+
let(:xml) { get('romeo@verona.lit') }
|
31
|
+
let(:router) { MiniTest::Mock.new }
|
32
|
+
|
33
|
+
before do
|
34
|
+
router.expect :route, nil, [xml]
|
35
|
+
stream.expect :router, router
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'routes rather than handle locally' do
|
39
|
+
subject.process
|
40
|
+
stream.verify
|
41
|
+
router.verify
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'and missing to address' do
|
46
|
+
let(:xml) { get('') }
|
47
|
+
let(:card) { vcard('Alice') }
|
48
|
+
let(:expected) { result(alice.jid, '', card) }
|
49
|
+
|
50
|
+
before do
|
51
|
+
storage.expect :find_vcard, card, [alice.jid.bare]
|
52
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
53
|
+
stream.expect :write, nil, [expected]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'sends vcard for authenticated jid' do
|
57
|
+
subject.process
|
58
|
+
stream.verify
|
59
|
+
storage.verify
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'for another user' do
|
64
|
+
let(:xml) { get(hatter) }
|
65
|
+
let(:card) { vcard('Hatter') }
|
66
|
+
let(:hatter) { Vines::JID.new('hatter@wonderland.lit') }
|
67
|
+
let(:expected) { result(alice.jid, hatter, card) }
|
68
|
+
|
69
|
+
before do
|
70
|
+
storage.expect :find_vcard, card, [hatter]
|
71
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
72
|
+
stream.expect :write, nil, [expected]
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'succeeds and returns vcard with from address' do
|
76
|
+
subject.process
|
77
|
+
stream.verify
|
78
|
+
storage.verify
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'for missing vcard' do
|
83
|
+
let(:xml) { get('') }
|
84
|
+
|
85
|
+
before do
|
86
|
+
storage.expect :find_vcard, nil, [alice.jid.bare]
|
87
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'returns an item-not-found stanza error' do
|
91
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
|
92
|
+
stream.verify
|
93
|
+
storage.verify
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'when setting vcard' do
|
99
|
+
describe 'and addressed to another user' do
|
100
|
+
let(:xml) { set('hatter@wonderland.lit') }
|
101
|
+
|
102
|
+
it 'raises a forbidden stanza error' do
|
103
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
|
104
|
+
stream.verify
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'and missing to address' do
|
109
|
+
let(:xml) { set('') }
|
110
|
+
let(:card) { vcard('Alice') }
|
111
|
+
let(:expected) { result(alice.jid) }
|
112
|
+
|
113
|
+
before do
|
114
|
+
storage.expect :save_vcard, nil, [alice.jid, card]
|
115
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
116
|
+
stream.expect :write, nil, [expected]
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'succeeds and returns an iq result' do
|
120
|
+
subject.process
|
121
|
+
stream.verify
|
122
|
+
storage.verify
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def vcard(name)
|
130
|
+
node(%Q{<vCard xmlns="vcard-temp"><FN>#{name}</FN></vCard>})
|
131
|
+
end
|
132
|
+
|
133
|
+
def get(to)
|
134
|
+
card = '<vCard xmlns="vcard-temp"/>'
|
135
|
+
iq(id: 42, to: to, type: 'get', body: card)
|
136
|
+
end
|
137
|
+
|
138
|
+
def set(to)
|
139
|
+
card = '<vCard xmlns="vcard-temp"><FN>Alice</FN></vCard>'
|
140
|
+
iq(id: 42, to: to, type: 'set', body: card)
|
141
|
+
end
|
142
|
+
|
143
|
+
def result(to, from=nil, card=nil)
|
144
|
+
iq(from: from, id: 42, to: to, type: 'result', body: card)
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq::Version do
|
6
|
+
subject { Vines::Stanza::Iq::Version.new(xml, stream) }
|
7
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
8
|
+
let(:stream) { MiniTest::Mock.new }
|
9
|
+
let(:config) do
|
10
|
+
Vines::Config.new do
|
11
|
+
host 'wonderland.lit' do
|
12
|
+
storage(:fs) { dir Dir.tmpdir }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
class << stream
|
19
|
+
attr_accessor :config, :user
|
20
|
+
end
|
21
|
+
stream.config = config
|
22
|
+
stream.user = alice
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'when not addressed to the server' do
|
26
|
+
let(:router) { MiniTest::Mock.new }
|
27
|
+
let(:xml) { node(%q{<iq id="42" to="romeo@verona.lit" type="get"><query xmlns="jabber:iq:version"/></iq>}) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
router.expect :route, nil, [xml]
|
31
|
+
stream.expect :router, router
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'routes the stanza to the recipient jid' do
|
35
|
+
subject.process
|
36
|
+
stream.verify
|
37
|
+
router.verify
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'when missing a to address' do
|
42
|
+
let(:xml) { node(%q{<iq id="42" type="get"><query xmlns="jabber:iq:version"/></iq>}) }
|
43
|
+
let(:expected) do
|
44
|
+
node(%Q{
|
45
|
+
<iq from="wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
|
46
|
+
<query xmlns="jabber:iq:version">
|
47
|
+
<name>Vines</name>
|
48
|
+
<version>#{Vines::VERSION}</version>
|
49
|
+
</query>
|
50
|
+
</iq>})
|
51
|
+
end
|
52
|
+
|
53
|
+
before do
|
54
|
+
stream.expect :domain, 'wonderland.lit'
|
55
|
+
stream.expect :domain, 'wonderland.lit'
|
56
|
+
stream.expect :write, nil, [expected]
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns a version result when missing a to jid' do
|
60
|
+
subject.process
|
61
|
+
stream.verify
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|