implement plan code

This commit is contained in:
Kyle Drake 2014-04-18 15:40:08 -07:00
parent 138725d00b
commit 1031324920
No known key found for this signature in database
GPG key ID: 8BE721072E1864BE
17 changed files with 266 additions and 114 deletions

View file

@ -18,6 +18,7 @@ gem 'mail'
gem 'google-api-client', require: 'google/api_client' gem 'google-api-client', require: 'google/api_client'
gem 'tilt' gem 'tilt'
gem 'erubis' gem 'erubis'
gem 'stripe', :git => 'https://github.com/stripe/stripe-ruby'
platform :mri do platform :mri do
gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic

View file

@ -1,3 +1,12 @@
GIT
remote: https://github.com/stripe/stripe-ruby
revision: 48f76057f425ab5c3bb147f3d71c3d36d951159f
specs:
stripe (1.11.0)
json (~> 1.8.1)
mime-types (~> 1.25)
rest-client (~> 1.4)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
@ -121,11 +130,12 @@ GEM
redis (3.0.7) redis (3.0.7)
redis-namespace (1.4.1) redis-namespace (1.4.1)
redis (~> 3.0.4) redis (~> 3.0.4)
rest-client (1.6.7)
mime-types (>= 1.16)
retriable (1.4.1) retriable (1.4.1)
rmagick (2.13.2) rmagick (2.13.2)
rubyzip (1.1.2) rubyzip (1.1.2)
safe_yaml (1.0.1) safe_yaml (1.0.1)
sass (3.3.5)
selenium-webdriver (2.40.0) selenium-webdriver (2.40.0)
childprocess (>= 0.5.0) childprocess (>= 0.5.0)
multi_json (~> 1.0) multi_json (~> 1.0)
@ -230,5 +240,6 @@ DEPENDENCIES
sinatra-flash sinatra-flash
sinatra-xsendfile sinatra-xsendfile
slim slim
stripe!
tilt tilt
webmock webmock

54
app.rb
View file

@ -74,6 +74,12 @@ get '/?' do
erb :index, layout: false erb :index, layout: false
end end
get '/site/:username/tip' do |username|
@site = Site[username: username]
@title = "Tip #{@site.title}"
erb :'tip'
end
get '/browse' do get '/browse' do
@current_page = params[:current_page] @current_page = params[:current_page]
@current_page = @current_page.to_i @current_page = @current_page.to_i
@ -128,22 +134,7 @@ get '/new' do
dashboard_if_signed_in dashboard_if_signed_in
@site = Site.new @site = Site.new
@site.username = params[:username] unless params[:username].nil? @site.username = params[:username] unless params[:username].nil?
slim :'new' erb :'new'
end
get '/dashboard' do
require_login
erb :'dashboard'
end
get '/signin' do
dashboard_if_signed_in
slim :'signin'
end
get '/settings' do
require_login
slim :'settings'
end end
post '/create' do post '/create' do
@ -160,17 +151,44 @@ post '/create' do
recaptcha_is_valid = ENV['RACK_ENV'] == 'test' || recaptcha_valid? recaptcha_is_valid = ENV['RACK_ENV'] == 'test' || recaptcha_valid?
if @site.valid? && recaptcha_is_valid if @site.valid? && recaptcha_is_valid
@site.save DB.transaction do
if !params[:stripe_token].nil? && params[:stripe_token] != ''
customer = Stripe::Customer.create(
card: params[:stripe_token],
description: @site.username,
email: @site.email,
plan: params[:selected_plan]
)
@site.stripe_customer_id = customer.id
end
@site.save
end
session[:id] = @site.id session[:id] = @site.id
redirect '/dashboard' redirect '/dashboard'
else else
@site.errors.add :captcha, 'You must type in the two words correctly! Try again.' if !recaptcha_is_valid @site.errors.add :captcha, 'You must type in the two words correctly! Try again.' if !recaptcha_is_valid
slim :'/new' erb :'/new'
end end
end end
get '/dashboard' do
require_login
erb :'dashboard'
end
get '/signin' do
dashboard_if_signed_in
slim :'signin'
end
get '/settings' do
require_login
slim :'settings'
end
post '/signin' do post '/signin' do
dashboard_if_signed_in dashboard_if_signed_in

View file

