User Tools

Site Tools


new_permission_model

This is an old revision of the document!


New Permission Model

(See also 8)

Goals

  • Allow non-owners to make changes
  • Allow individual “clients” access to different sets of photos
  • Allow finer-grained control over original images

This permission model will be group-based; individual users will have a personal “group”, but can exist in any number of groups. “Guests” will have their own special group, and permissions can be assigned to them like any other group.

By default, no groups will have permission to do anything, other than the administrator, who has full access to everything. Permissions are explicitly granted on an image-by-image basis, so if no specific permission is set on the image for a particular group, access will be denied.

This allows “group ownership” of images, folders, etc, and allows for individual user control while allowing them to share a common set of images.

Schema

-- as of 4/26/2007 @12:15pm

create sequence groups_sequence start 0;

-- 'date_added' is set via trigger.

create table groups (
      identifier integer not null primary key,
      description text,
      password text,                         -- group password, if any...
      date_added timestamp without time zone
);

create table group_memberships (
      group_id integer not null references groups(identifier),
      user integer not null references users(identifier),
      owner boolean not null default 'f', -- aka can change permissions
      date_added timestamp without time zone
);

-- setting 'owner' to 't' implicitly sets 'view' to 't' (via trigger)
-- setting 'edit' to 't' implicitly sets 'caption' to 't' (via trigger)

create table photo_permissions (
      photo integer not null references photo(identifier),
      group_id integer not null references groups(identifier),
      -- basic permissions per-image
      owner boolean not null, -- aka can change permissions
      view boolean not null, -- aka thumbnail/preview & basic info
      details boolean not null, -- view all detailed info on image
      original boolean not null, -- access original
      edit boolean not null, -- modify 
      caption boolean not null, -- modify keywords/captions/etc
      delete boolean not null -- remove
);

create table folder_permissions (
      folder integer not null references folder(identifier),
      group_id integer not null references groups(identifier),
      -- default image permissions for this folder
      owner boolean not null, -- aka can change permissions
      edit boolean not null, -- modify 
      delete boolean nut null, -- remove
      list boolean not null, -- display folder & view photo list
      modify boolean not null -- add/remove entries, (photos and/or subfolders)
);

create table album_permissions (
      album integer not null references album(identifier),
      group_id integer not null references groups(identifier),
      -- default image permissions for this album
      owner boolean not null, -- aka can change permissions
      edit boolean not null, -- modify 
      delete boolean nut null, -- remove
      list boolean not null, -- display album & view photo list
      modify boolean not null -- add/remove entries, (photos and/or subalbums)
);

-- Lookup functions go here!


-- post-migration we need to:

drop table client;
drop table client_status;

alter table photo drop users;
alter table folder drop users;
alter table album drop users;

alter table photo drop hide_original;
alter table photo drop access_rights;
alter table folder drop access_rights;
alter table album drop access_rights;

------- not sure about these:

-- alter table users drop type; 
-- drop table user_type;
-- drop sequence user_type_sequence;

-- Don't forget about camera/film/filter/flash/support/scanner/location/clients
-- as they also have user/owners..
-- We also need Indices!

Psuedocode

This code is roughly what we need to do to see if an image/folder/album has the appropriate permissions. Before it goes into production it'll need to be implemented on the database using pl/pgsql.

// type == photo, group, album
// identifier == photo#, group#, album#
// user == userid
// permission == view/original/edit/caption/delete/details list/modify
// returns true if allowed, or false if no match found or denied.
function detail_permission(user, type, identifier, permission) {
      "SELECT g.group_id, p.$permission
        FROM $type_permissions p,
       WHERE p.$type = $identifier
         AND p.group_id in (SELECT 1 UNION SELECT g.group_id from group_memberships g
                            WHERE g.user = $user);"

      foreach ($results as $result) {
              if ($result == true) {
                      return true;
              }
      }
      return false;
}

function user_in_admin_grp($user) {
    $res = "SELECT userid from group_memberships where user = $user and group_id = 0";

    return (num_rows($res) > 0));
}

// view == "folder", "album", "photo", "search", etc...
function permission(user, photo, permission, view) {
      if ($user == NULL) user = "null";
      // members of admin group get all permissions implicitly.
      if (user_in_admin_grp($user)) return TRUE;

      // explicit permission on the photo trumps everything else.
      $stored = detail_permission($user, 'photo',
                                  $photo, $permission);
      return $stored;
}

A few comments:

  • Admin group id is 0. Guest group id is 1. These are fixed.
  • Guest users have a NULL userid, which has to be handled cleanly.
  • All users (and guests) are implicitly members of the 'guests' group.

Migration

The goal of this migration is to transform all existing permissions to the new model.

Set things up
  • Create new tables. (see above)
  • Create group 0, “Admin Users”, and populate it with all admin users.
INSERT INTO groups(identifier, owner_id, description)  
     VALUES (0, 0 , 'Administrators');
