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.
parent::init();in our init method. Adding that allows us to remove theself::ALLOW_ANONYMOUS_LIVEaddition and if it was in place to begin with, no change would have been necessary. – Ben Parizek Jul 15 '19 at 15:04init()method then you should always call the parent method withparent::init():) – Ben Croker Jul 15 '19 at 15:25