From: Aidan Cornelius-Bell Date: Tue, 8 Oct 2024 08:02:49 +0000 (+1030) Subject: Added subscriptions, yo X-Git-Url: https://gitweb.mndrdr.org/?a=commitdiff_plain;h=95921c6b9fe3d72a0e120b10e2168cd89b250804;p=arelpe.git Added subscriptions, yo --- diff --git a/Gemfile b/Gemfile index 59be3ae..09f2d0b 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,8 @@ gem "httparty" gem "dotenv" #humanity verification gem "hcaptcha" +# subscribers +gem "stripe" # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] # gem "kredis" #api stuff diff --git a/Gemfile.lock b/Gemfile.lock index fae35dc..b9066b7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -291,6 +291,7 @@ GEM activesupport (>= 6.1) sprockets (>= 3.0.0) stringio (3.1.1) + stripe (13.0.0) thor (1.3.2) timeout (0.4.1) tzinfo (2.0.6) @@ -341,6 +342,7 @@ DEPENDENCIES rubocop-rails-omakase selenium-webdriver sprockets-rails + stripe tzinfo-data web-console diff --git a/app/assets/images/aidan_about_u.svg b/app/assets/images/aidan_about_u.svg new file mode 100644 index 0000000..7477c08 --- /dev/null +++ b/app/assets/images/aidan_about_u.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/aidan_arrow.svg b/app/assets/images/aidan_arrow.svg new file mode 100644 index 0000000..e84bdd8 --- /dev/null +++ b/app/assets/images/aidan_arrow.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/aidan_be_premium.svg b/app/assets/images/aidan_be_premium.svg new file mode 100644 index 0000000..f6e2d87 --- /dev/null +++ b/app/assets/images/aidan_be_premium.svg @@ -0,0 +1,717 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/aidan_dispatches.svg b/app/assets/images/aidan_dispatches.svg new file mode 100644 index 0000000..fefa5fe --- /dev/null +++ b/app/assets/images/aidan_dispatches.svg @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3c95e20..7989027 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -271,6 +271,16 @@ footer p { padding: 20px; } +.aidans_arrow { + max-width: 70px; + float: right; + padding: 20px; +} + +.aidan_about_u { + max-width: 360px; +} + .post .container p img { max-width: 170px; float: right; diff --git a/app/controllers/.DS_Store b/app/controllers/.DS_Store index 315c166..b0dba72 100644 Binary files a/app/controllers/.DS_Store and b/app/controllers/.DS_Store differ diff --git a/app/controllers/mailing_lists_controller.rb b/app/controllers/mailing_lists_controller.rb new file mode 100644 index 0000000..39144be --- /dev/null +++ b/app/controllers/mailing_lists_controller.rb @@ -0,0 +1,36 @@ +class MailingListsController < ApplicationController + before_action :authenticate_user! + + def index + @user = current_user + @buttondown_status = @user.buttondown_status + @is_paid_user = @user.paid_user? + end + + def subscribe + result = ButtondownService.new.subscribe(current_user) + if result + redirect_to mailing_lists_path, notice: "Successfully subscribed to the mailing list." + else + redirect_to mailing_lists_path, alert: "Failed to subscribe. Please try again later." + end + end + + def unsubscribe + result = ButtondownService.new.unsubscribe(current_user) + if result + redirect_to mailing_lists_path, notice: "Successfully unsubscribed from the mailing list." + else + redirect_to mailing_lists_path, alert: "Failed to unsubscribe. Please try again later." + end + end + + def sync_status + result = ButtondownService.new.update_subscriber(current_user) + if result + redirect_to mailing_lists_path, notice: "Successfully synced subscription status." + else + redirect_to mailing_lists_path, alert: "Failed to sync subscription status. Please try again later." + end + end +end \ No newline at end of file diff --git a/app/controllers/pubview_controller.rb b/app/controllers/pubview_controller.rb index c1aa555..e947fcb 100644 --- a/app/controllers/pubview_controller.rb +++ b/app/controllers/pubview_controller.rb @@ -1,5 +1,4 @@ class PubviewController < ApplicationController - before_action :set_pages, only: [:index, :show_public] def index @per_page = 15 @@ -68,14 +67,4 @@ class PubviewController < ApplicationController word_count = content.split.size (word_count / 200.0).ceil end - - def set_pages - @pages = Page.where(visibility: :visible) - .order(Arel.sql("CASE - WHEN title = 'About' THEN 1 - WHEN title = 'Sponsorship' THEN 2 - ELSE 3 - END")) - .limit(2) - end end diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb new file mode 100644 index 0000000..a601317 --- /dev/null +++ b/app/controllers/subscriptions_controller.rb @@ -0,0 +1,107 @@ +class SubscriptionsController < ApplicationController + before_action :authenticate_user! + + def index + @user = current_user + @subscription_status = @user.subscription_status + @support_type = @user.support_type + @last_payment_date = @user.last_payment_at + @last_payment_amount = @user.payment_amount + + if @user.stripe_customer_id.present? + Stripe.api_key = Rails.configuration.stripe[:secret_key] + @payments = Stripe::PaymentIntent.list(customer: @user.stripe_customer_id) + @portal_session = create_portal_session if @user.subscription_status == 'active' + else + @payments = [] + end + end + + def new + end + + def create + support_type = params[:support_type] + payment_amount = params[:payment_amount]&.gsub(/[^0-9.]/, '')&.to_f + + if support_type == 'non_financial' + current_user.update(support_type: 'non_financial') + AdminMailer.new_non_financial_member(current_user).deliver_later + redirect_to subscriptions_path, notice: 'Thank you for your non-financial support!' + elsif ['one_time', 'ongoing'].include?(support_type) + begin + process_payment(support_type, payment_amount) + AdminMailer.new_paid_member(current_user).deliver_later + redirect_to subscriptions_path, notice: 'Thank you for your support, it means the world to me! I will be in touch.' + rescue Stripe::CardError => e + flash.now[:error] = e.message + render :new + rescue Stripe::StripeError => e + flash.now[:error] = "An error occurred while processing your payment: #{e.message}" + render :new + rescue => e + flash.now[:error] = "An unexpected error occurred: #{e.message}" + render :new + end + else + flash.now[:error] = 'Invalid support type' + render :new + end + end + + private + + def create_portal_session + Stripe::BillingPortal::Session.create({ + customer: current_user.stripe_customer_id, + return_url: subscriptions_url, + }) + end + + def process_payment(support_type, amount) + amount_cents = (amount * 100).to_i + + Stripe.api_key = Rails.configuration.stripe[:secret_key] + + if current_user.stripe_customer_id.blank? + customer = Stripe::Customer.create({ + email: current_user.email, + source: params[:stripeToken] + }) + current_user.update(stripe_customer_id: customer.id) + else + customer = Stripe::Customer.retrieve(current_user.stripe_customer_id) + Stripe::Customer.update(customer.id, { + source: params[:stripeToken] + }) + end + + if support_type == 'ongoing' + product = Stripe::Product.create(name: 'Ongoing Support') + price = Stripe::Price.create({ + unit_amount: amount_cents, + currency: 'aud', + recurring: {interval: 'year'}, + product: product.id, + }) + + subscription = Stripe::Subscription.create({ + customer: customer.id, + items: [{price: price.id}], + }) + current_user.update(subscription_status: 'active', buttondown_status: 'premium', support_type: 'ongoing') + else + payment_intent = Stripe::PaymentIntent.create({ + amount: amount_cents, + currency: 'aud', + customer: customer.id, + payment_method_types: ['card'], + description: 'One-time donation', + confirm: true, + }) + current_user.update(subscription_status: 'one_time', buttondown_status: 'premium', support_type: 'one_time') + end + + current_user.update(last_payment_at: Time.current, payment_amount: amount) + end +end \ No newline at end of file diff --git a/app/assets/images/.DS_Store b/app/controllers/users/.DS_Store similarity index 100% copy from app/assets/images/.DS_Store copy to app/controllers/users/.DS_Store diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb new file mode 100644 index 0000000..7f846c7 --- /dev/null +++ b/app/controllers/users/confirmations_controller.rb @@ -0,0 +1,17 @@ +class Users::ConfirmationsController < Devise::ConfirmationsController + def show + super do |resource| + if resource.errors.empty? + resource.post_confirmation_setup if resource.respond_to?(:post_confirmation_setup) + set_flash_message!(:notice, :confirmed_and_subscribe) + redirect_to new_subscription_path and return + end + end + end + + protected + + def after_confirmation_path_for(resource_name, resource) + new_subscription_path + end +end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index 837c1c3..5a12454 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,8 +1,66 @@ class Users::RegistrationsController < Devise::RegistrationsController - prepend_before_action :check_captcha, only: [:create] + prepend_before_action :check_captcha, only: [:create], if: -> { Rails.configuration.hcaptcha_enabled } + + def create + super do |user| + if ['one_time', 'ongoing'].include?(params[:user][:support_type]) + process_payment(user) + else + user.update(buttondown_status: 'unpaid') + end + end + end private + def sign_up_params + params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :subscribe_to_newsletter, :payment_amount, :support_type) + end + + def process_payment(user) + amount = (params[:user][:payment_amount].to_f * 100).to_i # Convert to cents + + begin + customer = Stripe::Customer.create({ + email: user.email, + source: params[:stripeToken] + }) + + user.update(stripe_customer_id: customer.id) + + if params[:user][:support_type] == 'ongoing' + subscription = Stripe::Subscription.create({ + customer: customer.id, + items: [{ + price_data: { + unit_amount: amount, + currency: 'usd', + recurring: { interval: 'year' }, + product: 'prod_your_product_id_here' # Replace with your actual product ID + } + }], + }) + user.update(subscription_status: 'active', buttondown_status: 'premium') + else + charge = Stripe::Charge.create({ + amount: amount, + currency: 'usd', + customer: customer.id, + description: 'One-time donation' + }) + user.update(subscription_status: 'one_time', buttondown_status: 'premium') + end + + user.update(last_payment_at: Time.current, payment_amount: amount / 100.0) + rescue Stripe::CardError => e + flash[:error] = e.message + user.update(buttondown_status: 'unpaid') + rescue Stripe::StripeError => e + flash[:error] = "An error occurred while processing your payment: #{e.message}" + user.update(buttondown_status: 'unpaid') + end + end + def check_captcha unless verify_hcaptcha self.resource = resource_class.new sign_up_params @@ -12,8 +70,4 @@ class Users::RegistrationsController < Devise::RegistrationsController respond_with_navigational(resource) { render :new } end end - - def sign_up_params - params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation) - end end \ No newline at end of file diff --git a/app/helpers/mailing_lists_helper.rb b/app/helpers/mailing_lists_helper.rb new file mode 100644 index 0000000..46bdf7f --- /dev/null +++ b/app/helpers/mailing_lists_helper.rb @@ -0,0 +1,2 @@ +module MailingListsHelper +end diff --git a/app/helpers/subscriptions_helper.rb b/app/helpers/subscriptions_helper.rb new file mode 100644 index 0000000..9ace045 --- /dev/null +++ b/app/helpers/subscriptions_helper.rb @@ -0,0 +1,2 @@ +module SubscriptionsHelper +end diff --git a/app/assets/images/.DS_Store b/app/mailers/.DS_Store similarity index 100% copy from app/assets/images/.DS_Store copy to app/mailers/.DS_Store diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb new file mode 100644 index 0000000..7cc3054 --- /dev/null +++ b/app/mailers/admin_mailer.rb @@ -0,0 +1,11 @@ +class AdminMailer < ApplicationMailer + def new_paid_member(user) + @user = user + mail(to: ENV['ADMIN_EMAIL'], subject: 'mind reader :: New Paid Member') + end + + def new_non_financial_member(user) + @user = user + mail(to: ENV['ADMIN_EMAIL'], subject: 'mind reader :: New Non-Financial Member') + end +end diff --git a/app/mailers/welcome_mailer.rb b/app/mailers/welcome_mailer.rb new file mode 100644 index 0000000..a99f9d1 --- /dev/null +++ b/app/mailers/welcome_mailer.rb @@ -0,0 +1,25 @@ +class WelcomeMailer < ApplicationMailer + def welcome_email(user) + @user = user + @paid = user.paid_user? + @subscription_type = determine_subscription_type(user) + mail(to: @user.email, subject: 'Welcome to mind reader') + end + + private + + def determine_subscription_type(user) + case user.buttondown_status + when 'premium' + 'Premium' + when 'trialed' + 'Trial' + when 'gifted' + 'Gifted' + when 'regular' + 'Regular' + else + 'Free' + end + end +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 4fd5fc6..d21d2ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,27 @@ class User < ApplicationRecord validates :first_name, presence: true validates :last_name, presence: true + attribute :subscribe_to_newsletter, :boolean, default: false + attribute :stripe_customer_id, :string + attribute :subscription_status, :string + attribute :subscription_type, :string + attribute :last_payment_at, :datetime + attribute :payment_amount, :decimal + attribute :buttondown_status, :string, default: 'unactivated' + attribute :support_type, :string + + def one_time_donor? + subscription_status == 'one_time' + end + + def ongoing_subscriber? + subscription_status == 'active' + end + + def non_financial_supporter? + support_type == 'non_financial' + end + def full_name "#{first_name} #{last_name}" end @@ -15,4 +36,27 @@ class User < ApplicationRecord def admin? admin end + + def paid_user? + ['premium', 'gifted', 'trialed', 'churning', 'paused', 'past_due'].include?(buttondown_status) || + subscription_status == 'active' || subscription_status == 'one_time' + end + + def active_subscriber? + ['premium', 'trialed', 'gifted'].include?(buttondown_status) + end + + def post_confirmation_setup + sync_with_buttondown if subscribe_to_newsletter? + send_welcome_email + end + + private + def sync_with_buttondown + ButtondownService.new.subscribe(self) + end + + def send_welcome_email + WelcomeMailer.welcome_email(self).deliver_later + end end diff --git a/app/services/buttondown_service.rb b/app/services/buttondown_service.rb new file mode 100644 index 0000000..e2b01bb --- /dev/null +++ b/app/services/buttondown_service.rb @@ -0,0 +1,64 @@ +class ButtondownService + include HTTParty + base_uri 'https://api.buttondown.email/v1' + + def initialize + @options = { + headers: { + 'Authorization' => "Token #{ENV['BUTTONDOWN_API_KEY']}", + 'Content-Type' => 'application/json', + 'Accept' => 'application/json' + } + } + end + + def subscribe(user) + body = { + email_address: user.email, + notes: user.paid_user? ? 'Paid subscriber' : 'Free subscriber', + type: determine_subscriber_type(user), + metadata: { + name: user.full_name + } + } + response = self.class.post('/subscribers', @options.merge(body: body.to_json)) + update_user_buttondown_status(user, response) if response.success? + response.success? + end + + def update_subscriber(user) + body = { + notes: user.paid_user? ? 'Paid subscriber' : 'Free subscriber', + type: determine_subscriber_type(user), + metadata: { + name: user.full_name + } + } + response = self.class.patch("/subscribers/#{user.email}", @options.merge(body: body.to_json)) + update_user_buttondown_status(user, response) if response.success? + response.success? + end + + def unsubscribe(user) + response = self.class.delete("/subscribers/#{user.email}", @options) + user.update(buttondown_status: 'unactivated') if response.success? + response.success? + end + + private + + def determine_subscriber_type(user) + if user.paid_user? + 'gifted' + elsif user.buttondown_status == 'unactivated' + 'regular' + else + user.buttondown_status + end + end + + def update_user_buttondown_status(user, response) + buttondown_data = JSON.parse(response.body) + user.update(buttondown_status: buttondown_data['type']) + end +end \ No newline at end of file diff --git a/app/views/.DS_Store b/app/views/.DS_Store index 1755872..ffc9d06 100644 Binary files a/app/views/.DS_Store and b/app/views/.DS_Store differ diff --git a/app/assets/images/.DS_Store b/app/views/admin_mailer/.DS_Store similarity index 100% copy from app/assets/images/.DS_Store copy to app/views/admin_mailer/.DS_Store diff --git a/app/views/admin_mailer/new_non_financial_member.html.erb b/app/views/admin_mailer/new_non_financial_member.html.erb new file mode 100644 index 0000000..26212f1 --- /dev/null +++ b/app/views/admin_mailer/new_non_financial_member.html.erb @@ -0,0 +1,13 @@ +

