Updating owner permissions across entire gallery

Spack

Joined: 2008-08-31
Posts: 32
Posted: Tue, 2009-05-19 13:16


Gallery version (not just "2"): 2.3 core 1.3.0
PHP version (e.g. 5.1.6): 5.2.4
PHPInfo Link (see FAQ): (private test server)
Webserver (e.g. Apache 1.3.33): Apache 2.2.8
Database (e.g. MySql 5.0.32): MySQL 5.0.51a
Activated toolkits (e.g. NetPbm, GD): netpbm, gd
Operating system (e.g. Linux): Ubuntu Server 8.04
Browser (e.g. Firefox 2.0): IE8

I'm trying to figure out if it's possible to update the owner permissions for every album in the gallery recursively. For instance, in my gallery root I have over 100 albums, each owned by a registered user. I want to be able to recursively add the Edit Item permission to every album and item but not change the ownership. If I go to the root album and choose Edit Permissions it will only let me set the permissions for a specific user, there doesn't seem to be a way to tell it to change permissions for the existing owner and so this would result in a specific user or group having Edit Item permissions on every album and item rather than the existing defined owner.

Is there a way to do this in the core code? Or is there an existing module to manage this? I've even been looking at possibly writing a MySQL query to perform the updates on the tables direct but this may end up trashing my gallery if I don't get it quite right.

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Tue, 2009-05-19 14:02

No, this has been a gripe of mine for years. Unfortunately Gallery does not have a concept of "Owner/Creator" like you may have seen with NTFS permission on Windows.

As for writing a script or something to do this, this is where I'd start:
http://codex.gallery2.org/Gallery2:How_To_Write_Scripts

____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Tue, 2009-05-19 15:16

Gallery does have a concept of owner - it's the very first option in the permissions page, in both Gallery 1 and 2. Each item in Gallery 2 has an ownerid value in the database too. Any new album created also has it's owner set to the user that created it. I've dug around in the database enough to have written some SQL to be able to reassign ownerships in my G1 migration (all user info is lost because my G1 is embedded in PHP Nuke).

I'll try and write a module to handle this and make it available to anyone who wants it, but I didn't want to start on it if someone had already done it (or it was already in the core).

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Tue, 2009-05-19 16:01
Quote:
Gallery does have a concept of owner

Of "owner" of an item, yes, but of an "owner/creator" permission, no, it does not. Same for Gallery 1 and most likely Gallery 3. If you have access to a Windows with NTFS and the ability to set permissions on files (not XP Home and maybe Vista Home). You'll see what I'm talking about.

If there was an "Owner/Creator" permission setting then all you'd have to do at your top level album is assign the "Owner/Creator" the Edit Permissions setting (or what ever you want to do) and you're done. The owner of the item will get the permissions without re-assigning the owner of the item.
____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Tue, 2009-05-19 16:37

But G1 does have a sort of owner permission handling, see the Owner Permissions tab in the properties for an album/item. You can set it so that the owner of an item can always edit or delete it, and this does work because on my existing G1 (1.5) site users can happily add and remove items that they have "ownership" of even though the permissions page has these permissions set to NOBODY .

However, I do see that I partly misunderstood your reply. It's a shame that G2 doesn't have even the simple option that G1 provides for this.

And I know what NTFS permissions are, I've been a Windows network admin and developer for 15 years :)

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Tue, 2009-05-19 17:00

Ah, I forgot about that in G1, it's been a very long time since I've used G1 ;)

It is a shame yes, but G1 and G2 share nothing but a name. G2 and G3 will be much the same. Sure there may be features that are the same and basic functionality is similar, but G2 is a completely different program from G1 as G3 will be from G2.

If you do hack the core code or make a module to do this, I'd love to see it.

Do keep in mind the more permissions you set in G2, the more performance could be impacted:
http://codex.gallery2.org/Gallery2:ACL_Performance

____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Tue, 2009-05-19 18:03

