Hi,

I have a db and a hook as described in:

#305248: Does my hook_views_data look right?

Now... I need to give users a way to restrict access to a view if a parameter doesn't correspond to the logged in user.
The reason is simple: if I set the view as user/%/disregarded where % is the requester UID, I don't want _everybody_ to be able to access this page -- just the requester, so that s/he can see the list of friends s/he said "no" to.

How can I do this?

THANK YOU!

Merc.

Comments

mercmobily’s picture

Hi,

Actually, let me change that. The access should only be granted if the logged in $user is $requested_id... I think?
I am a little big confused about this. I had never ever used views before tonight... let alone writing a hook for it for the D6 RC2 version of views...

Merc.

mercmobily’s picture

Hi,

Could this possibly be done by creating a field called "logged_in_user" (with a hook?) and then adding a filter to it?
Just a (mad?) idea.

Merc.

mooffie’s picture

Could this possibly be done by creating a field called "logged_in_user" (with a hook?) and then adding a filter to it?

Filtering could work, but not perfectly: it would result in empty data; that is, in an empty list. But the "Disregarded" tab will still show on the profile page.

What you want is not to show the tab at all.

======

First, let's suppose your module doesn't exist.

How can an administrator disallow access to 'one/two/%/three' if % doesn't equal 67 or 56 ?

