zenbe-flareshow 0.2.4 → 0.3.0
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.
- data/Flareshow.gemspec +7 -5
- data/README.md +4 -4
- data/VERSION +1 -1
- data/lib/flareshow.rb +6 -2
- data/lib/http_encoding_helper.rb +49 -0
- data/lib/mime_parts.rb +37 -0
- data/lib/resource.rb +1 -0
- data/lib/service.rb +115 -90
- metadata +6 -4
data/Flareshow.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{flareshow}
|
8
|
-
s.version = "0.
|
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-
|
13
|
-
s.description = %q{
|
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.
|
50
|
-
s.summary = %q{
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
1
|
+
0.3.0
|
data/lib/flareshow.rb
CHANGED
@@ -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 '
|
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
|
data/lib/mime_parts.rb
ADDED
@@ -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
|
data/lib/resource.rb
CHANGED
data/lib/service.rb
CHANGED
@@ -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(
|
37
|
+
def post(uri, params, files=[])
|
37
38
|
raise Flareshow::ConfigurationException unless server_defined?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
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
|
-
#
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
153
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
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.
|
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-
|
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:
|
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:
|
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
|