Skip to content
● Grav 2.2 is out: 2x faster cold starts and 96% less memory on big sites. Read the announcement →
Premium / Forum Pro
Premium Plugin · v1.0.15

Forum Pro

A real community forum, running inside your Grav site

Forum Pro is a complete, self-hosted discussion platform that lives inside your Grav site. Not an iframe, not a hosted widget, not a monthly per-seat bill. Your members get everything they expect from a modern forum (topics, reactions, private messages, notifications, live updates, real moderation and search) as first-class Grav pages that inherit your theme, share one login with the rest of your site, and store every post in a database you own. Built for Grav 2 and Admin Next, it runs the identical schema on SQLite, MySQL/MariaDB or PostgreSQL, so a hobby board and a community of tens of thousands are a config change apart, not a rewrite. And when you outgrow a hosted forum, the one-command Discourse importer brings your members, content and files across intact. We are not asking you to take that on faith: the Grav Community Forum runs Forum Pro, with over 41,000 posts across 9,300 topics from 3,800 members, and it runs great.

Grav 2.0+
Live Demo Documentation

Forum Pro is built for Grav 2 and requires the free API plugin. It is not compatible with Grav 1.7.

We run our own community on it

The Grav Community Forum is not a demo instance we spun up for this page. It is Forum Pro, it is where the Grav team works, and anyone is welcome to sign up and take part.

41,742 posts
9,332 topics
3,841 members

Nine years of community history, imported out of Discourse in a single command, with every member's password still working. Full-text search, live updates, private messages, badges, ranks and the full spam pipeline are all switched on. And it runs great.

Everything you need. Nothing you don’t.

Over 84 distinct features and integrations, out of the box.

Discussions & Content

The reading and writing experience your members spend all of their time in. Everything is server-rendered first, so the forum works with JavaScript off and search engines index it like the rest of your site.

01
Sections, categories and topics with per-category permissions, custom icons and ordering. The index shows each forum's latest topic and its author.
02
Rich posts through a hardened Markdown pipeline: @mentions with autocomplete, formatted quotes with reply-below-post, and fenced code blocks with server-side syntax highlighting, including automatic language detection when a block doesn't name one.
03
A WYSIWYG editor enhances the posting forms, while plain HTML forms keep working with JavaScript disabled.
04
Image and file attachments by drag-and-drop, by pasting a screenshot (it previews inline as it uploads), or with a plain file picker. Content-addressed dedupe, per-file, per-post and per-member limits, and automatic cleanup of abandoned uploads.
05
Reactions in a hover tray, with configurable types, emoji, and a reputation weight per type for the post author.
06
Polls on new topics, single or multiple choice, with vote changing and live result bars.
07
Tags with chips on listings, a tag browser, per-tag pages, and a tags field when starting a topic. You control who may mint new ones.
08
Accepted answers: the topic author or staff marks the reply that solved it, listings show a checkmark, and the answer's author gets notified.
09
Full revision history on every edit, with a configurable edit window. Authors and staff can browse every prior version of a post and restore one.
10
Bookmarks on topics and posts, reviewable on a private bookmarks page.
11
Unread tracking with a per-member read baseline, a new-post counter on unread topics, and links that jump straight to the first unread reply.
12
Suggested topics under each topic (your unread first, then related) plus a scrollspy timeline rail for scrubbing long threads.

Members & Community

Everything that makes contributors feel recognized and gives your community a sense of identity. Forum Pro runs its own account system, so members never need a Grav account, but your existing Grav admin and staff accounts link in automatically and keep working.

01
Native forum accounts with registration, email verification and password reset. Passwords use PHP's native bcrypt, sessions ride an HttpOnly cookie with a sliding window, and reset links are single-use, hashed at rest and pinned to a trusted host.
02
Public profiles with avatars, recent activity, ranks, badges, reputation and group affiliations, plus a send-message button.
03
Avatars that members upload, change or remove, with a per-member colored letter avatar derived from the username when none is set.
04
Automatic ranks that members climb as they post, plus custom ranks so staff can grant a handpicked honor like Founder with its own icon.
05
Badges awarded automatically for milestones and grantable or revocable by staff, shown as compact hover-labeled icons beside member names.
06
Member groups such as Core Team or Moderators, each with a color and icon, shown as badge bars under names in posts and topic lists.
07
Member titles shown under the name and editable from the admin.
08
A member directory at /forum/members, filterable and searchable, with an always-online window and who's-online counts.
09
An always-visible member toolbar with search and quick links to recent, unread, unanswered and participated topics. The avatar menu reaches profile, notifications, messages, bookmarks, your topics and settings.
10
Announcements: staff post dismissible banners above every forum page, with an optional expiry, color variant, icon and Markdown body.

Moderation & Safety

Tools that scale from a hobby board to a large community without turning moderation into a second job. Most of it happens on the forum itself, so your moderators never need admin access.

