pwpush 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/Capfile +8 -0
  4. data/Gemfile +51 -0
  5. data/Gemfile.lock +224 -0
  6. data/LICENSE.txt +674 -0
  7. data/Procfile +3 -0
  8. data/README.md +91 -0
  9. data/Rakefile +8 -0
  10. data/TODO +21 -0
  11. data/app.json +21 -0
  12. data/app/assets/flash/clippy.swf +0 -0
  13. data/app/assets/flash/github-clippy.swf +0 -0
  14. data/app/assets/images/apple-touch-icon-ipad.png +0 -0
  15. data/app/assets/images/apple-touch-icon-ipad3.png +0 -0
  16. data/app/assets/images/apple-touch-icon-iphone.png +0 -0
  17. data/app/assets/images/apple-touch-icon-iphone4.png +0 -0
  18. data/app/assets/images/black_wood.jpg +0 -0
  19. data/app/assets/images/broken_noise.png +0 -0
  20. data/app/assets/images/button_down.png +0 -0
  21. data/app/assets/images/button_over.png +0 -0
  22. data/app/assets/images/button_up.png +0 -0
  23. data/app/assets/images/concrete_wall_3.png +0 -0
  24. data/app/assets/images/favicon.ico +0 -0
  25. data/app/assets/images/forkme.png +0 -0
  26. data/app/assets/images/outlets.png +0 -0
  27. data/app/assets/images/pwpush_favicon.jpg +0 -0
  28. data/app/assets/images/pwpush_logo.png +0 -0
  29. data/app/assets/images/rails.png +0 -0
  30. data/app/assets/javascripts/api.js.coffee +4 -0
  31. data/app/assets/javascripts/application.js +52 -0
  32. data/app/assets/javascripts/errors.js.coffee +3 -0
  33. data/app/assets/javascripts/fd-slider.js +1299 -0
  34. data/app/assets/javascripts/jquery-cookie.js +117 -0
  35. data/app/assets/javascripts/jquery.noty.js +520 -0
  36. data/app/assets/javascripts/layouts/top.js +34 -0
  37. data/app/assets/javascripts/passwords.js +62 -0
  38. data/app/assets/javascripts/spoiler.js +101 -0
  39. data/app/assets/javascripts/themes/default.js +156 -0
  40. data/app/assets/stylesheets/api.css.scss +3 -0
  41. data/app/assets/stylesheets/application.css +7 -0
  42. data/app/assets/stylesheets/errors.css.scss +3 -0
  43. data/app/assets/stylesheets/fd-slider.css +650 -0
  44. data/app/assets/stylesheets/global.css.scss +52 -0
  45. data/app/assets/stylesheets/passwords.css.scss +114 -0
  46. data/app/assets/stylesheets/users.css.scss +11 -0
  47. data/app/controllers/api_controller.rb +30 -0
  48. data/app/controllers/application_controller.rb +23 -0
  49. data/app/controllers/errors_controller.rb +7 -0
  50. data/app/controllers/passwords_controller.rb +153 -0
  51. data/app/controllers/users/omniauth_callbacks_controller.rb +71 -0
  52. data/app/controllers/views_controller.rb +11 -0
  53. data/app/helpers/api_helper.rb +2 -0
  54. data/app/helpers/application_helper.rb +31 -0
  55. data/app/helpers/errors_helper.rb +2 -0
  56. data/app/helpers/passwords_helper.rb +2 -0
  57. data/app/helpers/views_helper.rb +2 -0
  58. data/app/mailers/.gitkeep +0 -0
  59. data/app/models/.gitkeep +0 -0
  60. data/app/models/password.rb +51 -0
  61. data/app/models/user.rb +20 -0
  62. data/app/models/view.rb +4 -0
  63. data/app/views/api/config.html.haml +2 -0
  64. data/app/views/api/create.html.haml +2 -0
  65. data/app/views/api/generate.html.haml +2 -0
  66. data/app/views/api/list.html.haml +2 -0
  67. data/app/views/devise/confirmations/new.html.erb +12 -0
  68. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  69. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  70. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  71. data/app/views/devise/passwords/edit.html.erb +16 -0
  72. data/app/views/devise/passwords/new.html.erb +12 -0
  73. data/app/views/devise/registrations/edit.html.erb +25 -0
  74. data/app/views/devise/registrations/new.html.haml +50 -0
  75. data/app/views/devise/sessions/new.html.haml +51 -0
  76. data/app/views/devise/shared/_links.erb +25 -0
  77. data/app/views/devise/unlocks/new.html.erb +12 -0
  78. data/app/views/errors/error_404.html.haml +21 -0
  79. data/app/views/errors/error_500.html.haml +21 -0
  80. data/app/views/layouts/_ga.html.erb +14 -0
  81. data/app/views/layouts/application.html.haml +41 -0
  82. data/app/views/pages/about.html.haml +159 -0
  83. data/app/views/passwords/edit.html.haml +7 -0
  84. data/app/views/passwords/index.html.haml +17 -0
  85. data/app/views/passwords/new.html.haml +68 -0
  86. data/app/views/passwords/show.html.haml +58 -0
  87. data/app/views/shared/_auth_providers.html.haml +9 -0
  88. data/app/views/shared/_messages.html.haml +4 -0
  89. data/app/views/views/_form.html.erb +16 -0
  90. data/app/views/views/edit.html.erb +8 -0
  91. data/app/views/views/index.html.erb +21 -0
  92. data/app/views/views/new.html.erb +5 -0
  93. data/app/views/views/show.html.erb +20 -0
  94. data/bin/bundle +13 -0
  95. data/config.ru +4 -0
  96. data/config/application.rb +51 -0
  97. data/config/boot.rb +6 -0
  98. data/config/capistrano_database_yml.rb +158 -0
  99. data/config/database.yml +19 -0
  100. data/config/deploy.rb +140 -0
  101. data/config/deploy/database.yml.erb +52 -0
  102. data/config/deploy/local_cap_config.rb.example +54 -0
  103. data/config/environment.rb +42 -0
  104. data/config/environments/development.rb +30 -0
  105. data/config/environments/engineyard.rb +60 -0
  106. data/config/environments/private.rb +60 -0
  107. data/config/environments/production.rb +60 -0
  108. data/config/environments/test.rb +39 -0
  109. data/config/initializers/backtrace_silencers.rb +7 -0
  110. data/config/initializers/devise.rb +211 -0
  111. data/config/initializers/inflections.rb +10 -0
  112. data/config/initializers/mime_types.rb +5 -0
  113. data/config/initializers/secret_token.rb +7 -0
  114. data/config/initializers/session_store.rb +8 -0
  115. data/config/initializers/wrap_parameters.rb +14 -0
  116. data/config/locales/devise.en.yml +58 -0
  117. data/config/locales/en.yml +5 -0
  118. data/config/routes.rb +16 -0
  119. data/config/unicorn.rb +22 -0
  120. data/db/migrate/20111128183630_create_passwords.rb +12 -0
  121. data/db/migrate/20111228183300_create_views.rb +16 -0
  122. data/db/migrate/20120102210558_devise_create_users.rb +54 -0
  123. data/db/migrate/20120102210559_create_rails_admin_histories_table.rb +18 -0
  124. data/db/migrate/20120102220933_add_admin_to_user.rb +9 -0
  125. data/db/migrate/20120129211750_add_lockable_to_users.rb +10 -0
  126. data/db/migrate/20120220172426_add_user_to_password.rb +11 -0
  127. data/db/migrate/20121105144421_add_deleted_to_password.rb +5 -0
  128. data/db/migrate/20150323145847_add_first_view_flag.rb +9 -0
  129. data/db/migrate/20160214205926_add_deletable_to_password.rb +5 -0
  130. data/db/schema.rb +78 -0
  131. data/db/seeds.rb +7 -0
  132. data/log/.gitkeep +0 -0
  133. data/public/404.html +26 -0
  134. data/public/422.html +26 -0
  135. data/public/500.html +26 -0
  136. data/public/favicon.ico +0 -0
  137. data/public/robots.txt +3 -0
  138. data/script/rails +6 -0
  139. metadata +226 -0
