Skip to content

Commit

Permalink
Add widget set endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
lpichler committed Dec 9, 2020
1 parent d550a30 commit 0103ab1
Show file tree
Hide file tree
Showing 3 changed files with 321 additions and 0 deletions.
130 changes: 130 additions & 0 deletions app/controllers/api/widget_sets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module Api
class WidgetSetsController < BaseController
REQUIRED_FIELDS_TO_COPY = %w[name].freeze
ALLOWED_FIELDS = REQUIRED_FIELDS_TO_COPY + %w[group description guid read_only set_data].freeze
SET_DATA_COLS = %i[col1 col2 col3].freeze

def init_set_data(set_data)
set_data ||= {}
new_set_data ||= {}
new_set_data[:col1] = set_data['col1'] || []
new_set_data[:col2] = set_data['col2'] || []
new_set_data[:col3] = set_data['col3'] || []
new_set_data[:reset_upon_login] = !!set_data['reset_upon_login']
new_set_data[:locked] = !!set_data['locked']
new_set_data
end

def init_widget_set(data)
data['set_type'] = "MiqWidgetSet"
data['owner_type'] = "MiqGroup"
data['set_data'] = init_set_data(data['set_data'])
data
end

def validate_description(group_id, description)
widget_set_exists_in_group = MiqWidgetSet.exists?(:owner_id => group_id, :description => description)
raise ArgumentError, "Description(Tab Title) must be unique for this group" if widget_set_exists_in_group
end

def validate_widgets_in_set_data(set_data)
widget_ids = SET_DATA_COLS.map { |x| set_data[x] }.flatten.compact
raise ArgumentError, "One widget must be selected(set_data)" if widget_ids.empty?

filtered_widget_ids = MiqWidget.where(:id => widget_ids).pluck(:id)
unless filtered_widget_ids.count == widget_ids.count
raise ArgumentError, "Unable to find widget set ids: #{widget_ids - filtered_widget_ids} "
end
end

def create_resource(type, id = nil, data = nil)
raise_if_unsupported_fields_passed(data)

raise ArgumentError, "Name cannot contain \"|\"" if data['name'].index('|')

data = init_widget_set(data)

validate_description(data['owner_id'], data['description'])
validate_widgets_in_set_data(data['set_data'])

data['owner_id'] = parse_resource_from(data.delete('group'))
group = resource_search(data['owner_id'], :groups, MiqGroup)
result = nil
group.transaction do
result = super(type, id, data)
group.settings ||= {:dashboard_order => []}
group.settings[:dashboard_order].push(result['id'])
group.save
widget_set_update_members(result)
end

result
end

def edit_resource(type, id = nil, data = nil)
raise_if_unsupported_fields_passed(data, ALLOWED_FIELDS - %w[name group])

if data['description']
resource = resource_search(id, type, collection_class(type))
validate_description(resource.owner_id, data['description'])
end

data['set_data'] = init_set_data(data['set_data'])
validate_widgets_in_set_data(data['set_data'])
result = nil
collection_class(type).transaction do
result = super(type, id, data)
widget_set_update_members(result)
end

result
end

def delete_resource(type, id = nil, data = nil)
klass = collection_class(type)
widget_set = resource_search(id, type, klass)
raise ArgumentError, "Unable to delete read_only widget_set" if widget_set.read_only?

widget_set.transaction do
group = MiqGroup.find(widget_set.owner_id)
group.save if group&.settings.try(:dashboard_order)&.delete(widget_set.id)

super(type, id, data)
end
end

def copy_resource(type, id = nil, data = nil)
raise ArgumentError, "Required field(s) #{REQUIRED_FIELDS_TO_COPY.join(", ")}" if (REQUIRED_FIELDS_TO_COPY - data.keys).present?

raise_if_unsupported_fields_passed(data)

api_action(type, id) do |klass|
widget_set = resource_search(id, type, klass)
group_id = data['id']&.to_i || parse_resource_from(data['group']) || widget_set.group_id
copied_widget_set = MiqWidgetSet.copy_dashboard(widget_set, data['name'], data['description'], group_id)
widget_set_update_members(copied_widget_set)

action_result(true, "Dashboard #{data['name']} successfully created.")
end
end

def parse_resource_from(attributes)
return unless attributes

attributes['id']&.to_i || (attributes['href'] && Api::Href.new(attributes['href']).subject_id) if attributes
end

def raise_if_unsupported_fields_passed(data, allowed_fields = ALLOWED_FIELDS)
unsupported_fields = data.keys - allowed_fields
raise ArgumentError, "Field(s) #{unsupported_fields.join(", ")} are not supported" if unsupported_fields.present?
end

def widget_set_update_members(widget_set)
widget_ids = SET_DATA_COLS.collect { |key| widget_set.set_data[key] }.flatten
widgets = Array(MiqWidget.where(:id => widget_ids))

