Table of Contents | ||||
---|---|---|---|---|
|
Prior to version
Status | ||
---|---|---|
|
...
<version>/<domain>/<action>/[modifiers]+
For instance named
Example: A pkgsecupremission
instance is defined with following with properties:
name: “Update owned offline“
...
permission:
v1/objectdata/update/$offline/$selfowner
...
Such permission grants to update instances in an offline status (status is not online and not archived) that he the operating user owns (object.owner == surfer.id
)
Patterns
version: The only available version for patterns is
v1
but introducing a version in patterns will ease further improvements and ease ascendent compatibility. Until new versions are available, just keep in mind that natively handled permissions start with “v1”.domain: The domain of the security rule that this permission will act on. As of
,Status title 2021.3.0 objectdata
andboards
are handledaction: The .
Since
,Status title 2022.3 objectactions
andapplications
domain are handledaction: The action within the domain that this permission will act on. As of
, all actions from objectdata domain can be handled.Status title 2021.3.0
Since
, new actions added to objectdata and objectactions are handled.Status title 2022.3 modifiers: Modifiers will define the context for which the action will be granted. Modifiers vary from one action to the other:
objectdata
insert action: 1 modifier is to be defined: creationMode. Therefore, all insert permissions follow this pattern:
v1/objectdata/insert/<creationMode>
changestatus action: 3 modifiers are to be defined: workflowAction, instanceStatus, ownership. Therefore, all changestatus permissions follow this pattern:
v1/objectdata/changestatus/<workflowAction>/<instanceStatus>/<ownership>
other objectdata actions (delete, i18nfieldstranslate, order, retrievecaption, update, view): 2 modifiers are to be defined: instanceStatus, ownership. Therefore, all those actions follow this pattern:
v1/objectdata/<action>/<instanceStatus>/<ownership>
boards
makepublicboard action: No modifiers - permission is granted or not
shareboard action: 3 modifiers are to be defined: boardVisibility, boardType, ownership,
Modifiers
Each modifier supports specific keywords to finely define the context.
boardVisibility
applications (since
)Status title 2022.3 isavailable action: 1 modifier is to be defined: applicationName. Therefore, all isavailable permissions follow this pattern:
v1/applications/isavailable/<applicationName>
Modifiers
Each modifier supports specific keywords to finely define the context.
boardVisibility
Allows to limit permission based on boards visibility:
...
$online
: An online marked state$archived
: An archived marked state$offline
: A state that is neither marked online not archived$initialstatus
: The initial state of the instance (usually = 2)$anystatus
: Any state<customMetaStatus>
: It is possible to create custom names regrouping several states (see further)
ownership
...
<statusID>
: It is possible to reference a status ID directly (New in
)Status title 2022.3.0
ownership
Ownership allows to limit a permission to the owner property of an instance. 2 7 keywords are available
$selfowner
: User must be the owner of the instance to be able to perform an action$anyowner
: No restriction on ownership$boardcollaborator
: Specific to boards domain - Identify the surfer as a collaborator on a board
Groups pkgsecugroup
Groups allow to centralize multiple permissions on one or many obects, for one or many roles and one or many users.
name: Name of the group
template (boolean): it is convenient to have groups as templates. If template is true, then this instance is not used when resolving groups to which belong a user
activated (boolean): Inactive instances are ignored
objectsselector (string): A structure selector to define which objects are managed by the group. For instance:
assetkeyword
would apply to structure named assetkeyword.#damobject
would apply to any structure having the tagdamobject
(on table level)assetkeyword,#damobject
would apply to structure assetkeyword and to any object having the tag damobject
permissions (childmulti → pkgsecupermission): Permissions granted to users belonging to this group for objects matching objectselector
roles (childmulti →role): All users of selected roles will be members of the group
users (childmulti →user): All users selected will be members of this group
Info |
---|
When defining a group as a template, properties objectsselector, roles and users will not be editable anymore. Creating templates is quite handy as you can think about it as being a group of permissions. It is recommended to create templates such as “[VIEWER]“, [CONTRIBUTOR]” or “[MANAGER]” and to link the typical permissions granted to such a group. |
Note |
---|
To avoid security issues, not all structures are eligible to this mechanism. To be able to grant a permission on a structure, the table MUST have the appropriate tags. |
Note |
---|
It is not possible to add users through their group. Users can only be assigned through their role or directly |
Identifying eligible structures
Structures eligibles to permission granting are marked with one or multiple table tags :
pkg/security/secugroup/<action>
or pkg/security/secugroup/all
this means that to be able to manage view permissions on object foo, foo table configuration must have either pkg/security/secugroup/view
or pkg/security/secugroup/all
Installing the feature
Initializing data
The default NAR file contains the required structures for managing the rights, but to ease migrations, and upgrades, the NAR file does not contains neither permissions definitions nor groups:
Providing default values would force some ids with functional meanings on permissions, groups, roles and eventually users, which is obviously not desired as each projects needs defines different roles, each project will make use of some permissions, but not all the possible ones…
Additionally, delivering configured permissions or groups directly in the NAR file would increase migration complexity as product added permissions and product added groups might come in conflict with projects definitions.
As the whole system only relies on permission strings, a service API is provided to “fill the gap” between actual values in DB and what the product team recommends to create:
/api/packaged/admin/security/update
This API requires Administrators or TestOperators HTTP role to be executed as well as the right to create instances of pkgsecupermission
and pkgsecugroup
This API will check current data in pkgsecupermission
and pkgsecugroup
and create missing data in both structures. Additional information is provided in the swagger UI.
permissions are identified based on the permission string
groups are identified based on their name.
Product team will only provide templates for groups. Product team will always give template names with brackets.
It is recommended to identify project specific template with either a prefix or a suffix
Make usage of the permissions
Permissions handled by the plugin are just a tool allowing to give you more flexibility to your rules, but they can be combined with any project specific rules.
The plugin provides a security macro per domain with the camel-cased name pkg<version><domain>
. These macro will be installed first time you activate the plugin.
You will need to make usage of these macros in your security rules:
For instance on objectdata/update, you can define a single rule “Packaged updates“ with following code:
Code Block |
---|
@pkgV1Objectdata('update') |
Of course you might have more specific rules regarding users' rights on specific objects, but you can always use the macros as a starting point:
For instance, this call is perfectly fine
Code Block |
---|
STRUCTUREHASTAG(objectname, 'damobject')
AND
NBCOMMONELEMENTS(object.someproperty, surfer.someproperty) > 0
AND
@pkgV1Objectdata('update') |
You could even add additional rules like to be able to update an object, you should be allowed to view it. In such a case, the rule could be written as
In objectdata/update, rule “To update, must also be allowed to view”
Code Block |
---|
@pkgV1Objectdata('view') AND @pkgV1Objectdata('update') |
Extending capabilities
Meta statuses definitions
Quite often, you will need to identify workflow statuses as specific, but will not be able to rely on native keywords. For instance, you might want to identify what are the “validation steps” to be able to create permissions that will only apply to those statuses.
You can achieve this by configuring the plugin parameter meta_statuses:
This parameter is JSON. It accepts either null or a JsonObject.
If null, then no specific “metastatuses” are defined.
If a JsonObject, each key is a metaStatus name (exemple: “validationStep”). Associated value can be either
an array of ids that corresponds to ids matching the metastatus
an object for which each key is the name of a workflow or default ; metastatuses will then be resolved based on the workflow name or default if not found
Custom permission resolver
It is possible to configure a specific groovy script to resolve permissions in the surfer:
In plugin, configure custom_permissions_builder to the SAN based groovy script path to your desired implementation. (When saving, the groovy script will be created if not exists, with sample code)
Troubleshooting
Datamodel compliance
You can check the compliance of your data model by accessing
/api/packaged/admin/security/validators/model/html
if first line is green, the data model is good
if first line is yellow, you could improve it
if first line is red, it won’t work
Testing a user
You can check what the plugin has resolved for a user by calling
/api/packaged/admin/security/surfer-keys/<userId>
Cheat sheet
Find for each managed domain / action, the permission pattern
...
domain
...
action
...
permission pattern
...
boards
...
makePublicBoard
...
v1/boards/makepublicboard
...
boards
...
shareBoard
...
v1/objectdata/shareboard/:boardVisibility/:boardType/:ownership
...
objectdata
...
changeStatus
...
v1/objectdata/changestatus/:workflowAction/:instanceStatus/:ownership
...
objectdata
...
delete
...
v1/objectdata/delete/:instanceStatus/:ownership
...
objectdata
...
i18nFieldsTranslate
...
v1/objectdata/i18nfieldstranslate/:instanceStatus/:ownership
...
objectdata
...
insert
...
v1/objectdata/insert/:creationMode
...
objectdata
...
order
...
v1/objectdata/order/:instanceStatus/:ownership
...
objectdata
...
retrieveCaption
...
v1/objectdata/retrieveCaption/:instanceStatus/:ownership
...
objectdata
...
update
...
v1/objectdata/update/:instanceStatus/:ownership
...
objectdata
...
view
...
v1/objectdata/view/:instanceStatus/:ownership
Find available values for modifiers
...
modifier
...
value
...
description
...
boardVisibility
...
$publicboard
...
A board that is not private
...
$privateboard
...
A private board
...
$anyvisibilityboard
...
A board private or not
...
boardType
...
$anyboardtype
...
Any type of board
...
<type>
...
A board of type <type>
...
creationMode
...
$newcreation
...
Only fresh new instances
...
$copycreation
...
Only copies
...
$anycreation
...
Any mode
...
instanceStatus
...
$online
...
An online marked state
...
$archived
...
An archived marked state
...
$offline
...
A state that is neither marked online not archived
...
$initialstatus
...
The initial state of the instance (usually = 2)
...
$anystatus
...
Any state
...
<customMetaStatus>
...
A custom meta state
...
ownership
...
$selfowner
...
User must be the owner of the instance to be able to perform an action
...
$anyowner
...
No restriction on ownership
...
$boardcollaborator
...
$teammember
:
Allows to check whether the surfer is part of the fieldStatus colour Purple title since 2024.1 team
(team is a child multi on user). This requires the structure to have thepkg/security/collaborative
config tag$teamleader
:
Allows to check whether the surfer is denoted in the fieldStatus colour Purple title since 2024.1 jobowner
. This requires the structure to have thepkg/security/collaborative
config tag$teamviewer
:
Allows to check whether the surfer is part of the fieldStatus colour Purple title since 2024.4 viewers
(viewers is a child multi on user). This requires the structure to have thepkg/security/collaborative
config tag.
Caution,$teamviewer
ownership can only be used with view action$public
:
Allows to check whether the instance is NOT private →private field as a child activated = 2. This requires the structure to have theStatus colour Purple title since 2024.4 pkg/security/collaborative
config tag.
Groups pkgsecugroup
Groups allow to centralize multiple permissions on one or many objects, for one or many roles and one or many users.
name: Name of the group
template (boolean): it is convenient to have groups as templates. If template is true, then this instance is not used when resolving groups to which belong a user
activated (boolean): Inactive instances are ignored
objectsselector (string): A structure selector to define which objects are managed by the group. For instance:
assetkeyword
would apply to structure named assetkeyword.#damobject
would apply to any structure having the tagdamobject
(on table level)assetkeyword,#damobject
would apply to structure assetkeyword and to any object having the tag damobject
permissions (childmulti → pkgsecupermission): Permissions granted to users belonging to this group for objects matching objectselector
roles (childmulti →role): All users of selected roles will be members of the group
users (childmulti →user): All users selected will be members of this group
Info |
---|
When defining a group as a template, properties objectsselector, roles and users will not be editable anymore. Creating templates is quite handy as you can think about it as being a group of permissions. It is recommended to create templates such as “[VIEWER]“, [CONTRIBUTOR]” or “[MANAGER]” and to link the typical permissions granted to such a group. |
Note |
---|
To avoid security issues, not all structures are eligible to this mechanism. To be able to grant a permission on a structure, the table MUST have the appropriate tags. |
Note |
---|
It is not possible to add users through their group. Users can only be assigned through their role or directly |
Identifying eligible structures
Structures eligibles to permission granting are marked with one or multiple table tags :
pkg/security/secugroup/<action>
or pkg/security/secugroup/all
this means that to be able to manage view permissions on object foo, foo table configuration must have either pkg/security/secugroup/view
or pkg/security/secugroup/all
Installing the feature
Initializing data
The default NAR file contains the required structures for managing the rights, but to ease migrations, and upgrades, the NAR file does not contains neither permissions definitions nor groups:
Providing default values would force some ids with functional meanings on permissions, groups, roles and eventually users, which is obviously not desired as each projects needs defines different roles, each project will make use of some permissions, but not all the possible ones…
Additionally, delivering configured permissions or groups directly in the NAR file would increase migration complexity as product added permissions and product added groups might come in conflict with projects definitions.
As the whole system only relies on permission strings, a service API is provided to “fill the gap” between actual values in DB and what the product team recommends to create:
/api/packaged/admin/security/update
This API requires Administrators or TestOperators HTTP role to be executed as well as the right to create instances of pkgsecupermission
and pkgsecugroup
This API will check current data in pkgsecupermission
and pkgsecugroup
and create missing data in both structures. Additional information is provided in the swagger UI.
permissions are identified based on the permission string
groups are identified based on their name.
Product team will only provide templates for groups. Product team will always give template names with brackets.
It is recommended to identify project specific template with either a prefix or a suffix
Make usage of the permissions
Permissions handled by the plugin are just a tool allowing to give you more flexibility to your rules, but they can be combined with any project specific rules.
The plugin provides a security macro per domain with the camel-cased name pkg<version><domain>
. These macro will be installed first time you activate the plugin.
You will need to make usage of these macros in your security rules:
For instance on objectdata/update, you can define a single rule “Packaged updates“ with following code:
Code Block |
---|
@pkgV1Objectdata('update') |
Of course you might have more specific rules regarding users' rights on specific objects, but you can always use the macros as a starting point:
For instance, this call is perfectly fine
Code Block |
---|
STRUCTUREHASTAG(objectname, 'damobject')
AND
NBCOMMONELEMENTS(object.someproperty, surfer.someproperty) > 0
AND
@pkgV1Objectdata('update') |
You could even add additional rules like to be able to update an object, you should be allowed to view it. In such a case, the rule could be written as
In objectdata/update, rule “To update, must also be allowed to view”
Code Block |
---|
@pkgV1Objectdata('view') AND @pkgV1Objectdata('update') |
Adapting PreparedWhere
As of
Status | ||
---|---|---|
|
AbstractPreparedWhereBusinessService
to resolve bases according to users’ given permissions:2 contexts are available:
base_pkgsecurity_view
will return aPreparedWhere
following user’s given VIEW permissionsbase_pkgsecurity_update
will return aPreparedWhere
following user’s given UPDATE permissions
Extend existing bases
It is possible to automatically extend some bases with the ones provided by the plugin:
Set plugin parameter
extend_bases
totrue
Make sure
extended_bases
references to the coma-separated list of bases you want the plugin to extend (base_list,base_search
by default)Make sure
extend_with
references the coma-separated list of bases you want to use to extend theextended_bases
list of bases (base_pkgsecurity_view
by default)
By doing so, you will be instructing the plugin to extend base_list
and base_search
with base_pkgsecurity_view
for each object.
Note |
---|
Caveats This configuration will work well for all objects handled by the plugin in terms of security (all objects marked with a tag
|
In order to work around those issues, you can configure extended_bases_config
to manage in a better way the configuration: this parameter accepts either null
(no config) or a JsonArray
to overwrite base extensions settings on objectselector + role context:
Each entry of the JsonArray MUST be a JsonObject that accepts the following properties:
objectSelector
: A selector for object(s) impacted by the item. If not provided or null, all objects are impactedroles
: AJsonArray
ofString
referencing the roles that are impacted by this item. If null or not provided, all roles will be impactedextendedBases
: AJsonArray
ofString
referencing the bases (contextnames) for which extension is changed. If null or not provided, the value from plugin parameterextended_bases
is used.extendWithBases
: AJsonArray
ofString
referencing the bases that should be added to extendedBases to extend them. If null or not provided, the value from plugin parameterextend_with
is used.
During the resolution of a base, JsonObjects
are processed in given order. If the JsonObject
matches the context (objectsSelector
, roles
from surfer, currentResolvedBase is part of extendedBases
, then the bases used for extending the base is redefined to value of extendWithBases
)
Examples
Preventing bases for Developers to be extended
Given that
extend_bases = true
extended_bases = base_list,base_search
extend_with = base_pkgsecurity_view
To deactivate the extension for all objects for role 4 (and therefor to be able to see any instance), you can define the config to:
Code Block |
---|
[
{
"roles": [
"4"
],
"extendWithBases": []
}
] |
for role 4, you want to redefine extendWithBases to an empty list
Preventing some objects bases to be extended for some roles
This can be quite handy if you don’t want to allow some objects to be accessible to permissions management:
Code Block |
---|
[
{
"objectsSelector": "user",
"roles": [
"27"
],
"extendWithBases": []
}
] |
Make usage of those bases programatically
You can easily make use of those context to augment base_list
, base_edit_list
, base_search
… in your project accordingly:
Code Block | ||
---|---|---|
| ||
import com.noheto.extensions.interfaces.services.AbstractPreparedWhereBusinessService;
import com.noheto.preparedwhere.PreparedWhereService;
import wsnoheto.engine.*;
public class ProjectExtendedBaseList extends AbstractPreparedWhereBusinessService {
@Override
public PreparedWhere getPreparedWhere(String contextName, CTSurfer surfer, String objectName, IObjectStructureReadOnly struct, IObjectTableReadOnly table) throws PreparedWhereException {
PreparedWhere pwProjectConstraints = PreparedWhere.load("");
// ... your project specific constraint
// retrieve a PreparedWhere compliant with surfer's permission
// note that if user has no permission OR if the object
// is not compliant with security, you will get 0=1 constraint
PreparedWhere pwPackagedSecurity = PreparedWhereService.getInstance()
.getPreparedWhere("base_pkgsecurity_view", surfer, objectName);
return pwProjectConstraints.and(pwPackagedSecurity);
}
} |
Extending capabilities
Meta statuses definitions
Quite often, you will need to identify workflow statuses as specific, but will not be able to rely on native keywords. For instance, you might want to identify what are the “validation steps” to be able to create permissions that will only apply to those statuses.
You can achieve this by configuring the plugin parameter meta_statuses:
This parameter is JSON. It accepts either null or a JsonObject.
If null, then no specific “metastatuses” are defined.
If a JsonObject, each key is a metaStatus name (exemple: “validationStep”). Associated value can be either
an array of ids that corresponds to ids matching the metastatus
an object for which each key is the name of a workflow or default ; metastatuses will then be resolved based on the workflow name or default if not found
Custom permission resolver
It is possible to configure a specific groovy script to resolve permissions in the surfer:
In plugin, configure custom_permissions_builder to the SAN based groovy script path to your desired implementation. (When saving, the groovy script will be created if not exists, with sample code)
Troubleshooting
Datamodel compliance
You can check the compliance of your data model by accessing
/api/packaged/admin/security/validators/model/html
if first line is green, the data model is good
if first line is yellow, you could improve it
if first line is red, it won’t work
Testing a user
You can check what the plugin has resolved for a user by calling
/api/packaged/admin/security/surfer-keys/<userId>
You can check the bases resolved by the plugin for a user by calling
/api/packaged/admin/security/surfer-bases/<userId>
New in 2022.3.0
New handled actions in objectdata
domain
Following actions were added to objectdata
domain and can be handled with @pkgV1Objectdata
broadcastVideo
defineVideoPoster
editPicture
editVideoChapters
editVideoSubtitles
embed
manageVideoCallToActions
manageVideoRolls
order
sliceVideo
All these actions follow the pattern v1/objectdata/<action>/<instanceStatus>/<ownership>
New handled domains
From
Status | ||
---|---|---|
|
Domain applications
applications
domain defines one action isAvailable
allowing to grant access on an application base on a code (parameter applicationname
).
By default, the BackOffice application has for code bo
, portal front-end has for code portal
, Office pickers have for code officeassetpicker
and all other pickers have for code assetpicker
.
Permissions for this action have the pattern:
v1/applications/<action>/<applicationname>
. As only one action is available as of
Status | ||
---|---|---|
|
v1/applications/isavailable/<applicationname>
The macro @pkgV1Applications
handles permissions checks. Note that as others PACKAGED_Security macros, the action ne is to be passed as an argument:
Code Block |
---|
@pkgV1Applications('isAvailable') |
Domain objectactions
objectactions
domain allows to define permissions on actions on an object type, with no restriction on an instance. Its primary goal is to help displaying actions triggers targeting multiple objects.
PACKAGED_Security plugin provides a new macro for handling objectactions
domain actions: @pkgV1ObjectActions
. As for @pkgV1Objectdata
, this macro takes one argument: the name of the action to test permissions for.
@pkgV1ObjectActions
is defined to check for an objectname
if some permissions were given to a user for the corresponding objectdata
action → No additional configuration is required on objectactions
: an action from objectactions domain will be granted if some permissions were given on objectdata
Equivalences
objectactions action domain | tested objectdata action | |
---|---|---|
create | insert | Check for existence of either
|
damimport | ||
massimport | ||
multiupdate | update | Check for existence of |
datavaluespicker | ||
broadcastVideo | broadcastVideo | Check for existence of |
defineVideoPoster | defineVideoPoster | Check for existence of |
delete | delete | Check for existence of |
editPicture | editPicture | Check for existence of |
editVideoChapters | editVideoChapters | Check for existence of |
editVideoSubtitles | editVideoSubtitles | Check for existence of |
embed | embed | Check for existence of |
manageVideoCallToActions | manageVideoCallToActions | Check for existence of |
manageVideoRolls | manageVideoRolls | Check for existence of |
order | order | Check for existence of |
sliceVideo | sliceVideo | Check for existence of |
Cheat sheet
Find for each managed domain / action, the permission pattern
domain | action | permission pattern |
---|---|---|
applications | isAvailable |
|
boards | makePublicBoard |
|
boards | shareBoard |
|
objectdata | broadcastVideo |
|
objectdata | changeStatus |
|
objectdata | defineVideoPoster |
|
objectdata | delete |
|
objectdata | editPicture |
|
objectdata | editVideoChapters |
|
objectdata | editVideoSubtitles |
|
objectdata | embed |
|
objectdata | i18nFieldsTranslate |
|
objectdata | insert |
|
objectdata | manageVideoCallToActions |
|
objectdata | manageVideoRolls |
|
objectdata | order |
|
objectdata | retrieveCaption |
|
objectdata | sliceVideo |
|
objectdata | update |
|
objectdata | view |
|
Find available values for modifiers
modifier | value | description | ||||
---|---|---|---|---|---|---|
applicationName |
| Name of the application (BackOffice → | ||||
boardVisibility |
| A board that is not private | ||||
| A private board | |||||
| A board private or not | |||||
boardType |
| Any type of board | ||||
| A board of type | |||||
creationMode |
| Only fresh new instances | ||||
| Only copies | |||||
| Any mode | |||||
instanceStatus |
| An online marked state | ||||
| An archived marked state | |||||
| A state that is neither marked online not archived | |||||
| The initial state of the instance (usually = 2) | |||||
| Any state | |||||
| A custom meta state | |||||
| The ID of a status | |||||
ownership |
| User must be the owner of the instance to be able to perform an action | ||||
| No restriction on ownership | |||||
| Specific to boards domain - Identify the surfer as a collaborator on a board | |||||
| User is referenced on Requires
| |||||
| User is referenced on Requires
| |||||
| User is referenced on Requires
| |||||
| Instance has property Requires
| |||||
workflowAction |
| Publishing action: performing a workflow action that will move the instance in an online marked state | ||||
| Archiving action: performing a workflow action that will move the instance in an archived marked state | |||||
| Forward action: performing an action marked forward, and that will not lead to online or archived marked state. | |||||
| Backward action: performing an action NOT marked forward, and that will not lead to online or archived marked state. | |||||
| Any process action: performing that will not lead to online or archived marked state. | |||||
| Any workflow action (including publishing and archiving actions) | |||||
| If none of the above keywords, the action name is taken as is and resolved base on the instance’s workflow |
Further reading
Rights and roles To learn how the default application is configured in terms of roles and permissions
Roles & Permissions To learn how you can use a dedicated user interface to configure roles and permissions