("disallow" = don't even show a tab, or a menu item.)

She can use a "validator". She goes to the argument settings form, then she picks the "PHP" validator, and in the textarea she types "return $argument == 67 || $argument == 56".

Now, to your module:

If all you want is to provide a "default view" with % restricted to current user, then I believe it's enough to export a ready made view where you typed the PHP into the right textarea. (This needs checking, though.)

Sometimes a module needs to provide a more complex validator for the benefit of its users. In this case you can write a validator class. The admin --that is, whoever builds a view-- is given the choice of whether to use it or not.

For example, the Organic Group module provide an "is % a group node?" validator.
For exmpale, the Flag module will provide an "is % a flagged object?" validator.

Maybe Views should provide an "is % the current user?" validator. Or an "is current user allowed to administer user % ?" Perhaps I'm missing something simple. Perhaps my long reply is unneeded, perhaps there's a completely different approach. Let's wait and see.

merlinofchaos’s picture

My most recent checking changed the access control mechanism to a plugin. You can now create a plugin that will tailor your access control appropriately. Be warned that there are two entry points to the access control: One where the view is loaded, and one where the view is not (via the menu system), so it can be a little more complex than you might like. But it's good, and it increased Views performance and flexibility at the same time.

mercmobily’s picture

Hi,

Since doing this now it _is_ possible, I guess this issue should be closed.
But... Merlin, I don't suppose you could point me towards the right direction in order for me to write an access plugin?

If not, that's fine. But even a pointer, a link, a file name, would be grand.

Merc.

merlinofchaos’s picture

Status: Active » Fixed

Sure, look at includes/plugins.inc for the hook_views_plugins() definitions for the access plugins, and look at plugins/views_plugin_access.inc (and the variants) to get an idea for how they work. I believe the existing examples should be a good template for creating new ones.

mercmobily’s picture

Status: Fixed » Active

Hi,

Sorry about reopening this... I've spent 6 more hours on this. I am exhausted. I think it's bounty/begging time.

I saw the files you pointed out, Merlin, but I haven't managed to do it. The main problem is that I can't work out how to get the parameters. The filter should be simply something like "access is there if the first parameter is the logged in $user ID". The problem is that I haven't managed to find a way of getting the parameter...

Now... since this is something that I believe might be of general purposes, and since this is clearly beyond me, can I offer a small bounty of $100 to 'sponsor' you writing such a plugin and commit it?

Thank you either way!

Merc.

mariusooms’s picture

@moofie: Maybe Views should provide an "is % the current user?" validator.

+1 for this concept. Since not everyone can write access plugins, so a default validator to check if the user is the logged user that's doing the viewing would be very desirable.

@merlinofchaos: You can now create a plugin that will tailor your access control appropriately.

-1 because currently I have many views that show user related content data I only want to be seen by the logged user. I understand the module creator could write an access plugin, but that doesn't solve the regular default created views with paths not depended on another module for the regular user.

I realize this is not a discussion, but how things are incorporated currently, but still I wish that beyond the current of choices of Unrestricted, By permission and By role there would be a forth option "By current user".

I hope my argumentation makes sense.

Kind regards,

Marius

mercmobily’s picture

Hi,

If I knew how to program OOP, if I knew Views' architecture, and basically if I were technically able to do it, I swear I would. Sorry :-(
Instead, all I can do is accept my limitations and offer a bounty to the capable Merlin... hopefully he has time.

Bye!

Merc.

merlinofchaos’s picture

Your argument makes sense in the "You have to do this for me" attitude that I am not fond of. Sorry, Views just isn't ever going to do everything for you. Sometimes features that seem obvious turn out not to be and you just have to live without them if you don't have the ability to write the plugins yourself.

merc: Because it has very little knowledge of your view, what you probably need to do is set the callback args to the arg() number you'll need, and you'll have to do this by taking the view path and breaking it up and seeing where you're arguments are. To be truly flexible you'll need to have a selector for which argument it should be as well.

mercmobily’s picture

Status: Active » Fixed

Hi,

Thanks Merlin. I will give it a shot.

If you can direct me to anybody who knows the Views APIs/framework well enough to be able to do it in a very short amount of time, and would be happy to get the small $100 bounty, please let me know.

Hey, I ported FriendList to the latest Views dev, the one after sept.3 where you have to register the hooks, and it works fantastically :-D

Thanks!

Merc.

mercmobily’s picture

Hi,

@merlin:
I gave it a shot, and I hurt myself. Sorry.
I think I am going tot have to give up on this one. However, since this would be a feature that would definitely benefit others as well, and since this issue has valuable info on how to do it, do you think we should keep this issue "open" in case somebody who needs it as well might find it and code it?

I don't want to reopen this because I know how annoying it can be... but please let me know.

Merc.

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

mercmobily’s picture

Category: support » feature
Status: Closed (fixed) » Active

Hi,

Merlin, I gave this another shot and failed -- again.
Now that the pressure for Views is off (congrats!), is there any chance to keep this open as a feature request?

I realise that it's probably a fringe request, but surely a few people out there would find it useful...

Thanks,

Merc.

mercmobily’s picture

Hi,

If anybody out there knows Views well enough to implement this in a very short time, I will offer a symbolic, pitiful $50 token plus a nice big fat thank you in Free Software Magazine's home page.

I fully realise that $50 doesn't go even close to the value of the time it will take, even if it only takes half an hour.

Bye!

Merc.

dawehner’s picture

its not very hard to do it :)
but there are two different ways:

first someone could write a access plugin
second there could be a additional views_plugin_argument_validate plugin

or
write a patch for views_plugin_argument_validate_user to extend it to only allow current uid, if wanted.

mercmobily’s picture

Hi,

Dereine, have a look here:

http://drupal.org/node/307087

I talked to Merin. I think he's suggesting writing a plugin...

The important part:

---------------------------------------

Hi,

In an IRC session, Merlin pointed this out:

http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/project_iss...

Thins to change according to MerlinOfChaos:

"The actual test; that one tests to see if the uid is empty, I think."

And to make it into a proper Views core patch:

"add an option in the options_form that is probably a radio that says "pass if the user is the user ID in the argument" and "fail if the user is the user ID in the argument". Or something along those lines.
----------------------------------

Sounds easy enough, worth a "Thank you " in Free Software Magazine and a token $50? :D

Merc.

voxpelli’s picture

Version: 6.x-2.0-rc1 » 6.x-2.6
Status: Active » Needs review
StatusFileSize
new2.03 KB
new2.37 KB

I'm attaching two patches here.

One patch adds an action for showing an access denied that can be used when an argument is not present or invalid.

The other patch extends the user validator with an option to limit to or exclude the currently logged in user.

