redmine_api_helper 0.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of redmine_api_helper might be problematic. Click here for more details.

Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +2 -0
  3. data/.gitignore +9 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +339 -0
  7. data/README.md +30 -0
  8. data/Rakefile +2 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/redmine_api_helper.rb +44 -0
  12. data/lib/redmine_api_helper/api_helper.rb +310 -0
  13. data/lib/redmine_api_helper/args_helper.rb +96 -0
  14. data/lib/redmine_api_helper/attachments_api_helper.rb +52 -0
  15. data/lib/redmine_api_helper/define_api_helpers.rb +78 -0
  16. data/lib/redmine_api_helper/document_categories_api_helper.rb +38 -0
  17. data/lib/redmine_api_helper/groups_api_helper.rb +80 -0
  18. data/lib/redmine_api_helper/helpers.rb +48 -0
  19. data/lib/redmine_api_helper/issue_priorities_api_helper.rb +38 -0
  20. data/lib/redmine_api_helper/issue_relations_api_helper.rb +66 -0
  21. data/lib/redmine_api_helper/issue_statuses_api_helper.rb +36 -0
  22. data/lib/redmine_api_helper/issues_api_helper.rb +124 -0
  23. data/lib/redmine_api_helper/my_account_api_helper.rb +45 -0
  24. data/lib/redmine_api_helper/news_api_helper.rb +73 -0
  25. data/lib/redmine_api_helper/project_memberships_api_helper.rb +77 -0
  26. data/lib/redmine_api_helper/projects_api_helper.rb +73 -0
  27. data/lib/redmine_api_helper/roles_api_helper.rb +52 -0
  28. data/lib/redmine_api_helper/search_api_helper.rb +38 -0
  29. data/lib/redmine_api_helper/time_entries_api_helper.rb +73 -0
  30. data/lib/redmine_api_helper/time_entry_activities_api_helper.rb +38 -0
  31. data/lib/redmine_api_helper/trackers_api_helper.rb +38 -0
  32. data/lib/redmine_api_helper/users_api_helper.rb +73 -0
  33. data/lib/redmine_api_helper/version.rb +24 -0
  34. data/lib/redmine_api_helper/wiki_pages_api_helper.rb +66 -0
  35. data/redmine_api_helper.gemspec +33 -0
  36. metadata +96 -0
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "deep_try"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ #
3
+ # aids creating fiddles for redmine_scripting_engine
4
+ #
5
+ # Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+ #
21
+
22
+ require "redmine_api_helper/api_helper"
23
+ require "redmine_api_helper/args_helper"
24
+ require "redmine_api_helper/define_api_helpers"
25
+ require "redmine_api_helper/attachments_api_helper"
26
+ require "redmine_api_helper/document_categories_api_helper"
27
+ require "redmine_api_helper/groups_api_helper"
28
+ require "redmine_api_helper/issue_priorities_api_helper"
29
+ require "redmine_api_helper/issue_relations_api_helper"
30
+ require "redmine_api_helper/issue_statuses_api_helper"
31
+ require "redmine_api_helper/issues_api_helper"
32
+ require "redmine_api_helper/my_account_api_helper"
33
+ require "redmine_api_helper/news_api_helper"
34
+ require "redmine_api_helper/project_memberships_api_helper"
35
+ require "redmine_api_helper/projects_api_helper"
36
+ require "redmine_api_helper/roles_api_helper"
37
+ require "redmine_api_helper/search_api_helper"
38
+ require "redmine_api_helper/time_entries_api_helper"
39
+ require "redmine_api_helper/time_entry_activities_api_helper"
40
+ require "redmine_api_helper/trackers_api_helper"
41
+ require "redmine_api_helper/users_api_helper"
42
+ require "redmine_api_helper/version"
43
+ require "redmine_api_helper/wiki_pages_api_helper"
44
+ require "redmine_api_helper/helpers"
@@ -0,0 +1,310 @@
1
+ ##
2
+ # aids creating fiddles for redmine_scripting_engine
3
+ #
4
+ # Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
5
+ #
6
+ # This program is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; either version 2
9
+ # of the License, or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ #
20
+
21
+ module RedmineAPIHelper
22
+ module APIHelper
23
+
24
+ ########################################################################################
25
+ # api functions
26
+ ########################################################################################
27
+ class TooManyRedirects < StandardError; end
28
+ LIMIT_REDIRECTS = 10
29
+
30
+ ########################################################################################
31
+ # returns error
32
+ ########################################################################################
33
+ def error(err)
34
+ OpenStruct.new(:error => err.message, :backtrace => err.backtrace)
35
+ end #def
36
+
37
+ ########################################################################################
38
+ # assembles url from fragments
39
+ ########################################################################################
40
+ def url_path(*fragments, **options)
41
+ [fragments.map do |fragment|
42
+ fragment.to_s.gsub(/\/\z/,"")
43
+ end.join("/"),
44
+ options.to_query.presence
45
+ ].compact.join("?")
46
+ end #def
47
+
48
+ ########################################################################################
49
+ # lists objects, corresponds to controller#index
50
+ ########################################################################################
51
+ def list_objects(objects, params={})
52
+ jget(:url => send("#{objects}_url"), :params => params ).send(objects)
53
+ rescue Exception => err
54
+ error(err)
55
+ end #def
56
+
57
+ def list_project_objects(project_id, objects, params={})
58
+ jget(:url => send("project_#{objects}_url", project_id), :params => params ).send(objects)
59
+ rescue Exception => err
60
+ error(err)
61
+ end #def
62
+
63
+ ########################################################################################
64
+ # reads object having id, corresponds to controller#show
65
+ ########################################################################################
66
+ def read_object(object, id, params={})
67
+ jget(:url => send("#{object}_url", id), :params => params ).send(object)
68
+ rescue Exception => err
69
+ error(err)
70
+ end #def
71
+
72
+ def read_project_object(project_id, object, id, params={})
73
+ jget(:url => send("project_#{object}_url", project_id, id), :params => params ).send(object)
74
+ rescue Exception => err
75
+ error(err)
76
+ end #def
77
+
78
+ ########################################################################################
79
+ # creates a new object with params, corresponds to controller#create
80
+ ########################################################################################
81
+ def create_object(object, params={})
82
+ jpost( {object => params}, :url => send("#{object.to_s.pluralize}_url") ).send(object)
83
+ rescue Exception => err
84
+ error(err)
85
+ end #def
86
+
87
+ def create_project_object(project_id, object, params={})
88
+ jpost( {object => params}, :url => send("project_#{object.to_s.pluralize}_url", project_id) ).send(object)
89
+ rescue Exception => err
90
+ error(err)
91
+ end #def
92
+
93
+ ########################################################################################
94
+ # updates an existing object with params, corresponds to controller#update
95
+ ########################################################################################
96
+ def update_object(object, id, params={})
97
+ jput( {object => params}, :url => send("#{object}_url", id) )
98
+ rescue Exception => err
99
+ error(err)
100
+ end #def
101
+
102
+ def update_project_object(project_id, object, id, params={})
103
+ jput( {object => params}, :url => send("project_#{object}_url", project_id, id) )
104
+ rescue Exception => err
105
+ error(err)
106
+ end #def
107
+
108
+ ########################################################################################
109
+ # deletes an existing object with params, corresponds to controller#destroy
110
+ ########################################################################################
111
+ def destroy_object(object, id, params={})
112
+ jdel(:url => send("#{object}_url", id), :params => params )
113
+ rescue Exception => err
114
+ error(err)
115
+ end #def
116
+
117
+ def destroy_project_object(project_id, object, id, params={})
118
+ jdel(:url => send("project_#{object}_url", project_id, id), :params => params )
119
+ rescue Exception => err
120
+ error(err)
121
+ end #def
122
+
123
+ ########################################################################################
124
+ # fetch(options), get request
125
+ ########################################################################################
126
+ def fetch(options={})
127
+
128
+ # create GET request
129
+ uri = URI.parse(options[:url])
130
+ req = Net::HTTP::Get.new(uri.request_uri)
131
+
132
+ # create HTTP handler
133
+ http = Net::HTTP.new(uri.host, uri.port)
134
+ http.use_ssl = uri.scheme.downcase == "https"
135
+
136
+ # get request
137
+ @http_response = http.request(req)
138
+
139
+ case @http_response
140
+
141
+ when Net::HTTPSuccess
142
+ @http_response.body.present? ? @http_response.body : serialize(:response => "OK")
143
+
144
+ when Net::HTTPRedirection
145
+ options[:redirects] = options[:redirects].to_i + 1
146
+ raise TooManyRedirects if options[:redirects] > LIMIT_REDIRECTS
147
+ fetch( options.merge(:url => response['location']) )
148
+
149
+ else
150
+ serialize(:response => @http_response.code)
151
+
152
+ end
153
+
154
+ end #def
155
+
156
+ ########################################################################################
157
+ # jget(options), get request
158
+ ########################################################################################
159
+ def jget(options={})
160
+
161
+ index = options[:index].to_i
162
+ json = options[:json].nil? || !!options[:json]
163
+ params = json ? options[:params].to_h.merge(:format => "json").to_query : options[:params].to_h.to_query
164
+ content_type = json ? "application/json" : options[:content_type]
165
+ api = options[:api_key].nil? ? true : !!options[:api_key]
166
+
167
+ # create GET request
168
+ uri = URI.parse(options[:url] ? [options[:url], params].join("?") : "#{args.objects[index].object_url}#{params}")
169
+ req = Net::HTTP::Get.new(uri.request_uri)
170
+ req["Content-Type"] = "content_type"
171
+ req['X-Redmine-API-Key'] = args.api_key if api
172
+ req.basic_auth(args.site_user, args.site_password) if args.site_user.present? || args.site_password.present?
173
+
174
+ # create HTTP handler
175
+ http = Net::HTTP.new(uri.host, uri.port)
176
+ http.use_ssl = uri.scheme.downcase == "https"
177
+
178
+ # get request
179
+ @http_response = http.request(req)
180
+
181
+ # follow redirection or get result code
182
+ handle_response(options)
183
+
184
+ end #def
185
+
186
+ ########################################################################################
187
+ # jput(body, options), put request
188
+ ########################################################################################
189
+ def jput(body, options={})
190
+
191
+ index = options[:index].to_i
192
+ json = options[:json].nil? || !!options[:json]
193
+ params = json ? options[:params].to_h.merge(:format => "json").to_query : options[:params].to_h.to_query
194
+ content_type = json ? "application/json" : options[:content_type]
195
+ api = options[:api_key].nil? ? true : !!options[:api_key]
196
+
197
+ # create PUT request
198
+ uri = URI.parse(options[:url] ? [options[:url], params].join("?") : "#{args.objects[index].object_url}#{params}")
199
+ req = Net::HTTP::Put.new(uri.request_uri)
200
+ req["Content-Type"] = content_type
201
+ req['X-Redmine-API-Key'] = args.api_key if api
202
+ req.basic_auth(args.site_user, args.site_password) if args.site_user.present? || args.site_password.present?
203
+
204
+ # create body
205
+ req.body = deserialize(body).to_json
206
+
207
+ # create HTTP handler
208
+ http = Net::HTTP.new(uri.host, uri.port)
209
+ http.use_ssl = uri.scheme.downcase == "https"
210
+
211
+ # get request
212
+ @http_response = http.request(req)
213
+
214
+ # follow redirection or get result code
215
+ handle_response(options)
216
+
217
+ end #def
218
+
219
+ ########################################################################################
220
+ # jpost(body, options), post request
221
+ ########################################################################################
222
+ def jpost(body, options={})
223
+
224
+ index = options[:index].to_i
225
+ json = options[:json].nil? || !!options[:json]
226
+ params = json ? options[:params].to_h.merge(:format => "json").to_query : options[:params].to_h.to_query
227
+ content_type = json ? "application/json" : options[:content_type]
228
+ api = options[:api_key].nil? ? true : !!options[:api_key]
229
+
230
+ # create POST request
231
+ uri = URI.parse(options[:url] ? [options[:url], params].join("?") : "#{args.objects[index].object_url}#{params}")
232
+ req = Net::HTTP::Post.new(uri.request_uri)
233
+ req["Content-Type"] = content_type
234
+ req['X-Redmine-API-Key'] = args.api_key if api
235
+ req.basic_auth(args.site_user, args.site_password) if args.site_user.present? || args.site_password.present?
236
+
237
+ # create body
238
+ req.body = deserialize(body).to_json
239
+
240
+ # create HTTP handler
241
+ http = Net::HTTP.new(uri.host, uri.port)
242
+ http.use_ssl = uri.scheme.downcase == "https"
243
+
244
+ # get request
245
+ @http_response = http.request(req)
246
+
247
+ # follow redirection or get result code
248
+ handle_response(options)
249
+
250
+ end #def
251
+
252
+ ########################################################################################
253
+ # jdel(options), delete request
254
+ ########################################################################################
255
+ def jdel(options={})
256
+
257
+ index = options[:index].to_i
258
+ json = options[:json].nil? || !!options[:json]
259
+ params = json ? options[:params].to_h.merge(:format => "json").to_query : options[:params].to_h.to_query
260
+ content_type = json ? "application/json" : options[:content_type]
261
+ api = options[:api_key].nil? ? true : !!options[:api_key]
262
+
263
+ # create DELETE request
264
+ uri = URI.parse(options[:url] ? [options[:url], params].join("?") : "#{args.objects[index].object_url}#{params}")
265
+ req = Net::HTTP::Delete.new(uri.request_uri)
266
+ req["Content-Type"] = "content_type"
267
+ req['X-Redmine-API-Key'] = args.api_key if api
268
+ req.basic_auth(args.site_user, args.site_password) if args.site_user.present? || args.site_password.present?
269
+
270
+ # create HTTP handler
271
+ http = Net::HTTP.new(uri.host, uri.port)
272
+ http.use_ssl = uri.scheme.downcase == "https"
273
+
274
+ # get request
275
+ @http_response = http.request(req)
276
+
277
+ # follow redirection or get result code
278
+ handle_response(options)
279
+
280
+ end #def
281
+
282
+ ########################################################################################
283
+ # private
284
+ ########################################################################################
285
+ private
286
+
287
+ ########################################################################################
288
+ # handle_response
289
+ ########################################################################################
290
+ def handle_response(options)
291
+
292
+ case @http_response
293
+
294
+ when Net::HTTPSuccess
295
+ @http_response.body.present? ? serialize(JSON.parse(@http_response.body)) : serialize(:result => @http_response.code)
296
+
297
+ when Net::HTTPRedirection
298
+ options[:redirects] = options[:redirects].to_i + 1
299
+ raise TooManyRedirects if options[:redirects] > LIMIT_REDIRECTS
300
+ function = caller_locations(1,1)[0].label.to_sym
301
+ send(function, options)
302
+
303
+ else
304
+ @http_response.body.present? ? serialize(JSON.parse(@http_response.body)) : serialize(:result => @http_response.code)
305
+
306
+ end
307
+ end #def
308
+
309
+ end #module
310
+ end #module
@@ -0,0 +1,96 @@
1
+ ##
2
+ # aids creating fiddles for redmine_scripting_engine
3
+ #
4
+ # Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
5
+ #
6
+ # This program is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; either version 2
9
+ # of the License, or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ #
20
+ require 'deep_try'
21
+
22
+ module RedmineAPIHelper
23
+ module ArgsHelper
24
+
25
+ ########################################################################################
26
+ # iterates over current object, set index for functions accessing current object
27
+ ########################################################################################
28
+ def objects(&block)
29
+ args.objects.map do |object|
30
+ obj = yield object
31
+ @index += 1 unless @index + 1 >= args.objects.length
32
+ obj
33
+ end
34
+ end #def
35
+
36
+ ########################################################################################
37
+ # gets value of field in current object
38
+ ########################################################################################
39
+ def value( *fields )
40
+ args.objects[index].deep_try(*fields)
41
+ end #def
42
+
43
+ ########################################################################################
44
+ # serializes object to OpenStruct
45
+ ########################################################################################
46
+ def serialize(object)
47
+ if object.is_a?(Hash)
48
+ return OpenStruct.new(object.map{ |key, val| [ key, serialize(val) ] }.to_h)
49
+ elsif object.is_a?(Array)
50
+ return object.map{ |o| serialize(o) }
51
+ else # assumed to be a primitive value
52
+ return object
53
+ end
54
+ end #def
55
+
56
+ ########################################################################################
57
+ # deserializes object from OpenStruct
58
+ ########################################################################################
59
+ def deserialize(object)
60
+ if object.is_a?(OpenStruct)
61
+ return deserialize( object.to_h )
62
+ elsif object.is_a?(Hash)
63
+ return object.map{|key, obj| [key, deserialize(obj)]}.to_h
64
+ elsif object.is_a?(Array)
65
+ return object.map{|obj| deserialize(obj)}
66
+ else # assumed to be a primitive value
67
+ return object
68
+ end
69
+ end #def
70
+
71
+ ########################################################################################
72
+ # print pretty arguments passed to ruby script by plugin
73
+ ########################################################################################
74
+ def pretty(a=args)
75
+ JSON.pretty_generate(deserialize(a))
76
+ end #def
77
+
78
+ ########################################################################################
79
+ # print pretty response returned from http request
80
+ ########################################################################################
81
+ def pretty_response(hr=@http_response)
82
+ JSON.pretty_generate({
83
+ :code => hr.try(:code),
84
+ :body => JSON.parse(hr.try(:body))
85
+ })
86
+ end #def
87
+
88
+ ########################################################################################
89
+ # create html link
90
+ ########################################################################################
91
+ def link_to(text, obj, id)
92
+ "<a href='#{[args.urls.try(obj.to_sym),id].join("/")}'>#{text}</a>"
93
+ end #def
94
+
95
+ end #module
96
+ end #module