fundraiser 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +72 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/javascripts/fundraiser/application.js +15 -0
  5. data/app/assets/stylesheets/fundraiser/application.css +13 -0
  6. data/app/assets/stylesheets/fundraiser/styles/forms.css.scss +16 -0
  7. data/app/controllers/fundraiser/application_controller.rb +14 -0
  8. data/app/controllers/fundraiser/home_controller.rb +4 -0
  9. data/app/controllers/fundraiser/ipns_controller.rb +24 -0
  10. data/app/controllers/fundraiser/manage/base_controller.rb +7 -0
  11. data/app/controllers/fundraiser/manage/rewards_controller.rb +45 -0
  12. data/app/controllers/fundraiser/manage/settings_controller.rb +17 -0
  13. data/app/controllers/fundraiser/pledges_controller.rb +32 -0
  14. data/app/controllers/fundraiser/rewards_controller.rb +9 -0
  15. data/app/controllers/fundraiser/thanks_controller.rb +6 -0
  16. data/app/helpers/fundraiser/application_helper.rb +16 -0
  17. data/app/models/fundraiser/contribution.rb +25 -0
  18. data/app/models/fundraiser/pledge.rb +8 -0
  19. data/app/models/fundraiser/reward.rb +10 -0
  20. data/app/models/fundraiser/settings.rb +39 -0
  21. data/app/views/fundraiser/application/_alerts.html.haml +5 -0
  22. data/app/views/fundraiser/application/_bootstrap_text_area.html.haml +9 -0
  23. data/app/views/fundraiser/application/_bootstrap_text_field.html.haml +9 -0
  24. data/app/views/fundraiser/application/_navbar.html.haml +6 -0
  25. data/app/views/fundraiser/devise/sessions/new.html.haml +16 -0
  26. data/app/views/fundraiser/home/show.html.haml +1 -0
  27. data/app/views/fundraiser/manage/rewards/_form.html.haml +3 -0
  28. data/app/views/fundraiser/manage/rewards/_reward.html.haml +6 -0
  29. data/app/views/fundraiser/manage/rewards/edit.html.haml +10 -0
  30. data/app/views/fundraiser/manage/rewards/index.html.haml +6 -0
  31. data/app/views/fundraiser/manage/rewards/new.html.haml +10 -0
  32. data/app/views/fundraiser/manage/settings/edit.html.haml +15 -0
  33. data/app/views/fundraiser/pledges/new.html.haml +19 -0
  34. data/app/views/fundraiser/pledges/show.html.haml +1 -0
  35. data/app/views/fundraiser/rewards/_reward.html.haml +5 -0
  36. data/app/views/fundraiser/rewards/index.html.haml +7 -0
  37. data/app/views/fundraiser/thanks/show.html.haml +1 -0
  38. data/app/views/layouts/fundraiser/application.html.haml +13 -0
  39. data/config/initializers/settings.rb +6 -0
  40. data/config/locales/devise.en.yml +58 -0
  41. data/config/routes.rb +13 -0
  42. data/db/migrate/20121008183146_create_fundraiser_settings.rb +10 -0
  43. data/db/migrate/20121009000016_create_fundraiser_rewards.rb +11 -0
  44. data/db/migrate/20121009070136_create_fundraiser_pledges.rb +19 -0
  45. data/db/migrate/20121010182436_create_fundraiser_contributions.rb +12 -0
  46. data/lib/amazon/fps/signature_utils.rb +142 -0
  47. data/lib/amazon/fps/signature_utils_for_outbound.rb +179 -0
  48. data/lib/amazon/fps/widget.rb +58 -0
  49. data/lib/fundraiser.rb +16 -0
  50. data/lib/fundraiser/engine.rb +5 -0
  51. data/lib/fundraiser/version.rb +3 -0
  52. data/lib/generators/fundraiser/views_generator.rb +11 -0
  53. data/lib/tasks/fundraiser_tasks.rake +7 -0
  54. metadata +293 -0