I think what I might do is have a group called Owners with no users in it, and assign permissions to that group as required. Then I can modify the appropriate permissions method in the core API (I think GalleryUserHelper_simple::hasItemPermission is the place to do this) so that when checking if a user has permissions it also checks if the user is the owner of the item and the Owners group for the appropriate permission, and if so then returns the same response as if the user had that same permission assigned. This way there should only be a few ACLs (on my own gallery there should be just one as all Owners will have the same permissions on their items), and so shouldn't impact the performance too much (and indeed should be better than having 1 ACL per user assigned to every item they own).

If you have any other ideas feel free to suggest them - I'll be messing with this over the next few hours and if I can get it to work I'll post the code changes.

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Thu, 2009-06-11 10:22

I think I managed to kludge a workaround for this, although I need to test it a lot more first to make sure.

I've created a group called ItemOwner - this is used to then set the permissions on the album/item that you want the owner to have. Do not put anyone in this group though; if any user is added they will have the same permissions as the item owner (then again, that might be useful as a non-admin moderator type user).

I then changed the following code in gallery/modules/core/classes/GalleryPermissionHelper_simple.class in the function fetchPermissionsForItems:

	$query = '
	SELECT
	    [GalleryAccessSubscriberMap::itemId],
	    ' . $bitOr . '
	FROM
	    [GalleryAccessMap], [GalleryAccessSubscriberMap]
	WHERE
	    [GalleryAccessSubscriberMap::itemId] IN (' . $itemIdMarkers . ')
	    AND
	    [GalleryAccessSubscriberMap::accessListId] = [GalleryAccessMap::accessListId]
	    AND
	    [GalleryAccessMap::userOrGroupId] IN (' . $entityIdMarkers . ')
	' . $groupBy;

replace with

	$query = '
	SELECT
	    [GalleryAccessSubscriberMap::itemId],
	    ' . $bitOr . '
	FROM
	    [GalleryAccessMap], [GalleryAccessSubscriberMap], [GalleryItem], [GalleryGroup]
	WHERE
	    [GalleryAccessSubscriberMap::itemId] IN (' . $itemIdMarkers . ')
	    AND
	    [GalleryAccessSubscriberMap::accessListId] = [GalleryAccessMap::accessListId]
	    AND
	    ( (
	    [GalleryItem::id] = [GalleryAccessSubscriberMap::itemId] AND [GalleryItem::ownerId] = ' . $userId . '
	    AND 
	    [GalleryAccessMap::userOrGroupId] = [GalleryGroup::id] AND [GalleryGroup::groupName] = \'ItemOwner\'
        ) OR 
	    [GalleryAccessMap::userOrGroupId] IN (' . $entityIdMarkers . ')
        )        
	' . $groupBy;

As you can see, the groupname ItemOwner is hardcoded here - a refinement to this would be to have the group id stored elsewhere in the gallery system and provide an admin interface to set the group that will be used to define the owner permissions, but for my purposes this will do for now. This query change simply adds an additional check to see if the user in the function call is also the item owner, and if so pulls the permissions for this item for the ItemOwner group in addition to the other permissions set on the item.

And that's it. For my entire gallery comprising of around 500 current users I have just one AccessMap table entry per album, and this points to just 4 AccessSubscriberMap rows (1 each for the ItemOwner, Everybody, Registered Users, and Site Admins groups defining their permissions).

If any has any suggestions of refinements I can apply feel free to share. I'm guessing there may be a way to turn this into a module so that the class doesn't need to be modified by I have no idea how to do that yet.

You'll also need to edit gallery/core/ItemAddAlbum.inc to remove the default permissions added when a new album is created.

If you're also using the UserAlbum module then you'll need to modify that to remove any permissions it adds too. Also make sure that you add the ItemOwner group permissions if you don't have these set on your "parent" album.

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Thu, 2009-06-11 15:59

Great! Please add to the wiki:
http://codex.gallery2.org/Gallery2:User_Contributions#Mods.2FPatches
____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Thu, 2009-06-11 16:30

I can't figure out how to add it - I'm logged in to the Gallery site and clicking My Account shows my details, but the wiki page says I'm not allowed to edit the page. Feel free to add this if you like.

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Thu, 2009-06-11 16:33

