fiddler 0.0.1 → 1.0.1

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.
Files changed (36) hide show
  1. data/README.md +70 -0
  2. data/lib/fiddler.rb +5 -1
  3. data/lib/fiddler/attachment.rb +142 -0
  4. data/lib/fiddler/configuration.rb +7 -2
  5. data/lib/fiddler/connection_manager.rb +62 -20
  6. data/lib/fiddler/errors.rb +1 -0
  7. data/lib/fiddler/extensions.rb +2 -0
  8. data/lib/fiddler/extensions/file.rb +5 -0
  9. data/lib/fiddler/extensions/hash.rb +15 -0
  10. data/lib/fiddler/formatters/base_formatter.rb +3 -0
  11. data/lib/fiddler/formatters/search_request_formatter.rb +2 -2
  12. data/lib/fiddler/history.rb +32 -0
  13. data/lib/fiddler/parsers.rb +3 -1
  14. data/lib/fiddler/parsers/attachment_parser.rb +54 -0
  15. data/lib/fiddler/parsers/base_parser.rb +41 -3
  16. data/lib/fiddler/parsers/history_parser.rb +72 -0
  17. data/lib/fiddler/parsers/ticket_parser.rb +52 -21
  18. data/lib/fiddler/ticket.rb +141 -43
  19. data/lib/fiddler/version.rb +1 -1
  20. data/spec/attachment_spec.rb +26 -0
  21. data/spec/cassettes/change-ownership-take.yml +98 -0
  22. data/spec/cassettes/get-tickets.yml +89087 -0
  23. data/spec/cassettes/reply-to-tickets.yml +232 -0
  24. data/spec/cassettes/root-request.yml +79 -0
  25. data/spec/cassettes/search-tickets.yml +38249 -0
  26. data/spec/cassettes/ticket-histories-count.yml +2195 -0
  27. data/spec/cassettes/ticket-histories.yml +954 -0
  28. data/spec/connection_manager_spec.rb +5 -1
  29. data/spec/formatters/search_request_formatter_spec.rb +13 -0
  30. data/spec/parsers/attachment_parser_spec.rb +29 -0
  31. data/spec/parsers/base_parser_spec.rb +16 -0
  32. data/spec/parsers/history_parser_spec.rb +32 -0
  33. data/spec/parsers/ticket_parser_spec.rb +5 -1
  34. data/spec/spec_helper.rb +9 -0
  35. data/spec/ticket_spec.rb +188 -6
  36. metadata +80 -9
data/README.md CHANGED
@@ -3,6 +3,76 @@ Fiddler
3
3
 
4
4
  Ruby gem to provide an easy interface to Request Tracker Installation.
5
5
 
6
+ Installation
7
+ -------------
8
+
9
+ Install the gem using this commands
10
+
11
+ `gem install fiddler`
12
+
13
+ or you can include it in your Gemfile.
14
+
15
+ `gem 'fiddler'`
16
+
17
+ Configuration
18
+ --------------
19
+
20
+ For a Rails app, create an initializer files and for any other app, include this before using the gem.
21
+ <pre>
22
+ <code>
23
+ Fiddler.configure do |config|
24
+ config.server_url = "request_tracker_url"
25
+ config.username = "some_user"
26
+ config.password = "some_password"
27
+ end
28
+ </code>
29
+ </pre>
30
+
31
+ You can modify the settings on the fly as well using `Fiddler.configuration` variable.
32
+
33
+ Attachments
34
+ -----------
35
+
36
+ Fiddler saves the attachments object in a folder specified by
37
+ `Fiddler.configuration.attachments_path`. This is relative to the rails
38
+ root.
39
+
40
+ Using Cookies
41
+ -------------
42
+
43
+ Make sure you have RT-External-Auth configured properly to use cookies with Request Tracker.
44
+ Once that part has been done, change the config file to the following format.
45
+
46
+ <pre>
47
+ <code>
48
+ Fiddler.configure do |config|
49
+ config.server_url = "request_tracker_url"
50
+ config.use_cookies = true
51
+ config.cookie_domain = ".domainname"
52
+ config.request_tracker_key = "loginCookieValue"
53
+ end
54
+ </code>
55
+ </pre>
56
+
57
+ Once the configuration is done, cookie value can be set using
58
+ `Fiddler.configuration.cookie_value` method (appropriate place for that
59
+ would be somewhere like ApplicationController where it can set
60
+ dynamically).
61
+
62
+ Debugging Response
63
+ ------------------
64
+
65
+ You can set the config option `Fiddler.configuration.debug_response` to
66
+ `true` to start debugging the responses from RT. If using in rails, it
67
+ will log to the current environment log otherwise print it to the stdout.
68
+
69
+ SSL Verification
70
+ ----------------
71
+
72
+ SSL certificate verification can be turned off by using
73
+ `Fiddler.configuration.ssl_verify` option. This is very helpful in jruby
74
+ implementations where ssl is bit of a pain.
75
+
6
76
  Supported Versions of Request Tracker
