Here are the new constants that Craft 3.2 introduced:
const ALLOW_ANONYMOUS_NEVER = 0;
const ALLOW_ANONYMOUS_LIVE = 1;
const ALLOW_ANONYMOUS_OFFLINE = 2;
By default every controller will have the following property:
protected $allowAnonymous = self::ALLOW_ANONYMOUS_NEVER;
And you can override it in your controller in various ways:
// Allow anonymous access to all actions only when the site is live
public $allowAnonymous = true;
// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview'];
// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];
// Allow anonymous access to the `preview` action only when the site is offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_OFFLINE];
// Allow anonymous access to the `preview` action when the site is live or offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE];
The single pipeline |
is a bitwise OR operator. It compares each bit (a binary digit of 0 or 1) in the integers and returns a new integer with a 1 wherever either numbers had a 1, and a 0 anywhere else (similar to how the ||
operator campares booleans). So the expression self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE
is the same as 1 | 2
and will evaluate to 3
. Here are some examples of how the |
bitwise operator works:
( 0 = 0000) | ( 0 = 0000) => ( 0 = 0000)
( 0 = 0000) | ( 1 = 0001) => ( 1 = 0001)
( 0 = 0000) | ( 2 = 0010) => ( 2 = 0010)
( 1 = 0001) | ( 1 = 0001) => ( 1 = 0001)
( 1 = 0001) | ( 2 = 0010) => ( 3 = 0011)
( 2 = 0010) | ( 2 = 0010) => ( 2 = 0010)
The init()
method of the Craft base controller now normalizes the value as follows:
// Normalize $allowAnonymous
if (is_bool($this->allowAnonymous)) {
$this->allowAnonymous = (int)$this->allowAnonymous;
} else if (is_array($this->allowAnonymous)) {
$normalized = [];
foreach ($this->allowAnonymous as $k => $v) {
if (
(is_int($k) && !is_string($v)) ||
(is_string($k) && !is_int($v))
) {
throw new InvalidArgumentException("Invalid \$allowAnonymous value for key \"{$k}\"");
}
if (is_int($k)) {
$normalized[$v] = self::ALLOW_ANONYMOUS_LIVE;
} else {
$normalized[$k] = $v;
}
}
$this->allowAnonymous = $normalized;
} else if (!is_int($this->allowAnonymous)) {
throw new InvalidConfigException('Invalid $allowAnonymous value');
}
Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96
So if the value is a boolean then false
will be normalized to 0
, whereas true
will be normalized to 1
.
If the value is an array then each key-value pair in the array will be inspected. If the key is an integer then the value is set to 1
, for example:
public $allowAnonymous = ['preview'];
equates to
public $allowAnonymous = [0 => 'preview'];
and is interpreted as
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];
If the key is a not an integer then the key-value pair is left as is.
Here is how $allowAnonymous
is enforced:
// Enforce $allowAnonymous
$isLive = Craft::$app->getIsLive();
$test = $isLive ? self::ALLOW_ANONYMOUS_LIVE : self::ALLOW_ANONYMOUS_OFFLINE;
if (is_int($this->allowAnonymous)) {
$allowAnonymous = $this->allowAnonymous;
} else {
$allowAnonymous = $this->allowAnonymous[$action->id] ?? self::ALLOW_ANONYMOUS_NEVER;
}
if (!($test & $allowAnonymous)) {
// Prevent access unless the user is logged in and has the required permissions to view the site
}
Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176
The single ampersand &
is a bitwise AND operator. It compares each bit in the integers and returns a new integer with a 1 wherever both numbers have a 1, and a 0 anywhere else (similar to how the &&
operator campares booleans). Here are some examples of how the &
bitwise operator works:
( 0 = 0000) & ( 0 = 0000) => ( 0 = 0000) => false
( 0 = 0000) & ( 1 = 0001) => ( 0 = 0000) => false
( 0 = 0000) & ( 2 = 0010) => ( 0 = 0000) => false
( 1 = 0001) & ( 1 = 0001) => ( 1 = 0001) => true
( 1 = 0001) & ( 2 = 0010) => ( 0 = 0000) => false
( 2 = 0010) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 1 = 0001) => ( 1 = 0001) => true
( 3 = 0011) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 3 = 0011) => ( 3 = 0011) => true
By enforcing the condition $test & $allowAnonymous
, we can check that $test
(whether the site is live or offline) and $allowAnonymous
(the permissions granted to the specific controller action) overlap.
More on bitwise operators here.
I'm not sure what the specific issue with your plugin is , but as far as I can tell the only thing that changed in Craft 3.2 was that the ALLOW_ANONYMOUS_OFFLINE
constant was added, allowing for (but not requiring) more specific permissions on controller actions.