Problem/Motivation
It's possible to create a user with no email address.
Enabling contact.module, and then trying to send a message to that user fails. (With not enough explanation to the sender about what went wrong)
To replicate
* Given that contact module is enabled
* And I am logged in as admin
* When I "Add user" at /admin/people/create
* - Observe that "E-mail address" is not required.
* Given that I create a user with NO email.
* And I tick "Personal contact form"
* When I visit the user account page
* And I press "Contact"
* And I use the form to send a message
* Then I see an error message "Unable to send e-mail. Contact the site administrator if the problem persists."
* And I see an error in the logs "Error sending e-mail (from me@example.com to with reply-to me@example.com)."
Optional email addresses is explained in AccountFormController::form()
// The mail field is NOT required if account originally had no mail set // and the user performing the edit has 'administer users' permission. // This allows users without e-mail address to be edited and deleted.
So this appears to be by design. HOWEVER, maybe it is unintentional that email is always optional for new accounts. If so maybe that is a separate issue.
Proposed resolution
Disable access to the personal contact form for users with no valid email.
User interface changes
contact.module contact form should be unavailable for such users.
It should not be possible for such user accounts to enable "Personal contact form" on their account.
Beta phase evaluation
Issue category | Bug, as this permits a user to fill out a form that can never be successfully transmitted. |
---|---|
Issue priority | Normal, as this does not break primary functionality but results in undesirable behaviour in only specific cases |
Prioritized changes | This is a prioritized issue as it will improve usability and result in a more logical UX. |
Disruption | No disruption expected, as the changes are limited to the "contact" module and should not interract in any significant way with other code. |
Comment | File | Size | Author |
---|---|---|---|
#26 | contact_module_allows-2225597-26.patch | 4.56 KB | tibbsa |
Comments
Comment #1
dman CreditAttribution: dman commentedComment #2
dman CreditAttribution: dman commentedComment #3
dman CreditAttribution: dman commentedComment #4
akozma CreditAttribution: akozma commentedComment #5
akozma CreditAttribution: akozma commentedAn ajax event is added to the mail form element. The personal contact form settings are disabled/enabled depending on the mail field.
I used #ajax to change the disabled element message too in order to give a feedback for the current user.
Comment #6
larowlanI don't think ajax is the answer here. I think a 404 for said users at user/{uid}/contact make more sense
Comment #7
larowlanIe we need both
Comment #8
larowlansomething like this
Comment #9
larowlanand some tests
Comment #10
dman CreditAttribution: dman commentedOo tests! Yay.
The test seems weak however. If I run the test-only, *without* the code patch, the test still runs green. Which indicates the test proves nothing new.
Why would that be? The code seems sound enough... I need to check manually.
In Manual testing I'm still seeing the tab on the user page (and still able to use the contact form, as admin at least).
That tab should just not be there.
... Admin seems to get a free pass as usual, but in this case, even admin probably should not.
// User administrators should always have access to personal contact forms.
Maybe the no-email logic needs to be above this.
Manual testing, as non admin, an authenticated user with 'View user profiles' and 'Use users' personal contact forms' permissions on ...
I do see the contact tab it for an account with a valid mail, normal.
But I also see it for an account with no mail. I am able to see the tab, get to the page, and able to trigger the error still.
Maybe it's just me, I need to reset my test system from scratch again maybe. Something seems wrong.
Comment #11
larowlanNa you're right, need to go before the admin bit. Also, tab access might be different, will have to take a look.
Comment #12
andyposttabs (local tasks) are differerent plugins, so probably re-use menu-links access checking
Comment #13
jhedstromPatch no longer applies. I'd say an error that can be produced through the UI qualifies as a bug rather than a task.
Comment #14
tibbsa CreditAttribution: tibbsa commentedI tried to work on a bit of a reroll of this, but a few things came up that persuaded me to stop and see if there was a better way to proceed. This will give a couple of hints if someone else wants to take a stab at this.
1. If the ajax callback is to be kept, note that valid_email_address() is on its way to the graveyard and we should be using the email validation service instead:
See: #2343043: valid_email_address() should use egulias/EmailValidator and become deprecated
2. The return values for access() have changed. The following works, which I would insert between the 'self-contact' test and the administrator override:
Now to the part that my relatively novice knowledge of the routing system, etc. has not prepared me for.
I tend to agree that, if we are going to throw an error on visiting user/{uid}/contact for someone without an email address defined, it seems more logical to return 404 (not found) rather than 403 (access denied). The latter is a more accurate description of the error.
Ergo, it seems to me a little bit of a kludge to implement this at the 'access' level. ContactController::contactSitePage() throws a NotFoundHttpException() if a user tries to visit a non-existent default site form, and we can do the same in ContactController::contactPersonalPage(). That works as expected.
However, that doesn't hide the Contact tab on the user profile. This was done in prior patches by denying access to the tab. But is there a better way to disable this without hacking a check into the access control layer?
The problem with doing it in the access check is that this fires before the controller callback, resulting in a 403 Forbidden error being returned to the client when visiting user/{uid}/contact, rather than a "not found" error (since ContactController::contactPersonalPage() never executes to throw the more meaningful 404 error). Throwing that error in the access() callback is not an option because that presumably breaks the user profile page, too.
Comment #15
dman CreditAttribution: dman commentedGood analysis tibbsa . Thanks for thinking about the message it sends.
Comment #16
tibbsa CreditAttribution: tibbsa commented(Working on this...)
Comment #17
tibbsa CreditAttribution: tibbsa commentedAdded beta evaluation.
Comment #18
tibbsa CreditAttribution: tibbsa commentedTwo patches are attached.
The first patch fixes the problem described in the issue description:
This does not yet deal with the account profile form or include the Ajax code provided above, as this has to be completely re-factored by the looks of it, and quite simply, I've not figured out even how to add additional validation to the form never mind Ajax validation.
The tests check for both of these conditions, and I expect two failures to be reported.
Before moving on to 'enhancements' with respect to the account edit forms, are we satisfied that this at least prevents the identified bug from manifesting?
Comment #20
tibbsa CreditAttribution: tibbsa commentedComment #21
jhedstrom@tibbsa, can you roll a patch that includes the tests and the fix in a single file, to illustrate that the fix truly addresses the failing tests?
Comment #22
tibbsa CreditAttribution: tibbsa commentedCombined patch + tests.
Comment #23
jhedstromI think it is OK that this doesn't take the ajax approach discussed above. Simply removing the tab and setting a 404 for the page makes sense to me.
Comment #24
tstoecklerCan maybe be fixed pre-commit so not setting to "needs work":
I think it would be more consistent to say "Hides", instead of "Hide". Also, this breaks before 80 chars.
The opening brace should be on the same line as the function definition
Comment #26
tibbsa CreditAttribution: tibbsa commentedFixed the minor issues identified in #24, and re-rolled.
Comment #27
jhedstromI think this is back to RTBC.
Comment #28
alexpottCommitted f067cd5 and pushed to 8.0.x. Thanks!
Thank you for adding the beta evaluation to the issue summary.