7
77
  -------------------------------------
8
78
  * 4.0.4
@@ -2,7 +2,11 @@ require 'fiddler/configuration'
2
2
  require 'fiddler/errors'
3
3
  require 'fiddler/parsers'
4
4
  require 'fiddler/formatters'
5
- require 'fiddler/ticket'
5
+ require 'fiddler/extensions'
6
6
  require 'fiddler/connection_manager'
7
7
 
8
+ require 'fiddler/ticket'
9
+ require 'fiddler/history'
10
+ require 'fiddler/attachment'
11
+
8
12
  require 'active_support/all'
@@ -0,0 +1,142 @@
1
+ require 'active_attr'
2
+ module Fiddler
3
+ class AttachmentCollection < Array
4
+ def to_payload
5
+ hash = Hash.new
6
+ self.each_with_index do |attach, index|
7
+ hash["attachment_#{index+1}"] = attach
8
+ end
9
+ hash
10
+ end
11
+
12
+ def self.fill(*args)
13
+ AttachmentCollection.new Array(args.compact).flatten.map { |attachment|
14
+ if attachment.is_a?(File)
15
+ AttachmentFile.new(attachment.path)
16
+ elsif attachment.is_a?(String)
17
+ AttachmentFile.new(attachment)
18
+ elsif attachment.is_a?(ActionDispatch::Http::UploadedFile)
19
+ AttachmentFile.new(attachment.tempfile.path, attachment.original_filename)
20
+ end
21
+ }.compact
22
+ end
23
+ end
24
+
25
+ class AttachmentFile < File
26
+ attr_accessor :name
27
+
28
+ def initialize(path,name=nil)
29
+ super(path)
30
+ @name = name || File.basename(path)
31
+ end
32
+ end
33
+
34
+ # the attachment in itself
35
+ class Attachment
36
+ include ActiveAttr::Model
37
+
38
+ attribute :id
39
+ attribute :subject
40
+ attribute :creator
41
+ attribute :created
42
+ attribute :transaction
43
+ attribute :parent
44
+ attribute :message_id
45
+ attribute :filename
46
+ attribute :content_type
47
+ attribute :content_encoding
48
+ attribute :headers
49
+
50
+ attr_accessor :ticket_id, :content, :path
51
+
52
+ # Public class method to get an attachment
53
+ def self.get(id, ticket_id)
54
+ url = "/ticket/#{ticket_id}/attachments/#{id}"
55
+ response = Fiddler::ConnectionManager.get(url)
56
+ attachment = Fiddler::Parsers::AttachmentParser.parse_single(response)
57
+ attachment.ticket_id = ticket_id
58
+ attachment
59
+ end
60
+
61
+ def content_length
62
+ length = header_value_for_key("Content-Length")
63
+ if !length.nil?
64
+ length.to_i
65
+ elsif @content.nil?
66
+ -1
67
+ else
68
+ @content.length
69
+ end
70
+ end
71
+
72
+ def content
73
+ populate_data
74
+ @content
75
+ end
76
+
77
+ def path
78
+ populate_data
79
+ @path
80
+ end
81
+
82
+ def has_text_content
83
+ if content_type == "text/plain" or content_type == "text/html"
84
+ return true
85
+ else
86
+ return false
87
+ end
88
+ end
89
+
90
+ protected
91
+
92
+ def populate_data
93
+ @data_populated ||= false
94
+ unless @data_populated
95
+ if content_length != 0
96
+ if has_text_content
97
+ load_content
98
+ @path = nil
99
+ else
100
+ @path = full_path_for_filename
101
+ if File.exists?(@path)
102
+ @content = ""
103
+ else
104
+ load_content
105
+ save_content_to_file
106
+ end
107
+ end
108
+ else
109
+ @content = ""
110
+ end
111
+ @data_populated = true
112
+ end
113
+ end
114
+
115
+ def load_content
116
+ url = "/ticket/#{ticket_id}/attachments/#{id}/content"
117
+ response = Fiddler::ConnectionManager.get(url)
118
+ @content = Fiddler::Parsers::AttachmentParser.parse_content(response)
119
+ end
120
+
121
+ def header_value_for_key(header_key)
122
+ final_value = nil
123
+ headers.each do |header_line|
124
+ (key,value) = header_line.split(":")
125
+ if header_key == key
126
+ final_value = value
127
+ break
128
+ end
129
+ end
130
+ return final_value
131
+ end
132
+
133
+ def save_content_to_file
134
+ File.open(full_path_for_filename, "w") { |f| f.write(@content) }
135
+ @content = ""
136
+ end
137
+
138
+ def full_path_for_filename
139
+ "#{Fiddler.configuration.attachments_path}/#{id}-#{filename}"
140
+ end
141
+ end
142
+ end
@@ -1,11 +1,16 @@
1
1
  module Fiddler
