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
[Admin-Hinweis] Eines deiner Themes oder Plug-ins enthält Code, der aktualisiert werden muss
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개가 새 주제로 분리되었습니다: 정책 생성을 스태프만 가능하게?

4개의 게시물이 새 주제로 분리되었습니다: 특정 정책에 대한 동의 철회를 금지할 수 있나요?

이 커밋에서 200 제한과 policy_max_group_size가 제거된 것으로 보입니다. 제가 놓친 부분이 있을까요?

3개의 좋아요

6개의 게시물이 새로운 주제로 분리되었습니다: 정책을 수락했음에도 불구하고 리마인더를 받는 사람들

긴 버튼 텍스트가 포함된 정책이 대규모 그룹에 적용되면 UI가 깨집니다. 아래 스크린샷에서 아바타가 거의 무한히 이어지는 열을 형성하여 다소 어색해 보이는 것을 확인할 수 있습니다. CSS를 살펴보고 쉽게 수정할 수 있는지 확인해 보겠지만, 아마도某种程度的重新设计이 필요합니다:

.cooked .policy .user-lists에서 display: flex를 제거하면 데스크톱에서 정상적으로 보입니다:

결국 다음 CSS를 사용했습니다:

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

플러그인 설치 후 오류가 발생했습니다. 원인을 알 수 없습니다. "while trying to load /admin/dashboard/general.json"와 관련된 문제인 것 같습니다.

서버 오류

while trying to load [/admin/plugins]

오류 코드: 500 오류

죄송합니다

이 토론 포럼을 구동하는 소프트웨어에서 예기치 않은 문제가 발생했습니다. 불편을 드려 죄송합니다.

오류에 대한 자세한 정보는 기록되었으며, 자동 알림이 생성되었습니다. 확인하겠습니다.

추가 조치는 필요하지 않습니다. 그러나 오류 상태가 지속되면, 오류를 재현하는 단계 등 추가 세부 정보를 사이트의 피드백 카테고리에 토론 주제를 게시하여 제공하실 수 있습니다.

안녕하세요,

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

감사합니다.

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

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개의 좋아요