Metadata-Version: 2.4
Name: splent_feature_events
Version: 0.5.0
License-Expression: LGPL-3.0-or-later
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: COPYING
License-File: COPYING.LESSER
Requires-Dist: splent_framework>=1.20.0
Dynamic: license-file

# splent_feature_events

The `events` feature of a [SPLENT](https://splent.io) product line.

A SPLENT feature is a Python package that a product composes with others.
Its models, routes, services, templates and hooks are registered when the
product starts. What this feature provides and requires is listed in the
`[tool.splent.contract]` section of `pyproject.toml`, which
`splent feature:contract --write` keeps in sync with the source.

## What it does

Talks, workshops, competitions, ceremonies and any other kind of activity a
product invents. `/events` lists the published events and `/events/<slug>`
shows one. The home page gets the next few events through the
`home.section` hook. Whether past events stay on the list and how many the
home page shows are settings of the panel.

A draft, an event that is not published, stays off the list and the home
page, and its page answers 404 to everyone but the accounts that open the
panel's event screens, who see it with a notice that it is a draft and not
visible to the public. The page asks `has_role` with
`endpoint="events.admin_index"` and the slug in `view_args`, so an access
policy registered for those screens decides the preview of each event too.

The description of an event is stored HTML, and the event page renders it
with the framework's `rich_text` filter, which keeps the formatting and
drops scripts, event handlers and `javascript:` links.

The image and the link of an event are addresses typed in the panel, which
the pages put in an `src` and in the `href` of the "More info" button. The
form refuses an address that is not `http://`, `https://`, `mailto:` or a
path on the site, `javascript:` and `data:` among them, with the reason
above the form and what was typed still in it, and saves nothing. The pages
draw both through the framework's `safe_url` filter, so an address stored
before the form checked it points nowhere instead of running.

The panel manages the events at `/admin/events`, where they are added,
edited, moved to another kind and deleted.

Other features add to these pages through the slots this one opens
(`events.list.*`, `events.detail.before_meta`, `events.admin.*`) instead of
copying its templates.

## Access

The screens under `/admin/events` open for the accounts whose role is
`admin` or `staff`, the same pair the admin dashboard lets in. Any other
signed-in account gets 403 and does not see the Events link in the sidebar,
and an anonymous visitor is sent to log in. The public pages stay open to
everyone, but for the page of a draft, which the same accounts preview.

Another feature can decide for these screens through an access policy, which
the framework asks before the roles (`register_access_policy` for the
endpoints under `events.admin`). `splent_feature_edition_staff` registers
one, which lets in an account that holds a role in some edition although its
own role is `user`, and that feature then narrows it to what its role allows
in each edition. `splent_feature_edition_staff` also keeps out a `staff`
account that holds no role in an edition. The sidebar link follows the same
answer. Without such a feature the roles alone decide, and to let a person
manage the events you give their account the staff role.

```bash
splent feature:auth set-role someone@example.com staff
```

With `splent_feature_edition_staff` installed, give the person a role in an
edition instead (see that feature).

Every button of the events list is drawn only when `has_role`, asked with
the endpoint it opens, says yes. Move, Edit and delete on the row of an
event ask with `view_args={"event_id": ...}` for that event, as the screen's
own gate does. So an access policy that closes one of those screens to an
account, for every event or for one, hides its button too, and no button
answers 403.

## Use it in a product

```bash
splent feature:add splent_feature_events
```

## Develop

```bash
splent feature:test splent_feature_events
splent feature:contract splent_feature_events
```

## Release

```bash
splent feature:release splent_feature_events --dry-run --bump patch
splent feature:release splent_feature_events
```

The first command rehearses the release and changes nothing. The second
publishes it to the git forge and to PyPI, and a PyPI version is permanent.