New Paid Member

+ +

A new user has become a paid member:

+ + + +

Please ensure that their account is properly set up and they have access to all paid member benefits.

\ No newline at end of file diff --git a/app/views/admin_mailer/new_paid_member.html.erb b/app/views/admin_mailer/new_paid_member.html.erb new file mode 100644 index 0000000..43bb8ba --- /dev/null +++ b/app/views/admin_mailer/new_paid_member.html.erb @@ -0,0 +1,5 @@ +

Admin#new_paid_member

+ +

+ <%= @greeting %>, find me in app/views/admin_mailer/new_paid_member.html.erb +

diff --git a/app/views/devise/base_template.html.erb b/app/views/devise/base_template.html.erb deleted file mode 100644 index 7c29747..0000000 --- a/app/views/devise/base_template.html.erb +++ /dev/null @@ -1,49 +0,0 @@ -
-

<%= yield(:title) %>

- - <%= yield(:form_content) %> - - -
- - \ No newline at end of file diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb index 4681e7c..d8f5bf0 100644 --- a/app/views/devise/confirmations/new.html.erb +++ b/app/views/devise/confirmations/new.html.erb @@ -16,4 +16,4 @@ <% end %> <% end %> -<%= render template: 'devise/base_template' %> \ No newline at end of file +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index 5c7c5e0..6e966ac 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -15,4 +15,4 @@ <% end %> <% end %> -<%= render template: 'devise/base_template' %> \ No newline at end of file +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 3d35d10..3d44108 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -3,6 +3,19 @@ <% content_for :form_content do %>