You've got to create a new account over there. If I get a chance and remember, I'll add it
____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Fri, 2009-06-12 10:36

I've realised that this might not be particularly efficient on a huge gallery, and that it might require a little adjustment. I'm testing using a UNION between the original query and a new one that just looks for the item owner handling, but while it works fine on MySQL5 I'm not sure if it'll work on other databases. There may be an issue with the group by clause where BIT_OR isn't supported, and I want to test that first before I post the changed query.

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Fri, 2009-06-12 11:31

Here's a revision using a UNION - this should be more scaleable, and it also moves the userid and group name into the $data array rather than putting them directly into the $query string.

Replace, from the original version of GalleryPermissionHelper_simple.class

	$query = '
	SELECT
	    [GalleryAccessSubscriberMap::itemId],
	    ' . $bitOr . '
	FROM
	    [GalleryAccessMap], [GalleryAccessSubscriberMap]
	WHERE
	    [GalleryAccessSubscriberMap::itemId] IN (' . $itemIdMarkers . ')
	    AND
	    [GalleryAccessSubscriberMap::accessListId] = [GalleryAccessMap::accessListId]
	    AND
	    [GalleryAccessMap::userOrGroupId] IN (' . $entityIdMarkers . ')
	' . $groupBy;

	$data = $itemIds;
	$data[] = (int)$userId;
	array_splice($data, count($data), 0, $groupIds);

with

	$query = '
	SELECT
	    [GalleryAccessSubscriberMap::itemId],
	    ' . $bitOr . '
	FROM
	    [GalleryAccessMap], [GalleryAccessSubscriberMap]
	WHERE
	    [GalleryAccessSubscriberMap::itemId] IN (' . $itemIdMarkers . ')
	    AND
	    [GalleryAccessSubscriberMap::accessListId] = [GalleryAccessMap::accessListId]
	    AND
	    [GalleryAccessMap::userOrGroupId] IN (' . $entityIdMarkers . ')

	' . $groupBy . '
	    
	UNION

	SELECT
	    [GalleryAccessSubscriberMap::itemId],
	    ' . $bitOr . '
	FROM
	    [GalleryAccessMap], [GalleryAccessSubscriberMap], [GalleryItem], [GalleryGroup]
	WHERE
	    [GalleryAccessSubscriberMap::itemId] IN (' . $itemIdMarkers . ')
	    AND
	    [GalleryAccessSubscriberMap::accessListId] = [GalleryAccessMap::accessListId]
	    AND
	    [GalleryItem::id] = [GalleryAccessSubscriberMap::itemId] AND [GalleryItem::ownerId] = ?
	    AND 
	    [GalleryAccessMap::userOrGroupId] = [GalleryGroup::id] AND [GalleryGroup::groupName] = ?
	    
	' . $groupBy;
    
	$data = $itemIds;
	$data[] = (int)$userId;
	array_splice($data, count($data), 0, $groupIds);
	
	//add the itemids, userid, and group name
	//to the array for insertion for the second part of the union
	$data2 = $itemIds;
	$data2[] = (int)$userId;
	$data2[] = 'ItemOwner';
	array_splice($data, count($data), 0, $data2);
	unset($data2);

So far this is working great on my gallery which has 588 albums and 5640 images, and just 4 rows in the AccessMap table (as I use only group permissions across my entire gallery).

 
SpikeX

Joined: 2009-06-13
Posts: 9
Posted: Wed, 2009-06-17 20:00

Just tested this hack on my G2 installation since I needed the owners of the images to be able to edit their own images, and it worked beautifully. Thanks so much for this.

Just as a side note... it's REALLY stupid that G2 doesn't have an "Owner" group / special user that lets you control what the owner's permissions are. This hack needs to be part of G2 - not a hack.

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16503
Posted: Wed, 2009-06-17 20:28

It sucks yes, but stupid, no. It's actually good. The fewer permissions you have have set, the better. Read all about it here:
http://codex.gallery2.org/Gallery2:ACL_Performance

