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
andDELETE
.- 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:
What operations are allowed when the logged in user is the owner
What operations are allowed when the logged in user is a member of the assigned group
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 whould then translate to:
Kalle
may READ, UPDATE and DELETEAny one in the group
Sales
may READ and UPDATEEveryone 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 groupstockholm
. This meansKalle
,Anna
andBill
.Objects created by
Anna
will be accessible to the groupOslo
but also the groupmanagers
asmanagers
is a member ofOslo
. This meansAnna
andBill
.Objects created by
Bill
will be accessible toStockholm
similar toKalle
.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.