Welcome back, <%= resource.first_name %>. Your email address is <%= resource.confirmed? ? "confirmed":"not yet confirmed, please check your email soon" %>.

+ <% if current_user %> + <% if current_user.ongoing_subscriber? %> +

Thank you for your ongoing support!

+ <% elsif current_user.one_time_donor? %> +

Thank you for your one-time donation!

+ <% elsif current_user.non_financial_supporter? %> +

Thank you for your non-financial support!

+ <% else %> +

Consider supporting mind reader to access premium features!

+ <% end %> + <% end %> + +

Are you looking to get emails with new dispatches? You still need to register and confirm your email by following instructions here.

On this page below you can modify your registration.

@@ -54,10 +67,13 @@ <% end %> <%= button_to "Log out", destroy_user_session_path, method: :delete %> - <% if current_user&.admin? %> -

Keys to the kingdom

-

As an author and administrator of mind reader you cannot delete your account here. You need to remove administrative privileges first, then you may modify your account.

-

Privilege destruction can only be done from the rails console.

+ <% if current_user&.admin? or current_user&.support_type? %> +

Account tools

+

You can <%= link_to "stop receiving mind reader emails", mailing_lists_path %> by clicking the link on this page at any time.

+

You cancel your financial support <%= link_to "on this page", subscriptions_path %> at any time without contacting a human.

