wagtail-core 1.0.0
A core Wagtail project for Wisemen containing all the common functionality.
License: MIT
Requires Python: >=3.11,<4.0

# Appwise Wagtail's Core

A Wagtail setup including sane defaults ready for headless consumption.

## Setup

Make sure to first create an empty database for the system to be installed on.

Then you are ready to setup your Python's virtual environment:

```bash
$ cd <your-path>/<your-project-directory>
$ python3 -m venv venv
$ source venv/bin/activate
```

Now install the needed Python packages (using Pip and Poetry):

```bash
$ pip install poetry
$ poetry install
```

Run the setup script and answer the questions:

```bash
$ python setup.py
```

And follow the steps outlined at the end of the script:

- Run `direnv allow`
- Run `python manage.py migrate`

Fill in any other desired environment variables in your newly created `.envrc` file.
Finally, setup a superuser for the install:

```bash
$ python manage.py createsuperuser
```

Your core is now setup! Happy Wagtailing...

## Notes

### Bitbucket pipelines / Deployment

This includes a pipelines file based on the Tribe Stijn "Dockerserver" setup, meaning
a docker deployment in `root/containers/<project_name>` and a directory per
environment (eg. `root/containers/<project_name>/development`, `root/containers/<project_name>/production`).

Each environment directory should contain an `.env-backend` file for the Wagtail docker image
which holds the environment variables for this setup.

This Pipelines file needs to be edited so it can deploy correctly, 
ask your local SysOps for deployment and/or see other Wagtail docker server setups as an example.

## Features

- Docker ready, using the latest Python on a Debian Slim (not Alpine!) image (including an example Compose file using async Uvicorn workers)
- Automatic Swagger/OpenAPI documentation (under `/api/docs`) using [DRF Spectacular](https://drf-spectacular.readthedocs.io/en/latest/)
- Base i18n and i10n setup using Wagtail's own [Wagtail Localize](https://www.wagtail-localize.org/)
- Base SEO setup with mixable SEO panels using [Wagtail SEO](https://docs.coderedcorp.com/wagtail-seo/)
- Sentry integration
- S3 integration via [Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) including a private file storage backend if the S3 environment variables are filled in
- Sitemap and robots.txt generation
- Redirects flow (old URLs to new URLs), manageable via CMS, presented via API for frontend consumption
- ChoiceArrayField: Multiple Choice field based on PostgreSQL ARRAY type.
- DisableCSRF middleware: Disables CSRF for all requests, useful during development.
- Serializers (For Images, Streamfields, etc.)
- Wagtail Hooks (Publish is default action)

## User login & model

We have chosen to let users login via the email instead of the default username.
This means that there is a custom User model implemented to make `email` a unique field.
If desired, additional fields can be implemented by overwriting this User model.
Keep in mind that if you wish to overwrite it, you need to add all additional fields to the `WAGTAIL_USER_CUSTOM_FIELDS`
setting so they appear in the Wagtail user administration.

## Password reset handling

Password reset handling is done via the Django Password Reset package and will emit a signal which can be recieved
and handled by your own code. For example:

```python
@receiver(reset_password_token_created)
def password_reset_token_created(
    sender, instance, reset_password_token, *args, **kwargs
):
  # send an e-mail to the user
    context = {
        "current_user": reset_password_token.user,
        "first_name": reset_password_token.user.first_name,
        "email": reset_password_token.user.email,
        "reset_password_url": f"{ENV('BASE_URL')}/some-urls/?token={reset_password_token.key}",
    }

    # render email text
    email_html_message = render_to_string(
        "email/user_reset_password.html", context
    )  # noqa

    msg = EmailMessage(
        settings.PASSWORD_RESET_EMAIL_SUBJECT,
        email_html_message,
        settings.PASSWORD_RESET_EMAIL_FROM_ADDRESS,
        [reset_password_token.user.email],
    )
    msg.content_subtype = "html"
    msg.send()
```