dradis-projects 4.6.0 → 4.8.0

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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/app/controllers/dradis/plugins/projects/packages_controller.rb +6 -1
  4. data/app/controllers/dradis/plugins/projects/templates_controller.rb +6 -1
  5. data/app/views/dradis/plugins/projects/export/_index-content.html.erb +1 -1
  6. data/dradis-projects.gemspec +2 -2
  7. data/lib/dradis/plugins/projects/engine.rb +2 -2
  8. data/lib/dradis/plugins/projects/export/template.rb +1 -3
  9. data/lib/dradis/plugins/projects/export/v1/template.rb +8 -0
  10. data/lib/dradis/plugins/projects/export/v2/template.rb +8 -0
  11. data/lib/dradis/plugins/projects/export/v3/template.rb +8 -0
  12. data/lib/dradis/plugins/projects/export/v4/template.rb +207 -0
  13. data/lib/dradis/plugins/projects/gem_version.rb +1 -1
  14. data/lib/dradis/plugins/projects/upload/template.rb +2 -4
  15. data/lib/dradis/plugins/projects/upload/v1/template.rb +8 -0
  16. data/lib/dradis/plugins/projects/upload/v2/template.rb +8 -0
  17. data/lib/dradis/plugins/projects/upload/v3/template.rb +8 -0
  18. data/lib/dradis/plugins/projects/upload/v4/template.rb +651 -0
  19. data/spec/fixtures/files/with_invalid_states.xml +111 -0
  20. data/spec/fixtures/files/with_states.xml +111 -0
  21. data/spec/lib/dradis/plugins/projects/export/v2/template_spec.rb +9 -1
  22. data/spec/lib/dradis/plugins/projects/export/v4/template_spec.rb +84 -0
  23. data/spec/lib/dradis/plugins/projects/upload/v1/template_spec.rb +8 -0
  24. data/spec/lib/dradis/plugins/projects/upload/v2/template_spec.rb +9 -1
  25. data/spec/lib/dradis/plugins/projects/upload/v4/template_spec.rb +168 -0
  26. metadata +20 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8faa53af81f8efa2f4b5a1c4895d0b6f9d1102ecdc8a053040b62b641498586
4
- data.tar.gz: ac5bc1e8e1cf1d85f724ebbc6ad2b8f6c35a183ef3a7359e251b874ecfa8d152
3
+ metadata.gz: f2bcef2954732f6a107819be6462b9b375503a822559a231090edd01f514862c
4
+ data.tar.gz: 1e9018effd346297a8903ac29a4c0bd6ee4041075c32acc3e7f8757da0d2ad50
5
5
  SHA512:
6
- metadata.gz: 5041579dccfc2356884fbae420b272bd32a57d8bc2791a6e46be47a6a3c3467b3fd13326409966cb94a013e33052bea0e71f9a4d23ce31aee43bfe5dcab7152d
7
- data.tar.gz: 8f652cc0034841511e6077539ecfd1774c58230315126fa6ee63ffc5cde65ffa59e851a920003bfd30de1d1c93f3fe5e9e04a1f4e234bc6c51ccc6b48d0644c6
6
+ metadata.gz: 1066f56c7938bb4b8d3f8d4cb2c3f38118a579d7a33a5b4e0b012df413887058863190fd6e5e324567d463ce2a894ddb5a5a8cfb17de15f759b75116f83bf107
7
+ data.tar.gz: 061dd18d56a3e4a1b3c1d98d0a1df0d703afd974f95018e377b3c7c2d920f9791a5c51f7467bcb3c62051d3eb10c69146fdfd7c639a3e0c4191c20b61d4553b2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ v4.8.0 (April 2023)
2
+ - Add exporting and uploading states
3
+ - Update export button copy
4
+
5
+ v4.7.0 (February 2023)
6
+ - No changes
7
+
1
8
  v4.6.0 (November 2022)
2
9
  - No changes
3
10
 
@@ -1,9 +1,14 @@
1
1
  module Dradis::Plugins::Projects
2
2
  class PackagesController < Dradis::Plugins::Export::BaseController
