Skip to content

A MyBB-style user reputation system for Discourse. Allows community members to rate each other with positive, neutral, or negative ratings accompanied by comments.

License

Notifications You must be signed in to change notification settings

JoaquinSantarcangelo/discourse-user-reputation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Discourse User Reputation Plugin

Discourse License: MIT PRs Welcome

A MyBB-style user reputation system for Discourse. Allows community members to rate each other with positive, neutral, or negative ratings accompanied by comments.

Table of Contents


Features

  • Three Rating Types: Positive (+1), Neutral (0), Negative (-1)
  • One Rating Per Pair: Each user can only have one active rating per target user (can update/delete)
  • Required Comments: Configurable minimum character requirement for rating comments
  • Configurable Points: Admin-defined point values per rating type
  • Moderation Tools: Staff can hide/unhide ratings with reason tracking
  • Multiple Display Locations: Show reputation in user cards, posts, and profiles
  • Interaction Requirement: Optional toggle to require topic interaction before rating
  • Category Filtering: Limit interaction checks to specific categories
  • Cooldown Period: Configurable days before a rating can be modified
  • Soft Delete: Ratings are soft-deleted with full audit trail
  • Localization: Supports multiple languages (English, Spanish included)

Quick Start

# 1. Clone into your Discourse plugins directory cd /var/discourse/plugins git clone https://github.com/JoaquinSantarcangelo/discourse-user-reputation.git # 2. Rebuild the container cd /var/discourse && ./launcher rebuild app # 3. Configure in Admin > Settings > search "user_reputation"

For detailed installation options, see Installation.


Screenshots

User Profile

Reputation score displayed on user profiles with "Rate this user" button.

User Profile

User Card

Reputation breakdown shown in user hover cards.

User Card

Rating Modal

Modal dialog for creating ratings with positive/neutral/negative options.

Rating Modal

Activity Page

User activity page showing all ratings received with full details.

Activity Page

Admin Settings

Plugin configuration in the admin panel.

Admin Settings


Installation

Production (Docker-based Discourse)

  1. Add the plugin to your container configuration

    Edit your app.yml file (usually at /var/discourse/containers/app.yml):

    hooks: after_code: - exec: cd: $home/plugins cmd: - git clone https://github.com/JoaquinSantarcangelo/discourse-user-reputation.git
  2. Rebuild the container

    cd /var/discourse ./launcher rebuild app
  3. Configure the plugin

    Go to Admin > Settings and search for user_reputation to configure.

Development (Local Setup)

  1. Clone the plugin into your plugins directory

    cd /path/to/discourse/plugins git clone https://github.com/JoaquinSantarcangelo/discourse-user-reputation.git
  2. Run database migrations

    Important: Plugin migrations require the LOAD_PLUGINS=1 flag to be detected.

    LOAD_PLUGINS=1 bin/rails db:migrate
  3. Restart your Discourse server

    bin/rails server
  4. Optional: Seed test data

    # Create test users bundle exec rake reputation:seed # Create sample ratings bundle exec rake reputation:seed_ratings

Configuration

Navigate to Admin > Settings and search for user_reputation:

Setting Default Type Description
user_reputation_enabled true boolean Enable/disable the reputation system
user_reputation_min_trust_level_to_rate 1 integer (0-4) Minimum trust level required to rate users
user_reputation_min_comment_length 10 integer (1-500) Minimum characters for rating comments
user_reputation_positive_points 1 integer (1-10) Points awarded for positive ratings
user_reputation_negative_points -1 integer (-10 to -1) Points deducted for negative ratings
user_reputation_neutral_points 0 integer Points for neutral ratings
user_reputation_allow_self_rating false boolean Allow users to rate themselves
user_reputation_require_interaction true boolean Require topic interaction before rating
user_reputation_interaction_categories "" category_list Categories where interaction is checked (empty = all)
user_reputation_cooldown_days 30 integer (0-365) Days before a rating can be modified
user_reputation_show_in_posts true boolean Display score next to post author name
user_reputation_show_in_user_card true boolean Display score in user hover cards

Usage

For Users

  1. Rate from Posts: Click the star icon in the post menu to rate the post author
  2. Rate from Profile: Visit a user's profile and click the rate button (if enabled)
  3. View Reputation: See a user's full reputation history at /u/{username}/activity/reputation
  4. Edit/Delete: Modify your own ratings within the cooldown period

For Staff

  1. Hide Ratings: Hide inappropriate ratings with optional reason
  2. Unhide Ratings: Restore hidden ratings
  3. View All: See hidden ratings and moderation history

