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: 5 additions & 1 deletion app/controllers/accounts/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ def google_oauth2
end

def after_sign_in_path_for(resource_or_scope)
stored_location_for(resource_or_scope) || root_path
stored = stored_location_for(resource_or_scope)
return stored if stored.present?
return page_checkout_path(resource_or_scope) if resource_or_scope.is_a?(Account) && resource_or_scope.requires_payment?

root_path
end

private
Expand Down
7 changes: 5 additions & 2 deletions app/controllers/accounts/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ def create
end

def after_sign_up_path_for(account)
# page_setup_index_path(account)
page_path(account)
if Rails.configuration.multiuser_mode
page_checkout_path(account)
else
page_path(account)
end
end

def update_resource(resource, params)
Expand Down
6 changes: 5 additions & 1 deletion app/controllers/accounts/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ class SessionsController < Devise::SessionsController
# end

def after_sign_in_path_for(account)
stored_location_for(account) || root_path
stored = stored_location_for(account)
return stored if stored.present?
return page_checkout_path(account) if account.is_a?(Account) && account.requires_payment?

root_path
end
end
end
2 changes: 1 addition & 1 deletion app/controllers/checkout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class CheckoutController < ApplicationController
before_action :redirect_in_solo

def show
url = @account.checkout_url(page_setup_url(@account, :domain), page_url(@account))
url = @account.checkout_url(page_url(@account), page_url(@account))
redirect_to url, status: :found, allow_other_host: true
end

Expand Down
18 changes: 18 additions & 0 deletions app/controllers/concerns/payment_required.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module PaymentRequired
extend ActiveSupport::Concern

included do
before_action :require_payment
end

private

def require_payment
return unless current_account&.requires_payment?
return if params.key?(:session_id) # Just returned from Stripe, webhook pending

redirect_to page_checkout_path(current_account)
end
end
1 change: 1 addition & 0 deletions app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class PagesController < ApplicationController
prepend_before_action :authenticate_account!
include PaymentRequired
before_action :set_account
layout 'dashboard'

Expand Down
1 change: 1 addition & 0 deletions app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class PostsController < ApplicationController
prepend_before_action :authenticate_account!
include PaymentRequired
before_action :set_account_from_path
before_action :set_post, only: %i[destroy edit update]

Expand Down
1 change: 1 addition & 0 deletions app/controllers/showcase_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class ShowcaseController < ApplicationController
prepend_before_action :authenticate_account!
include PaymentRequired
before_action :set_account_from_path
layout 'dashboard_container'

Expand Down
1 change: 1 addition & 0 deletions app/controllers/subscribers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

class SubscribersController < ApplicationController
prepend_before_action :authenticate_account!
include PaymentRequired
before_action :set_account_from_path
layout 'dashboard_container'

Expand Down
15 changes: 15 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ def active_subscription?
payment_processor&.subscribed?
end

def requires_payment?
return false if Rails.configuration.solo_mode
return false if grandfathered?
return false if ever_subscribed?

!payment_processor&.subscribed?
end

def ever_subscribed?
Pay::Subscription.joins(:customer)
.where(pay_customers: { owner_type: 'Account', owner_id: id })
.exists?
end

