Skip to content

Commit

Permalink
Fixes username and password auth for downloader script
Browse files Browse the repository at this point in the history
Fixes #570
  • Loading branch information
atruskie committed Apr 7, 2022
1 parent c49ee5c commit 964ce72
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 8 deletions.
8 changes: 5 additions & 3 deletions app/modules/include_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ def render_error(status_symbol, detail_message, error, method_name, options = {}
error,
env: request.env,
data: {
method_name: method_name,
json_response: json_response
method_name:,
json_response:
}
)
end
Expand Down Expand Up @@ -346,7 +346,9 @@ def validate_contains_post_params
# json or form encoded with text/plain content type will have the form {}
return unless request.POST.values.all?(&:blank?)

if request.body.string.blank?
# sometimes in prod body can be a PhusionPassenger::Utils::TeeInput which does not have a `string` method
body = request.body
if body.respond_to?(:string) && body.string.blank?
message = 'Request body was empty'
status = :bad_request
# include link to 'new' endpoint if body was empty
Expand Down
29 changes: 24 additions & 5 deletions app/views/audio_recordings/downloader/download_audio_files_ps1.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ $ ./download_audio_files.ps1
param(
# Where to download the recordings. Defaults to the present working directory if not specified.
$target = $null,
# The username to use to login to the workbench. This value's default value is templated when the script is generated.
$user_name = $null,
# The auth token to use to login to the workbench. You only need to supply an auth token if you want to log in without a password.
# The auth token to use to login to the workbench. You only need to supply an auth token if you want to log in without a password.
$auth_token = $null,
# The username to use to login to the workbench. This value's default value is templated when the script is generated. This is not needed if you use an auth_token.
$user_name = $null,
# The poassword to use to login to the workbench. This is not needed if you use an auth_token.
$password = $null,

# The filter to use to select audio recordings to download. This value's default value is templated when the script is generated.
# See https://github.com/QutEcoacoustics/baw-server/wiki/API:-Filtering for details on valid filters. This argument
# should be a valid JSON encoded string.
Expand Down Expand Up @@ -87,8 +90,24 @@ Write-Information "Workbench URL: $workbench_url"
$headers = @{}

if ($null -eq $auth_token) {
$credentials = Get-Credential -Message "Provide credentials for logging into $workbench_url" -UserName $user_name
$json_credentials = $credentials.GetNetworkCredential() | ForEach-Object{ @{"email"=$_.UserName;"password"=$_.Password}} | ConvertTo-Json
if ($user_name -and $password) {
$User = $user_name
$PWord = ConvertTo-SecureString -String $password -AsPlainText -Force
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
}
else {
$credentials = Get-Credential -Message "Provide credentials for logging into $workbench_url" -UserName $user_name
}


$json_credentials = $credentials.GetNetworkCredential() | ForEach-Object{
if ($_.UserName -like '*@*') {
@{"email"=$_.UserName;"password"=$_.Password}
}
else {
@{"login"=$_.UserName;"password"=$_.Password}
}
}

Write-Information "Logging in to workbench $workbench"

Expand Down
19 changes: 19 additions & 0 deletions spec/requests/application_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@
expect(response.headers).not_to have_key('X-Error-Message')
end

it 'can handle malformed post requests' do
# a json value encoded in a string (malformed)
body = "{\r\n \"password\": \"password\",\r\n \"email\": \"SladeAA\"\r\n}"
post '/security', params: body,
headers: {
'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
'Accept' => 'application/json',
'CONTENT_LENGTH' => 56
}

expect(response).to have_http_status(:unsupported_media_type)
expect(response.headers).not_to have_key('X-Error-Message')
expect(response.content_type).to include('application/json')
parsed_response = JSON.parse(response.body)
expect(parsed_response['meta']['error']['details']).to eq(
'Failed to parse the request body. Ensure that it is formed correctly and matches the content-type (application/x-www-form-urlencoded)'
)
end

describe 'filtering tests' do
create_entire_hierarchy

Expand Down
41 changes: 41 additions & 0 deletions spec/requests/audio_recordings/downloader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,47 @@ def prepare_audio_file(audio_recording)
expect(files.size).to eq(11)
expect(files.map(&:to_s)).to all(end_with('.mp3'))
end

it 'downloads the files (with username and password)', web_server_timeout: 30 do
logger.measure_info('downloading script') do
out_and_err, status = Open3.capture2e(
'curl -JO localhost:3000/audio_recordings/downloader?items=2',
chdir: BawApp.tmp_dir
)
logger.info(out_and_err, status:)
end

script.chmod(0o764)

script_output = ''

logger.measure_info('running download script') do
logger.tagged('download script output') do
# we need a promise here to force the process wait onto another thread
# without it, our async web server (from expose_app_as_web_server above) crashes with
# Errno::EBADF:
# Bad file descriptor - epoll_ctl(process_wait)
Concurrent::Promises.future {
script_output, status = Open3.capture2e(
'pwsh download_audio_files.ps1 -target downloader_test -user_name admin -password password',
chdir: BawApp.tmp_dir,
stdin_data: "password\n"
)
logger.info(script_output, status:)
}.run.wait!
end
end

expect(script_output).to match(
"Downloading recordings\nGetting page 1\nGot page 1 of 6, 2 recordings in this page.\nDownloading recording"
)
expect(script_output).to match('Got page 6 of 6, 1 recordings in this page.')
expect(script_output).to match(%r{Downloaded recording \d+ to downloader_test/\d+_sitename\d+/.*.mp3})

files = (BawApp.tmp_dir / 'downloader_test').glob('**/*.mp3')
expect(files.size).to eq(11)
expect(files.map(&:to_s)).to all(end_with('.mp3'))
end
end
end
end

0 comments on commit 964ce72

Please sign in to comment.