+

Account removal

+

As an author, member, or past financial contributor to mind reader you cannot delete your account here. You will need to contact Aidan to request deletion, this way we can ensure you do not incur any expense or friction when leaving.

+

Contact me here and I will remove your account, subscriptions, emails and any associated data within 96 hours.

<% else %>

Cancel my account

If you wish, you may delete your registration with this website. Please be aware, by doing this you will lose access to any content you have purchased or been granted. You will not be unsubscribed from dispatches at the same email address as this is a separate system.

@@ -66,4 +82,4 @@ <% end %> <% end %> -<%= render template: 'devise/base_template' %> \ No newline at end of file +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index c9efc47..6cfcf9f 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,17 +1,19 @@ <% content_for :title do %>Sign up<% end %> - <% content_for :form_content do %> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= render "devise/shared/error_messages", resource: resource %> - -
- <%= f.label :first_name %> - <%= f.text_field :first_name, autofocus: true %> -
- -
- <%= f.label :last_name %> - <%= f.text_field :last_name %> + + <%= image_tag "aidan_about_u.svg", class: "aidan_about_u", alt: "To get started, tell me about yourself:" %> + +
+
+ <%= f.label :first_name %> + <%= f.text_field :first_name, autofocus: true %> +
+
+ <%= f.label :last_name %> + <%= f.text_field :last_name %> +
@@ -19,27 +21,36 @@ <%= f.email_field :email, autocomplete: "email" %>
-
- <%= f.label :password %> - <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %> - <%= f.password_field :password, autocomplete: "new-password" %> -
- -
- <%= f.label :password_confirmation %> - <%= f.password_field :password_confirmation, autocomplete: "new-password" %> +
+
+ <%= f.label :password %> + <%= f.password_field :password, autocomplete: "new-password", placeholder: @minimum_password_length ? "#{@minimum_password_length} characters minimum" : "" %> +
+ +
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: "new-password" %> +
+ <%= image_tag "aidan_dispatches.svg", class: "aidan_about_u", alt: "Want new dispatches delivered right to you?" %> + +
+ <%= f.check_box :subscribe_to_newsletter %> + <%= f.label :subscribe_to_newsletter, "I want to receive mind reader dispatches by email newsletter", id: "sub" %> +
+

Note: you may be sent two confirmation emails – one to confirm your registration, one to confirm your mailing list preferences.

+ + <% if Rails.env.production? %>
<%= hcaptcha_tags %>
+ <% end %>
- <%= f.submit "Sign up" %> + <%= f.submit "Sign up", class: "button primary" %>
<% end %> <% end %> -<%= render template: 'devise/base_template' %> \ No newline at end of file +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 05b72a2..a471d0d 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -25,4 +25,4 @@ <% end %> <% end %> -<%= render template: 'devise/base_template' %> \ No newline at end of file +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/layouts/_home_post_links.html.erb b/app/views/layouts/_home_post_links.html.erb new file mode 100644 index 0000000..0d43f21 --- /dev/null +++ b/app/views/layouts/_home_post_links.html.erb @@ -0,0 +1,8 @@ +<% if !@post&.short_dispatch? %> +<% if @post&.title? %>

Follow via RSS, Email or Membership...

<% end %> +

→ Prefer email or want to sponsor? Learn about supporting my work and joining the free mailing list <%= link_to "right here ↙︎".html_safe, "/join/" %>.

+

→ Prefer RSS? you can subscribe to a combined <%= link_to "bookmarks+dispatches feed here ↙︎".html_safe, rss_path %> or <%= link_to "full text dispatches only feed here ↗︎".html_safe, dispatches_rss_path %>.

+<% end %> +<% if @post %> +

<%= link_to "↑ Back to top", "#top" %> or <%= link_to "↼ Back to some other dispatches...", "#{root_path}?filter=posts" %>

