At the moment, users can't edit todos after they are created unless they have "administer node" permissions. Other modules that create "special" content types (eg. poll.module) have these permissions:
-create poll content
-delete any poll content
-delete own poll content
-edit any poll content
-edit own poll content

to_do needs a similar set, and possibly also an additional "edit todos assigned to user"

Comments

AlexisWilke’s picture

naught101,

Yeah... I was thinking about it. I don't know that much about the GRANT mechanism and it was working the way it was...

Changing it that much would require all the existing users to update their database "properly."

I'm not too sure how much impact it would have, but it could be dramatic.

If you can post a patch, I'll be happy to look into it.

Thank you.
Alexis

naught101’s picture

Alexis: Yeah, I'm happy to have a poke at this. I will start simply, maybe with just the "Edit any todo" and work from there.

I'm not sure what you mean about GRANT - it shouldn't be hard to do all the permissions stuff in drupal and completely ignore the SQL stuff..

I haven't had a chance to look at the code at all yet, and probably won't for the next couple of days (I'm setting this up on a local intranet, and am going away, so I'm in bug-hunting rather than -fixing mode right now). Any pointers or ideas you have would be appreciated, but I'm sure I'll bring some questions back soon :)

AlexisWilke’s picture

naught101,

The to_do pages are nodes and to work properly, which means work with the db_sql_rewrite() function, it must use the GRANT system.

This being said, the poll module, as you mentioned, may be a good starting point. 8-)

Thank you.
Alexis

naught101’s picture

Title: New permissions: edit/delete own/any todo items » Permission system overhaul

Wow. There are some serious permissions problems here.

As stated in #531330: Need page to list all items assigned to all users, the "view all to do listings" permission doesn't work correctly.

I've also noticed that the "To do list assignment" permission doesn't work - only user who are admins can be assigned to a to do by other users. Users with this permission don't appear in the auto-complete list.

I wasn't sure of the meaning of that permission until I read http://www.m2osw.com/doc_to_do_list_permissions . which makes me think that the permissions need to be re-named to more accurately reflect what they mean. (and I'd prefer to do this, and get them working before I start on the extra permissions).

Here are my suggestions:
- 'administer to do list' (doesn't need to change)
- 'to do list assignment' => 'can be assigned to dos'
- 'create to do list' => "create to do content"
- 'view all to do listings' => "view all to do content"

The latter two mostly because they then fit the drupal defacto permission naming scheme.

Also, the hook_access() implementation should deal with all the permissions, not just "create".

Perhaps it would be better to do it all in one big go?

AlexisWilke’s picture

naught101,

If you are to change the permissions, we'll need an update path too. Which is fine, it's just that we need to somehow make sure our users either go to their permission screen and rearrange the want they want it, or try to fix it by code (I think having an error/warning until you make changes to your permissions would be enough: less work for us and not so much work for the users.)

Now, I think if you're to change the perms, we should also consider doing what you mentioned earlier:

view + create + delete + update

We want all 4 permissions on content so we can have as much granularity as we need.

We want to keep at least one 'administer to do' for the global settings.

'can be assigned to do assignments' sounds good to me, instead of the 'to do list assignment'. The only problem now is that someone who can create or update a To do task should also be considered someone who can be assigned a to do item. Not like the current system work well yet 8-)... On the other hand, there could be one person creating To do entries but never otherwise assigned a to do.

Now, if we are to change all of those, let's make it 100% like the node permissions. In alphabetical order:

'administer to do'
'access to do content'
'can be assigned to do assignments'
'create to do content'
'delete any to do content'
'delete own to do content'
'edit any to do content'
'edit own to do content'

What do you think?

Thank you.
Alexis

naught101’s picture

Yep, sounds good.

I would change "access to do content" to "access all to do content"
I would also add the permission '"edit assigned to do content".

Are we assuming that any user who can edit, who owns, or who is assigned to a to do should be able to mark it started/finished/etc. or should there be another permission "change assigned to do status"? (or "increment..."?)

I think we should just assume for now that creators/updaters can be assigned to to dos. Perhaps in the future there can be more granularity in who can be assigned to what to dos. for example, perhaps there could be a permission "assign to dos to anyone" (which works in the opposite direction to the current "assign" to do).

I'll get started :)

naught101’s picture

Also, the name of the module is "to do list", right? so the admin permission should remain as "Administer to do list", yeah?

AlexisWilke’s picture

Yes, we should keep 'administer to do list'.