01
Scoped moderators: grant a moderator role globally, or limit it to specific sections and categories.
02
A review queue on the forum at /forum/queue with one-click publish, delete, or delete-and-ban, a jump to the post in its topic, and a step-through review mode that clears the whole queue in place.
03
A full moderation queue in the admin with pending, spam and flagged views, bulk actions on up to 100 items at a time, and one-click bans.
04
Per-category premoderation, applied to new members only or to everyone.
05
Member reports, where heavily reported posts auto-hide until a moderator reviews them.
06
Bans that can be global or scoped, temporary or permanent, with appeals and a content disposition: keep, reversibly hide everything, anonymize, or delete it all. Banned members are recognized if they try to re-register.
07
Undo for deletions and bans: a Deleted tab lists everything recently removed with who removed it, when and why, and a one-click Restore. A Bans area lists every active ban with a Lift that also brings back the content the ban had hidden.
08
In-topic moderation to pin, lock, hide, move and delete topics, and to hide, mark spam, restore or delete individual posts, all from a tidy wrench menu.
09
A complete audit log of every staff action, and legal holds that exempt a member, topic or post from all automated cleanup.
10
A daily moderator digest email with queue counts and activity, scheduled to a specific local time and timezone, and silent on quiet days.

Spam Defense

Three independent stages plus account-level gates, so unproven newcomers can't turn your board into a link farm. Everything any stage catches lands in the review queue, never deleted automatically before the retention window.

01
Heuristics (instant, always on): honeypot, submit speed, link counts, blocklists, flood limits and new-member weighting score every post. Configurable thresholds route content into the pending queue or straight into spam.
02
An ML classifier (instant, optional, self-hosted): posts by low-trust members are checked against a quantized DistilRoBERTa model served by a tiny Python and ONNX sidecar. Roughly 200ms, no GPU, and an install script sets it up on any Linux host. The client fails open, so a slow or dead sidecar can never block posting.
03
AI review (hourly, optional, via AI Pro): an LLM reviews new members' recent posts with full topic context and queues confident spam for moderators, logging its reasoning on every decision.
04
Provisional-member restrictions keep brand-new accounts on a lighter footing until they have both posted a configurable number of times and been registered a while. While provisional you can strip links to plain text, hide website, social, signature and title, mark the profile noindex, show a New badge, and block uploads and private messages. Every restriction is its own switch.
05
Invisible captcha: an optional transparent proof-of-work check on register and login that needs no user interaction at all.
06
Maintenance and read-only mode lets members browse but not post, react or sign up during a window, with an optional banner. Staff can keep full access or be locked out too.

Notifications, Email & Private Messages

Keep members in the loop without flooding their inbox, and let them talk to each other privately when a thread isn't the right place.

01
An in-app notification bell with live unread counts for replies, quotes, @mentions, watched activity, moderation decisions and badges.
02
Live toast notifications that slide in the moment a reply, mention or private message arrives, naming the sender, previewing PMs, and linking straight to the post.
03
Burst coalescing, so twelve replies in a watched topic become one bell entry rather than twelve.
04
Watch levels (Watching, Normal, Muted) per topic and per whole forum, with members auto-watching topics they start or reply to.
05
Email that mirrors the bell per member preference: immediate (throttled to one email per topic per window), daily or weekly digests, or never, with per-type toggles and one-click unsubscribe signed into every message.
06
Queued, individually-addressed delivery, never BCC blasts, drained by the background worker with retry and backoff. Sent payloads purge on schedule.
07
Private messages at /forum/messages, one-to-one or in groups, with a toolbar envelope carrying a live unread count and new replies appearing without a refresh.
08
Archiving, blocking and bulk cleanup on messages, including select-all-on-page and select-all-N so you can clear an entire tab and keep just the few you want. Conversations are reportable to moderators, who see only the reported message, with the access audited.

Search & Live Updates

Finding things, and seeing them happen. Search is always constrained by the visitor's category permissions, and live updates are a progressive enhancement that degrades to a perfectly good server-rendered forum.

01
Full-text search at /forum/search over published posts, with filters for keywords, author, a single forum and topics-only.
02
Post-style result cards with author avatar, name and group badges, date, a solution flag on accepted answers, and the matching text highlighted.
03
Two search engines: builtin uses SQLite FTS5, MySQL FULLTEXT or PostgreSQL tsvector with zero setup, or hand indexing to YetiSearch Pro for fuzzy matching and tuned relevance. The index maintains itself and rebuilds with a single CLI command.
04
New replies appear in place, reaction counts tick up, and category listings raise a refresh bar.
05
Presence and typing indicators on topic pages, showing who's viewing and who's typing.
06
Permission-aware channels, so private categories never broadcast to outsiders.
07
Transports, best first: Mercure push over server-sent events with a bundled hub binary, automatic polling fallback, or the plain server-rendered experience with zero live markup.
08
In-page navigation swaps forum pages without a full reload, handling the back button, page titles and focus correctly, and standing down automatically when your theme ships its own htmx.

