zenbe-flareshow 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{flareshow}
8
- s.version = "0.2.4"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Will Bailey"]
12
- s.date = %q{2009-09-11}
13
- s.description = %q{TODO: a ruby gem for interacting with the shareflow collaboration service by Zenbe}
12
+ s.date = %q{2009-09-12}
13
+ s.description = %q{a ruby gem for interacting with the shareflow collaboration service by Zenbe}
14
14
  s.email = %q{will.bailey@gmail.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
@@ -30,8 +30,10 @@ Gem::Specification.new do |s|
30
30
  "lib/file_attachment.rb",
31
31
  "lib/flareshow.rb",
32
32
  "lib/flow.rb",
33
+ "lib/http_encoding_helper.rb",
33
34
  "lib/invitation.rb",
34
35
  "lib/membership.rb",
36
+ "lib/mime_parts.rb",
35
37
  "lib/post.rb",
36
38
  "lib/resource.rb",
37
39
  "lib/searchable.rb",
@@ -46,8 +48,8 @@ Gem::Specification.new do |s|
46
48
  s.rdoc_options = ["--charset=UTF-8"]
47
49
  s.require_paths = ["lib"]
48
50
  s.rubyforge_project = %q{flareshow}
49
- s.rubygems_version = %q{1.3.5}
50
- s.summary = %q{TODO: a ruby gem for interacting with the shareflow collaboration service}
51
+ s.rubygems_version = %q{1.3.4}
52
+ s.summary = %q{a ruby gem for interacting with the shareflow collaboration service}
51
53
  s.test_files = [
52
54
  "test/flareshow_test.rb",
53
55
  "test/test_helper.rb"
data/README.md CHANGED
@@ -91,7 +91,7 @@ Flareshow offers an ActiveRecord like syntax for retrieving and manipulating mod
91
91
  f.name = 'a different name'
92
92
  f.save
93
93
 
94
- ### Inviting someone to a flow (only available if you are the creator of the flow)
94
+ #### inviting someone to a flow (only available if you are the creator of the flow)
95
95
 
96
96
  f=Flow.find_by_name('test')
97
97
  f.send_invitations('test@test.com')
@@ -99,21 +99,21 @@ Flareshow offers an ActiveRecord like syntax for retrieving and manipulating mod
99
99
  # this also works
100
100
  f.send_invitations(['test1@test.com', 'test2@test.com'])
101
101
 
102
- ### Canceling an invitation to a flow (only available if you are the creator of the flow)
102
+ #### canceling an invitation to a flow (only available if you are the creator of the flow)
103
103
 
104
104
  f=Flow.find_by_name('test')
105
105
  # revoke an invitation by the email address that was invited
106
106
  f.revoke_invitations('test@test.com')
107
107
 
108
108
 
109
- ### Removing a user from a flow (only available if you are the creator of the flow)
109
+ #### removing a user from a flow (only available if you are the creator of the flow)
110
110
 
111
111
  f = Flow.find_by_name('test')
112
112
  users = f.list_users # get a listing of the users on the flow
113
113
  # remove the last user in the list from the flow...you cant remove yourself in this way
114
114
  f.remove_members(users.last.id)
115
115
 
116
- ### listing all the users on a flow
116
+ #### listing all the users on a flow
117
117
 
118
118
  f=Flow.first
119
119
  f.list_users
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.3.0
@@ -3,16 +3,19 @@ ROOT = File.dirname(__FILE__) unless defined? ROOT
3
3
  # gems
4
4
  require 'rubygems' #TODO fix
5
5
  require 'json'
6
- require 'curb'
7
6
  require 'facets'
8
7
  require 'facets/dictionary'
9
8
  require 'uuid'
10
- require 'ruby-debug'
9
+ require 'mime/types'
10
+ require 'cgi'
11
11
 
12
12
  # std lib
13
+ require 'net/http'
14
+ require 'net/https'
13
15
  require 'ostruct'
14
16
  require 'yaml'
15
17
  require 'logger'
18
+ require 'ruby-debug'
16
19
 
17
20
  # Application Constants and configuration
18
21
  module Flareshow
@@ -47,6 +50,7 @@ Dir.glob(File.join(ROOT, "*.rb")).each{|lib| require lib}
47
50
  config_file_path = File.expand_path("~/.flareshowrc")
48
51
  if File.exists?(config_file_path) && !Flareshow::Service.authenticated?
49
52
  data = YAML.load_file(config_file_path)
53
+ Flareshow::Service.debug_output=true if data["debug_http"]
50
54
  host = data["host"] || "biz.zenbe.com"
51
55
  subdomain = data["subdomain"]
52
56
  DEFAULT_LOGGER.level = data["log_level"].to_i if data["log_level"]
@@ -0,0 +1,49 @@
1
+ # Intended to extend the Net::HTTP response object
2
+ # and adds support for decoding gzip and deflate encoded pages
3
+ #
4
+ # Author: Jason Stirk <http://griffin.oobleyboo.com>
5
+ # Home: http://griffin.oobleyboo.com/projects/http_encoding_helper
6
+ # Created: 5 September 2007
7
+ # Last Updated: 23 November 2007
8
+ #
9
+ # Usage:
10
+ #
11
+ # require 'net/http'
12
+ # require 'http_encoding_helper'
13
+ # headers={'Accept-Encoding' => 'gzip, deflate' }
14
+ # http = Net::HTTP.new('griffin.oobleyboo.com', 80)
15
+ # http.start do |h|
16
+ # request = Net::HTTP::Get.new('/', headers)
17
+ # response = http.request(request)
18
+ # content=response.plain_body # Method from our library
19
+ # puts "Transferred: #{response.body.length} bytes"
20
+ # puts "Compression: #{response['content-encoding']}"
21
+ # puts "Extracted: #{response.plain_body.length} bytes"
22
+ # end
23
+ #
24
+
25
+ require 'zlib'
26
+ require 'stringio'
27
+
28
+ class Net::HTTPResponse
29
+ # Return the uncompressed content
30
+ def plain_body
31
+ encoding=self['content-encoding']
32
+ content=nil
33
+ if encoding then
34
+ case encoding
35
+ when 'gzip'
36
+ i=Zlib::GzipReader.new(StringIO.new(self.body))
37
+ content=i.read
38
+ when 'deflate'
39
+ i=Zlib::Inflate.new
40
+ content=i.inflate(self.body)
41
+ else
42
+ raise "Unknown encoding - #{encoding}"
43
+ end
44
+ else
45
+ content=self.body
46
+ end
47
+ return content
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ # Adapted From : http://deftcode.com/code/flickr_upload/multipartpost.rb
2
+
3
+ class Param
4
+ attr_accessor :key, :value, :content_type
5
+ def initialize(key, value, content_type)
6
+ @key = key; @value = value; @content_type = content_type
7
+ end
8
+
9
+ def to_multipart
10
+ return "\r\nContent-Disposition: form-data; name=\"#{CGI::escape(key)}\"\r\n" +
11
+ "Content-Type: #{content_type}; charset=UTF-8" +
12
+ "\r\n\r\n#{value}\r\n"
13
+ end
14
+ end
15
+
16
+ class FileParam
17
+ attr_accessor :key, :filename, :content
18
+ def initialize( key, filename, content )
19
+ @key = key; @filename = filename; @content = content
20
+ end
21
+
22
+ def to_multipart
23
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(key)}\"; filename=\"#{filename}\"\r\n" +
24
+ "Content-Transfer-Encoding: binary\r\n" +
25
+ "Content-type: #{MIME::Types.type_for(filename)}\r\n\r\n" + content + "\r\n"
26
+ end
27
+ end
28
+
29
+ class MultipartPost
30
+ BOUNDARY = "flareshow_multipart_boundary_A0n23hja"
31
+ HEADER = {"Content-type" => "multipart/form-data, boundary=" + BOUNDARY + " "}
32
+
33
+ def self.prepare_query(params)
34
+ query = params.map {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
35
+ [query, HEADER]
36
+ end
37
+ end
@@ -97,6 +97,7 @@ class Flareshow::Resource
97
97
  self
98
98
  rescue Exception => e
99
99
  Flareshow::Util.log_error e.message
100
+ Flareshow::Util.log_error e.backtrace.join("\n")
100
101
  throw e
101
102
  false
102
103
  end
@@ -5,22 +5,23 @@ class Flareshow::Service
5
5
  # = Class Methods =
6
6
  # =================
7
7
  class << self
8
- attr_accessor :server
8
+ attr_accessor :server, :debug_output, :key
9
9
 
10
10
  # setup the service to use a particular host and domain
11
11
  def configure(subdomain=nil, host='api.zenbe.com')
12
12
  raise Flareshow::ConfigurationException unless subdomain
13
13
  self.server=Server.new(host, subdomain)
14
+ @auth_endpoint = @api_endpoint = nil
14
15
  end
15
16
 
16
17
  # return the authentication endpoint for a given host and domain
17
18
  def auth_endpoint
18
- "http://#{server.host}/#{server.domain}/shareflow/api/v2/auth.json"
19
+ @auth_endpoint ||= URI.parse("http://#{server.host}/#{server.domain}/shareflow/api/v2/auth.json")
19
20
  end
20
21
 
21
22
  # return the api endpoint for a given host and domain
22
23
  def api_endpoint
23
- "http://#{server.host}/#{server.domain}/shareflow/api/v2.json"
24
+ @api_endpoint ||= URI.parse("http://#{server.host}/#{server.domain}/shareflow/api/v2.json")
24
25
  end
25
26
 
26
27
  # has the server been configured?
@@ -33,73 +34,74 @@ class Flareshow::Service
33
34
  # - status code
34
35
  # - headers
35
36
  # - body
36
- def post(url, params)
37
+ def post(uri, params, files=[])
37
38
  raise Flareshow::ConfigurationException unless server_defined?
38
- request = Curl::Easy.new(url) do |curl|
39
- curl.headers = {
40
- 'Accept' => 'application/json',
41
- 'User-Agent' => 'flareshow 0.1'
42
- }
43
- curl.multipart_form_post=true
44
- end
45
- request.http_post(*params)
46
- response = process_response(request)
39
+ # create the request object
40
+ req = Net::HTTP::Post.new(uri.path)
41
+ # set request headers
42
+ req.add_field "Accept", "application/json"
43
+ req.add_field "User-Agent", "ruby flareshow"
44
+ req.add_field "Accept-Encoding", "compress, gzip"
47
45
 
48
- # log a service exception
49
- case response["status_code"]
50
- when 400
51
- log_service_error(response)
52
- when 500
53
- log_service_error(response)
54
- when 403
55
- log_service_error(response)
56
- end
57
-
58
- response
59
- end
60
-
61
- # do a get request
62
- def http_get(url)
63
- request = Curl::Easy.new(url + "?key=#{@key}") do |curl|
64
- curl.headers = {
65
- 'User-Agent' => 'flareshow 0.1'
46
+ # just json
47
+ if !files || files.empty?
48
+ req.add_field "Content-type", "application/json; charset=UTF-8"
49
+ # set the postbody
50
+ req.body = params.to_json
51
+ # handle file params
52
+ else
53
+ params = params.map{|p|
54
+ val = p[1].is_a?(String) ? p[1] : p[1].to_json
55
+ Param.new(p[0], val, "application/json")
66
56
  }
57
+ files.each do |f|
58
+ params << FileParam.new(f["part_id"], f["file_path"], File.read(f["file_path"]))
59
+ end
60
+ body, header = *MultipartPost.prepare_query(params)
61
+ req.add_field "Content-type", header["Content-type"]
62
+ req.body = body
67
63
  end
68
- request.perform()
69
- response = process_response(request)
70
64
 
71
- Flareshow::Util.log_error("resource not found") if response["status_code"] == 404
65
+ # make the request
66
+ http = Net::HTTP.new(uri.host, uri.port)
67
+ http.set_debug_output DEFAULT_LOGGER if debug_output
68
+ response = http.start {|h| h.request(req)}
72
69
 
70
+ # normalize the response
71
+ response = process_response(response)
72
+ log_response(response)
73
73
  response
74
74
  end
75
75
 
76
- # get the interesting bits out of the curl response
77
- def process_response(request)
78
- response = {"status_code" => request.response_code, "headers" => request.header_str, "body" => request.body_str}
79
- if (/json/i).match(request.content_type)
80
- response["resources"] = JSON.parse(response["body"])
81
- end
82
- Flareshow::Util.log_info(response["status_code"])
83
- Flareshow::Util.log_info(response["body"])
76
+ # do a get request
77
+ def http_get(uri)
78
+ uri = URI.parse(uri) unless uri.is_a? URI
79
+ req = Net::HTTP::Get.new(uri.path + "?key=#{@key}")
80
+ req.add_field "User-Agent", "ruby flareshow"
81
+ http = Net::HTTP.new(uri.host, uri.port)
82
+ http.set_debug_output DEFAULT_LOGGER if debug_output
83
+ response = http.start{|h|http.request(req)}
84
+ response = process_response(response)
85
+ Flareshow::Util.log_error("resource not found") if response["status_code"] == 404
84
86
  response
85
87
  end
86
88
 
87
- # log a service error
88
- def log_service_error(response)
89
- if response["resources"]
90
- Flareshow::Util.log_error(response["resources"]["message"])
91
- Flareshow::Util.log_error(response["resources"]["details"])
92
- else
93
- Flareshow::Util.log_error(response["body"])
89
+ # log the response
90
+ def log_response(response)
91
+ # log a service exception
92
+ case response["status_code"]
93
+ when 400
94
+ log_service_error(response)
95
+ when 500
96
+ log_service_error(response)
97
+ when 403
98
+ log_service_error(response)
94
99
  end
95
100
  end
96
101
 
97
102
  # authenticate with the server using an http post
98
103
  def authenticate(login, password)
99
- params = [
100
- Curl::PostField.content("login", login),
101
- Curl::PostField.content("password", password)
102
- ]
104
+ params = {:login => login, :password => password}
103
105
  response = post(auth_endpoint, params)
104
106
  # store the auth token returned from the authentication request
105
107
  if response["status_code"] == 200
@@ -110,59 +112,82 @@ class Flareshow::Service
110
112
  end
111
113
  rescue Exception => e
112
114
  Flareshow::Util.log_error e.message
113
- end
114
-
115
- # clear the authenticated session
116
- def logout
117
- @key = nil
118
- end
119
-
120
- # are we authenticated
121
- def authenticated?
122
- !!@key
115
+ Flareshow::Util.log_error e.backtrace.join("\n")
123
116
  end
124
117
 
125
118
  # query the server with an http post of the query params
126
119
  def query(params={})
127
120
  raise Flareshow::AuthenticationRequired unless @key
128
-
129
- # add the json request parts
130
- params = [
131
- Curl::PostField.content("key", @key, 'application/json'),
132
- Curl::PostField.content("query", params.to_json, 'application/json')
133
- ]
134
-
121
+ params = {"key" => @key, "query" => params}
135
122
  post(api_endpoint, params)
136
123
  end
137
124
 
138
125
  # commit changes to the server with an http post
139
126
  def commit(params={}, files=[])
140
127
  raise Flareshow::AuthenticationRequired unless @key
141
-
142
- curl_params = []
143
- has_files = false
144
- if params["posts"]
145
- # add any file parts passed in and assign a part id to the
146
- params["posts"] = (params["posts"]).map do |f|
147
- if f["files"]
148
- f["files"] = (f["files"]).each do |ff|
149
- has_files = true
150
- curl_params.push(Curl::PostField.file(ff["part_id"], ff["file_path"]))
128
+ params, files = *files_from_params(params) if params["posts"]
129
+ params = {"key" => @key, "data" => params}
130
+ post(api_endpoint, params, files)
131
+ end
132
+
133
+ # get the files out of the params
134
+ def files_from_params(params)
135
+ files = []
136
+ # add any file parts passed in and assign a part id to the
137
+ params["posts"] = (params["posts"]).map do |f|
138
+ if f["files"]
139
+ f["files"] = (f["files"]).map do |ff|
140
+ # we only want to send up new files from the client so we'll strip out any existing
141
+ # files in the params that came down from the server
142
+ val = nil
143
+ if ff["part_id"]
144
+ val = {"part_id" => ff["part_id"], "file_path" => ff["file_path"]}
145
+ files << val
151
146
  end
152
- end
153
- f
147
+ val
148
+ end.compact
154
149
  end
150
+ f
155
151
  end
152
+ [params, files]
153
+ end
154
+
155
+ # get the interesting bits out of the curl response
156
+ def process_response(response)
157
+ # read the response headers
158
+ headers = {}; response.each_header{|k,v| headers[k] = v}
159
+ # build a response object
160
+ response_obj = {"status_code" => response.code.to_i, "headers" => headers, "body" => response.plain_body}
156
161
 
157
- params["files"] = []
158
-
159
- # add the json request parts
160
- curl_params += [
161
- Curl::PostField.content("key", @key, 'application/json'),
162
- Curl::PostField.content("data", params.to_json, 'application/json')
163
- ]
162
+ # automatically handle json response
163
+ if (/json/i).match(response.content_type)
164
+ response_obj["resources"] = JSON.parse(response_obj["body"])
165
+ end
164
166
 
165
- post(api_endpoint, curl_params)
167
+ # log the response
168
+ Flareshow::Util.log_info(response_obj["status_code"])
169
+ Flareshow::Util.log_info(response_obj["body"])
170
+ response_obj
171
+ end
172
+
173
+ # log a service error
174
+ def log_service_error(response)
175
+ if response["resources"]
176
+ Flareshow::Util.log_error(response["resources"]["message"])
177
+ Flareshow::Util.log_error(response["resources"]["details"])
178
+ else
179
+ Flareshow::Util.log_error(response["body"])
180
+ end
181
+ end
182
+
183
+ # clear the authenticated session
184
+ def logout
185
+ @key = nil
186
+ end
187
+
188
+ # are we authenticated
189
+ def authenticated?
190
+ !!@key
166
191
  end
167
192
 
168
193
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zenbe-flareshow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Will Bailey
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-11 00:00:00 -07:00
12
+ date: 2009-09-12 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -72,7 +72,7 @@ dependencies:
72
72
  - !ruby/object:Gem::Version
73
73
  version: "0"
74
74
  version:
75
- description: "TODO: a ruby gem for interacting with the shareflow collaboration service by Zenbe"
75
+ description: a ruby gem for interacting with the shareflow collaboration service by Zenbe
76
76
  email: will.bailey@gmail.com
77
77
  executables: []
78
78
 
@@ -95,8 +95,10 @@ files:
95
95
  - lib/file_attachment.rb
96
96
  - lib/flareshow.rb
97
97
  - lib/flow.rb
98
+ - lib/http_encoding_helper.rb
98
99
  - lib/invitation.rb
99
100
  - lib/membership.rb
101
+ - lib/mime_parts.rb
100
102
  - lib/post.rb
101
103
  - lib/resource.rb
102
104
  - lib/searchable.rb
@@ -131,7 +133,7 @@ rubyforge_project: flareshow
131
133
  rubygems_version: 1.2.0
132
134
  signing_key:
133
135
  specification_version: 3
134
- summary: "TODO: a ruby gem for interacting with the shareflow collaboration service"
136
+ summary: a ruby gem for interacting with the shareflow collaboration service
135
137
  test_files:
136
138
  - test/flareshow_test.rb
137
139
  - test/test_helper.rb