|
| 1 | +require 'net/http' |
| 2 | +require 'rack' |
| 3 | + |
1 | 4 | class SubscriptionIssuesController < ApplicationController
|
2 | 5 |
|
3 | 6 | before_action :find_template_and_authorize
|
4 | 7 | skip_before_action :verify_authenticity_token, only: [:create]
|
5 | 8 | accept_api_auth :create
|
6 | 9 |
|
7 | 10 | def create
|
8 |
| - # Check if there's an existing issue with the same fiware_entity and subscription_template_id |
9 |
| - # that was created within the threshold_create time frame |
10 |
| - existing_issue = Issue.where(fiware_entity: params["entity"], subscription_template_id: @subscription_template.id) |
11 |
| - .where("created_on >= ?", Time.now - @subscription_template.threshold_create.seconds) |
12 |
| - .order(created_on: :desc) |
13 |
| - .first |
| 11 | + @issue = find_or_initialize_issue |
14 | 12 |
|
15 |
| - if existing_issue |
16 |
| - # Create a new journal note for the existing issue |
17 |
| - note = existing_issue.init_journal(User.current, params["notes"]) |
18 |
| - |
19 |
| - # If the redmine_gtt plugin is installed and enabled, and geometry data is provided, |
20 |
| - # try to convert it to an RGeo geometry object and update the issue's geometry |
21 |
| - if Redmine::Plugin.installed?(:redmine_gtt) && @subscription_template.project.module_enabled?('gtt') && params[:geometry] |
22 |
| - begin |
23 |
| - new_geom = RedmineGtt::Conversions.to_geom(params[:geometry].to_json) |
24 |
| - if new_geom != existing_issue.geom |
25 |
| - old_geom = existing_issue.geom |
26 |
| - existing_issue.geom = new_geom |
27 |
| - # Create a new JournalDetail record to track the change to the geom attribute |
28 |
| - note.details.build(property: 'attr', prop_key: 'geom', old_value: old_geom, value: new_geom) |
29 |
| - end |
30 |
| - rescue => e |
31 |
| - logger.warn "Failed to convert geometry data: #{e.message}" |
32 |
| - end |
33 |
| - end |
| 13 | + if params[:attachments] |
| 14 | + handle_attachments |
| 15 | + end |
34 | 16 |
|
35 |
| - # Save the existing issue and respond with the appropriate JSON response |
36 |
| - if existing_issue.save |
37 |
| - render json: existing_issue.as_json(include: [:status, :tracker, :author, :assigned_to, :journals]), status: :ok |
38 |
| - else |
39 |
| - render json: { errors: existing_issue.errors.full_messages }, status: :unprocessable_entity |
40 |
| - end |
| 17 | + if @issue.save |
| 18 | + render json: @issue.as_json(include: [:status, :tracker, :author, :assigned_to, :attachments, :journals]), status: :ok |
41 | 19 | else
|
42 |
| - # Create a new issue based on the provided parameters and the subscription template |
43 |
| - @issue = Issue.new() |
44 |
| - @issue.project = @subscription_template.project |
45 |
| - @issue.tracker = @subscription_template.tracker |
46 |
| - @issue.subject = params[:subject] |
47 |
| - @issue.description = params[:description] |
48 |
| - @issue.is_private = @subscription_template.is_private |
49 |
| - @issue.status = @subscription_template.issue_status |
50 |
| - @issue.author = User.current |
51 |
| - @issue.category = @subscription_template.issue_category |
52 |
| - @issue.priority = @subscription_template.issue_priority |
53 |
| - @issue.fixed_version = @subscription_template.version |
54 |
| - |
55 |
| - # Set the fiware_entity and subscription_template_id attributes of the new issue |
56 |
| - @issue.fiware_entity = params["entity"] |
57 |
| - @issue.subscription_template_id = @subscription_template.id |
58 |
| - |
59 |
| - # If the redmine_gtt plugin is installed and enabled, and geometry data is provided, |
60 |
| - # try to convert it to an RGeo geometry object |
61 |
| - if Redmine::Plugin.installed?(:redmine_gtt) && @subscription_template.project.module_enabled?('gtt') && params[:geometry] |
62 |
| - begin |
63 |
| - @issue.geom = RedmineGtt::Conversions.to_geom(params[:geometry].to_json) |
64 |
| - rescue => e |
65 |
| - logger.warn "Failed to convert geometry data: #{e.message}" |
66 |
| - end |
67 |
| - end |
68 |
| - |
69 |
| - if @issue.save |
70 |
| - # Respond with the newly created issue and a 201 status code |
71 |
| - render json: @issue.as_json(include: [:status, :tracker, :author, :assigned_to]), status: :created |
72 |
| - else |
73 |
| - # If saving fails, respond with error messages and a 422 status code |
74 |
| - render json: { errors: @issue.errors.full_messages }, status: :unprocessable_entity |
75 |
| - end |
| 20 | + render json: { errors: @issue.errors.full_messages }, status: :unprocessable_entity |
76 | 21 | end
|
77 | 22 | end
|
78 | 23 |
|
79 | 24 | private
|
80 | 25 |
|
81 | 26 | def find_template_and_authorize
|
82 |
| - # Get subscription template from the provided ID |
83 | 27 | @subscription_template = SubscriptionTemplate.find_by(id: params[:subscription_template_id])
|
84 | 28 | unless @subscription_template
|
85 | 29 | render json: { error: 'Subscription template not found' }, status: :not_found
|
86 | 30 | return
|
87 | 31 | end
|
88 | 32 |
|
89 |
| - # Check if the user has permissions to add issues to the project |
90 | 33 | unless User.current.allowed_to?(:add_issues, @subscription_template.project)
|
91 | 34 | render json: { error: 'Not authorized to create issues' }, status: :forbidden
|
92 | 35 | return
|
93 | 36 | end
|
94 | 37 | end
|
95 | 38 |
|
| 39 | + def find_or_initialize_issue |
| 40 | + existing_issue = Issue.where(fiware_entity: params["entity"], subscription_template_id: @subscription_template.id) |
| 41 | + .where("created_on >= ?", Time.now - @subscription_template.threshold_create.seconds) |
| 42 | + .order(created_on: :desc) |
| 43 | + .first |
| 44 | + |
| 45 | + if existing_issue |
| 46 | + handle_existing_issue(existing_issue) |
| 47 | + existing_issue |
| 48 | + else |
| 49 | + handle_new_issue |
| 50 | + @issue |
| 51 | + end |
| 52 | + end |
| 53 | + |
| 54 | + def handle_existing_issue(existing_issue) |
| 55 | + note = existing_issue.init_journal(User.current, params["notes"]) |
| 56 | + |
| 57 | + if Redmine::Plugin.installed?(:redmine_gtt) && @subscription_template.project.module_enabled?('gtt') && params[:geometry] |
| 58 | + begin |
| 59 | + new_geom = RedmineGtt::Conversions.to_geom(params[:geometry].to_json) |
| 60 | + if new_geom != existing_issue.geom |
| 61 | + old_geom = existing_issue.geom |
| 62 | + existing_issue.geom = new_geom |
| 63 | + note.details.build(property: 'attr', prop_key: 'geom', old_value: old_geom, value: new_geom) |
| 64 | + end |
| 65 | + rescue => e |
| 66 | + logger.warn "Failed to convert geometry data: #{e.message}" |
| 67 | + end |
| 68 | + end |
| 69 | + end |
| 70 | + def handle_new_issue |
| 71 | + @issue = Issue.new() |
| 72 | + @issue.project = @subscription_template.project |
| 73 | + @issue.tracker = @subscription_template.tracker |
| 74 | + @issue.subject = params[:subject] |
| 75 | + @issue.description = params[:description] |
| 76 | + @issue.is_private = @subscription_template.is_private |
| 77 | + @issue.status = @subscription_template.issue_status |
| 78 | + @issue.author = User.current |
| 79 | + @issue.category = @subscription_template.issue_category |
| 80 | + @issue.priority = @subscription_template.issue_priority |
| 81 | + @issue.fixed_version = @subscription_template.version |
| 82 | + @issue.fiware_entity = params["entity"] |
| 83 | + @issue.subscription_template_id = @subscription_template.id |
| 84 | + |
| 85 | + if Redmine::Plugin.installed?(:redmine_gtt) && @subscription_template.project.module_enabled?('gtt') && params[:geometry] |
| 86 | + begin |
| 87 | + @issue.geom = RedmineGtt::Conversions.to_geom(params[:geometry].to_json) |
| 88 | + rescue => e |
| 89 | + logger.warn "Failed to convert geometry data: #{e.message}" |
| 90 | + end |
| 91 | + end |
| 92 | + end |
| 93 | + |
| 94 | + def handle_attachments |
| 95 | + existing_filenames = @issue.attachments.map { |a| a.filename } |
| 96 | + |
| 97 | + params[:attachments].each do |attachment| |
| 98 | + uri = URI.parse(attachment['url']) |
| 99 | + filename = attachment['filename'] || File.basename(uri.path) |
| 100 | + |
| 101 | + next if existing_filenames.include?(filename) |
| 102 | + |
| 103 | + begin |
| 104 | + response = Net::HTTP.get_response(uri) |
| 105 | + |
| 106 | + if response.is_a?(Net::HTTPSuccess) |
| 107 | + file = Tempfile.new('attachment') |
| 108 | + file.binmode |
| 109 | + file.write(response.body) |
| 110 | + file.rewind |
| 111 | + |
| 112 | + description = attachment['description'] || '' |
| 113 | + content_type = attachment['content_type'] || response.content_type |
| 114 | + |
| 115 | + uploaded_file = Rack::Multipart::UploadedFile.new(file.path, content_type, true, filename: filename) |
| 116 | + |
| 117 | + @issue.attachments.build(file: uploaded_file, description: description, author: User.current) |
| 118 | + else |
| 119 | + logger.warn "Failed to download file: #{response.message}" |
| 120 | + end |
| 121 | + rescue => e |
| 122 | + logger.warn "Failed to attach file: #{e.message}" |
| 123 | + end |
| 124 | + end |
| 125 | + end |
| 126 | + |
96 | 127 | def issue_params
|
97 |
| - # Defines the allowed parameters for an issue |
98 | 128 | params.require(:issue).permit(:project, :tracker, :subject, :description, :is_private, :status, :author, :fixed_version, :category, :priority)
|
99 | 129 | end
|
100 | 130 |
|
|
0 commit comments