Comments for Your Whole Site

Turn any page, blog posts especially, into a commentable article whose discussion lives in the forum. This is the classic comments backed by a real board model with none of the iframe or JS-embed friction, because the forum runs in the same Grav install.

01
One account covers comments and the forum alike.
02
The first comment opens the forum thread automatically, seeded with the article excerpt and a link back to the page.
03
Comments are ordinary forum posts, so spam scoring, premoderation, the review queue, search, notifications and reputation all apply, and the thread can be read and continued in the forum.
04
Enabled per template or per page, with a forum_comments(page) Twig call and a forum_comments_count(page) helper for 12 comments links on your listings.

Theming, Accessibility & SEO

The forum is theme-agnostic by design. Every color, radius, font and shadow resolves through a token chain, so a theme that publishes design tokens gets a forum that looks native to the site with no work at all.

01
Design token chain: --forum-* site overrides fall back to --grav-* theme tokens, then to --theme-accent, then to accessible neutral defaults.
02
*Themes that publish `--grav-` tokens** get matching typography, cards, buttons, chips and labels automatically. Themes that don't get contrast-checked neutral styles in both light and dark schemes.
03
One-property branding: a theme that only wants the forum to match its brand color publishes --theme-accent and is done. Labels sitting on a filled accent pick black or white automatically from how light that accent resolves.
04
Dark mode without a token set, recognizing data-theme, data-bs-theme and a dark class on html or body, and falling back to the Canvas system color for popovers and dialogs.
05
Inline Lucide SVG icons that recolor with the surrounding text.
06
Canonical URLs: topic addresses canonicalize by id, and slug or category mismatches 301 to the correct address, so links never rot and search engines see one URL per topic.
07
Per-page browser titles that follow in-page navigation, breadcrumb trails on every page, and noindex on provisional or hidden profiles.
08
Assistive technology support: focus moves to new content so screen readers announce where you landed, and icon-only buttons, the editor, its toolbar and the live-update bar are all labeled and announced.
09
Fully translatable visitor-facing text.

Privacy, Storage & Operations

The engineering that makes all of the above dependable at scale, plus the compliance controls you need when you are the one holding the data.

01
A portable database layer running the identical schema and migrations on SQLite, MySQL/MariaDB and PostgreSQL, selected by config. CI runs the full test suite against all three.
02
Safe migrations behind a database run-lock, auto-applied on SQLite and reviewable or manual elsewhere.
03
A scheduled worker on the Grav scheduler handles email delivery, badge awards, retention purges, session cleanup, view-count folding and scheduled scans, with a job queue that large ban dispositions defer to.
04
Content-addressed blob storage for attachments and avatars, local by default or on any S3-compatible store (Cloudflare R2 recommended) with a local read-through cache and render-time CDN switching. No AWS SDK, signing is built in.
05
Member self-deletion (GDPR erasure) confirmed by an email double opt-in, with a configurable cooling-off window that logging back in cancels.
06
Retention windows that hard-delete soft-deleted and spam content, scrub stored IP addresses, drop closed-report snapshots, read notifications and sent-email payloads. Each is configurable and each is enforced by the worker.
07
Legal holds that override retention for anything under investigation.
08
Efficient view counting and denormalized counters kept honest by a recount command and a read-only integrity checker.
09
A public, permission-filtered read-only API for forum data, and a metrics ledger tracking DAU, MAU, engaged-user trends, posting activity, top posters and queue health.
10
A full CLI: status, migrate, work, recount, reindex, rerender, integrity, files-sync, avatars-sync, ai-scan and import-discourse.

Migrating from Discourse

A genuine replacement, not a fresh start. Point the importer at a standard Discourse admin backup (the .sql.gz kind) and it stream-parses the dump in PHP. No PostgreSQL install required.

01
Members arrive with working passwords. Discourse's pbkdf2 hashes verify natively and upgrade to bcrypt on each member's first login, so nobody has to reset anything.
02
Content converts faithfully: categories (parents with children become sections, restricted ones go staff-only), topics, posts with uploads, quotes, emoji and [details] blocks converted, post revision history, likes as reactions, tags, accepted answers, bookmarks, polls with votes, watched and muted topics, and private messages.
03
People and identity come too: admins and moderators as moderator grants, custom groups with their flair colors, custom award badges and member titles.
04
Files rehost into your own storage. A --download-files pass pulls every referenced image, attachment and avatar off the old CDN into content-addressed storage and rewrites the posts that use them. Resumable and rate-limited.
05
Internal links are rewritten, and every imported row carries its Discourse id, so re-running an interrupted import never duplicates anything.
06
Legacy redirects 301 old Discourse URLs (/t, /p, /c, /u) to their Forum Pro equivalents, which makes the DNS cutover a non-event for search engines and old bookmarks.
07
On a different platform? Talk to us at [email protected] about building an importer for it. The Discourse importer sits on a general import layer, so a new source is mostly a matter of reading a different export format.
A real forum, not an embed

