Answers.Body: <p>Here are the new constants that Craft 3.2 introduced:</p>
  
  <pre><code>const ALLOW_ANONYMOUS_NEVER = 0;
  const ALLOW_ANONYMOUS_LIVE = 1;
  const ALLOW_ANONYMOUS_OFFLINE = 2;
  </code></pre>
  
  <p>By default every controller will have the following property:</p>
  
  <pre><code>protected $allowAnonymous = self::ALLOW_ANONYMOUS_NEVER;
  </code></pre>
  
  <p>And you can override it in your controller in various ways:</p>
  
  <pre><code>// 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' =&gt; self::ALLOW_ANONYMOUS_LIVE];
  
  // Allow anonymous access to the `preview` action only when the site is offline
  public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_OFFLINE];
  
  // Allow anonymous access to the `preview` action when the site is live or offline
  public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE];
  </code></pre>
  
  <p>The single pipeline <code>|</code> 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 <em>either</em> numbers had a 1, and a 0 anywhere else (similar to how the <code>||</code> operator campares booleans). So the expression <code>self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE</code> is the same as <code>1 | 2</code> and will evaluate to <code>3</code>. Here are some examples of how the <code>|</code> bitwise operator works:</p>
  
  <pre><code>( 0 = 0000) | ( 0 = 0000) =&gt; ( 0 = 0000)
  ( 0 = 0000) | ( 1 = 0001) =&gt; ( 1 = 0001)
  ( 0 = 0000) | ( 2 = 0010) =&gt; ( 2 = 0010)
  ( 1 = 0001) | ( 1 = 0001) =&gt; ( 1 = 0001)
  ( 1 = 0001) | ( 2 = 0010) =&gt; ( 3 = 0011)
  ( 2 = 0010) | ( 2 = 0010) =&gt; ( 2 = 0010)
  </code></pre>
  
  <p>The <code>init()</code> method of the Craft base controller now normalizes the value as follows:</p>
  
  <pre><code>// Normalize $allowAnonymous
  if (is_bool($this-&gt;allowAnonymous)) {
      $this-&gt;allowAnonymous = (int)$this-&gt;allowAnonymous;
  } else if (is_array($this-&gt;allowAnonymous)) {
      $normalized = [];
      foreach ($this-&gt;allowAnonymous as $k =&gt; $v) {
          if (
              (is_int($k) &amp;&amp; !is_string($v)) ||
              (is_string($k) &amp;&amp; !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-&gt;allowAnonymous = $normalized;
  } else if (!is_int($this-&gt;allowAnonymous)) {
      throw new InvalidConfigException('Invalid $allowAnonymous value');
  }
  </code></pre>
  
  <p><em>Source: <a href="https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96" rel="noreferrer">https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96</a></em></p>
  
  <p>So if the value is a boolean then <code>false</code> will be normalized to <code>0</code>, whereas <code>true</code> will be normalized to <code>1</code>.</p>
  
  <p>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 <code>1</code>, for example:</p>
  
  <pre><code>public $allowAnonymous = ['preview'];
  </code></pre>
  
  <p>equates to</p>
  
  <pre><code>public $allowAnonymous = [0 =&gt; 'preview'];
  </code></pre>
  
  <p>and is interpreted as </p>
  
  <pre><code>public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_LIVE];
  </code></pre>
  
  <p>If the key is a not an integer then the key-value pair is left as is.</p>
  
  <p>Here is how <code>$allowAnonymous</code> is enforced:</p>
  
  <pre><code>// Enforce $allowAnonymous
  $isLive = Craft::$app-&gt;getIsLive();
  $test = $isLive ? self::ALLOW_ANONYMOUS_LIVE : self::ALLOW_ANONYMOUS_OFFLINE;
  
  if (is_int($this-&gt;allowAnonymous)) {
      $allowAnonymous = $this-&gt;allowAnonymous;
  } else {
      $allowAnonymous = $this-&gt;allowAnonymous[$action-&gt;id] ?? self::ALLOW_ANONYMOUS_NEVER;
  }
  
  if (!($test &amp; $allowAnonymous)) {
      // Prevent access unless the user is logged in and has the required permissions to view the site
  }
  </code></pre>
  
  <p><em>Source: <a href="https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176" rel="noreferrer">https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176</a></em></p>
  
  <p>The single ampersand <code>&amp;</code> is a bitwise AND operator. It compares each bit in the integers and returns a new integer with a 1 wherever <em>both</em> numbers have a 1, and a 0 anywhere else (similar to how the <code>&amp;&amp;</code> operator campares booleans). Here are some examples of how the <code>&amp;</code> bitwise operator works:</p>
  
  <pre><code>( 0 = 0000) &amp; ( 0 = 0000) =&gt; ( 0 = 0000) =&gt; false
  ( 0 = 0000) &amp; ( 1 = 0001) =&gt; ( 0 = 0000) =&gt; false
  ( 0 = 0000) &amp; ( 2 = 0010) =&gt; ( 0 = 0000) =&gt; false
  ( 1 = 0001) &amp; ( 1 = 0001) =&gt; ( 1 = 0001) =&gt; true
  ( 1 = 0001) &amp; ( 2 = 0010) =&gt; ( 0 = 0000) =&gt; false
  ( 2 = 0010) &amp; ( 2 = 0010) =&gt; ( 2 = 0010) =&gt; true
  ( 3 = 0011) &amp; ( 1 = 0001) =&gt; ( 1 = 0001) =&gt; true
  ( 3 = 0011) &amp; ( 2 = 0010) =&gt; ( 2 = 0010) =&gt; true
  ( 3 = 0011) &amp; ( 3 = 0011) =&gt; ( 3 = 0011) =&gt; true
  </code></pre>
  
  <p>By enforcing the condition <code>$test &amp; $allowAnonymous</code>, we can check that <code>$test</code> (whether the site is live or offline) and <code>$allowAnonymous</code> (the permissions granted to the specific controller action) overlap.</p>
  
  <p>More on bitwise operators <a href="https://www.php.net/manual/en/language.operators.bitwise.php" rel="noreferrer">here</a>.</p>
  
  <hr>
  
  <p>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 <code>ALLOW_ANONYMOUS_OFFLINE</code> constant was added, allowing for (but not requiring) more specific permissions on controller actions.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-15T15:04:54.787Z
Answers.Text: It appears the issue we had in Sprout Forms was because we were not calling `parent::init();` in our init method. Adding that allows us to remove the `self::ALLOW_ANONYMOUS_LIVE` addition and if it was in place to begin with, no change would have been necessary.
Answers.UserDisplayName: Ben Parizek
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-15T15:06:11.210Z
Answers.Text: Also, thanks for the break down of how the strings get translated. Nice detail.
Answers.UserDisplayName: Ben Parizek
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-15T15:25:01.150Z
Answers.Text: Yeah that must have been it. In Craft and Yii, if you ever override the `init()` method then you should always call the parent method with `parent::init()` :)
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-15T14:30:49.617Z
Answers.LastActivityDate: 2019-07-19T16:00:40.577Z
Answers.LastEditDate: 2019-07-19T16:00:40.577Z
Answers.UserDisplayName: Ben Croker
Body: <p>Craft 3.2 updates how the <code>allowAnonymous</code> behavior works. I have things working in our plugins but I don't understand the different syntaxes needed across our different <code>allowAnonymous</code> use cases.</p>
  
  <p>For example, Sprout Forms fails to submit unless we update the action to use the new <code>self::ALLOW_ANONYMOUS_LIVE</code> setting. However, Sprout SEO XML Sitemaps work fine without any updates. When I look through Craft I see some methods using the conventions (install controller, preview controller) and others not using any new conventions (generate thumb, live preview controller)</p>
  
  <p>In one case, the Sprout Address Field controller, the prefix action- seems to matter now and removing it alone, gets things updated and working again:</p>
  
  <pre class="lang-php prettyprint-override"><code>// Failure while logged out
  protected $allowAnonymous = [
      'action-update-address-form-html'
  ];
  
  // Success while logged out
  protected $allowAnonymous = [
      'update-address-form-html'
  ];
  
  // Success while logged out
  protected $allowAnonymous = [
      'update-address-form-html' =&gt; self::ALLOW_ANONYMOUS_LIVE
  ];
  </code></pre>
  
  <p>The general question is: what has been updated with the <code>allowAnonymous</code> behavior in Craft 3.2 and what scenarios does it require that we use the additional configuration settings such as <code>ALLOW_ANONYMOUS_LIVE</code> and <code>ALLOW_ANONYMOUS_OFFLINE</code>?</p>
  
Tags: <plugin-development><form><controller>
Title: What are the different scenarios to plan for when using $allowAnonymous in a controller?
ThreadText: # What are the different scenarios to plan for when using $allowAnonymous in a controller?
  
  (Asked by: username_0 on 2019-07-09)
  
  Craft 3.2 updates how the `allowAnonymous` behavior works. I have things working in our plugins but I don't understand the different syntaxes needed across our different `allowAnonymous` use cases.
  
  For example, Sprout Forms fails to submit unless we update the action to use the new `self::ALLOW_ANONYMOUS_LIVE` setting. However, Sprout SEO XML Sitemaps work fine without any updates. When I look through Craft I see some methods using the conventions (install controller, preview controller) and others not using any new conventions (generate thumb, live preview controller)
  
  In one case, the Sprout Address Field controller, the prefix action- seems to matter now and removing it alone, gets things updated and working again:
  
  ```php
  // Failure while logged out
  protected $allowAnonymous = [
      'action-update-address-form-html'
  ];
  
  // Success while logged out
  protected $allowAnonymous = [
      'update-address-form-html'
  ];
  
  // Success while logged out
  protected $allowAnonymous = [
      'update-address-form-html' => self::ALLOW_ANONYMOUS_LIVE
  ];
  
  ```
  
  The general question is: what has been updated with the `allowAnonymous` behavior in Craft 3.2 and what scenarios does it require that we use the additional configuration settings such as `ALLOW_ANONYMOUS_LIVE` and `ALLOW_ANONYMOUS_OFFLINE`?
  
  **Tags:** plugin-development, form, controller
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-07-15. Score: 8 | Accepted answer
  
  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](https://www.php.net/manual/en/language.operators.bitwise.php).
  
  ---
  
  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.
  
  > **Comments:**
  > **username_0**: It appears the issue we had in Sprout Forms was because we were not calling `parent::init();` in our init method. Adding that allows us to remove the `self::ALLOW_ANONYMOUS_LIVE` addition and if it was in place to begin with, no change would have been necessary.  
  > **username_0**: Also, thanks for the break down of how the strings get translated. Nice detail.  
  > **username_1**: Yeah that must have been it. In Craft and Yii, if you ever override the `init()` method then you should always call the parent method with `parent::init()` :)  
  
  ---
  
  