Skip to content

Commit

Permalink
Merge pull request #1695 from kreuzwerker/missing-agent-warning
Browse files Browse the repository at this point in the history
Rescue from AR:SubclassNotFound and allow to delete agents
  • Loading branch information
dsander committed Sep 21, 2016
2 parents d2b26a0 + 42b1320 commit e0fa7f0
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 1 deletion.
6 changes: 6 additions & 0 deletions app/controllers/agents_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ def complete
render json: @agent.complete_option(params[:attribute])
end

def destroy_undefined
current_user.undefined_agents.destroy_all

redirect_back "All undefined Agents have been deleted."
end

protected

# Sanitize params[:return] to prevent open redirect attacks, a common security issue.
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ class ApplicationController < ActionController::Base

helper :all

rescue_from 'ActiveRecord::SubclassNotFound' do
@undefined_agent_types = current_user.undefined_agent_types

render template: 'application/undefined_agents'
end

def redirect_back(fallback_path, *args)
redirect_to :back, *args
rescue ActionController::RedirectBackError
Expand Down
4 changes: 4 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,8 @@ def highlighted?(id)

@highlighted_ranges.any? { |range| range.cover?(id) }
end

def agent_type_to_human(type)
type.gsub(/^.*::/, '').underscore.humanize.titleize
end
end
15 changes: 15 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,19 @@ def requires_no_invitation_code!
def requires_no_invitation_code?
!!@requires_no_invitation_code
end

def undefined_agent_types
agents.reorder('').group(:type).pluck(:type).select do |type|
begin
type.constantize
false
rescue NameError
true
end
end
end

def undefined_agents
agents.where(type: undefined_agent_types).select('id, schedule, type as undefined')
end
end
2 changes: 1 addition & 1 deletion app/views/agents/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<% if @agent.new_record? %>
<div class="form-group type-select">
<%= f.label :type %>
<%= f.select :type, options_for_select([['Select an Agent Type', 'Agent', {title: ''}]] + Agent.types.map {|type| [type.name.gsub(/^.*::/, '').underscore.humanize.titleize, type, {title: h(Agent.build_for_type(type.name,current_user,{}).html_description.lines.first.strip)}] }, @agent.type), {}, :class => 'form-control' %>
<%= f.select :type, options_for_select([['Select an Agent Type', 'Agent', {title: ''}]] + Agent.types.map {|type| [agent_type_to_human(type.name), type, {title: h(Agent.build_for_type(type.name,current_user,{}).html_description.lines.first.strip)}] }, @agent.type), {}, :class => 'form-control' %>
</div>
<% end %>
</div>
Expand Down
44 changes: 44 additions & 0 deletions app/views/application/undefined_agents.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="container">
<div class='row'>
<div class='col-md-12'>
<div class="page-header">
<h3>
<div class="alert alert-danger" role="alert">
Error: Agent(s) are 'missing in action'
</div>
</h3>
</div>
<blockquote>
<p>
You have one or more Agents registered in the database for which no corresponding definition is available in the source code:
</p>
<ul>
<% @undefined_agent_types.each do |type| %>
<li><%= agent_type_to_human(type) %></li>
<% end %>
</ul>
<br/>
<p>
The issue most probably occurred because of one or more of the following reasons:
</p>
<ul>
<li>If the respective Agent is distributed as a Ruby gem, it might have been removed from the <code>ADDITIONAL_GEMS</code> environment setting.</li>
<li>If the respective Agent is distributed as part of the Huginn application codebase, it might have been removed from that either on purpose (because the Agent has been deprecated or been moved to an Agent gem) or accidentally. Please check if the Agent(s) in question are available in your Huginn codebase under the path <code>app/models/agents/</code>.</li>
</ul>
<br/>
<p>
You can fix the issue by adding the Agent(s) back to the application codebase by
</p>
<ul>
<li>adding the respective Agent(s) to the the <code>ADDITIONAL_GEMS</code> environment setting. Please see <a href="https://github.com/cantino/huginn_agent" target="_blank">https://github.com/cantino/huginn_agent</a> for documentation on how to properly set it.</li>
<li>adding the respective Agent(s) code to the Huginn application codebase (in case it was deleted accidentally).</li>
<li>deleting the respective Agent(s) from the database using the button below.</li>
</ul>
<br/>
<div class="btn-group">
<%= link_to icon_tag('glyphicon-trash') + ' Delete Missing Agents', undefined_agents_path, class: "btn btn-danger", method: :DELETE, data: { confirm: 'Are you sure all missing Agents should be deleted from the database?'} %>
</div>
</blockquote>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
get :event_descriptions
post :validate
post :complete
delete :undefined, action: :destroy_undefined
end

resources :logs, :only => [:index] do
Expand Down
14 changes: 14 additions & 0 deletions spec/controllers/agents_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,18 @@ def valid_attributes(options = {})
expect(agent.reload.memory).to eq({ "test" => 42})
end
end

describe 'DELETE undefined' do
it 'removes an undefined agent from the database' do
sign_in users(:bob)
agent = agents(:bob_website_agent)
agent.update_attribute(:type, 'Agents::UndefinedAgent')
agent2 = agents(:jane_website_agent)
agent2.update_attribute(:type, 'Agents::UndefinedAgent')

expect {
delete :destroy_undefined
}.to change { Agent.count }.by(-1)
end
end
end
21 changes: 21 additions & 0 deletions spec/features/undefined_agents_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'capybara_helper'

describe "handling undefined agents" do
before do
login_as(users(:bob))
agent = agents(:bob_website_agent)
agent.update_attribute(:type, 'Agents::UndefinedAgent')
end

it 'renders the error page' do
visit agents_path
expect(page).to have_text("Error: Agent(s) are 'missing in action'")
expect(page).to have_text('Undefined Agent')
end

it 'deletes all undefined agents' do
visit agents_path
click_on('Delete Missing Agents')
expect(page).to have_text('Your Agents')
end
end
27 changes: 27 additions & 0 deletions spec/models/users_spec.rb → spec/models/user_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'rails_helper'

describe User do
let(:bob) { users(:bob) }

describe "validations" do
describe "invitation_code" do
context "when configured to use invitation codes" do
Expand Down Expand Up @@ -64,4 +66,29 @@
expect(users(:bob).deactivated_at).to be_nil
end
end

context '#undefined_agent_types' do
it 'returns an empty array when no agents are undefined' do
expect(bob.undefined_agent_types).to be_empty
end

it 'returns the undefined agent types' do
agent = agents(:bob_website_agent)
agent.update_attribute(:type, 'Agents::UndefinedAgent')
expect(bob.undefined_agent_types).to match_array(['Agents::UndefinedAgent'])
end
end

context '#undefined_agents' do
it 'returns an empty array when no agents are undefined' do
expect(bob.undefined_agents).to be_empty
end

it 'returns the undefined agent types' do
agent = agents(:bob_website_agent)
agent.update_attribute(:type, 'Agents::UndefinedAgent')
expect(bob.undefined_agents).not_to be_empty
expect(bob.undefined_agents.first).to be_a(Agent)
end
end
end

0 comments on commit e0fa7f0

Please sign in to comment.