class Roust
Constants
- VERSION
Public Class Methods
new(credentials, headers = {})
click to toggle source
# File lib/roust.rb, line 15 def initialize(credentials, headers = {}) @server = credentials[:server] @username = credentials[:username] @password = credentials[:password] if @server =~ /REST\/1\.0/ raise ArgumentError, 'The supplied :server has REST in the URL. You only need to specify the base, e.g. http://rt.example.org/' end headers['User-Agent'] = 'Roust' unless headers.key?('User-Agent') self.class.headers.merge!(headers) authenticate! end
Public Instance Methods
authenticate!()
click to toggle source
# File lib/roust.rb, line 29 def authenticate! # - There is no way to authenticate against the API. The only way to log # in is to fill out the same HTML form humans fill in, cache the cookies # returned, and send them on every subsequent request. # - RT does not provide *any* indication that the authentication request # has succeeded or failed. RT will always return a HTTP 200. self.class.base_uri(@server) response = self.class.post( '/index.html', :body => { :user => @username, :pass => @password } ) cookie = response.headers['set-cookie'] self.class.headers['Cookie'] = cookie if cookie # Switch the base uri over to the actual REST API base uri. self.class.base_uri "#{@server}/REST/1.0" # - The easiest way to programatically check if an authentication request # succeeded is by doing a request for a ticket, and seeing if the API # responds with some specific text ("401 Credentials required") that # indicates authentication has previously failed. # - The authenticated? method will return false if an Unauthenticated # exception bubbles up from response handling. We (dirtily) rethrow the # exception. raise Unauthenticated unless authenticated? end
authenticated?()
click to toggle source
# File lib/roust.rb, line 62 def authenticated? return true if show('1') rescue Unauthenticated return false end
Private Instance Methods
body_to_hash(body)
click to toggle source
# File lib/roust.rb, line 134 def body_to_hash(body) body.gsub!(/\n\s*\n/, "\n") # remove blank lines for Mail message = Mail.new(body) pairs = message.header.fields.map do |header| key = header.name.to_s value = header.value.to_s [ key, value ] end hash = Hash[pairs] end
compose_content(type, id, attrs)
click to toggle source
compose_content
turns a Hash into an RFC2822 “key: value”-like header blob
This is the fucked up format RT demands all content is sent and received in.
# File lib/roust.rb, line 73 def compose_content(type, id, attrs) default_attrs = { 'id' => [ type, id ].join('/') } attrs = default_attrs.merge(attrs).stringify_keys! content = attrs.map do |k, v| # Don't lowercase strings if they're already camel cased. k = case when k.is_a?(Symbol) k.to_s when k == 'id' k when k =~ /^[a-z]/ k.capitalize else k end k = sanitize_content_key(k) v = v.join(', ') if v.respond_to?(:join) "#{k}: #{v}" end content.join("\n") end
explode_response(response)
click to toggle source
explode_response
separates RT's response content from the response status.
All HTTP-level response codes from RT are a lie. The only way to check if the request was successful is by inspecting the body of the content back from RT, and separating the first line from the rest of the content.
-
The first line contains the status of the operation.
-
All subsequent lines (if there are any) are the message body.
# File lib/roust.rb, line 122 def explode_response(response) body = response.body status = body[/RT\/\d+\.\d+\.\d+\s(\d{3}\s.*)\n/, 1] body.gsub!(/RT\/\d+\.\d+\.\d+\s\d{3}\s.*\n/, '') body = body.empty? ? nil : body.lstrip raise Unauthenticated, 'Invalid username or password' if status =~ /401 Credentials required/ return body, status end
sanitize_content_key(k)
click to toggle source
# File lib/roust.rb, line 101 def sanitize_content_key(k) case k.downcase when 'requestors' 'Requestors' when 'cc' 'Cc' when 'admincc' 'AdminCc' else k end end