From 98496698cbf7d009bdfe6e18d3484096de24cb73 Mon Sep 17 00:00:00 2001 From: Kyle Drake Date: Sat, 19 Apr 2014 14:02:19 -0700 Subject: [PATCH] This completes the stripe integration for existing sites --- app.rb | 81 +++++++++++++++-- migrations/020_add_plan_ended.rb | 9 ++ models/site.rb | 52 +++++++++-- views/_header.erb | 3 + views/dashboard.erb | 4 +- views/index.erb | 3 + views/layout.erb | 2 +- views/new.erb | 2 +- views/plan/end.erb | 34 ++++++++ views/plan/index.erb | 145 +++++++++++++++++++++++++++++++ views/plan/manage.erb | 19 ++++ views/settings.slim | 11 +++ views/signin.slim | 28 +++--- views/site_files/new.slim | 2 +- views/site_files/upload.slim | 2 +- 15 files changed, 364 insertions(+), 33 deletions(-) create mode 100644 migrations/020_add_plan_ended.rb create mode 100644 views/plan/end.erb create mode 100644 views/plan/index.erb create mode 100644 views/plan/manage.erb diff --git a/app.rb b/app.rb index 3fc9bb64..ce118fbf 100644 --- a/app.rb +++ b/app.rb @@ -74,6 +74,75 @@ get '/?' do erb :index, layout: false end +get '/plan/?' do + erb :'plan/index' +end + +post '/plan/create' do + require_login + + DB.transaction do + customer = Stripe::Customer.create( + card: params[:stripe_token], + description: current_site.username, + email: current_site.email, + plan: params[:selected_plan] + ) + current_site.stripe_customer_id = customer.id + current_site.plan_ended = false + current_site.save + end + + redirect '/plan' +end + +def get_plan_name(customer_id) + subscriptions = Stripe::Customer.retrieve(current_site.stripe_customer_id).subscriptions.all + @plan_name = subscriptions.first.plan.name +end + +get '/plan/manage' do + require_login + redirect '/plan' unless current_site.supporter? && !current_site.plan_ended + @title = 'Manage Plan' + @plan_name = get_plan_name current_site.stripe_customer_id + erb :'plan/manage' +end + +get '/plan/end' do + require_login + redirect '/plan' unless current_site.supporter? && !current_site.plan_ended + @title = 'End Plan' + @plan_name = get_plan_name current_site.stripe_customer_id + erb :'plan/end' +end + +post '/plan/end' do + require_login + redirect '/plan' unless current_site.supporter? && !current_site.plan_ended + + recaptcha_is_valid = ENV['RACK_ENV'] == 'test' || recaptcha_valid? + + if !recaptcha_is_valid + @error = 'Recaptcha was filled out incorrectly, please try re-entering.' + @plan_name = get_plan_name current_site.stripe_customer_id + halt erb :'plan/end' + end + + customer = Stripe::Customer.retrieve current_site.stripe_customer_id + subscriptions = customer.subscriptions.all + + DB.transaction do + subscriptions.each do |subscription| + customer.subscriptions.retrieve(subscription.id).delete + end + current_site.plan_ended = true + current_site.save + end + + redirect '/plan' +end + get '/site/:username/tip' do |username| @site = Site[username: username] @title = "Tip #{@site.title}" @@ -330,7 +399,7 @@ post '/site_files/upload' do halt http_error_code, 'Did not receive file upload.' end - if params[:newfile][:tempfile].size > Site::MAX_SPACE || (params[:newfile][:tempfile].size + current_site.total_space) > Site::MAX_SPACE + if current_site.file_size_too_large? params[:newfile][:tempfile].size @errors << 'File size must be smaller than available space.' halt http_error_code, 'File size must be smaller than available space.' end @@ -390,15 +459,15 @@ post '/site_files/save/:filename' do |filename| tempfile = Tempfile.new 'neocities_saving_file' - if (tempfile.size + current_site.total_space) > Site::MAX_SPACE - halt 'File is too large to fit in your space, it has NOT been saved. Please make a local copy and then try to reduce the size.' - end - input = request.body.read tempfile.set_encoding input.encoding tempfile.write input tempfile.close + if current_site.file_site_too_large? tempfile.size + halt 'File is too large to fit in your space, it has NOT been saved. Please make a local copy and then try to reduce the size.' + end + sanitized_filename = filename.gsub(/[^a-zA-Z0-9_\-.]/, '') current_site.store_file sanitized_filename, tempfile @@ -622,7 +691,7 @@ post '/api/upload' do uploaded_size = files.collect {|f| f[:tempfile].size}.inject{|sum,x| sum + x } - if (uploaded_size + current_site.total_space) > Site::MAX_SPACE + if current_site.file_size_too_large? uploaded_size api_error 400, 'too_large', 'files are too large to fit in your space, try uploading smaller (or less) files' end diff --git a/migrations/020_add_plan_ended.rb b/migrations/020_add_plan_ended.rb new file mode 100644 index 00000000..538071b2 --- /dev/null +++ b/migrations/020_add_plan_ended.rb @@ -0,0 +1,9 @@ +Sequel.migration do + up { + DB.add_column :sites, :plan_ended, :boolean, default: false + } + + down { + DB.drop_column :sites, :plan_ended + } +end \ No newline at end of file diff --git a/models/site.rb b/models/site.rb index 0937079f..cba4a26f 100644 --- a/models/site.rb +++ b/models/site.rb @@ -28,7 +28,13 @@ class Site < Sequel::Model html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff json geojson csv tsv mf ico pdf asc key pgp xml mid midi } - MAX_SPACE = (5242880*2) # 10MB + + ONE_MEGABYTE_IN_BYTES = 1048576 + FREE_MAXIMUM_IN_MEGABYTES = 10 + SUPPORTER_MAXIMUM_IN_MEGABYTES = 200 + FREE_MAXIMUM_IN_BYTES = FREE_MAXIMUM_IN_MEGABYTES * ONE_MEGABYTE_IN_BYTES + SUPPORTER_MAXIMUM_IN_BYTES = SUPPORTER_MAXIMUM_IN_MEGABYTES * ONE_MEGABYTE_IN_BYTES + MINIMUM_PASSWORD_LENGTH = 5 BAD_USERNAME_REGEX = /[^\w-]/i VALID_HOSTNAME = /^[a-z0-9][a-z0-9-]+?[a-z0-9]$/i # http://tools.ietf.org/html/rfc1123 @@ -294,22 +300,54 @@ class Site < Sequel::Model Dir.glob(File.join(files_path, '*')).collect {|p| File.basename(p)}.sort.collect {|sitename| SiteFile.new sitename} end - def total_space + def file_size_too_large?(size_in_bytes) + return true if size_in_bytes + used_space_in_bytes > maximum_space_in_bytes + false + end + + def used_space_in_bytes space = Dir.glob(File.join(files_path, '*')).collect {|p| File.size(p)}.inject {|sum,x| sum += x} space.nil? ? 0 : space end - def total_space_in_megabytes - (total_space.to_f / 2**20).round(2) + def used_space_in_megabytes + (used_space_in_bytes.to_f / self.class::ONE_MEGABYTE_IN_BYTES).round(2) end - def available_space - remaining = MAX_SPACE - total_space + def available_space_in_bytes + remaining = maximum_space_in_bytes - used_space_in_bytes remaining < 0 ? 0 : remaining end def available_space_in_megabytes - (available_space.to_f / 2**20).round(2) + (available_space_in_bytes.to_f / self.class::ONE_MEGABYTE_IN_BYTES).round(2) + end + + def maximum_space_in_bytes + supporter? ? self.class::SUPPORTER_MAXIMUM_IN_BYTES : self.class::FREE_MAXIMUM_IN_BYTES + end + + def maximum_space_in_megabytes + supporter? ? self.class::SUPPORTER_MAXIMUM_IN_MEGABYTES : self.class::FREE_MAXIMUM_IN_MEGABYTES + end + + def space_percentage_used + ((used_space_in_bytes.to_f / maximum_space_in_bytes) * 100).round(1) + end + + # This returns true even if they end their support plan. + def supporter? + !values[:stripe_customer_id].nil? + end + + # This will return false if they have ended their support plan. + def ended_supporter? + values[:ended_plan] + end + + def plan_name + return 'Free Plan' if !supporter? || (supporter? && ended_supporter?) + 'Supporter Plan' end def title diff --git a/views/_header.erb b/views/_header.erb index 7ab50b73..68487016 100644 --- a/views/_header.erb +++ b/views/_header.erb @@ -22,6 +22,9 @@
  • About
  • +
  • + Supporters +