2
2
  # Based on the Clearance gem configuration - https://github.com/thoughtbot/clearance/blob/master/lib/clearance/configuration.rb
3
3
  class Configuration
4
- attr_accessor :server_url, :username, :password, :use_cookies, :cookie_domain, :ssl_verify
4
+ attr_accessor :server_url, :username, :password, :use_cookies, :cookie_domain, :cookie_value, :request_tracker_key, :ssl_verify, :attachments_path, :debug_response
5
5
 
6
6
  def initialize
7
7
  @use_cookies = false
8
8
  @ssl_verify = true
9
+ @attachments_path = "attachments"
10
+ @cookie_value = nil
11
+ @cookie_domain = nil
12
+ @request_tracker_key = "loginCookieValue"
13
+ @debug_response = false
9
14
  end
10
15
  end
11
16
 
@@ -17,4 +22,4 @@ module Fiddler
17
22
  self.configuration ||= Configuration.new
18
23
  yield configuration
19
24
  end
20
- end
25
+ end
@@ -1,33 +1,67 @@
1
1
  require 'httpclient'
2
+ require 'awesome_print'
2
3
 
3
4
  module Fiddler
4
5
  module ConnectionManager
5
6
 
6
7
  class Connection
7
- attr_accessor :client
8
+ attr_accessor :client, :logged_in
9
+
8
10
  def initialize
9
11
  @client = HTTPClient.new
10
12
  @client.set_cookie_store("cookies.dat")
13
+ @logged_in = false
11
14
  end
12
15
 
13
- def base_url
14
- "#{Fiddler.configuration.server_url}/REST/1.0/"
16
+ def get(path,options)
17
+ login! unless @logged_in
18
+ @client.get(url_for(path),options).content
15
19
  end
16
20
 
17
- def get(url,options)
18
- url = "#{base_url}#{url}"
19
- options = options_with_login(options)
20
- @client.get(url,options).content
21
+ def post(path,options)
22
+ login! unless @logged_in
23
+ @client.post(url_for(path),options).content
21
24
  end
22
25
 
23
- def post(url,options)
24
- url = "#{base_url}#{url}"
25
- @client.post(url,options_with_login(options)).content
26
+ def post_content(path,options)
27
+ login! unless @logged_in
28
+ @client.post_content(url_for(path),options)
26
29
  end
27
30
 
28
- def options_with_login(options)
31
+ private
32
+
33
+ def login!
29
34
  unless Fiddler.configuration.use_cookies
30
- options.merge({ :user => Fiddler.configuration.username, :pass => Fiddler.configuration.password })
35
+ unless @logged_in
36
+ @client.post(url_for(base_url), :user => Fiddler.configuration.username, :pass => Fiddler.configuration.password )
37
+ @logged_in = true
38
+ end
39
+ else
40
+ @client.cookie_manager.cookies = []
41
+ cookie = WebAgent::Cookie.new
42
+ cookie.name = Fiddler.configuration.request_tracker_key
43
+ cookie.value = Fiddler.configuration.cookie_value
44
+ cookie.url = URI.parse(Fiddler.configuration.server_url)
45
+ cookie.domain_orig = Fiddler.configuration.cookie_domain
46
+ @client.cookie_manager.add(cookie)
47
+ @logged_in = false
48
+ end
49
+ end
50
+
51
+ def base_url
52
+ server_url = Fiddler.configuration.server_url
53
+ if server_url =~ /\/$/
54
+ "#{Fiddler.configuration.server_url}REST/1.0"
55
+ else
56
+ "#{Fiddler.configuration.server_url}/REST/1.0"
57
+ end
58
+ end
59
+
60
+ def url_for(path)
61
+ if path =~ /^\//
62
+ "#{base_url}#{path}"
63
+ else
64
+ "#{base_url}/#{path}"
31
65
  end