3
+ skip_before_action :validate_scope
4
+
3
5
  def show
4
6
  filename = Rails.root.join('tmp', 'dradis-export.zip')
5
7
 
6
- options = export_options.merge(plugin: Dradis::Plugins::Projects)
8
+ options = export_params.merge(
9
+ plugin: Dradis::Plugins::Projects,
10
+ scope: :all
11
+ )
7
12
  exporter = Dradis::Plugins::Projects::Export::Package.new(options)
8
13
  template = exporter.export(filename: filename)
9
14
 
@@ -1,10 +1,15 @@
1
1
  module Dradis::Plugins::Projects
2
2
  class TemplatesController < Dradis::Plugins::Export::BaseController
3
+ skip_before_action :validate_scope
4
+
3
5
  def show
4
6
  # this allows us to have different exporters in different editions
5
7
  exporter_class = Rails.application.config.dradis.projects.template_exporter
6
8
 
7
- options = export_options.merge(plugin: Dradis::Plugins::Projects)
9
+ options = export_params.merge(
10
+ plugin: Dradis::Plugins::Projects,
11
+ scope: :all
12
+ )
8
13
  exporter = exporter_class.new(options)
9
14
  template = exporter.export
10
15
 
@@ -14,6 +14,6 @@
14
14
  <label class="custom-control-label" for='route_template'>Template</label>
15
15
  </div>
16
16
 
17
- <button id="export-button" class="btn btn-lg btn-primary mt-4">Export</button>
17
+ <button id="export-button" class="btn btn-lg btn-primary mt-4">Export All Records</button>
18
18
  <% end %>
19
19
  <% end%>
@@ -22,9 +22,9 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency 'bundler', '~> 2.2'
24
24
  spec.add_development_dependency 'combustion'
25
- spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rake', '>= 12.3.3'
26
26
  spec.add_development_dependency 'rspec'
27
27
 
28
- spec.add_dependency 'dradis-plugins', '~> 4.0'
28
+ spec.add_dependency 'dradis-plugins', '>= 4.8.0'
29
29
  spec.add_dependency 'rubyzip'
30
30
  end
@@ -18,8 +18,8 @@ module Dradis
18
18
 
19
19
  initializer "dradis-projects.set_configs" do |app|
20
20
  options = app.config.dradis.projects
21
- options.template_exporter ||= Dradis::Plugins::Projects::Export::V3::Template
22
- options.template_uploader ||= Dradis::Plugins::Projects::Upload::V3::Template::Importer
21
+ options.template_exporter ||= Dradis::Plugins::Projects::Export::V4::Template
22
+ options.template_uploader ||= Dradis::Plugins::Projects::Upload::V4::Template::Importer
23
23
  end
24
24
 
25
25
 
@@ -27,6 +27,4 @@ module Dradis::Plugins::Projects::Export
27
27
  end
28
28
  end
29
29
 
30
- require_relative 'v1/template'
31
- require_relative 'v2/template'
32
- require_relative 'v3/template'
30
+ require_relative 'v4/template'
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v1 of the Template Exporter and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V1 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V1
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Export::V1
2
10
  class Template < Dradis::Plugins::Projects::Export::Template
3
11
  VERSION = 1
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v2 of the Template Exporter and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V2 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V2
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Export::V2
2
10
  class Template < Dradis::Plugins::Projects::Export::V1::Template
3
11
  VERSION = 2
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v3 of the Template Exporter and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V3 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V3
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Export::V3
2
10
  class Template < Dradis::Plugins::Projects::Export::V2::Template
3
11
  VERSION = 3