@@ -0,0 +1,52 @@
1
+
2
+ @import url("https://fonts.googleapis.com/css?family=Crete+Round:400,400italic");
3
+
4
+ body {
5
+ margin: 0em 0em 3em 0em;
6
+ text-align: center;
7
+ background: #000000 image-url('outlets.png') repeat;
8
+ font-family: 'Crete Round', serif;
9
+ color: #ddd;
10
+ }
11
+
12
+ a:link, a:visited, a:active {
13
+ color: yellow;
14
+ text-decoration: none;
15
+ }
16
+
17
+ a:hover {
18
+ color: #00CC00;
19
+ text-decoration: none;
20
+ }
21
+
22
+ div.content {
23
+ margin-top: 50px;
24
+ }
25
+
26
+ .auth_providers_area {
27
+ width: 600px;
28
+ margin-left: auto;
29
+ margin-right: auto;
30
+ }
31
+
32
+ .auth_provider img {
33
+ display: block;
34
+ }
35
+
36
+ .auth_provider {
37
+ display: inline-block;
38
+ text-decoration: none;
39
+ margin-right: 20px;
40
+ text-align: center;
41
+ margin-bottom: 10px;
42
+ }
43
+
44
+ .footer {
45
+ font-size: 80%;
46
+ }
47
+
48
+ .about_content {
49
+ text-align: left;
50
+ width: 800px;
51
+ margin: 50px auto 50px auto;
52
+ }
@@ -0,0 +1,114 @@
1
+ // Place all the styles related to the passwords controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
4
+
5
+ input.password {
6
+ border: 1px solid #bbb;
7
+ width: 500px;
8
+ height: 25px;
9
+ text-align: center;
10
+ color: #808080;
11
+ font-size: 1.5em;
12
+ }
13
+
14
+ input.slider {
15
+ width: 400px;
16
+ }
17
+
18
+ p.slider_box, span#daysrange, span#viewsrange { vertical-align: top; }
19
+ p.slider_box { margin: .5em; }
20
+ span#daysrange, span#viewsrange { display: inline-block; width: 80px; text-align: left; }
21
+
22
+ div.title {
23
+ margin: 3em;
24
+ }
25
+
26
+ span.title {
27
+ font-size: 4em;
28
+ color: yellow;
29
+ }
30
+ span.tagline {
31
+ font-size: 1.5em;
32
+ }
33
+
34
+ p.payload { margin: 1em; }
35
+
36
+ p.notes { margin-top: 50px; font-size: .9em; }
37
+ span.note, span.tip { font-size: .9em; }
38
+ span.note { color: #808080; }
39
+ span.tip { font-style: italic; }
40
+ p.notes a:link, p.notes a:visited, p.notes a:hover, p.notes a:active { font-size: .9em; }
41
+
42
+ p.url { vertical-align: top; margin: 0;}
43
+
44
+ p.url input {
45
+ border: 1px solid #808080;
46
+ text-align: center;
47
+ width: 400px;
48
+ font-size: .8em;
49
+ }
50
+
51
+ p.url span.clippy {}
52
+
53
+ /* This is a decent font to display passwords as L, l, 0, o, i, I are fairly distinguishable */
54
+ @import url(https://fonts.googleapis.com/css?family=PT+Mono);
55
+
56
+ div.payload {
57
+ font-family: 'PT Mono', sans-serif;
58
+ font-size: 4em;
59
+ line-height: 4em;
60
+ border-top: 3px solid #eee;
61
+ border-bottom: 3px solid #eee;
62
+ background: #000;
63
+ opacity: 0.5;
64
+ -khtml-opacity: 0.5;
65
+ -moz-opacity: 0.5;
66
+ filter: alpha(opacity = 50);
67
+ }
68
+
69
+ .cookie-save { font-size: .9em; }
70
+
71
+ .share_note {
72
+ padding: 1em;
73
+ border: 2px solid yellow;
74
+ width: 600px;
75
+ margin-left: auto;
76
+ margin-right: auto;
77
+ margin-top: 0;
78
+ background: #000;
79
+ filter: alpha(opacity = 90);
80
+ -khtml-opacity: 0.90;
81
+ -moz-opacity: 0.90;
82
+ opacity: 0.9;
83
+ color: #fff;
84
+ }
85
+
86
+ #clippy { display: inline-block; }
87
+
88
+ #clippy span{ display: none; }
89
+
90
+ #clippy:hover span{
91
+ display: block;
92
+ position:absolute;
93
+ top: 5em;
94
+ color: #fff;
95
+ text-align: center;
96
+ padding: 1px;
97
+ font-size: .8em;
98
+ background: #808080;
99
+ border: 1px solid yellow;
100
+ z-index: 1;
101
+ filter: alpha(opacity = 90);
102
+ -khtml-opacity: 0.90;
103
+ -moz-opacity: 0.90;
104
+ opacity: 0.90;
105
+ }
106
+
107
+ div.footer_note {
108
+ clear: both;
109
+ color: #bebebe;
110
+ margin-top: 100px;
111
+ text-align: center;
112
+ font-size: .85em;
113
+ }
114
+
@@ -0,0 +1,11 @@
1
+
2
+ .sign_up {
3
+ width: 400px;
4
+ margin-left: auto;
5
+ margin-right: auto;
6
+ text-align: left;
7
+ }
8
+
9
+ .full_row {
10
+ text-align: center;
11
+ }
@@ -0,0 +1,30 @@
1
+ class ApiController < ApplicationController
2
+ def create
3
+ # Required Parameters
4
+ # api_key=string
5
+ # password=string
6
+
7
+ # Optional 1 time parameters
8
+ # expire_days=number
9
+ # expire_views=number
10
+
11
+ unless params.has_key?(:api_key)
12
+ respond_to do |format|
13
+ format.text { render :text => "Please provide your API key available at https://pwpush.com/api" }
14
+ end
15
+ return
16
+ end
17
+
18
+
19
+ end
20
+
21
+ def generate
22
+ end
23
+
24
+ def list
25
+ end
26
+
27
+ def config
28
+ end
29
+
30
+ end
@@ -0,0 +1,23 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+
4
+ def not_found
5
+ raise ActionController::RoutingError.new('Not Found')
6
+ end
7
+
8
+ # unless Rails.application.config.consider_all_requests_local
9
+ rescue_from Exception, with: lambda { |exception| render_error 500, exception }
10
+ rescue_from ActionController::RoutingError, ActionController::UnknownController,
11
+ ::AbstractController::ActionNotFound, ActiveRecord::RecordNotFound,
12
+ with: lambda { |exception| render_error 404, exception }
13
+ # end
14
+
15
+ private
16
+ def render_error(status, exception)
17
+ respond_to do |format|
18
+ format.html { render template: "errors/error_#{status}", layout: 'layouts/application', status: status }
19
+ format.all { render nothing: true, status: status }
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,7 @@
1
+ class ErrorsController < ApplicationController
2
+ def error_404
3
+ end
4
+
5
+ def error_500
6
+ end
7
+ end
@@ -0,0 +1,153 @@
1
+ class PasswordsController < ApplicationController
2
+ # GET /passwords/1
3
+ # GET /passwords/1.json
4
+ def show
5
+ if params.has_key?(:id)
6
+ @password = Password.find_by_url_token!(params[:id])
7
+
8
+ # If this is the first view, update record. Otherwise, record
9
+ # a view.
10
+ @first_view = @password.first_view
11
+
12
+ if @first_view
13
+ @password.update_attribute(:first_view, false)
14
+ else
15
+ @password.views = View.where(:password_id => @password.id, :successful => true)
16
+ end
17
+ else
18
+ redirect_to :root
19
+ return
20
+ end
21
+
22
+ # This password may have expired since the last view. Validate the password
23
+ # expiration before doing anything.
24
+ @password.validate!
25
+
26
+ unless @password.expired
27
+ # Decrypt the passwords
28
+ @key = EzCrypto::Key.with_password CRYPT_KEY, CRYPT_SALT
29
+ @payload = @key.decrypt64(@password.payload)
30
+ end
31
+
32
+ log_view(@password) unless @first_view
33
+
34
+ expires_now()
35
+
36
+ respond_to do |format|
37
+ format.html # show.html.erb
38
+ format.json { render :json => @password }
39
+ end
40
+ end
41
+
42
+ # GET /passwords/new
43
+ # GET /passwords/new.json
44
+ def new
45
+ @password = Password.new
46
+
47
+ expires_in 3.hours, :public => true, 'max-stale' => 0
48
+
49
+ respond_to do |format|
50
+ format.html # new.html.erb
51
+ format.json { render :json => @password }
52
+ end
53
+ end
54
+
55
+ # POST /passwords
56
+ # POST /passwords.json
57
+ def create
58
+ if params[:password][:payload].blank? or params[:password][:payload] == PAYLOAD_INITIAL_TEXT
59
+ redirect_to '/'
60
+ return
61
+ end
62
+
63
+ if params[:password][:payload].length > 250
64
+ redirect_to '/', :error => "That password is too long."
65
+ return
66
+ end
67
+
68
+ @password = Password.new()
69
+
70
+ @password.expire_after_days = params[:password][:expire_after_days]
71
+ @password.expire_after_views = params[:password][:expire_after_views]
72
+
73
+ if DELETABLE_BY_VIEWER_PASSWORDS && params[:password].key?(:deletable_by_viewer)
74
+ @password.deletable_by_viewer = true
75
+ else
76
+ @password.deletable_by_viewer = false
77
+ end
78
+
79
+ @password.url_token = rand(36**16).to_s(36)
80
+ @password.user_id = current_user.id if current_user
81
+
82
+ # The first view on new passwords are free since we redirect
83
+ # the passwd creator to the password itself (and don't burn up
84
+ # a view).
85
+ @password.first_view = true
86
+
87
+ # Encrypt the passwords
88
+ @key = EzCrypto::Key.with_password CRYPT_KEY, CRYPT_SALT
89
+ @password.payload = @key.encrypt64(params[:password][:payload])
90
+
91
+ @password.validate!
92
+
93
+ respond_to do |format|
94
+ if @password.save
95
+ format.html { redirect_to @password, :notice => "The password has been pushed." }
96
+ format.json { render :json => @password, :status => :created }
97
+ else
98
+ format.html { render :action => "new" }
99
+ format.json { render :json => @password.errors, :status => :unprocessable_entity }
100
+ end
101
+ end
102
+ end
103
+
104
+ def destroy
105
+ if params.has_key?(:id)
106
+ @password = Password.find_by_url_token!(params[:id])
107
+ end
108
+
109
+ # Redirect to root if we couldn't find password or
110
+ # the found password wasn't market as deletable
111
+ unless @password || @password.deletable_by_viewer
112
+ redirect_to :root
113
+ return
114
+ end
115
+
116
+ @password.expired = true
117
+ @password.payload = nil
118
+ @password.deleted = true
119
+
120
+ respond_to do |format|
121
+ if @password.save
122
+ format.html { redirect_to @password, :notice => "The password has been deleted." }
123
+ format.json { render :json => @password, :status => :destroyed }
124
+ else
125
+ format.html { render :action => "new" }
126
+ format.json { render :json => @password.errors, :status => :unprocessable_entity }
127
+ end
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ ##
134
+ # log_view
135
+ #
136
+ # Record that a view is being made for a password
137
+ #
138
+ def log_view(password)
139
+ view = View.new
140
+ view.password_id = password.id
141
+ view.ip = request.env["HTTP_X_FORWARDED_FOR"].nil? ? request.env["REMOTE_ADDR"] : request.env["HTTP_X_FORWARDED_FOR"]
142
+
143
+ # Limit retrieved values to 256 characters
144
+ view.user_agent = request.env["HTTP_USER_AGENT"].to_s[0,255]
145
+ view.referrer = request.env["HTTP_REFERER"].to_s[0,255]
146
+
147
+ view.successful = password.expired ? false : true
148
+ view.save
149
+
150
+ password.views << view
151
+ password
152
+ end
153
+ end
@@ -0,0 +1,71 @@
1
+ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
2
+ def google
3
+ @user = User.find_for_open_id(request.env["omniauth.auth"], current_user)
4
+
5
+ if @user.persisted?
6
+ flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
7
+ sign_in_and_redirect @user, :event => :authentication
8
+ else
9
+ session["devise.google_data"] = request.env["omniauth.auth"]
10
+ redirect_to new_user_registration_url
11
+ end
12
+ end
13
+ def yahoo
14
+ @user = User.find_for_open_id(request.env["omniauth.auth"], current_user)
15
+
16
+ if @user.persisted?
17
+ flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Yahoo"
18
+ sign_in_and_redirect @user, :event => :authentication
19
+ else
20
+ session["devise.yahoo_data"] = request.env["omniauth.auth"]
21
+ redirect_to new_user_registration_url
22
+ end
23
+ end
24
+ def twitter
25
+ @user = User.find_for_open_id(request.env["omniauth.auth"], current_user)
26
+
27
+ if @user.persisted?
28
+ flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter"
29
+ sign_in_and_redirect @user, :event => :authentication
30
+ else
31
+ session["devise.twitter_data"] = request.env["omniauth.auth"]
32
+ redirect_to new_user_registration_url
33
+ end
34
+ end
35
+
36
+ def create
37
+ unless params.has_key?(:confirm)
38
+ omniauth = request.env["omniauth.auth"]
39
+ authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
40
+ if authentication
41
+ flash[:success] = "Welcome back!"
42
+ sign_in_and_redirect(:user, authentication.user)
43
+ return
44
+
45
+ elsif user_signed_in?
46
+ current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
47
+ flash[:success] = "Successfully linked account. You can now use this account to log into Gameface."
48
+ redirect_to authentications_url and return
49
+
50
+ else
51
+ session[:omniauth] = omniauth.except('extra')
52
+ redirect_to auth_confirm_path and return
53
+ end
54
+ else
55
+ omniauth = session[:omniauth]
56
+ user = User.new
57
+ user.apply_omniauth(omniauth)
58
+ if params.has_key?(:email)
59
+ user.email = params[:email]
60
+ end
61
+ if user.save
62
+ flash[:success] = "Welcome to Gameface! We're excited to have you!"
63
+ sign_in_and_redirect(:user, user) and return
64
+ else
65
+ session[:omniauth] = omniauth.except('extra')
66
+ raise "failed to save user record"
67
+ redirect_to auth_finalize_path and return
68
+ end
69
+ end
70
+ end
71
+ end