foreman_openscap 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 48ae466c6c227a222397d8a8151177798cf1a035
4
- data.tar.gz: 6abafa02b5291e3b1aa4c36a682e4ea931ccd646
3
+ metadata.gz: 92cfa722f49b4849b12e6de9b12752f7403250c9
4
+ data.tar.gz: 216d2b98129dc7cf0de15c0c294522d8147e3a7c
5
5
  SHA512:
6
- metadata.gz: d3c84160ddb908cd9f928878bed4f11c14e9691fe827f072795003e1bc97687db1c2ce33826b57a3ef64997c10bd7d4e44aa5b9d505da02bf9b0145e53511e85
7
- data.tar.gz: e9fcbe1028267dbc7ca0d548e41d4390309e540465609eefe739a3fce064566119d72a8fc498e6174697057be2642520839f1f15227ca1e1ac09fcf7fafc0af5
6
+ metadata.gz: 8c90cfa657a43e9490a5246dc8a195d0476b2d2c84ff33c97ffc633c96af029a8ebe71f87b5bc980212192a25aa50bd773d19b01648fea3082f186120e05713a
7
+ data.tar.gz: b7044c839f2b328e2591f93dc85081f1cc97fded7d0346ed5ab0afdc1896bd4cb82c168ad3af354976e4fb6eaf76c8c3bd1c6f9b0fc0ec558f582257b0df6f50
@@ -70,6 +70,16 @@ module Api::V2
70
70
  process_response @policy.destroy
71
71
  end
72
72
 
73
+ api :GET, '/compliance/policies/:id/content', N_("Show a policy's SCAP content")
74
+ param :id, :identifier, :required => true
75
+
76
+ def content
77
+ @scap_content = @policy.scap_content
78
+ send_data @scap_content.scap_file,
79
+ :type => 'application/xml',
80
+ :filename => @scap_content.original_filename
81
+ end
82
+
73
83
  private
74
84
  def find_resource
75
85
  not_found and return if params[:id].blank?
@@ -26,7 +26,7 @@ module ForemanOpenscap
26
26
  end
27
27
 
28
28
  def combined_policies
29
- combined = self.policies + self.hostgroup.policies
29
+ combined = self.hostgroup ? self.policies + self.hostgroup.policies : self.policies
30
30
  combined.uniq
31
31
  end
32
32
 
@@ -19,19 +19,19 @@ module ForemanOpenscap
19
19
  attr_accessible :location_ids, :organization_ids, :current_step, :hostgroup_ids
20
20
  attr_writer :current_step
21
21
 
22
- SCAP_PUPPET_CLASS = 'foreman_scap_client'
22
+ SCAP_PUPPET_CLASS = 'foreman_scap_client'
23
23
  POLICIES_CLASS_PARAMETER = 'policies'
24
- SERVER_CLASS_PARAMETER = 'server'
25
- PORT_CLASS_PARAMETER = 'port'
24
+ SERVER_CLASS_PARAMETER = 'server'
25
+ PORT_CLASS_PARAMETER = 'port'
26
26
 
27
- validates :name, :presence => true, :uniqueness => true, :format => { without: /\s/ }
27
+ validates :name, :presence => true, :uniqueness => true, :format => {without: /\s/}
28
28
  validate :ensure_needed_puppetclasses
29
29
  validates :period, :inclusion => {:in => %w[weekly monthly custom]},
30
- :if => Proc.new { | policy | policy.new_record? ? policy.step_index > 3 : !policy.id.blank? }
30
+ :if => Proc.new { |policy| policy.new_record? ? policy.step_index > 3 : !policy.id.blank? }
31
31
  validates :weekday, :inclusion => {:in => Date::DAYNAMES.map(&:downcase)},
32
- :if => Proc.new { | policy | policy.period == 'weekly' && (policy.new_record? ? policy.step_index > 3 : !policy.id.blank?) }
32
+ :if => Proc.new { |policy| policy.period == 'weekly' && (policy.new_record? ? policy.step_index > 3 : !policy.id.blank?) }
33
33
  validates :day_of_month, :numericality => {:greater_than => 0, :less_than => 32},
34
- :if => Proc.new { | policy | policy.period == 'monthly'&& (policy.new_record? ? policy.step_index > 3 : !policy.id.blank?) }
34
+ :if => Proc.new { |policy| policy.period == 'monthly'&& (policy.new_record? ? policy.step_index > 3 : !policy.id.blank?) }
35
35
  validate :valid_cron_line
36
36
  validate :ensure_period_specification_present
37
37
 
