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
14 changes: 14 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class Account < ApplicationRecord

validates :external_account_id, uniqueness: true, allow_nil: true

after_commit :create_careerplug_webhook, on: :create

scope :active, -> { where(archived_at: nil) }

def self.find_or_create_by_external_id(external_id, name, attributes = {})
Expand All @@ -72,4 +74,16 @@ def default_template_folder
super || build_default_template_folder(name: TemplateFolder::DEFAULT_NAME,
author_id: users.minimum(:id)).tap(&:save!)
end

private

def create_careerplug_webhook
return if ENV['CAREERPLUG_WEBHOOK_SECRET'].blank?

webhook_urls.create!(
url: ENV.fetch('CAREERPLUG_WEBHOOK_URL'),
events: %w[form.viewed form.started form.completed form.declined],
secret: { 'X-CareerPlug-Secret' => ENV.fetch('CAREERPLUG_WEBHOOK_SECRET') }
)
end
end
28 changes: 17 additions & 11 deletions bin/start_console_production
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ fetch_env_variables() {
export NEWRELIC_APP_NAME=$(echo "$SECRET_JSON" | jq -r '.newrelic_app_name')
export NEWRELIC_MONITOR_MODE=$(echo "$SECRET_JSON" | jq -r '.newrelic_monitor_mode')
export ENCRYPTION_SECRET=$(echo "$SECRET_JSON" | jq -r '.ENCRYPTION_SECRET // empty')
export CAREERPLUG_WEBHOOK_SECRET=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_SECRET // empty')
export CAREERPLUG_WEBHOOK_URL=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_URL // empty')


# Validate that we got the values
Expand All @@ -187,19 +189,11 @@ fetch_env_variables() {
# Write variables to .env.production file
echo "Writing environment variables to .env.production..."

# Remove existing DB_HOST, REDIS_URL, and S3_ATTACHMENTS_BUCKET lines if they exist
# Remove existing environment variables if they exist
if [ -f "./.env.production" ]; then
echo "Removing existing variables from .env.production"
grep -v "^DB_HOST=" ./.env.production > ./.env.production.tmp || true
grep -v "^REDIS_URL=" ./.env.production.tmp > ./.env.production || true
grep -v "^S3_ATTACHMENTS_BUCKET=" ./.env.production.tmp > ./.env.production || true
grep -v "^AIRBRAKE_ID=" ./.env.production.tmp > ./.env.production || true
grep -v "^AIRBRAKE_KEY=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_LICENSE_KEY=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_APP_NAME=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_MONITOR_MODE=" ./.env.production.tmp > ./.env.production || true
grep -v "^ENCRYPTION_SECRET=" ./.env.production.tmp > ./.env.production || true
rm -f ./.env.production.tmp
grep -Ev "^(DB_HOST|REDIS_URL|S3_ATTACHMENTS_BUCKET|AIRBRAKE_ID|AIRBRAKE_KEY|NEWRELIC_LICENSE_KEY|NEWRELIC_APP_NAME|NEWRELIC_MONITOR_MODE|ENCRYPTION_SECRET|CAREERPLUG_WEBHOOK_SECRET|CAREERPLUG_WEBHOOK_URL)=" ./.env.production > ./.env.production.tmp || true
mv ./.env.production.tmp ./.env.production
fi

# Append the new credentials
Expand All @@ -218,6 +212,18 @@ fetch_env_variables() {
echo "✓ ENCRYPTION_SECRET written to .env.production"
fi

# Add CareerPlug webhook secret if it exists
if [ -n "$CAREERPLUG_WEBHOOK_SECRET" ]; then
echo "CAREERPLUG_WEBHOOK_SECRET=$CAREERPLUG_WEBHOOK_SECRET" >> ./.env.production
echo "✓ CAREERPLUG_WEBHOOK_SECRET written to .env.production"
fi

# Add CareerPlug webhook URL if it exists
if [ -n "$CAREERPLUG_WEBHOOK_URL" ]; then
echo "CAREERPLUG_WEBHOOK_URL=$CAREERPLUG_WEBHOOK_URL" >> ./.env.production
echo "✓ CAREERPLUG_WEBHOOK_URL written to .env.production"
fi

echo "✓ Environment variables successfully retrieved and written to .env.production"
}

Expand Down
28 changes: 17 additions & 11 deletions bin/start_console_staging
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ fetch_env_variables() {
export NEWRELIC_APP_NAME=$(echo "$SECRET_JSON" | jq -r '.newrelic_app_name')
export NEWRELIC_MONITOR_MODE=$(echo "$SECRET_JSON" | jq -r '.newrelic_monitor_mode')
export ENCRYPTION_SECRET=$(echo "$SECRET_JSON" | jq -r '.ENCRYPTION_SECRET // empty')
export CAREERPLUG_WEBHOOK_SECRET=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_SECRET // empty')
export CAREERPLUG_WEBHOOK_URL=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_URL // empty')

# Validate that we got the values
if [ "$DB_HOST" = "null" ] || [ "$REDIS_URL" = "null" ] || [ "$S3_ATTACHMENTS_BUCKET" = "null" ] || [ -z "$DB_HOST" ] || [ -z "$REDIS_URL" ] || [ -z "$S3_ATTACHMENTS_BUCKET" ]; then
Expand All @@ -186,19 +188,11 @@ fetch_env_variables() {
# Write variables to .env.staging file
echo "Writing environment variables to .env.staging..."

# Remove existing DB_HOST, REDIS_URL, and S3_ATTACHMENTS_BUCKET lines if they exist
# Remove existing environment variables if they exist
if [ -f "./.env.staging" ]; then
echo "Removing existing variables from .env.staging"
grep -v "^DB_HOST=" ./.env.staging > ./.env.staging.tmp || true
grep -v "^REDIS_URL=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^S3_ATTACHMENTS_BUCKET=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^AIRBRAKE_ID=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^AIRBRAKE_KEY=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_LICENSE_KEY=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_APP_NAME=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_MONITOR_MODE=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^ENCRYPTION_SECRET=" ./.env.staging.tmp > ./.env.staging || true
rm -f ./.env.staging.tmp
grep -Ev "^(DB_HOST|REDIS_URL|S3_ATTACHMENTS_BUCKET|AIRBRAKE_ID|AIRBRAKE_KEY|NEWRELIC_LICENSE_KEY|NEWRELIC_APP_NAME|NEWRELIC_MONITOR_MODE|ENCRYPTION_SECRET|CAREERPLUG_WEBHOOK_SECRET|CAREERPLUG_WEBHOOK_URL)=" ./.env.staging > ./.env.staging.tmp || true
mv ./.env.staging.tmp ./.env.staging
fi

# Append the new credentials
Expand All @@ -217,6 +211,18 @@ fetch_env_variables() {
echo "✓ ENCRYPTION_SECRET written to .env.staging"
fi

# Add CareerPlug webhook secret if it exists
if [ -n "$CAREERPLUG_WEBHOOK_SECRET" ]; then
echo "CAREERPLUG_WEBHOOK_SECRET=$CAREERPLUG_WEBHOOK_SECRET" >> ./.env.staging
echo "✓ CAREERPLUG_WEBHOOK_SECRET written to .env.staging"
fi

# Add CareerPlug webhook URL if it exists
if [ -n "$CAREERPLUG_WEBHOOK_URL" ]; then
echo "CAREERPLUG_WEBHOOK_URL=$CAREERPLUG_WEBHOOK_URL" >> ./.env.staging
echo "✓ CAREERPLUG_WEBHOOK_URL written to .env.staging"
fi

echo "✓ Environment variables successfully retrieved and written to .env.staging"
}

Expand Down
39 changes: 23 additions & 16 deletions bin/start_production
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ fetch_allowed_hosts() {
exit 1
fi

# Remove existing ALLOWED_HOSTS line if it exists
if [ -f "./.env.production" ]; then
grep -v "^ALLOWED_HOSTS=" ./.env.production > ./.env.production.tmp || true
mv ./.env.production.tmp ./.env.production
fi

Comment on lines +131 to +136
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there a reason for removing this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed since Docker containers in ECS restart frequently, and the .env.production file persists across restarts, causing duplicates without this cleanup logic. At least that's my understanding 😅

# Write allowed hosts to .env.production file
echo "Writing allowed hosts to .env.production..."
echo "ALLOWED_HOSTS=$ALLOWED_HOSTS" >> ./.env.production
Expand Down Expand Up @@ -170,6 +176,8 @@ fetch_env_variables() {
export SECURED_STORAGE_BUCKET=$(echo "$SECRET_JSON" | jq -r '.secured_storage_bucket')
export SECURED_STORAGE_REGION=$(echo "$SECRET_JSON" | jq -r '.secured_storage_region')
export ENCRYPTION_SECRET=$(echo "$SECRET_JSON" | jq -r '.ENCRYPTION_SECRET // empty')
export CAREERPLUG_WEBHOOK_SECRET=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_SECRET // empty')
export CAREERPLUG_WEBHOOK_URL=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_URL // empty')

# Validate that we got the values
if [ "$DB_HOST" = "null" ] || [ "$REDIS_URL" = "null" ] || [ "$S3_ATTACHMENTS_BUCKET" = "null" ] || [ -z "$DB_HOST" ] || [ -z "$REDIS_URL" ] || [ -z "$S3_ATTACHMENTS_BUCKET" ]; then
Expand All @@ -193,24 +201,11 @@ fetch_env_variables() {
# Write variables to .env.production file
echo "Writing environment variables to .env.production..."

# Remove existing DB_HOST, REDIS_URL, and S3_ATTACHMENTS_BUCKET lines if they exist
# Remove existing environment variables if they exist
if [ -f "./.env.production" ]; then
echo "Removing existing variables from .env.production"
grep -v "^DB_HOST=" ./.env.production > ./.env.production.tmp || true
grep -v "^REDIS_URL=" ./.env.production.tmp > ./.env.production || true
grep -v "^S3_ATTACHMENTS_BUCKET=" ./.env.production.tmp > ./.env.production || true
grep -v "^AIRBRAKE_ID=" ./.env.production.tmp > ./.env.production || true
grep -v "^AIRBRAKE_KEY=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_LICENSE_KEY=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_APP_NAME=" ./.env.production.tmp > ./.env.production || true
grep -v "^NEWRELIC_MONITOR_MODE=" ./.env.production.tmp > ./.env.production || true
grep -v "^CF_URL=" ./.env.production.tmp > ./.env.production || true
grep -v "^CF_KEY_PAIR_ID=" ./.env.production.tmp > ./.env.production || true
grep -v "^CF_KEY_SECRET=" ./.env.production.tmp > ./.env.production || true
grep -v "^SECURED_STORAGE_BUCKET=" ./.env.production.tmp > ./.env.production || true
grep -v "^SECURED_STORAGE_REGION=" ./.env.production.tmp > ./.env.production || true
grep -v "^ENCRYPTION_SECRET=" ./.env.production.tmp > ./.env.production || true
rm -f ./.env.production.tmp
grep -Ev "^(DB_HOST|REDIS_URL|S3_ATTACHMENTS_BUCKET|AIRBRAKE_ID|AIRBRAKE_KEY|NEWRELIC_LICENSE_KEY|NEWRELIC_APP_NAME|NEWRELIC_MONITOR_MODE|CF_URL|CF_KEY_PAIR_ID|CF_KEY_SECRET|SECURED_STORAGE_BUCKET|SECURED_STORAGE_REGION|ENCRYPTION_SECRET|CAREERPLUG_WEBHOOK_SECRET|CAREERPLUG_WEBHOOK_URL)=" ./.env.production > ./.env.production.tmp || true
mv ./.env.production.tmp ./.env.production
fi

# Append the new credentials
Expand All @@ -234,6 +229,18 @@ fetch_env_variables() {
echo "✓ ENCRYPTION_SECRET written to .env.production"
fi

# Add CareerPlug webhook secret if it exists
if [ -n "$CAREERPLUG_WEBHOOK_SECRET" ]; then
echo "CAREERPLUG_WEBHOOK_SECRET=$CAREERPLUG_WEBHOOK_SECRET" >> ./.env.production
echo "✓ CAREERPLUG_WEBHOOK_SECRET written to .env.production"
fi

# Add CareerPlug webhook URL if it exists
if [ -n "$CAREERPLUG_WEBHOOK_URL" ]; then
echo "CAREERPLUG_WEBHOOK_URL=$CAREERPLUG_WEBHOOK_URL" >> ./.env.production
echo "✓ CAREERPLUG_WEBHOOK_URL written to .env.production"
fi

echo "✓ Environment variables successfully retrieved and written to .env.production"
}

Expand Down
33 changes: 17 additions & 16 deletions bin/start_staging
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ fetch_env_variables() {
export SECURED_STORAGE_BUCKET=$(echo "$SECRET_JSON" | jq -r '.secured_storage_bucket')
export SECURED_STORAGE_REGION=$(echo "$SECRET_JSON" | jq -r '.secured_storage_region')
export ENCRYPTION_SECRET=$(echo "$SECRET_JSON" | jq -r '.ENCRYPTION_SECRET // empty')
export CAREERPLUG_WEBHOOK_SECRET=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_SECRET // empty')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add CAREERPLUG_WEBHOOK_URL?

export CAREERPLUG_WEBHOOK_URL=$(echo "$SECRET_JSON" | jq -r '.CAREERPLUG_WEBHOOK_URL // empty')


# Validate that we got the values
Expand All @@ -198,24 +200,11 @@ fetch_env_variables() {
# Write variables to .env.staging file
echo "Writing environment variables to .env.staging..."

# Remove existing DB_HOST, REDIS_URL, and S3_ATTACHMENTS_BUCKET lines if they exist
# Remove existing environment variables if they exist
if [ -f "./.env.staging" ]; then
echo "Removing existing variables from .env.staging"
grep -v "^DB_HOST=" ./.env.staging > ./.env.staging.tmp || true
grep -v "^REDIS_URL=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^S3_ATTACHMENTS_BUCKET=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^AIRBRAKE_ID=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^AIRBRAKE_KEY=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_LICENSE_KEY=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_APP_NAME=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^NEWRELIC_MONITOR_MODE=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^CF_URL=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^CF_KEY_PAIR_ID=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^CF_KEY_SECRET=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^SECURED_STORAGE_BUCKET=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^SECURED_STORAGE_REGION=" ./.env.staging.tmp > ./.env.staging || true
grep -v "^ENCRYPTION_SECRET=" ./.env.staging.tmp > ./.env.staging || true
rm -f ./.env.staging.tmp
grep -Ev "^(DB_HOST|REDIS_URL|S3_ATTACHMENTS_BUCKET|AIRBRAKE_ID|AIRBRAKE_KEY|NEWRELIC_LICENSE_KEY|NEWRELIC_APP_NAME|NEWRELIC_MONITOR_MODE|CF_URL|CF_KEY_PAIR_ID|CF_KEY_SECRET|SECURED_STORAGE_BUCKET|SECURED_STORAGE_REGION|ENCRYPTION_SECRET|CAREERPLUG_WEBHOOK_SECRET|CAREERPLUG_WEBHOOK_URL)=" ./.env.staging > ./.env.staging.tmp || true
mv ./.env.staging.tmp ./.env.staging
fi

# Append the new credentials
Expand All @@ -239,6 +228,18 @@ fetch_env_variables() {
echo "✓ ENCRYPTION_SECRET written to .env.staging"
fi

# Add CareerPlug webhook secret if it exists
if [ -n "$CAREERPLUG_WEBHOOK_SECRET" ]; then
echo "CAREERPLUG_WEBHOOK_SECRET=$CAREERPLUG_WEBHOOK_SECRET" >> ./.env.staging
echo "✓ CAREERPLUG_WEBHOOK_SECRET written to .env.staging"
fi

# Add CareerPlug webhook URL if it exists
if [ -n "$CAREERPLUG_WEBHOOK_URL" ]; then
echo "CAREERPLUG_WEBHOOK_URL=$CAREERPLUG_WEBHOOK_URL" >> ./.env.staging
echo "✓ CAREERPLUG_WEBHOOK_URL written to .env.staging"
fi

echo "✓ Environment variables successfully retrieved and written to .env.staging"
}

Expand Down
5 changes: 5 additions & 0 deletions config/dotenv.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# frozen_string_literal: true

if ENV['RAILS_ENV'] == 'development'
require 'dotenv'
Dotenv.load('.env')
end

if ENV['RAILS_ENV'] == 'production' || ENV['RAILS_ENV'] == 'staging'
if !ENV['AWS_SECRET_MANAGER_ID'].to_s.empty?
require 'aws-sdk-secretsmanager'
Expand Down
57 changes: 57 additions & 0 deletions lib/tasks/webhooks.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

namespace :webhooks do
desc 'Configure CareerPlug webhook secret from CAREERPLUG_WEBHOOK_SECRET env var'
task configure_careerplug: :environment do
secret = ENV.fetch('CAREERPLUG_WEBHOOK_SECRET') do
if Rails.env.development?
'development_webhook_secret'
else
abort 'CAREERPLUG_WEBHOOK_SECRET environment variable is required'
end
end

webhook_urls = WebhookUrl.where('url LIKE ? OR url LIKE ? OR url LIKE ?',
'%careerplug%', '%cpats%', '%localhost:3000%')

if webhook_urls.any?
webhook_urls.find_each do |webhook_url|
webhook_url.update!(secret: { 'X-CareerPlug-Secret' => secret })
puts "Updated webhook secret for #{webhook_url.url}"
end
puts "Updated #{webhook_urls.count} webhook URL(s)"
else
puts 'No CareerPlug webhook URLs found. Available webhooks:'
WebhookUrl.find_each { |w| puts " - #{w.id}: #{w.url}" }
end
end

desc 'Set up development webhook URLs for all accounts (creates URLs + configures secret)'
task setup_development: :environment do
abort 'This task is only for development' unless Rails.env.development?

url = 'http://localhost:3000/api/docuseal/events'
secret = { 'X-CareerPlug-Secret' => 'development_webhook_secret' }
events = %w[form.viewed form.started form.completed form.declined]

created = 0
updated = 0

Account.find_each do |account|
webhook_url = WebhookUrl.find_or_initialize_by(account: account, sha1: Digest::SHA1.hexdigest(url))

if webhook_url.new_record?
webhook_url.assign_attributes(url: url, events: events, secret: secret)
webhook_url.save!
created += 1
puts "Created webhook URL for account #{account.id}: #{account.name}"
elsif webhook_url.secret != secret
webhook_url.update!(secret: secret)
updated += 1
puts "Updated webhook secret for account #{account.id}: #{account.name}"
end
end

puts "Done: #{created} created, #{updated} updated"
end
end
65 changes: 65 additions & 0 deletions spec/models/account_create_careerplug_webhook_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Account, '#create_careerplug_webhook' do
around do |example|
original_secret = ENV.fetch('CAREERPLUG_WEBHOOK_SECRET', nil)
original_url = ENV.fetch('CAREERPLUG_WEBHOOK_URL', nil)

# Set required env vars for webhook creation
ENV['CAREERPLUG_WEBHOOK_SECRET'] = 'test_secret'
ENV['CAREERPLUG_WEBHOOK_URL'] = 'http://example.com/webhook'

example.run

# Restore original env vars
ENV['CAREERPLUG_WEBHOOK_SECRET'] = original_secret
ENV['CAREERPLUG_WEBHOOK_URL'] = original_url
end

describe 'CareerPlug webhook creation' do
it 'creates webhook after successful account creation' do
account = build(:account)
expect(account.webhook_urls).to be_empty

account.save!

expect(account.webhook_urls.count).to eq(1)
webhook = account.webhook_urls.first
expect(webhook.url).to eq('http://example.com/webhook')
expect(webhook.events).to eq(['form.viewed', 'form.started', 'form.completed', 'form.declined'])
expect(webhook.secret).to eq({ 'X-CareerPlug-Secret' => 'test_secret' })
end

it 'does not create webhook if account creation fails' do
# This test verifies that after_commit behavior works correctly
# by simulating a transaction rollback

expect do
described_class.transaction do
create(:account)
# Simulate some error that would cause rollback
raise ActiveRecord::Rollback
end
end.not_to change(described_class, :count)

expect do
described_class.transaction do
create(:account)
raise ActiveRecord::Rollback
end
end.not_to change(WebhookUrl, :count)
end

it 'does not create webhook when CAREERPLUG_WEBHOOK_SECRET is blank' do
original_secret = ENV.fetch('CAREERPLUG_WEBHOOK_SECRET', nil)
ENV['CAREERPLUG_WEBHOOK_SECRET'] = ''

account = create(:account)
expect(account.webhook_urls.count).to eq(0)

ENV['CAREERPLUG_WEBHOOK_SECRET'] = original_secret
end
end
end
Loading