32
66
  end
33
67
  end
@@ -37,16 +71,17 @@ module Fiddler
37
71
 
38
72
  def get(url,options={})
39
73
  check_config
40
- response = connection.get(url,options)
41
- debug(response)
42
- response
74
+ debug connection.get(url,options)
43
75
  end
44
76
 
45
77
  def post(url,options={})
46
78
  check_config
47
- response = connection.post(url,options)
48
- debug(response)
49
- response
79
+ debug connection.post(url,options)
80
+ end
81
+
82
+ def post_content(url,options={})
83
+ check_config
84
+ debug connection.post_content(url,options)
50
85
  end
51
86
 
52
87
  protected
@@ -55,7 +90,7 @@ module Fiddler
55
90
  config = Fiddler.configuration
56
91
  raise InvalidConfigurationError if config.server_url.blank?
57
92
  if config.username.blank? or config.password.blank?
58
- raise InvalidConfigurationError unless config.use_cookies
93
+ raise InvalidConfigurationError unless config.use_cookies and config.request_tracker_key and config.cookie_value and config.cookie_domain
59
94
  end
60
95
  end
61
96
 
@@ -64,7 +99,14 @@ module Fiddler
64
99
  end
65
100
 
66
101
  def debug(response)
67
- puts response.inspect if ENV['DEBUG']
102
+ if ENV['DEBUG'] or Fiddler.configuration.debug_response
103
+ if defined?(Rails)
104
+ Rails.logger.debug response
105
+ else
106
+ ap response
107
+ end
108
+ end
109
+ return response
68
110
  end
69
111
  end # end class method definitions
70
112
  end # end ConnectionManager module definition
@@ -4,4 +4,5 @@ module Fiddler
4
4
  class InvalidConfigurationError < StandardError; end
5
5
  class TicketAccessDeniedError < StandardError; end
6
6
  class RequestError < StandardError; end
7
+ class IllegalCharacterError < StandardError; end
7
8
  end
@@ -0,0 +1,2 @@
1
+ require 'fiddler/extensions/hash'
2
+ require 'fiddler/extensions/file'
@@ -0,0 +1,5 @@
1
+ class File
2
+ def name
3
+ File.basename(path)
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ class Hash
2
+ def to_content_format
3
+ fields = self.map do |key,value|
4
+ unless value.nil?
5
+ value = Fiddler::Formatters::BaseFormatter.format_string(value.to_s)
6
+ if key.to_s.match(/^cf_.+/)
7
+ "CF-#{key.to_s[3..key.to_s.length].gsub(/_/, " ").camelize.humanize}: #{value}"
8
+ else
9
+ "#{key.to_s.camelize}: #{value}"
10
+ end
11
+ end
12
+ end
13
+ content = fields.compact.sort.join("\n")
14
+ end
15
+ end
@@ -1,6 +1,9 @@
1
1
  module Fiddler
2
2
  module Formatters
3
3
  class BaseFormatter
4
+ def self.format_string(string)
5
+ string.gsub("\r", '').gsub("\n", "\n ")
6
+ end
4
7
  end
5
8
  end
6
9
  end
@@ -51,8 +51,8 @@ module Fiddler
51
51
  end
52
52
  query_array << '( ' + parts.join(" AND ") + ' )'
53
53
  elsif value.is_a?(String)
54
- # special case for when user is Nobody, like doesnt work there
55
- if key == "Owner" and value == "Nobody"
54
+ # special case for the owner field
55
+ if key == "Owner"
56
56
  query_array << "#{key} = '#{value}'"
57
57
  else
58
58
  query_array << "#{key} LIKE '#{value}'"
@@ -0,0 +1,32 @@
1
+ require 'active_attr'
2
+ module Fiddler
3
+ class History
4
+ include ActiveAttr::Model
5
+
6
+ attribute :id
7
+ attribute :ticket
8
+ attribute :time_taken
9
+ attribute :type
10
+ attribute :field
11
+ attribute :old_value
12
+ attribute :new_value
13
+ attribute :data
14
+ attribute :description
15
+ attribute :content
16
+ attribute :creator
17
+ attribute :created
18
+ attribute :attachment_ids
19
+
20
+ attr_reader :attachments
21
+
22
+ def attachments
23
+ if @attachments == nil
24
+ @attachments = []
25
+ attachment_ids.each do |id|
26
+ @attachments << Fiddler::Attachment.get(id,ticket)
27
+ end
28
+ end
29
+ @attachments
30
+ end
31
+ end
32
+ end