Last updated: Jun 14 2017
Approvals is a core system for the process of reviewing and approving. Specific approval types are built on top of this. The most common case is content approvals used in the editorial UI to review and approve content items before publishing, and this is also the main reason that the approval system exists. It will be possible to create custom approval types similar to how content approvals are defined but this is currently not supported and is not covered here. The main focus of this topic is content approvals.
An approval definition is a series of steps to be approved in sequence. Each step has one or more reviewers. One reviewer in each step must approve the content before it is moved to the next step in the definition. If the site is a multi-language site, the definition can be configured so that different reviewers can approve different languages in a step.
Definitions are mostly static, and they are created and changed rarely.
A definition has a Uri-based reference to an object, in most cases a content item. A saved definition with a reference can be used for that reference but also for other references, for example, a content item and its descendants. To check if a reference has access to a definition, the resolve method, which searches for a definition, is used. In the case of content approvals, that means traversing the content tree upwards looking for a definition.
Each time a definition is saved, a definition version is created. The latest saved version is the current definition, and also the version returned when asking for a definition through IApprovalDefinitionRepository. It is also possible to get a specific version through the IApprovalDefinitionVersionRepository.
An approval is created when something needs reviewing (for example, a content item before publishing) and is connected to a definition. Multiple approvals can be created for each definition.
Running an approval is the process of stepping through the definition where the reviewers of each step make a decision whether to approve or reject. All steps need to be approved for the approval to be approved. If a step is rejected, then the approval is rejected.
A Uri-based reference identifies an approval and it must have a definition.
A started approval is locked to the definition version that was the current version when the approval was started. It does not switch to a new definition version if the definition is changed, but new approvals will use the new version.
The Content approvals feature is accessed through the EPiServer.Approvals.ContentApprovals namespace which gives access to content versions of the classes ApprovalDefinition and Approval, and also extension methods with ContentReferences in the repository interfaces. The ContentReference is converted to the Uri reference under the hood.
Note: The methods in this namespace should only be used for content approvals. If another approval system for content is used that also wants to identify by ContentReference, it should have its own set of extension methods in its own namespace.
A definition can be created on a content item in a content tree and be used by the descendants of that content item. Use ResolveAsync to find a definition.
Note: A content definition is shared for all versions/languages of a content item. Content approvals are created for a specific content version/language. That means it is possible to have multiple approvals for a content item running at the same time if they have different languages.
A content approval is started by setting the status of a content item to AwaitingApproval. When a content approval is approved, the referenced content item is transitioned to status CheckedIn. If it is rejected, the content item is transitioned to status Rejected.
Before CMS UI 10.10, a reviewer in an approval definition is the name of a user. In release 10.10, we have introduced a role reviewer, where a reviewer can be either the name of a user or a role.
From CMS UI 11.8, it is possible to implement the four-eyes principle. When configuring an approval sequence, you can choose to prevent users from approving their own changes. The default value is false, which allows users to approve their own changes.
When a user approves or rejects a content item, a validation is made to see if the user is part of the step either as a user or as a member of a role. A call to the SecurityEntityProvider is used to validate if a user is part of a role. This will call the underlying user/role provider that is configured for the site (for example, AspNet Identity Provider or Membership Provider).
Note: It is only the role name that is part of the definition, not the users in the role. The validation to see if a user is part of a role is made at the moment it is needed. This means that a user can be added to a role or removed from one and that will affect an already started approval.
Note: The underlying user/role providers can have their own restrictions. For example, that the user must log in for the roles to update.
The normal state flow for a content version that is being approved is:
- CheckedOut. The editor has created a new version that is being edited.
- AwaitingApproval. The editor is done and marks the version as ready for approval.
- Rejected. If some reviewer does not approve the version it transitions to Rejected. After the editor has done changes it can be set for approval again.
- CheckedIn. The version has been approved and is ready for publish.
- Published. The version is published.