+<% end %> \ No newline at end of file diff --git a/app/views/layouts/_navigation_buttons.html.erb b/app/views/layouts/_navigation_buttons.html.erb new file mode 100644 index 0000000..f4d1725 --- /dev/null +++ b/app/views/layouts/_navigation_buttons.html.erb @@ -0,0 +1,19 @@ +
+ <%= link_to "All", root_path(filter: 'all'), class: "button #{@filter == 'all' ? 'active' : ''}" %> + <%= link_to "Dispatches", root_path(filter: 'posts'), class: "button #{@filter == 'posts' ? 'active' : ''}" %> + <%= link_to "Bookmarks", root_path(filter: 'bookmarks'), class: "button #{@filter == 'bookmarks' ? 'active' : ''}" %> + <%= link_to "About", public_page_path("about"), class: "button #{@page.is_a?(Page) && @page.slug == 'about' ? 'active' : ''}" %> + + <% if !current_user %> + <%= link_to "Join mind reader", join_path, class: "button" %> + <% else %> + <%= link_to "Manage membership", subscriptions_path, class: "button #{controller_name == 'subscriptions' ? 'active' : ''}" %> + <%= link_to "Manage emails", mailing_lists_path, class: "button #{controller_name == 'mailing_lists' ? 'active' : ''}" %> + <% end %> + + <% if current_user&.admin? %> + <%= link_to "Manage Posts", posts_path, class: "button" %> + <%= link_to "Manage Pages", pages_path, class: "button" %> + <%= link_to "Manage API Keys", api_keys_path, class: "button" %> + <% end %> +
\ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index bc10708..9571de8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -40,10 +40,11 @@ <%= yield %>
- +

© <%= Time.current.year %> <%= link_to "Aidan Cornelius-Bell", "https://aidan.cornelius-bell.com" %>, CC-NC-SA.

This site is managed from the sovereign Yarta of the Kaurna Miyurna, with respect and gratitude for the custodianship of Elders past and present of the many Countries it may appear upon.

For legal purposes: any views expressed directly on this website are my own and not reflective of those of any employers, colleagues or affiliates. Links provided remain the views and intellectual property of their respective owners.

+ <%= yield :javascript %> \ No newline at end of file diff --git a/app/views/layouts/user_page_template.html.erb b/app/views/layouts/user_page_template.html.erb new file mode 100644 index 0000000..bab9cee --- /dev/null +++ b/app/views/layouts/user_page_template.html.erb @@ -0,0 +1,152 @@ +
+ <%= link_to root_path do %> + <%= image_tag "icon-512.png", class: "logo" %> + <% end %> + <% content_for :title %> +

<%= content_for :title %>

+ + <%= render partial: "layouts/navigation_buttons" %> +
+ +
+
+ <%= yield(:form_content) %> +
+
+ + + + + \ No newline at end of file diff --git a/app/views/mailing_lists/edit.html.erb b/app/views/mailing_lists/edit.html.erb new file mode 100644 index 0000000..12136ff --- /dev/null +++ b/app/views/mailing_lists/edit.html.erb @@ -0,0 +1,2 @@ +

MailingLists#edit

+

Find me in app/views/mailing_lists/edit.html.erb

diff --git a/app/views/mailing_lists/index.html.erb b/app/views/mailing_lists/index.html.erb new file mode 100644 index 0000000..3961721 --- /dev/null +++ b/app/views/mailing_lists/index.html.erb @@ -0,0 +1,29 @@ +<% content_for :title do %>Your mailing list membership<% end %> +<% content_for :form_content do %> + +<% if @buttondown_status == 'unactivated' %> +

You are not currently subscribed to our mailing list.

+ <%= button_to "Subscribe", subscribe_mailing_lists_path, method: :post, class: "button" %> +<% else %> +

Your current subscription status: <%= @buttondown_status.titleize %>

+ + <% if @is_paid_user %> +

You are a paid subscriber. Thank you for your support!

+ <% if @buttondown_status != 'gifted' %> +

Your mailing list status is not synced with your paid status. Click below to sync:

+ <%= button_to "Sync Subscription Status", sync_status_mailing_lists_path, method: :post, class: "button" %> + <% end %> + <% end %> + + <%= button_to "Unsubscribe", unsubscribe_mailing_lists_path, method: :delete, class: "button danger", data: { confirm: "Are you sure you want to unsubscribe?" } %> +<% end %> + +<% if @is_paid_user && @buttondown_status != 'gifted' %> +

Your account is marked as a paid user, but your mailing list status is not synced. Click below to sync your status:

+ <%= button_to "Sync Subscription Status", sync_status_mailing_lists_path, method: :post, class: "button" %> +<% end %> + + +<% end %> + +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/mailing_lists/update.html.erb b/app/views/mailing_lists/update.html.erb new file mode 100644 index 0000000..583f631 --- /dev/null +++ b/app/views/mailing_lists/update.html.erb @@ -0,0 +1,2 @@ +

MailingLists#update

+

Find me in app/views/mailing_lists/update.html.erb

diff --git a/app/views/pubview/index.html.erb b/app/views/pubview/index.html.erb index d2005a2..8758f10 100644 --- a/app/views/pubview/index.html.erb +++ b/app/views/pubview/index.html.erb @@ -6,20 +6,7 @@

Aidan’s anti-capitalist posting and sharing project