I think a combination of these two patches might solve the core issue reported here - I wanted this functionality in a view I coded anyway I thought I could just as well create patches for it and share with you.

mercmobily’s picture

Hi,

+1 ! I would _love_ this for FriendList...

Merc.

merlinofchaos’s picture

This would be more useful to Views as an access plugin.

The reason access plugins are valuable is that if you have multiple displays with the same path, the access plugin can be used to control *which* display is presented. Validators, however, cannot do this, as they are too late in the process.

So while this is useful, it would be more useful as an access plugin.

mercmobily’s picture

Hi,

Voxpelli: any chance to change this into an access pluging?

Merc.

TC44’s picture

Subscribing. I would also find this incredibly useful.

voxpelli’s picture

@merlinofchaos: Interesting - didn't know that you could assign many views to the same path and have it select the right one based on access. I will try to get some time and write an access plugin - seems more usable.

Do you think the access denied validator action can have a place in Views anyway though?

tevih’s picture

Is there a reason this can't be included instead of as a patch? I can't get the patch to work (patching by hand.. tried four times.)

jimmb’s picture

+ 1.

duellj’s picture

Version: 6.x-2.6 » 6.x-2.x-dev
StatusFileSize
new1.63 KB
new4.97 KB

Attached is a new access plugin for views that allows you to restrict access based on the comparison of the logged in user and an UID argument.

For those of you that don't want to patch views, I'm also attaching a separate module that does the same thing.
@merlinofchaos: if you don't want to patch views with this access plugin, I can release this as a separate module.

duellj’s picture

StatusFileSize
new1.64 KB

There was an error in the views_user_access module, attached code fixes it.

merlinofchaos’s picture

duellj: This is very interesting. It is also very close, I think.

I believe this will fail if a uid is set via a default argument.

Take this case: I have a path, 'foo'. If I visit foo, I see 'my' foo. If I visit foo/51 I see foo for uid 51. This is accomplished by adding a default argument that provides the current uid if the argument is empty.

project.module has some fairly thorny code to accomplish this in its access checks.

merlinofchaos’s picture

I believe that, if we can get this working adequately, I will put this in Views.

duellj’s picture

Status: Needs review » Needs work

I believe this will fail if a uid is set via a default argument.

It looks like it works if you set the default argument to be "User ID from logged in user". For "User ID from URL", it doesn't seem to work. For example, a block with "logged in user" access control shown on /user/51 will show the content for user 51 regardless if it's the logged in user. Desired behavior is to not show the block (since logged in user doesn't match argument).

I'll work on fixing this.

duellj’s picture

Status: Needs work » Needs review
StatusFileSize
new5.08 KB

Actually, everything appears to be working. Got a false positive by the "access all views" permission :).

I reworked the patch a bit to match the naming of the other access check functions and to make the argument field required.

Is there a way to have a different error message for the options form? It would be nice to say something like "Please add an uid argument before configuring this access control" if there are no arguments defined yet.

merlinofchaos’s picture

You probably need to do an if() when presenting the select widget and provide a #type => 'markup' thing instead if there are not acceptable arguments.

merlinofchaos’s picture

Should I hold off on this patch until you've made that change? It seems like that nicety should go in.

duellj’s picture

Status: Needs review » Needs work

You probably should hold off on the patch until I've made this change. It causes a fatal error if you use the access control without associating an argument. It'd be nice to make it so the user can't add the access control if there are no arguments, but I can just through a few if() statements in there for now.

duellj’s picture

Status: Needs work » Needs review
StatusFileSize
new5.39 KB

Here's a new patch that displays a message if there are no arguments available, and denies access if argument hasn't been set.

ajayg’s picture

Wouldn't we need a similar patch for 6-x-3.x as well?

dawehner’s picture

Status: Needs review » Needs work
+++ plugins/views_plugin_access_logged_in_user.inc	25 Mar 2010 19:36:11 -0000
@@ -0,0 +1,70 @@
+
+  function option_defaults(&$options) {
+    $options['logged_in_user_argument'] = '';
+    $options['logged_in_user_access'] = 1;
+  }
+  ¶

