Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add WidgetSet endpoint #968

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions app/controllers/api/widget_sets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with 'read_only' here, does this mean the API can create read_only widget sets and cannot delete them ? I usually think of read_only as set to true for some system seeded resources.


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

data['group_id'] = parse_resource_from(data.delete('group'))
data['owner_id'] = data['group_id']
super(type, id, data)
end

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

super(type, id, data)
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?

api_action(type, id) do |_klass|
super(type, id, data)

action_result(true, "Dashboard #{widget_set.name} has been successfully deleted.")
end
end

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

klass = collection_class(type)
widget_set = resource_search(id, type, klass)
group_id = parse_resource_from(data['group']) || widget_set.group_id

widget_set = MiqWidgetSet.copy_dashboard(widget_set, data['name'], data['description'], group_id)

result = action_result(true, "Dashboard #{data['name']} successfully created.")
add_href_to_result(result, type, widget_set.id)
result
end

private

def parse_resource_from(attributes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these two below be private?

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 BadRequestError, "Field(s) #{unsupported_fields.join(", ")} are not supported" if unsupported_fields.present?
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, :set_data_with_one_widget, :owner => group) }
let(:miq_widget_set_other) { FactoryBot.create(:miq_widget_set, :set_data_with_one_widget, :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, widget_set_id]}
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