approval_hub 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: []