-
- <%= link_to "All", root_path(filter: 'all'), class: "button #{@filter == 'all' ? 'active' : ''}" %> - <%= link_to "Dispatches", root_path(filter: 'posts'), class: "button #{@filter == 'posts' ? 'active' : ''}" %> - <%= link_to "Bookmarks", root_path(filter: 'bookmarks'), class: "button #{@filter == 'bookmarks' ? 'active' : ''}" %> - <%= link_to "Join mind reader", join_path, class: "button" %> - <% @pages.each do |pg| %> - <%= link_to "#{pg.title}", public_page_path(pg.slug), class: "button" %> - <% end %> - <% if current_user&.admin? %> - <%= link_to "Manage Posts", posts_path, class: "button" %> - <%= link_to "Manage Pages", pages_path, class: "button" %> - <%= link_to "Manage API Keys", api_keys_path, class: "button" %> - <% end %> -
+<%= render partial: "layouts/navigation_buttons" %>
    @@ -55,8 +42,6 @@
    <%= paginate @items %>
    diff --git a/app/views/pubview/join.html.erb b/app/views/pubview/join.html.erb index 4b9f93e..ddfa5ac 100644 --- a/app/views/pubview/join.html.erb +++ b/app/views/pubview/join.html.erb @@ -10,14 +10,12 @@
    <%= image_tag "growchart.svg", class: "porter" %> -

    Below you can join mind reader and receive new dispatches via email.

    +

    Below you can join mind reader and sign up to receive new dispatches via email.

    Joining by email means you never have to visit this (admittedly beautiful) website ever again. You’ll receive new posts straight in your email inbox. Bookmarks, however, are sent in digest to subscribers only – so if you’d like to see those, come back or keep reading.

    -

    Optionally, once you’ve signed up and confirmed your email address you are able to subscribe to mind reader financially by entering any non $0 AUD amount you wish. You are under no obligation to do this! Paid subscribers receive a digest of bookmarks and a monthly update from me on the state of the world that regular members miss out on.

    -

    If you’re looking to cancel an existing membership or subscription, please go to Buttondown.

    -
    - - - -
    +

    Optionally, once you’ve signed up and confirmed your email address you are able to subscribe to mind reader financially by entering any non $0 AUD amount you wish. You are under no obligation to do this! Paid subscribers may opt to receive a digest of bookmarks and a monthly update from me on the state of the world that regular members miss out on.

    +

    If you’re looking to cancel an existing membership or subscription, <%= link_to "please click here", subscriptions_path %>.

    + <%= image_tag "aidan_arrow.svg", class: "aidans_arrow" %> +

    To get started with mind reader membership, first register for an account on this website. Don’t worry, I’ll guide you through each step of the process! Just click on that button below:

    +

    <%= link_to "Get started, free forever", new_user_registration_path, class: "button" %>

    diff --git a/app/views/pubview/post.html.erb b/app/views/pubview/post.html.erb index 8dc8849..02124d4 100644 --- a/app/views/pubview/post.html.erb +++ b/app/views/pubview/post.html.erb @@ -19,12 +19,5 @@
- <% if !@post.short_dispatch?%> -

Follow via email

-
-

More stuff from Aidan

-

→ Circular economy: if this work has been of interest to you, please consider subsidising my existence, no subscriptions: <%= link_to "click here to donate with PayPal ↗︎".html_safe, "https://paypal.me/aidancornelius/10.00/" %> or <%= link_to "here for more options and information ↙︎".html_safe, "/sponsor/" %>.

-

→ Stay updated: email masochists amongst us may receive my dispatches directly in their inbox with the form below. Alternatively, you are able to subscribe in an RSS reader via the <%= link_to "feed ↙︎".html_safe, "https://mndrdr.org/feed/dispatches/" %> to keep your inbox sanity.

- <% end %> -

<%= link_to "↑ Back to top", "#top" %> or <%= link_to "↼ Back to some other dispatches...", "#{root_path}?filter=posts" %>

+ <%= render partial: "layouts/home_post_links" %>
\ No newline at end of file diff --git a/app/views/pubview/show_public.html.erb b/app/views/pubview/show_public.html.erb index 0e67bd1..a553053 100644 --- a/app/views/pubview/show_public.html.erb +++ b/app/views/pubview/show_public.html.erb @@ -8,13 +8,7 @@
- <%= link_to "Home", root_path(filter: 'all'), class: "button #{@filter == 'all' ? 'active' : ''}" %> - <%= link_to "Dispatches", root_path(filter: 'posts'), class: "button #{@filter == 'posts' ? 'active' : ''}" %> - <%= link_to "Bookmarks", root_path(filter: 'bookmarks'), class: "button #{@filter == 'bookmarks' ? 'active' : ''}" %> - <%= link_to "Join mind reader", join_path, class: "button" %> - <% @pages.each do |pg| %> - <%= link_to "#{pg.title}", public_page_path(pg.slug), class: "button #{params[:slug] == pg.slug ? 'active' : ''}" %> - <% end %> + <%= render partial: "layouts/navigation_buttons" %>
diff --git a/app/views/subscriptions/create.html.erb b/app/views/subscriptions/create.html.erb new file mode 100644 index 0000000..b88739c --- /dev/null +++ b/app/views/subscriptions/create.html.erb @@ -0,0 +1,2 @@ +

Subscriptions#create

+

Find me in app/views/subscriptions/create.html.erb

diff --git a/app/views/subscriptions/index.html.erb b/app/views/subscriptions/index.html.erb new file mode 100644 index 0000000..886e5f2 --- /dev/null +++ b/app/views/subscriptions/index.html.erb @@ -0,0 +1,57 @@ + +<% content_for :title do %>Your memberships and subscription status<% end %> +<% content_for :form_content do %> +<% if !@subscription_status.present? %> +

Hi <%= current_user.first_name if current_user&.first_name.present? %>, thank you for being interested in supporting mind reader! To get started click the big button below.

+<% else %> +
+

Current Status: <%= @subscription_status.titleize if @subscription_status.present? %>

+

Support Type: <%= @support_type.titleize if @support_type.present? %>

+ <% if @last_payment_date %> +

Last Payment Date: <%= @last_payment_date.strftime('%B %d, %Y') %>

+ <% end %> + <% if @last_payment_amount %> +

Last Payment Amount: AU$<%= sprintf('%.2f', @last_payment_amount) %>

+ <% end %> +

If you are a mailing list subscriber, <%= link_to "check that your premium status", mailing_lists_path %> has transferred so that you get bonus mail for premium members. Please be aware that data here are slightly delayed – don’t panic if things are not yet up to date!

+
+ + <% if @portal_session %> +

+ <%= link_to "Manage your subscription", @portal_session.url, class: "button", data: { turbo: false } %> +

+ <% end %> + <% end %> + + <% if @payments.present? %> +

Payment History

+ + + + + + + + + + <% @payments.each do |payment| %> + + + + + + <% end %> + +
DateAmountStatus
<%= Time.at(payment.created).strftime('%B %d, %Y') %>AU$<%= sprintf('%.2f', payment.amount / 100.0) %><%= payment.status.titleize %>
+ <% else %> +

No payment history available.