@@ -0,0 +1,207 @@
1
+ module Dradis::Plugins::Projects::Export::V4
2
+ class Template < Dradis::Plugins::Projects::Export::Template
3
+ VERSION = 4
4
+
5
+ protected
6
+
7
+ def build_activities_for(builder, trackable)
8
+ builder.activities do |activities_builder|
9
+ trackable.activities.each do |activity|
10
+ activities_builder.activity do |activity_builder|
11
+ activity_builder.action(activity.action)
12
+ activity_builder.user_email(user_email_for_activity(activity))
13
+ activity_builder.created_at(activity.created_at.to_i)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def build_categories(builder)
20
+ categories = []
21
+ categories << Category.issue if @issues.any?
22
+ categories += @nodes.map do |node|
23
+ node.notes.map { |note| note.category }.uniq
24
+ end.flatten.uniq
25
+
26
+ builder.categories do |categories_builder|
27
+ categories.each do |category|
28
+ categories_builder.category do |category_builder|
29
+ category_builder.id(category.id)
30
+ category_builder.name(category.name)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def build_evidence_for_node(builder, node)
37
+ builder.evidence do |evidences_builder|
38
+ node.evidence.each do |evidence|
39
+ evidences_builder.evidence do |evidence_builder|
40
+ evidence_builder.id(evidence.id)
41
+ evidence_builder.author(evidence.author)
42
+ evidence_builder.tag!('issue-id', evidence.issue_id)
43
+ evidence_builder.content do
44
+ evidence_builder.cdata!(evidence.content)
45
+ end
46
+ build_activities_for(evidence_builder, evidence)
47
+ build_comments_for(evidence_builder, evidence)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def build_issues(builder)
54
+ @issues = Issue.where(node_id: project.issue_library).includes(:activities)
55
+
56
+ builder.issues do |issues_builder|
57
+ @issues.each do |issue|
58
+ issues_builder.issue do |issue_builder|
59
+ issue_builder.id(issue.id)
60
+ issue_builder.author(issue.author)
61
+ issue_builder.state(issue.state)
62
+ issue_builder.text do
63
+ issue_builder.cdata!(issue.text)
64
+ end
65
+ build_activities_for(issue_builder, issue)
66
+ build_comments_for(issue_builder, issue)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def build_methodologies(builder)
73
+ methodologies = project.methodology_library.notes
74
+ builder.methodologies do |methodologies_builder|
75
+ methodologies.each do |methodology|
76
+ methodologies_builder.methodology(version: VERSION) do |methodology_builder|
77
+ methodology_builder.text do
78
+ methodology_builder.cdata!(methodology.text)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def build_nodes(builder)
86
+ @nodes = project.nodes.includes(:activities, :evidence, :notes, evidence: [:activities], notes: [:activities, :category]).all.reject do |node|
87
+ [Node::Types::METHODOLOGY,
88
+ Node::Types::ISSUELIB].include?(node.type_id)
89
+ end
90
+
91
+ builder.nodes do |nodes_builder|
92
+ @nodes.each do |node|
93
+ nodes_builder.node do |node_builder|
94
+ node_builder.id(node.id)
95
+ node_builder.label(node.label)
96
+ node_builder.tag!('parent-id', node.parent_id)
97
+ node_builder.position(node.position)
98
+ node_builder.properties do
99
+ node_builder.cdata!(node.raw_properties)
100
+ end
101
+ node_builder.tag!('type-id', node.type_id)
102
+ # Notes
103
+ build_notes_for_node(node_builder, node)
104
+ # Evidence
105
+ build_evidence_for_node(node_builder, node)
106
+ build_activities_for(node_builder, node)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def build_notes_for_node(builder, node)
113
+ builder.notes do |notes_builder|
114
+ node.notes.each do |note|
115
+ notes_builder.note do |note_builder|
116
+ note_builder.id(note.id)
117
+ note_builder.author(note.author)
118
+ note_builder.tag!('category-id', note.category_id)
119
+ note_builder.text do
120
+ note_builder.cdata!(note.text)
121
+ end
122
+ build_activities_for(note_builder, note)
123
+ build_comments_for(note_builder, note)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ # No-op here, overwritten in PRO
130
+ def build_report_content(builder); end
131
+
132
+ def build_tags(builder)
133
+ tags = project.tags
134
+ builder.tags do |tags_builder|
135
+ tags.each do |tag|
136
+ tags_builder.tag do |tag_builder|
137
+ tag_builder.id(tag.id)
138
+ tag_builder.name(tag.name)
139
+ tag_builder.taggings do |taggings_builder|
140
+ tag.taggings.each do |tagging|
141
+ taggings_builder.tagging do |tagging_builder|
142
+ tagging_builder.tag!('taggable-id', tagging.taggable_id)
143
+ tagging_builder.tag!('taggable-type', tagging.taggable_type)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+
153
+ # Cache user emails so we don't have to make an extra SQL request
154
+ # for every activity
155
+ def user_email_for_activity(activity)
156
+ return activity.user if activity.user.is_a?(String)
157
+
158
+ @user_emails ||= begin
159
+ User.select([:id, :email]).all.each_with_object({}) do |user, hash|
160
+ hash[user.id] = user.email
161
+ end
162
+ end
163
+ @user_emails[activity.user_id]
164
+ end
165
+
166
+ # Use the class VERSION constant, but allow for subclasses to overwrite it.
167
+ #
168
+ # See:
169
+ # http://stackoverflow.com/questions/3174563/how-to-use-an-overridden-constant-in-an-inheritanced-class
170
+ def version
171
+ self.class::VERSION
172
+ end
173
+
174
+
175
+ # Export::V2::Template
176
+ #
177
+ def build_comments_for(builder, commentable)
178
+ builder.comments do |comments_builder|
179
+ commentable.comments.each do |comment|
180
+ comments_builder.comment do |comment_builder|
181
+ comment_builder.content do
182
+ comment_builder.cdata!(comment.content)
183
+ end
184
+ comment_builder.author(comment.user&.email)
185
+ comment_builder.created_at(comment.created_at.to_i)
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ # Export::V3::Template
192
+ #
193
+ def build_methodologies(builder)
194
+ boards = content_service.all_boards
195
+
196
+ builder.methodologies do |methodologies_builder|
197
+
198
+ boards.each do |board|
199
+ node_id =
200
+ board.node == project.methodology_library ? nil : board.node_id
201
+
202
+ board.to_xml(methodologies_builder, includes: [:activities, :assignees, :comments], version: VERSION)
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
@@ -8,7 +8,7 @@ module Dradis
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 4
11
- MINOR = 6
11
+ MINOR = 8
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
@@ -33,7 +33,6 @@ module Dradis::Plugins::Projects::Upload
33
33
  # table to re-associate the attachments in the project archive with the new