@ -8,3 +8,17 @@ development:
sidekiq_pass: ENTER PASS HERE sidekiq_pass: ENTER PASS HERE
phantomjs_url: phantomjs_url:
- http://localhost:8910 - http://localhost:8910
stripe_publishable_key: fillout
stripe_api_key: fillout
test:
database: 'postgres://neocities@127.0.0.1/neocities_test'
database_pool: 1
session_secret: SECRET GOES HERE
recaptcha_public_key: ENTER PUBLIC KEY HERE
recaptcha_private_key: ENTER PRIVATE KEY HERE
sidekiq_user: ENTER USER HERE
sidekiq_pass: ENTER PASS HERE
phantomjs_url:
- http://localhost:8910
stripe_publishable_key: fillout
stripe_api_key: fillout

View file

@ -58,6 +58,8 @@ Sequel::Model.plugin :defaults_setter
Sequel.default_timezone = 'UTC' Sequel.default_timezone = 'UTC'
Sequel::Migrator.apply DB, './migrations' Sequel::Migrator.apply DB, './migrations'
Stripe.api_key = $config['stripe_api_key']
Dir.glob('models/*.rb').each {|m| require File.join(DIR_ROOT, "#{m}") } Dir.glob('models/*.rb').each {|m| require File.join(DIR_ROOT, "#{m}") }
DB.loggers << Logger.new(STDOUT) if ENV['RACK_ENV'] == 'development' DB.loggers << Logger.new(STDOUT) if ENV['RACK_ENV'] == 'development'

View file

@ -0,0 +1,11 @@
Sequel.migration do
up {
DB.drop_column :sites, :stripe_token
DB.add_column :sites, :stripe_customer_id, :text, default: nil
}
down {
DB.drop_column :sites, :stripe_customer_id
DB.add_column :sites, :stripe_token, :text, default: nil
}
end

View file

@ -311,4 +311,8 @@ class Site < Sequel::Model
def available_space_in_megabytes def available_space_in_megabytes
(available_space.to_f / 2**20).round(2) (available_space.to_f / 2**20).round(2)
end end
def title
values[:title] || values[:username]
end
end end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

File diff suppressed because one or more lines are too long

View file

@ -20,7 +20,6 @@
</div> </div>
<% end %> <% end %>
<h2>Contact Us</h2> <h2>Contact Us</h2>
<h6>Please Note Before Contacting:</h6> <h6>Please Note Before Contacting:</h6>

View file

@ -322,21 +322,8 @@
<%== erb :'_footer', layout: false%> <%== erb :'_footer', layout: false%>
</footer> </footer>
</div> <!-- end .page --> </div>
<script src="/assets/scripts/jquery-1.11.0.min.js"></script>
<!-- scripts --> <script src="/assets/scripts/app.min.js"></script>
<script src="assets/scripts/jquery-1.10.1.min.js"></script>
<script src="assets/scripts/app.min.js"></script> <!-- Script block allowing child pages to inject their own scripts -->
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID.
<script type="text/javascript>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src='//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
-->
</body> </body>
</html> </html>

View file

@ -20,7 +20,7 @@
<link href="/css/bootstrap.min.css" rel="stylesheet"> <link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/bootstrap-responsive.min.css" rel="stylesheet"> <link href="/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="assets/css/neo.min.css" rel="stylesheet" type="text/css" media="all"/> <link href="/assets/css/neo.min.css" rel="stylesheet" type="text/css" media="all"/>
<link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css" media="all"/> <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css" media="all"/>
<link href="/css/styles.css" rel="stylesheet" type="text/css" media="all"> <link href="/css/styles.css" rel="stylesheet" type="text/css" media="all">
@ -35,6 +35,10 @@
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]--> <![endif]-->
<script>
var RecaptchaOptions = {theme: 'clean'}
</script>
</head> </head>
<body class="interior"> <body class="interior">
@ -46,8 +50,8 @@
<%== erb :'_footer', layout: false %> <%== erb :'_footer', layout: false %>
</footer> </footer>
<script src="assets/scripts/jquery-1.10.1.min.js"></script> <script src="/assets/scripts/jquery-1.11.0.min.js"></script>
<script src="assets/scripts/nav.min.js"></script> <script src="/assets/scripts/nav.min.js"></script>
<script src="/js/bootstrap.min.js"></script> <script src="/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>

View file

