gliffy 0.0.6

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.
@@ -0,0 +1,10 @@
1
+ # Gliffy OAuth implementation is screwed - longer nonce values causes
2
+ # it to complain about the timestamp value; we're limiting the length
3
+ # to 25 characters here
4
+ module OAuth
5
+ module Helper
6
+ def generate_key(size=25)
7
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <accounts>
4
+ <account max-users="10"
5
+ account-type="Business"
6
+ terms="true"
7
+ id="%{account_id}">
8
+ <name>BurnsODyne</name>
9
+ <expiration-date>%{expiration}</expiration-date>
10
+ <users>
11
+ <user id="209">
12
+ <username>barney</username>
13
+ <email>barney@BurnsODyne.apiuser.gliffy.com</email>
14
+ </user>
15
+ <user id="205">
16
+ <username>bart</username>
17
+ <email>bart@BurnsODyne.apiuser.gliffy.com</email>
18
+ </user>
19
+ <user id="210">
20
+ <username>discostu</username>
21
+ <email>discostu@BurnsODyne.apiuser.gliffy.com</email>
22
+ </user>
23
+ </users>
24
+ </account>
25
+ </accounts>
26
+ </response>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <documents>
4
+ <document is-public="true" num-versions="5" id="%{document_id}">
5
+ <name>%{document_name}</name>
6
+ <mod-date>1215538283000</mod-date>
7
+ <create-date>1215538284000</create-date>
8
+ <published-date>1215538285000</published-date>
9
+ <owner id="203">
10
+ <username>smithers</username>
11
+ <email>smithers@BurnsODyne.apiuser.gliffy.com</email>
12
+ </owner>
13
+ </document>
14
+ </documents>
15
+ </response>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <documents></documents>
4
+ </response>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <documents>
4
+ <document num-versions="4" id="1000000">
5
+ <name>Проверка</name>
6
+ <mod-date>1215538283000</mod-date>
7
+ <create-date>1215538283000</create-date>
8
+ <published-date>1215538283000</published-date>
9
+ <owner id="202">
10
+ <username>monty</username>
11
+ <email>monty@BurnsODyne.apiuser.gliffy.com</email>
12
+ </owner>
13
+ </document>
14
+ <document is-public="true" num-versions="5" id="1000002">
15
+ <name>SNPP Domain Model</name>
16
+ <mod-date>1215538283000</mod-date>
17
+ <create-date>1215538283000</create-date>
18
+ <published-date>1215538283000</published-date>
19
+ <owner id="203">
20
+ <username>smithers</username>
21
+ <email>smithers@BurnsODyne.apiuser.gliffy.com</email>
22
+ </owner>
23
+ </document>
24
+ <document num-versions="2" id="1000001">
25
+ <name>World Domination Flow</name>
26
+ <mod-date>1215538283000</mod-date>
27
+ <create-date>1215538283000</create-date>
28
+ <published-date>1215538283000</published-date>
29
+ <owner id="202">
30
+ <username>monty</username>
31
+ <email>monty@BurnsODyne.apiuser.gliffy.com</email>
32
+ </owner>
33
+ </document>
34
+ </documents>
35
+ </response>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <folders>
4
+ <folder is-default="true">
5
+ <name>ROOT</name>
6
+ <path>ROOT</path>
7
+ <folder is-default="false">
8
+ <name>Burns Top Secret</name>
9
+ <path>ROOT/Burns Top Secret</path>
10
+ </folder>
11
+ <folder is-default="false">
12
+ <name>Casino</name>
13
+ <path>ROOT/Casino</path>
14
+ </folder>
15
+ <folder is-default="false">
16
+ <name>Drunks Only</name>
17
+ <path>ROOT/Drunks Only</path>
18
+ </folder>
19
+ <folder is-default="false">
20
+ <name>Simpsons Family</name>
21
+ <path>ROOT/Simpsons Family</path>
22
+ <folder is-default="false">
23
+ <name>Bart Only</name>
24
+ <path>ROOT/Simpsons Family/Bart Only</path>
25
+ </folder>
26
+ <folder is-default="false">
27
+ <name>Maggie and Lisas Stuff</name>
28
+ <path>ROOT/Simpsons Family/Maggie and Lisas Stuff</path>
29
+ </folder>
30
+ </folder>
31
+ </folder>
32
+ </folders>
33
+ </response>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <response xmlns="http://www.gliffy.com" success="true">
3
+ <oauth-token-credentials>
4
+ <oauth-token>140a1b58c248d13872499df769606766</oauth-token>
5
+ <oauth-token-secret>481830f5827e35b0644a32c1caac5245</oauth-token-secret>
6
+ <create-date>1236204382765</create-date>
7
+ </oauth-token-credentials>
8
+ </response>
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gliffy::Account do
4
+ let(:account_id) { 101 }
5
+ let(:expiration) { 32154788584000 }
6
+ let(:api) do
7
+ api = double(Gliffy::API)
8
+ api.stub(
9
+ :get_folders
10
+ ).and_return(
11
+ Gliffy::API::Response.new(fixture("folder"))
12
+ )
13
+ api
14
+ end
15
+
16
+ let(:account) do
17
+ response = Gliffy::API::Response.new(
18
+ fixture(
19
+ "account",
20
+ :account_id => account_id,
21
+ :expiration => expiration
22
+ )
23
+ )
24
+ Gliffy::Account.load(api, response)
25
+ end
26
+
27
+ it "has an id" do
28
+ expect(account).to respond_to :id
29
+ expect(account.id).to eq account_id
30
+ end
31
+
32
+ it "has a name" do
33
+ expect(account).to respond_to :name
34
+ expect(account.name).to eq "BurnsODyne"
35
+ end
36
+
37
+ it "has max users count" do
38
+ expect(account).to respond_to :max_users
39
+ expect(account.max_users).to eq 10
40
+ end
41
+
42
+ it "has a type" do
43
+ expect(account).to respond_to :type
44
+ expect(account.type).to eq Gliffy::Account::TYPE_BUSINESS
45
+ end
46
+
47
+ it "has 'terms accepted' flag" do
48
+ expect(account).to respond_to :terms_accepted
49
+ expect(account.terms_accepted).to be_true
50
+ end
51
+
52
+ it "has an expiration date" do
53
+ expect(account).to respond_to :expiration_date
54
+ expect(account.expiration_date).to eq Time.at(expiration / 1000).to_datetime
55
+ end
56
+
57
+ it "provides direct access to documents" do
58
+ expect(account).to respond_to :document
59
+ end
60
+
61
+ it "delegates task of fetching the document to API" do
62
+ document_id = 1011
63
+ document_name = "NAME"
64
+
65
+ document_fixture = fixture(
66
+ "document",
67
+ :document_id => document_id,
68
+ :document_name => document_name
69
+ )
70
+
71
+ api.should_receive(
72
+ :get
73
+ ).with(
74
+ "/accounts/#{account_id}/documents/#{document_id}/meta-data.xml",
75
+ hash_including(
76
+ :action => 'get'
77
+ )
78
+ ).and_return(Gliffy::API::Response.new(document_fixture))
79
+
80
+ document = account.document(document_id)
81
+
82
+ expect(document.id).to eq document_id
83
+ expect(document.name).to eq document_name
84
+ expect(document.owner).to be account
85
+ end
86
+
87
+ it "has a root folder" do
88
+ expect(account).to respond_to :root
89
+ expect(account.root).to be_instance_of Gliffy::Folder
90
+ end
91
+
92
+ describe "root folder" do
93
+ subject(:root_folder) { account.root }
94
+
95
+ it "is named ROOT" do
96
+ expect(root_folder.name).to eq "ROOT"
97
+ end
98
+
99
+ it "has ROOT path" do
100
+ expect(root_folder.path).to eq "ROOT"
101
+ end
102
+
103
+ it "refers to the original account as owner" do
104
+ expect(root_folder.owner).to be account
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "an API facade" do
4
+ context "when sending GET request" do
5
+ it "forwards request to the API backend with HTTP protocol" do
6
+ api.should_receive(
7
+ :get
8
+ ).with(
9
+ match(url_matcher),
10
+ hash_including(params)
11
+ ).and_return(response)
12
+
13
+ expect(facade.get("/test", params)).to be response
14
+ end
15
+ end
16
+
17
+ context "when sending POST request" do
18
+ it "forwards request to the API backend with HTTP protocol" do
19
+ api.should_receive(
20
+ :post
21
+ ).with(
22
+ match(url_matcher),
23
+ hash_including(params)
24
+ ).and_return(response)
25
+
26
+ expect(facade.post("/test", params)).to be response
27
+ end
28
+ end
29
+
30
+ context "when GETting raw resource contents" do
31
+ it "forwards request to the API backend with HTTP protocol" do
32
+ api.should_receive(
33
+ :raw
34
+ ).with(
35
+ match(url_matcher),
36
+ hash_including(params)
37
+ ).and_return(response)
38
+
39
+ expect(facade.raw("/test", params)).to be response
40
+ end
41
+ end
42
+
43
+ context "when generating web link" do
44
+ it "forwards request to the API backend with HTTP protocol" do
45
+ api.should_receive(
46
+ :web
47
+ ).with(
48
+ match(url_matcher),
49
+ hash_including(params)
50
+ ).and_return(response)
51
+
52
+ expect(facade.web("/test", params)).to be response
53
+ end
54
+ end
55
+
56
+ context "when loading a list of folders" do
57
+ it "wraps own 'get' method" do
58
+ account_id = 99
59
+
60
+ facade.should_receive(
61
+ :get
62
+ ).with(
63
+ "/accounts/#{account_id}/folders.xml",
64
+ { :action => "get"}
65
+ ).and_return(response)
66
+
67
+ expect(facade.get_folders(account_id)).to be response
68
+ end
69
+ end
70
+ end
71
+
72
+ describe Gliffy::API::Facade do
73
+ let(:api) { double(Gliffy::API) }
74
+ let(:response) { double(Gliffy::API::Response) }
75
+ let(:params) {
76
+ {
77
+ :test1 => "value1",
78
+ :test2 => "value2"
79
+ }
80
+ }
81
+
82
+ describe "plain facade" do
83
+ let(:facade) { Gliffy::API::Facade.http(api) }
84
+
85
+ it_should_behave_like "an API facade" do
86
+ let(:url_matcher) { %{http://.+/test} }
87
+ end
88
+ end
89
+
90
+ describe "secure facade" do
91
+ let(:facade) { Gliffy::API::Facade.https(api) }
92
+
93
+ it_should_behave_like "an API facade" do
94
+ let(:url_matcher) { %{https://.+/test} }
95
+ end
96
+ end
97
+
98
+ describe "static methods" do
99
+ subject { Gliffy::API::Facade }
100
+
101
+ it "provide access to API via basic HTTP protocol" do
102
+ expect(subject).to respond_to :http
103
+ expect(subject.http(api)).to be_instance_of Gliffy::API::Facade
104
+ end
105
+
106
+ it "provide access to API via secure HTTPS protocol" do
107
+ expect(subject).to respond_to :https
108
+ expect(subject.https(api)).to be_instance_of Gliffy::API::Facade
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gliffy::API::Response do
4
+ let(:xml) { fixture("documents") }
5
+ let(:response) { Gliffy::API::Response.new(xml) }
6
+
7
+ it "allows to search node by XPath expression" do
8
+ expect(response).to respond_to :node
9
+ expect(
10
+ response.node("//g:documents")
11
+ ).to be_instance_of Gliffy::API::Response
12
+ end
13
+
14
+ it "allows to search for a set of nodes by XPath expression" do
15
+ expect(response).to respond_to :nodes
16
+
17
+ result = response.nodes("//g:document")
18
+ expect(result).to be_instance_of Array
19
+ expect(result.length).to eq 3
20
+ end
21
+
22
+ it "allows to access text node content" do
23
+ node = response.node("//g:document[3]/g:name")
24
+ expect(node).to respond_to :content
25
+ expect(
26
+ node.content
27
+ ).to eq "World Domination Flow"
28
+ end
29
+
30
+ it "allows to get string node content by XPath expression" do
31
+ expect(response).to respond_to :string
32
+ expect(
33
+ response.string("//g:document[2]/g:name")
34
+ ).to eq "SNPP Domain Model"
35
+ end
36
+
37
+ it "allows to get integer node content by XPath expression" do
38
+ expect(response).to respond_to :integer
39
+ expect(
40
+ response.integer("//g:document[1]/g:owner/@id")
41
+ ).to eq 202
42
+ end
43
+
44
+ it "allows to get timestamps by XPath expression" do
45
+ expect(response).to respond_to :timestamp
46
+ expect(
47
+ response.timestamp("//g:document[1]/g:create-date")
48
+ ).to eq Time.at(1215538283000 / 1000).to_datetime
49
+ end
50
+
51
+ it "allows to check for a node existence by XPath" do
52
+ expect(response).to respond_to :exists
53
+ expect(response.exists("//g:document[1]/@is-public")).to be_false
54
+ expect(response.exists("//g:document[2]/@is-public")).to be_true
55
+ end
56
+ end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gliffy::API do
4
+ let(:key) { "sample-key" }
5
+ let(:secret) { "sample-secret" }
6
+ let(:account_id) { 112233 }
7
+ let(:consumer) { double(OAuth::Consumer) }
8
+ let(:api) { Gliffy::API.new(account_id, key, secret) }
9
+
10
+ it "has an OAuth service consumer" do
11
+ expect(api).to respond_to :consumer
12
+ expect(api.consumer).to be_instance_of OAuth::Consumer
13
+ end
14
+
15
+ context "when being initialized" do
16
+ it "uses API key and shared secret to create a new OAuth consumer object" do
17
+ OAuth::Consumer.should_receive(
18
+ :new
19
+ ).with(
20
+ key,
21
+ secret,
22
+ hash_including(:site => Gliffy.web_root, :scheme => :query_string)
23
+ ).and_return(
24
+ consumer
25
+ )
26
+
27
+ api = Gliffy::API.new(account_id, key, secret)
28
+ expect(api.consumer).to be(consumer)
29
+ end
30
+ end
31
+
32
+ it "has a Gliffy API account id" do
33
+ expect(api).to respond_to :account_id
34
+ expect(api.account_id).to eq account_id
35
+ end
36
+
37
+ it "has a Giffy account" do
38
+ response = fixture(
39
+ "account",
40
+ :account_id => account_id,
41
+ :expiration => 1000
42
+ )
43
+ account = double(Gliffy::Account)
44
+
45
+ Gliffy::API::Facade.any_instance.stub(:get).and_return(response)
46
+ Gliffy::Account.should_receive(
47
+ :load
48
+ ).with(
49
+ instance_of(Gliffy::API::Facade),
50
+ response
51
+ ).and_return(account)
52
+
53
+ expect(api).to respond_to :account
54
+ expect(api.account).to be account
55
+ end
56
+
57
+ it "has an application name" do
58
+ expect(api).to respond_to :application_name
59
+ end
60
+
61
+ describe "application name" do
62
+ it "has a default value" do
63
+ expect(api.application_name).to eq Gliffy.default_application_name
64
+ end
65
+
66
+ it "can be overridden" do
67
+ expect(api).to respond_to :application_name=
68
+
69
+ test_name = "TEST APP NAME"
70
+ api.application_name = test_name
71
+ expect(api.application_name).to eq test_name
72
+ end
73
+ end
74
+
75
+ it "has a plain HTTP API facade" do
76
+ expect(api).to respond_to :plain
77
+ expect(api.plain).to be_instance_of Gliffy::API::Facade
78
+ end
79
+
80
+ it "has a secure HTTPS API facade" do
81
+ expect(api).to respond_to :secure
82
+ expect(api.secure).to be_instance_of Gliffy::API::Facade
83
+ end
84
+
85
+ it "handles GET requests" do
86
+ expect(api).to respond_to :get
87
+ end
88
+
89
+ it "handles raw GET requests" do
90
+ expect(api).to respond_to :raw
91
+ end
92
+
93
+ it "handles POST requests" do
94
+ expect(api).to respond_to :post
95
+ end
96
+
97
+ it "generates signed web links" do
98
+ expect(api).to respond_to :web
99
+ end
100
+
101
+ context "when doing a request" do
102
+ let(:url) { 'http://www.gliffy.com/test' }
103
+ let(:params) { { :param => 'value' } }
104
+ let(:xml) { fixture_xml("document", :document_id => 11, :document_name => "TEST" ) }
105
+ let(:raw) { double(Object, :body => xml) }
106
+
107
+ it "delegates to 'raw' call when doing GET" do
108
+ api.should_receive(
109
+ :raw
110
+ ).with(
111
+ url, params
112
+ ).and_return(xml)
113
+
114
+ result = api.get(url, params)
115
+
116
+ expect(result.exists('//g:documents')).to be_true
117
+ end
118
+
119
+ it "delegates raw GET requsts to OAuth token instance" do
120
+ OAuth::AccessToken.any_instance.should_receive(
121
+ :get
122
+ ).with(
123
+ 'http://www.gliffy.com/test?param=value'
124
+ ).and_return(raw)
125
+
126
+ result = api.raw(url, params)
127
+ expect(
128
+ result
129
+ ).to eq xml
130
+ end
131
+
132
+ it "delegates POST requests to OAuth token instance" do
133
+ OAuth::AccessToken.any_instance.should_receive(
134
+ :post
135
+ ).with(
136
+ url,
137
+ params
138
+ ).and_return(raw)
139
+
140
+ result = api.post(url, params)
141
+ expect(
142
+ result
143
+ ).to be_instance_of Gliffy::API::Response
144
+ expect(result.exists('//g:documents')).to be_true
145
+ end
146
+
147
+ it "delegates signed links generation to OAuth consumer" do
148
+ signed_url = "mock signed url value"
149
+
150
+ OAuth::Consumer.any_instance.should_receive(
151
+ :create_signed_request
152
+ ).with(
153
+ :get,
154
+ 'http://www.gliffy.com/test?param=value',
155
+ instance_of(OAuth::AccessToken)
156
+ ).and_return(double(Object, :path => signed_url))
157
+
158
+ expect(api.web(url, params)).to eq signed_url
159
+ end
160
+ end
161
+
162
+ it "allows to impersonate user" do
163
+ expect(api).to respond_to :impersonate
164
+ end
165
+
166
+ context "when impersonating user" do
167
+ let(:response) { Gliffy::API::Response.new(fixture("token")) }
168
+
169
+ it "sends POST to correct URL" do
170
+ escaped_user = URI.escape 'test@test.com'
171
+
172
+ Gliffy::API::Facade.any_instance.should_receive(
173
+ :post
174
+ ).with(
175
+ "/accounts/#{account_id}/users/#{escaped_user}/oauth_token.xml",
176
+ hash_including(:action => "create")
177
+ ).and_return(
178
+ response
179
+ )
180
+
181
+ api.impersonate("test@test.com")
182
+ end
183
+
184
+ it "updates OAuth token using server response" do
185
+ Gliffy::API::Facade.any_instance.should_receive(
186
+ :post
187
+ ).and_return(
188
+ response
189
+ )
190
+
191
+ OAuth::AccessToken.any_instance.should_receive(
192
+ :token=
193
+ ).with(
194
+ "140a1b58c248d13872499df769606766"
195
+ )
196
+
197
+ OAuth::AccessToken.any_instance.should_receive(
198
+ :secret=
199
+ ).with(
200
+ "481830f5827e35b0644a32c1caac5245"
201
+ )
202
+
203
+ api.impersonate("test@test.com")
204
+ end
205
+ end
206
+ end