Skip to content

Commit 0496794

Browse files
committed
fix: Add class comments to fix issues
1 parent 74e3dc3 commit 0496794

9 files changed

Lines changed: 95 additions & 46 deletions

File tree

Gemfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,13 @@ group :development do
1313
gem 'rubocop-rake'
1414
gem 'rubocop-rspec'
1515
end
16+
17+
group :development, :test do
18+
gem 'combustion', '~> 1.3'
19+
gem 'rspec', '~> 3.13'
20+
gem 'rspec-rails', '~> 6.1'
21+
end
22+
23+
group :test do
24+
gem 'database_cleaner-mongoid', '~> 2.0'
25+
end

app/controllers/consyncful/webhook_controller.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
# frozen_string_literal: true
22

33
module Consyncful
4+
# The Consyncful::WebhookController is responsible for handling incoming
5+
# webhook requests that can trigger synchronization jobs within Consyncful.
6+
#
7+
# Features:
8+
# - Only responds to requests if `sync_mode` is configured as `:webhook`.
9+
# - Optionally requires HTTP Basic authentication if
10+
# `webhook_authentication_required` is enabled in configuration.
11+
# - Exposes a single endpoint (`trigger_sync`) that signals a sync process
12+
# through `Consyncful::Sync.signal_webhook!`.
13+
#
14+
# Security:
15+
# - Uses `ActionController::HttpAuthentication::Basic` to enforce
16+
# authentication when enabled.
17+
# - Compares provided credentials with configured values using
18+
# `ActiveSupport::SecurityUtils.secure_compare` to prevent timing attacks.
19+
#
20+
# Responses:
21+
# - Returns `404 Not Found` if webhooks are not enabled.
22+
# - Returns `202 Accepted` after signaling a sync.
423
class WebhookController < ActionController::API
524
include ActionController::HttpAuthentication::Basic::ControllerMethods
625
before_action :authenticate, if: -> { Consyncful.configuration.webhook_authentication_required && use_webhooks? }

consyncful.gemspec

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,9 @@ Gem::Specification.new do |spec|
3131
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
3232
spec.require_paths = ['lib']
3333

34-
#
35-
# Runtime dependencies
36-
#
3734
spec.add_dependency 'contentful', ['>=2.11.1', '<3.0.0']
3835
spec.add_dependency 'hooks', '>=0.4.1'
3936
spec.add_dependency 'mongoid', '>=7.0.2'
4037
spec.add_dependency 'rainbow'
4138
spec.metadata['rubygems_mfa_required'] = 'true'
42-
43-
#
44-
# Development / test dependencies (installed in CI because Gemfile has `gemspec`)
45-
#
46-
spec.add_development_dependency "rspec", "~> 3.13"
47-
spec.add_development_dependency "rspec-rails", "~> 6.1"
48-
spec.add_development_dependency "combustion", "~> 1.3"
49-
spec.add_development_dependency "database_cleaner-mongoid", "~> 2.0"
5039
end

lib/consyncful/configuration.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
# Handles Rails configurations for Consyncful
44
module Consyncful
5+
# Provides configuration options for Consyncful, including:
6+
# - Contentful API client and sync options
7+
# - MongoDB client and collection settings
8+
# - Locale and content tag filtering
9+
# - Sync mode (poll or webhook)
10+
# - Webhook authentication credentials
11+
#
12+
# This class is typically accessed and customized via
13+
# Consyncful.configure do |config|
14+
# config.locale = 'en-NZ'
15+
# config.mongo_collection = 'my_models'
16+
# end
517
class Configuration
618
attr_accessor :contentful_client_options,
719
:contentful_sync_options,
@@ -16,6 +28,7 @@ class Configuration
1628
:webhook_user,
1729
:webhook_password
1830

31+
# rubocop:disable Metrics/MethodLength
1932
def initialize
2033
@sync_mode = :poll
2134
@contentful_client_options = {}
@@ -31,6 +44,7 @@ def initialize
3144
@webhook_user = nil
3245
@webhook_password = nil
3346
end
47+
# rubocop:enable Metrics/MethodLength
3448

3549
def initial_sync_options
3650
options = { initial: true }

lib/consyncful/engine.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# frozen_string_literal: true
22

33
module Consyncful
4+
# Rails engine for Consyncful.
5+
#
6+
# This isolates the Consyncful namespace and allows the gem
7+
# to provide its own routes, controllers, and configuration
8+
# within a Rails application without clashing with the host app.
49
class Engine < ::Rails::Engine
510
isolate_namespace Consyncful
611
end

lib/consyncful/sync_runner.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
# frozen_string_literal: true
22

3-
# lib/consyncful/sync_runner.rb
43
module Consyncful
4+
# The SyncRunner is responsible for continuously executing Contentful sync
5+
# jobs at a configurable interval or in response to webhook signals.
6+
#
7+
# Modes:
8+
# - :poll — runs the sync every N seconds (default 15)
9+
# - :webhook — waits for webhook signals and triggers a sync when received
10+
#
11+
# Behavior:
12+
# - Starts with an initial sync (`Consyncful::Sync.latest.run`).
13+
# - In poll mode, sleeps for the configured interval and then re-runs sync.
14+
# - In webhook mode, listens for webhook signals and runs sync immediately.
515
class SyncRunner
616
DEFAULT_INTERVAL = 15
717
VALID_MODES = %i[poll webhook].freeze
@@ -17,9 +27,7 @@ def run
1727

