Merge pull request #1695 from kreuzwerker/missing-agent-warning

Rescue from AR:SubclassNotFound and allow to delete agents
This commit is contained in:
Dominik Sander 2016-09-21 21:04:46 +02:00 committed by GitHub
commit e0fa7f00d0
10 changed files with 139 additions and 1 deletions

View file

@ -208,6 +208,12 @@ class AgentsController < ApplicationController
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.

View file

@ -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

View file

@ -113,4 +113,8 @@ module ApplicationHelper
@highlighted_ranges.any? { |range| range.cover?(id) }
end
def agent_type_to_human(type)
type.gsub(/^.*::/, '').underscore.humanize.titleize
end
end

View file

@ -75,4 +75,19 @@ class User < ActiveRecord::Base
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

View file

@ -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>

View file

@ -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>

View file

@ -15,6 +15,7 @@ Huginn::Application.routes.draw do
get :event_descriptions
post :validate
post :complete
delete :undefined, action: :destroy_undefined
end
resources :logs, :only => [:index] do

View file

@ -434,4 +434,18 @@ describe AgentsController do
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

View file

@ -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

View file

@ -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
@ -64,4 +66,29 @@ describe User do
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