Skip to content

Commit

Permalink
[Feature] Enable Ruby Proc for require_confirm_worker_params (#32)
Browse files Browse the repository at this point in the history
* Add disable Sidekiq CSRF
* Refactor specs
* Enable Ruby Proc
* Second confirmation alert
* Update `require_confirm_worker_names` new usages
  • Loading branch information
khoaanguyenn committed Jan 18, 2023
1 parent a6d6441 commit 2d8198a
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 153 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ SidekiqAdhocJob.configure do |config|
config.module_names = ['YourProject::Worker']
config.strategy_name = :active_job
config.load_paths = ['app/jobs/**/*.rb']

config.require_confirm_worker_names = %w[YourProject::Worker::A YourProject::Worker::B]
# List of Symbols = %i[YourProject::Worker::A YourProject::Worker::B]
# Apply to workers name ending with "A" = ->(worker_class) { worker_class.end_with?('A') }
# Ruby class that implements #call = CallableObject.new
end
SidekiqAdhocJob.init
```
Expand All @@ -35,7 +40,7 @@ Options:
- `active_job`: check for all classes that extend `ActiveJob::Base`
- `rails_application_job`: check for all classes that extend `ApplicationJob`
- `load_paths` (optional - default `[]`): takes in a list of file paths that the gem should load when initializing, in order to include the necessary classes in the app `ObjectSpace`
- `require_confirm_worker_names` (optional - default `[]`): takes in a list of fully namespaced worker class names that the web UI will request for confirmation before running the job
- `require_confirm_worker_names` (optional - default `[]`): takes in a Ruby callable object, or a Proc, or fully namespaced worker class names that require confirmation before running the job through web UI.
- `require_confirm_prompt_message` (optional - default `confirm`): takes a string that is used for challenge keyword before running jobs included in `require_confirm_worker_names`. This value must be a string, otherwise, an error with message `'require_confirm_prompt_message must be string'` will be raised

### Keyword Arguments Support (>= v2.1.0)
Expand Down
13 changes: 10 additions & 3 deletions lib/sidekiq_adhoc_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,15 @@ def module_names
Array(@module_names).map(&:to_s)
end

def require_confirm
@require_confirm ||= Array(@require_confirm_worker_names).map(&:to_s)
def require_confirm_proc
@require_confirm_proc ||= \
if @require_confirm_worker_names.respond_to?(:call)
@require_confirm_worker_names
else
shortlisted_workers = Array(@require_confirm_worker_names).map(&:to_s)

->(worker_name) { shortlisted_workers.include?(worker_name) }
end
end

def require_confirm_prompt_message=(message)
Expand All @@ -70,7 +77,7 @@ def require_confirm_prompt_message=(message)
end

def require_confirmation?(worker_name)
require_confirm.include?(worker_name)
require_confirm_proc.call(worker_name)
end

def strategy
Expand Down
7 changes: 6 additions & 1 deletion lib/sidekiq_adhoc_job/web/templates/jobs/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,13 @@
<script>
document.getElementById('adhoc-jobs-submit-form').addEventListener('submit', (event) => {
const confirmPrompt = "<%= @presented_job.confirm_prompt_message %>";
if (prompt(`Please enter "${confirmPrompt}" to confirm`) !== confirmPrompt)
const input = prompt(`Please enter "${confirmPrompt}" to confirm`);
if (input !== confirmPrompt) {
event.preventDefault();
if (input !== null) {
alert('Your confirmation input is incorrect, try again.');
}
}
})
</script>
<% end %>
40 changes: 21 additions & 19 deletions spec/sidekiq_adhoc_job/requests/jobs/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@

expect(response_body).to include('<h3>Adhoc Jobs</h3>')

expect(response_body).to include(compact_html(
<<~HTML
<tr>
<td>SidekiqAdhocJob::Test::DummyWorker</td>
<td>dummy</td>
<td>id, overwrite</td>
<td>retry_job, retries, interval, name, options</td>
<td>type</td>
<td>dryrun</td>
<td>false</td>
<td>true</td>
<td class="text-center">
<a class="btn btn-warn btn-xs" href="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_worker">
View Job
</a>
</td>
</tr>
HTML
))
expect(response_body).to include(
compact_html(
<<~HTML
<tr>
<td>SidekiqAdhocJob::Test::DummyWorker</td>
<td>dummy</td>
<td>id, overwrite</td>
<td>retry_job, retries, interval, name, options</td>
<td>type</td>
<td>dryrun</td>
<td>false</td>
<td>true</td>
<td class="text-center">
<a class="btn btn-warn btn-xs" href="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_worker">
View Job
</a>
</td>
</tr>
HTML
)
)
end

end
15 changes: 10 additions & 5 deletions spec/sidekiq_adhoc_job/requests/jobs/schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@

let(:fake_schedule_job) { double(call: true) }

it 'runs ScheduleAdhocJob service' do
expect(SidekiqAdhocJob::ScheduleAdhocJob).to receive(:new).with('sidekiq_adhoc_job_test_dummy_worker', schedule_job_params) { fake_schedule_job }
expect(fake_schedule_job).to receive(:call)
before do
disable_csrf
allow(SidekiqAdhocJob::ScheduleAdhocJob)
.to receive(:new)
.with('sidekiq_adhoc_job_test_dummy_worker', schedule_job_params)
.and_return(fake_schedule_job)
end

it 'runs ScheduleAdhocJob service' do
post '/adhoc-jobs/sidekiq_adhoc_job_test_dummy_worker/schedule', request_params

expect(last_response.status).to eq 302
expect(fake_schedule_job).to have_received(:call)
expect(last_response.status).to eq(302)
expect(last_response.headers['Location']).to eq "#{last_request.base_url}/adhoc-jobs"
end

end
181 changes: 96 additions & 85 deletions spec/sidekiq_adhoc_job/requests/jobs/show_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,62 @@

response_body = compact_html(last_response.body)

expect(response_body).to include(compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_worker/schedule">
HTML
))

expect(response_body).to include(compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="id">*id:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="id" id="id" required/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="overwrite">*overwrite:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="overwrite" id="overwrite" required/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="retry_job">retry_job:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="retry_job" id="retry_job"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="retries">retries:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="retries" id="retries"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="interval">interval:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="interval" id="interval"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="name">name:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="name" id="name"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="options">options:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="options" id="options"/>
</div>
</div>
HTML
))
expect(response_body).to include(
compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_worker/schedule" id="adhoc-jobs-submit-form">
HTML
)
)

expect(response_body).to include(
compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="id">*id:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="id" id="id" required/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="overwrite">*overwrite:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="overwrite" id="overwrite" required/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="retry_job">retry_job:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="retry_job" id="retry_job"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="retries">retries:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="retries" id="retries"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="interval">interval:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="interval" id="interval"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="name">name:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="name" id="name"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="options">options:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="options" id="options"/>
</div>
</div>
HTML
)
)
end
end

Expand All @@ -77,33 +81,39 @@

response_body = compact_html(last_response.body)

expect(response_body).to include(compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_rest_args_worker/schedule">
HTML
))

expect(response_body).to include(compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="id">*id:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="id" id="id" required/>
</div>
</div>
HTML
))

expect(response_body).to include(compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="rest_args">Rest arguments (please provide a json string representing the arguments):</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="rest_args" id="rest_args"/>
</div>
</div>
HTML
))
expect(response_body).to include(
compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_rest_args_worker/schedule" id="adhoc-jobs-submit-form">
HTML
)
)

expect(response_body).to include(
compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="id">*id:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="id" id="id" required/>
</div>
</div>
HTML
)
)

expect(response_body).to include(
compact_html(
<<~HTML
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="rest_args">Rest arguments (please provide a json string representing the arguments):</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="rest_args" id="rest_args"/>
</div>
</div>
HTML
)
)
end
end

Expand All @@ -115,11 +125,13 @@

response_body = compact_html(last_response.body)

expect(response_body).to include(compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_no_arg_worker/schedule">
HTML
))
expect(response_body).to include(
compact_html(
<<~HTML
<form method="POST" action="/adhoc-jobs/sidekiq_adhoc_job_test_dummy_no_arg_worker/schedule" id="adhoc-jobs-submit-form">
HTML
)
)

expect(response_body).to include('<p>No job arguments</p>')
end
Expand All @@ -133,5 +145,4 @@
expect(last_response.headers['Location']).to eq "#{last_request.base_url}/adhoc-jobs"
end
end

end

0 comments on commit 2d8198a

Please sign in to comment.