📚 Product Knowledge
Access Rights Languages
📖 Docs

Access Rights & Languages - Optimizely CMS 12

Exam Area: Area 1 – Product Knowledge (15%) Reference: https://docs.developers.optimizely.com/content-management-system/docs/access-rights


1. Two Levels of Access Control

CMS 12 has two independent access control mechanisms:

LevelWhat it controls
Role-based (UI access)Whether a user can access Edit View, Admin View
ACL (content-based)What a user can do with a specific content item

2. Content ACL Access Levels

// Defined in EPiServer.Security.AccessLevel enum
public enum AccessLevel
{
    NoAccess   = 0,
    Read       = 1,    // View published content
    Create     = 2,    // Create child content
    Edit       = 4,    // Edit content
    Delete     = 8,    // Delete content
    Publish    = 16,   // Publish content
    Administer = 64,   // Manage access rights
    FullAccess = 255   // All of the above
}

3. ACL Inheritance

Content ACLs inherit downward through the page tree by default:

/StartPage/          [WebEditors: Read,Create,Edit,Publish]
  /News/             [inherits parent]
    /NewsArticle/    [inherits parent — same ACL as News]

If you change /News/ ACL:
  → Right-click → Access Rights
  → Change settings
  → Options: Apply to this item only / Apply to all descendants

4. Language-Specific Access Rights

Access rights can be restricted per language branch:

Admin → Languages → Swedish (sv) → Edit permissions:
  → SwedishEditors: ✅ can edit Swedish content
  → GermanEditors:  ❌ cannot edit Swedish content

This is independent of content ACLs.
A user needs BOTH:
  1. Content ACL (Edit level) on the content
  2. Language permission to edit that language

5. SetAccess / Save ACL in Code

public class AccessRightsService
{
    private readonly IContentSecurityRepository _securityRepo;

    public AccessRightsService(IContentSecurityRepository securityRepo)
    {
        _securityRepo = securityRepo;
    }

    public void GrantPublishToRole(ContentReference contentRef, string roleName)
    {
        var descriptor = (IContentSecurityDescriptor)
            _securityRepo.Get(contentRef).CreateWritableClone();

        descriptor.AddEntry(new AccessControlEntry(
            name:       roleName,
            access:     AccessLevel.Read | AccessLevel.Edit | AccessLevel.Publish,
            entityType: SecurityEntityType.Role));

        _securityRepo.Save(
            contentRef,
            descriptor,
            SecuritySaveType.ReplaceChildPermissions);  // Apply to all descendants
    }
}

6. SecuritySaveType

ValueDescription
NoneApply only to this content item
ReplaceChildPermissionsRecursively apply to all descendants
MergeMerge with existing ACL entries
ReplaceReplace all existing ACL entries

7. Checking Access in Code

// Option 1: IContentAccessEvaluator
bool canPublish = _contentAccessEvaluator.HasAccess(
    content,
    PrincipalInfo.CurrentPrincipal,
    AccessLevel.Publish);

// Option 2: QueryDistinctRoots — get all content roots the user has access to
var roots = _contentRepository.GetChildren<IContent>(
    ContentReference.StartPage,
    new AccessControlFilter(PrincipalInfo.CurrentPrincipal, AccessLevel.Read));

8. Virtual Roles and Language Access

// CreatorRole = virtual role that matches only the creator of the content
// Can be used to allow editors to publish only their own content

[Display(Name = "My Articles")]
public virtual bool AllowSelfPublish { get; set; }

9. Setting Permissions in the Edit View

Edit View → Page Tree → right-click page → "Access Rights"
  → Shows current ACL for this page
  → Add: user or role
  → Set: Read / Create / Edit / Delete / Publish / Administer
  → Apply to: this item only / this item and all descendants

Review Questions

  1. What are the 6 access levels in CMS (from the AccessLevel enum)? (Read, Create, Edit, Delete, Publish, Administer)
  2. Do content ACLs inherit by default? (Yes — child content inherits the parent's ACL)
  3. Can access rights be language-specific? (Yes — via Admin → Languages → per-language permissions)
  4. Which interface reads and saves content ACLs? (IContentSecurityRepository)
  5. What does SecuritySaveType.ReplaceChildPermissions do? (Recursively applies the new ACL to all descendants of the content item)