Skip to content

Object Access

The feature called Object access solves the problem of restricting access to a specific object. This is different from type level permissions which are handled through policies and ACLs.

Nomenclature

  • Object
    Any instance of a LimeType. Ex a company or a person

  • User
    A user of the system. Not to be confused with a coworker object

  • Owner
    A user that is considered to own a object

  • Group
    A Security group in lime, capable of referencing a number of members (users) and subgroups

  • Operations
    What is allowed to be done with a object. The supported operations are READ, UPDATE and DELETE.

  • Permission
    A definition of what operations are permitted in the defined context

  • Record access
    The older implementation of this type of access restriction

Concept

Every object in lime, independent of type, is assigned a owner, a group and a set of permissions.

The permissions are separated into three different context:

  1. What operations are allowed when the logged in user is the owner
  2. What operations are allowed when the logged in user is a member of the assigned group
  3. What operations are allowed when non of the above apply

The permissions are additive, so that if the user, i.ex. are allowed to read as a result of being the owner in context #1 but does not qualify for context #2, then permission is still granted.

Example:

Consider the following settings for a object:

Owner: Kalle
Group: Sales
Permission:
    owner: READ, UPDATE, DELETE
    group: READ, UPDATE
    other: READ

This would then translate to:

  • Kalle may READ, UPDATE and DELETE
  • Any one in the group Sales may READ and UPDATE
  • Everyone may READ

NOTE:

These permissions apply everywhere (except some legacy use cases) and are always enforced. Take care that any integration user or similar have adequate permissions.

Changing permissions

By default the following values are set when a object is created:

  • Owner
    The current user

  • Group
    The current users default group

  • Permissions
    The default permissions for the limetype of the object

These properties are exposed on the LimeObject and can be manipulated and saved together with the object.

Example:

limeobject.security_model.owner_id = user.id
limeobject.security_model.group_id = group.id
limeobject.security_model.permissions.group.update = True
limeobject.security_model.permissions.other.read = False

uow = application.unit_of_work()
uow.add(limeobject)
uow.commit()

This could i.ex. be called using custom limeobjects

Checking permissions

The security model for a limeobject can be applied to a specific user using the apply method in order to resolve what operations should be permitted to the supplied user. This will be enforced by the system for the logged in user but might also be needed in customizations if a user is impersonated.

Example:

if limeobject.security_model.apply(User).read == True:
    do_the_thing()

Configuration

  • The users default group and the default permissions for a limetype can be configured through the admin pages in the webclient.
  • Groups are managed through LISA or by python script

Example: For a customer who wants their projects to be restricted to the offices of the users but allow managers to see everything.

The users:

Bill:
    info: is a mangager
    default_group: Stockholm
Kalle:
    info: works in Stockholm
    default_group: Stockholm
Anna:
    info: works in Oslo but helps out in Stockholm
    default_group: Oslo

Define groups for the users and their offices:

Managers:
    members:
        - Bill
Stockholm:
    members:
        - managers
        - Kalle
        - Anna
Oslo:
    members:
        - managers
        - Anna

Default permissions for limetypes:

Project.default_permissions:
    owner: None
    group: READ
    other: None

Resolution:

  • Objects created by Kalle will be accessible to the group stockholm. This means Kalle, Anna and Bill.
  • Objects created by Anna will be accessible to the group Oslo but also the group managers as managers is a member of Oslo. This means Anna and Bill.
  • Objects created by Bill will be accessible to Stockholm similar to Kalle.
  • The default permissions for project grants no permissions for the owner or other

Technical details

The database schema for user tables has been extended with the following columns:

  • _sys_owner id of the owner (user)

  • _sys_group id of the group

  • _sys_permissions
    A integer value representing all the permissions

_sys_permissions is the integer representation of a the 9 bits that make up the permissions.

Bit no 8 7 6 5 4 3 2 1 0
Bit value 256 128 64 32 16 8 4 2 1
Access type READ UPDATE DELETE READ UPDATE DELETE READ UPDATE DELETE
Applies to owner owner owner group group group other other other

Example:

  • Allowing everyone to READ but nothing els: 100100100
  • Allowing Only owner to access or modify the record: 111000000
  • Allowing everyone to do everything: 111111111
  • Allowing no-one to do nothing: 000000000

This binary value is then stored in the database as an integer in base 10. That means that the sequence 111111111 would be stored as the value 511.

Separation from Record access

Please note that Object access is fundamentally different from Record access although it solves the same problem. The features can, and should, co-exist if the desktop client is used. Great care should be taken to configure the two in a way that the same rules apply as they are enforced in different parts of the application. Record access being enforced only on read operations in the desktop client and Object access being enforced in most non-legacy use cases.

It is a long term goal to replace record access with object access in all parts of Lime CRM.

Compatibility with Record access

Lime supplies tools to apply object access rules to record access in an attempt to provide consistency while both record access and object access are in play. This is achived by generating record access functions that reflects the object access logic.

The regeneration can be triggered by running:

$limefu object-access configure-legacy-support -a my_app

or, for a specific limetype:

$limefu object-access configure-legacy-support -a my_app -t my_limetype

Please note that this function does nothing if there is an existing function for the type or if a non-function based record access query is configured in LISA.

One can override existing configuration and force regeneration of the sql functions by using the --override flag.