widget_set.replace_children(widgets)
widget_set.members.each { |w| w.create_initial_content_for_user(current_user.userid) } # Generate content if not there
end
end
end
45 changes: 45 additions & 0 deletions config/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4619,6 +4619,51 @@
:identifier:
- vm_snapshot_delete
- sui_vm_snapshot_delete
:widget_sets:
:description: Dashboards
:identifier: miq_report_dashboard_editor
:options:
- :collection
:verbs: *gpppd
:klass: MiqWidgetSet
:collection_actions:
:get:
- :name: read
:identifier: miq_report_dashboard_editor
:post:
- :name: query
:identifier: miq_report_dashboard_editor
- :name: create
:identifier: db_new
- :name: edit
:identifier: db_edit
- :name: delete
:identifier: db_delete
- :name: copy
:identifier: db_copy
:delete:
- :name: delete
:identifier: db_delete
:resource_actions:
:get:
- :name: read
:identifier: miq_report_dashboard_editor
:post:
- :name: edit
:identifier: db_edit
- :name: delete
:identifier: db_delete
- :name: copy
:identifier: db_copy
:patch:
- :name: edit
:identifier: db_edit
:put:
- :name: edit
:identifier: db_edit
:delete:
- :name: delete
:identifier: db_delete
:widgets:
:description: Miq Widgets
:identifier: miq_report_widget_admin
Expand Down
146 changes: 146 additions & 0 deletions spec/requests/widget_sets_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
describe "Widget Sets API" do
let(:group) { User.current_user.current_group }
let(:miq_widget_set) { FactoryBot.create(:miq_widget_set, :owner => group) }
let(:miq_widget_set_other) { FactoryBot.create(:miq_widget_set, :owner => group) }
let(:widgets) { FactoryBot.create_list(:miq_widget, 3) }
let(:widget_params) do
{
"name" => "XXX",
"description" => "YYY",
"set_data" => {"col1" => widgets.map(&:id),
"reset_upon_login" => false,
"locked" => false}
}
end

before do
User.current_user = User.first
end

context "GET" do
it "returns single" do
api_basic_authorize collection_action_identifier(:widget_sets, :read, :get)

get(api_widget_set_url(nil, miq_widget_set))

expect(response).to have_http_status(:ok)
expect(response.parsed_body['id'].to_i).to eq(miq_widget_set.id)
end

it "returns all widget sets" do
api_basic_authorize collection_action_identifier(:widget_sets, :read, :get)

get(api_widget_sets_url)

expect(response).to have_http_status(:ok)
widget_sets_hrefs = response.parsed_body['resources'].map { |x| x['href'] }
all_widget_sets_hrefs = MiqWidgetSet.all.map { |ws| api_widget_set_url(nil, ws) }
expect(widget_sets_hrefs).to match_array(all_widget_sets_hrefs)
end

it "doesn't find widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :read, :get)

get(api_widget_set_url(nil, 999_999))

expect(response).to have_http_status(:not_found)
end

it "forbids action get for non-super-admin user" do
expect_forbidden_request do
get(api_widget_set_url(nil, miq_widget_set))
end
end
end

context "POST" do
let(:group_href) { api_group_url(nil, group) }

it "creates widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :create, :post)

post api_widget_sets_url, :params => gen_request(:create, widget_params.merge('group' => {'href' => group_href}))

expect(response).to have_http_status(:ok)

widget_params["set_data"]["col2"] = []
widget_params["set_data"]["col3"] = []
expect(response.parsed_body['results'][0].values_at(*widget_params.keys)).to match_array(widget_params.values)
ws = MiqWidgetSet.find(response.parsed_body['results'][0]['id'])
expect(ws.members.map(&:id)).to eq(widgets.map(&:id))
group.reload
expect(group.settings["dashboard_order"]).to eq([ws.id])
end

it "updates widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :edit, :post)

widget_params_for_update = widget_params.except('name')
post api_widget_set_url(nil, miq_widget_set), :params => gen_request(:edit, widget_params_for_update)

expect(response).to have_http_status(:ok)
expect(response.parsed_body['id'].to_i).to eq(miq_widget_set.id)
widget_params["set_data"]["col2"] = []
widget_params["set_data"]["col3"] = []
expect(response.parsed_body.values_at(*widget_params_for_update.keys)).to match_array(widget_params_for_update.values)
ws = MiqWidgetSet.find(response.parsed_body['id'])
expect(ws.members.map(&:id)).to eq(widgets.map(&:id))
end

it "deletes widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :delete, :post)
widget_set_id = miq_widget_set.id
group.settings = {"dashboard_order" => [1, 2]}
group.save
post api_widget_set_url(nil, miq_widget_set), :params => gen_request(:delete, widget_params)
expect(response).to have_http_status(:ok)
expect(MiqWidgetSet.find_by(:id => widget_set_id)).to be_nil
group.reload
expect(group.settings["dashboard_order"]).not_to include(widget_set_id)
end

it "forbids action for non-super-admin user" do
expect_forbidden_request do
post(api_widget_sets_url)
end
end
end

context "PUT" do
it "updates widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :edit, :post)
params_for_put = widget_params.except('name')
put api_widget_set_url(nil, miq_widget_set), :params => params_for_put

expect(response).to have_http_status(:ok)
expect(response.parsed_body['id'].to_i).to eq(miq_widget_set.id)

widget_params["set_data"]["col2"] = []
widget_params["set_data"]["col3"] = []
expect(response.parsed_body.values_at(*params_for_put.keys)).to match_array(params_for_put.values)
end

it "forbids action for non-super-admin user" do
expect_forbidden_request do
put(api_widget_set_url(nil, miq_widget_set))
end
end
end

context "DELETE" do
it "deletes widget set" do
api_basic_authorize collection_action_identifier(:widget_sets, :delete, :post)
widget_set_id = miq_widget_set.id

delete api_widget_set_url(nil, miq_widget_set)
expect(response).to have_http_status(:no_content)
expect(MiqWidgetSet.find_by(:id => widget_set_id)).to be_nil
end

it "forbids action for non-super-admin user" do
expect_forbidden_request do
delete(api_widget_set_url(nil, miq_widget_set))
end
end
end
end

0 comments on commit 0103ab1

Please sign in to comment.