34
34
  # node IDs in the current project.
35
35
  def import(params={})
36
-
37
36
  # load the template
38
37
  logger.info { "Loading template file from: #{params[:file]}" }
39
38
  template = Nokogiri::XML(File.read(params[:file]))
@@ -44,6 +43,7 @@ module Dradis::Plugins::Projects::Upload
44
43
  return false
45
44
  end
46
45
 
46
+
47
47
  if template.xpath('/dradis-template').empty?
48
48
  error = "The uploaded file doesn't look like a Dradis project template (/dradis-template)."
49
49
  logger.fatal{ error }
@@ -91,6 +91,4 @@ module Dradis::Plugins::Projects::Upload
91
91
  end
92
92
  end
93
93
 
94
- require_relative 'v1/template'
95
- require_relative 'v2/template'
96
- require_relative 'v3/template'
94
+ require_relative 'v4/template'
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v1 of the Template Importer and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V1 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V1
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Upload::V1
2
10
  module Template
3
11
 
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v2 of the Template Importer and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V2 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V2
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Upload::V2
2
10
  module Template
3
11
  class Importer < Dradis::Plugins::Projects::Upload::V1::Template::Importer
@@ -1,3 +1,11 @@
1
+ # DEPRECATED - this class is v3 of the Template Importer and shouldn't be updated.
2
+ # V4 released on Apr 2022
3
+ # V3 can be removed on Apr 2024
4
+ #
5
+ # We're duplicating this file for v4, and even though the code lives in two
6
+ # places now, this file isn't expected to evolve and is now frozen to V3
7
+ # behavior.
8
+
1
9
  module Dradis::Plugins::Projects::Upload::V3
2
10
  module Template
3
11
  class Importer < Dradis::Plugins::Projects::Upload::V2::Template::Importer