Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -46,7 +46,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
Expand All @@ -59,6 +59,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: '/language:${{matrix.language}}'
54 changes: 28 additions & 26 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
FROM ruby:3.3.0-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# Set environment variables early
ENV DEBIAN_FRONTEND=noninteractive \
app_path=/usr/app \
RAILS_SERVE_STATIC_FILES=true \
RAILS_LOG_TO_STDOUT=true \
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 \
RAILS_ENV="production"

RUN apt-get update && apt-get install -y --no-install-recommends \
libjemalloc-dev \
curl \
gnupg \
build-essential \
software-properties-common
ca-certificates \
&& mkdir -p /etc/apt/keyrings

# 1. Install Node.js 20 (LTS) - Modern Method
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& curl -sL https://deb.nodesource.com/setup_14.x | bash -
# 2. Install Node.js and enable Yarn via corepack (more reliable than yarn apt package)
RUN apt-get update && apt-get install -y --no-install-recommends nodejs \
&& corepack enable \
&& corepack prepare yarn@stable --activate

RUN apt-get install -y --no-install-recommends \
# 3. Install all dependencies in one layer
RUN apt-get update && apt-get install -y --no-install-recommends \
bzip2 \
git \
shared-mime-info \
ca-certificates \
libffi-dev \
libpq-dev \
libgdbm-dev \
Expand All @@ -34,8 +47,6 @@ RUN apt-get install -y --no-install-recommends \
file \
imagemagick \
iproute2 \
nodejs \
yarn \
ffmpeg \
supervisor \
libvips42 \
Expand All @@ -45,37 +56,28 @@ RUN apt-get install -y --no-install-recommends \
vim \
&& rm -rf /var/lib/apt/lists/*

ENV DEBIAN_FRONTEND=noninteractive
ENV app_path=/usr/app
ENV RAILS_SERVE_STATIC_FILES=true
ENV RAILS_LOG_TO_STDOUT=true
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
ENV RAILS_ENV="production"

WORKDIR $app_path

# Install Bundler
RUN gem install bundler -v 2.6.6

# Copy Gemfile first for better caching
COPY Gemfile* ./
RUN bundle config set --local deployment 'true'
RUN bundle config set --local without 'development test'
RUN bundle install --jobs 4
RUN bundle config set --local deployment 'true' \
&& bundle config set --local without 'development test' \
&& bundle install --jobs 4

# Copy the rest of the application
ADD . $app_path
COPY . $app_path

# Precompile Assets with a dummy SECRET_KEY_BASE (only used during build)
RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:clean
RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:precompile
# Precompile Assets
RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:clean \
&& SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:precompile

# Set Executable Permission for Entrypoint
RUN chmod +x /usr/app/docker-entrypoint.sh
ENTRYPOINT ["/usr/app/docker-entrypoint.sh"]

# Copy supervisord configuration
COPY ./supervisord.conf /etc/supervisord.conf

# Start supervisord
CMD ["supervisord", "-c", "/etc/supervisord.conf"]
38 changes: 22 additions & 16 deletions Dockerfile.backup
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ruby:3.1.2-slim
FROM ruby:3.3.0-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
libjemalloc-dev \
curl \
gnupg \
Expand Down Expand Up @@ -30,12 +30,11 @@ RUN apt-get install -y --no-install-recommends \
default-mysql-client \
default-libmysqlclient-dev \
openssl \
file \
tzdata \
file \
imagemagick \
iproute2 \
nodejs \
libpq-dev\
yarn \
ffmpeg \
supervisor \
Expand All @@ -46,30 +45,37 @@ RUN apt-get install -y --no-install-recommends \
vim \
&& rm -rf /var/lib/apt/lists/*

ENV DEBIAN_FRONTEND noninteractive
ENV app_path /usr/app
ENV RAILS_SERVE_STATIC_FILES true
ENV RAILS_LOG_TO_STDOUT true

ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so
ENV DEBIAN_FRONTEND=noninteractive
ENV app_path=/usr/app
ENV RAILS_SERVE_STATIC_FILES=true
ENV RAILS_LOG_TO_STDOUT=true
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
ENV RAILS_ENV="production"

WORKDIR $app_path

RUN echo "install: --no-document" > $HOME/.gemrc && echo "update: --no-document" >> $HOME/.gemrc
# Install Bundler
RUN gem install bundler -v 2.6.6

# Copy Gemfile first for better caching
COPY Gemfile* ./
RUN gem install bundler
RUN bundle config set --local deployment 'true'
RUN bundle config set --local without 'development test'
RUN bundle install --jobs 4

# Copy the rest of the application
ADD . $app_path

RUN bundle exec rake assets:clean
RUN bundle exec rake assets:precompile

# Precompile Assets with a dummy SECRET_KEY_BASE (only used during build)
RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:clean
RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:precompile

RUN ["chmod", "+x", "/usr/app/docker-entrypoint.sh"]
# Set Executable Permission for Entrypoint
RUN chmod +x /usr/app/docker-entrypoint.sh
ENTRYPOINT ["/usr/app/docker-entrypoint.sh"]

# Copy supervisord configuration
COPY ./supervisord.conf /etc/supervisord.conf

# Start supervisord
CMD ["supervisord", "-c", "/etc/supervisord.conf"]
62 changes: 58 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ Welcome to the Patchwork. Developed and maintained by The Newsmast Foundation.

Patchwork is a plugin dashboard designed to enhance your Mastodon server with advanced features and a streamlined admin experience, making stewardship of a Mastodon server easier, safer and more fun.



## Features

#### Opt users in to search
Expand All @@ -23,12 +21,24 @@ Block spam posts arriving on your server from the federated network. Filters ide
#### Content filters

Block harmful content arriving on your server from the federated network. Filters identify keywords or phrases in lists of words for specific harms eg. NSFW, Hate speech etc. Each list can be toggled on or off. Create your own list for customised filters.
#### Channel Management

Channel Types: Support for multiple channel types including Channels, Channel Feeds, Hubs, and Newsmast channels.
Content Types: Configure channels as hashtag-based, contributor-based, group channels, or custom channels with flexible content rules.
Community Rules: Define and display community guidelines and rules for each channel.
Additional Information: Add custom headings and text blocks to provide context for channel visitors.
Social & General Links: Configure sidebar links to external resources, social media profiles, and related content.
#### Channel Content Curation

Hashtag-Based Content: Populate channels with content from specific hashtags across the Fediverse.
Contributor Management: Add, search, and manage contributors who can post to channels.
Mute Contributors: Mute specific accounts from appearing in channel feeds.
Relay Integration: Connect to relay services like relay.fedi.buzz for hashtag content distribution.
Post Boosting: Automatic boosting of posts through designated boost bot accounts.
#### Customise email branding

Replace the Mastodon logo in automatic emails with your own. This feature allows you to add your own header image, footer image and accent colour.



## Installing Patchwork

Find full instructions on how to install Patchwork on your Mastodon server [here](https://github.com/patchwork-hub/patchwork_dashboard/wiki/Installation-guide).
Expand All @@ -39,7 +49,47 @@ Before running Patchwork, please ensure you have set up a Mastodon server and it

You can find the instructions to set up a Mastodon server [here](https://docs.joinmastodon.org/admin/install/).

## Development

### Prerequisites
- Ruby (check `.ruby-version` for required version)
- PostgreSQL
- Redis

### Setup

1. Clone the repository and install dependencies:
```bash
git clone https://github.com/patchwork-hub/patchwork_dashboard.git
cd patchwork_dashboard
bin/setup
```

2. Configure environment variables:
```bash
cp .env.sample .env
# Edit .env with your configuration
```

3. Set up the database:
```bash
bundle exec rails db:create
bundle exec rails db:migrate
bundle exec rails db:seed
```

4. Start the development server:
```bash
bundle exec rails server
```

### Code Quality Tools

The project includes several development tools:
- **Bullet**: N+1 query detection
- **Rack Mini Profiler**: Request profiling
- **RuboCop**: Ruby style guide enforcement
- **AnnotateRB**: Schema annotation for models

## The Newsmast Foundation

Expand All @@ -51,10 +101,14 @@ Visit our website to learn [more](https://www.newsmastfoundation.org/).

For support in installing Patchwork, or for more information on our partnerships, please contact us at support@newsmastfoundation.org

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/patchwork-hub/patchwork_dashboard. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

## Licenses

Patchwork is an open source project, licensed under AGPL-3.0. Have fun!

## Code of Conduct
Everyone interacting in the Patchwork Dashboard project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

22 changes: 19 additions & 3 deletions app/controllers/api/v1/channels_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,27 @@ class ChannelsController < ApiController
].freeze

DEFAULT_FIND_OUT_CHANNELS = [
{ slug: 'us-politics', channel_type: Community.channel_types[:newsmast] },
{ slug: 'us-politics', channel_type: Community.channel_types[:newsmast] },
{ slug: 'newyork', channel_type: Community.channel_types[:channel_feed] },
{ slug: 'activism-civil-rights', channel_type: Community.channel_types[:newsmast] },
{ slug: 'privacy', channel_type: Community.channel_types[:channel_feed] },
{ slug: 'climate-change', channel_type: Community.channel_types[:newsmast]},
{ slug: 'democracy-human-rights', channel_type: Community.channel_types[:newsmast]},
{ slug: 'news-comment-data', channel_type: Community.channel_types[:newsmast] },
{ slug: 'lgbtq', channel_type: Community.channel_types[:newsmast] },
{ slug: 'us-sport', channel_type: Community.channel_types[:newsmast]}
].freeze

DEFAULT_LEICESTER_CHANNELS = [
{ slug: 'Leicester', channel_type: Community.channel_types[:channel_feed] },
{ slug: 'activism-civil-rights', channel_type: Community.channel_types[:newsmast] },
{ slug: 'climate-change', channel_type: Community.channel_types[:newsmast]},
{ slug: 'trees', channel_type: Community.channel_types[:channel_feed] },
{ slug: 'podcasting', channel_type: Community.channel_types[:channel_feed] },
{ slug: 'greens', channel_type: Community.channel_types[:channel]},
{ slug: 'fedibookclub', channel_type: Community.channel_types[:channel_feed]},
{ slug: 'NoticiasBrasil', channel_type: Community.channel_types[:channel_feed]},
{ slug: 'RenewedResistance', channel_type: Community.channel_types[:channel]}
]

def recommend_channels
@recommended_channels = Community.recommended.exclude_array_ids
render json: Api::V1::ChannelSerializer.new(@recommended_channels).serializable_hash.to_json
Expand Down Expand Up @@ -155,6 +167,10 @@ def find_out_channels
render_custom_channels(DEFAULT_FIND_OUT_CHANNELS)
end

def leicester_channels
render_custom_channels(DEFAULT_LEICESTER_CHANNELS)
end

def starter_packs_channels
starter_packs_channels = load_json_data(starter_pack_data_path('starter_pack_list.json'))

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/server_settings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def prepare_server_setting

desired_order = ['Local Features', 'User Management', 'Content filters', 'Spam filters', 'Federation', 'Plug-ins', 'Bluesky Bridge']
base_features = [
'Automatic Search Opt-in', 'Long posts',
'Automatic Search Opt-out', 'Long posts',
'Automatic Bluesky bridging for new users', 'Spam filters', 'Content filters'
]
dashboard_extras = ['Custom theme', 'Guest accounts', 'Analytics', 'Live blocklist', 'Sign up challenge']
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/wait_lists_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class WaitListsController < ApplicationController
PER_PAGE = 10

def index
@search = WaitList.where(channel_type: WaitList.channel_types[:hub]).ransack(params[:q])
@search = WaitList.ransack(params[:q])
@wait_lists = @search.result.order(used: :asc, created_at: :desc).page(params[:page]).per(PER_PAGE)
end

Expand Down
2 changes: 1 addition & 1 deletion app/jobs/create_community_instance_data_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def build_payload(community_id, community_slug)
sidekiq: calculate_sidekiq_port(community_id),
upstream_web: "#{community_id}_#{community_slug}_web",
upstream_stream: "#{community_id}_#{community_slug}_stream",
REDIS_NAMESPACE: community_slug,
COMMUNITY_SLUG: community_slug,
WEB_DOMAIN: @domain,
STREAMING_API_BASE_URL: "wss://#{@domain}",
LOCAL_DOMAIN: @domain,
Expand Down
12 changes: 6 additions & 6 deletions app/jobs/scheduler/follow_bluesky_bot_scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ class FollowBlueskyBotScheduler
sidekiq_options retry: 0, lock: :until_executed, lock_ttl: 15.minutes.to_i, queue: :scheduler

def perform
# return unless ServerSetting.find_by(name: 'Automatic Bluesky bridging for new users')&.value
return unless ServerSetting.find_by(name: 'Automatic Bluesky bridging for new users')&.value

# if is_channel_instance?
# ChannelBlueskyBridgeService.new.process_communities
# else
# NonChannelBlueskyBridgeService.new.process_users
# end
if is_channel_instance?
ChannelBlueskyBridgeService.new.process_communities
else
NonChannelBlueskyBridgeService.new.process_users
end

end

Expand Down
4 changes: 4 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ def following_ids(account_id = nil)
(follow_ids + follow_request_ids).uniq
end

# Configures user searchability and discoverability based on the Dashboard's 'search-opt' ServerSetting.
#
# Enabled search-opt: The user becomes hidden from search results.
# Disabled search-opt: The user remains visible and discoverable.
def self.update_all_discoverability(value = false)
update_all(
discoverable: !value,
Expand Down
Loading