def unverified_domain?
domains.each do |domain|
return true unless domain.verified?
Expand Down Expand Up @@ -212,6 +226,7 @@ def checkout_url(success_url, cancel_url) # rubocop:disable Metrics/MethodLength
allow_promotion_codes: true,
billing_address_collection: 'auto',
payment_method_collection: 'if_required',
subscription_data: { trial_period_days: 30 },
customer_update: {
address: 'auto',
name: 'auto'
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/dashboard.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ secondaryMenuItems = [
name: "Billing",
newTab: false,
to: page_billing_path(@account),
show: @account&.active_subscription? && Rails.configuration.multiuser_mode
show: @account&.payment_processor&.subscribed? && Rails.configuration.multiuser_mode
},
{
name: "Queue",
Expand Down
2 changes: 1 addition & 1 deletion app/views/marketing_pages/_cta.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<span class="block">Ready to set up your website?</span>
</h2>
<p class="mt-4 text-lg leading-6 text-gray-925">Have your page published in minutes.</p>
<a href="<%= new_registration_path('account') %>" class="mt-6 shadow-xl btn btn-big btn-primary">Get started</a>
<a href="<%= new_registration_path('account') %>" class="mt-6 shadow-xl btn btn-big btn-primary">Start free trial</a>
</div>
</div>
<ul class="hidden lg:block">
Expand Down
2 changes: 1 addition & 1 deletion app/views/marketing_pages/_hero.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</p>
<div class="flex items-center mt-9 gap-x-6">
<a href="<%= new_registration_path('account') %>" class="btn btn-primary btn-big">
Make your website
Start your free trial
<%= render :partial => "shared/button_loading_arrow" %>
</a>
<%#>
Expand Down
59 changes: 14 additions & 45 deletions app/views/marketing_pages/_pricing.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,57 @@
<div class="text-center dashboard-container">
<div class="max-w-3xl mx-auto space-y-2 lg:max-w-none">
<h2 class="homepage-label">Pricing</h2>
<p class="text-4xl font-bold leading-8 tracking-tight text-gray-950 sm:text-5xl md:text-6xl">Free page + newsletter</p>
<p class="text-xl text-gray-800">Affordable premium plan for hosting on a custom domain.</p>
<p class="text-4xl font-bold leading-8 tracking-tight text-gray-950 sm:text-5xl md:text-6xl">One simple plan</p>
<p class="text-xl text-gray-800">Everything you need for your personal website and newsletter.</p>
</div>
</div>
</div>
<div class="mt-8 sm:mt-12 sm:pb-16 lg:mt-16">
<div class="relative">
<div class="absolute inset-0 h-3/4"></div>
<div class="relative z-10 px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="max-w-md mx-auto space-y-4 lg:max-w-5xl lg:grid lg:grid-cols-2 lg:gap-5 lg:space-y-0 ">
<div class="max-w-lg mx-auto">
<div class="flex flex-col overflow-hidden border rounded-lg shadow-lg border-gray-050">
<div class="px-6 pt-8 bg-white sm:p-10 sm:pb-0">
<div>
<h3 class="badge-secondary" id="tier-basic">
Basic
</h3>
<h3 class="badge" id="tier-postcard">Postcard</h3>
</div>
<div class="flex items-baseline mt-4 text-6xl font-extrabold">
Free
$4
<span class="ml-1 text-2xl font-medium text-gray-500"> per month </span>
</div>
<p class="mt-5 text-lg text-gray-800">Personal homepage + newsletter</p>
<p class="mt-5 text-lg text-accent font-semibold">30-day free trial</p>
</div>
<div class="flex flex-col justify-between flex-1 px-6 pt-6 pb-8 space-y-6 bg-white sm:px-10 sm:pt-6">
<div class="flex flex-col justify-between flex-1 px-6 pt-6 pb-8 space-y-6 bg-white sm:p-10 sm:pt-6">
<ul role="list" class="space-y-4">
<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "text-gray-500 h-6 w-6" %>
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
</div>
<p class="ml-3 text-base text-gray-700">Personalize your homepage</p>
</li>


<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "h-6 w-6 text-gray-500" %>
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
</div>
<p class="ml-3 text-base text-gray-700">Collect email signups on your page</p>
</li>

<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "h-6 w-6 text-gray-500" %>
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
</div>
<p class="ml-3 text-base text-gray-700">Send emails to your subscribers</p>
</li>

<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "h-6 w-6 text-gray-500" %>
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
</div>
<p class="ml-3 text-base text-gray-700">Host on postcard.page domain</p>
</li>


</ul>
<div class="rounded-md shadow">
<a href="<%= new_registration_path('account') %>" class="flex items-center justify-center w-full btn btn-primary btn-big" aria-describedby="tier-basic"> Make a free account </a>
</div>
</div>
</div>

<div class="flex flex-col overflow-hidden border rounded-lg shadow-lg border-gray-050">
<div class="px-6 pt-8 bg-white sm:p-10 sm:pb-0">
<div>
<h3 class="badge" id="tier-premium">Premium</h3>
</div>
<div class="flex items-baseline mt-4 text-6xl font-extrabold">
$4
<span class="ml-1 text-2xl font-medium text-gray-500"> per month </span>
</div>
<p class="mt-5 text-lg text-gray-800">Connect Postcard on your own domain</p>
</div>
<div class="flex flex-col justify-between flex-1 px-6 pt-6 pb-8 space-y-6 bg-white sm:p-10 sm:pt-6">
<ul role="list" class="space-y-4">
<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
Expand All @@ -90,22 +67,14 @@
</div>
<p class="ml-3 text-base text-gray-700">Add custom code, such as analytics</p>
</li>

<li class="flex items-start">
<div class="flex-shrink-0">
<%= heroicon "check", class: "h-6 w-6 text-accent" %>
</div>
<p class="ml-3 text-base text-gray-700">Integrations + API <span class="text-gray-500">(Coming soon)</span></p>
</li>

</ul>
<div class="rounded-md shadow">
<a href="<%= new_registration_path('account') %>" class="flex items-center justify-center w-full btn btn-primary btn-big" aria-describedby="tier-premium">Get started </a>
<a href="<%= new_registration_path('account') %>" class="flex items-center justify-center w-full btn btn-primary btn-big" aria-describedby="tier-postcard">Start free trial</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
4 changes: 2 additions & 2 deletions app/views/welcome_mailer/how_i_replaced_twitter.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<% end %>

<p>
Hi, I’m Philip - the maker of Postcard! Today I want to share with you how I use Postcard for my own personal website and newsletter at <a href="https://www.philipithomas.com">philipithomas.com</a>.
Hi, I’m Philip - the maker of Postcard! Today I want to share with you how I use Postcard for my own personal website and newsletter at <a href="https://philipithomas.postcard.page">philipithomas.postcard.page</a>.
</p>

<p>
Expand All @@ -17,7 +17,7 @@
</ul>

<p>
(Check out a recent example <a href="https://www.philipithomas.com/posts/what-i-m-up-to-december-2022">here</a>)
(Check out a recent example <a href="https://philipithomas.postcard.page/posts/what-i-m-up-to-december-2022">here</a>)
</p>

<p>
Expand Down
2 changes: 1 addition & 1 deletion app/views/welcome_mailer/social_networks_over.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
If you are ready to break the cycle on addictive social networks, try setting up a personal newsletter with Postcard. You can still participate in social networks by sharing posts on those sites. But you can build a newsletter over time that you own. 
</p>

<p><i>Originally published on <a href="https://www.philipithomas.com/posts/why-i-built-postcard-a-calmer-alternative-to-social-networks">philipithomas.com</a>.</i></p>
<p><i>Originally published on <a href="https://philipithomas.postcard.page/posts/why-i-built-postcard-a-calmer-alternative-to-social-networks">philipithomas.postcard.page</a>.</i></p>

<% content_for :button_label do %>Write your newsletter<% end %>

Expand Down
6 changes: 3 additions & 3 deletions config/brakeman.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,20 @@
{
"warning_type": "Redirect",
"warning_code": 18,
"fingerprint": "7091306dd0b02a1c02eaadd5138fef97feb5c99ac385b19973467ed117fc84e9",
"fingerprint": "e0630695d24b9edc6f4723712fc38efa47e131e46fd11380309fa39f79e3e6c5",
"check_name": "Redirect",
"message": "Possible unprotected redirect",
"file": "app/controllers/checkout_controller.rb",
"line": 10,
"link": "https://brakemanscanner.org/docs/warning_types/redirect/",
"code": "redirect_to(Account.friendly.find(params[:page_slug]).checkout_url(page_setup_url(Account.friendly.find(params[:page_slug]), :domain), page_url(Account.friendly.find(params[:page_slug]))), :status => :found, :allow_other_host => true)",
"code": "redirect_to(Account.friendly.find(params[:page_slug]).checkout_url(page_url(Account.friendly.find(params[:page_slug])), page_url(Account.friendly.find(params[:page_slug]))), :status => :found, :allow_other_host => true)",
"render_path": null,
"location": {
"type": "method",
"class": "CheckoutController",
"method": "show"
},
"user_input": "Account.friendly.find(params[:page_slug]).checkout_url(page_setup_url(Account.friendly.find(params[:page_slug]), :domain), page_url(Account.friendly.find(params[:page_slug])))",
"user_input": "Account.friendly.find(params[:page_slug]).checkout_url(page_url(Account.friendly.find(params[:page_slug])), page_url(Account.friendly.find(params[:page_slug])))",
"confidence": "Weak",
"cwe_id": [
601
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20260312034422_add_grandfathered_to_accounts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class AddGrandfatheredToAccounts < ActiveRecord::Migration[7.1]
def up
add_column :accounts, :grandfathered, :boolean, default: false, null: false
Account.update_all(grandfathered: true)
end

def down
remove_column :accounts, :grandfathered
end
end
3 changes: 2 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions test/fixtures/accounts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
grandfathered_user:
name: Grandfathered User
email: grandfathered@example.com
encrypted_password: <%= Devise::Encryptor.digest(Account, 'password123') %>
slug: grandfathered-user
grandfathered: true
accent_color: "#2c6153"

new_user:
name: New User
email: newuser@example.com
encrypted_password: <%= Devise::Encryptor.digest(Account, 'password123') %>
slug: new-user
grandfathered: false
accent_color: "#2c6153"
Loading
Loading