Closed (outdated)
Project:
Drupal core
Version:
7.x-dev
Component:
openid.module
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
24 Jan 2009 at 15:42 UTC
Updated:
20 Oct 2022 at 18:33 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
robloachJust ran into this and it's persistent in HEAD.
Comment #2
robloachThere might be a better way around this....
Comment #3
frega commentedfunctionality test, and coder review'ed one line patch :)
Comment #4
webchickHm, ick. :\ I really don't want to put in conditionals for optional core modules in menu.inc. Plus, if OpenID has this problem, others such as LDAP integration module probably do too, for example.
Let's ask chx/pwolanin if they can come up with something clever to work around this.
Comment #5
chx commentedSure they can.
Comment #6
chx commentedIf someone wants to write a test: implement test module with a single login_paths hook with filter/tips ('cos that has an access callback TRUE), drupalPost (admin / maintenancepage ) , logout, check the page you just defined it's accessible, check another page say 'node' to see it's naccessible, done!
Comment #7
dries commentedMmm, this feels a little cumbersome. Need to ponder about it a bit.
Comment #8
moshe weitzman commentedI can't think of a better solution.
Comment #9
webchickWe're still missing tests, regardless of the final solution that gets accepted.
Comment #10
webchickTagging.
Comment #11
wasare commentedMy site have the same problem on version 6.12.
Comment #12
robloachStill needs tests in 7.
We can't add another hook in Drupal 6, so this would have to be something like #2 for 6.
Comment #13
robloach#5: hook_login_paths.patch queued for re-testing.
Comment #14
robloachThis should be critical as it means people who depend on logging into their website via OpenID can't log into their site if it's in maintenance.
Comment #16
gábor hojtsyHere is a reroll of the patch, so it applies. Looking into writing tests. Agreed adding hooks in Drupal 6 does not sound like a good idea.
Comment #17
gábor hojtsyOk, looking at the existing test case, I'm not sure we can get better coverage by adding more. Since the patch moves the existing user and user/login paths to the hook, testing that this hook works will already be required for existing tests to pass. This is what we have:
Now we could add another module with another path and check for that other path, but we already check for two paths which are now defined via the hook in the user module. So I think we cannot get better test coverage on this by adding a custom module.
Comment #18
robloachWhat are your thoughts on testing the hook through menu_test.module?
Comment #20
gábor hojtsy@Rob Loach: that path has access control which will 403 it for anonymous users. Therefore @chx's suggestion to look at the filter/tips path instead which is access callback TRUE. Or you can just create one such path in menu_test.module to make the tests more robust.
Comment #21
gábor hojtsyUpdated patch including my suggestions.
Comment #23
moshe weitzman commentedI reviewed the code and it looks good. I will rtbc once bot is happy.
Comment #24
rfayHere's a version that I think will pass the testbot. There was one small error in hook_menu(), and I drupalLogout() didn't seem to make sense.
I have to admit to changing drupalLogout(), but I think the new version is actually more correct, as an actual user would hit /user/logout and then hit /user.
Now, given that, could I piggyback #733784: Friendly response to logged-in user landing on user/login or user/register into this one? If that's acceptable it could be rolled into here pretty easily. Instead of using a variable there, it would just change its behavior based on hook_login_paths().
Alternately, perhaps that one could follow this one in.
Comment #25
robloachGreat job, Randy.
Comment #26
chx commentedI think that piggybacking is a good idea -- but needs to be done before commit because that needs a hook which returns login path => redirect (i dont want to hardwire 'user' redirect path in) and also an alter would be just nice.
Comment #27
rfayPer #26, this patch extends hook_login_paths() so that it can be used in more circumstances.
1. It changes the use of the hook so it returns an associative array.
2. Uses the array to handle the case where a logged-in user accesses user/login (and other paths) with a friendly response instead of a 403.
3. Adds handling for the case where an anon user hits a protected URL and sends them to /user.
4. Adds tests for these cases.
The issues around handling these URLs with more kindness to our users is discussed in #733784: Friendly response to logged-in user landing on user/login or user/register, especially #1.
The difference between this patch and #24 is also attached.
Comment #28
chx commentedThis implements the hook as described in #26. #27 not just went over the board with the hook but misses the alter. I have created a utility function which has the alter too. I have totally removed the "anonymous user should be presented with 'user' instead of 403" that's absolutely unwanted. It's entirely possible that you want to communicate some information (premium content!) about why a page is denied. You are free to make your 403 page a redirect but adding this to core is not what we want -- a separate issue if you want but I doubt it'll get in.
Comment #29
rfayI don't feel like I have much standing to comment on this issue, as I'm just trying to get in the friendly handling of auth users innocently landing on user/login and friends So I'm probably fine with any result that preserves the original issue and (hopefully) lands some friendliness to poor naive users. In general this one would work.
#28 makes the fundamental assumption that the paths which should be handled in a friendly way for logged in users are exactly the same as the paths which should be allowed to anon users during maintenance mode. I don't think this is necessarily the case. I really don't like the path openid/authenticate returning a redirect path of 'user'. Sure, it would never happen, but it's misleading and probably inappropriate. And that's the basic problem with consolidating the two different ideas together (friendly handling for logged-in users + allowed paths for anon users when in maintenance mode). Very high WTF factor.
I'm not convinced that the friendly handling of auth users shouldn't just be done with an array of paths from a Drupal variable unless we can increase the expressiveness of hook_login_paths() (and it's up to those of you who have invested in this issue whether that should happen).
I like the drupal_alter() for login_paths, and I imagine chx expected that I'd put that in, but I missed it.
We have #24 as RTBC if we just don't want to go down this route.
I ran the tests on this and it fails for some fairly trivial reasons that are easily fixed, and this approach can work with just a little fixup if it's the way we want to go.
I've attached a diff of #27 to #28 if it's useful.
Needs a t()
Comments not relevant to this version.
The WTF factor on this one is too high. Perhaps 'openid/authenticate' => TRUE? This is the whole problem with consolidating two different semantics into one simple data structure.
This one also reverted the change to drupalLogout() in drupal_web_test_case.php (logging out, then hitting /user, instead of just hitting /logout?destination=user) which improved the test in #24. I think that will have to go back in.
142 critical left. Go review some!
Comment #31
chx commentedYes drupal_set_message needs a t that's why a tests failed. Anyways, check the API as I wrote it , you can simply specify redirection to the same path to not redirect. I am fine changing it to TRUE if you want -- it's a good idea.
Comment #32
rfayHere's another roll based on chx's comments and patch.
I had to drop 'user/register' out of the paths, because it's something that should not be allowed during maintenance mode. That's where the conflict in semantics comes in.
Other than that, I think it's basically the way @chx sees it, and it does get us a friendly response to a user landing on user/login, which is the most significant case.
Comment #34
rfayOoops. Left the test in for user/register even after the code was gone.
Comment #35
chx commentedI did some work on this and i must realize that there are paths like user/register which are not accessible during maintenance but still require friendly redirect. Oh well! #27 it is but a) add alter b) remove the force-redirect to user on 403.
Comment #36
rfayOK, here's #27 rerolled with chx's alter (and the anon-user redirect removed).
Comment #37
chx commentedSo to sum up, we have two kinds of paths
These paths often have two of these. Any page that has a login form on it, like user/login or any other site-specific login form is both. So we thought it's best to solve the two together.
Comment #38
rfayThe bugfix to drupalLogout() (two-step logout, first hitting user/logout, then hitting user) is also in #721086: Create tests for system actions, clean up token replacement, clean up triggers, so whichever one goes in second will need a reroll.
Comment #39
sunCritical bump.
Comment #40
japerryFails testing, re-rolling.
Comment #41
jwbuzz commentedRemoved "needs tests" because the patch includes tests.
Comment #42
japerryRerolled patch from #36
Comment #43
Remon commentedpatch works as promised on todays drupal dev
Comment #44
rfayLike so many issues, it's hard to figure out how we got from the start to the finish on this one. Here's an attempt at an issue summary.
This patch provides a new hook_login_paths() to deal with this problem in a generic, extensible way. It was obvious that since we had this hidden problem with OpenID, we could have the exact same problem with many other situations, including contrib modules providing alternate authentication, etc. So now user.module and openid.module implement hook_login_paths() to declare paths that should be available when in maintenance mode.
While doing this, it became obvious that there's another case where it's important to know when a path is a "login path". Authenticated users who stumble upon a "login path" have traditionally in Drupal been given an incomprehensible "access denied" instead of a friendly redirection. So we allowed hook_login_paths() to provide information about that situation as well, specifying how "login paths" should be redirected if an authenticated user lands on them.
The bottom line: This is critical because it takes core openid out of service at a terribly important time. It's done as a hook so that problems like openid's can be handled easily by the module instead of requiring a core patch.
Comment #45
rfayMarked #551880: Make "Request new password" available to anonymous users when site is offline a duplicate (or at least a dependency) of this one.
Comment #46
shawn dearmond commentedI'd like to propose one minor change to this patch which would support wildcards in hook_login_paths().
Comment #47
rfayI think that makes perfect sense and would be an improvement. It would require additional tests, though.
I'm hesitant to muck with this one as it hasn't gotten committed even as is. But your improvement is excellent.
What does anybody else say? Should we muck with it?
Also, since #551880: Make "Request new password" available to anonymous users when site is offline has been marked as dup, should we use user/password and user/reset/* as login paths? The use case: Site is in maintenance mode, admin user doesn't have password so has to use the user/password to access the site. This must have happened to Shawn DeArmond before.
Comment #48
shawn dearmond commentedExactly... well, not to me personally, but to my clients who were supposed to be adding content to an "under construction" site. I didn't grant them MySQL access (for obvious reasons) and I was inaccessible to them to reset their password in an appropriate amount of time.
I already wrote a little contrib module that takes advantage of this hook and solves #551880: Make "Request new password" available to anonymous users when site is offline in a very flexible way. If this patch is committed, I'll create the project node and contribute the module. No point in doing so until this patch is in core, though.
Comment #49
rfay@Shawn, I think we should go for it. Please roll a patch. If you can, please add a test for the user/password + user/reset path.
Comment #50
shawn dearmond commentedSure. I'll do that tonight or tomorrow. I'm going to have to also add the hook implementation into common-test.module. Think that's the best place? hook_login_paths() is invoked in common.inc, so I would imagine that's where it should go.
Comment #51
rfay@Shawn, I was assuming you'd add the /user/password and /user/reset/* right into user.module's hook_login_paths(). I think it makes sense.
Comment #52
shawn dearmond commented@rfay, oh. That's different. Okay, I can do that.
Comment #53
shawn dearmond commentedOkay, here's a patch, re-rolled from HEAD, which includes my change from #46, and includes user/password and user/reset/* in user_login_paths(). Also, I added tests to the maintenance mode tests in system.test which verifies that the password reset functionality works when the site is in maintenance mode.
Comment #54
rfay@Shawn: It looks like you lost the existing tests (see #42). Please put them back in.
Comment #55
rfayThis brings back the tests from #42, although there is a little bit of overlap.
It also updates the hook documentation to mention that we can now handle path patterns.
The issue summary is in #44.
Comment #56
rfayIf somebody would RTBC this minor change maybe we can get it in this week.
Comment #57
moshe weitzman commentedOnce again, a fine issue summary is in #44.
Comment #58
yesct commented#55: drupal.openid_maint_363580_55.patch queued for re-testing.
Comment #59
yoroy commentedStill applies…
Comment #60
Remon commented#55: drupal.openid_maint_363580_55.patch queued for re-testing.
Comment #61
kathyh commentedVerified patch. First verified that issue occurs without patch. Applied patch drupal.openid_maint_363580_55.patch and user can now login in using OpenId when site is in maintenance mode. Tests passed. #ladrupal #lacodecamp
Comment #62
dries commentedThis looks like a fine patch but I wonder if we can simplify this. Instead of adding another hook, can we do something based upon convention (i.e. say anything below /user/login/%)? It seems like that could simplify things drastically ... Thoughts?
Comment #63
dries commentedOn the other hand, this is consistent with hook_admin_paths() ...
Comment #64
sun1) isset() seems to be sufficient here instead of !empty().
2) Could use type-agnostic comparison, i.e., !==.
Do we really need this message? I'd prefer to drop it.
Wrong indentation on first line.
Do we still call this "Drupal path"? I thought it's a "system path" in the meantime, or similar without "Drupal" in it...?
hm, this loop is quite slow from a performance perspective.
Reads a bit weird; read it 3 times, but still don't understand...
"Anonymous users have to be able to access certain pages in maintenance mode."
1) Should start with a uppercase letter.
2) Strange parenthesis here.
3) It also looks like this entire sentence could be moved down, above the actual line that invokes drupal_get_login_paths(), so as to maintain context.
4) However, with simplification of the previous sentence, this second one might as well be dropped entirely.
Can we maintain a consistent coding style for this hook implementation and use a multi-line array syntax, please?
Why is this changed? I'm not sure in which way the user/logout behavior is related to this issue/patch...?
"special action"...? I think this entire Doxygen paragraph can be improved and reworded a bit.
We cannot and must not allow fully fledged path patterns here (which support to define multiple paths in a single key) -- I wonder whether drupal_match_path() is the proper lookup/identification in the first place... why aren't these router paths?
Also, speaking of menu router paths... isn't this becoming a parallel registry to hook_menu()? Can't we declare, register, and store those properties via hook_menu()?
See http://drupal.org/node/1354 for proper list formatting in PHPDoc.
Should be hook_user_login_paths() and therefore located in user.api.php.
1) Let's replace underscores with spaces in these properties.
2) We can improve these property names to make them more precise:
"redirect authenticated"
"maintenance mode access"
Trailing white-space.
What's the devilish "66" here?
Interestingly - shouldn't "user" redirect to "user/login" for anonymous users? (whereas "redirect anonymous" is not yet handled in this patch)
Overall, however, this entire logic is bound to menu router paths, which have access handling already. It feels a bit odd to first negotiate a request, attempt to return an access denied, and while doing so, hack in some special access cases - which should have been covered during regular access handling already - to figure out that we actually want to revert our decision and grant access, or redirect to another system path... this back and forth already sounds icky...
But hold on... why do we build a registry of user login paths here in the first place? Why don't we skip that needless registry and instead, build a quick + small $context to pass around to modules after figuring out a basic positive/negative result in http://api.drupal.org/api/function/menu_execute_active_handler/7 - i.e.
1) Figure out a basic accessible/offline/404/403 result in menu_execute_active_handler().
2) put that into a small $context array
3) drupal_alter('menu_execute_active_handler', $context)
4) proceed as usual, but based on $context
Of course, not a full-blown context à la Butler, but possibly a very first tiny step towards that.
Powered by Dreditor.
Comment #65
rfayMost of sun's thorough comments are relatively easy to deal with.
However, both Dries (#62) and sun (end of #64) suggested vastly different alternate approaches for this issue as well.
The existing approach has been reviewed and RTBC on and off for months. It's important to come to a conclusion here whether we're going to abandon this and start over. IMO, the most likely and fastest way to get this "done" is to stay with the current approach.
Comment #66
moshe weitzman commentedI agree with staying with current approach. If someone can patch for sun's concerns, i will review until rtbc.
Comment #67
berdirUhm.
I started a re-roll of this patch and then pretty much got lost. I don't get the point of this hook as it is now:
- first, it is call hook_login_paths(), but is not limited to that (that hook can be used to allow access to /whatever/you/want to anon users in maintenance mode for example)
- It is used to address two technically unrelated special cases (forwarding authenticated users on specific pages and allow access to anon users during maintenance mode) which only have in common that they are related to user login paths. So, the hook is named after what we are using it for? That doesn't make any sense to me.
- As of the above, I guess it is obvious that I don't agree with renaming this to hook_user_login_paths(), and why should it be in user.api.php if we're using it in the menu system?
- Saying that, I don't know a good name for the hook either (hook_authenticed_redirect_and_allow_anon_maintenance_access_paths() :p)
I actually had a similiar idea as sun in #64, adding a hook to which we pass some information and let the hook decide if he wants to do something special instead of collecting a list of paths to handle two specific cases.
I really wanted to not delay this any further (the opposite, actually), sorry :)
Comment #68
sunVery good points, Berdir, thanks! I must confess I didn't read the issue prior to reviewing the latest patch. If we both had the same or similar idea, then I can only guess it must be the proper resolution for this issue.
Comment #69
berdirI'll try to write a patch.
We already have "drupal_alter('menu_active_handler', $router_item, $path);", I'll try to move stuff around a bit so that we can re-use that.
Comment #70
rfay@berdir, @sun, the issue summary is in #44. It's important that if we're going to start over the history is understood. Note that the patch as it stands has significant support and has been reviewed and RTBC for some time.
Comment #71
rfayUpdate: One way of dealing with this is hook_menu_active_handler_alter(). However, @chx is deperately opposed to the future life of that hook, and has filed #838408: Remove hook_menu_active_handler_alter.
Comment #72
berdirHere's a patch with an extended hook_menu_active_handler_alter().
- Not yet finished, I just want to see what the tests will do with my patch.
- The patch changes menu_execute_active_handler() to also load the menu router item and execute the alter hook when the site is in maintance mode. page_callback_result can be altered by hook implementations to disable (and enable, if they'd want to do that) offline mode for that request (
- moved all user specific stuff in _menu_site_is_offline() to user.module
- the hook implementation in user.module is a mess currently ;)
- I've just added the context as a third argument to the hook, if we are allowed to break the api of that hook, then we can merge path into $context. Especially because $path is actually *not* so useful as it is not set to the actual path on a normal page request.
Note that chx did not like (already existing) hook_menu_active_handler_alter() at all :) If that hook is removed, then this approach won't work anymore. But I'd say the forwarding could simply be put in a hook_init() or something like that.
While testing this, I've noticed #838404: drupal_access_denied() in page callback displays access denied page twice.
Ok, let's see if the tests pass and feel free to vote this down if you don't like it. I'm *not* interested in bikeshedding.
Comment #73
chx commentedOh yeah we are adding context to a hook which should not exist in the first place. This whole context idea screams Drupal 8 to me.
Comment #74
rfayComment #76
berdirHm.
Note that I did add "context to a hook which should not exist in the first place" because the hook still existed at the time I wrote the patch and I wanted to re-use something existing as it was already almost there. (And it doesn't apply because the hook got removed in the meantime ;))
- We can also make a simple hook which we call directly in _menu_site_is_offline() and allow modules to disable offline mode without giving them access to the router_item.
- We can rename $context to something different if you don't like the name ;). Also, $context is not a D8 pattern. There is for example http://api.drupal.org/api/function/t/7, which has a context key in the $options and drupal_alter() itself uses context: http://api.drupal.org/api/function/drupal_alter/7. And there are some fields hooks which use $context and probably many more that just don't use the name context but it is one :)
- Why not simply moving these goto()'s to hook_init() or another place in user.module that's called when this happens? There must be something we can re-use :) (custom access callback could work too, but probably a bit hacky (the current solution is hacky too, so...)).
- In fact, all I suggest is switching from a passive hook (hook implementations provide information about specific cases and core checks if these cases are met) to an active one (modules decide if they want to enable or disable offline mode). So modules like update.module or backup.module could temporarly set the site to offline mode (while uploading new files, for example). Sure, they can currently do this by setting variable_set() but that is persisting and would for example end up in your backup or will not be automatically re-enabled if the backup/upload dies with a fatal error.
The actual code could look as simple as this:
<?php
$is_offline = variable_get('maintenance_mode', 0);
drupal_alter('menu_site_offline', $is_offline);
return $is_offline;
Comment #77
rfay@berdir, I'm still thinking that since we had strong consensus for the earlier approach, and we can just fix sun's style issues and questions and go forward. However, I don't want to cross wires with you on this. I'm in IRC; chx and I are at the code sprint in Denver. We could conceivably get somewhere on this today. If you think you have a viable solution (especially one that handles the whole situation) I'm fine with you running with it. Otherwise, you or I can fix up the original approach with sun's comments.
Comment #78
chx commentedI had at one point a hope that the two issues here (login paths and authenticated redirects on 403) can be merged. user/register smashed that hope. We have dived into a bottomless rabbithole trying to solve this.
Don't.
Two hooks. One to give a list of login paths to solve this critical. One to give redirects on 403 to solve the usability critical. Two simple hooks. Do it, move on.
Comment #79
coltraneI began addressing sun's points in #64 but really keyed on:
The alternate, "mini" context option in this thread seems too great of an endeavor at this late point, but the hook_menu() idea that sun brings up does match the context option in providing a method that is not built around special cases.
So, back to the hook_menu() idea, what would that take? Would we have to alter the menu_router schema and would that kind of change even get in?
Comment #80
berdirI guess I'm fine with #78. Just wondering is there is a better name than hook_login_paths. Something that better explains what it is used for (allow anon users access to paths in offline mode).
I just don't get why everyone seems to stumble over the word context. It's a 100% typical alter hook. We pass an array with some information to a hook and let other modules change it. With the new site offline hook idea from #76, it's not even a array anymore, just a single boolean (It would probably be cleaner to pass the actual path (not the $path argument which is useless in most cases) to that hook as a .... context ;))
Extending hook_menu() and have a new column in the schema to store something that ~5 of possibly hundreds of router items need sounds a much bigger change to me...
Comment #81
sunBerdir, I fully agree with you. I don't see why we need two hooks, if we can solve this elegantly by rolling back the removal of hook_menu_active_handler_alter() and slightly improving that to account for our real requirements here.
People wanted use-cases for that hook, here are two. Counter-proposal to introduce two new hooks for the very same. Confusion on a innocent word "context", just because some butlers talked too much instead of serving drinks. Yes, we are trying to fix the last criticals. But can we maintain at least some sanity and open-minded process to fix the system properly? Don't panic.
So if we can forget about variable names and release date panic for a moment, are there actually any real reasons to not go after the hook_menu_active_handler_alter() approach?
The consideration about hook_menu() was related to the last hook_login_paths() patch only. As that would return a similar router_path => properties array only. Merging these additional properties into hook_menu() would require additional dedicated storage columns for router paths. This would add to an already convoluted list of menu router and menu link properties, which we need to entirely revamp in D8.
Contrary to that, hook_menu_active_handler_alter() would allow for a quite flexible reaction to the current request. We do not build yet another registry, and simply allow modules to intercept the request, right after we figured out what we "would" want to do, but before we are actually doing it. We can't use/enhance hook_init(), menu system information is not yet available at that point.
Comment #82
berdirOk.
chx and I agreed on the following, patch should hopefully come soon, either by me or by chx (I need to finish my exams first)
- We introduce a new hook in menu_execute that can set the $page_callback_result (will be renamed to something more intuitive I guess). This will happen before we call menu_get_item(), maybe even before we call _menu_site_is_offline. That was the last idea, but I'm not sure how to easily force not to use offlne mode. Anyway, that hook can set that variable to MENU_SITE_OFFLINE, MENU_ACCESS_DENIED, MENU_NOT_FOUND or NULL. If the value is not NULL, menu_get_item() is not even called and we directly deliver the page according to the status.
- As obvious from the above description, the hook does *not* have access to the $router_item array. The only use case that has been found in #838408: Remove hook_menu_active_handler_alter is to globally deny access for a specific request, this can be done by setting $page_callback_result to MENU_ACCESS_DENIED.
- The drupal_goto()'s in case of an 403 can be moved directly into the access callbacks, as this does not need access to "the menu system" but simply $_GET['q']. Or into the new hook explained above. Or hook_init(). Or wherever they make sense.
Comment #83
effulgentsia commentedSubscribe.
Comment #84
effulgentsia commentedIn #838408: Remove hook_menu_active_handler_alter, sun and Moshe were the two developers most lamenting the loss of hook_menu_active_handler_alter(), so I asked them to use this issue to continue their lobbying efforts for the restoration of that complete hook, rather than the more limited variant suggested in #82.
Not exactly. Moshe's use-case in #838408-11: Remove hook_menu_active_handler_alter wasn't just to deny access to IP addresses in a certain country, but to do so with a custom page per country. One can also extend the use-case to do the same thing, but without a 403 header (perhaps not letting the people know they're being denied access, but instead giving them an alternate page with a 200 header). What I argued for in that issue is that per-country 403 pages would be best achieved with the 'site_403' variable set to a Drupal path whose page callback contains the necessary dispatching logic. And that per-country alternate non-403 pages would be best achieved with hook_url_inbound_alter(). But I'm not sure that sun or Moshe agree with those claims yet.
Comment #85
berdirAgreed on hook_url_inbound_alter(). (This could imho also work for "The drupal_goto()'s in case of an 403 can be moved directly into the access callbacks, as this does not need access to "the menu system" but simply $_GET['q']. Or into the new hook explained above. Or hook_init(). Or wherever they make sense.")
Not sure how access to $router_item would help with the custom 403 page since drupal only allows to configure a single 403 page. So, instead, a module that would define a 'denied/%' router item would probably be needed anyway, and we need to route the request to that page (again, could even happen through the url_inbound_alter() hook).
Comment #86
chx commentedhow will hook_url_inbound_alter solve the offline issue? we need a utility function that is called instead of _menu_site_is_offline from menu_execute_active_handler. This utility function will call _menu_site_is_offline and then the new alter.
Comment #87
berdirIt will not. We're already discussing three different things here. The third is moshe's use case for keeping the old hook, and I think that his use case can be solved either by using drupal_goto() anywhere or by using hook_url_inbound_alter().
Comment #88
berdirThis is a first try, let's see what the tests say.
No helper function yet.
I also did not move the drupal_goto() to the access callbacks (yet), because user/login uses user_is_anonymous() directly and user/register indirectly and that function has that $_GLOBAL['menu_admin'] check.
Oh, and this will conflict (again) with the clean up patch in the remove hook issue, I guess.
Comment #90
berdirThe other issue was commited in the meantime... again :)
Git was able to auto-merge the changes, though.
Comment #91
chx commentedThe approach is solid. I have rerolled and amended the documentation.
Comment #92
berdirThat's better :)
There's a trailing whitespace in the hook documentation but I wan't to see some green first (or at least an actually executed test run), I guess there will be another re-roll or two anyway where we can fix that.
Comment #94
berdirFixed the failing tests. We're not testing against a router path anymore, so it needs drupal_match_path() for user/reset/...
Comment #95
chx commentedone, the if needs two more spaces of indent, two, ugh, what's wrong with a simple substr?
Comment #96
berdirFixed indentation, switched to a strpos() check. Untested...
Comment #97
moshe weitzman commentedWhy forcibly logout users during maint mode? Once maint mode ends, they'll have to re-enter passwords which they potentially haven't used in months.
"the current router item is retrieve and executed"
missing a 'd' at end of retrieve
Comment #98
berdirWe do that since Drupal 6. I have no idea why we do nor about the consequences of changing that now. I just moved the code around (into the hook).
http://api.drupal.org/api/function/_menu_site_is_offline
Comment #99
moshe weitzman commentedAh, OK. If anyone knows why we do that, I'm interested.
Meanwhile, I think we can send this one for commit.
Comment #100
dries commentedretrieved instead of retrieve?
That 'return' is not necessary because drupal_goto() will call drupal_exit().
Should we introduce a more explicit variable instead of NULL? Like MENU_SITE_ONLINE?
37 critical left. Go review some!
Comment #101
webchickYeah, I was wondering that too. MENU_SITE_ONLINE is much easier to grok. Looking at the top of menu.inc, it looks like 0 is unclaimed as a status, although 0 for "it's working" is a little odd.
Comment #102
chx commentedFixed the broken system.api.php example, added a slash after user/reset, introduce MENU_SITE_ONLINE and addressed the other two concerns of Dries.
Comment #103
chx commentedOh the openid hunk was using == NULL too. Too bad!
Comment #105
chx commentedAll that happened was the test menu alter used NULL still.
Comment #106
berdirPatch looks good to me, I agree with adding MENU_SITE_ONLINE.
@moshe, sun: Can you confirm that this hook is a sufficient replacement for hook_menu_active_handler_alter? As said before, the differences are that you don't have access to the router_item and you can only change access/offline/online/not found or forward to another page. Also, the url can be changed in hook_url_inbound_alter(), so you can either redirect to denied/some-country with drupal_goto() or internally change the path to denied/some-country.
Comment #107
moshe weitzman commentedThis is a good patch and fixes a critical. I don't think this substitutes for the active_handler hook but thats OK. We can deal with that in the other issue or a new issue or whatever. Lets get this one in.
Comment #108
rfayA definite +1 from me. This resolves all the issues for which I was involved in this issue. I tested the results of hitting /user/login and /user/register as auth user, and tested the login process (including getting a one-time login link) when in maintenance mode and using openid. It all seems to work fine.
The one anomaly: The "Create new account" link to user/register is visible when you visit /user and the site is in maintenance mode. The link just gets a "Site under maintenance" page, so I don't think this is worthy of worry.
Please write an updated issue summary and describe the new hook and its possible other use cases.
Thanks for the good work,
-Randy
Comment #109
rfayIn #108 I mentioned the purported anomaly that the "Create new account" link is visible in offline mode, even though the link is not accessible.
That was *not* introduced by this patch. I tested and it's the same without the patch.
Comment #110
webchickI like this much better than previous approaches, thanks. The comments are good, and expanded tests are a great feature, as well (although, humourously enough, not one for this actual bug. ;) Is that easy to add?).
The only thing I don't quite understand is this:
Why are we doing this belly-dancing? Why not give them access to change the path? I looked for guidance over in #838408: Remove hook_menu_active_handler_alter but only see reference to it being "made for abuse".
So if there's an actual reason, which I assume there is, let's document it here.
Other than that, this looks good to go from me.
Comment #111
berdirThat was a rather spontanous decision but it is quite simple (and has nothing to do with the linked issue):
Changing $path there does not change it globally but only what we pass to menu_get_item(). $_GET['q'], arg() and all other functions would still use/contain the old path. Instead, you should use hook_url_inbound_alter() when you want to change the path. I added that information to the hook_menu_site_status_alter() hook documentation but not when calling it. If the following is clear enough, I can add something similiar to that place:
Comment #112
berdirUpdated the documentation and added a test for openid login when the site is offline. Let's see if this passes...
Comment #113
webchickAwesome, thanks!
Committed to HEAD!
Comment #114
sunWhich "global variable" ?
The comment totally does not match the condition on the following line. Something must be wrong here?
Trailing white-space.
Weird sentence... not sure I understand.
"Any other value than MENU_SITE_ONLINE skips the default menu handling and will be passed to drupal_deliver_page() [with no default callback?]."
Needs improvement.
1) drupal_goto() ends the request, but we should still append a break; and newline after this switch case.
2) Separate switch cases with newlines, unless it's a fall-through logic.
40 critical left. Go review some!
Comment #115
webchickComment #116
karens commentedJust a note that we still need a backport for D6. The D7 solution seems pretty cumbersome for D6, but the original patch in #2 works fine for me as a D6 solution.
Comment #117
sunWould be nice to fix the coding style and documentation issues outlined #114.
Comment #118
kattekrab commentedNo idea about the openid aspect - but this is still a problem for core in D6 - going to user/login returns access denied. Previous versions of this are marked as duplicates, I've been going round in circles trying to find where to post this issue.
so have posted a new issue
http://drupal.org/node/1112824
Comment #119
damienmckennaAny plans to backport this to D6?
Comment #120
c960657 commentedFYI:
I did not understand the reasoning behind the change to drupalLogout(). I have created a new issue about reverting this change: #1545930: drupalLogout() should only do one request, not two
Comment #126
ressaThanks for taking care of many "Access denied" situations. I just found an outlier I think, about opening Drush generated one-time login links while logged in, and have created #3316655: Friendly response to logged-in user landing on user/reset. Sharing it here, since it's related.