Skip to content

Commit

Permalink
Dedicated documentation files
Browse files Browse the repository at this point in the history
  • Loading branch information
julianwachholz committed Dec 2, 2021
1 parent 957838f commit b988cb9
Show file tree
Hide file tree
Showing 21 changed files with 705 additions and 481 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ poetry.lock
/dist/
.tox
.pytest_cache
docs/_build
281 changes: 14 additions & 267 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![Code Lint](https://github.com/julianwachholz/django-guest-user/actions/workflows/lint.yml/badge.svg)](https://github.com/julianwachholz/django-guest-user/actions/workflows/lint.yml)
[![Python Tests](https://github.com/julianwachholz/django-guest-user/actions/workflows/test.yml/badge.svg)](https://github.com/julianwachholz/django-guest-user/actions/workflows/test.yml)
[![Documentation](https://readthedocs.org/projects/django-guest-user/badge/?style=flat)](https://django-guest-user.readthedocs.io)

# django-guest-user

Expand All @@ -8,276 +9,22 @@ without requiring registration.

Largely inspired by [django-lazysignup](https://github.com/danfairs/django-lazysignup) and rewritten for Django 3.1+ and Python 3.7+.

## Requirements
## Quickstart

The tests cover the following versions:
1. Install the `django-guest-user` package
2. Add `guest_user` to your `INSTALLED_APPS` and migrate your database
3. Add `guest_user.backends.GuestBackend` to your `AUTHENTICATION_BACKENDS`
4. Include `guest_user.urls` in your URLs
5. Decorate your views with `@allow_guest_user`:

- Python 3.7, 3.8, 3.9
- Django 3.1, 3.2 and `main` (4.0)
```
from guest_user.decorators import allow_guest_user
## Installation

Install the package with your favorite package manager from PyPI:

```
pip install django-guest-user
```

Add the app to your `INSTALLED_APPS` and `AUTHENTICATION_BACKENDS`:

```python
INSTALLED_APPS = [
# ...
"guest_user",
]

AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"guest_user.backends.GuestBackend",
]
```

Add the patterns to your URL config:

```python
urlpatterns = [
# ...
path("convert/", include("guest_user.urls")),
]
```

Don't forget to run migrations:

```
python manage.py migrate
```

## How to use

Guest users are **not** created for every unauthenticated request. Instead, use the
[`@allow_guest_user`](#allow_guest_user) decorator on a view to enable that view to
be accessed by a temporary guest user.

Each time an anonymous user requests a decorated view, a new temporary guest user
will be created and logged in with a randomly generated username.

At any point in time, the guest user may choose to permanently register with
the website by using the conversion view. This will delete the associated
`Guest` instance for the user and prevent deletion from cleanup jobs.

Guest instances must be deleted periodically. This can be done manually in the admin,
by selecting the "Delete selected guests older than 1 day" action, or by running
the management command on a schedule (for example using a cronjob):

```
./manage.py delete_expired_users
```

**Note**: Your Django project should be set up in such a way, that deleting a
`User` will not be prevented by `PROTECT` or `RESTRICT` on_delete clauses.
Instead, it's recommended that every foreign key to a User either use [CASCADE or SET_NULL](https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ForeignKey.on_delete).

## Additional Features

### django-allauth integration

A small submodule is provided that will allow converting guest users by connecting
a social account with [django-allauth](https://www.intenct.nl/projects/django-allauth/).

See documentation details for it in [`guest_user.contrib.allauth`](./guest_user/contrib/allauth/).

## API

### Decorators

Module: `guest_user.decorators`

#### `@allow_guest_user`

View decorator that will create a temporary guest user in the event that the
decorated view is accessed by an unauthenticated visitor.

```python
from guest_user.decorators import allow_guest_user

@allow_guest_user
def my_view(request):
# Will always be either a registered a guest user.
username = request.user.username
return HttpResponse(f"Hello, {username}!")
```

Takes no arguments.

#### `@guest_user_required`

View decorator that only allows guest users. Anonymous or registered users will
be redirected to their respective redirect targets.

```python
@guest_user_required(anonymous_url="/login/", registered_url="/dashboard/")
def only_for_guests(request):
pass
```

Arguments:

- **anonymous_url**: Redirect target for anonymous users.
Defaults to the `GUEST_USER_REQUIRED_ANON_URL` setting.
- **registered_url**: Redirect target for registered users.
Defaults to the `GUEST_USER_REQUIRED_USER_URL` setting.

#### `@regular_user_required`

If some parts of the application should not be used by guests, you can use
this decorator to disable guest access.

In the event that a guest user tries to access a view decorated with it,
they will be redirected to the conversion page.

```python
@regular_user_required(login_url="/login/", convert_url="/convert/")
def only_for_real_users(request):
pass
```

Arguments:

- **login_url**: Redirect target for anonymous users.
Defaults to the `GUEST_USER_REQUIRED_ANON_URL` setting.
- **convert_url**: Redirect target for **guest** users.
Defaults to the `GUEST_USER_REQUIRED_USER_URL` setting.
- **redirect_field_name**: URL parameter used to redirect to the origin page.
Defaults to `django.contrib.auth.REDIRECT_FIELD_NAME` (which is `"next"`).

### Functions

Module: `guest_user.functions`

#### `is_guest_user(user)`

Check wether the given user instance is a temporary guest.

Returns `bool`.

### Signals

Module: `guest_user.signals`

#### `guest_created(request, user)`

Signal dispatched when a visitor accessed a view that created a guest user.

Provides `user` and `request` arguments.

#### `converted(user)`

Signal dispatched when a guest user is converted to a regular user.

Provides `user` argument.

### Template Tags

#### `is_guest_user`

A filter to use in templates to check if the user object is a guest.

```
{% load guest_user %}
{% if user|is_guest_user %}
Hello guest.
{% endif %}
```

## Settings

Various settings are provided to allow customization of the guest user behavior.

### `GUEST_USER_ENABLED`

**bool** - If False, the `@allow_guest_user` decorator will not create guest users.
Defaults to `True`.

### `GUEST_USER_MODEL`

**str**. The swappable model identifier to use as the guest model.
Defaults to `guest_user.Guest`.

### `GUEST_USER_NAME_GENERATOR`

**str**. Import path to a function that will generate a username for a guest user.
Defaults to `guest_user.functions.generate_uuid_username`.

Included with the package are two alternatives:

- `guest_user.functions.generate_numbered_username`

Will create a random four digit
number prefixed by `GUEST_USER_NAME_PREFIX`.

- `guest_user.functions.generate_friendly_username`

Creates a friendly and easy to remember username by combining an
adjective, noun and number. Requires the package [`random_username`](https://pypi.org/project/random-username/).

### `GUEST_USER_NAME_PREFIX`

**str**. A prefix to use with the `generate_numbered_username` generator.

Defaults to `Guest`.

### `GUEST_USER_MAX_AGE`

**int**. Seconds to keep a guest user before expiring.

Defaults to `settings.SESSION_COOKIE_AGE`.

### `GUEST_USER_CONVERT_FORM`

**str**. Import path for the guest conversion form.
Must implement `get_credentials` to be passed to Django's authenticate function.

Defaults to `guest_user.forms.UserCreationForm`.

### `GUEST_USER_CONVERT_PREFILL_USERNAME`

**bool**. Set the generated username as initial value on the conversion form.

Defaults to `False`.

### `GUEST_USER_CONVERT_URL`

**str**. URL name for the convert view.

Defaults to `guest_user_convert`.

### `GUEST_USER_CONVERT_REDIRECT_URL`

**str**. URL name to redirect to after conversion, unless a redirect parameter was provided.

Defaults to `guest_user_convert_success`.

### `GUEST_USER_REQUIRED_ANON_URL`

**str**. URL name to redirect to when an anonymous visitor tries to access a view
with the `@guest_user_required` decorator.

Defaults to `settings.LOGIN_URL`.

### `GUEST_USER_REQUIRED_USER_URL`

**str**. URL name to redirect to when a registered user tries to access a view
with the `@guest_user_required` decorator.

Defaults to `settings.LOGIN_REDIRECT_URL`.

### `GUEST_USER_BLOCKED_USER_AGENTS`

**list[str]**. Web crawler and other user agents to block from becoming guest users.
The list will be combined into a regular expression.

Default includes [a number of well known bots and spiders](https://github.com/julianwachholz/django-guest-user/blob/main/guest_user/settings.py#L122-L133).
@allow_guest_user
def my_view(request):
assert request.user.is_authenticated
return render(request, "my_view.html")
```

## Status

Expand Down
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
45 changes: 45 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
API
===


Decorators
----------

.. currentmodule:: guest_user.decorators

.. automodule:: guest_user.decorators

.. autodecorator:: allow_guest_user

.. autodecorator:: guest_user_required

.. autodecorator:: regular_user_required


Mixins
------

.. automodule:: guest_user.mixins
:members:

Template Tags
-------------

The package registers a template filter to use in your Django templates.

.. autodata:: guest_user.templatetags.guest_user.is_guest_user
:no-value:

Functions
---------

Several helper functions are provided for advanced usage.

.. automodule:: guest_user.functions
:members:

Signals
-------

.. automodule:: guest_user.signals
:members:
Loading

0 comments on commit b988cb9

Please sign in to comment.