API Endpoints

Base path: /reputation

Method Endpoint Auth Description
GET /users/:username No Get user's reputation profile
GET /:id No Get a specific rating
POST / Yes Create a new rating
PUT /:id Yes Update a rating
DELETE /:id Yes Delete a rating
POST /:id/hide Staff Hide a rating
POST /:id/unhide Staff Unhide a rating

Request Examples

Create Rating:

POST /reputation { "target_user_id": 123, "rating_type": "positive", "comment": "Excellent seller, fast and reliable!", "topic_id": 456 }

Response:

{ "id": 789, "author_id": 1, "target_user_id": 123, "rating_type": "positive", "points": 1, "comment": "Excellent seller, fast and reliable!", "created_at": "2024-01-15T10:00:00Z" }

Get User Reputation:

GET /reputation/users/username { "score": 15, "breakdown": { "positive": 18, "neutral": 2, "negative": 3 }, "ratings": [...] }

Database Schema

Table: user_reputations

Column Type Description
id integer Primary key
author_id integer User giving the rating (FK to users)
target_user_id integer User receiving the rating (FK to users)
rating_type integer -1 (negative), 0 (neutral), 1 (positive)
points integer Calculated point value
comment text Required comment text
topic_id integer Optional linked topic (FK)
post_id integer Optional linked post (FK)
hidden boolean Hidden by moderator
hidden_by_id integer Staff who hid it (FK)
hidden_at datetime When hidden
hidden_reason text Reason for hiding
deleted_at datetime Soft delete timestamp
deleted_by_id integer User who deleted (FK)
created_at datetime Creation time
updated_at datetime Last update time

Indexes:

  • author_id - Lookup by rating author
  • target_user_id - Lookup by rated user
  • (author_id, target_user_id) UNIQUE WHERE deleted_at IS NULL
  • topic_id, rating_type, created_at, deleted_at

Frontend Components

Component Description
reputation-score Score badge with color coding (positive/neutral/negative)
reputation-rating-modal Modal dialog for creating/editing ratings
reputation-list-item Individual rating display with actions
rate-author-button Post menu button to rate author
post-reputation Score display next to post author
reputation-badge Score in user hover cards
rate-user-button Profile button to rate user
reputation-stat Score in profile statistics
reputation-nav "Reputation" tab in user activity

User Activity Page

Route: /u/:username/activity/reputation

Displays:

  • Total score with color coding
  • Breakdown by rating type
  • Paginated list of all ratings received
  • Edit/delete controls for own ratings
  • Hide/unhide controls for staff

Architecture

System Overview

flowchart TB subgraph Frontend["Frontend (Ember.js)"] UI[UI Components] API[reputation-api.js] Routes[Routes & Templates] end subgraph Backend["Backend (Rails)"] Controller[ReputationController] Engine[ReputationEngine] Model[UserReputation Model] Serializer[UserReputationSerializer] end subgraph Database DB[(user_reputations)] end UI --> API API -->|AJAX| Controller Controller --> Engine Controller --> Model Controller --> Serializer Engine --> Model Model --> DB Serializer -->|JSON| API 
Loading

Rating Flow

sequenceDiagram actor User participant Modal as Rating Modal participant API as reputation-api.js participant Controller as ReputationController participant Engine as ReputationEngine participant Model as UserReputation participant DB as Database User->>Modal: Click "Rate User" Modal->>Modal: Select rating type + comment User->>Modal: Submit Modal->>API: createRating(data) API->>Controller: POST /reputation Controller->>Engine: can_rate?(author, target) Engine-->>Controller: true/false alt Can Rate Controller->>Model: create(params) Model->>DB: INSERT DB-->>Model: record Model-->>Controller: reputation Controller-->>API: JSON response API-->>Modal: Success Modal-->>User: Rating created else Cannot Rate Controller-->>API: Error + reason API-->>Modal: Error Modal-->>User: Show error message end 
Loading

Database Schema

