This is the bug tracker for Photo Organizer.
FS#8 - Better permission hierarchy
Attached to Project:
Photo Organizer
Opened by Solomon Peachy (pizza) - Tuesday, 25 April 2006, 12:12 GMT-4
Last edited by Solomon Peachy (pizza) - Sunday, 06 January 2008, 11:01 GMT-4
Opened by Solomon Peachy (pizza) - Tuesday, 25 April 2006, 12:12 GMT-4
Last edited by Solomon Peachy (pizza) - Sunday, 06 January 2008, 11:01 GMT-4
|
DetailsRight now there are three permissions -- public, private, and "protected", which equates to "public only to all of my clients"
This is pretty lousy; I can certianly envision scenarios where you'd want a client to only see stuff that's specific to that client. To do this now, you have to create separate accounts and mark clients for those specific accounts. I'd like to see a more generic hierarchical user/group model. Only the photo owner can make changes to their images, but the permission model would break down as follows: Permissions would be granted on a per-group basis, and individual users can be members of various groups. "Guest" access would just be another group, and would default to assigned. A permission is inherited; so if "guest" is granted access to the top-level folder, they would be allowed to see everything below it unless a more restrictive permission was specified. This is sort of similar to unix permissions with the "sticky bit" turned on. This gets a little tricky when talking about folders vs albums, as a user may not be allowed to browse the folder, but the image could be included in a public album. When viewing the image from the folder perspective, it would be disallowed, but from the album perspective, it would be allowed. EDIT: see http://po.shaftnet.org/new_permission_model |
This task depends upon
I described something like this before on Balint's pages (or maybe in an email to him, can't remember for sure).
The option I would like is to have two (or more) user accounts that share a single set of photos. It does not matter who uploads them, as both will have all owner rights.
Then again, I might want to share not all my photos with all my friends in my group. So I may have multiple groups for different friends. So photos I would like to share with friends in multiple groups. We could solve this by allowing photos to belong to multiple groups or to create groups of groups.
A group could have read, modify and ownership permissions. So a user belonging to a certain group can be treated as owner for a photo that has the ownership flag opened up on its group flag for this group.
Next we can have permission masks. So we could mask out permission on photos when we watch them trough an album, and have a different mask when reached trough a folder.
This may need more thinking. We might be able to create a bit more simplicity in the permissions structure while still retaining the flexibility we seek above.
create sequence groups_sequence start 1;
create table groups (
identifier integer not null primary key,
description text
);
create table group_memberships (
group integer not null references groups(identifier),
user integer not null references users(identifier)
);
create table folder_permissions (
folder integer not null references folder(identifier),
group integer not null references groups(identifier),
view boolean not null,
read boolean not null,
edit boolean not null,
delete boolean nut null
);
create table album_permissions (
album integer not null references album(identifier),
group integer not null references groups(identifier),
view boolean not null,
read boolean not null,
edit boolean not null,
delete boolean nut null
);
create table photo_permissions (
photo integer not null references photo(identifier),
group integer not null references groups(identifier),
view boolean not null, -- aka preview, basic info
read boolean not null, -- aka "original"
edit boolean not null, -- modify
delete boolean nut null -- remove
);
-- permissions are looked up as follows:
-- best = none;
-- foreach groups_for_user(userid) {
--- if (lookup (photo,group)) store best2;
--- if (best_2 > best) best = best_2; continue;
-- }
-- if (best) return (best);
-- foreach groups_for_user(userid) {
--- folder = folder_for_photo(photo);
--- if (lookup (folder,group)) store best_2;
--- if (best_2 > best) best = best_2;
--- foreach albums_for_photo(photo) {
--- if (lookup(album, group)) store best_2;
--- if (best_2 > best) best = best_2;
--- }
-- }
My plan is to implement this permission function in pl/pgsql, so we can do something like "select * from photo where read_permission(identifier) is true;' Otherwise it would require an insane set of JOINs or many, many database round trips.
* Create one group per user with only that user in the group. (eg "Solomon" --> "Solomon's Group")
* Create one group per user with all of that user's clients in the group. (eg "Solomon" --> "Solomon's Clients")
* For each image, insert a row into photo_permissions for the appropriate group plus rights (owner, access_type, original_image), and an additional row for the client group if clients have access to the image.
* For each folder, insert a row into folder_permissions with the appropriate settings (owner group, access_type)
* For each album, insert a row into folder_permissions with the appropriate settings (owner group, access_type)
Now, from here things get more complicated. Currently, images, folders, and albums are "owned" by a single user. I'd like to change this so that they're owned by a particular group instead -- basically eliminating the "users" field from both table altogether, replacing it with the appropriate group (containing only that one user). Come to think of it, this would be a natural first phase of the project; the auto-creation of groups and the transformation of the "users" field to "owner" in the photo, album, and folder tables.
To give an example: two persons are adding photos, for some reason, the actions of on eof the two need ot be reversed (e.g. remove those photos). It is the very nice to know who uploaded the photos in the first place.
Fot the rest your proposed steps seem ok to me.
The entire permission model will revolve around groups; this should be extended to photo/album ownership too. When you upload an image, it'll be owned by your "personal" group by default -- with the option of assigning its ownership to any group that the user is a member of. You could, of course, assign read/edit/etc rights to other groups and keep it owned by your personal group.
I would like to share thumbnails and previews to the public, but not the original.
If I select "Protected" as access rights, then the general public will not even see the thumbnail. So to allow for that I need to set the access rights to "Public".
However, if I do that, then the public can also download the original. As I understood from the remarks in task "
FS#79— ability to make the original photo available to the public" (http://bugs.shaftnet.org/task/79), the "High Resolution Original" is "Only accessible for authorized users" doesn't make much sense if the public is authorized. In the current setup, I cannot do what I described above.It would make more sense to have the following options for "High Resolution Original":
- Owner
- Owner and Users
- Owner, Users and Clients
- Public
Or possibly toggle each of these separately, but that would fit more in the bigger permission change as described in the previous comments of this task.
Maybe
FS#79should be reopened to change the list as given in this post?Yeah, I know it's stupid. And yeah, it needs to be fixed.
But not for 2.33 (As of yesterday I closed the last blocker), and the new permission model is the main feature I have planned for 2.34.
I have my folder public, the photos in it public and original set to authorized users only. With this setup, anonymous viewers can download the original, just as what is claimed in
FS#79.If I look at your demo site, then for example I see you have set the photo permission of the balloon to original downloadable by _owner_ only. This seems to be the difference.
However, I want my fellow users to be able to download the originals, but not anonymous viewers.
This is not a pressing issue at the moment, so I can live with a fix not going into 2.33. (And if I couldn't I should still shut up, as you've been very helpful ;-)
As this bug has probably been present since the beginning, I agree that it can wait for the new permission model, which will bring along its own pile of bugs. :)
The only addition either now or later that I could see would be to include the option to define which fields could be edited by a particular group. For example, I upload many photos that I take. I would like to allow other users to have the ability to update the caption and the keywords without being able to update the location, date, etc. This could be accomplished with "permission sets". A new table with two columns, field name, and a boolean. Then a foreign key into, most likely, the photo, album and folder permission tables. This field might be able to replace the current boolean "edit" field. This way, if the field is NOT NULL then the users can edit the fields that are in the permission set. There are, of course, lots of othert options that could be used particularly since using a NULL "value" really shouldn't be used to signify anything other than "Unknown".
As well, I completely agree with using pl/pgsql to provide the functionality.
Meanwhile, this notion "permission sets" is interesting, but it's also a complexity that I would prefer to defer. I'm still trying to come up with a permission UI that isn't horribly confusing to users...
A solution is to create "password-protected groups". If a user supplies the appropriate password, they're added to that group for that transaction, and can see any protected folders/images.
Registered users could be permenantly/temporarily added to that group, but guest users would need to maintain those credentials in the PHP session, so I guess there's no point in implementing the former just yet.
I'm about to start coding up the migration functions and PL/pgsql lookup code.
Meanwhile, I've been converting image/folder/album permission lookups to a stored prodecude model; this way to migrate to the new system all we'll need to do is replace the can_access_*() functions and voila. It doesn't handle 'read/write/edit/etc' permissions yet; I may fix up the function call convention to use this.
I need to think about how this change will affect the new permission model proposal, but to my thinking:
(1) Add the notion of user groups, and the ability to manage said groups. (2.35)
(2) Migrate the notion of "user ownership" to "group ownership" to all resources in the database, keeping the current set of permissions. (2.35) This would give us 90% of the remaining desired functionality with little additional complexity.
(3) Split the permissions into separate tables, so that fine-grained access control is possible. (aka the proposed "model") (2.36, if ever) The problem with this is that it's very difficult to manage, and higher-level features (ie clients, shoots, etc) have to automagically set/clear permissions as needed. This is a very complex task.
(I found it just now and have no idea of this specific ACL would be a good pick, it's just an example).
The downside would be that it's php and therefore does not benefit from the performance gains that a stored procedures model would give, but potential upsides would be less coding (probably) and a verified secure model. Maybe there are ready-made solutions for stored procedures as well? I don't know, it just seems like a rather obvious wheel re-invention...
Meanwhile, the real holdup is (as always) the UI work necessary for a complex ACL system to be truly useful. I have mostly-complete mappings to and from the old system (allowing the old UI to be retained) but any of the more advanced features will require additional work. (Actually I haven't updated the model to more easily deal with clients..)
I've come full-circle several times now, and once again I'm thinking it's best to more incrementally upgrade the current permission model. The most crucial aspect is to denormalize the permissions into their own set of tables. Oddly enough, it's also the least invasive from a code perspective. Initially the UI will remain the same; restricting us to the same functionality we have now.
Once that's done, we can remap the old permissions into the new set (ie view/edit/etc) and make the necessary UI changes to expose that.
Once that's done, we can add group support and UI to manage groups.
Once that's done, we enable "multiple permissions" per item, finally exposing the full permission model to the user.
(This question also applies to #327)
Here are the components as I see it:
0) Group editor (create/delete/edit groups -- group edit involves adding/deleting users from a group)
1) Basic permission 'row' editor -- eg "Photo X+Group Y" -> 'Read/Display/!Edit/!Original'
2) Aggregate permission editor -- applies a set of permission 'rows' to a given resource. -- Eg 'Photo X' -> GroupY RD!E!O, GroupZ RE!DO
It can be implemented in javascript; I think that'll be simpler overall.
The photo upload page will have a form field that displays the current permission set. When clicked on, it'll pop up the 'aggregate' editor, which will list the permission rows and allow the user to add/edit/delete them through the row editor, another popup. The final permission set is submitted as a single form input, probably in JSON or something like that...