INSERT INTO group_memberships(group_id, user)
     SELECT 0 as group_id, u.identifier as user
       FROM users u, user_type t
      WHERE u.type = t.identifier
        AND t.value = 'Administrator';
  • Create group 1, “Guest”
INSERT INTO groups(identifier, owner_id, description)  
     VALUES (1, 0, 'Guests');
  • Create group 2, “Registered Users”, and populate it.
INSERT INTO groups(identifier, owner_id, description)  
     VALUES (2, 2, 'Registered Users');
INSERT INTO group_memberships(group_id, user)
     SELECT 2 as group_id, u.identifier as user
       FROM users u;
The following list needs to be repeated for each user
  • Create a new group of the same name, make only that user a member.

$_user_id = …

$_grp_id = SELECT nextval(groups_sequence);

INSERT INTO groups(identifier, owner_id, description)  
     VALUES (_$grp_id, $_user_id ,'$_username's group');
INSERT INTO group_memberships(group, user) 
     VALUES ($_grp_id, $_user_id);
  • Update ownerships to point to the new group:
UPDATE folder f 
   SET f.owner = $_grp_id
 WHERE f.users = $_user_id;
      
  UPDATE album a
   SET a.owner = $_grp_id
 WHERE a.users = $_user_id;

  UPDATE photo p
   SET p.owner = $_grp_id
 WHERE p.users = $_user_id;  
  • Create a new group called “$_userid's clients”, make all of their clients members.
INSERT INTO groups(identifier, description)  
     VALUES (SELECT nextval(groups_sequence),'$_userid's clients');
INSERT INTO group_memberships(group_id, user)  
     SELECT $_userid_clients_grpid as group_id, c.client
       FROM clients c
      WHERE c.users = $_userid;
  • Create a group for each individual client and add owner and client to it.
For each folder
  • Add row granting owner all rights, including defaults:
INSERT INTO folder_permissions (folder, group_id, edit, caption, delete, list, modify)
     VALUES ($_folderid, $_usergrp, 't', 't', 't', 't', 't');
  • if access_rights is private, stop here.
  • if access_rights is protected (ie clients-only)
INSERT INTO folder_permissions (folder, group_id, edit, caption, delete, list, modify)
     VALUES ($_folderid, $_user_clients_grp, 'f', 'f', 'f', 't', 'f'); 
  • if access_rights is public (ie everyone)
INSERT INTO folder_permissions (folder, group_id, edit, caption, delete, list, modify)
     VALUES ($_folderid, $_guest_grp, 'f', 'f', 'f', 't', 'f'); 
For each album:
  • Add row granting owner all rights, including defaults:
INSERT INTO album_permissions (album, group_id, edit, caption, delete, list, modify)
     VALUES ($_albumid, $_usergrp, 't', 't', 't', 't', 't');
  • if access_rights is private, stop here.
  • if access_rights is protected (ie clients-only)
INSERT INTO album_permissions (album, group_id, edit, caption, delete, list, modify)
     VALUES ($_albumid, $_user_client_grp, 'f', 'f', 'f', 't', 'f'); 
  • if access_rights is public (ie everyone)
INSERT INTO album_permissions (album, group_id, edit, caption, delete, list, modify)
     VALUES ($_albumid, $_guest_grp, 'f', 'f', 'f', 't', 'f'); 
For each photo:
  • Add row granting owner all rights.
INSERT INTO photo_permissions (photo, group_id, view, details, original, edit, caption, delete)
     VALUES ($_photoid, $_usergrp, 't', 't', 't', 't', 't', 't');
  • If access_rights is private, stop here.
  • If access_rights is protected (ie clients only):
INSERT INTO photo_permissions (photo, group_id, view, details, original, edit, caption, delete)
     VALUES ($_photoid, $_user_client_grp, 't', 't', !$_hide_original, 'f', 'f', 'f');
  • If access_rights is public (ie guest access):
INSERT INTO photo_permissions (photo, group_id, view, details, original, edit, caption, delete)
     VALUES ($_photoid, $_guest_grp, 't', 'f', !$_hide_original, 'f', 'f', 'f');

Note2: The hide_original problem 8 79 makes this part difficult; existing behaivor says that “if hide_original is false, everyone who can view the preview can download the original.” but the help text says “allow for authorized users” but there's no mechanism for saying who those users are.

Finally
  1. Drop all necessary columns from the database (see above)
  2. ???
  3. Profit

Source Hax0r (in rough order)

  1. Schema finalization
  2. Migration code for installer
  3. Write PL/pgsql permission lookup code
  4. Port account registration auto-create groups, etc)
  5. Port photo view/description pages
  6. Port folder/album/search/print/export/spool/etc (photo listing) pages
  7. Port folder/album add/edit/delete pages (don't forget password-protection!)
  8. Port photo import/version/etc
  9. Port bulk update
  10. Create Group UI elements
  11. Create Permission UI elements (for photo add and bulk update too!)
  12. Port over equipment/profile pages. (yuck)
new_permission_model.1177615420.txt.gz · Last modified: 2007/04/26 19:23 by pizza