redmine_api_helper 0.1.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.

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