wtforum 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/lib/wtforum.rb +125 -20
- data/lib/wtforum/session.rb +8 -18
- data/lib/wtforum/user.rb +16 -137
- data/lib/wtforum/version.rb +3 -4
- data/spec/fixtures/vcr_cassettes/WTForum_Session/when_user_doesn_t_exist/raises_an_exception.yml +67 -0
- data/spec/fixtures/vcr_cassettes/WTForum_Session/when_user_exists/can_log_in_users.yml +814 -0
- data/spec/fixtures/vcr_cassettes/WTForum_User/can_CRUD_users.yml +2965 -0
- data/spec/fixtures/vcr_cassettes/WTForum_User/raises_an_exception_when_a_user_is_not_found.yml +398 -0
- data/spec/integration/wtforum_session_spec.rb +14 -6
- data/spec/integration/wtforum_spec.rb +11 -0
- data/spec/integration/wtforum_user_spec.rb +13 -12
- data/spec/spec_helper.rb +18 -6
- data/wtforum.gemspec +2 -0
- metadata +73 -56
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 00474e1b12114c2ccf88d1ccc553c3f54cdc536d
|
4
|
+
data.tar.gz: f5efb1ed8f8c2213d5496d122970982a219f1bf9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0797211a73ee69f5784b3dfd5263f6cf76d76d2243d9ae247b1a0eea6ac1ed94afed767801978912ba5a5856379caab7c742d5e31fdee29991a8bc1345095b91
|
7
|
+
data.tar.gz: f0ecfb63998e32c27d0d5efb8b865926bf0e2a4bbc99feceb9381064e05dbad70a742639b88b57db86a5edda8bab072585e3984419f8c0bfd642f70d7366aa56
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
wtforum
|
data/lib/wtforum.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require "uri"
|
4
2
|
require "active_support/core_ext/object"
|
5
3
|
require "mechanize"
|
@@ -8,31 +6,138 @@ require "nokogiri"
|
|
8
6
|
require "wtforum/user"
|
9
7
|
require "wtforum/session"
|
10
8
|
|
11
|
-
|
9
|
+
class WTForum
|
12
10
|
class WTForumError < StandardError; end
|
13
11
|
|
14
|
-
|
15
|
-
|
12
|
+
def self.extract_value key, options
|
13
|
+
xml = Nokogiri::XML.parse(options[:from])
|
14
|
+
node = xml.css(key.to_s)
|
15
|
+
if node.present?
|
16
|
+
node.text
|
17
|
+
else
|
18
|
+
raise WTForumError, xml.css("errormessage, error, .errorMsg").text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_accessor :domain, :api_key, :admin_username, :admin_password
|
23
|
+
|
24
|
+
def initialize credentials
|
25
|
+
credentials.each do |key, value|
|
26
|
+
self.send :"#{key}=", value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_session user_id
|
31
|
+
uri = base_api_uri(userid: user_id)
|
32
|
+
uri.path = "/register/setauthtoken"
|
33
|
+
response = agent.get uri
|
34
|
+
Session.create self, response
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_user attributes
|
38
|
+
defaults = { pw: Digest::MD5.hexdigest(attributes.to_s) }
|
39
|
+
attributes[:member] ||= attributes.delete(:username)
|
40
|
+
attributes[:field276177] ||= attributes.delete(:gender)
|
41
|
+
attributes[:field276178] ||= attributes.delete(:location)
|
42
|
+
attributes[:field276179] ||= attributes.delete(:about)
|
43
|
+
attributes.reverse_merge! defaults
|
16
44
|
|
17
|
-
|
18
|
-
|
45
|
+
uri = base_api_uri(attributes)
|
46
|
+
uri.path = "/register/create_account"
|
47
|
+
response = agent.get uri
|
48
|
+
User.create self, response, attributes
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_user user_id
|
52
|
+
response = authorized_agent.get uri(path: "/register/register", query: "edit=1&userid=#{user_id}")
|
53
|
+
raise User::NotFound if response.body.include?("Error: The specified account was not found")
|
54
|
+
|
55
|
+
body = Nokogiri::HTML.parse(response.body)
|
56
|
+
attributes = {
|
57
|
+
id: user_id,
|
58
|
+
member: body.css(".tables td:contains('Username:') + td input").first["value"],
|
59
|
+
email: body.css(".tables td:contains('Email Address:') + td").first.text.split(" - ").first,
|
60
|
+
name: body.css(".tables td:contains('Full Name:') + td input").first["value"],
|
61
|
+
field276177: body.css(".tables select[name='field276177'] option[selected]").first.try(:text).try(:strip),
|
62
|
+
field276178: body.css(".tables input[name='field276178']").first["value"],
|
63
|
+
field276179: body.css(".tables textarea[name='field276179']").first.text
|
64
|
+
}
|
65
|
+
User.new(self, attributes)
|
66
|
+
end
|
67
|
+
|
68
|
+
def find_user_by_username username
|
69
|
+
response = authorized_agent.get uri(path: "/register", query: "action=members&search=true&s_username=#{username}")
|
70
|
+
body = Nokogiri::HTML.parse(response.body)
|
71
|
+
|
72
|
+
# scrape markup: <a href="/profile/1234567" title="View profile">username\t\n</a>
|
73
|
+
# search returns partial matches :( so find the exact match.
|
74
|
+
# hopefully there aren't more than 50 matches!
|
75
|
+
link = body.css("a[title='View profile']:contains('#{username}')").find do |a|
|
76
|
+
a.text.strip == username
|
19
77
|
end
|
20
78
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
79
|
+
link or raise User::NotFound
|
80
|
+
|
81
|
+
id = link["href"].split("/").last
|
82
|
+
find_user(id)
|
83
|
+
end
|
84
|
+
|
85
|
+
def edit_user user_id
|
86
|
+
response = authorized_agent.get uri(path: "/register/register", query: "edit=1&userid=#{user_id}")
|
87
|
+
end
|
88
|
+
|
89
|
+
def edit_user_username user_id
|
90
|
+
authorized_agent.get uri(path: "/register/edit_username", query: "userid=#{user_id}")
|
91
|
+
end
|
92
|
+
|
93
|
+
def edit_user_email user_id
|
94
|
+
authorized_agent.get uri(path: "/register/edit_password", query: "userid=#{user_id}")
|
95
|
+
end
|
96
|
+
|
97
|
+
def count_users
|
98
|
+
response = agent.get uri(path: "/register/members")
|
99
|
+
count = response.body.match(/Members\s+\(([\d,]+)\)/m)[1]
|
100
|
+
count.gsub(",", "").to_i
|
101
|
+
end
|
102
|
+
|
103
|
+
def destroy_user user_id
|
104
|
+
authorized_agent.get uri(path: "/register/delete", query: "mem_userid=#{user_id}")
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def authorized_agent
|
110
|
+
@authorized_agent ||= begin
|
111
|
+
a = agent
|
112
|
+
a.get(login_uri)
|
113
|
+
a
|
26
114
|
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def agent
|
118
|
+
Mechanize.new
|
119
|
+
end
|
120
|
+
|
121
|
+
def base_uri
|
122
|
+
URI("http://#{domain}")
|
123
|
+
end
|
27
124
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
125
|
+
def base_api_uri attributes={}
|
126
|
+
attributes[:apikey] = api_key
|
127
|
+
uri = base_uri
|
128
|
+
uri.query = attributes.to_param
|
129
|
+
uri
|
130
|
+
end
|
131
|
+
|
132
|
+
def login_uri
|
133
|
+
uri path: "/register/dologin", query: "member=#{admin_username}&pw=#{admin_password}&remember=checked"
|
134
|
+
end
|
135
|
+
|
136
|
+
def uri attributes
|
137
|
+
base_uri.tap do |uri|
|
138
|
+
uri.path = attributes[:path]
|
139
|
+
uri.query = attributes[:query]
|
36
140
|
end
|
37
141
|
end
|
38
142
|
end
|
143
|
+
|
data/lib/wtforum/session.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module WTForum
|
1
|
+
class WTForum
|
4
2
|
class Session
|
5
|
-
def self.create
|
6
|
-
|
7
|
-
|
8
|
-
auth_token = WTForum.extract_value(:authtoken, from: page.body)
|
9
|
-
new(auth_token)
|
3
|
+
def self.create wtforum, response
|
4
|
+
auth_token = WTForum.extract_value(:authtoken, from: response.body)
|
5
|
+
new(wtforum, auth_token)
|
10
6
|
rescue WTForumError => e
|
11
7
|
if e.message == "Error: The specified user does not exist."
|
12
8
|
raise WTForum::User::NotFound
|
@@ -15,18 +11,12 @@ module WTForum
|
|
15
11
|
end
|
16
12
|
end
|
17
13
|
|
18
|
-
def initialize token
|
14
|
+
def initialize wtforum, token
|
15
|
+
@wtforum = wtforum
|
19
16
|
@token = token
|
20
17
|
end
|
21
18
|
|
22
|
-
attr_reader :token
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def self.create_uri user_id
|
27
|
-
uri = WTForum.base_api_uri(userid: user_id)
|
28
|
-
uri.path = "/register/setauthtoken"
|
29
|
-
uri
|
30
|
-
end
|
19
|
+
attr_reader :wtforum, :token
|
31
20
|
end
|
32
21
|
end
|
22
|
+
|
data/lib/wtforum/user.rb
CHANGED
@@ -1,76 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "securerandom"
|
4
|
-
|
5
|
-
module WTForum
|
1
|
+
class WTForum
|
6
2
|
class User
|
7
3
|
class NotFound < StandardError; end
|
8
4
|
|
9
|
-
def self.create attributes
|
10
|
-
|
11
|
-
attributes[:member] ||= attributes.delete(:username)
|
12
|
-
attributes[:field276177] ||= attributes.delete(:gender)
|
13
|
-
attributes[:field276178] ||= attributes.delete(:location)
|
14
|
-
attributes[:field276179] ||= attributes.delete(:about)
|
15
|
-
attributes.reverse_merge! defaults
|
16
|
-
uri = create_uri attributes
|
17
|
-
|
18
|
-
page = agent.get(uri)
|
19
|
-
user_id = WTForum.extract_value(:userid, :from => page.body)
|
5
|
+
def self.create wtforum, response, attributes
|
6
|
+
user_id = WTForum.extract_value(:userid, from: response.body)
|
20
7
|
attributes[:id] = user_id.to_i
|
21
|
-
new(attributes)
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.find user_id
|
25
|
-
page = authorized_agent.get(find_uri(user_id))
|
26
|
-
raise NotFound if page.body.include?("Error: The specified account was not found")
|
27
|
-
|
28
|
-
body = Nokogiri::HTML.parse(page.body)
|
29
|
-
attributes = {
|
30
|
-
id: user_id,
|
31
|
-
member: body.css(".tables td:contains('Username:') + td input").first["value"],
|
32
|
-
email: body.css(".tables td:contains('Email Address:') + td").first.text.split(" - ").first,
|
33
|
-
name: body.css(".tables td:contains('Full Name:') + td input").first["value"],
|
34
|
-
field276177: body.css(".tables select[name='field276177'] option[selected]").first.try(:text),
|
35
|
-
field276178: body.css(".tables input[name='field276178']").first["value"],
|
36
|
-
field276179: body.css(".tables textarea[name='field276179']").first.text
|
37
|
-
}
|
38
|
-
new(attributes)
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.find_by_username username
|
42
|
-
page = authorized_agent.get(find_by_username_uri(username))
|
43
|
-
body = Nokogiri::HTML.parse(page.body)
|
44
|
-
|
45
|
-
# scrape markup: <a href="/profile/1234567" title="View profile">username\t\n</a>
|
46
|
-
# search returns partial matches :( so find the exact match.
|
47
|
-
# hopefully there aren't more than 50 matches!
|
48
|
-
link = body.css("a[title='View profile']:contains('#{username}')").find do |a|
|
49
|
-
a.text.strip == username
|
50
|
-
end
|
51
|
-
|
52
|
-
link or raise NotFound
|
53
|
-
|
54
|
-
id = link["href"].split("/").last
|
55
|
-
find id
|
8
|
+
new(wtforum, attributes)
|
56
9
|
end
|
57
10
|
|
58
|
-
def self.update user_id, attributes
|
59
|
-
|
11
|
+
def self.update wtforum, user_id, attributes
|
12
|
+
wtforum.find_user(user_id).update_attributes!(attributes)
|
60
13
|
end
|
61
14
|
|
62
|
-
def self.destroy user_id
|
63
|
-
|
15
|
+
def self.destroy wtforum, user_id
|
16
|
+
wtforum.destroy_user(user_id)
|
64
17
|
true
|
65
18
|
end
|
66
19
|
|
67
|
-
def
|
68
|
-
|
69
|
-
count = page.body.match(/Members \(([\d,]+)\)/)[1]
|
70
|
-
count.gsub(",", "").to_i
|
71
|
-
end
|
72
|
-
|
73
|
-
def initialize attributes
|
20
|
+
def initialize wtforum, attributes
|
21
|
+
self.wtforum = wtforum
|
74
22
|
self.attributes = attributes
|
75
23
|
end
|
76
24
|
|
@@ -80,7 +28,7 @@ module WTForum
|
|
80
28
|
end
|
81
29
|
|
82
30
|
def save!
|
83
|
-
|
31
|
+
wtforum.edit_user(id).tap do |page|
|
84
32
|
form = page.forms.first
|
85
33
|
form["name"] = name
|
86
34
|
form["field276177"] = field276177
|
@@ -88,12 +36,12 @@ module WTForum
|
|
88
36
|
form["field276179"] = field276179
|
89
37
|
form.submit
|
90
38
|
end
|
91
|
-
|
39
|
+
wtforum.edit_user_username(id).tap do |page|
|
92
40
|
form = page.forms.first
|
93
41
|
form["new_username"] = username
|
94
42
|
form.submit
|
95
43
|
end
|
96
|
-
|
44
|
+
wtforum.edit_user_email(id).tap do |page|
|
97
45
|
form = page.forms.first
|
98
46
|
form["email"] = email
|
99
47
|
form.submit
|
@@ -101,10 +49,10 @@ module WTForum
|
|
101
49
|
end
|
102
50
|
|
103
51
|
def destroy
|
104
|
-
self.class.destroy id
|
52
|
+
self.class.destroy self.wtforum, id
|
105
53
|
end
|
106
54
|
|
107
|
-
attr_accessor :id, :member, :email, :name, :field276177, :field276178, :field276179
|
55
|
+
attr_accessor :wtforum, :id, :member, :email, :name, :field276177, :field276178, :field276179
|
108
56
|
attr_writer :pw, :apikey
|
109
57
|
|
110
58
|
def username
|
@@ -146,75 +94,6 @@ module WTForum
|
|
146
94
|
send :"#{key}=", value
|
147
95
|
end
|
148
96
|
end
|
149
|
-
|
150
|
-
def self.agent
|
151
|
-
Mechanize.new
|
152
|
-
end
|
153
|
-
|
154
|
-
def self.authorized_agent
|
155
|
-
@authorized_agent ||= begin
|
156
|
-
a = agent
|
157
|
-
a.get(login_uri)
|
158
|
-
a
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.login_uri
|
163
|
-
uri = WTForum.base_uri
|
164
|
-
uri.path = "/register/dologin"
|
165
|
-
uri.query = "member=#{WTForum.admin_username}&pw=#{WTForum.admin_password}&remember=checked"
|
166
|
-
uri
|
167
|
-
end
|
168
|
-
|
169
|
-
def self.create_uri attributes
|
170
|
-
uri = WTForum.base_api_uri(attributes)
|
171
|
-
uri.path = "/register/create_account"
|
172
|
-
uri
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.find_uri user_id
|
176
|
-
uri = WTForum.base_uri
|
177
|
-
uri.path = "/register/register"
|
178
|
-
uri.query = "edit=1&userid=#{user_id}"
|
179
|
-
uri
|
180
|
-
end
|
181
|
-
|
182
|
-
def self.find_by_username_uri username
|
183
|
-
uri = WTForum.base_uri
|
184
|
-
uri.path = "/register"
|
185
|
-
uri.query = "action=members&search=true&s_username=#{username}"
|
186
|
-
uri
|
187
|
-
end
|
188
|
-
|
189
|
-
def self.edit_uri user_id
|
190
|
-
find_uri user_id
|
191
|
-
end
|
192
|
-
|
193
|
-
def self.edit_username_uri user_id
|
194
|
-
uri = WTForum.base_uri
|
195
|
-
uri.path = "/register/edit_username"
|
196
|
-
uri.query = "userid=#{user_id}"
|
197
|
-
uri
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.edit_email_uri user_id
|
201
|
-
uri = WTForum.base_uri
|
202
|
-
uri.path = "/register/edit_password"
|
203
|
-
uri.query = "userid=#{user_id}"
|
204
|
-
uri
|
205
|
-
end
|
206
|
-
|
207
|
-
def self.count_uri
|
208
|
-
uri = WTForum.base_uri
|
209
|
-
uri.path = "/register/members"
|
210
|
-
uri
|
211
|
-
end
|
212
|
-
|
213
|
-
def self.destroy_uri user_id
|
214
|
-
uri = WTForum.base_uri
|
215
|
-
uri.path = "/register/delete"
|
216
|
-
uri.query = "mem_userid=#{user_id}"
|
217
|
-
uri
|
218
|
-
end
|
219
97
|
end
|
220
98
|
end
|
99
|
+
|
data/lib/wtforum/version.rb
CHANGED
data/spec/fixtures/vcr_cassettes/WTForum_Session/when_user_doesn_t_exist/raises_an_exception.yml
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://forums.complexityexplorer.org/register/setauthtoken?apikey=pteGzAPZyr4&userid=1
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip,deflate,identity
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Mechanize/2.5.1 Ruby/2.0.0p195 (http://github.com/tenderlove/mechanize/)
|
16
|
+
Accept-Charset:
|
17
|
+
- ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
18
|
+
Accept-Language:
|
19
|
+
- en-us,en;q=0.5
|
20
|
+
Host:
|
21
|
+
- forums.complexityexplorer.org
|
22
|
+
Connection:
|
23
|
+
- keep-alive
|
24
|
+
Keep-Alive:
|
25
|
+
- 300
|
26
|
+
response:
|
27
|
+
status:
|
28
|
+
code: 200
|
29
|
+
message: OK
|
30
|
+
headers:
|
31
|
+
Cache-Control:
|
32
|
+
- no-cache, no-store, must-revalidate
|
33
|
+
Content-Encoding:
|
34
|
+
- gzip
|
35
|
+
Content-Type:
|
36
|
+
- text/xml
|
37
|
+
Date:
|
38
|
+
- Wed, 04 Sep 2013 18:33:52 GMT
|
39
|
+
Expires:
|
40
|
+
- Nov, 8 1991 00:00:01 GMT
|
41
|
+
P3p:
|
42
|
+
- CP='NOI DSP COR NID CURa TAIi OUR BUS INT PRE'; policyref='http://forums.complexityexplorer.org/w3c/p3p.xml';
|
43
|
+
Pragma:
|
44
|
+
- no-cache
|
45
|
+
Server:
|
46
|
+
- nginx/1.0.10
|
47
|
+
Set-Cookie:
|
48
|
+
- hascookies=1; path=/; domain=.forums.complexityexplorer.org;
|
49
|
+
- lastvisit=1378319632; path=/; domain=.forums.complexityexplorer.org; expires=Wed,
|
50
|
+
25-Aug-2020 00:00:00 GMT;
|
51
|
+
- newvisit=1378319632; path=/; domain=.forums.complexityexplorer.org; expires=Wed,
|
52
|
+
25-Aug-2020 00:00:00 GMT;
|
53
|
+
Vary:
|
54
|
+
- Accept-Encoding
|
55
|
+
Content-Length:
|
56
|
+
- '123'
|
57
|
+
Connection:
|
58
|
+
- keep-alive
|
59
|
+
body:
|
60
|
+
encoding: ASCII-8BIT
|
61
|
+
string: !binary |-
|
62
|
+
H4sIAAAAAAAAA1XMQQ6CQAxG4as0sxd0Z0gZVnoCPABhfrGJtKRFwvENGxOX
|
63
|
+
b/E97vb5TRs8xLRNl+qcCDpaEZ3a9Ojvp2vqMjtiMQ1khrv5jIhhQr4d0VD/
|
64
|
+
AsWCUZ6CQp+AUzEEqa2EXWKtuP5zXP+GX3LWZ2qBAAAA
|
65
|
+
http_version:
|
66
|
+
recorded_at: Wed, 04 Sep 2013 18:33:52 GMT
|
67
|
+
recorded_with: VCR 2.5.0
|