Permalink
Browse files

Merge branch 'master' of github.com:echen1031/fakerio

  • Loading branch information...
2 parents 906ee47 + 4f8646b commit 6d7a6df3c892d2ec300c67464fa4ae909da1e2c2 Elad Meidar committed Jun 24, 2014
View
@@ -14,3 +14,5 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
+/.config/application.yml
+/.env
View
@@ -44,4 +44,7 @@ gem 'faker'
gem 'bootstrap-sass', '~> 3.1.1'
gem 'simple_form'
gem 'stripe'
+gem 'haml'
+gem 'haml-rails'
+gem 'redis'
View
@@ -65,6 +65,13 @@ GEM
railties (>= 3.0.0)
faker (1.3.0)
i18n (~> 0.5)
+ haml (4.0.5)
+ tilt
+ haml-rails (0.5.3)
+ actionpack (>= 4.0.1)
+ activesupport (>= 4.0.1)
+ haml (>= 3.1, < 5.0)
+ railties (>= 4.0.1)
hike (1.2.3)
httparty (0.12.0)
json (~> 1.8)
@@ -123,6 +130,7 @@ GEM
rake (10.3.2)
rdoc (4.1.1)
json (~> 1.4)
+ redis (3.1.0)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec-core (2.14.8)
@@ -205,6 +213,8 @@ DEPENDENCIES
devise
factory_girl_rails (~> 4.0)
faker
+ haml
+ haml-rails
httparty
jbuilder (~> 2.0)
jquery-rails
@@ -213,6 +223,7 @@ DEPENDENCIES
pry
rails (= 4.1.0)
rails_12factor
+ redis
rspec-rails
sass-rails (~> 4.0.3)
sdoc (~> 0.4.0)
View
Binary file not shown.
@@ -5,6 +5,19 @@ class Api::V1::BaseController < ApplicationController
before_filter :authenticate_user_from_token!
before_filter :authenticate_user!
+ around_filter :protect_api_methods
+
+ def protect_api_methods
+ if current_user.credits <= 0
+ respond_with({error: "You are out of credits, please purchase more."}, status: :payment_required)
+ else
+ yield
+ current_user.credits_in_cents -= 1
+ current_user.save
+ response.headers["X-FAKER-IO-CREDITS-REMAINING"] = current_user.credits_in_cents.to_s
+ end
+ end
+
private
def authenticate_user_from_token!
@@ -1,4 +1,4 @@
-class Api::V1::CompanyController < Api::V1::BaseController
+class Api::V1::CompaniesController < Api::V1::BaseController
def index
count = (params[:count] || 1).to_i
has_product = params[:with_product].present?
@@ -1,4 +1,4 @@
-class Api::V1::PetController < Api::V1::BaseController
+class Api::V1::PetsController < Api::V1::BaseController
def index
count = (params[:count] || 1).to_i
pet = []
@@ -1,4 +1,4 @@
-class Api::V1::ProductController < Api::V1::BaseController
+class Api::V1::ProductsController < Api::V1::BaseController
def index
count = (params[:count] || 1).to_i
products = []
@@ -1,5 +1,30 @@
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
+
protect_from_forgery with: :exception
+ #before_filter :throttle
+
+ def throttle
+ client_ip = request.env["REMOTE_ADDR"]
+ key = "count:#{client_ip}"
+ count = REDIS.get(key)
+
+ unless count
+ REDIS.set(key, 0)
+ REDIS.expire(key, THROTTLE_TIME_WINDOW)
+ return true
+ end
+
+ if count.to_i >= THROTTLE_MAX_REQUESTS
+ render :status => 429, :json => {:message => "You have fired too many requests. Please wait for some time."}
+ return
+ end
+ REDIS.incr(key)
+ true
+ end
+
+ def after_sign_in_path_for(resource)
+ dashboards_path
+ end
end
@@ -0,0 +1,9 @@
+class DashboardsController < ApplicationController
+
+ before_filter :authenticate_user!
+
+ def index
+
+ end
+end
+
@@ -0,0 +1,5 @@
+class FooController < ApplicationController
+ def index
+ render json: {foo: :bar}
+ end
+end
@@ -0,0 +1,52 @@
+class PurchasesController < ApplicationController
+ before_filter :authenticate_user!
+
+ def create
+ @amount = params[:amount].to_i * 100
+
+ #Creates a Stripe Customer object, for associating with the purchase
+ customer = Stripe::Customer.create(
+ email: current_user.email,
+ card: params[:stripeToken]
+ )
+
+ #Where the real magic happens
+ purchase = Stripe::Charge.create(
+ customer: customer.id, #Note -- this is NOT the user_id in your app
+ amount: @amount,
+ description: "Faker.io Credits - #{current_user.email}",
+ currency: 'usd'
+ )
+
+ flash[:notice] = "Thanks for your payment, #{current_user.email}!"
+
+
+ current_user.credits_in_cents = current_user.credits_in_cents + @amount
+ current_user.save
+
+ redirect_to dashboards_index_path
+
+ #Stripe will send back CardErrors, with friendly messages
+ #when somethin goes wrong.
+ #This 'rescue block' catches and displays those errors.
+ rescue Stripe::CardError => e
+ flash[:error] = e.message
+ redirect_to new_purchase_path
+ end
+
+ def new
+ #Because large hashes in haml are no fun
+
+ @stripe_btn_hash = {
+ src: "https://checkout.stripe.com/checkout.js",
+ class: 'stripe-button',
+ data: {
+ key: "#{ Rails.configuration.stripe[:publishable_key] }",
+ description: "Faker.io Credits - #{current_user.email}"#,
+# amount: 100
+ # We're like the Snapchat for Wikipedia. But really,
+ # change this amount. Stripe won't charge $9 billion.
+ }
+ }
+ end
+end
@@ -0,0 +1,49 @@
+class RateLimit
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ client_ip = env["REMOTE_ADDR"]
+ key = "count:#{client_ip}"
+ count = REDIS.get(key)
+ unless count
+ REDIS.set(key, 0)
+ REDIS.expire(key, THROTTLE_TIME_WINDOW)
+ end
+
+ if count.to_i >= THROTTLE_MAX_REQUESTS
+ [
+ 429,
+ rate_limit_headers(count, key),
+ [message]
+ ]
+ else
+ REDIS.incr(key)
+ status, headers, body = @app.call(env)
+ [
+ status,
+ headers.merge(rate_limit_headers(count.to_i + 1, key)),
+ body
+ ]
+ end
+ end
+
+ private
+ def message
+ {
+ :message => "You have fired too many requests. Please wait for some time."
+ }.to_json
+ end
+
+ def rate_limit_headers(count, key)
+ ttl = REDIS.ttl(key)
+ time = Time.now.to_i
+ time_till_reset = (time + ttl.to_i).to_s
+ {
+ "X-Rate-Limit-Limit" => "60",
+ "X-Rate-Limit-Remaining" => (60 - count.to_i).to_s,
+ "X-Rate-Limit-Reset" => time_till_reset
+ }
+ end
+end
View
@@ -12,7 +12,11 @@ def ensure_authentication_token
self.authentication_token = generate_authentication_token
end
end
-
+
+ def credits
+ self.credits_in_cents.to_f / 100.0
+ end
+
private
def generate_uuid
@@ -0,0 +1,16 @@
+<div class="page-header">
+ <h1>Dashboard</h1>
+</div>
+
+<div class="row">
+ <div class="well">
+ <div class="col-md-8">
+ <strong>Your remaining credits:</strong>
+ </div>
+ <div class="col-md-4">
+ <%= link_to "Buy More", new_purchase_url, class: "btn btn-lg btn-success pull-right" %>
+ <%= number_to_currency(current_user.credits) %>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+</div>
@@ -10,15 +10,15 @@
<div class="row">
<div class="col-md-4">
- <h2>Solves world hunger</h2>
- <p>Fakerio will deliver food and water to those in need, all over the world.</p>
+ <h2>How it works</h2>
+ <p>Fakerio will generate fake people, companies, products and more</p>
</div>
<div class="col-md-4">
- <h2>Eliminates poverty</h2>
- <p>Fakerio will deliver money and education to those in need, all over the world.</p>
+ <h2>Pricing</h2>
+ <p>Fakerio will charge 1 cent per HTTP request.</p>
</div>
<div class="col-md-4">
- <h2>Makes you better looking</h2>
- <p>Fakerio will make you better looking: it's scientifically proven to make men look like Ryan Gosling and women look like Shakira.</p>
+ <h2>Get involved</h2>
+ <p>Fakerio will grant you 1000 free request for one referal through twitter.</p>
</div>
</div>
@@ -0,0 +1,9 @@
+= form_tag purchases_path do
+
+ /The form doesn't pass the amount to the create action,
+ /so we have to pass it manually.
+ .controls
+ %label Enter the amount you wish to charge your account with
+ = text_field_tag :amount, @stripe_btn_hash[:data][:amount]
+ .controls
+ %script{ @stripe_btn_hash }
View
@@ -26,5 +26,6 @@ class Application < Rails::Application
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
+ config.middleware.use "RateLimit"
end
end
View
@@ -0,0 +1,2 @@
+STRIPE_SECRET_KEY: 'pk_test_nqmHCw1SfH53pcDIo8o4CZXs'
+STRIPE_PUBLISHABLE_KEY: 'sk_test_9BSKUfvoFChrKCCqczB0bxRG'
View
@@ -2,3 +2,13 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
+
+require 'rubygems'
+
+if File.exists?('.env')
+ env_lines = File.read(".env").split("\n")
+ env_lines.each do |line|
+ key, value = line.split("=")
+ ENV[key] ||= value
+ end
+end
@@ -0,0 +1,8 @@
+# Store the environment variables on the Rails.configuration object
+Rails.configuration.stripe = {
+ :publishable_key => 'pk_test_nqmHCw1SfH53pcDIo8o4CZXs',
+ :secret_key => 'sk_test_9BSKUfvoFChrKCCqczB0bxRG'
+}
+
+# Set our app-stored secret key with Stripe
+Stripe.api_key = Rails.configuration.stripe[:secret_key]
@@ -0,0 +1,7 @@
+require "redis"
+
+redis_conf = YAML.load(File.join(Rails.root, "config", "redis.yml"))
+REDIS = Redis.new(:host => redis_conf["host"], :port => redis_conf["port"])
+
+THROTTLE_TIME_WINDOW = 15 * 60
+THROTTLE_MAX_REQUESTS = 60
View
@@ -0,0 +1,2 @@
+host: localhost
+port: 6379
View
@@ -3,14 +3,21 @@
namespace :api do
namespace :v1 do
resources :people, only: [:index]
- resources :company, only: [:index]
+ resources :companies, only: [:index]
namespace :internet do
resources :ip_addresses, only: [:index]
resources :emails, only: [:index]
end
end
end
+ resources :purchases, only: [:new, :create]
devise_for :users
+ authenticated :user do
+ root to: "dashboards#index", as: :user_dashboard
+ end
+
+ resources :dashboards, only: [:index]
root :to => "home#index"
+ get 'foo.json' => 'foo#index'
end
@@ -0,0 +1,5 @@
+class AddCreditsInCentsToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :credits_in_cents, :integer, default: 0
+ end
+end
Oops, something went wrong.

0 comments on commit 6d7a6df

Please sign in to comment.