Granting to unauthenticated
===========================

There are 3 special groups:

- Everybody, that everybody belongs to,

- Unauthenticated, that unauthenticated users belong to, and

- Authenticating, that authenticated users belong to.

Here's an example:

First, we'll set up a pluggable authentication utility containing a
principal folder, which we'll create first.

Create the principal folder:

  >>> print http(r"""
  ... POST /++etc++site/default/+/AddPrincipalFolder.html%3D HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: multipart/form-data; boundary=---------------------------51955270618919134971413296540
  ... 
  ... -----------------------------51955270618919134971413296540
  ... Content-Disposition: form-data; name="field.prefix"
  ... 
  ... users.
  ... -----------------------------51955270618919134971413296540
  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
  ... 
  ... Add
  ... -----------------------------51955270618919134971413296540
  ... Content-Disposition: form-data; name="add_input_name"
  ... 
  ... 
  ... -----------------------------51955270618919134971413296540--
  ... """)
  HTTP/1.1 303 See Other
  ...

Register it:

  >>> print http(r"""
  ... POST /++etc++site/default/PrincipalFolder/addRegistration.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: multipart/form-data; boundary=---------------------------1211945862063657304996683149
  ... 
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.name"
  ... 
  ... users
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.provided"
  ... 
  ... zope.app.authentication.interfaces.ISearchableAuthenticationPlugin
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.provided-empty-marker"
  ... 
  ... 1
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.status"
  ... 
  ... Active
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.permission"
  ... 
  ... 
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="field.permission-empty-marker"
  ... 
  ... 1
  ... -----------------------------1211945862063657304996683149
  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
  ... 
  ... Add
  ... -----------------------------1211945862063657304996683149--
  ... """)
  HTTP/1.1 303 See Other
  ...

Add a principal to it:

  >>> print http(r"""
  ... POST /++etc++site/default/PrincipalFolder/+/AddPrincipalInformation.html%3D HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: multipart/form-data; boundary=---------------------------10033016405103631412002637985
  ... 
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="field.login"
  ... 
  ... bob
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="field.password"
  ... 
  ... 123
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="field.title"
  ... 
  ... Bob
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="field.description"
  ... 
  ... 
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
  ... 
  ... Add
  ... -----------------------------10033016405103631412002637985
  ... Content-Disposition: form-data; name="add_input_name"
  ... 
  ... 
  ... -----------------------------10033016405103631412002637985--
  ... """)
  HTTP/1.1 303 See Other
  ...

Create a pluggable-authentication utility:

  >>> print http(r"""
  ... POST /++etc++site/default/@@contents.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... 
  ... type_name=BrowserAdd__zope.app.authentication.authentication.LocalPluggableAuthentication&new_value=""")
  HTTP/1.1 303 See Other
  ...

and register it:

  >>> print http(r"""
  ... POST /++etc++site/default/LocalPluggableAuthentication/addRegistration.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: multipart/form-data; boundary=---------------------------2567744622114531019698320091
  ... Referer: http://localhost:8081/++etc++site/default/LocalPluggableAuthentication/addRegistration.html
  ... 
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.name"
  ... 
  ... 
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.provided"
  ... 
  ... zope.app.security.interfaces.IAuthentication
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.provided-empty-marker"
  ... 
  ... 1
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.status"
  ... 
  ... Active
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.permission"
  ... 
  ... 
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="field.permission-empty-marker"
  ... 
  ... 1
  ... -----------------------------2567744622114531019698320091
  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
  ... 
  ... Add
  ... -----------------------------2567744622114531019698320091--
  ... """)
  HTTP/1.1 303 See Other
  ...