A real forum, not an embed

Topic lists that do the work: pinned and locked states, group badges under author names, solved checkmarks, unread dots with a jump-to-first-unread counter, overlapping avatars of everyone in the conversation, tags, replies, views and activity. It's a Grav page, at whatever route you choose (including your home page), rendered by your theme, indexed by search engines, and served from your own database.

Posts worth reading

Markdown with @mentions, quotes, and server-side syntax highlighting with automatic language detection. Accepted answers get called out at the top of the topic with a jump to the solution. A timeline rail tracks where you are in a long thread and lets you scrub through it. Every edit is kept, so authors and staff can browse the full history of a post and restore any prior version.

Posts worth reading
Spam stops before your members see it

Spam stops before your members see it

Moderators work the review queue right on the forum, no admin login needed. Spam, awaiting approval, reported and deleted each get their own tab with a live count, every card shows its spam score, and one click publishes, deletes, or deletes and bans the author. A step-through mode clears the entire queue in place. Nothing is ever hard-deleted before your retention window, so an accidental removal is always recoverable.

Recognition that keeps people around

Profiles pull together ranks, reputation, group badges and award badges alongside recent activity and a send-message button. Ranks climb automatically as people post, or staff can grant a custom honor like Founder with its own icon. Groups get a color and an icon and show up as badge bars everywhere the member appears.

Recognition that keeps people around
Comments for your whole site

Comments for your whole site

Drop one Twig call into your article template and your blog posts get a comment section backed by a real forum topic. The first comment opens the thread automatically, seeded with the article excerpt and a link back. From there it's an ordinary forum post: moderated, scored for spam, searchable, notified on, and continuable in the forum itself. One account covers both.

Run it from Grav Admin

Admin Next gets a full Forum section: Structure for sections and categories with icons, ordering and permissions, plus Queue, Members, Groups, Tags, Moderators, Bans and a Status panel that reports on your database, schema, background jobs, scheduler and real-time health. Settings live in seven tabs covering everything from posting limits to retention windows.

Run it from Grav Admin
Know how your community is doing

Know how your community is doing

A metrics ledger tracks signups, topics, posts, likes, new contributors, daily active users, engaged users and the DAU/MAU ratio over 7, 30 or 90 days, alongside top posters, most viewed topics and queue health. There's a Forum Activity report in Tools, and an optional widget that puts the same numbers on your site-wide admin dashboard.

Member management that scales

Search and filter thousands of members by group, badge or moderator status, and edit accounts, ranks, badges, passwords and suspensions in place. Grav admin and staff accounts link in automatically and coexist with native forum accounts, so one login covers your whole site without you juggling two user systems.

Member management that scales

Your community, on your infrastructure

No per-seat pricing, no data sitting on someone else's servers, no vendor lock-in. Forum Pro runs on the same host as your Grav site, backs up with it, and moves with it. Members sign in once for the forum, your blog comments, and the rest of your site. And because it is built on a portable database layer rather than Grav's file-based users, a community of tens of thousands is a config change, not a rewrite.

Up and running in about five minutes

  1. Install the plugin and enable it.
  2. Set frontend.enabled: true and visit /forum. The schema migrates itself on first use and the forum is live immediately on SQLite.
  3. Add the Grav scheduler to your crontab. The admin Status tab prints the exact line for your install. The worker delivers email, awards badges, purges expired content and runs the scheduled scans.
  4. Open Admin → Forum to create your sections and categories, then work through the settings tabs.

Want it somewhere other than /forum? Create a page with the Forum page type and the forum takes over that route, including your home page. Real site pages always win over forum routes, so nothing else on your site breaks.

A full CLI for the operational side

BASH
bin/plugin forum-pro status            # connection, schema, jobs, scheduler health
bin/plugin forum-pro migrate           # apply pending migrations (--status to preview)
bin/plugin forum-pro work              # process background jobs once
bin/plugin forum-pro recount           # repair denormalized counters
bin/plugin forum-pro reindex           # rebuild the full-text search index
bin/plugin forum-pro integrity         # read-only consistency report
bin/plugin forum-pro import-discourse  # migrate a Discourse backup
bin/plugin forum-pro files-sync        # push local blobs to S3/R2

Full setup, configuration and migration documentation lives on the Learn site.

A peek at sites running Forum Pro.

Frequently Asked Questions

The most commonly asked questions about the Forum Pro plugin

Can I see it running somewhere?

You can, and it is not a sandbox. The Grav Community Forum is Forum Pro. It is our main working environment, it is where we answer questions and talk about releases, and anyone is welcome to sign up and take part.