@@ -82,7 +82,7 @@ module ForemanOpenscap
82
82
  end
83
83
 
84
84
  def next_step
85
- steps[steps.index(current_step) + 1 ]
85
+ steps[steps.index(current_step) + 1]
86
86
  end
87
87
 
88
88
  def rewind_step
@@ -111,14 +111,14 @@ module ForemanOpenscap
111
111
 
112
112
  def used_location_ids
113
113
  Location.joins(:taxable_taxonomies).where(
114
- 'taxable_taxonomies.taxable_type' => 'Scaptimony::Policy',
115
- 'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
114
+ 'taxable_taxonomies.taxable_type' => 'Scaptimony::Policy',
115
+ 'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
116
116
  end
117
117
 
118
118
  def used_organization_ids
119
119
  Organization.joins(:taxable_taxonomies).where(
120
- 'taxable_taxonomies.taxable_type' => 'Scaptimony::Policy',
121
- 'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
120
+ 'taxable_taxonomies.taxable_type' => 'Scaptimony::Policy',
121
+ 'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
122
122
  end
123
123
 
124
124
  def used_hostgroup_ids
@@ -136,9 +136,10 @@ module ForemanOpenscap
136
136
 
137
137
  def to_enc
138
138
  {
139
- 'id' => self.id,
140
- 'profile_id' => self.scap_content_profile.try(:profile_id) || '',
141
- 'content_path' => "/var/lib/openscap/content/#{self.scap_content.digest}.xml",
139
+ 'id' => self.id,
140
+ 'profile_id' => self.scap_content_profile.try(:profile_id) || '',
141
+ 'content_path' => "/var/lib/openscap/content/#{self.scap_content.digest}.xml",
142
+ 'download_path' => "/compliance/policies/#{self.id}/content" # default to proxy path
142
143
  }.merge(period_enc)
143
144
  end
144
145
 
@@ -147,22 +148,22 @@ module ForemanOpenscap
147
148
  def period_enc
148
149
  # get crontab expression as an array (minute hour day_of_month month day_of_week)
149
150
  cron_parts = case period
150
- when 'weekly'
151
- [ '0', '1', '*', '*', weekday_number.to_s ]
152
- when 'monthly'
153
- [ '0', '1', day_of_month.to_s, '*', '*']
154
- when 'custom'
155
- cron_line_split
156
- else
157
- raise 'invalid period specification'
158
- end
151
+ when 'weekly'
152
+ ['0', '1', '*', '*', weekday_number.to_s]
153
+ when 'monthly'
154
+ ['0', '1', day_of_month.to_s, '*', '*']
155
+ when 'custom'
156
+ cron_line_split
157
+ else
158
+ raise 'invalid period specification'
159
+ end
159
160
 
160
161
  {
161
- 'minute' => cron_parts[0],
162
- 'hour' => cron_parts[1],
163
- 'monthday' => cron_parts[2],
164
- 'month' => cron_parts[3],
165
- 'weekday' => cron_parts[4],
162
+ 'minute' => cron_parts[0],
163
+ 'hour' => cron_parts[1],
164
+ 'monthday' => cron_parts[2],
165
+ 'month' => cron_parts[3],
166
+ 'weekday' => cron_parts[4],
166
167
  }
167
168
  end
168
169
 
@@ -182,8 +183,8 @@ module ForemanOpenscap
182
183
  return false
183
184
  end
184
185
 
185
- policies_param.override = true
186
- policies_param.key_type = 'array'
186
+ policies_param.override = true
187
+ policies_param.key_type = 'array'
187
188
  policies_param.default_value = '<%= @host.policies_enc %>'
188
189
 
189
190
  if policies_param.changed? && !policies_param.save
@@ -233,11 +234,11 @@ module ForemanOpenscap
233
234
  if hostgroup.puppet_proxy && (url = hostgroup.puppet_proxy.url).present?
234
235
  case override.key
235
236
  when SERVER_CLASS_PARAMETER
236
- lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
237
+ lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
237
238
  puppet_proxy_fqdn = URI.parse(url).host
238
239
  lookup_value.update_attribute(:value, puppet_proxy_fqdn)
239
240
  when PORT_CLASS_PARAMETER
240
- lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
241
+ lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
241
242
  puppet_proxy_port = URI.parse(url).port
242
243
  lookup_value.update_attribute(:value, puppet_proxy_port)
243
244
  end
@@ -13,7 +13,7 @@
13
13
  </tr>
14
14
  <% latest_reports.each do |report| %>
15
15
  <tr>
16
- <td><%= link_to h(report.host.name), scaptimony_arf_report_path(report) %></td>
16
+ <td><%= link_to h(report.host.nil? ? _('Host does not exist anymore') : report.host.name), scaptimony_arf_report_path(report) %></td>
17
17
  <td><%= link_to h(report.policy.name), scaptimony_policy_dashboard_scaptimony_policy_path(report.policy) %></td>
18
18
  <td><%= report_event_column(report.passed, "label-success") %></td>
19
19
  <td><%= report_event_column(report.failed, "label-danger") %></td>
@@ -9,7 +9,7 @@
9
9
  </tr>
10
10
  <% for arf_report in @arf_reports %>
11
11
  <tr>
12
- <td><%= name_column(arf_report.host) %></td>
12
+ <td><%= arf_report.host.nil? ? _('Host does not exist anymore') : name_column(arf_report.host) %></td>
13
13
  <td><%= _("%s ago") % time_ago_in_words(arf_report.date) %></td>
14
14
  <td><%= report_arf_column(arf_report.passed, "label-info") %></th>
15
15
  <td><%= report_arf_column(arf_report.failed, "label-danger") %></th>
@@ -2,24 +2,21 @@
2
2
 
3
3
  <% title _("Compliance policy: %s") % @policy.name %>
4
4
 
5
- <div id='dashboard' class="row gridster">
5
+ <div id='dashboard' class="gridster col-md-12 ready">
6
6
  <ul>
7
- <%= policy_widget_list.map do |widget|
8
- content_tag(:li, render(widget.id), :data => {
9
- :id => widget.id,
10
- :name => widget.name || widget.id,
11
- :row => widget.row,
12
- :col => widget.col,
13
- :sizex => widget.sizex,
14
- :sizey => widget.sizey,
15
- :hide => widget.hide
16
- })
17
- end.join(' ').html_safe
18
- %>
7
+ <% [{:template => 'policy_status_widget', :sizex => 8, :sizey => 1, :name => N_('Status table')},
8
+ {:template => 'policy_chart_widget', :sizex => 4, :sizey => 1, :name => N_('Status chart')}].each do |w| %>
9
+ <% widget = Widget.new(w) %>
10
+ <%= content_tag(:li, widget_data(widget)) do %>
11
+ <div class="widget <%= widget.name.parameterize %>">
12
+ <%= render_widget(widget) %>
13
+ </div>
14
+ <% end %>
15
+ <% end %>
19
16
  </ul>
20
17
  </div>
21
18
  <% if @policy.arf_reports.any? %>
22
- <div class="row gridster">
19
+ <div class="col-md-12 gridster">
23
20
  <%= _("Latest reports for policy: %s") % @policy.name %>
24
21
  <%= render :partial => 'policy_reports' %>
25
22
  </div>
data/config/routes.rb CHANGED
@@ -40,7 +40,11 @@ Rails.application.routes.draw do
40
40
  :apiv => /v1|v2/, :constraints => ApiConstraints.new(:version => 2) do
41
41
  namespace :compliance do
42
42
  resources :scap_contents, :except => [:new, :edit]
43
- resources :policies, :except => [:new, :edit]
43
+ resources :policies, :except => [:new, :edit] do
44
+ member do
45
+ get 'content'
46
+ end
47
+ end
44
48
  resources :arf_reports, :only => [:index, :show, :destroy]
45
49
  post 'arf_reports/:cname/:policy_id/:date', \
46
50
  :constraints => { :cname => /[^\/]+/ }, :to => 'arf_reports#create'
@@ -0,0 +1,2 @@
1
+ require 'foreman_openscap/bulk_upload'
2
+ ForemanOpenscap::BulkUpload.new(true).generate_scap_default_content
@@ -0,0 +1,62 @@
1
+ require 'digest/sha2'
2
+ module ForemanOpenscap
3
+ class BulkUpload
4
+ attr_accessor :from_scap_security_guide
5
+ def initialize(from_scap_security_guide=false)
6
+ @from_scap_security_guide = from_scap_security_guide
7
+ end
8
+
9
+ def generate_scap_default_content
10
+ return unless @from_scap_security_guide
11
+
12
+ if `rpm -qa | grep scap-security-guide`.empty?
13
+ Rails.logger.debug "Can't find scap-security-guide RPM"
14
+ return
15
+ end
16
+
17
+ files_array = `rpm -ql scap-security-guide | grep ds.xml`.split
18
+ upload_from_files(files_array) unless files_array.empty?
19
+ end
20
+
21
+ def upload_from_files(files_array)
22
+ files_array.each do |datastream|
23
+ file = File.open(datastream, 'rb').read
24
+ digest = Digest::SHA2.hexdigest(datastream)
25
+ title = content_name(datastream)
26
+ filename = original_filename(datastream)
27
+ scap_content = Scaptimony::ScapContent.where(:title => title, :digest => digest, :scap_file => file).first_or_initialize
28
+ unless scap_content.persisted?
29
+ scap_content.original_filename = filename
30
+ next puts "## SCAP content is invalid: #{scap_content.errors.full_messages.uniq.join(',')} ##" unless scap_content.valid?
31
+ if scap_content.save
32
+ puts "Saved #{datastream} as #{scap_content.title}"
33
+ else
34
+ puts "Failed saving #{datastream}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def upload_from_directory(directory_path)
41
+ files_array = Dir["#{directory_path}/*-ds.xml"]
42
+ upload_from_files(files_array) unless files_array.empty?
43
+ end
44
+
45
+ private
46
+
47
+ def extract_name_from_file(file)
48
+ # SCAP datastream files are in format of ssg-<OS>-ds.xml
49
+ # We wish to extract the <OS> and create a name of it
50
+ original_filename(file).gsub('ssg-','').gsub('-ds.xml', '')
51
+ end
52
+
53
+ def original_filename(file)
54
+ file.split('/').last
55
+ end
56
+
57
+ def content_name(datastream)
58
+ os_name = extract_name_from_file(datastream)
59
+ @from_scap_security_guide ? "Red Hat #{os_name} default content" : "#{os_name} content"
60
+ end
61
+ end
62
+ end
@@ -10,8 +10,25 @@
10
10
 
11
11
  module ForemanOpenscap::Helper
12
12
  def self.get_asset(cname, policy_id)
13
- asset = Host.find_by_name!(cname).get_asset
13
+ asset = find_host_by_name_or_uuid(cname).get_asset
14
14
  asset.policy_ids += [policy_id]
15
15
  asset
16
16
  end
17
+
18
+ private
19
+
20
+ def self.find_host_by_name_or_uuid(cname)
21
+ if defined?(Katello::System)
22
+ host = Host.includes(:content_host).where(:katello_systems => {:uuid => cname}).first
23
+ host ||= Host.find_by_name(cname)
24
+ else
25
+ host = Host.find_by_name(cname)
26
+ end
27
+ unless host
28
+ Rails.logger.error "Could not find Host with name: #{cname}"
29
+ Rails.logger.error "Please check that Content host is linked to Foreman host" if defined?(Katello::System)
30
+ raise ActiveRecord::RecordNotFound
31
+ end
32
+ host
33
+ end
17
34
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanOpenscap
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -1,9 +1,19 @@
1
1
  # Tasks
2
2
  namespace :foreman_openscap do
3
- namespace :example do
4
- desc 'Example Task'
5
- task :task => :environment do
6
- # Task goes here
3
+ require 'foreman_openscap/bulk_upload'
4
+ namespace :bulk_upload do
5
+ desc 'Bulk upload SCAP content from directory'
6
+ task :directory, [:directory] => [:environment] do |task, args|
7
+ abort("# No such directory, please check the path you have provided. #") unless args[:directory].blank? || Dir.exist?(args[:directory])
8
+ ForemanOpenscap::BulkUpload.new.upload_from_directory(args[:directory])
9
+ end
10
+
11
+ task :files, [:files] => [:environment] do |task, args|
12
+ files_array = args[:files].split(' ')
13
+ files_array.each do |file|
14
+ abort("# #{file} is a directory, expecting file. Try using 'rake foreman_openscap:bulk_upload:directory' with this directory. #") if File.directory?(file)
15
+ end
16
+ ForemanOpenscap::BulkUpload.new.upload_from_files(files_array)
7
17
  end
8
18
  end
9
19
  end
@@ -55,4 +55,11 @@ class Api::V2::PoliciesControllerTest < ActionController::TestCase
55
55
  assert_response :ok
56
56
  refute Scaptimony::Policy.exists?(policy.id)
57
57
  end
58
+
59
+ test "should return xml of scap content" do
60
+ policy = FactoryGirl.create(:policy)
61
+ get :content, { :id => policy.id }, set_session_user
62
+ assert(@response.header['Content-Type'], 'application/xml')
63
+ assert_response :success
64
+ end
58
65
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_openscap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
- - "Šimon Lukašík"
7
+ - Šimon Lukašík
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-25 00:00:00.000000000 Z
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: scaptimony
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.3.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.3.0
41
41
  description: Foreman plug-in for managing security compliance reports
@@ -75,8 +75,6 @@ files:
75
75
  - app/overrides/hosts/overview/host_compliance_status.rb
76
76
  - app/services/scaptimony/host_report_dashboard/data.rb
77
77
  - app/services/scaptimony/policy_dashboard/data.rb
78
- - app/services/scaptimony/policy_dashboard/loader.rb
79
- - app/services/scaptimony/policy_dashboard/manager.rb
80
78
  - app/services/scaptimony/report_dashboard/data.rb
81
79
  - app/views/api/v2/compliance/arf_reports/base.json.rabl
82
80
  - app/views/api/v2/compliance/arf_reports/index.json.rabl
@@ -128,7 +126,9 @@ files:
128
126
  - app/views/scaptimony_scap_contents/welcome.html.erb
129
127
  - config/routes.rb
130
128
  - db/seeds.d/openscap_feature.rb
129
+ - db/seeds.d/openscap_scap_default.rb
131
130
  - lib/foreman_openscap.rb
131
+ - lib/foreman_openscap/bulk_upload.rb
132
132
  - lib/foreman_openscap/engine.rb
133
133
  - lib/foreman_openscap/helper.rb
134
134
  - lib/foreman_openscap/version.rb
@@ -153,12 +153,12 @@ require_paths:
153
153
  - lib
154
154
  required_ruby_version: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - ">="
156
+ - - '>='
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
159
  required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  requirements:
161
- - - ">="
161
+ - - '>='
162
162
  - !ruby/object:Gem::Version
163
163
  version: '0'
164
164
  requirements: []
@@ -168,14 +168,14 @@ signing_key:
168
168
  specification_version: 4
169
169
  summary: Foreman plug-in for displaying OpenSCAP audit reports
170
170
  test_files:
171
- - test/unit/openscap_host_test.rb
172
- - test/test_plugin_helper.rb
173
- - test/files/scap_contents/ssg-fedora-ds.xml
174
- - test/functional/api/v2/arf_reports_controller_test.rb
175
- - test/functional/api/v2/scap_contents_controller_test.rb
176
- - test/functional/api/v2/policies_controller_test.rb
177
- - test/factories/asset_factory.rb
178
171
  - test/factories/policy_factory.rb
172
+ - test/factories/asset_factory.rb
179
173
  - test/factories/scap_content_related.rb
180
174
  - test/factories/arf_report_factory.rb
175
+ - test/unit/openscap_host_test.rb
176
+ - test/files/scap_contents/ssg-fedora-ds.xml
177
+ - test/functional/api/v2/policies_controller_test.rb
178
+ - test/functional/api/v2/scap_contents_controller_test.rb
179
+ - test/functional/api/v2/arf_reports_controller_test.rb
180
+ - test/test_plugin_helper.rb
181
181
  has_rdoc:
@@ -1,20 +0,0 @@
1
- #
2
- # Copyright (c) 2014 Red Hat Inc.
3
- #
4
- # This software is licensed to you under the GNU General Public License,
5
- # version 3 (GPLv3). There is NO WARRANTY for this software, express or
6
- # implied, including the implied warranties of MERCHANTABILITY or FITNESS
7
- # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
8
- # along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
9
- #
10
-
11
- module Scaptimony::PolicyDashboard
12
- class Loader
13
- def self.load
14
- Scaptimony::PolicyDashboard::Manager.map do |dashboard|
15
- dashboard.widget 'policy_status_widget', :row=>1,:col=>1,:sizex=>8,:sizey=>1,:name=> N_('Status table')
16
- dashboard.widget 'policy_chart_widget', :row=>1,:col=>9,:sizex=>4,:sizey=>1,:name=> N_('Status chart')
17
- end
18
- end
19
- end
20
- end
@@ -1,32 +0,0 @@
1
- #
2
- # Copyright (c) 2014 Red Hat Inc.
3
- #
4
- # This software is licensed to you under the GNU General Public License,
5
- # version 3 (GPLv3). There is NO WARRANTY for this software, express or
6
- # implied, including the implied warranties of MERCHANTABILITY or FITNESS
7
- # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
8
- # along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
9
- #
10
-
11
- module Scaptimony::PolicyDashboard
12
- module Manager
13
- class << self
14
- def map
15
- @widgets ||= []
16
- mapper = Mapper.new(@widgets)
17
- if block_given?
18
- yield mapper
19
- else
20
- mapper
21
- end
22
- end
23
-
24
- def widgets
25
- @widgets ||= Scaptimony::PolicyDashboard::Loader.load
26
- end
27
- end
28
-
29
- class Mapper < ::Dashboard::Manager::Mapper
30
- end
31
- end
32
- end