@ -12,7 +12,7 @@ html
meta property="og:title" content="NeoCities" meta property="og:title" content="NeoCities"
meta property="og:description" content="NeoCities is the new Geocities. Create your own free home page, and do whatever you want with it." meta property="og:description" content="NeoCities is the new Geocities. Create your own free home page, and do whatever you want with it."
meta name="csrf-token" content="#{csrf_token}" meta name="csrf-token" content="#{csrf_token}"
script src="/js/jquery.min.js" script src="/assets/scripts/jquery-1.11.0.min.js"
link href="/assets/css/neo.min.css" rel="stylesheet" type="text/css" media="all" link href="/assets/css/neo.min.css" rel="stylesheet" type="text/css" media="all"
script src="/assets/scripts/nav.min.js" script src="/assets/scripts/nav.min.js"

170
views/new.erb Normal file
View file

@ -0,0 +1,170 @@
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('<%= $config['stripe_publishable_key'] %>');
</script>
<main class="content-Base">
<div class="row content">
<div class="col col-100">
<form method="POST" action="/create" id="signupform">
<input name="csrf_token" type="hidden" value="<%= csrf_token %>">
<h2 class="txt-Center">Create a New Home Page</h2>
<div class="col col-50" style="margin:0 auto; float:none">
<% if !@site.errors.empty? %>
<div class="row content">
<div class="col col-100 txt-Center">
<div class="alert alert-block alert-error">
<p>There were errors creating your home page:</p>
<% @site.errors.each do |error| %>
<p class="tiny"><%= error.last.first %></p>
<% end %>
</div>
</div>
</div>
<% end %>
<hr>
<p class="tiny">
First, enter a username. This will also be used as your site name.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It can only contain letters, numbers, underscores and hyphens, and can only be 32 characters long.
</p>
<h5>Username</h5>
<p class="tiny">
<input class="input-Area" name="username" type="text" placeholder="yourusername" value="<%= @site.username %>" autocapitalize="off" autocorrect="off">.neocities.org
</p>
<hr>
<p class="tiny">
Next, enter a password. This will be used to allow you to login. Minimum 5 characters. If you don't make it a good password, Dade Murphy from the movie Hackers will come in and steal your "garbage files".
</p>
<h5>Password</h5>
<input class="input-Area" name="password" type="password">
<hr>
<p class="tiny">
Now you can enter an e-mail address. Your e-mail address is private and we will not show it to anyone for any reason. You don't have to provide one, but <b>we will not be able to reset your password without it, so don't lose your username and password if you leave this blank!</b>
</p>
<h5>Email</h5>
<input class="input-Area" name="email" type="email" placeholder="youremail@example.com" value="<%= @site.email %>">
<hr>
<p class="tiny">You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of ten tags, and there is a two word per tag maximum (extra words in a tag will be removed).</p>
<h5>Tags</h5>
<input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="<%= params[:tags] %>" autocapitalize="off" autocorrect="off">
<hr>
<p class="tiny"><strong>The site you are creating will be free, forever.</strong> We will never charge you for your free web site.</p>
<p class="tiny"><a href="/donate" target="_blank">Neocities has to pay the bills though</a>, and we like the idea of being able to work on the site full-time someday. So if you would like to help us reach this goal, we have created the <strong>Supporter Plan</strong>!
<p class="tiny">Right now, the <strong>Supporter Plan</strong> is the same as the free plan, except that <strong>Supporter Plan members get 200MB</strong> of web space. You will also be listed as a supporter on our contributors page, and on your site profile page.</p>
<p class="tiny">The base plan is $12 per year ($1/mo) paid annually, which is the cost of <a href="/img/yafagrillmenu.jpg" target="_blank">a delicious Yafa Combo with a lousy tip</a>. If you ever decide to cancel, you get to keep the extra space.</p>
<div>
<input type="radio" name="plan" value="free" <%= params[:plan].nil? || params[:plan] == 'free' ? 'checked' : '' %>>
<span><strong>Free Plan (10MB)</strong></span>
</div>
<a name="plan_error_link"></a>
<div>
<input id="supporter" type="radio" name="plan" value="supporter" <%= params[:plan] == 'supporter' ? 'checked' : '' %>>
<span><strong>Supporter Plan (200MB)</strong></span>
</div>
<div id="plan_container" style="margin-top:20px; display: none">
<input id="stripe_token" name="stripe_token" type="hidden" value="<%= params[:stripe_token] %>">
<div id="plan_error" class="alert alert-block alert-error" style="display:none"></div>
<p class="tiny">
Plan type:
<select name="selected_plan" style="width: 200px">
<option value="plan_one">$12/year ($1/month)</option>
<option value="plan_two" <%= params[:selected_plan].nil? ? 'selected' : '' %>>$24/year ($2/month)</option>
<option value="plan_three">$36/year ($3/month)</option>
<option value="plan_four">$48/year ($4/month)</option>
<option value="plan_five">$60/year ($5/month)</option>
</select>
</p>
<% if params[:stripe_token] %>
<p class="tiny">Billing information has been saved, thank you!</p>
<% else %>
<p class="tiny">
Card Number: <input type="text" size="20" data-stripe="number">
CVC: <input type="text" size="4" maxlength="4" data-stripe="cvc" style="width: 60px">
</p>
<p class="tiny">
Expiration:
<input type="text" size="2" data-stripe="exp-month" placeholder="MM" maxlength="2" style="width: 50px">
<input type="text" size="4" data-stripe="exp-year" placeholder="YYYY" maxlength="4" style="width: 60px">
</p>
<% end %>
</div>
<hr>
<p class="tiny"><b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).</p>
<div class="recaptcha">
<%== recaptcha_tag :challenge, ssl: true %>
</div>
<hr>
<h3>You're done. Just click the button below!</h3>
<input class="btn-Action" type="submit" value="Create Home Page">
</form>
</div>
</div>
</main>
<script>
window.onload = function() {
$('#signupform').find(':submit').prop('disabled', false)
$('#signupform').submit(function(event) {
if($('#signupform input:radio[name="plan"]:checked').val() == 'free') {
return true
}
if($('#stripe_token').val() != '')
return true
var planError = $('#plan_error')
planError.css('display', 'none')
var signupform = $(this)
signupform.find(':submit').prop('disabled', true)
Stripe.card.createToken(signupform, function(status, response) {
console.log(response)
if(response.error) {
planError.text(response.error.message)
planError.css('display', 'block')
window.location = '#plan_error_link'
signupform.find(':submit').prop('disabled', false)
return false
} else {
$('#stripe_token').val(response.id)
signupform.submit()
}
})
return false
})
$('#signupform input:radio[name="plan"]').change(function(){
showPlanIfSelected()
})
function showPlanIfSelected() {
var planContainer = $('#plan_container')
if($('#signupform input:radio[name="plan"]:checked').val() == 'supporter')
return planContainer.css('display', 'block')
planContainer.css('display', 'none')
}
showPlanIfSelected()
}
</script>

