= Access control =

[[PageOutline]]

== Summary of Design ==

=== user-role table ===

Each package or group has a list of users and their roles. These are set from the 'authorization' tab of a package/group (assuming you are an 'admin' for the particular package/group).

Example 1: Package 'paper-industry-stats':
          * David Brent is 'admin'
          * Gareth Keenan is 'editor'
          * Logged-in is 'editor' (This is a special user, meaning 'anyone who is logged in')
          * Visitor is 'editor' (Another special user, meaning 'anyone')

Example 2: The current default for new packages is:
          * the user who creates it is an 'admin'
          * Visitor and Logged-in are both an 'editor' (these are special users

=== role-action table ===

Each role has a list of action priviledges for a package or group.

Currently:
 * An 'admin' can do anything (includes package/group deletion & changing user roles)
 * An 'editor' can edit or read
 * A 'reader' can read


----


== Design Notes ==

When a new package is created you as the creator automatically become admin for it and you can assign which other users have write or read access. NB: by default any user (including someone who is not-logged-in) will be able to read and write.

There are "system" level admins for CKAN who may alter permissions on any package.

=== Use Cases ===

  * A user means someone who is logged in.
  * A visitor means someone who is not logged in.
  * An entity is the subject of a permission (either a user or a pseudo-user)
  * There are roles named: Admin, Reader, Writer

1. A visitor visits a package page and reads the content

2. A visitor visits a package page and edits the package

3+4: Ditto for a user

5. On package creation if done by a user and not a visitor then user is made the 'admin'

6. An admin of a package adds a user as an admin

7. An admin of a package removes a user as an admin

8. Ditto for admin re. editor

9. Ditto for admin re. reader

10. We wish to be able assign roles to 2 specific entire groups in addition to specific users: 'visitor', 'users'. These will be termed pseudo-users as we do not have AC 'groups' as such.

11. The sysadmin alters the assignment of entities to roles for any package

12. A visitor goes to a package where the editor role does not include 'visitor' pseudo-user. They are unable to edit the package.

13. Ditto for user where users pseudo-user does not have editor role and user is not an editor for the package

14+15: Ditto for above re reader role ...

16: Try to edit over REST interface a package for which 'visitor' has Editor role, but no API is supplied. Not allowed.

=== Optional ===

  * Support for access-related groups
  * Support for blacklisting


=== Implementation ===

{{{
      Context
Entity ----> Role

E.g. a user is assigned to a given role for a particular package.

    Context
Role ----> Action/Permission/Capability (on an Object e.g. a Package)
}}}


Package level:

  * Package Roles: admin, editor, reader
  * Entities: xyz@xyz.com (user), pseudo-users 'visitor'
  * Assignment of entities to roles in a given context (the package)
  * Roles give permissions (in a given context)
    * admin -> update assignment to roles, delete package, plus editor
    * editor -> update package plus reader
    * reader -> read package

System level permissions:
  * Roles:??
  * create package 
  * update assignment of system level role

==== Determining permissions ====

{{{
def is_allowed(name, action, context=None):
    user = locate_user(name)
    if not user:
        # they are a visitor ...
   
    if context is None:
        context = 'system'
    contextroles = locate_roles(user, context)
    if context != 'system':
        sysrole =
        if sysrole = 'sysadmin':
            # can do anything ...
            return True
    for role in contextroles:
        # assuming 'ORing' of permissions
        if role.is_allowed(action)
            return True
    if visitor:
        visitor_role = locate_roles(visitor, context)
        # check again
    return False
}}}

==== Initializing Permissions for a Package ====

 when we create a package: visitor is given reader and editor roles automatically (ditto for user)

==== DB Sketch ====

{{{
role enum: admin, editor, reader
action enum: read, edit, delete (to deleted state), purge (destroy), edit-permissions, create
context enum: system, package, tag, group, revision

shortcuts:
sysadmin can do everything on anything
? admin can do everything on the given object


role-action table

role | context | action
admin| package | update
admin| package | update-permissions
admin| package | read
editor| package | update
editor| package | read

user-role table

username.id | context | objectid    | role
xyz.id      | package | geonames.id | admin
rgrp.id     | system  |             | admin
visitor.id  | package | geonames.id | editor 
visitor.id  | package | geonames.id | reader

}}}