you should use option_definition. Therefore have a look at views_plugin_access_role for example. without this the export in views3 does not work.

Powered by Dreditor.

There was a patch in the queue, which allowed to send dynamic arguments to the access callback.
I think this would make the code much cleaner and faster, because you wouldn't have to load the view.

deverman’s picture

We are testing this patch now and need this functionality. Subscribing.

duellj’s picture

you should use option_definition. Therefore have a look at views_plugin_access_role for example.

It looks like view_plugin_access* only use option_definition in views3. I'll reroll the patch into 6.x-3.x that includes option_definition(), but I think the patch in #35 is ready for 6.x-2.x

duellj’s picture

Status: Needs work » Needs review
StatusFileSize
new5.47 KB

Here's the patch for 6.x-3.x

deverman’s picture

The patch in comment #35 worked for us in views 2 well done.

dawehner’s picture

Status: Needs review » Needs work

It looks like view_plugin_access* only use option_definition in views3. I'll reroll the patch into 6.x-3.x that includes option_definition(), but I think the patch in #35 is ready for 6.x-2.x

I don't think so, the option_definition api is there since ever. Have a look at the other access plugins.

cyberwolf’s picture

Subscribing.

cyberwolf’s picture

In reply to #37, just in case anyone needs it, the patch for dynamic access arguments is here: http://drupal.org/node/644008

bojanz’s picture

I like this idea, would remove the need to write custom access plugins for many use cases.

guillaumev’s picture

StatusFileSize
new14.82 KB

Hi,

I had the same use case and wrote a module before finding this post. It's less complete than duellj module because it assumes the user ID is the first argument (so you can't select the argument in a list). I'm attaching the module here...

crea’s picture

Subscribing

yesct’s picture

Status: Needs work » Needs review

Is #35 the one to review? Maybe we could bring this thread back to life.

hosais’s picture

subscribe.

I also have little confused this access control issue in views.

I recently made some views for the member system of my web site. I use these view as a block on the path /users/user-name. These views will release info about:

1. User profile (core)
2. content profile (content type)
3. User's collection (flag)

1. <- To my surprise, with this setup, the user can see other's drupal profile directly. This is serious privacy violation.
2. <- Only content profile is protected (I guess this is because Views and content access are integrated very well).
3. <- They can also see other's flag info.

Currently I do this will PHP validation to arguments (like many posts above). However, should views take care of access control or let other module do this with hooks?

If anyone knows any document related to this issue, please let me know. Thanks.

rob230’s picture

Issue summary: View changes

I want to have a tab on the user profile which is a view. But this should only be viewable to the user in question.

For example, "user/%/myview".

As far as I can tell, this isn't possible using the current permission and role-based access checks. What is the best way to go about this? The only thing I can think of is to create the path in a module using hook_menu() and then in the callback render the view. Then I would have full control over the access callback. But before I go down the custom code route, I wanted to check that it isn't possible using just views. If it isn't, it might be a feature worth considering to have "current user matches contextual argument" as an access option.

I am using Views 7.x-3.x.

rob230’s picture

I created my own module with a views access plugin. Thanks to the people who supplied patches in this thread. I think this is probably a cleaner way of doing it, although it's a shame you have to manually set the view args based on the view path and the current path, but it doesn't seem that any of the existing views code can be reused for that.

barraponto’s picture

@Rob230 can you post your module?

rob230’s picture

StatusFileSize
new2.75 KB

It's quite basic. I based it on the patches other people provided.

Edit: actually that has a bug in it. It doesn't work for blocks. You just need to add:

$this->view->set_display($this->display->id);
$this->view->init_handlers();

to the access function in views_plugin_access_current_user.inc.

chris matthews’s picture

Status: Needs review » Closed (outdated)

The Drupal 6 branch is no longer supported, please check with the D6LTS project if you need further support. For more information as to why this issue was closed, please see issue #3030347: Plan to clean process issue queue