It currently holds 41,000+ posts across 9,300+ topics from 3,800+ members, nine years of community history imported out of Discourse, and it runs great. Every screenshot on this page comes from the same software you would be installing.

How well does it handle a big forum?

Our own forum is the answer we point people at: 41,000+ posts, 9,300+ topics, 3,800+ members, with full-text search, live updates, private messages and the spam pipeline all switched on. Listings and topics are server-rendered with denormalized counters and efficient view counting rather than counting rows on every page view, so a busy board stays quick.

If you outgrow SQLite, moving to MySQL/MariaDB or PostgreSQL is a config change. The schema and the migrations are identical across all three engines, and our CI runs the full test suite against each of them on every commit.

Is this a one-time purchase or a subscription?

Forum Pro is a one-time purchase. You get all future updates and new features for free as long as your license stays active. There are no recurring fees, no per-seat pricing, and no cap on how many members your community can have. Compare that to a hosted forum that bills you monthly and gets more expensive the more successful your community becomes.

Does Forum Pro work on Grav 1.7?

No. Forum Pro is built for Grav 2 and requires the API plugin for its Admin Next integration. It uses a real database layer, the Grav 2 event and permission model, and Admin Next UI extension points that simply don't exist in 1.7. If you are still on 1.7, take a look at the Migration chapter on the Learn site.

Do I need a database server?

No. SQLite works out of the box with zero configuration. The database file is created under user/data/forum-pro/ with deny-all protection files written next to it, and the schema migrates itself on first use. When you outgrow it, point the config at MySQL 8+, MariaDB 10.6+ or PostgreSQL 14+ and the identical schema and migrations run there instead. Our CI runs the full test suite against all three engines on PHP 8.3 and 8.4.

How does it look with my theme?

Forum Pro resolves every color, radius, font and shadow through a token chain: --forum-* site overrides, then --grav-* theme design tokens, then --theme-accent, then accessible neutral fallbacks. If your theme publishes --grav-* tokens, the forum matches it automatically. If it doesn't, you get contrast-checked neutral styling in both light and dark schemes, and a single line of CSS (:root { --theme-accent: #8428df; }) is enough to give the forum your brand color. Anything you want to tune independently is a --forum-* custom property away.

Can I move my existing Discourse forum over?

Yes, and this is one of the things we are proudest of. Take a standard Discourse admin backup (Settings, then Backups, the .sql.gz kind) and run:

BASH
bin/plugin forum-pro import-discourse backup.sql.gz \
    --source-url https://discourse.example.com --download-files

The dump is stream-parsed in PHP, so you don't need a PostgreSQL install anywhere. Members keep working passwords because Discourse's pbkdf2 hashes verify natively and upgrade to bcrypt on first login. Categories, topics, posts, revision history, likes, tags, badges, titles, accepted answers, bookmarks, polls, watched topics and private messages all come across, internal links are rewritten, and --download-files rehosts every image and attachment into your own storage. Every row carries its Discourse id, so re-running an interrupted import never duplicates anything.

This is exactly how the Grav Community Forum got here: nine years and 41,000 posts, moved across in one command.

I'm on a different forum platform. Can you help?

Very likely, yes. Talk to us about building an importer for your platform. The Discourse importer is built on a general import layer (id mapping for idempotency, a Markdown conversion pipeline, password-hash adapters, resumable file rehosting), so adding a new source is mostly a matter of teaching it to read your export format.

Get in touch at [email protected] with what you're running and what an export looks like, and we'll tell you honestly what's involved. If your platform is a common one, other people are asking for it too.

Where do uploaded files live?

By default, on local disk under user/data/forum-pro/, served from a content-addressed path with immutable caching. You can point storage.driver at any S3-compatible store (we recommend Cloudflare R2) and new uploads go to the bucket while staying locally cached. A locally missing blob pulls back through on first request, so serving never depends on the bucket being reachable. Set a public_url and pages reference your CDN instead, applied at render time so flipping it on or off is instant with no database rewrite.

What does the forum need to run properly?

Grav 2 (>= 2.0.0-rc.8), PHP 8.3 or newer, and the API plugin. That's it for the core experience. Several optional plugins each unlock more:

  • Email for outbound notification mail
  • Sync and Sync Mercure for live updates and presence
  • AI Pro for the hourly AI spam review
  • YetiSearch Pro for fuzzy search with tuned relevance
  • CodeSH for server-side syntax highlighting in code blocks
  • Form for the invisible captcha on register and login

You'll also want the Grav scheduler in your crontab. The admin Status tab prints the exact line for your install. The background worker delivers email, awards badges, purges expired content and runs the scheduled scans.

Can the forum live at my site root?

Yes. By default the forum mounts at /forum, but create a page with the Forum page type and the forum takes over that page's route, including the home page. Real site pages always win over forum routes, so a home-mounted forum coexists happily with the rest of your content, and /forum keeps working when no mount page exists.

Do members need a Grav account?

No. Forum Pro runs its own account system with registration, email verification and password reset under reserved routes, and members never touch your Grav user files. At the same time, authenticated Grav users are treated as forum members automatically (a linked forum account is created on first visit), so your admins and staff are already there. You can turn that off entirely if you would rather keep Grav logins out of the forum.

How much spam is this actually going to stop?

Quite a lot, and in three independent stages. The heuristic scorer runs on every post instantly: honeypot, submit speed, link counts, blocklists, flood limits and new-member weighting, with thresholds you control for pending versus spam. An optional self-hosted ML classifier adds a second opinion on posts from low-trust members in about 200ms, and it fails open so it can never block posting. An optional hourly AI review through AI Pro then reads new members' posts with full context and queues confident spam with its reasoning logged. On top of that, provisional-member restrictions stop brand-new accounts from posting live links, uploading files or sending private messages until they have earned it.

Can I use Forum Pro on multiple sites?

Per the Grav Premium License, you need a license for each site. Development and staging copies of the same site are covered by the same license. Get in touch if you need bulk pricing.

Forum Pro Changelog

v1.0.15

1 week ago

    • Works on hosts that disable getmypid() and gethostname(), a common PHP-FPM hardening. The bundled grav-db-kit (now 1.0.6) called them without a check when naming a lease owner or a job worker, which is a fatal error there, so every lease taken in a web request and the job drain after each request failed. It now falls back to 0 and unknown getgrav/grav-premium-issues#625

v1.0.14

2 weeks ago

    • Site login mode (auth.site_login, off by default; "Site Login" on the Members tab): the site's own sign-in, the Login plugin's page, replaces the forum's, so one login and one logout cover the forum and the rest of the site. Members come from the Grav session only, the forum_session cookie is ignored and cleared, /forum/login and /forum/reset hand off to the Login plugin (a login returns to the forum page you were on), /forum/logout ends the whole site session, and password and email changes in forum settings are replaced by a link to the new auth.account_url. The forum shows no sign-in or sign-out of its own in this mode: no Log in or Register links in its top bar, no Log out in the account menu, and its "log in to reply" prompts, members-only panel and comment box link to the Login plugin's page with the page to come back to. Registration stays with the forum; when a new account becomes usable it fires onForumProSiteAccountNeeded (with user, password_hash and email_proven, true only when the person clicked an emailed link) so a site plugin can create or find its account. If the listener answers existing = true (it attached the forum account to a site account that was already there), nobody is signed in automatically: the person is told to sign in and goes to the site's sign-in page, so the normal login runs with its second factor. Otherwise the person is signed in, with twofa passed to the Login plugin from plugins.login.twofa_enabled and a half-signed-in account sent to the site's code form. The verification link needs a person: opening it shows a small "Confirm your email" page, and only its button (a POST with the page's nonce) uses the token, verifies the address and fires the event, so a mail scanner that fetches every link in a message verifies nothing and burns nothing; an email-change link works the same way. The confirmation signs in only the browser that registered (the new member's id is kept in that browser's session); confirmed anywhere else it verifies the address and asks the person to sign in. Before signing anyone in, after a verification or an invite, the forum checks that the account the Login plugin resolved is exactly the site account the listener answered for (its storage key equals the event's grav_uid, the way KahunaCart's sign-in link checks), so a YAML or Flex account named like the registration email can never receive the session; if it is not that account, nobody is signed in, anything the Login plugin set is logged out, and the person is asked to sign in. In this mode staff cannot set a password or send a set-password link for a member linked to a site account, because the site owns that password (the API answers "This member signs in with their site account; their password is managed there", and Admin2 shows that note in place of the password controls). The same goes for the linked member's email address and "email verified" flag: the API refuses a change to either ("... their email address is managed there"; saving the editor with the values unchanged still works) and Admin2 shows them read-only, because staff could otherwise point the address at their own inbox, run a forum reset and plant a password. For the same reason a linked member gets no forum password-reset link and an old one is refused (a request on /forum/reset is handed to the site's forgot-password page even when a token is posted with it), and linking a member to a site account deletes their unused forum reset links. Unlinked members and sites without site login are unchanged. With site login on, /forum/verify with no token is a small forum page where an unverified member asks for a new verification email (neutral answer, same rate limits), and a dead or expired link, and the check-your-email step after registering, land there instead of at the login page, so a member who never got the link can get another. See "Site login mode" in the README
    • Pending-username members: a site account whose username is not a valid forum name (a shop customer whose username is their email) now gets a forum account with no username yet instead of publishing that name. They can read, but are left out of the member directory, counts and stats, the online list, mention suggestions, author search and profile pages, and any write sends them to a new "Choose your username" page at /forum/welcome (opened on their first page view of a session, with a banner on every forum page until they choose). Admin2's member list marks them "no username yet". The first request after updating runs one migration (0029), which adds a forum_users.username_pending column
    • New public methods for a site-wide sign-in bridge: AuthService::verifyCredentials() checks a username or email and password against forum accounts of every hash format, IdentityMapper::linkNative() links an existing forum member to a site account, and UserRepository::findByLogin() looks a member up by username or email
    • Two more public methods for the same bridge, used when two site accounts are merged into one: IdentityMapper::relinkNative() moves a linked member from one site account to another (refusing if the member is linked to something else, or if another member already holds the target), and IdentityMapper::unlinkNative() cuts a member loose from a site account and leaves the forum account in place with nobody signing in to it. Both change only the link (and, in site login mode, delete the member's unused forum reset links when relinking), and both can be repeated safely
    • In site login mode every page gets a forum_member Twig variable (username, display_name, pending) for the signed-in person, so the site header can link their forum profile or ask them to choose a username. It only reads; the forum row is created at login. It is set only for an active member or one in the self-deletion grace period (the same rule as the forum's actor), so a suspended member gets no "Forum profile" link that would 404. In this mode a forum row created for a signed-in site account starts with its email verified (the site login already confirmed it), so Admin2 no longer shows it as unverified
    • In site login mode the forum owns each member's display name. It is copied from the site account's full name only when the forum row is created, or while the member is still pending and has not chosen one; it is never refreshed afterwards, so a linked member's chosen forum name is not replaced by the name on their shop account. With site login off, the account's full name still refreshes it on every visit, unless the member typed their own on the chooser
    • A Grav account is no longer able to replace its forum username with a value that is not a valid forum username, such as an email address, when it is linked on a later visit
    • A suspended forum member could still act as a member through a Grav login (pages, comments, live updates and the API) because only deleted accounts were turned away. Only active members, and members in the self-deletion grace period, resolve now
    • A member without a chosen username could react, report, vote, bookmark, watch, message, tag, block, upload or edit a profile through the API, which does not go through the pages that send them to the username chooser. Every write service now refuses them through one shared check, the moderation and staff ones included (post and topic states, flag resolution, bans and appeals, announcements, legal holds and member administration), so a pending member who also holds moderation grants can no longer close a topic or issue a ban through the API. Every route that changes something (POST, PUT, PATCH, DELETE) is also registered through one guard that refuses a pending member before the handler runs, so the handlers that only check a Grav permission (tags, structure, groups, member updates and passwords) are covered, and a handler or service added later is too; reads and members who have chosen a username are not affected
    • A member without a chosen username who set a forum password and signed in with the forum's own login lost the pending state and could post under the __pending- placeholder. Native sessions carry it now, so the chooser and the write check apply with site login off as well
    • Registering with require_email_verification: false no longer marks the email as verified, since nobody proved it. Sign-in does not depend on it in that mode, and the cleanup of unverified accounts skips sites that do not require verification; Admin2 shows such addresses as unverified. Those sign-ups are also marked as accepted without verification, and the cleanup never removes a marked member, so turning verification on later does not delete readers who joined while it was off (the forum's own sign-in then asks them to verify like anyone else). Sign-ups that were waiting on a verification email are cleaned up as before

v1.0.13

3 weeks ago

    • Invite by email: on the Members tab, "Invite by email" sends someone a link that opens the register form for their address, even when auth.allow_registration is off. Pick the groups they should join, and see every invitation still waiting in a "Pending invites" list where you can resend (the old link stops working) or revoke it. The invited address is fixed on the form and counts as verified, since the link proved they own it. Links work once and last auth.invite_ttl_days days (7 by default); maintenance mode still closes sign-ups
    • Add member: "Add member" on the Members tab creates an account straight away from a username and email, with the groups you pick, and emails the member a link to choose their own password. Until they do, nobody can log in as them. The link uses the same lifetime as invitations, and a member who hasn't set a password yet has a "Send set-password link" button in their editor
    • Members who joined through an invitation or were added by an admin are treated as vouched for: they are never marked as new (provisional) members, so their links, profile fields, uploads and messages aren't restricted, and the daily cleanup of unverified accounts never removes an added member before they set a password
    • Both emails are sent through the email plugin and the admin screen says when one could not be sent. The invite and set-password links use the site address the forum recorded, or security.site_url when set, never the address the admin is browsing from
    • New admin API routes behind admin.forum-pro.admin: POST /forum-pro/members, POST /forum-pro/members/{id}/set-password-link, GET and POST /forum-pro/invites, POST /forum-pro/invites/{id}/resend and DELETE /forum-pro/invites/{id}. Inviting, adding and revoking are recorded in the moderation log. The first request after updating runs one migration (0028), which adds the forum_invites table and a forum_users.invited_by column
    • A password reset or set-password link that has expired or was already used now says so as soon as it is opened and offers to send a new one, instead of asking for a new password first and refusing it afterwards
    • Primary buttons (Create account, Log in, Post) showed a thin stripe of the wrong color down one edge on themes with a gradient accent. The gradient was sized to the inside of the button's border and repeated underneath it

v1.0.12

3 weeks ago

    • Help text on the category and section icon fields now follows the admin's Help text setting, showing below the label or in a tooltip behind an info icon

v1.0.11

3 weeks ago

    • database.persistent (off by default): keeps the MySQL/MariaDB or PostgreSQL connection open in the PHP-FPM worker between requests instead of opening a new one every time. No effect on SQLite or on a named connection; see the setting's help text for the max_connections budget and the PHP-FPM restart it needs after a database settings change. grav-db-kit 1.0.3
    • Topic pages failed on MySQL and MariaDB. The query that finds reply links named a column before, a reserved word on both, so every topic view there hit a syntax error. SQLite and PostgreSQL were unaffected
    • Member directory search and the @mention lookup failed on MySQL and MariaDB. Both escaped LIKE wildcards with ESCAPE '\', which MySQL reads as an unterminated string because a backslash is also a string escape there. They use ! as the escape character now, as the XenForo importer already did
    • The attachment link backfill links a post's files in the order the post mentions them on every engine, instead of the order the database happened to return them (MariaDB returned them sorted by hash)

v1.0.10

4 weeks ago

    • The database layer, migrator, job queue, KV store, rate limiter and unsubscribe signer now come from grav-db-kit, the shared database package KahunaCart and Helpdesk Pro already use, bundled under Forum Pro's own namespace so it never clashes with another plugin's copy. Existing forums keep their tables and data. The first request after updating runs one migration (0027), which adds any unflushed topic view counts to their topics, rebuilds forum_rate_limits in the kit's layout and adds the kit's columns to forum_jobs. Rate-limit counters start fresh, and unsubscribe links already sent keep working

v1.0.9

4 weeks ago

    • Forum admin and moderator rights granted through a Grav group now count on the forum itself. The forum read admin.forum-pro.admin and admin.forum-pro.moderate only from the account's own access settings, while the API checks groups too, so a moderator made one through a group could use the moderation API but got no staff tools on the forum pages and was treated as a regular member. Both now resolve permissions the same way, and the member stats count group-granted admins

v1.0.8

4 weeks ago

    • Attachments now follow the access rules of the posts that use them. A file in a members-only, group or staff forum answers 404 to anyone who can't read that post, and the same goes for files on posts that are pending, deleted or hidden, message attachments for anyone outside the conversation, and draft uploads for anyone but the uploader. Before, anyone with the link could download it, including guests on a private forum. Files a guest could see still cache forever and go through the CDN; restricted ones are sent with a private cache and always go through the forum, even with storage.s3.public_url set. Avatars stay public, and a file that isn't tied to any post or message follows the forum as a whole (public on an open forum, members-only on a private one)
    • New bin/plugin forum-pro link-files command. Files brought in by the Discourse importer were never tied to the posts and messages that use them, so the new access check couldn't apply to them. The command scans posts and private messages for file references and adds the missing links. Run it once on a forum imported before this release (--dry-run shows the counts first); it's safe to repeat. The importer's --download-files pass now does this on its own

v1.0.7

1 month ago

    • Sign-up blocklists. auth.blocked_email_domains refuses registrations and email changes at listed domains (example.com, or *.example.com for every subdomain too), and auth.blocked_username_patterns refuses usernames matching simple patterns (1win*, *melbet*). A refused sign-up gets a plain "Registration is not available for these details" that doesn't say which rule tripped, creates no account and sends no email. Each refusal is logged at info level with the rule, domain and IP, never the full address
    • Sign-ups at a domain with no MX and no A record are refused with "That email address can't receive mail" instead of sending a verification email that can only bounce (auth.check_email_domain, on by default). A failed DNS lookup never blocks anyone, and answers are cached per domain for a day
    • Accounts that never verified their email and never did anything (no posts, topics, messages, uploads, reactions or votes) are deleted once they're a week old, by a daily scheduler job (auth.prune_unverified_days, 0 turns it off). Imported and Grav-linked accounts are never touched. The new bin/plugin forum-pro prune-unverified command runs it by hand with --days, --domain and --dry-run
    • The invisible captcha now works when the login or register page is reached by clicking through the forum. In-forum navigation swaps in the page without its script tags, so the Cap check never ran and every login or sign-up from those pages failed with "captcha failed" until the page was reloaded

v1.0.6

1 month ago

    • Deleting a category from the Structure tab always failed with "No route matches 'DELETE /forum-pro/categorys/…'": the admin built the URL by adding an "s" to the word category. Sections were unaffected