+ <% end %> + + <% if @subscription_status != 'active' %> +
+ <%= link_to "Subscribe", new_subscription_path, class: "button primary" %> +
+ <% end %> +<% end %> + +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/subscriptions/new.html.erb b/app/views/subscriptions/new.html.erb new file mode 100644 index 0000000..7904959 --- /dev/null +++ b/app/views/subscriptions/new.html.erb @@ -0,0 +1,157 @@ +<% content_for :title do %>Subscribe to mind reader<% end %> + +<% content_for :form_content do %> +

Become a premium member?

+

What’s that? Premium members are those who want more than just the email – you think there’s something to this project, and want to see it thrive! Thanks for even considering it, you legendary person.

+

There are three kinds of membership:

+
    +
  1. Non-financial support, or “mutual aid” – you’re a practicing activist, working hard in communities to create grassroots change, and you’re very welcome to this community. Don’t even think twice about paying – free premium features forever!
  2. +
  3. One-time donation – or, as many times as you like, you like some of the work I’ve done here and want to let me know what I have done matters to you. You have my undying appreciation, and forever access to premium features.
  4. +
  5. Ongoing support – an annual subscription for as much as you can manage, you want me to commit more time to doing this work and are willing to become a patron of my work. You’ll have premium features forever, even if you end your subscription. This takes me one step closer to being able to craft daily change making theory.
  6. +
+ + <% flash.each do |type, message| %> +
+ <%= message %> +
+ <% end %> + + <%= form_tag subscriptions_path, id: 'payment-form' do %> +
+ <%= label_tag :support_type, "Support Type" %> + <%= select_tag :support_type, + options_for_select([ + ['Non-financial support', 'non_financial'], + ['One-time donation', 'one_time'], + ['Ongoing support (annual)', 'ongoing'] + ], 'non_financial'), + class: 'support-type-select' + %> +
+ + + +
+ <%= submit_tag "Subscribe", class: "button primary" %> +
+ <% end %> +<% end %> + +<% content_for :javascript do %> + + +<% end %> + +<%= render template: 'layouts/user_page_template' %> \ No newline at end of file diff --git a/app/views/welcome_mailer/welcome_email.html.erb b/app/views/welcome_mailer/welcome_email.html.erb new file mode 100644 index 0000000..fc3a395 --- /dev/null +++ b/app/views/welcome_mailer/welcome_email.html.erb @@ -0,0 +1,13 @@ +

Welcome to mind reader, <%= @user.first_name %>,

+ +

Your membership here is greatly appreciated.

+ +<% if @paid %> +

I deeply appreciate your financial support! As a <%= @subscription_type %> subscriber, you have access to bookmark digest emails and occasional premium updates from me. They’ll come to you right here – in your inbox – if you said you’d like to receive them.

+<% else %> +

Thank you for joining mind reader as a <%= @subscription_type %> member.

+

Your support of my work is much appreciated, and it’s wonderful you’re now part of the community. You can also upgrade to a paid subscription, one time donation, or just a free lifetime solidarity member (yes, free!) and gain access to premium features, including bookmark digests and occasional special updates by visiting this page.

+<% end %> + +

My thanks again, comrade.
+Aidan.

\ No newline at end of file diff --git a/app/views/welcome_mailer/welcome_email.text.erb b/app/views/welcome_mailer/welcome_email.text.erb new file mode 100644 index 0000000..f7fc4fc --- /dev/null +++ b/app/views/welcome_mailer/welcome_email.text.erb @@ -0,0 +1,12 @@ +Welcome to mind reader, <%= @user.first_name %>, + +Your membership here is greatly appreciated. + +<% if @paid %> +I deeply appreciate your financial support! As a <%= @subscription_type %> subscriber, you have access to bookmark digest emails and occasional premium updates from me. They’ll come to you right here – in your inbox – if you said you’d like to receive them. +<% else %> +Thank you for joining as a <%= @subscription_type %> member. Your support of my work is much appreciated. Note you can also upgrade to a paid subscription or one time donation to access premium features, including bookmark digests and occasional special updates! +<% end %> + +My thanks again, comrade. +Aidan. \ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 3f95c9f..31b16e5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -75,6 +75,9 @@ Rails.application.configure do # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = true + + # Turn of captcha stuff for localhost + config.hcaptcha_enabled = false # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. # config.generators.apply_rubocop_autocorrect_after_generate! diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb new file mode 100644 index 0000000..948b8e8 --- /dev/null +++ b/config/initializers/stripe.rb @@ -0,0 +1,8 @@ + +Rails.configuration.stripe = { + publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'], + secret_key: ENV['STRIPE_SECRET_KEY'], + currency: 'aud' +} + +Stripe.api_key = Rails.configuration.stripe[:secret_key] \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 2715b99..2232850 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,4 @@ Rails.application.routes.draw do - namespace :api do namespace :v1 do match 'api', to: 'api#handle_request', via: [:get, :post] @@ -11,12 +10,20 @@ Rails.application.routes.draw do end end + resources :mailing_lists, only: [:index] do + collection do + post 'subscribe' + delete 'unsubscribe' + post 'sync_status' + end + end + resources :subscriptions, only: [:new, :create, :index] resources :pages get 'importer', to: 'posts#importer' get 'export', to: 'posts#export' post 'import', to: 'posts#import' resources :api_keys - devise_for :users, controllers: { registrations: 'users/registrations' } + devise_for :users, controllers: { registrations: 'users/registrations', confirmations: 'users/confirmations' } resources :posts get '/feed', to: 'pubview#rss', as: 'rss', defaults: { format: 'rss' } get '/feed/dispatches', to: 'pubview#dispatches_rss', as: 'dispatches_rss', defaults: { format: 'rss' } diff --git a/db/migrate/20241008003544_add_subscription_fields_to_users.rb b/db/migrate/20241008003544_add_subscription_fields_to_users.rb new file mode 100644 index 0000000..9fea78d --- /dev/null +++ b/db/migrate/20241008003544_add_subscription_fields_to_users.rb @@ -0,0 +1,10 @@ +class AddSubscriptionFieldsToUsers < ActiveRecord::Migration[7.2] + def change + add_column :users, :subscribe_to_newsletter, :boolean, default: false + add_column :users, :stripe_customer_id, :string + add_column :users, :subscription_status, :string + add_column :users, :last_payment_at, :datetime + add_column :users, :payment_amount, :decimal, precision: 10, scale: 2 + add_column :users, :buttondown_status, :string, default: 'unactivated' + end +end diff --git a/db/migrate/20241008005649_add_subscription_type_to_users.rb b/db/migrate/20241008005649_add_subscription_type_to_users.rb new file mode 100644 index 0000000..866ba3b --- /dev/null +++ b/db/migrate/20241008005649_add_subscription_type_to_users.rb @@ -0,0 +1,5 @@ +class AddSubscriptionTypeToUsers < ActiveRecord::Migration[7.2] + def change + add_column :users, :subscription_type, :string + end +end diff --git a/db/migrate/20241008010447_add_support_type_to_users.rb b/db/migrate/20241008010447_add_support_type_to_users.rb new file mode 100644 index 0000000..cc42ca7 --- /dev/null +++ b/db/migrate/20241008010447_add_support_type_to_users.rb @@ -0,0 +1,5 @@ +class AddSupportTypeToUsers < ActiveRecord::Migration[7.2] + def change + add_column :users, :support_type, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f4a8b33..8275001 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_07_220924) do +ActiveRecord::Schema[7.2].define(version: 2024_10_08_010447) do create_table "api_keys", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "key" t.datetime "created_at", null: false @@ -61,6 +61,14 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_07_220924) do t.integer "failed_attempts", default: 0 t.string "unlock_token" t.datetime "locked_at" + t.boolean "subscribe_to_newsletter", default: false + t.string "stripe_customer_id" + t.string "subscription_status" + t.datetime "last_payment_at" + t.decimal "payment_amount", precision: 10, scale: 2 + t.string "buttondown_status", default: "unactivated" + t.string "subscription_type" + t.string "support_type" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/test/controllers/mailing_lists_controller_test.rb b/test/controllers/mailing_lists_controller_test.rb new file mode 100644 index 0000000..6b69c78 --- /dev/null +++ b/test/controllers/mailing_lists_controller_test.rb @@ -0,0 +1,18 @@ +require "test_helper" + +class MailingListsControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get mailing_lists_index_url + assert_response :success + end + + test "should get edit" do + get mailing_lists_edit_url + assert_response :success + end + + test "should get update" do + get mailing_lists_update_url + assert_response :success + end +end diff --git a/test/controllers/subscriptions_controller_test.rb b/test/controllers/subscriptions_controller_test.rb new file mode 100644 index 0000000..3958a5a --- /dev/null +++ b/test/controllers/subscriptions_controller_test.rb @@ -0,0 +1,18 @@ +require "test_helper" + +class SubscriptionsControllerTest < ActionDispatch::IntegrationTest + test "should get new" do + get subscriptions_new_url + assert_response :success + end + + test "should get create" do + get subscriptions_create_url + assert_response :success + end + + test "should get view" do + get subscriptions_view_url + assert_response :success + end +end diff --git a/test/mailers/admin_mailer_test.rb b/test/mailers/admin_mailer_test.rb new file mode 100644 index 0000000..43f15c3 --- /dev/null +++ b/test/mailers/admin_mailer_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +class AdminMailerTest < ActionMailer::TestCase + test "new_paid_member" do + mail = AdminMailer.new_paid_member + assert_equal "New paid member", mail.subject + assert_equal [ "to@example.org" ], mail.to + assert_equal [ "from@example.com" ], mail.from + assert_match "Hi", mail.body.encoded + end + + test "new_non_financial_member" do + mail = AdminMailer.new_non_financial_member + assert_equal "New non financial member", mail.subject + assert_equal [ "to@example.org" ], mail.to + assert_equal [ "from@example.com" ], mail.from + assert_match "Hi", mail.body.encoded + end +end diff --git a/test/mailers/previews/admin_mailer_preview.rb b/test/mailers/previews/admin_mailer_preview.rb new file mode 100644 index 0000000..a04596f --- /dev/null +++ b/test/mailers/previews/admin_mailer_preview.rb @@ -0,0 +1,12 @@ +# Preview all emails at http://localhost:3000/rails/mailers/admin_mailer +class AdminMailerPreview < ActionMailer::Preview + # Preview this email at http://localhost:3000/rails/mailers/admin_mailer/new_paid_member + def new_paid_member + AdminMailer.new_paid_member + end + + # Preview this email at http://localhost:3000/rails/mailers/admin_mailer/new_non_financial_member + def new_non_financial_member + AdminMailer.new_non_financial_member + end +end diff --git a/test/mailers/previews/welcome_mailer_preview.rb b/test/mailers/previews/welcome_mailer_preview.rb new file mode 100644 index 0000000..1b5a5a6 --- /dev/null +++ b/test/mailers/previews/welcome_mailer_preview.rb @@ -0,0 +1,7 @@ +# Preview all emails at http://localhost:3000/rails/mailers/welcome_mailer +class WelcomeMailerPreview < ActionMailer::Preview + # Preview this email at http://localhost:3000/rails/mailers/welcome_mailer/welcome_email + def welcome_email + WelcomeMailer.welcome_email + end +end diff --git a/test/mailers/welcome_mailer_test.rb b/test/mailers/welcome_mailer_test.rb new file mode 100644 index 0000000..0c5ce68 --- /dev/null +++ b/test/mailers/welcome_mailer_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class WelcomeMailerTest < ActionMailer::TestCase + test "welcome_email" do + mail = WelcomeMailer.welcome_email + assert_equal "Welcome email", mail.subject + assert_equal [ "to@example.org" ], mail.to + assert_equal [ "from@example.com" ], mail.from + assert_match "Hi", mail.body.encoded + end +end