To make it better the entire permission system would need to be redesigned. That's not going to happen. Major development on G2 is finished. G3 is coming up next and at most only security patches will be forth coming for G2, if there are any. A security firm did a very thorough audit of G2's code prior to 2.3 being released, so it's very likely 2.3 is the last of 2.x.

The developers learned from G1 and created G2, they learned from G2 and are not focused on creating something better for G3:
http://gallery.menalto.com/gallery_3_begins
http://gallery.menalto.com/gallery_3.0_beta_1_released

I haven't dug into G3 very deeply yet, but photo level permissions are gone, see 2nd paragraph under Scope and target audience here Focusing on performance and simplicity.

I'd really suggest taking a look at User Albums. Each user has their own they can deal with.
____________________________________________
Like Gallery? Like the support? Donate now!!! See G2 live here

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Thu, 2009-06-18 04:30

SpikeX, I'm glad it's helped :)

As to User Albums, I use these too so that new users can create their own album - but they also have the added overhead of setting user specific permissions on the album and items, which performance wise isn't going to be great on a huge gallery. I still consider mine to be very small, I've currently got just over 100 users. I've modified the User Album code on my site to remove the user specific permissions it adds and so they just use the inherited group permissions I've set, which also makes it much simpler to adjust the permissions; for instance if 3 months from now I want to allow the item owner to turn ratings on I don't have to go to each root user album and adjust it's permissions, I can just add the permission to the root album and tick the option to change all subalbums :)

I'm still trying to figure out how to turn this into a module so that the core class doesn't need to be changed, but I'm also trying to finalise migration of my site from PHP Nuke with Gallery1 to phpBB3 + Gallery2 (I think I've pretty much got it ready, even down to getting the owners fixed via SQL queries as the Migrate module can't do this with a Nuke embedded G1 import) so it might not be for a few weeks.

 
Spack

Joined: 2008-08-31
Posts: 32
Posted: Wed, 2009-07-29 16:35

Argh! Looks like more edits are needed. My gallery is now live, and I've got a user who couldn't delete one of his own photos. I tracked it down to gallery calling hasItemPermission in GalleryUserHelper_simple, and if the item isn't in the sesssion cache then it doesn't allow it to be removed because it's looking up the access list ids specific to that user. I can't modify fetchAccessListIds because I don't want users to be ItemOwner members for all photos as they'd have permissions on everything, but I think I've worked around this by adding a call to the modified fetchPermissionsForItems function above before the session cache is checked. I need to test this fully yet, but in case anyone else is using this code here's the change.

In function hasItemPermission in GalleryUserHelper_simple.class, before the following line

$cacheKey = "GalleryPermissionHelper::getPermissions($itemId,$userId,$sessionPermissions)";

add the following:

//dcc mod 29/7/09 - item_owner group handling get perms into cache if not already there
$itemIds[] = $itemId;
list ($ret, $permissionsTable) =
GalleryCoreApi::fetchPermissionsForItems($itemIds, $userId, $sessionPermissions);
if ($ret) {
return $ret;
}
//dcc end mod

It's not very efficient doing it this way, but it should hopefully be a short term workaround. I'm looking into the rest of the code to see if there's anywhere else that the permissions are pulled direct rather than using the fetchPermissionsForItems function.

So far everything else seems to be working in my live gallery. It's at http://www.ageofstrife.com/gallery2.php , it's an embedded gallery in phpbb 3 using the NukedGallery integration. 5 ACLs cover 518 albums and 6245 photos, with everyone able to add/edit/delete their own images and albums :)

There are some issues though which might be related to this integration - users get logged out even when they tick remember me which I think is due to the Gallery session handling and using the random gallery image block, and the GalleryEmbed::Logout call when clicking Logout often results in a blank screen so I've had to comment it out until I can pick through the gallery code and figure out why it's not returning an error message if there's a problem. Both of these seem to be caused by the gallery session handling, which also suggests that it's an issue in the embedded calls but the gallery2.php looks to be doing it correctly. If I can't figure it out soon I'll be posting a new topic in this forum asking for help ;)