View file

@ -1,62 +0,0 @@
javascript:
var RecaptchaOptions = {
theme : 'clean'
};
- if !@site.errors.empty?
.row
.span8.offset2
.alert.alert-block.alert-error
p There were errors creating your home page:
- @site.errors.each do |error|
p = error.last.first
.page
.content-Base
.row.content style="padding-top:0"
form method="POST" action="/create"
input name="csrf_token" type="hidden" value="#{csrf_token}"
h2.txt-Center Create a New Home Page
.col.col-50 style="margin:0 auto; float:none"
hr
p.tiny First, enter a username. This will also be used as your site name.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It can only contain letters, numbers, underscores and hyphens, and can only be 32 characters long.
br
h5 Username
p.tiny <input class="input-Area" name="username" type="text" placeholder="yourusername" value="#{@site.username}" autocapitalize="off" autocorrect="off">.neocities.org
hr
p.tiny Next, enter a password. This will be used to allow you to login. Minimum 5 characters. If you don't make it a good password, Dade Murphy from the movie Hackers will come in and steal your "garbage files".
h5 Password
input class="input-Area" name="password" type="password"
br
hr
p.tiny Now you can enter an e-mail address. Your e-mail address is private and we will not show it to anyone for any reason. You don't have to provide one, but <b>we will not be able to reset your password without it, so don't lose your username and password if you leave this blank!</b>
h5 Email
input class="input-Area" name="email" type="email" placeholder="youremail@example.com" value="#{@site.email}"
br
hr
p.tiny You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of ten tags, and there is a two word per tag maximum (extra words in a tag will be removed).
h5 Tags
p: input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="#{params[:tags]}" autocapitalize="off" autocorrect="off"
hr
input name="is_nsfw" type="hidden" value="false"
p If your page will contain objectionable (adult) content, check this box:&nbsp;&nbsp;&nbsp;<input name="is_nsfw" type="checkbox" value="true" style="margin-top:0">
hr
p.tiny <b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).
div style="background:#fff; width:100%; overflow:auto"
== recaptcha_tag :challenge, ssl: true
br
h3 You're done. Just click the button below!
.txt-Center
input.btn-Action type="submit" value="Create Home Page"