erDiagram users ||--o{ user_reputations : "gives ratings" users ||--o{ user_reputations : "receives ratings" topics ||--o{ user_reputations : "optional link" posts ||--o{ user_reputations : "optional link" user_reputations { int id PK int author_id FK int target_user_id FK int rating_type "1/0/-1" int points text comment int topic_id FK int post_id FK boolean hidden int hidden_by_id FK datetime hidden_at text hidden_reason datetime deleted_at int deleted_by_id FK datetime created_at datetime updated_at } 
Loading

Component Hierarchy

graph TD subgraph Profile["User Profile"] RUB[rate-user-button] RS[reputation-stat] end subgraph Card["User Card"] RB[reputation-badge] end subgraph Posts["Post Stream"] RAB[rate-author-button] PR[post-reputation] end subgraph Activity["Activity Page"] RLI[reputation-list-item] RSC[reputation-score] end subgraph Modal["Rating Modal"] RRM[reputation-rating-modal] end RUB -->|opens| RRM RAB -->|opens| RRM RRM -->|creates/updates| RLI 
Loading

File Structure

discourse-user-reputation/ ├── plugin.rb # Main plugin file ├── README.md # Documentation ├── app/ │ ├── controllers/ │ │ └── reputation_controller.rb │ ├── models/ │ │ └── user_reputation.rb │ └── serializers/ │ └── user_reputation_serializer.rb ├── assets/ │ ├── javascripts/discourse/ │ │ ├── components/ # UI components │ │ ├── connectors/ # Plugin outlets │ │ ├── services/ │ │ │ └── reputation-api.js │ │ ├── routes/ │ │ └── templates/ │ └── stylesheets/ │ └── reputation.scss ├── config/ │ ├── settings.yml # Plugin settings │ └── locales/ # Translations (en, es) ├── db/migrate/ │ └── 20241220000001_create_user_reputations.rb └── lib/ ├── reputation_engine.rb # Business logic └── tasks/ └── seed.rake # Development seed data 

Key Classes

UserReputation Model:

  • Scopes: active, visible, for_user, by_user, positive_ratings, negative_ratings
  • Methods: soft_delete!, hide!, unhide!, can_be_modified_by?
  • Class methods: calculate_total_score, breakdown_for, existing_rating

ReputationEngine:

  • can_rate?(author, target) - Check if rating is allowed
  • cannot_rate_reason(author, target) - Get denial reason
  • has_interaction?(user1, user2) - Verify topic interaction
  • color_class_for_score(score) - CSS class for styling

User Model Extensions:

  • reputation_score - Get user's total score
  • reputation_breakdown - Get count by type
  • can_rate_user?(target) - Permission check

Development

Seed Data for Testing

# Create test users (6 users with different trust levels) bundle exec rake reputation:seed # Create sample reputation ratings between test users bundle exec rake reputation:seed_ratings

Test Users Created:

Username Trust Level Role Password
seller_trusted TL3 User reputation_test_2024
buyer_new TL1 User reputation_test_2024
user_active TL2 User reputation_test_2024
moderator_rep TL4 Moderator reputation_test_2024
user_problematic TL0 User reputation_test_2024
seller_new TL2 User reputation_test_2024

Running Tests

# Ruby specs LOAD_PLUGINS=1 bin/rspec plugins/discourse-user-reputation/spec # JavaScript tests bin/qunit plugins/discourse-user-reputation/test

Linting

bin/lint plugins/discourse-user-reputation

Localization

Translation files in config/locales/:

  • client.{locale}.yml - Frontend strings
  • server.{locale}.yml - Backend strings

Included languages: English (en), Spanish (es)

To add a new language, create the corresponding locale files following the existing structure.


Troubleshooting

"relation user_reputations does not exist" error

The plugin migrations haven't run. Run migrations with the plugin flag:

LOAD_PLUGINS=1 bin/rails db:migrate

Then restart your Rails server.

Plugin not loading

  1. Check that the plugin is in the correct directory: plugins/discourse-user-reputation/
  2. Ensure plugin.rb exists in the plugin root
  3. Check Discourse logs for errors: ./launcher logs app

Ratings not showing

  1. Verify the plugin is enabled: Admin > Settings > search user_reputation_enabled
  2. Check display settings: user_reputation_show_in_posts, user_reputation_show_in_user_card

Cannot rate users

  1. Check your trust level meets the minimum requirement
  2. If interaction is required, ensure you've participated in topics with the user
  3. Verify you haven't already rated the user

Contributing

Contributions are welcome! Here's how you can help:

Reporting Issues

  • Search existing issues before creating a new one
  • Include Discourse version, plugin version, and steps to reproduce

Submitting Changes

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Follow existing code style and conventions
  4. Test your changes locally (see Development)
  5. Submit a pull request with a clear description

Adding Translations

  1. Copy config/locales/client.en.yml to client.{locale}.yml
  2. Copy config/locales/server.en.yml to server.{locale}.yml
  3. Translate all strings
  4. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A MyBB-style user reputation system for Discourse. Allows community members to rate each other with positive, neutral, or negative ratings accompanied by comments.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •