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 +79 -0
- data/lib/approval_hub.rb +23 -0
- data/lib/approval_hub/api.rb +255 -0
- data/lib/approval_hub/detail.rb +31 -0
- data/lib/approval_hub/request.rb +19 -0
- metadata +65 -0
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
|
data/lib/approval_hub.rb
ADDED
@@ -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: []
|