I also thought of that problem... being able to click on the buttons if you're assigned a To do list item would make sense to me too. And since this module is supposed to be relatively simple to use, adding too many permissions is not a good solution, I think. So people who have Edit, Update or Assign rights should see the buttons and be able to click on them. And with time we could also add a few more buttons... to go to other statuses (such as Canceled or Wait statuses.)

Thank you.
Alexis

naught101’s picture

Status: Active » Needs work
StatusFileSize
new10.66 KB

Getting there. I've now got it working so that all the permissions listed above work. a couple of things:

What is the implementation of hook_node_access_records() for? it seems to just be doing what hook_access should be doing (and now is, in my version). I commented it out, and nothing seems to have happened. Maybe I'm missing something though.

user/%/* pages are currently accessible by anyone, or at least some of them are. Since this didn't seem to be working for me properly before, I'm not sure exactly what the default behaviour should be. Obviously the % user should have access, but what about users with "adminster to do list" permissions? or "access user profiles", or "administer users"? None of these are really vital, but might be good for them to have access.

It's a bit drastic, but it would make it far, far easier to read if I could move the to_do_menu_array() back into the hook_menu() declaration...

The only thing that I've found that's not working correctly so far after this patch is that the "view all todos" page (user/%/all) is not showing all to dos (for me it's not showing to dos from user 1, I'll have to do some more testing).

So, this patch is only a partial solution, feedback welcome.

jaypan’s picture

hook_node_access_records() and hook_access() do different things. hook_access() is for defining access permissions across a whole content type, while hook_node_access_records() (combined with hook_node_grants()) are used for defining access grants for individual nodes.

hook_access() is independent of db_rewrite_sql(). db_rewrite_sql() only deals with the grants system.

If I have time over the next few days, I'll try to look at the module and bust out a patch to fix the problem, but I haven't seen the code since Alexis took it over, and I have no idea what it looks like right now. I'm also pretty busy, so I can't guarantee that I will have time, but I'll do what I can.

naught101’s picture

Hi Jay, thanks for the info. I'm happy to keep looking at this, so don't stress unless you want to.

I guess the thing I'm stumbling over right now is, why do you need access grants for individual nodes? Maybe I've overlooked something...

AlexisWilke’s picture

Hi naught101,

That's a start... 8-)

The grant system is important to avoid showing nodes to users of systems such as views and organic groups. Other systems do not call the hook_access() function when they read the nodes from the database. Instead, they use the db_sql_rewrite() function that uses the grands saved in the database to determine whether the user who sent the request has the right to see that node.

So to test it, you should be able to use a views that shows a complete list of all the TO DO anyone created. You should then only see the TO DO that you created and whatever others were assigned to you (unless you have more rights and can see other's TO DO items.)

I think that we should be able to do that, although if it does not directly work in TO DO itself, someone can make it work with tac_lite, which, by the way, is a very good example on how to use grands. In tac_lite, the author uses taxonomy terms to protect pages, but the functioning is otherwise what we want.

Thank you.
Alexis

naught101’s picture

Status: Needs work » Active

Holy crap. I just noticed that hook_access doesn't even exist in drupal7 any more, and the way you're going about things (with hook_node_access) is the only way to do it there, which basically makes this patch a backwards step, as it'd all have to be undone come upgrade time (see #537862: Convert hook_access() to hook_node_access() for more flexibility).

I think I'm going to have to do a bit more reading before I understand enough to create a patch for this.

jaypan’s picture

I think I originally set up the grants system to make it so that to do list items were only shown and accessible to people who either created the item, or had the item assigned to them. Otherwise, the item was shown on the front page to everyone, and was also accessible to everyone. If there were ever any private to do list items (such as 'Fire naught101 after work on Friday'!), then it would be no good if everyone could see them!

naught101’s picture

Status: Active » Needs review

Ok, this fixes all the permission problems, as far as I can tell. Needs a review obviously.

Some minor related changes:
- to_do now redirects to user/%/to_do instead of user/%/to_do/all, as it's accessible to more users.
- changed the grand realm 'to_do_user' to 'to_do_assignee' - more descriptive.
- I've left a couple of new comments in, discussing the code.
- Added in two new access callbacks for to_do redirect and autocomplete list

There is still the problem with retrieving the nodes on user/%/to_do/all (doesn't get nodes un-related to author or assignees). I would suggest that we get this patch in, and then work on the listing problem, as it's a slightly different problem, and isn't really affected by this patch.

naught101’s picture

StatusFileSize
new12.63 KB

And now, for your entertainment, THE PATCH!!

sorry.

jaypan’s picture

A few points.

1) hook_access is used for permissions for the whole content type, not individual nodes. You have a lot of logic in hook_access() that is checking individual node access, for example the following:


    case "view":
      if ($node->uid == $account->uid || in_array($account->uid, array_keys($node->users)) || user_access('access all to do content', $account)) {
	return TRUE;
      }
      break;
}

This is what the grants system (hook_node_access_records() and hook_node_grants()) is used for. hook_access() checks the whole content type, the grants system checks individual nodes.

2) case 'view' should never be implemented in hook_access(). The way the grants system works is that if nothing is found in hook_access to give or deny permission for a node, then next it moves onto the grants system. By defining a value in hook_access() for 'view', you never give the grants system a chance to work on the node, and as such any access modules, such as tac_lite or even Organic Groups (which is really just a complex grants system) stop working for viewing the node.

3) hook_access() is not called when rendering teasers. So the rules you have defined for the case of 'view' will be ignored, and even if a person isn't supposed to be able to see a node, they will still be able to see the teaser, though clicking on the link to the node will give them an access denied message. Grants take care of this situation.

4)

//can't we assume it's a to_do? otherwise this hook would not get called.
   if ($node->type == 'to_do') {

No, you can't assume that. Unlike other module based hooks, hook_node_access_records() is called for all nodes, not just the node type defined in the module. This is to allow for the creation of access modules.

I didn't look through the rest of the patch, or check your logic or anything, this is just what I noticed at a quick glance.

Nice contribution though! It looks like you put a lot of work into it.

naught101’s picture

That hook_access stuff is left over from when I thought everything had to be done through hook_access. So basically, hook_grants()/hook_node_access_records should cover the update/delete/view permissions, and they don't need to be in hook_access().

The thing I don't get, is that there's no view permission for users not-related to the node. If they try to access it, hook_grants() won't give them any grants with the correct GID, so they will they be ignored, or denied? Especially since the basic permission 'access content' is going to be ALLOW...

cheers
ned

AlexisWilke’s picture

naught101,

It looks like Jay knows more about this than I... 8-)

The hook_access() 'view' case should return FALSE when access is forbidden and nothing otherwise. That would be my take. Whenever you return TRUE or FALSE you break the loop and that very value is returned.

You have a few tab characters in the patch. Only spaces for Drupal!

You may want to run Coder on your changes before submitting them too. There are a few "mistakes."

> to_do now redirects to user/%/to_do instead of user/%/to_do/all, as it's accessible to more users.

I do agree with this change. It makes sense to send people to their list rather than the website list.

Thank you.
Alexis

AlexisWilke’s picture

We'll have to test, but so far the default was not ALLOW... It was DENY. As we should keep it that way.

Thank you.
Alexis

jaypan’s picture

Actually, 'view' in hook_access() shouldn't even be implemented at all. Returning any value prevents the access system from proceeding onto the grants system, which means that other modules cannot implement their access systems.

This video (and accompanying PDF) where a great learning tool for me when I was trying to figure out the grants system: http://szeged2008.drupalcon.org/program/sessions/using-node-access

naught101’s picture

Ok, this is the same as above, with all the extraneous hook_access stuff removed (it's all duplicated in hook_node_access_records()), and with the elseif/else statement formats fixed up.

I see now that hook_node_access_records() seems to assume DENY, so it doesn't need a DENY for unrelated to-dos. nice.

naught101’s picture

StatusFileSize
new11.69 KB

grrr...

jaypan’s picture

At a glace, that's looking much better. But you're still missing a test for the $node->type in hook_node_access_records(). Without this, you are going to attach your grants to all nodes, not just to do listings.

naught101’s picture

It's still there, look again :)

maybe the author user_load should be inside the if though...

AlexisWilke’s picture

Hi naught101,

I've got a little problem with the following:

       foreach ($node->users as $uid => $ignore) {
+
+        //get user object for uid
+        $user = user_load($uid);
+        $grant_update = (user_access('edit any assigned to do content', $user) || user_access('edit all to do content', $author) || user_access('adminster to do list', $author) );
+        $grant_delete = ( user_access('delete all to do content', $author) || user_access('adminster to do list', $author) );
         if ($uid > 0) {

(1) you use $uid in user_load() before testing whether it is larger than 0.

(2) you called the variable $user which is an overlap of the global variable of the same name (dangerous long term)

(3) you use $author in the user_access() calls...

Other than that, there are some simplifications we could apply here and there, but nothing major.

Btw, shouldn't the hook_access() be changed and use the new permission names? I think that the hook_access() is still important for when you try to create a new to_do node.

Thank you.
Alexis

naught101’s picture

StatusFileSize
new11.79 KB

Good catches :)

All fixed in this one.

AlexisWilke’s picture

naught101,

Okay, I still need to test with an install, but I think we should have an update hook to fix some of the permissions since we're renaming some of them it is easy to just copy the current status of those couple. And we may want to duplicate some selection for some of the permissions in some of the new permissions. That way people can expect the system to more or less work the same way as before without having to fix the permissions.

What do you think?

The permission table:

psql> \d permission
                            Table "public.permission"
 Column |     Type     |                        Modifiers                         
--------+--------------+----------------------------------------------------------
 pid    | integer      | not null default nextval('permission_pid_seq'::regclass)
 rid    | int_unsigned | not null default 0
 perm   | text         | 
 tid    | int_unsigned | not null default 0
Indexes:
    "permission_pkey" PRIMARY KEY, btree (pid)
    "permission_rid_idx" btree (rid)

Thank you.
Alexis

jaypan’s picture

Just a quick note, you will also need to rebuild the node_access permissions when the update is run.

AlexisWilke’s picture

Actually we should not rebuild the node_access(). Instead, we should mark that the access is out of date. Slight difference. There is a flag to set to 1 or something like that. There's probably a function you can call in the core to do that. I've seen that somewhere... 8-)

Thank you.
Alexis

jaypan’s picture

Ahh ya, good point.

naught101’s picture

StatusFileSize
new13.49 KB

ok, update stuff included in this one.

AlexisWilke’s picture

naught101,

A hook_update_N() function is expected to return an array of errors. There are db_...() calls that accept a $ret as the first parameter which is set to an empty array by default and returned at the end of the function.

In any event, whenever possible, use %s and %d and not "$direct_var" for SQL statements. Even though roles and permissions are quite safe, it is better/safer.

Thank you.
Alexis

naught101’s picture

StatusFileSize
new13.6 KB

Ok, this time with return array

Can't use string placeholders because update_sql() doesn't like them. See http://api.drupal.org/api/function/hook_update_N/6

AlexisWilke’s picture

Status: Needs review » Fixed
Issue tags: +access permissions

naught101,

Man! You should be more careful about your spelling! 8-)

Okay. This is checked in. I noticed that (1) some permissions were not spelled correctly, (2) you did not change the corresponding permissions in the to_do_block.* files, (3) there was still a problem with the 'view all to do listings' option, which required a new grant.

Other than that, it was working pretty much as is.

Thank you for your effort. It is now checked in (available in 12h)
Alexis

P.S. you also have a new Navigation feature and a way to automatically go to another page on Mark Finished (see global settings.)

naught101’s picture

Awesome. Thanks Alexis. - I forgot to look at to_do_block...

AlexisWilke’s picture

Status: Fixed » Active

naught101, Jay,

As I was working on another project, I noticed something that caught my eye. The naming convention we just (tried to) fixed is not a 1 to 1 match to what D7 intends. I think it would be better to fix the problem sooner rather than later.

The node accesses are checked by node_node_access() and they clearly use the node type as the name for the access. In other words, if the node type is "to_do", it will use that and not "to do" (space instead of underscore) for the name of the permissions to be checked.

So, I suggest we fix all the permission names with "to_do". This should be easy although in D6 it does not matter much.

Let me know what you think.

Thank you.
Alexis

function node_node_access($node, $op, $account) {
  $type = is_string($node) ? $node : $node->type;

  if (in_array($type, node_permissions_get_configured_types())) {
    if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
      return NODE_ACCESS_ALLOW;
    }

    if ($op == 'update') {
      if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
        return NODE_ACCESS_ALLOW;
      }
    }

    if ($op == 'delete') {
      if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
        return NODE_ACCESS_ALLOW;
      }
    }
  }

  return NODE_ACCESS_IGNORE;
}
capellic’s picture

1.4 was released -- but it doesn't look like this made it in? Please advise as to the stability of the patch -- I'd need to have this functionality before considering using this module.. thanks for all the work!

http://drupal.org/node/997562

UPDATE: 10:25 AM EST

I installed 1.4 and it appears that the patches in this issue have been applied, so this issue is now resolved? BTW, when testing the permissions, I noted that Masquerade doesn't quite work with your module. It was giving me permissions to edit a task that I didn't create and I didn't assign when permissions were:
- administer to do list
- can be assigned to dos
- create to do content
- delete own to do content

AlexisWilke’s picture

capellic,

The naming convention used for the permissions is wrong. "to do" should have an underscore to be compatible with 7.x ("to_do") as it is the exact name of the module. The previous patches were in the previous version as far as I recall, wasn't it?

Is Masquerade using the GRANT system? If so, then know that if you grant permission in one module, that's it, the user has the right to edit/delete/create nodes of that type.

Thank you.
Alexis Wilke