Skip to main content

Post

Vasyl MartyniukAbout 6 min

Syntax

Post:<post-type-key>:<ID|slug>

The post-type-key has to exactly match the post type key for the registered post type with register_post_typeopen in new window. For example, the regular WordPress posts use the post type key post, and pages - page.

Definition

Redefine how users can access a post. Under post we mean any post, page, media library item or custom post type. Basically any record stored in the wp_posts database table.

Each post is identified internally by three attributes:

  • post type (e. g. post, page, product, attachment).
  • post ID (e. g. 174, 12, 89).
  • slug aka post name (e. g. hello-world, first-post).

When defining the Post resource, you explicitly provide the post type and either post ID or slug. For example if you need to restrict to edit and delete the page "Contact" (ID 78 and slug contact) the following statements do the magic.

{
    "Statement": [
        {
            "Effect": "deny",
            "Resource": "Post:page:78",
            "Action": [
                "Edit",
                "Delete"
            ]
        },
        {
            "Effect": "deny",
            "Resource": "Post:page:contact",
            "Action": [
                "Edit",
                "Delete"
            ]
        }
    ]
}

FYI!

We recommend using post slugs instead of post IDs in your policies to keep them compatible across multiple website environments and to improve policy readability. For example, if you have a local instance of a website, staging, and production, a page with the same name may have different IDs.

The Post resource supports several actions that define more granular access to what users can or cannot do with the post. However, note that the access policy is area-agnostic. It does not differentiate between frontend, backend, and API areas. So if a statement restricts access to read a post, it restricts in all areas. It significantly simplifies and enhances your website access and security management. But, if you need to be more specific about where access controls should be applicable, use conditions.

Read Action

Manage the ability to read or directly access a post. However, note that this does not hide the post link in the search results, list of posts, menu, etc. To hide the post, use the List action.

The following statement restricts to read some posts, pages and custom post types.

{
    "Statement": [
        {
            "Effect": "deny",
            "Resource": [
                "Post:page:members-only",
                "Post:post:how-does-membership-pricing-work",
                "Post:course:introduction-to-ecommerce",
                "Post:course:advanced-email-marketing"
            ],
            "Action": "Read"
        }
    ]
}

You can fine-tune how direct access to a post is protected with additional configurations. For example, you may want to protect your content with a password or show a teaser message instead. Last but not least, maybe you want to redirect the user to a different location. The additional property Metadata in the statement allows you to do so.

The Password metadata declares a password to access the restricted post. You can define the password directly in the statement as a string or dynamically injected with a marker.

In the example statement below, the password is declared as a constant WORDCAMP_PASSWORD in the wp-config.php file, and the post wordcamp-material is password protected between April 1st and April 30th, 2023.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:post:wordcamp-material",
        "Action": "Read",
        "Metadata": {
            "Password": {
                "Value": "${CONST.WORDCAMP_PASSWORD}"
            }
        },
        "Condition": {
            "Between": {
                "${DATETIME.y-m-d}": [
                    "2023-04-01",
                    "2023-04-30"
                ]
            }
        }
    }
}

The Teaser metadata declares the teaser message instead of the post's content. In other words, a user can directly access the post, however, instead of its content, they see the defined teaser message. The message can be plain text or rich HTML with embedded shortcodesopen in new window.

The common use case for the teaser message is to show the end user that certain content is available for logged-in users or paid members. In the example statement below the custom callback function ContentLimiter::generateTeaserMessage returns the teaser message instead of the "Introduction to AWS" E-book page if the user does not have the Gold tier.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:ebook:introduction-to-aws",
        "Action": "Read",
        "Metadata": {
            "Teaser": {
                "Value": "${CALLBACK.ContentLimiter::generateTeaserMessage}"
            }
        },
        "Condition": {
            "NotIn": {
                "gold": "(*array)${USER.roles}"
            }
        }
    }
}

The Redirect metadata allows defining the HTTP redirect to a different page or URL. The redirect happens before the post content renders, so the end-user does not see the restricted content.

Currently, we support three different types of redirects:

  • Redirect to a different page by slug or ID.
  • Redirect to a different URL within the allowed hosts (AAM performs the safe redirect with the core WordPress function wp_safe_redirectopen in new window).
  • Trigger a callback function that performs redirect.

If the redirect type is either page or URL, you can set any HTTP redirect code as recommended by MDNopen in new window as following.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:post:postman-testing",
        "Action": "Read",
        "Metadata": {
            "Redirect": {
                "Type": "page",
                "Slug": "authentication-required",
                "Code": 301
            }
        }
    }
}

Similarly, you can use page ID instead of slug.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:post:postman-testing",
        "Action": "Read",
        "Metadata": {
            "Redirect": {
                "Type": "page",
                "ID": 76,
                "Code": 307
            }
        }
    }
}