1828
loop do
1929
sleep(@interval)
20-
if @mode == :poll || Consyncful::Sync.consume_webhook_signal!
21-
current_sync.run
22-
end
30+
current_sync.run if @mode == :poll || Consyncful::Sync.consume_webhook_signal!
2331
end
2432
end
2533

spec/controllers/consyncful/webhook_controller_spec.rb

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,84 @@
11
# frozen_string_literal: true
2-
require "rails_helper"
32

4-
RSpec.describe "Consyncful::WebhookController", type: :request do
3+
require 'rails_helper'
4+
5+
RSpec.describe 'Consyncful::WebhookController', type: :request do
56
let(:config) do
67
# Provide a simple configuration double with the fields used by the controller
78
instance_double(
8-
"Consyncful::Configuration",
9+
'Consyncful::Configuration',
910
sync_mode: sync_mode,
1011
webhook_authentication_required: auth_required,
11-
webhook_user: "user1",
12-
webhook_password: "secret"
12+
webhook_user: 'user1',
13+
webhook_password: 'secret'
1314
)
1415
end
1516

1617
before do
1718
allow(Consyncful).to receive(:configuration).and_return(config)
1819
end
1920

20-
describe "POST /consyncful/webhook" do
21-
subject(:perform) { post "/consyncful/webhook", headers: headers }
21+
describe 'POST /consyncful/webhook' do
22+
subject(:perform) { post '/consyncful/webhook', headers: headers }
2223

2324
let(:headers) { {} }
2425

25-
context "when sync mode is not :webhook" do
26+
context 'when sync mode is not :webhook' do
2627
let(:sync_mode) { :poll }
2728
let(:auth_required) { false }
2829

29-
it "returns 404 Not Found" do
30+
it 'returns 404 Not Found' do
3031
perform
3132
expect(response).to have_http_status(:not_found)
3233
end
3334
end
3435

35-
context "when sync mode is :webhook" do
36+
context 'when sync mode is :webhook' do
3637
let(:sync_mode) { :webhook }
3738

38-
context "and authentication is not required" do
39+
context 'and authentication is not required' do
3940
let(:auth_required) { false }
4041

41-
it "signals the sync and returns 202 Accepted" do
42+
it 'signals the sync and returns 202 Accepted' do
4243
expect(Consyncful::Sync).to receive(:signal_webhook!)
4344
perform
4445
expect(response).to have_http_status(:accepted)
4546
end
4647
end
4748

48-
context "and authentication is required" do
49+
context 'and authentication is required' do
4950
let(:auth_required) { true }
5051

51-
context "with no credentials" do
52-
it "returns 401 Unauthorized" do
52+
context 'with no credentials' do
53+
it 'returns 401 Unauthorized' do
5354
perform
5455
expect(response).to have_http_status(:unauthorized)
5556
end
5657
end
5758

58-
context "with wrong credentials" do
59+
context 'with wrong credentials' do
5960
let(:headers) do
6061
{
61-
"HTTP_AUTHORIZATION" =>
62-
ActionController::HttpAuthentication::Basic.encode_credentials("user1", "wrong")
62+
'HTTP_AUTHORIZATION' =>
63+
ActionController::HttpAuthentication::Basic.encode_credentials('user1', 'wrong')
6364
}
6465
end
6566

66-
it "returns 401 Unauthorized" do
67+
it 'returns 401 Unauthorized' do
6768
perform
6869
expect(response).to have_http_status(:unauthorized)
6970
end
7071
end
7172

72-
context "with correct credentials" do
73+
context 'with correct credentials' do
7374
let(:headers) do
7475
{
75-
"HTTP_AUTHORIZATION" =>
76-
ActionController::HttpAuthentication::Basic.encode_credentials("user1", "secret")
76+
'HTTP_AUTHORIZATION' =>
77+
ActionController::HttpAuthentication::Basic.encode_credentials('user1', 'secret')
7778
}
7879
end
7980

80-
it "signals the sync and returns 202 Accepted" do
81+
it 'signals the sync and returns 202 Accepted' do
8182
expect(Consyncful::Sync).to receive(:signal_webhook!)
8283
perform
8384
expect(response).to have_http_status(:accepted)

spec/internal/config/routes.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# frozen_string_literal: true
2+
13
Rails.application.routes.draw do
2-
mount Consyncful::Engine => "/consyncful"
3-
end
4+
mount Consyncful::Engine => '/consyncful'
5+
end

spec/rails_helper.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# frozen_string_literal: true
2-
ENV["RAILS_ENV"] ||= "test"
32

4-
require "bundler/setup"
5-
require "combustion"
6-
require "consyncful"
7-
require "consyncful/engine"
3+
ENV['RAILS_ENV'] ||= 'test'
4+
5+
require 'bundler/setup'
6+
require 'combustion'
7+
require 'consyncful'
8+
require 'consyncful/engine'
89

910
Combustion.initialize! :action_controller, :active_support
1011

11-
require "rspec/rails"
12+
require 'rspec/rails'
1213

1314
RSpec.configure do |config|
1415
config.use_active_record = false

0 commit comments

Comments
 (0)