private
def sign_up_params
- params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :subscribe_to_newsletter, :payment_amount, :support_type)
+ params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :subscribe_to_newsletter, :payment_amount, :support_type, :hide_ai_summaries)
+ end
+
+ def account_update_params
+ params.require(:user).permit(
+ :first_name,
+ :last_name,
+ :email,
+ :password,
+ :password_confirmation,
+ :current_password,
+ :hide_ai_summaries
+ )
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,
subscription = Stripe::Subscription.create({
customer: customer.id,
items: [{
- price_data: {
+ price_data: {
unit_amount: amount,
currency: 'usd',
recurring: { interval: 'year' },
respond_with_navigational(resource) { render :new }
end
end
-end
\ No newline at end of file
+end
:recoverable, :rememberable, :validatable,
:confirmable, :lockable, :two_factor_authenticatable, :two_factor_backupable,
otp_secret_encryption_key: Rails.application.credentials.active_record_encryption[:primary_key]
-
+
encrypts :otp_secret
attr_accessor :otp_plain_secret
-
+
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 :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
-
+
def admin?
admin
end
-
+
+ def show_ai_summaries?
+ !hide_ai_summaries
+ 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
-
+
def generate_two_factor_secret_if_missing!
return unless otp_secret.nil?
update!(otp_secret: User.generate_otp_secret)
end
-
+
def enable_two_factor!
update!(otp_required_for_login: true)
end
-
+
def disable_two_factor!
update!(
otp_required_for_login: false,
otp_backup_codes: nil
)
end
-
+
def two_factor_qr_code_uri
issuer = 'Your App Name'
label = "#{issuer}:#{email}"
otp_provisioning_uri(label, issuer: issuer)
end
-
+
def generate_otp_backup_codes!
codes = []
10.times do
end
update!(otp_backup_codes: codes)
end
-
+
# Getter and setter for otp_backup_codes
def otp_backup_codes
return [] if super.nil?
JSON.parse(super)
end
-
+
def otp_backup_codes=(codes)
super(codes.to_json)
end
-
+
private
def sync_with_buttondown
ButtondownService.new.subscribe(self)
end
-
+
def send_welcome_email
WelcomeMailer.welcome_email(self).deliver_later
end
</div>
</div>
+ <hr>
+
+ <div class="field">
+ <%= f.label :hide_ai_summaries do %>
+ <%= f.check_box :hide_ai_summaries %>
+ Hide AI-generated summaries
+ <% end %>
+ <p class="help-text">When enabled, AI-generated summaries will not be displayed on posts.</p>
+ </div>
+
+ <hr>
+
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i>
<%= f.password_field :current_password, autocomplete: "current-password" %>
<span class="post-link">
<%= link_to item.title, item.url, target: "_blank" %>
<abbr title="external link">↗︎</abbr> <br><span class="comment-separator">↳</span> <span class="bookmark-comment"><%= item.content %></span>
- <% if item.summary? %>
+ <% if item.summary? && (!current_user&.hide_ai_summaries?) %>
<blockquote class="excerpt">
<span class="ai-summary">AI Summary</span><span class="ai-summary-block"><%= item.summary %>
</blockquote>
</ul>
</div>
<% end %>
-
+
<div>
<%= form.label :email %>
<%= form.email_field :email %>
</div>
-
+
<div>
<%= form.label :first_name %>
<%= form.text_field :first_name %>
</div>
-
+
<div>
<%= form.label :last_name %>
<%= form.text_field :last_name %>
</div>
-
+
<div>
<%= form.label :admin %>
<%= form.check_box :admin %>
</div>
-
+
<div>
<%= form.label :subscription_status %>
<%= form.select :subscription_status, ['active', 'inactive', 'one_time'], include_blank: true %>
</div>
-
+
<div>
<%= form.label :buttondown_status %>
<%= form.select :buttondown_status, ['unactivated', 'regular', 'premium', 'gifted', 'trialed'], include_blank: true %>
</div>
-
+
<div>
<%= form.label :support_type %>
<%= form.select :support_type, ['one_time', 'ongoing', 'non_financial'], include_blank: true %>
</div>
-
+
<div>
<%= form.submit 'Update User' %>
</div>
<% end %>
-
+
<%= link_to 'Show User', user_manager_path(@user) %> |
<%= link_to 'Back to Users', user_manager_path %>
</div>
-</div>
\ No newline at end of file
+</div>
--- /dev/null
+class AddAiPreferencesToUsers < ActiveRecord::Migration[7.2]
+ def change
+ add_column :users, :hide_ai_summaries, :boolean, default: false
+ end
+end
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.2].define(version: 2024_12_08_070031) do
+ActiveRecord::Schema[7.2].define(version: 2024_12_09_215122) 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
t.text "otp_secret"
t.boolean "otp_required_for_login"
t.text "otp_backup_codes"
+ t.boolean "hide_ai_summaries", default: false
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