FYI!

If HTTP redirect code is not provided, the default is 307 (Temporary Redirect).

When you need a custom callback function to redirect, use the callback type instead. It is important that the provided callback function redirects and halts the further code execution with exit or die statement. Otherwise there is a chance that WordPress core will render the protected content.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:post:postman-testing",
        "Action": "Read",
        "Metadata": {
            "Redirect": {
                "Type": "callback",
                "Callback": "MyCustomRedirectFunction"
            }
        }
    }
}

ReadByOthers Action

Premium Feature

Available with the Complete Package.

Similarly to the Read action, managing the ability to read or directly access a post by a user with the same role as the post's author. However, if the policy is applied to everybody, then it truly allows accessing the post only for the author.

The policy below allows reading a post with slug my-personal-journey only by its author.

{
    "Statement": [
        {
            "Effect": "deny",
            "Resource": [
                "Post:post:my-personal-journey"
            ],
            "Action": "ReadByOthers"
        }
    ]
}

List Action

Manage a post visibility. In other words - hide the post, however, allow direct access with the URL. To protect the post from accessing it, use the Read action.

The following statement hides a few pages even if the page is part of any menu or fetched via RESTful API.

{
    "Statement": [
        {
            "Effect": "deny",
            "Resource": [
                "Post:page:discounts",
                "Post:page:123"
            ],
            "Action": "List"
        }
    ]
}

ListToOthers Action

Premium Feature

Available with the Complete Package.

Similarly to List, manage a post's visibility to a user with the same role as the post's author. However, if the policy is applied to everybody, then it truly allows showing the post only for the author.

The following statement hides the "John's Personal Info" page for everybody except him if the statement applies to the default access level.

{
    "Statement": [
        {
            "Effect": "deny",
            "Resource": [
                "Post:page:john-personal-info"
            ],
            "Action": "ListToOthers"
        }
    ]
}

Comment Action

Determine if the commenting feature is enabled for a post. It basically controls the WordPress core native "Allow Comments" feature.

WordPress Allow Comments

In the policy below, we restrict commenting for the post if user is not authenticated.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:post:idea-board",
        "Action": "Comment",
        "Condition": {
            "Equals": {
                "(*bool)${USER.isAuthenticated}": false
            }
        }
    }
}

Edit Action

Manage the ability to edit a post. If denied, the user will not be able to make changes to the post through the backend or RESTful API unless conditioned differently.

The following statement restricts a user from editing the page with ID 45.

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:page:45",
        "Action": "Edit"
    }
}

EditByOthers Action

Premium Feature

Available with the Complete Package.

Similarly to the Edit action, managing the ability to edit a post by a user with the same role as the post's author. However, if the policy is applied to everybody, then it truly allows editing the post only by the author.

The example statement below denies editing a couple pages that all editors except those who created them.

{
    "Statement": {
        "Effect": "deny",
        "Resource": [
            "Post:page:sample-page-one",
            "Post:page:sample-page-two"
        ],
        "Action": "EditByOthers"
    }
}

Delete Action

Manage the ability to delete a post (move to trash). If denied, the user will not be able to delete a post through the backend or RESTful API unless conditioned differently.

The following statement restricts a user to delete the page "Home".

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:page:home",
        "Action": "Delete"
    }
}

DeleteByOthers Action

Premium Feature

Available with the Complete Package.

Similarly to the Delete action, managing the ability to delete a post by a user with the same role as the post's author. However, if the policy is applied to everybody, then it truly allows deleting the post only by the author.

The example statement below denies deleting a couple posts that all users except those who created them.

{
    "Statement": {
        "Effect": "deny",
        "Resource": [
            "Post:post:science-introduction",
            "Post:page:history-introduction"
        ],
        "Action": "DeleteByOthers"
    }
}

Publish Action

Manage the ability to publish a draft post. If denied, the user will not be able to publish a draft the post through the backend or RESTful API unless conditioned differently. However, if the post is already published, the action has no effect.

The following statement restricts a user from publishing the page "Discounts".

{
    "Statement": {
        "Effect": "deny",
        "Resource": "Post:page:discounts",
        "Action": "Publish"
    }
}

PublishByOthers Action

Premium Feature

Available with the Complete Package.

Similarly to the Publish action, managing the ability to publish a draft post by a user with the same role as the post's author. However, if the policy is applied to everybody, then it truly allows publishing a draft post only by the author.

The example statement below denies publishing a post by all users except author.

{
    "Statement": {
        "Effect": "deny",
        "Resource": [
            "Post:post:science-introduction"
        ],
        "Action": "PublishByOthers"
    }
}