@@ -0,0 +1,5 @@
1
+ - if alert
2
+ .alert= alert
3
+
4
+ - if notice
5
+ .alert.alert-success= notice
@@ -0,0 +1,9 @@
1
+ .control-group
2
+ = f.label column, :class => "control-label"
3
+
4
+ .controls
5
+ = f.text_area column, :class => input_class, :rows => 10
6
+ - unless f.object.errors[column].empty?
7
+ .help-inline.error
8
+ = f.object.errors[column].join(', ')
9
+
@@ -0,0 +1,9 @@
1
+ .control-group
2
+ = f.label column, :class => "control-label"
3
+
4
+ .controls
5
+ = f.text_field column, :class => input_class
6
+ - unless f.object.errors[column].empty?
7
+ .help-inline.error
8
+ = f.object.errors[column].join(', ')
9
+
@@ -0,0 +1,6 @@
1
+ .navbar
2
+ .navbar-inner
3
+ = link_to 'Fundraiser', fundraiser.root_path, :class => 'brand'
4
+ %ul.nav
5
+ %li= link_to 'Manage Rewards', fundraiser.manage_rewards_path
6
+ %li= link_to 'Settings', fundraiser.edit_manage_settings_path
@@ -0,0 +1,16 @@
1
+ %h2 Sign in
2
+ = form_for(resource, :as => resource_name, :url => fundraiser.user_session_path) do |f|
3
+ %div
4
+ = f.label :email
5
+ %br/
6
+ = f.email_field :email
7
+ %div
8
+ = f.label :password
9
+ %br/
10
+ = f.password_field :password
11
+ - if devise_mapping.rememberable?
12
+ %div
13
+ = f.check_box :remember_me
14
+ = f.label :remember_me
15
+ %div= f.submit "Sign in", :class => "btn btn-primary"
16
+ = render "devise/shared/links"
@@ -0,0 +1 @@
1
+ %h1 Fundraiser
@@ -0,0 +1,3 @@
1
+ = bootstrap_text_field(f, :title, "span5")
2
+ = bootstrap_text_area(f, :description, "span5")
3
+ = bootstrap_text_field(f, :minimum_pledge, "span3")
@@ -0,0 +1,6 @@
1
+ = content_tag_for :tr, reward do
2
+ %td= reward.title
3
+ %td= reward.minimum_pledge
4
+ %td= link_to 'Edit', fundraiser.edit_manage_reward_path(reward)
5
+ %td= link_to 'Delete', fundraiser.manage_reward_path(reward),
6
+ :method => :delete, :confirm => "Are you sure?"
@@ -0,0 +1,10 @@
1
+ %h1 Edit Reward
2
+
3
+ .row
4
+ .span5
5
+ = form_for [ :manage, @reward ] do |f|
6
+ = render 'form', :f => f
7
+
8
+ .form-actions
9
+ = f.submit :class => "btn btn-primary"
10
+ = link_to 'Cancel', fundraiser.manage_rewards_path
@@ -0,0 +1,6 @@
1
+ %h1 Rewards
2
+
3
+ = link_to 'New Reward', new_manage_reward_path, :class => 'btn'
4
+
5
+ %table.table.table-striped
6
+ = render :partial => 'reward', :collection => @rewards
@@ -0,0 +1,10 @@
1
+ %h1 New Reward
2
+
3
+ .row
4
+ .span5
5
+ = form_for [ :manage, @reward ] do |f|
6
+ = render 'form', :f => f
7
+
8
+ .form-actions
9
+ = f.submit :class => "btn btn-primary"
10
+ = link_to 'Cancel', fundraiser.manage_rewards_path, :class => "btn"
@@ -0,0 +1,15 @@
1
+ %h1 Settings
2
+
3
+ = form_for [ :manage, @settings ], :url => {:controller => :settings, :action => :update }, :method => :put do |f|
4
+ %h2 General
5
+ - Fundraiser::Settings::GENERAL_SETTINGS.each do |setting|
6
+ = f.label setting
7
+ = f.text_field setting
8
+
9
+ %h2 Amazon Simplepay
10
+ - Fundraiser::Settings::AMAZON_SETTINGS.each do |setting|
11
+ = f.label setting
12
+ = f.text_field setting
13
+
14
+ .form-actions
15
+ = f.submit 'Update', :class => 'btn'
@@ -0,0 +1,19 @@
1
+ %h1 Make a pledge
2
+
3
+ = form_for [ :reward, @pledge ] do |f|
4
+ = bootstrap_text_field f, :pledge_amount
5
+ = bootstrap_text_field f, :name
6
+ = bootstrap_text_field f, :address_line_1
7
+ = bootstrap_text_field f, :address_line_2
8
+ = bootstrap_text_field f, :country
9
+ = bootstrap_text_field f, :state
10
+ = bootstrap_text_field f, :city
11
+ = bootstrap_text_field f, :zip_code
12
+ = bootstrap_text_field f, :phone
13
+
14
+ .form-actions
15
+ = f.submit 'Pledge Now'
16
+
17
+ .reward
18
+ %h2= @reward.title
19
+ %h3= @reward.description
@@ -0,0 +1 @@
1
+ %h1 Thank You
@@ -0,0 +1,5 @@
1
+ = div_for reward, :class => "span6" do
2
+ %h2= "#{reward.title} (#{number_to_currency(reward.minimum_pledge)})"
3
+ .description.lead= reward.description
4
+ .buy
5
+ = simplepay_button(reward)
@@ -0,0 +1,7 @@
1
+ %h1 Choose a Reward
2
+
3
+ %h2 Total Contribution: #{number_to_currency Fundraiser::Contribution.total_contributed}
4
+ %h3 of #{number_to_currency Fundraiser::Settings.funding_goal} until #{Fundraiser::Settings.funding_end_date}
5
+
6
+ #rewards
7
+ .row= render @rewards
@@ -0,0 +1 @@
1
+ %h1 Thank you!
@@ -0,0 +1,13 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Fundraiser
5
+ = stylesheet_link_tag "//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap-combined.min.css"
6
+ = stylesheet_link_tag "fundraiser/application", :media => "all"
7
+ = javascript_include_tag "fundraiser/application"
8
+ = csrf_meta_tags
9
+ %body
10
+ .container
11
+ .row= render 'fundraiser/application/navbar'
12
+ .row= render 'fundraiser/application/alerts'
13
+ .row= yield
@@ -0,0 +1,6 @@
1
+ Fundraiser::Settings.load_from_persistance
2
+
3
+ if Fundraiser::Settings.ready?
4
+ Fundraiser::Settings.
5
+ amazon_checkout_url = ENV['AMAZON_FPS_URL'] || "https://authorize.payments-sandbox.amazon.com/pba/paypipeline"
6
+ end
@@ -0,0 +1,58 @@
1
+ # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2
+
3
+ en:
4
+ errors:
5
+ messages:
6
+ expired: "has expired, please request a new one"
7
+ not_found: "not found"
8
+ already_confirmed: "was already confirmed, please try signing in"
9
+ not_locked: "was not locked"
10
+ not_saved:
11
+ one: "1 error prohibited this %{resource} from being saved:"
12
+ other: "%{count} errors prohibited this %{resource} from being saved:"
13
+
14
+ devise:
15
+ failure:
16
+ already_authenticated: 'You are already signed in.'
17
+ unauthenticated: 'You need to sign in or sign up before continuing.'
18
+ unconfirmed: 'You have to confirm your account before continuing.'
19
+ locked: 'Your account is locked.'
20
+ invalid: 'Invalid email or password.'
21
+ invalid_token: 'Invalid authentication token.'
22
+ timeout: 'Your session expired, please sign in again to continue.'
23
+ inactive: 'Your account was not activated yet.'
24
+ sessions:
25
+ signed_in: 'Signed in successfully.'
26
+ signed_out: 'Signed out successfully.'
27
+ passwords:
28
+ send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
29
+ updated: 'Your password was changed successfully. You are now signed in.'
30
+ updated_not_active: 'Your password was changed successfully.'
31
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
32
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
33
+ confirmations:
34
+ send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
35
+ send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
36
+ confirmed: 'Your account was successfully confirmed. You are now signed in.'
37
+ registrations:
38
+ signed_up: 'Welcome! You have signed up successfully.'
39
+ signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
40
+ signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
41
+ signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
42
+ updated: 'You updated your account successfully.'
43
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
44
+ destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
45
+ unlocks:
46
+ send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
47
+ unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
48
+ send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
49
+ omniauth_callbacks:
50
+ success: 'Successfully authenticated from %{kind} account.'
51
+ failure: 'Could not authenticate you from %{kind} because "%{reason}".'
52
+ mailer:
53
+ confirmation_instructions:
54
+ subject: 'Confirmation instructions'
55
+ reset_password_instructions:
56
+ subject: 'Reset password instructions'
57
+ unlock_instructions:
58
+ subject: 'Unlock Instructions'
@@ -0,0 +1,13 @@
1
+ Fundraiser::Engine.routes.draw do
2
+ root :to => 'rewards#index'
3
+
4
+ namespace :manage do
5
+ root :to => 'rewards#index'
6
+ resource :settings
7
+ resources :rewards
8
+ end
9
+
10
+ resources :rewards, :only => :index
11
+ resource :thanks, :only => :show
12
+ resources :ipns
13
+ end
@@ -0,0 +1,10 @@
1
+ class CreateFundraiserSettings < ActiveRecord::Migration
2
+ def change
3
+ create_table :fundraiser_settings do |t|
4
+ t.string :var
5
+ t.text :value
6
+ end
7
+
8
+ add_index :fundraiser_settings, :var
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ class CreateFundraiserRewards < ActiveRecord::Migration
2
+ def change
3
+ create_table :fundraiser_rewards do |t|
4
+ t.string :title
5
+ t.text :description
6
+ t.integer :minimum_pledge
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ class CreateFundraiserPledges < ActiveRecord::Migration
2
+ def change
3
+ create_table :fundraiser_pledges do |t|
4
+ t.integer :user_id
5
+ t.integer :reward_id
6
+ t.integer :pledge_amount
7
+ t.string :name
8
+ t.string :address_line_1
9
+ t.string :address_line_2
10
+ t.string :state
11
+ t.string :city
12
+ t.string :zip_code
13
+ t.string :phone
14
+ t.string :country
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ class CreateFundraiserContributions < ActiveRecord::Migration
2
+ def change
3
+ create_table :fundraiser_contributions do |t|
4
+ t.string :email
5
+ t.string :reference
6
+ t.text :request_params
7
+ t.integer :amount
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,142 @@
1
+ ###############################################################################
2
+ # Copyright 2008-2010 Amazon Technologies, Inc
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ #
5
+ # You may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at: http://aws.amazon.com/apache2.0
7
+ # This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
9
+ # specific language governing permissions and limitations under the License.
10
+ ##############################################################################
11
+ require 'base64'
12
+ require 'cgi'
13
+ require 'openssl'
14
+
15
+ module Amazon
16
+ module FPS
17
+
18
+ #
19
+ # Copyright:: Copyright (c) 2009 Amazon.com, Inc. or its affiliates. All Rights Reserved.
20
+ #
21
+ # RFC 2104-compliant HMAC signature for request parameters
22
+ # Implements AWS Signature, as per following spec:
23
+ #
24
+ # If Signature Version is 1, it performs the following:
25
+ #
26
+ # Sorts all parameters (including SignatureVersion and excluding Signature,
27
+ # the value of which is being created), ignoring case.
28
+ #
29
+ # Iterate over the sorted list and append the parameter name (in original case)
30
+ # and then its value. It will not URL-encode the parameter values before
31
+ # constructing this string. There are no separators.
32
+ #
33
+ # If Signature Version is 2, string to sign is based on following:
34
+ #
35
+ # 1. The HTTP Request Method followed by an ASCII newline (%0A)
36
+ # 2. The HTTP Host header in the form of lowercase host, followed by an ASCII newline.
37
+ # 3. The URL encoded HTTP absolute path component of the URI
38
+ # (up to but not including the query string parameters);
39
+ # if this is empty use a forward '/'. This parameter is followed by an ASCII newline.
40
+ # 4. The concatenation of all query string components (names and values)
41
+ # as UTF-8 characters which are URL encoded as per RFC 3986
42
+ # (hex characters MUST be uppercase), sorted using lexicographic byte ordering.
43
+ # Parameter names are separated from their values by the '=' character
44
+ # (ASCII character 61), even if the value is empty.
45
+ # Pairs of parameter and values are separated by the '&' character (ASCII code 38).
46
+ #
47
+ class SignatureUtils
48
+
49
+ SIGNATURE_KEYNAME = "Signature"
50
+ SIGNATURE_METHOD_KEYNAME = "SignatureMethod"
51
+ SIGNATURE_VERSION_KEYNAME = "SignatureVersion"
52
+
53
+ HMAC_SHA256_ALGORITHM = "HmacSHA256"
54
+ HMAC_SHA1_ALGORITHM = "HmacSHA1"
55
+
56
+ def self.sign_parameters(args)
57
+ signature_version = args[:parameters][SIGNATURE_VERSION_KEYNAME]
58
+ string_to_sign = "";
59
+ algorithm = 'sha1';
60
+ if (signature_version == '1') then
61
+ string_to_sign = calculate_string_to_sign_v1(args)
62
+ elsif (signature_version == '2') then
63
+ algorithm = get_algorithm(args[:parameters][SIGNATURE_METHOD_KEYNAME])
64
+ string_to_sign = calculate_string_to_sign_v2(args)
65
+ else
66
+ raise "Invalid Signature Version specified"
67
+ end
68
+ return compute_signature(string_to_sign, args[:aws_secret_key], algorithm)
69
+ end
70
+
71
+ # Convert a string into URL encoded form.
72
+ def self.urlencode(plaintext)
73
+ CGI.escape(plaintext.to_s).gsub("+", "%20").gsub("%7E", "~")
74
+ end
75
+
76
+ private # All the methods below are private
77
+
78
+ def self.calculate_string_to_sign_v1(args)
79
+ parameters = args[:parameters]
80
+
81
+ # exclude any existing Signature parameter from the canonical string
82
+ sorted = (parameters.reject { |k, v| k == SIGNATURE_KEYNAME }).sort { |a,b| a[0].downcase <=> b[0].downcase }
83
+
84
+ canonical = ''
85
+ sorted.each do |v|
86
+ canonical << v[0]
87
+ canonical << v[1] unless(v[1].nil?)
88
+ end
89
+
90
+ return canonical
91
+ end
92
+
93
+ def self.calculate_string_to_sign_v2(args)
94
+ parameters = args[:parameters]
95
+
96
+ uri = args[:uri]
97
+ uri = "/" if uri.nil? or uri.empty?
98
+ uri = urlencode(uri).gsub("%2F", "/")
99
+
100
+ verb = args[:verb]
101
+ host = args[:host].downcase
102
+
103
+
104
+ # exclude any existing Signature parameter from the canonical string
105
+ sorted = (parameters.reject { |k, v| k == SIGNATURE_KEYNAME }).sort
106
+
107
+ canonical = "#{verb}\n#{host}\n#{uri}\n"
108
+ isFirst = true
109
+
110
+ sorted.each { |v|
111
+ if(isFirst) then
112
+ isFirst = false
113
+ else
114
+ canonical << '&'
115
+ end
116
+
117
+ canonical << urlencode(v[0])
118
+ unless(v[1].nil?) then
119
+ canonical << '='
120
+ canonical << urlencode(v[1])
121
+ end
122
+ }
123
+
124
+ return canonical
125
+ end
126
+
127
+ def self.get_algorithm(signature_method)
128
+ return 'sha256' if (signature_method == HMAC_SHA256_ALGORITHM);
129
+ return 'sha1'
130
+ end
131
+
132
+ def self.compute_signature(canonical, aws_secret_key, algorithm = 'sha1')
133
+ digest = OpenSSL::Digest::Digest.new(algorithm)
134
+ return Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_key, canonical)).chomp
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+ end
141
+
142
+