and configure it:

  >>> print http(r"""
  ... POST /++etc++site/default/LocalPluggableAuthentication/@@edit.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: multipart/form-data; boundary=---------------------------12424310211503201098946683515
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.extractors.to"
  ... 
  ... HTTP Basic
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.extractors-empty-marker"
  ... 
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.authenticators.to"
  ... 
  ... users
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.authenticators-empty-marker"
  ... 
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.challengers.to"
  ... 
  ... No Challenge if Authenticated
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.challengers.to"
  ... 
  ... Zope Realm HTTP Basic
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.challengers-empty-marker"
  ... 
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.factories.to"
  ... 
  ... Default
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.factories-empty-marker"
  ... 
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.searchers.to"
  ... 
  ... users
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.searchers-empty-marker"
  ... 
  ... 
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
  ... 
  ... Change
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.extractors"
  ... 
  ... HTTP Basic
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.authenticators"
  ... 
  ... users
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.challengers"
  ... 
  ... No Challenge if Authenticated
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.challengers"
  ... 
  ... Zope Realm HTTP Basic
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.factories"
  ... 
  ... Default
  ... -----------------------------12424310211503201098946683515
  ... Content-Disposition: form-data; name="field.searchers"
  ... 
  ... users
  ... -----------------------------12424310211503201098946683515--
  ... """)
  HTTP/1.1 200 Ok
  ...

Normally, the anonymous role has view, we'll deny it:

  >>> print http(r"""
  ... POST /++etc++site/AllRolePermissions.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... 
  ... role_id=zope.Anonymous""" 
  ... """&Deny%3Alist=zope.View""" 
  ... """&Deny%3Alist=zope.app.dublincore.view""" 
  ... """&SUBMIT_ROLE=Save+Changes""")
  HTTP/1.1 200 Ok
  ...

Now, if we try to access the main page as an anonymous user, we'll be unauthorized:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 401 Unauthorized
  ...

We'll even be unauthorized if we try to access it as bob:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 403 Forbidden
  ...

No, let's grant view to the authenticated group:

  >>> print http(r"""
  ... POST /@@grant.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... 
  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk&field.principal.displayed=y"""
  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=allow"""
  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=allow"""
  ... """&GRANT_SUBMIT=Change""")
  HTTP/1.1 200 Ok
  ...

Now, with this, we can access the main page as bob, but not as an
anonymous user:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 200 Ok
  ...

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 401 Unauthorized
  ...

Now, we'll grant to unauthenticated:

  >>> print http(r"""
  ... POST /@@grant.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... Referer: http://localhost:8081/@@grant.html
  ... 
  ... field.principal=em9wZS5Bbnlib2R5"""
  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=allow"""
  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=allow"""
  ... """&GRANT_SUBMIT=Change""")
  HTTP/1.1 200 Ok
  ...

With this, we can access the page as either bob or anonymous:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 200 Ok
  ...

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 200 Ok
  ...

Now, we'll remove the authenticated group grant:

  >>> print http(r"""
  ... POST /@@grant.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... 
  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk"""
  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=unset"""
  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=unset"""
  ... """&GRANT_SUBMIT=Change""")
  HTTP/1.1 200 Ok
  ...

And anonymous people will be able to access the page, but bob won't be able to:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 403 Forbidden
  ...

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 200 Ok
  ...

Now, we'll remove the unauthenticated group grant:

  >>> print http(r"""
  ... POST /@@grant.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... Referer: http://localhost:8081/@@grant.html
  ... 
  ... field.principal=em9wZS5Bbnlib2R5"""
  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=unset"""
  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=unset"""
  ... """&GRANT_SUBMIT=Change""")
  HTTP/1.1 200 Ok
  ...

and neither bob nor anonymous can access:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 403 Forbidden
  ...

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 401 Unauthorized
  ...

Finally, we'll grant to everybody:

  >>> print http(r"""
  ... POST /@@grant.html HTTP/1.1
  ... Authorization: Basic mgr:mgrpw
  ... Content-Type: application/x-www-form-urlencoded
  ... 
  ... field.principal=em9wZS5FdmVyeWJvZHk_"""
  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.View=allow"""
  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.app.dublincore.view=allow"""
  ... """&GRANT_SUBMIT=Change""", handle_errors = False)
  HTTP/1.1 200 Ok
  ...

and both bob nor anonymous can access:

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... Authorization: Basic bob:123
  ... """)
  HTTP/1.1 200 Ok
  ...

  >>> print http(r"""
  ... GET / HTTP/1.1
  ... """)
  HTTP/1.1 200 Ok
  ...
