Conversation
|
supersedes: #4399 |
|
So great, @everreau! I've suggested some changes in line with ORCID's brand guidelines This is only for journals at the moment, is that correct? Could the co-author use the ORCID login option to connect their iD to their account rather than connecting the iD in their profile? What happens if the co-author is a frozen author without an account, or if the account isn't active? |
|
@alainna. All of the login features also work for preprints. I don't see any reference at all to orcids in the preprint author interface. I think we (cdl) would send whatever orcid was in the author's account to crossref even though it's not visible and it appears in the preprint front end. The profile and the account are the same as far as I know. The interface on main is a bit different than what we're currently running. Maybe we should setup a time so you can take a look at what I have. I hadn't really thought about what would happen if a user connects their orcid after the frozen authors were already made. I'll take a look at that. |
On the |
|
@joemull can you do the first technical review on this and then pass it to me please? |
|
Just an update: I should be able to get to this |
|
Some suggestions for this dev: eScholarship#46 |
joemull
left a comment
There was a problem hiding this comment.
This is hugely appreciated--thank you for putting it in.
I'm having trouble testing it out (an issue with OLH's ORCID sandbox that will take a few days to resolve), but I've gone ahead and given you some comments from reading the code. Hope they're clear but please do ping me if anything does not make sense.
| response = self.client.get(reverse("core_edit_profile")) | ||
| self.assertContains(response, "ORCID iD could not be validated.") | ||
| self.assertContains(response, "Connect your ORCID") | ||
| self.assertContains(response, "https://sandbox.orcid.org/0000-0000-0000-0000") |
There was a problem hiding this comment.
Does this test (or any of the ones below) rely on a network connection? We'll need to put mocks into any test that relies on a network connection.
There was a problem hiding this comment.
None of the tests rely on network connection. It's setting the orcid url purely for display purposes. I noticed that ruff is failing now but it was passing at some point and the tests ran successfully.
There was a problem hiding this comment.
This is using a network connection, because is_orcid_token_valid calls the ORCID API using requests. I turned my internet off and got the error below. So I think we'll just want to mock it where the Janeway logic that is being tested ends, and the ORCID API code begins, in this and subsequent tests that use the API.
Traceback (most recent call last):
File "/home/joemull/git/janepr/src/core/tests/test_app.py", line 563, in setUp
self.article_one = helpers.create_article(
File "/home/joemull/git/janepr/src/utils/testing/helpers.py", line 300, in create_article
author.snapshot_as_author(article)
File "/home/joemull/git/janepr/src/core/models.py", line 893, in snapshot_as_author
frozen_dict["is_frozen_orcid_valid"] = self.is_orcid_token_valid()
File "/home/joemull/git/janepr/src/core/models.py", line 963, in is_orcid_token_valid
return is_token_valid(self.orcid, self.orcid_token)
File "/home/joemull/git/janepr/src/utils/orcid.py", line 76, in is_token_valid
r = api_client._get_public_info(
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/orcid/orcid.py", line 410, in _get_public_info
return requests.get(request_url, headers=headers,
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/api.py", line 73, in get
return request("get", url, params=params, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/adapters.py", line 700, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='pub.orcid.org', port=443): Max retries exceeded with url: /v2.0/0004-5678-9012-345X/record (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7c9bc79e8190>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))
|
Suggested email text for the situation in which an author account exists, but may or may not be active. The below is written with the assumption that:
[if account is not active]
[if account is active]
|
…n author, refactor templates
…e more fault tolerant
…dated orcid already exists
|
@joemull I think this may be ready for review. I think the login logic in core.views is getting quite confusing. I was trying to rewrite so we can favor accounts that have authenticated orcids and prevent duplicate authenticated orcids. Maybe it would be easier to just make the orcid field unique at this point? I'm not sure if there is anything else in the queue that is needed before that. |
|
OK @everreau I will try to get to it first thing next week (I'm out the rest of this week). Yes every time I try to read through that logic I get confused. I agree it is high time to make the ORCID unique. I think the hard thing there is that there are duplicates currently. So the data migration would have to enforce the unique constraint while also recording the duplicates somehow and making them visible to someone (press manager, editor)? to resolve. |
|
@joemull so, my thought on dealing with the duplicates would be to create a migration that looks for the best account to retain the orcid by a set of criteria (eg is active, matches info held in orcid, last login), remove it from the others and create a log entry that says it was removed. Then we could add some logic that would allow a user to reclaim the orcid to their own account by authenticating with orcid and we could add a view that lets managers see everything that has the given log entry and resolve manually? |
joemull
left a comment
There was a problem hiding this comment.
This is getting really close to being ready, and it's great that you were able to loop in the frozen author piece. I took a careful read through the logic and tested it out, and it's mostly working great for me. I just have a few requests around tests, the admin view, and maintainability, and one suggestion for usability--in the verification request, taking the user straight to the verification step rather than to their profile.
| response = self.client.get(reverse("core_edit_profile")) | ||
| self.assertContains(response, "ORCID iD could not be validated.") | ||
| self.assertContains(response, "Connect your ORCID") | ||
| self.assertContains(response, "https://sandbox.orcid.org/0000-0000-0000-0000") |
There was a problem hiding this comment.
This is using a network connection, because is_orcid_token_valid calls the ORCID API using requests. I turned my internet off and got the error below. So I think we'll just want to mock it where the Janeway logic that is being tested ends, and the ORCID API code begins, in this and subsequent tests that use the API.
Traceback (most recent call last):
File "/home/joemull/git/janepr/src/core/tests/test_app.py", line 563, in setUp
self.article_one = helpers.create_article(
File "/home/joemull/git/janepr/src/utils/testing/helpers.py", line 300, in create_article
author.snapshot_as_author(article)
File "/home/joemull/git/janepr/src/core/models.py", line 893, in snapshot_as_author
frozen_dict["is_frozen_orcid_valid"] = self.is_orcid_token_valid()
File "/home/joemull/git/janepr/src/core/models.py", line 963, in is_orcid_token_valid
return is_token_valid(self.orcid, self.orcid_token)
File "/home/joemull/git/janepr/src/utils/orcid.py", line 76, in is_token_valid
r = api_client._get_public_info(
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/orcid/orcid.py", line 410, in _get_public_info
return requests.get(request_url, headers=headers,
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/api.py", line 73, in get
return request("get", url, params=params, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
File "/home/joemull/git/janepr/.venv/lib/python3.10/site-packages/requests/adapters.py", line 700, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='pub.orcid.org', port=443): Max retries exceeded with url: /v2.0/0004-5678-9012-345X/record (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7c9bc79e8190>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))
| ) | ||
| orcid_token = models.CharField(max_length=40, blank=True, default="") | ||
| orcid_token_expiration = models.DateTimeField(null=True, blank=True) | ||
| date_orcid_requested = models.DateTimeField(blank=True, null=True) |
There was a problem hiding this comment.
The admin view for the account is a bit unique in that we have to manually add the fields we want to see. I think it would be helpful to see these new ones in the admin when troubleshooting login issues for users, so could we add them in the list in AccountAdmin.fieldsets?
| messages.WARNING, | ||
| _("You must be logged in to connect an ORCID iD to your account."), | ||
| ) | ||
| return redirect(logic.reverse_with_next("core_login", next_url)) |
There was a problem hiding this comment.
OK, with my proposed change to the email template, this might catch a fair number of users. So if you like that change, let's make sure users come back here after they've done the non-ORCID login. Something like this:
next_url = request.get_full_path()
redirect(logic.reverse_with_next("core_login", next_url))| self.assertIn( | ||
| f"/register/step/orcid/", | ||
| response.redirect_chain[0][0], | ||
| ) |
There was a problem hiding this comment.
If I'm reading this right, the redirect to registration would happen here even if the account was active, because neither the ORCID nor email matches. Should we add some of those in here so it's clear the test is just testing active / inactive status?
| self.assertIn( | ||
| f"/register/step/orcid/", | ||
| response.redirect_chain[0][0], | ||
| ) |
There was a problem hiding this comment.
I'm not sure what this test is testing. Is it about duplicate ORCIDs, or the account being inactive? I think it basically does what I was asking for, for the previous test, but it also has a bit in the name about duplicates, so I'm not sure.
| subject = "subject_orcid_request" | ||
| else: | ||
| template = "orcid_activate_request" | ||
| subject = "subject_orcid_activate_request" |
There was a problem hiding this comment.
I think we just want one of these now, since there is just one template, right?
| "user": user, | ||
| "user_profile_url": request.site_type.site_url( | ||
| reverse("core_edit_profile"), | ||
| ), |
There was a problem hiding this comment.
Have you considered making the link straight to the verification step? I think this might be clearer for users who do not remember what the profile page looks like. If they are taken to the profile page, they have to scroll down to the social media and accounts section and notice the button to connect their ORCID, but if they are taken straight to the redirect cycle, they'll be prompted at each step what to do.
We have a helper function in this file that might be useful:
reverse_with_query("core_edit_profile", { "action": "add_profile_orcid" })| return username.lower() | ||
|
|
||
| def get_orcid_url(self): | ||
| return f"{settings.ORCID_URL.replace('oauth/authorize', '')}{self.orcid}" |
There was a problem hiding this comment.
I wonder what are the benefits and drawbacks of this versus the logic in orcid_uri for the frozen author (and now the preprint author)? I'm thinking of a few things:
- The ORCID IDs in Janeway databases have sometimes been input as URLs (obviously something to fix when we make the field unique), so
get_orcid_urlwould potentially result in repeating the host name and domain parts. - It might be useful in some contexts to surface the
sandbox.orcid.orgdomain, but this is not accounted for byorcid_uribecause it hard-codes the domain.
Maybe it's time to combine the logic and have one method for Account, FrozenAuthor, and PreprintAuthor?
That does sound like a good approach to me. I think we'd open another can of worms by putting it in this PR, but I added your comment on the thread for #4751, where a few people commented on how to go about de-duping. |
Addresses: #2610
When orcid is enabled: