Discourse Policy

:discourse2: Summary Discourse Policy gives the ability to confirm your users have seen or done something, with optional reminders.
:open_book: Install Guide This plugin is bundled with Discourse core. There is no need to install the plugin separately.

Features

Discourse policy shares much of its DNA with polls, it has the goal of ensuring members of a group accept certain policies by clicking a button.

It has some specific features that set it apart from polls:

  1. It must apply to a group.

  2. It can optionally nag members of a group either weekly or daily to click accept on a policy.

  3. The UX makes it very easy to see who accepted and who did not accept a policy.

Configuration

Screenshots

Before clicking accept

After clicking “grey” person on top right

After clicking accept

Creating a policy

Discourse policy registers a custom [policy] BBCode element. Which means you need to write this block of code in your post where you want to show this policy.

[policy group=founders reminder=daily]
I accept this policy will annoy me daily until I click accept
[/policy]

In this case the policy applies to the founders group and a reminder is sent daily to all users that did not accept the policy.

Site settings

policy_enabled : Enable the discourse policy plugin on the site.

policy_restrict_to_staff_posts: Policies may only appear on staff posts.

policy easy revoke: Show the accept and revoke buttons at the same time.

BBCode attributes

The [policy] element can accept the following attributes.

  • group: the group name that policy will apply to required
  • version: the version number of the policy, bump number up to require all users re-accept the policy
  • reminder: remind users of the group to accept policy (weekly or daily), optional, default off
  • accept: text used for accept button, default is “Accept Policy”
  • revoke: text used for revoke button, default is “Revoke Policy”
  • renew: number of days or text describing period (monthly, quarterly or yearly) after which a user needs to re-accept policy
  • renew-start: the first date renewals will start at Eg: 17-10-2017, useful if you want to set the renewal cadence so it happens every half-year (Jan,June)
  • add-users-to-group: accepts a single group as input; users who accept the policy will be automatically added into this group (when policy is manually revoked or if the policy version is updated, user(s) gets removed from group)
  • private: hide users who accepted/did not accept the policy

:information_source: The backend job to check for policy reminders runs every 6 hours. If the reminder element is set to weekly or daily, users who have not accepted a policy will be sent notification reminders to accept the policy only if they have not already received a reminder notification for the policy within the past week or day.

Usage examples

Basic policy:

[policy group="team" reminder="daily" accept="Accept" revoke="Ignore" version="1"]
I have read, understand and acknowledge this policy.
[/policy]

Bumping the revision number, to require that everyone reads the update:

[policy group="team" reminder="daily" accept="Accept" revoke="Ignore" version="2"]
I have read, understand and acknowledge this policy. (Last updated [date=2020-04-23 timezone="America/Los_Angeles"])
[/policy]

Periodic auditing task:

[policy group="audit_committee" reminder="weekly" renew="90" renew-start="01-07-2019" version="1" accept="Assignment Complete"] 
I have ensured that someone is assigned to this quarterly audit task.
[/policy]

CHANGELOG

TODO

  • Optional immediate reminder for new policies
  • Possibly allow certain groups to apply policies (expanding on staff)

Last edited by @david 2025-07-22T13:14:42Z

Check documentPerform check on document:
65개의 좋아요
How to make users to explicitly agree to ToS
Have-to-read topics? (or RSVP topics)
Plugin to maintain group membership based on accepting a Policy
Ability to view if PM has been read (Moderation ability?)
Group Membership base on accepting a Discourse Policy
Force existing users to accept ToS
Dashboard Report - Unaccepted Policies
Improving Discourse Policy for large groups
How to get email notifications when new users have signed up?
Best practices for communicating to user base
Is there a plugin that helps with Age Verification on the site?
Restrict posting in a category until they "like" a topic
Restrict posting in a category until they "like" a topic
Topic should be a notification
Plugin or other option to require a post and a like?
Watching category mandatory
Policy reminder cannot be left empty
Bundling more popular plugins with Discourse core
Age prompt for NSFW catagories
Button to join group on post
Bump topic with API
Publish group read state
How to handle changing organizational roles, re. past mentions on the forum
Delivered and read notifications?
Habit tracking within Discourse...is it possible?
Changing policy texts
Agree to additional terms before joining group
Know who has viewed your post
How can I compare arbitrary revisions of a post?
Require accepting new terms (after changes) as a modal inside forum
Tips into building a community aside a variety of already existing tools
How to force existing users to accept ToS
Plugin to gather approvals / signatures on an initiative?
Recommnded plugins for supporting a tech community run by a big enterprise?
AUP location
I can't display my policy

2 posts were split to a new topic: Limit Policy creation to just staff?

4 posts were split to a new topic: Is it possible to disallow revoking agreement to certain policies?

It looks like the 200 limit and the policy_max_group_size got removed with this commit. Am I missing something?

https://github.com/discourse/discourse-policy/pull/43

3개의 좋아요

6 posts were split to a new topic: People receiving reminders even though they’ve accepted the policy

When a policy with long button text is applied to a large group, the UI gets mangled: in the screenshot below, we can see that the avatars form an near infinite column that makes it a bit akward. I will look into the CSS to see if that can be easily fixed, but probably there should be some kind of redesign:

Removing display: flex on .cooked .policy .user-lists makes it look fine on Desktop:

I ended up using the following CSS:

/* Make policy user list not overflow */
.cooked .policy .user-lists {
    display: block;
}
3개의 좋아요

Error after installing the plugin. Don’t know why. Something related “while trying to load /admin/dashboard/general.json”.

Server Error

while trying to load [/admin/plugins]

Error code: 500 error

Oops

