approval_hub 0.0.3

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/README.md ADDED
@@ -0,0 +1,79 @@
1
+ Approval Hub API
2
+ ================
3
+ A simple library for talking to the Enterprise Approval Hub.
4
+ See the rdoc for detailed usage instructions
5
+
6
+ quick start
7
+ -----------
8
+ install the gem
9
+
10
+ gem install approval_hub
11
+
12
+ require and use
13
+
14
+ require 'approval_hub'
15
+
16
+ # default uat instance
17
+ api = ApprovalHub::API.uat(username,password)
18
+
19
+ # default prod instance
20
+ api = ApprovalHub::API.prod(username,password)
21
+
22
+ # register an approval
23
+ api.register do |r|
24
+ r.request_id = "001"
25
+ r.requestor_id = "neilcuk"
26
+ r.approver_id = "kasperdulles[,others..]"
27
+ r.short_description = "A summary"
28
+ r.long_description = "A lengthier expose"
29
+ r.url = "http://url.to.source/system"
30
+ end
31
+
32
+ # get details
33
+ api.details(request_id)
34
+
35
+ # get approval status
36
+ api.status(request_id)
37
+
38
+ # approve a request
39
+ api.approve(request_id, approver_id)
40
+
41
+ # cancel a request
42
+ api.cancel(request_id, approver_id)
43
+
44
+ # decline a request
45
+ api.decline(request_id, approver_id)
46
+
47
+ troubleshooting
48
+ ---------------
49
+ All methods come with a bang version *method!* which
50
+ will throw relevant exceptions
51
+
52
+ If you want to see what is happening with the http
53
+ session, grab an API instance with debugging enabled
54
+
55
+ api = ApprovalHub::API.uat_with_debugging(username,password)
56
+ # or
57
+ api = ApprovalHub::API.prod_with_debugging(username,password)
58
+
59
+ The URL's for each of the instances are set in the root
60
+ of the module. It's unlikely these will change. If for
61
+ some reason they do and I can't get around to updating
62
+ the package you can use the default constructor
63
+
64
+ # include a url and boolean indicating whether to turn on
65
+ # http session debugging
66
+ api = ApprovalHub::API.new(url,username,password,enable_debugging)
67
+
68
+
69
+ The Enterprise Approval Hub facilitates centralised
70
+ sign-off for any kind of request. See
71
+ http://wiki.office.aol.com/wiki/ApprovalKiosk
72
+
73
+ acknowledgements
74
+ ----------------
75
+ Thanks to [HTTParty](https://github.com/jnunemaker/httparty) for making http fun!
76
+
77
+ bugs
78
+ ----
79
+ Send me an email
@@ -0,0 +1,23 @@
1
+ module ApprovalHub
2
+ # approval hub API interfaces
3
+ REGISTER = "/Register"
4
+ DETAILS = "/getDetails"
5
+ DECLINE = "/DeclineRequest"
6
+ APPROVE = "/ApproveRequest"
7
+ CANCEL = "/deleteRequest"
8
+
9
+ # approval hub status responses
10
+ PENDING = "Open"
11
+ APPROVED = "Approve"
12
+ REJECTED = "Decline"
13
+ NOT_FOUND = "Not Found"
14
+
15
+ # default URLs
16
+ URL_UAT = "http://csoweb-m01.office.aol.com:8080/EnterpriseApprovalWS/hub/system"
17
+ URL_PROD = "https://approvals-hub.office.aol.com/EnterpriseApprovalWS/hub/system"
18
+ end
19
+
20
+ require 'approval_hub/request'
21
+ require 'approval_hub/detail'
22
+ require 'approval_hub/api'
23
+
@@ -0,0 +1,255 @@
1
+ require 'httparty'
2
+
3
+ module ApprovalHub
4
+ #
5
+ # The ApprovalHub API
6
+ #
7
+ class API
8
+ include HTTParty
9
+
10
+ class << self
11
+
12
+ # get an instance of the uat hub
13
+ # requires a username and password
14
+ #
15
+ def uat(username, password)
16
+ new(URL_UAT,username,password)
17
+ end
18
+
19
+ # get an instance of the prod hub
20
+ # requires a username and password
21
+ #
22
+ def prod(username, password)
23
+ new(URL_PROD,username,password)
24
+ end
25
+
26
+ # get an instance of the uat hub with session debugging
27
+ # requires a username and password
28
+ #
29
+ def uat_with_debugging(username,password)
30
+ new(URL_UAT,username,password, true)
31
+ end
32
+
33
+ # get an instance of the prod hub with session debugging
34
+ # requires a username and password
35
+ #
36
+ def prod_with_debugging(username,password)
37
+ new(URL_PROD,username,password, true)
38
+ end
39
+
40
+ # get an instance of your choosing
41
+ # requires a url, username, password and boolean indicating
42
+ # whether or not to turn on session debugging
43
+ #
44
+ def custom_config(config={})
45
+ raise(ArgumentError, "config cannot be empty") if config.empty?
46
+ new(config["url"], config["username"], config["password"], config["with_debugging"])
47
+ end
48
+ end
49
+
50
+ def initialize(url, username, password, with_debugging=false)
51
+ raise ArgumentError if url.nil? || username.nil? || password.nil?
52
+ unless url.nil?
53
+ @uri = url
54
+ end
55
+ @auth = {:user => username, :pw => password}
56
+ if with_debugging
57
+ self.class.debug_output $stderr
58
+ end
59
+ end
60
+
61
+ # Register your approval request with the hub
62
+ # Registration takes a Request object or a block
63
+ # returns true is successful else false
64
+ #
65
+ # example1:
66
+ # api = ApprovalHub::API.uat("someuser","somepwd")
67
+ # api.register do |r|
68
+ # r.request_id = "001"
69
+ # r.requestor_id = "neilcuk"
70
+ # r.approver_id = "kasperdulles[,others..]"
71
+ # r.short_description = "A summary"
72
+ # r.long_description = "A lengthier expose"
73
+ # r.url = "http://url.to.source/system"
74
+ # end
75
+ #
76
+ # example2:
77
+ # api = ApprovalHub::API.uat("someuser","somepwd")
78
+ # r = ApprovalHub::Request.new
79
+ # r.request_id = "001"
80
+ # r.requestor_id = "neilcuk"
81
+ # r.approver_id = "kasperdulles[,others..]"
82
+ # r.short_description = "A summary"
83
+ # r.long_description = "A lengthier expose"
84
+ # r.url = "http://url.to.source/system"
85
+ # api.register(r)
86
+ #
87
+ def register(request = Request.new, &block)
88
+ register!(request,&block) rescue false
89
+ end
90
+
91
+ # Same as register but will throw an exception
92
+ # if it encounteres an error
93
+ #
94
+ def register!(request = Request.new, &block)
95
+ begin
96
+ options = assemble_request(request,&block)
97
+ request = self.class.get( @uri + REGISTER, options )
98
+ rescue Exception => e
99
+ raise e, "Unable to register approval request"
100
+ end
101
+ if request.response.code != "200"
102
+ raise "Approval hub denied request registration with code #{request.response.code}"
103
+ end
104
+ true
105
+ end
106
+
107
+ # Retrieves a Detail object from the hub
108
+ # requires a request_id
109
+ # returns false if an error occured
110
+ # takes an optional block which will be passed
111
+ # the detail object
112
+ #
113
+ def details(request_id, &block)
114
+ details!(request_id, &block) rescue false
115
+ end
116
+
117
+ # Same as details but will throw an exception
118
+ # if it encounters an error
119
+ #
120
+ def details!(request_id, &block)
121
+ raise "Request ID cannot be nil" if request_id.nil?
122
+ begin
123
+ options = {
124
+ :query => {
125
+ :requestID => request_id
126
+ }.merge!(@auth)
127
+ }
128
+ detail = self.class.get( @uri + DETAILS, options )
129
+ if detail["response"]["status"] == 200
130
+ detail = Detail.new(detail["ApprovalList"][0])
131
+ if block_given?
132
+ yield detail
133
+ else
134
+ detail
135
+ end
136
+ else
137
+ raise ArgumentError, "request not found"
138
+ end
139
+ rescue Exception => e
140
+ raise e, "Unable to retrieve details for #{request_id}"
141
+ end
142
+ end
143
+
144
+ # Returns the status of the provided request id
145
+ # or false if some error occured
146
+ #
147
+ def status(request_id)
148
+ status!(request_id) rescue false
149
+ end
150
+
151
+ # Same as status but will throw an excption
152
+ # if it encounters an error
153
+ #
154
+ def status!(request_id)
155
+ detail = details!(request_id)
156
+ if detail.open?
157
+ "Pending Approval"
158
+ elsif detail.approved?
159
+ "Approved"
160
+ elsif detail.declined?
161
+ "Declined"
162
+ end
163
+ end
164
+
165
+ # Approve an open request
166
+ # Returns true if successful else false
167
+ #
168
+ def approve_request(request_id, approver_id)
169
+ approve_request!(request_id,approver_id) rescue false
170
+ end
171
+
172
+ # Same as approve_request but will throw
173
+ # exception on error
174
+ #
175
+ def approve_request!(request_id, approver_id)
176
+ update_request(request_id,approver_id, ApprovalHub::APPROVE)
177
+ end
178
+
179
+ # Cancel an open request
180
+ # Returns true if successful else false
181
+ #
182
+ def cancel_request(request_id, approver_id)
183
+ cancel_request!(request_id,approver_id) rescue false
184
+ end
185
+
186
+ # Same as cancel_request but will throw
187
+ # exception on error
188
+ #
189
+ def cancel_request!(request_id, approver_id)
190
+ update_request(request_id,approver_id, ApprovalHub::CANCEL)
191
+ end
192
+
193
+ # decline an open request.
194
+ # Takes an optional reason for rejection
195
+ # Returns true if success else false
196
+ #
197
+ def decline_request(request_id, approver_id, reason=nil)
198
+ decline_request!(request_id,approver_id,reason) rescue false
199
+ end
200
+
201
+ # Same as decline_request but will throw
202
+ # exception on error
203
+ #
204
+ def decline_request!(request_id, approver_id, reason=nil)
205
+ update_request(request_id,approver_id, ApprovalHub::DECLINE,reason)
206
+ end
207
+
208
+ private
209
+
210
+ def update_request(request_id, approver_id, action, reason=nil)
211
+ options = {
212
+ :query => {
213
+ :requestID => request_id,
214
+ :actionedByCdid => approver_id,
215
+ :actionedByName => approver_id,
216
+ :actionedByWhen => Time.now.strftime("%Y-%m-%d %H:%M:%S"),
217
+ :reason => reason
218
+ }.merge!(@auth)
219
+ }
220
+ begin
221
+ response = self.class.get( @uri + action, options )
222
+ if response["status"] == 200
223
+ true
224
+ elsif response["status"] == 202
225
+ raise ArgumentError, "Request with id #{request_id} does not exist"
226
+ else
227
+ false
228
+ end
229
+ rescue Exception => e
230
+ raise e, "Unable to update approval request"
231
+ end
232
+ end
233
+
234
+ def assemble_request(request,&block)
235
+ if block_given?
236
+ yield request
237
+ end
238
+ raise "approval request not valid" if not request.is_valid?
239
+ options ={
240
+ :query => {
241
+ :state =>'open', # default required during registration
242
+ :requestID => request.request_id,
243
+ :shortDescription => request.short_description,
244
+ :longDescription => request.long_description,
245
+ :url => request.url,
246
+ :requestorCdid => request.requestor_id,
247
+ :approverCdid => request.approver_id,
248
+ :requestTime => Time.now.strftime("%Y-%m-%d %H:%M:%S")
249
+ }.merge!(@auth)
250
+ }
251
+ end
252
+
253
+ end
254
+
255
+ end
@@ -0,0 +1,31 @@
1
+ module ApprovalHub
2
+ class Detail
3
+ attr_reader :request_id, :long_description, :short_description
4
+ attr_reader :requestor_id, :approver_id, :url, :reason, :state
5
+
6
+ def initialize(hash={})
7
+ unless hash.empty?
8
+ @request_id = hash["requestID"]
9
+ @long_description = hash["longDescription"]
10
+ @short_description = hash["shortDescription"]
11
+ @requestor_id = hash["requestorCDID"]
12
+ @approver_id = hash["actionedByCDID"]
13
+ @url = hash["url"]
14
+ @reason = hash["reason"]
15
+ @state = hash["state"]
16
+ end
17
+ end
18
+
19
+ def approved?
20
+ not (state =~ /#{ApprovalHub::APPROVED}/i).nil?
21
+ end
22
+
23
+ def declined?
24
+ not (state =~ /#{ApprovalHub::REJECTED}/i).nil?
25
+ end
26
+
27
+ def open?
28
+ not (state =~ /#{ApprovalHub::PENDING}/i).nil?
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module ApprovalHub
2
+ # A Request is passed to the hub for registration
3
+ #
4
+ class Request
5
+ attr_accessor :request_id, :long_description, :short_description
6
+ attr_accessor :requestor_id, :approver_id, :url
7
+
8
+ # Will return false if fields have not been set
9
+ # TODO - return an errors hash stating why the request is not valid
10
+ def is_valid?
11
+ not request_id.nil? ||
12
+ long_description.nil? ||
13
+ short_description.nil? ||
14
+ requestor_id.nil? ||
15
+ approver_id.nil? ||
16
+ url.nil?
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: approval_hub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Neil Chambers
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: A library for interacting with the Enterprise Approval Kiosk
31
+ email: neil.chambers@teamaol.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/approval_hub/api.rb
37
+ - lib/approval_hub/detail.rb
38
+ - lib/approval_hub/request.rb
39
+ - lib/approval_hub.rb
40
+ - README.md
41
+ homepage: http://wiki.office.aol.com/wiki/ApprovalKiosk
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 1.8.24
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Approval Hub API
65
+ test_files: []