Thank you for an incredibly useful feature! Switch Users is fantastic for checking what the site looks like for "normal" users and for various roles, especially when you run the site in a different language than the one you use for the administrator. Obviously, you don't want to grant "switch users" privilege to everyone, or they'll start 'helping' you to administer your site.
To that end I've defined a role "System" and one user for each role that also has the System role. The administrator has the system role, too, and only the System role has the devel module privileges. Now I can easily switch among all System roles -- it works like a dream!
The only problem is that the "Switch Users" menu displays all users, and as their number increases it becomes tedious to search for my System accounts. As a well-meaning administrator, I don't see why I would ever want to switch into the account of one of my real users, i.e. into an account that does not have the "switch users" privilege.
Thus the list of users in the "Switch Users" block should be limited to those users that have that privilege (which will also help to remember exactly which users are part of that all-powerful circle). Maybe someone uses Switch Users in a different way that requires having the full users list, and so it would make sense to provide a configuration option, but IMHO the default should be to limit the list.
Hans
Comment | File | Size | Author |
---|---|---|---|
#36 | devel_switch_auth_users.6x.patch.txt | 2.67 KB | dww |
#35 | devel_switch_auth_users.5x.patch.txt | 2.74 KB | dww |
#34 | devel_switch_auth_users.patch.txt | 1.96 KB | dww |
#30 | devel_switch_users.d6.patch.txt | 2.62 KB | dww |
#29 | devel_switch_users.patch_3.txt | 2.58 KB | dww |
Comments
Comment #1
moshe weitzman CreditAttribution: moshe weitzman commentedI actually never thought of using the feature like that. Nice idea ...I'm inclined to aceept this feature. I'd like to hear input from others.
Sometimes it is useful to switch into the accounts of real users when those users are reporing a problem with their account that can't be otherwise verified. But thats fairly rare, and you can't switch back anyway.
Note that there is also masquerade.module which provides a more production strength version of this feature.
Comment #2
salvisOk, I'll buy that about reproducing problems in a specific user account.
I've only read the description of masquerade, and it seems to be an improvement over having to log out and log in among various accounts, but Switch Users is light-years ahead by showing a menu of users at all times and being able to switch with a single click, without even loosing your place in the site. I haven't actually used that yet, but I guess if you have System users with different themes, you should be able to switch between themes with a single click and without losing your place (as long as the new user has access to the page (1)).
I'm only just getting started with Drupal and haven't had much use for the other devel features yet, but Switch Users is absolutely fantastic, and if you trim the user list, it won't lose any of its appeal as the list of users grows. Maybe you can trim the list and add a menu item "other users" that expands to show all other users? Then you don't need to introduce a configuration option, and the added value of seeing who has the privilege will more than make up for the inconvenience of an additional click.
(1) One thing bothers me a bit: Whenever I change an administrative setting and switch to a normal System user to check the effect, I get an access denied error (because the normal user doesn't have access to the administrative page). Of course that's correct behavior, but it needlessly pollutes the log file. Would it be possible to check whether the page is accessible to the new user and redirect to /node if it isn't?
Comment #3
salvisI just added my twelveth user and found out that the Switch User menu seems to be limited to 10 items. Is that true?
That makes it all the more desirable to filter out the users that don't have the Switch User privilege and keep those in the list that do. Can you switch to a user that is not on the list? Makes a submenu with the full user list look attractive. And sort the items, too. It's not always the same user that gets clipped, but often it's the administrator, and that obviously kills the feature!
Is there any chance that you might do some work on this in the next few days? I'm new to PHP, but I must have this functionality, and if I can't convince you to do it, I'll have to try to do it myself...
Comment #4
moshe weitzman CreditAttribution: moshe weitzman commentedI won't be working on this, but i would review a patch contributed by other.
Comment #5
salvisOk, here's the first tiny iteration: change the sort order in the Change User list such that you get the ten most recently used users instead of the ten that haven't been active the longest.
Comment #6
salvisAt this point I don't know how to proceed. One possibility is this:
(add the user_roles() call, the if and the then branch)
This preserves the old functionality in the case where no roles have been given the "switch users" permission, i.e. the administrator gets the Switch User block with the 10 most recent (after the patch in #5) users. No one else gets the Switch User block.
If one or more roles have the "switch users" privilege, then it shows only those users. This might not include the administrator, if he doesn't have one of those roles. In the past (before the patch in #5) he also scrolled off the list when there were more than 10 users, but if the list was short, he was included.
If we may use subqueries, we can include the administrator with:
If we may not use a subquery, we can do the subquery ourselves, adding one database access. Alternatively, we can check at the end whether we have the administrator and only if we don't, we can add it (but then it won't be in the proper sequence, and the code won't be pretty...).
Let me know which path you want me to pursue...
Comment #7
salvisI have 5 System users, and when my Change User menu dropped down from 10 to 5, I found that I'd started to enjoyed seeing the 5 other most recently logged in users. So, where are we now:
1. With your current code, the active users scrolled off the list because the inactive ones were sorted to the top. This is a bug IMHO, and #5 fixes it.
2. #6 was my attempt to limit the list to only those users that have the "change users" privilege, with a nested query (or a kludge) to ensure that the administrator was part of the list.
3. After seeing the result, I'm backing off a little, and this is what this patch does:
a) take all uid's that have a role with "change users"
b) add uid 1 if not already there
c) fill any remaining spots up to 10 with other most recently logged-in uid's
d) populate the menu, ordered by access
This might result in more than 10 items, if more than 10 users have the "change user" privilege, but that's fine. All those should be in there IMO. It requires one or two additional database queries, but they're all straight one-table queries, and they add value.
This patch depends on the one in #5.
Thanks for reviewing and considering inclusion.
Comment #8
salvisHere's the last iteration I can provide: It bothers me a bit to have two kinds of users in the list, those that can "switch users" and those that can't. This patch builds upon #7 and appends an asterisk to the user names that have the privilege, i.e. to those that'll let you switch back.
There's one thing that I don't understand in your code: what is the purpose of the
WHERE uid > 0
clause? I haven't included it in my SQL -- if it's required, please add it.I would have liked to check the accessability of the destination url, but I haven't been able to find out how to get the $nid from the url...
I would also have liked to add an expandable "all users" menu item, but I don't know how to do it, so this is how far I can take it. IAC, each iteration adds value, and you don't lose anything compared to what you have now: if there are 10 users or less, you'll always see all of them, if there are more than 10, you'll see the important ones (those that have the "switch users" privilege) plus the most recent ones up to 10.
Comment #9
dwwcool... i was thinking of exactly the same thing and came to post a feature request about it, and found this. ;) +1, for sure. now that devel has the nice textbox for typing in the user you want to switch to, that solves the problem moshe raised about sometimes wanting to switch to a specific, non-priv'ed user to see what the site looks like for them. i doubt the patch still applies, but i'd love to see this get in. if i get a chance, i'll review it, update it as necessary, and get this RTBC.
Comment #10
salvisThanks for the encouragement, dww. I've just upgraded to 5.1 and ported the sum of the patches up to #8. Only slight changes were needed. Your review might help to get this into the module.
I'd still like to check the accessibility of the destination url and avoid going to the 403 page (or maybe just prepend a '!' to those user names that won't have access), but I don't know how to do it...
Comment #11
moshe weitzman CreditAttribution: moshe weitzman commentedanyone available to review this?
Comment #12
dwwpatch was a good start, but i a) didn't like the behavior in a few ways and b) the implementation was a little bit complicated. new patch that:
- follows coding style exactly (e.g. no "} else {" on the same line)
- always puts the users that can switch (if any) at the top of the list
- never includes the current user as a valid target to switch to
- has (IMHO) clearer variable names
...
Comment #13
moshe weitzman CreditAttribution: moshe weitzman commentedlooks great. thanks. feel free to commit, dww. note that DRUPAL-5 and HEAD are different now. Please commit to both.
I only found one nit - you could optimze a bit by only selecting out the right number of additional users. notice last param of:
$users = db_query_range('SELECT uid, name FROM {users} WHERE uid != %d ORDER BY access DESC', $current_uid, 0, 10-count($links));
Comment #14
dwwactually, i thought of an even better way to do these queries while i was in the car on the way to class tonight. i'll re-roll right now.
Comment #15
dwwComment #16
webchickMuch easier to use now, but we really need some kind of indication of what that asterisk means (and maybe also use a different marker -- elsewhere in core, * means 'required').
Here's a patch that's the same, but prepends a simple description to the block:
* = user who may switch back
same font style as the description for the user search box.
Comment #17
dwwyeah, i was thinking about that, too. however, i don't like the fact we always print that, even for a list that has no '*' in it. and, i agree that '*' might be too confusing. a better way to indicate who can switch would be nice.
maybe we want a title on these links so that when you mouse-over, it tells you "User can switch" or not... ?
Comment #18
dwwwhat about this?
Comment #19
salvisThanks for getting the ball rolling!
#12: - always puts the users that can switch (if any) at the top of the list
I disagree with this. Having the entire list sorted by last access date is valuable information, and it's part of the original design. If you put the ones with the asterisks at the top you don't add any information (after all they're easy to spot in a list of ten), but you unnecessarily destroy information. I use some of the switchable users more often than others and having the entire list sorted will instantly give me an idea of how recently the non-switchable most recently logged-in users were on.
In my implementation, it can also happen that all switchable users are at the top: If I've just used all of them, that's the normal state, but if the lesser used ones don't tend to sink to the bottom of the list, then I know that my testers haven't been on-line for a while, and that's very useful information! Also, the very moment one of my testers comes online, I see his name rise to the top -- that too, is useful information — I might even give him a quick phone call, seeing that he's working for me and I'm not interrupting him in something entirely different.
There are other ways to get that information, but having it in the Switch Users block is free (code-wise, processing-wise, screen real estate-wise, and user attention-wise). Please revert the separation in two disjoint lists!
- never includes the current user as a valid target to switch to
I disagree with this, too. I've been using my patch for almost half a year, so I may be a little bit ahead of you :-). You save one spot out of ten, but you lose a lot of usability:
You could flip back to tab 2, switch users to Member, but then the Log is replaced with your 403 page and you generate a 403 entry in the log because Member is not allowed to view the Log, and flip back-back to tab 1 to continue your Member session, but this is certainly not ideal. In my version of the patch, a "Member" link is at the top of the list in the Member view on tab 1, and I can just click on it to switch the session back to Member.
After some interaction as Member, you want to check the Log again and you flip to tab 2. With my patch you'll see the Log and you click on "Webmaster" to switch the session to Webmaster and refresh the view. That's how it's supposed to work! If you take away the "Webmaster" entry (to save one out of ten) you're stuck!
So, here's the routine: whenever you flip from one browser tab to another that has a different user context, you just click on the user name, which is conveniently located at the top of the Switch Users list, to restore the correct user context for that tab.
If it hurts you to "waste" one of ten, then why not just raise the count to eleven, but by all means don't remove the current user!
(In fact it might make sense to make the number of entries configurable, so that those who have many switchable users could raise the count if they want, but that's another issue.)
Comment #20
dwwwell, different people use this block for different things, and therefore want different behavior. in your case, you want to overload the "Switch users" block as your "Recently logged in" block and/or your "Who's online" block. in the case of the d.o testing profile (http://drupal.org/project/drupalorg_testing), we have a crapload of randomly generated users, and 10 that are in a special role that can switch. we just want the switch block to show those users that can switch (which are in other roles that mimic the different roles on d.o itself), so you can easily flip around on the site and see how things behave at different priv levels.
so, i can see leaving the current user in the list, since, now that you mention it, i've used that functionality on my own test sites before, too.
but, i'm not yet ready to just jumble everything back into a big list sorted by access, not permission.
probably we should just have 2 blocks, instead:
then, you can turn on #1, and we can turn on #2 in the d.o testing profile, and we'll all be happy...
Comment #21
salvis#16: * means 'required'
This is true for * in connection with entry fields. Here we don't have entry fields, so it's obvious, that we're in a different context where 'required' doesn't apply.
The * is a useful hint for those who know what it means, but it's not a problem if you don't know. If we take away the *, most people wouldn't recognize the difference in the behavior of the Switch Users block (assuming that the changes from #12 will be reverted as suggested in #19) — the way you use it stays the same, whether
It's very similar to the ellipses on button captions and menu entries. If you know that [Print...] will lead you to a dialog with a [Cancel] button and [Print] will print right away, then you appreciate having the ellipsis, but if you don't know the difference, then it doesn't matter.
In the default installation (without a group that has the switch users permission), only user 1 will have an *, and I don't believe that the concept of user 1 being different will confuse or disturb anyone.
Moreover, after switching to a user that won't let them switch back, people will quickly recognize that there are two different kinds of users, so I'd say that this is self-explanatory.
A mouse-over hint doesn't hurt much, but IMO its usefulness is extremely short and slight, nothing compared to the annoyance of flashing up unnecessary tooltips for the rest of your life.
Comment #22
dwwit still needs work. ;) clearly, we need 2 different blocks to keep everyone happy.
i don't care that much about the '*', i'll let you and webchick fight that one out... i still agree that if we stick with *, we need that (slightly ugly/annoying) description of what the '*' is about. your "if you don't know what it is, it doesn't hurt you" attitude isn't really the right approach in general. OTOH, this is the devel module after all... not for the casual drupal users. ;)
however, until somone posts a working patch to split this up into the 2 blocks i outlined in #20, please leave the status at "code needs work" (CNW).
thanks,
-derek
Comment #23
salvis(Oops, sorry about resetting the status — that wasn't intentional. My form had the old status, you changed it, and when I submitted my form, it was inadvertently changed back.)
#20: we have [...] 10 that are in a special role that can switch. we just want the switch block to show those users that can switch
My code did exactly that. Now I understand why you wrote "was a little bit complicated" in #12. You simplified it and inadvertently removed an essential property that you're trying to bring back now at the expense of another valuable property.
My code did this:
10-count
, because some of the first10-count
ones may already be in the list and we need others to fill the list up to 10,access
and clip to 10.This never clips switchable ones while keeping non-switchable ones, because if there are 10 or more switchable ones, step 3 does nothing and no non-switchable ones ever get added.
It might make sense to not clip to 10 at this point to avoid dropping switchable users, because if we have more than 10 users in the switchable role, we probably want to see all of them.
So, if you have exactly 10 switchable users (including user 1), then my code did exactly what you wanted, and I don't understand why you would need to break the list into two, because you only see those that would be in the first half anyway. It doesn't matter to you whether the others would appear below, or in
access
order.#20: in your case, you want to overload the "Switch users" block as your "Recently logged in" block and/or your "Who's online" block.
I want to keep/preserve the "Recently logged in" and "Who's online" information that is already in the current Switch Users block. It's not that I want to add something new, I'd like to keep you from removing something that's there.
Actually, I don't know the "Recently logged in" block, that must be an separate module? But adding those two blocks would be overkill and far away from the convenience of the "Switch Users" block which can provide exactly the right mix of "recently logged in" and "currently online" information in a spot that I look at regularly anyway.
So far you haven't provided a reason for why you want to break the over-all sort by
access
, on the contrary, you've explained that it doesn't matter to you, so why unnecessarily destroy a feature that the old Switch Users list has?#22: however, until somone posts a working patch to split this up into the 2 blocks i outlined in #20
I see no need for two blocks as explained above. If you take my patch
Rather than bloating this to two blocks (I don't think anyone would want to see both at the same time or even at different times...) a configurable number of entries and/or a flag to limit the selection to switchable users only (and possibly use simpler queries), might be a better idea.
Thanks for bearing with me...
Hans
Comment #24
salvis#22: your "if you don't know what it is, it doesn't hurt you" attitude isn't really the right approach in general.
Yeah, not in general, but don't you see the analogy to the ellipses? And your OTOH is pretty convincing, too... :-)
Oh, and in a sense the * does stand for required — if you hope to come back without having to log out and in again, you're "required" to chose an entry with a *. ;-)
OTOH we could also argue that we should really use ellipses, because the changeable users allow you to "cancel" the switch and come back, while the others switch you permanently. 8-0
I'm simply looking for the most unintrusive way to distinguish the switchable ones — the * seemed to fit nicely, but I'm happy with anything else, as long as it's visible without mousing over, and preferably without any annoying dynamic behavior at all. Would menu.module support making them bold or italic? Not that I'd prefer that over a tiny *, just exploring the possibilities...
Comment #25
salvisSorry about opening a third subthread, but things have moved so quickly when I was away yesterday, that I'd like to bring this up as long as there's still time, and it's related to the discussion about the * indicator.
As mentioned before (#10) I'd like to check the accessibility of the destination url. If you've used the patch for any length of time you've doubtlessly found yourself switching to a user with lesser permissions and ending up with "Access Denied." I could live with that, but what really bothers me is that a watchdog record is created.
Is there a way to check whether the current page is accessible for each user? Would this add undue overhead? Could it be made optional?
If we can detect accessibility there are two possible strategies:
drupal_get_destination()
.If you get the 403, the URL is not changed, and you can switch back to a user that has the required permission and see your page again, without losing your place. This is a valuable property and I'd hate losing it.
Nonetheless, I believe a visual indicator would add considerable value to the Switch Users block: you'd be able to see at a glance which of your users (role models) are able to view the current page!
If we had a visual indicator, there'd be no need to break the link target, because the user would know ahead of time that he can't go there without risking a 403 and a watchdog entry.
So, the indicator: Being a programmer, I thought of the exclamation mark (!), the tilde (~), and the minus (-), all meaning some sort of 'not' or 'negation', but they all carry more weight than the *. The * is easily used in colloquial writing as a footnote reference, and I feel that most people should be able to pass over it without second thoughts. The other three, however, are less common and beg for questions.
As with the *, once you've realized what it means, you won't need constant reminding, because the division into "can go" and "cannot go" users is just as fundamental as the one into "can come back" and "cannot come back" ones, but I'm hard-pressed for another symbol that is both unobtrusive and sufficiently intuitively distinct from *.
If menu.module supports it, I'd suggest using strike-through text as an intuitive indicator for "Don't go there!" Is there a way to do this?
text-decoration
property, but does menu.module support it?Is there any chance for rolling this into this patch?
Comment #26
webchickHoly crap. I don't have time to read all of this atm, but I was thinking rather than *, a simple theme('placeholder') around the username with a title attribute, so when you highlighted them to say "Hmm.. why's this person italicized?" it would tell you. Then we could ditch the description.
Comment #27
moshe weitzman CreditAttribution: moshe weitzman commentedi am fine with astersisk or title - just please don't discuss it anymore. we have enough discussing about trivialities in this project - not in devel!
i don't want to check the permissions on the destination url just because of the watchdog issue. if you don't like that, make your own watchdog (possible in drupal6) or comment that out in your code.
from the most recent patch, i ould be happy if we committed it with just the change to put self back in. i'm ok with other changes, but thats the only one i see as *necessary*
Comment #28
dww@salvis: nothing i changed was inadvertent. ;) i changed it because i didn't think this block's primary function was to show you the 10 most recent users, it was to allow you to switch, and the users that can switch back are the most important to put in that list for ease-of-use. i don't have time or desire to point-by-point refute your comments about the necessity of the ineffecient and convoluted queries, LIMIT clauses, the actual behavior of your patch vs. what you describe above, etc. i'm starting to think i should just commit my patch (agreed, restoring the current user in the possible list), move on with my life, and you can always write one of the world's smallest drupal contribs that depends on devel.module and provides whatever "Switch recent users" block you'd like, with whatever queries you want.
@webchick: i like the theme('placeholder') + title.
@moshe: well said. ;)
Comment #29
dwwComment #30
dwwpatch for HEAD (old one didn't apply cleanly, and l() has changed)
Comment #31
webchickWorks for me. Should make everyone happy (or at least allow them to live with it ;)).
Comment #32
dwwcommitted to DRUPAL-5 and HEAD.
phew! ;)
Comment #33
salvis@All: Thank you for considering my input.
@dww: I'm sorry, I didn't want to escalate this into a fight where point-by-point refutes are needed.
It seems that your latest (and committed) version doesn't ensure anymore that user 1 is among the selected list.
You mentioned that my patch didn't do what I described, and you questioned the necessity of the ineffecient and convoluted queries. I don't want to argue, but I'd sincerely like to recognize and learn from my mistakes. I have two or three straight-forward single-table SELECTs. You have one less in your last iteration, but you may have to re-add it for user 1, and one of yours is a two-table JOIN.
I cannot see why your solution is more efficient, nor can I find a mismatch in my specs vs. code. Would you enlighten me, please? (I'd be glad to expose the code and add some comments and numbering, to make it as easy as possible for you to comment.)
@moshe: I'm sorry to test your patience and I won't beat this dead horse anymore, but I'd really appreciate
The Drupal Dojo is probably the right place for this type of discussions, but we've gone this far here — maybe you'll let us hash it out to the end?
Comment #34
dww@salvis: sorry i was cranky, but i don't have time now to go into it.
no, my committed version doesn't ensure uid 1 is in the list, which is by design, based on the feedback you gave. we ensure it's in the query (see how i build the $where array in the patch), just not that it's in the top 10 most active users.
i did notice a problem on a test site regarding giving the "switch users" permission to the "authenticated users" role, since those don't show up in {user_roles}. attached patch fixes this. please review/test.
Comment #35
dwwNew patch (for DRUPAL-5) that fixes 2 more important problems:
1) making the queries pgsql compatible again
2) we weren't properly filtering out uid 0
Tested on pgsql and mysql. RTBC?
Comment #36
dwwsame fixes for HEAD.
(kind of a bummer that the code was refactored in one branch and not the other, since it makes this porting more of a pain. oh well.)
Comment #37
dwwSince these are just bug fixes, moshe gave me the green light in IRC to commit without other reviews. Committed to HEAD and DRUPAL-5. New features I dream up will continue to go through the usual patch workflow...
Comment #38
(not verified) CreditAttribution: commented