Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Require authentication for facility CSV downloads and log requests #697

Merged
merged 5 commits into from Jul 25, 2019

Conversation

jwalgran
Copy link
Contributor

@jwalgran jwalgran commented Jul 19, 2019

Overview

Require a login to download a facility CSV from the map page and log all CSV download requests to the database.

Connects #668

Demo

Screen Shot 2019-07-23 at 7 10 43 PM

Notes

We have kept the method, model, and model attribute names relatively generic so we have the option of logging other downloads using the same code while avoiding the need to change names.

Testing Instructions

This assumes the fixture data has been loaded and processed with ./scripts/resetdb

  • Log in as c2@example.com
  • Search for shoes
  • Click "Download CSV" and verify that is behaves as before.
  • Run ./scripts/manage dbshell
  • Run select * from api_downloadlog and verify that the path and record_count columns match.
  • Stop ./scripts/server. Click "Download CSV" and verify that error toast is shown. Start ./scripts/server
  • Log out
  • Search for "shoes" again and click "Download CSV." Verify that the "Log In To Download" dialog is shown.
    • Verify each button behavior (Cancel, Register, and Log In).

Checklist

  • fixup! commits have been squashed
  • CI passes after rebase
  • CHANGELOG.md updated with summary of features or fixes, following Keep a Changelog guidelines

@jwalgran jwalgran changed the title WIP Log CSV downloads Log CSV downloads Jul 24, 2019
@jwalgran jwalgran marked this pull request as ready for review July 24, 2019 02:23
@jwalgran jwalgran requested a review from kellyi July 24, 2019 02:23
@kellyi
Copy link
Contributor

kellyi commented Jul 24, 2019

Setting this up to take a look!

createAction('COMPLETE_LOG_DOWNLOAD');

export function logDownload(rows, callback) {
return (dispatch) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the facilities data lives in the app's Redux store state, conceivably we could change this function to actually perform the download directly rather than having to pass rows and callback in as arguments. If we handled it this way, we could get the facilities data here via getState and then directly import the downloadFacilitiesCSV utility function to execute it in the promise chain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We discussed this in person and it does make sense given the future refactoring of the search result handling to have this action fetch the results from the state rather than having the caller pass them in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in fixup c53103b

.then(() => {
callback(rows);
return dispatch(completeLogDownload());
})
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick but consider

.then(() => callback(rows))
.then(() => dispatch(completeLogDownload())
.catch....

Or whatever similar construction would work with a potential revision to use getState.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in fixup c53103b

help_text='The User account that made the request'
)
path = models.CharField(
max_length=2083,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is 2083 a maximum value for paths?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a well researched StackOverflow answer that contributed to this choice of maximum value
https://stackoverflow.com/a/417184

In summary, URLs larger than this bump into some limits in browsers and search crawling infrastructure so it is a reasonable maximum value.

Copy link
Contributor

@kellyi kellyi left a comment

Choose a reason for hiding this comment

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

👍 This worked well! I saw the dialog prompting me to login when I tried to download the CSV without logging in, and I see the downloadlog record created after logging in & downloading the CSV:

openapparelregistry=# SELECT * FROM api_downloadlog;
 id |    path     | record_count |          created_at           |          updated_at           | user_id 
----+-------------+--------------+-------------------------------+-------------------------------+---------
  1 | /facilities |          500 | 2019-07-24 18:37:56.752855+00 | 2019-07-24 18:37:56.752905+00 |       1
(1 row)

I made a comment about a small refactor that I think might clean up the download code: essentially, since the CSV rows originate from the Redux store data, we can do all of the CSV downloading work in the new logDownload action by accessing the store with getState and then calling the proper utility functions. On one hand it'd help make the code a little easier to reason about; on the other I don't know how likely it is that we'll add more new features around this part of the app -- so it may not be beneficial.

Feel free either to do that or not, depending on how soon you'd like to deploy the new release!

@kellyi
Copy link
Contributor

kellyi commented Jul 24, 2019

I tested this, btw without reconciling the merge conflict, which is just that one of the reducers on develop now has a different name than it does on this branch.

@jwalgran
Copy link
Contributor Author

Rebased to resolve the merge conflict.

@kellyi kellyi assigned jwalgran and unassigned kellyi Jul 25, 2019
Records will be written to this table when an authenticated user downloads a CSV
from the web client.
CSVs are compiled on the client side, so we did not have an existing endpoint
to which we could attach the new logging code.
@jwalgran jwalgran changed the title Log CSV downloads Require authentication for facility CSV downloads and log requests Jul 25, 2019
Requiring authentication on the log endpoint effectively restricts downloads to
registered users, which is what we want.

Now that we are requiring users to log in before downloading a CSV we guide them
to login/registration if they attempt to download without a session.
@jwalgran
Copy link
Contributor Author

Thanks for the great architecture suggestions. The implementation is better for it.

@jwalgran jwalgran merged commit 241263b into develop Jul 25, 2019
@jwalgran jwalgran deleted the jcw/log-csv-downloads branch July 25, 2019 17:26
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants