= !BluePrint for Authorization = == User Stories == * A Developer needs to be able to restrict access to a Module * ~~s3.modules in {{{01_modules.py}}}~~ * Add Controller check as well as menu check. * Configure permissions in {{{000_config.py}}} instead of {{{01_modules.py}}}? * Change {{{deployment_settings.modules}}} from a list of strings to a Storage() {{{ # Need to define Roles in dict for visibility by modules before inserted into DB deployment_settings.auth.roles = { 1 : "Administrator", 2 : "Authenticated", .... 6 : "AdvancedJS", } deployment_settings_modules = Storage( gis = Storage( name_nice = "Mapping", description = "Situation Awareness & Geospatial Analysis", readable = None, # All Users (inc Anonymous) can see this module in the default menu & access the controller writable = None, # All Authenticated users can edit resources which aren't specially protected module_type = 2, # Used to locate the module in the default menu resource_readable = Storage( apikey = 1, # This resource is only visible to Administrators ) resource_writable = Storage( layer_js = deployment_settings.auth.roles["AdvancedJS"], # This resource requires the 'AdvancedJS' role to edit (or admin) ) ), ... ) }}} * A Developer needs to be able to restrict access to a Function * ~~Decorator function : @auth.requires_membership("Administrator")~~ * doesn't support OR (we could easily write our own function to do this, though) * A Developer needs to be able to restrict access to a resource * REST controller can be blocked via a Decorator * Full security policy can be invoked, but this is painful (based on protected by default & granted manually) & untested within S3 recently * We could check for what other functions can access data? Sync. Hard to maintain though. * Need a new method: open by default & restricted manually * Needs to be a DAL-level method since not all accesses go via S3XRC. * Use an {{{auth_permission}}} table similar to Web2Py 'full' for tables? * Set within {{{000_config.py}}}, along with module permissions? * A Developer needs to be able to restrict access to a record * Add 2 reusable {{{multiple=True}}} fields to each table which needs this: {{{reader_id}}} & {{{writer_id}}} combined as {{{permissions_id}}} * Full backward compatibility since they default to None * reader_id checked with a new API function (called from shn_read() & shn_list(), but also available for other functions) * combine with the {{{deleted==True}}} check? * makes it easier to then replace that check with an 'inactive' field which is a date instead of a boolean, so that records can be set to expire (as well as giving us easy access to know when a record was deleted) * Option 1: Do the check alongside deleted as part of a big JOIN {{{ def shn_accessible_query(table): """ Modified version of current function from models/01_crud.py """ deleted = (table.deleted == None) try: user_id = auth.user.id _memberships = db.auth_membership memberships = db(_memberships.user_id == user_id).select(_memberships.group_id) except: memberships = None roles = [] for membership in memberships: roles.append(membership.group_id) if 1 in roles: # Admins see all data query = deleted else: # Fields with no restriction accessible = (table.reader_id == None) for role in roles: #accessible = accessible & (table.reader_id == str(role)) & (table.reader_id.like('%d|%' % role)) & (table.reader_id.like('%|%d|%' % role)) & (table.reader_id.like('%|%d' % role)) accessible = accessible & (table.reader_id.like('%|%d|%' % role)) query = deleted & accessible return query def user_function: table = db[tablename] available = shn_accessible_query(table) query = available & query }}} * Advantages: * Combines the deleted into single API call * Single JOIN for optimal DB performance (Assumption needs testing) * Option 2: Do the check in Python after the initial query has returned * Advantage: Might have better performance than complex DB string? * Disadvantage: More records pulled from DB than necessary * writer_id checked with a new API function (called from shn_update(), but also available for other functions) * UI to manage the fields. * We expect relatively few groups per instance, so can use the checkboxes widget? * Have a single checkbox for 'Restrict access' which then opens out the 2 fields. === Specific Examples === * A Person's Contacts shouldn't be visible by default. * Authenticated is OK * Simply add the Authenticated group (2) to the table (or records in the table?) * ~~This requires all authenticated users to be added to the 'Authenticated' group~~ * A Person's Subscriptions shouldn't be visible by default. * Admin or themselves is OK * This requires the default of adding 1 group per user! * We therefore filter these out of our views? * An Admin should be able to restrict access to records to just those within a certain GIS location (e.g. Country or Region) * If access to a record is restricted then access to messages relating to that record should also be restricted * unless routed somewhere visible as well! * onaccept on message routing (tagging) to check if the only tags are on restricted resources...if they are then restrict the message too. * Some tables should be writable by unauthenticated users (writable=|0|) * Need special handling for this in shn_create/shn_update? * Might need to differentiate the 2 (can deposit new but not edit existing) ---- BluePrintAuthenticationAccess BluePrints BluePrints