The software powering this discussion forum encountered an unexpected problem. We apologize for the inconvenience.

Detailed information about the error was logged, and an automatic notification generated. We’ll take a look at it.

No further action is necessary. However, if the error condition persists, you can provide additional detail, including steps to reproduce the error, by posting a discussion topic in the site’s feedback category.

안녕하세요,

정책이 답변을 허용하지 않는 닫힌 카테고리 토픽에 있을 경우, 승인/거절 버튼이 표시되나요?

감사합니다.

이 플러그인을 꽤 오래 사용하지 않았지만, 주제가 닫힐 때 사용자가 승인/거부할 수 있도록 해줄 것 같습니다. 버튼을 누르는 것은 답글이 아니기 때문에, 주제 닫힘이 방지하는 답글 작성과는 별개이죠.

1개의 좋아요

안녕하세요, 질문이 있습니다:
우리는 Discourse Policy 플러그인을 사용하여 초기 사용자에게 서비스 약관(ToS) 수락을 강제하려 합니다. 요구사항은 다음과 같습니다:

  • 수락하지 않으면 → 포럼을 사용할 수 없습니다(ToS 페이지만 표시됨)
  • 수락하면 → 포럼을 사용할 수 있으며 “ToS” 배지를 받음

제안한 해결책은 새 주제를 생성하고 그 안에 다음 내용을 추가하는 것이었습니다:
[policy group=trust_level_0 reminder=daily add-users-to-group=tos_accepted accept=“I Accept Terms” version=“1”]
"I Accept Terms"를 클릭하면 서비스 약관을 읽었으며 이에 동의한다는 것을 확인합니다.
[/policy]

하지만 신규 사용자가 로그인하면 정책이 전혀 표시되지 않고 아무거나 할 수 있습니다. "Accept"를 클릭한 후에만 페이지에 접근할 수 있도록 하고 싶습니다. 어떻게 해야 하는지 알려주시면 감사하겠습니다.

사용자 정의 필드를 사용하여 약관(TOS) 및 FAQ 페이지를 연결할 수 있습니다. 사용자가 이를 읽으면 ‘지침 읽음’ 배지를 받게 됩니다.

2개의 좋아요

답변 감사합니다 — 말씀하신 대로 잘 작동했습니다. 다만, 제가 실제로 원하는 것은 사용자가 로그인한 후에 이 배너를 표시하고, 사용자가 '수락’을 클릭한 경우에만 페이지 접근을 허용하는 것입니다. 그렇지 않으면 배너가 계속 표시되어야 하고, 사용자는 페이지와 상호작용할 수 없어야 합니다.

현재 제 상태는 다음과 같습니다:


그 후 사용자는 정상적으로 페이지에 접근할 수 있습니다.

이것을 구현할 수 있는 방법이 있을까요? 감사합니다

:partying_face: 이 플러그인은 이제 Bundling more popular plugins with Discourse core 에 따라 Discourse 코어에 번들링됩니다. 자체 호스팅을 사용 중이면서 이 플러그인을 사용 중인 경우, 다음 업그레이드 전에 app.yml에서 플러그인을 제거해야 합니다.

3개의 좋아요

사용자가 수락하거나 거절할 때 그룹에서 제거할 수 있는 기능을 추가해 주시면 좋겠습니다.

현재 이 기능은 (선택적으로) 사용자에게 반복적으로 알림을 보내고 추가하는 것만 하는 것으로 보입니다. 제가 뭘 놓치고 있는 건지 모르겠네요.

감사합니다!

3개의 좋아요

이것은 훌륭하지만, 정책에 동의하지 않은 모든 사용자에게 리마인더를 전달하는 방식이 더 명확하고 눈에 잘 띄어야 한다는 점에서 아쉬움이 남습니다. 대부분의 사용자는 프로필 아이콘 뒤에 숨겨진 간단한 알림을 거의 보지 않으므로, 팝업 리마인더가 거의 필수적입니다.

아래는 해당 그룹 내에서 정책에 동의하지 않은 모든 활성 사용자를 식별하는 쿼리입니다. 추가 후속 조치가 필요할 때 유용합니다.

WITH target_policy AS (
-- 주제에 연결된 마스터 정책 ID 찾기
SELECT pp.id AS post_policy_id
FROM post_policies pp
JOIN posts p ON p.id = pp.post_id
WHERE p.topic_id = YOUR_TOPIC_ID
LIMIT 1
),
any_accepted_users AS (
-- 이 정책 로그 행과 관련된 모든 사용자 ID 수집
-- 버전 확인을 우회하면 오래된 서명이 결과를 왜곡하는 것을 방지할 수 있음
SELECT DISTINCT pu.user_id
FROM policy_users pu
JOIN target_policy tp ON tp.post_policy_id = pu.post_policy_id
WHERE pu.accepted_at IS NOT NULL
)
SELECT
u.id AS user_id,
u.username,
u.name,
ue.email,
u.last_seen_at
FROM users u
-- 기본 이메일 계정을 안전하게 가져오기
LEFT JOIN user_emails ue ON ue.user_id = u.id AND ue.primary = true
-- 대상 풀을 특정 그룹으로 엄격히 제한
JOIN group_users gu ON gu.user_id = u.id
JOIN groups g ON g.id = gu.group_id
WHERE g.name = 'YOUR_GROUP'
AND u.active = true
AND u.id > 0 -- 기본 시스템/봇 계정 제외
-- 정책 로그 데이터베이스 블록에 존재하는 모든 사용자 ID 하드 드롭
AND u.id NOT IN (SELECT user_id FROM any_accepted_users)
ORDER BY u.last_seen_at DESC

2개의 좋아요