diff options
36 files changed, 1046 insertions, 7 deletions
diff --git a/Gemfile b/Gemfile index e2147ef..32a78dc 100644 --- a/Gemfile +++ b/Gemfile | |||
@@ -55,3 +55,4 @@ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] | |||
55 | 55 | ||
56 | gem 'haml' | 56 | gem 'haml' |
57 | gem 'normalize-rails' | 57 | gem 'normalize-rails' |
58 | gem 'devise' | ||
diff --git a/Gemfile.lock b/Gemfile.lock index 60b7136..41f4d51 100644 --- a/Gemfile.lock +++ b/Gemfile.lock | |||
@@ -41,6 +41,7 @@ GEM | |||
41 | addressable (2.5.1) | 41 | addressable (2.5.1) |
42 | public_suffix (~> 2.0, >= 2.0.2) | 42 | public_suffix (~> 2.0, >= 2.0.2) |
43 | arel (8.0.0) | 43 | arel (8.0.0) |
44 | bcrypt (3.1.11) | ||
44 | bindex (0.5.0) | 45 | bindex (0.5.0) |
45 | builder (3.2.3) | 46 | builder (3.2.3) |
46 | byebug (9.0.6) | 47 | byebug (9.0.6) |
@@ -61,6 +62,12 @@ GEM | |||
61 | execjs | 62 | execjs |
62 | coffee-script-source (1.12.2) | 63 | coffee-script-source (1.12.2) |
63 | concurrent-ruby (1.0.5) | 64 | concurrent-ruby (1.0.5) |
65 | devise (4.3.0) | ||
66 | bcrypt (~> 3.0) | ||
67 | orm_adapter (~> 0.1) | ||
68 | railties (>= 4.1.0, < 5.2) | ||
69 | responders | ||
70 | warden (~> 1.2.3) | ||
64 | erubi (1.6.0) | 71 | erubi (1.6.0) |
65 | execjs (2.7.0) | 72 | execjs (2.7.0) |
66 | ffi (1.9.18) | 73 | ffi (1.9.18) |
@@ -92,6 +99,7 @@ GEM | |||
92 | nokogiri (1.8.0) | 99 | nokogiri (1.8.0) |
93 | mini_portile2 (~> 2.2.0) | 100 | mini_portile2 (~> 2.2.0) |
94 | normalize-rails (4.1.1) | 101 | normalize-rails (4.1.1) |
102 | orm_adapter (0.5.0) | ||
95 | public_suffix (2.0.5) | 103 | public_suffix (2.0.5) |
96 | puma (3.9.1) | 104 | puma (3.9.1) |
97 | rack (2.0.3) | 105 | rack (2.0.3) |
@@ -124,6 +132,9 @@ GEM | |||
124 | rb-fsevent (0.9.8) | 132 | rb-fsevent (0.9.8) |
125 | rb-inotify (0.9.10) | 133 | rb-inotify (0.9.10) |
126 | ffi (>= 0.5.0, < 2) | 134 | ffi (>= 0.5.0, < 2) |
135 | responders (2.4.0) | ||
136 | actionpack (>= 4.2.0, < 5.3) | ||
137 | railties (>= 4.2.0, < 5.3) | ||
127 | ruby_dep (1.5.0) | 138 | ruby_dep (1.5.0) |
128 | rubyzip (1.2.1) | 139 | rubyzip (1.2.1) |
129 | sass (3.4.24) | 140 | sass (3.4.24) |
@@ -160,6 +171,8 @@ GEM | |||
160 | thread_safe (~> 0.1) | 171 | thread_safe (~> 0.1) |
161 | uglifier (3.2.0) | 172 | uglifier (3.2.0) |
162 | execjs (>= 0.3.0, < 3) | 173 | execjs (>= 0.3.0, < 3) |
174 | warden (1.2.7) | ||
175 | rack (>= 1.0) | ||
163 | web-console (3.5.1) | 176 | web-console (3.5.1) |
164 | actionview (>= 5.0) | 177 | actionview (>= 5.0) |
165 | activemodel (>= 5.0) | 178 | activemodel (>= 5.0) |
@@ -178,6 +191,7 @@ DEPENDENCIES | |||
178 | byebug | 191 | byebug |
179 | capybara (~> 2.13) | 192 | capybara (~> 2.13) |
180 | coffee-rails (~> 4.2) | 193 | coffee-rails (~> 4.2) |
194 | devise | ||
181 | haml | 195 | haml |
182 | jbuilder (~> 2.5) | 196 | jbuilder (~> 2.5) |
183 | listen (>= 3.0.5, < 3.2) | 197 | listen (>= 3.0.5, < 3.2) |
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 40358bb..5ddb0bb 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | @import url('https://fonts.googleapis.com/css?family=Inconsolata'); | 18 | @import url('https://fonts.googleapis.com/css?family=Inconsolata'); |
19 | 19 | ||
20 | body { | 20 | body#main-body { |
21 | background-color: #bfefff; | 21 | background-color: #bfefff; |
22 | } | 22 | } |
23 | 23 | ||
@@ -76,3 +76,140 @@ body { | |||
76 | #sidebar h2 { | 76 | #sidebar h2 { |
77 | font-size: 1em; | 77 | font-size: 1em; |
78 | } | 78 | } |
79 | |||
80 | #flash { | ||
81 | width: 100%; | ||
82 | text-align: center; | ||
83 | padding: .25em; | ||
84 | font-weight: bold | ||
85 | } | ||
86 | |||
87 | .flash-notice { | ||
88 | background-color: #fffde8; | ||
89 | } | ||
90 | |||
91 | .flash-alert { | ||
92 | background-color: #ff6a6a; | ||
93 | } | ||
94 | |||
95 | html { | ||
96 | height: 100%; | ||
97 | } | ||
98 | |||
99 | body#userdata-body { | ||
100 | background-color: #eeeeee; | ||
101 | height: 100%; | ||
102 | } | ||
103 | |||
104 | #userdata-container { | ||
105 | margin: 4em auto 0; | ||
106 | width: 25%; | ||
107 | } | ||
108 | |||
109 | #userdata-form { | ||
110 | background-color: #fefefe; | ||
111 | -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
112 | -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
113 | box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
114 | border-radius: 2px 2px 2px 2px; | ||
115 | -moz-border-radius: 2px 2px 2px 2px; | ||
116 | -webkit-border-radius: 2px 2px 2px 2px; | ||
117 | padding: 1em; | ||
118 | } | ||
119 | |||
120 | #userdata-form .field { | ||
121 | margin-bottom: 1em; | ||
122 | } | ||
123 | |||
124 | #userdata-form .field label { | ||
125 | display: block; | ||
126 | margin-bottom: .25em; | ||
127 | } | ||
128 | |||
129 | #userdata-form input[type=text], #userdata-form input[type=password] { | ||
130 | font-size: 24px; | ||
131 | padding: 3px; | ||
132 | width: 100%; | ||
133 | box-sizing: border-box; | ||
134 | -webkit-box-shadow: inset 0px 1px 2px 0px rgba(0,0,0,0.7); | ||
135 | -moz-box-shadow: inset 0px 1px 2px 0px rgba(0,0,0,0.7); | ||
136 | box-shadow: inset 0px 1px 2px 0px rgba(0,0,0,0.7); | ||
137 | border: 1px solid #ddd; | ||
138 | outline: 0; | ||
139 | border-radius: 0; | ||
140 | } | ||
141 | |||
142 | .remember-me-field { | ||
143 | float: left; | ||
144 | } | ||
145 | |||
146 | .submit-field { | ||
147 | text-align: right; | ||
148 | } | ||
149 | |||
150 | .userdata-link { | ||
151 | margin: 1em; | ||
152 | } | ||
153 | |||
154 | .userdata-link a { | ||
155 | text-decoration: none; | ||
156 | } | ||
157 | |||
158 | .userdata-link a:hover { | ||
159 | text-decoration: underline; | ||
160 | } | ||
161 | |||
162 | #userdata-form, .userdata-link a, .userdata-link a:visited { | ||
163 | color: #555d66; | ||
164 | } | ||
165 | |||
166 | #userdata-form label, .userdata-link a { | ||
167 | font-size: .75em; | ||
168 | } | ||
169 | |||
170 | #userdata-flash { | ||
171 | color: black; | ||
172 | background-color: white; | ||
173 | padding: .75em; | ||
174 | margin-bottom: 2em; | ||
175 | font-size: .8em; | ||
176 | -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
177 | -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
178 | box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75); | ||
179 | } | ||
180 | |||
181 | .userdata-flash-alert { | ||
182 | border-left: 5px solid red; | ||
183 | } | ||
184 | |||
185 | .userdata-flash-notice { | ||
186 | border-left: 5px solid green; | ||
187 | } | ||
188 | |||
189 | .userdata-flash-tag { | ||
190 | font-weight: bold; | ||
191 | } | ||
192 | |||
193 | .sidebar-module + .sidebar-module { | ||
194 | margin-top: 2em; | ||
195 | } | ||
196 | |||
197 | .sidebar-module ul { | ||
198 | padding-left: 0; | ||
199 | } | ||
200 | |||
201 | .sidebar-module li { | ||
202 | list-style-type: none; | ||
203 | } | ||
204 | |||
205 | .sidebar-module a { | ||
206 | text-decoration: none; | ||
207 | } | ||
208 | |||
209 | .sidebar-module a:hover { | ||
210 | text-decoration: underline; | ||
211 | } | ||
212 | |||
213 | .sidebar-module a:visited { | ||
214 | color: #352712; | ||
215 | } | ||
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c07694..0174cae 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb | |||
@@ -1,3 +1,9 @@ | |||
1 | class ApplicationController < ActionController::Base | 1 | class ApplicationController < ActionController::Base |
2 | protect_from_forgery with: :exception | 2 | protect_from_forgery with: :exception |
3 | |||
4 | private | ||
5 | |||
6 | def after_sign_out_path_for(resource) | ||
7 | new_session_path(resource) | ||
8 | end | ||
3 | end | 9 | end |
diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb new file mode 100644 index 0000000..1126e23 --- /dev/null +++ b/app/controllers/users/confirmations_controller.rb | |||
@@ -0,0 +1,28 @@ | |||
1 | class Users::ConfirmationsController < Devise::ConfirmationsController | ||
2 | # GET /resource/confirmation/new | ||
3 | # def new | ||
4 | # super | ||
5 | # end | ||
6 | |||
7 | # POST /resource/confirmation | ||
8 | # def create | ||
9 | # super | ||
10 | # end | ||
11 | |||
12 | # GET /resource/confirmation?confirmation_token=abcdef | ||
13 | # def show | ||
14 | # super | ||
15 | # end | ||
16 | |||
17 | # protected | ||
18 | |||
19 | # The path used after resending confirmation instructions. | ||
20 | # def after_resending_confirmation_instructions_path_for(resource_name) | ||
21 | # super(resource_name) | ||
22 | # end | ||
23 | |||
24 | # The path used after confirmation. | ||
25 | # def after_confirmation_path_for(resource_name, resource) | ||
26 | # super(resource_name, resource) | ||
27 | # end | ||
28 | end | ||
diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb new file mode 100644 index 0000000..1907e5b --- /dev/null +++ b/app/controllers/users/omniauth_callbacks_controller.rb | |||
@@ -0,0 +1,28 @@ | |||
1 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController | ||
2 | # You should configure your model like this: | ||
3 | # devise :omniauthable, omniauth_providers: [:twitter] | ||
4 | |||
5 | # You should also create an action method in this controller like this: | ||
6 | # def twitter | ||
7 | # end | ||
8 | |||
9 | # More info at: | ||
10 | # https://github.com/plataformatec/devise#omniauth | ||
11 | |||
12 | # GET|POST /resource/auth/twitter | ||
13 | # def passthru | ||
14 | # super | ||
15 | # end | ||
16 | |||
17 | # GET|POST /users/auth/twitter/callback | ||
18 | # def failure | ||
19 | # super | ||
20 | # end | ||
21 | |||
22 | # protected | ||
23 | |||
24 | # The path used when OmniAuth fails | ||
25 | # def after_omniauth_failure_path_for(scope) | ||
26 | # super(scope) | ||
27 | # end | ||
28 | end | ||
diff --git a/app/controllers/users/passwords_controller.rb b/app/controllers/users/passwords_controller.rb new file mode 100644 index 0000000..53cc34e --- /dev/null +++ b/app/controllers/users/passwords_controller.rb | |||
@@ -0,0 +1,32 @@ | |||
1 | class Users::PasswordsController < Devise::PasswordsController | ||
2 | # GET /resource/password/new | ||
3 | # def new | ||
4 | # super | ||
5 | # end | ||
6 | |||
7 | # POST /resource/password | ||
8 | # def create | ||
9 | # super | ||
10 | # end | ||
11 | |||
12 | # GET /resource/password/edit?reset_password_token=abcdef | ||
13 | # def edit | ||
14 | # super | ||
15 | # end | ||
16 | |||
17 | # PUT /resource/password | ||
18 | # def update | ||
19 | # super | ||
20 | # end | ||
21 | |||
22 | # protected | ||
23 | |||
24 | # def after_resetting_password_path_for(resource) | ||
25 | # super(resource) | ||
26 | # end | ||
27 | |||
28 | # The path used after sending reset password instructions | ||
29 | # def after_sending_reset_password_instructions_path_for(resource_name) | ||
30 | # super(resource_name) | ||
31 | # end | ||
32 | end | ||
diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb new file mode 100644 index 0000000..4d6fbad --- /dev/null +++ b/app/controllers/users/registrations_controller.rb | |||
@@ -0,0 +1,60 @@ | |||
1 | class Users::RegistrationsController < Devise::RegistrationsController | ||
2 | # before_action :configure_sign_up_params, only: [:create] | ||
3 | # before_action :configure_account_update_params, only: [:update] | ||
4 | |||
5 | # GET /resource/sign_up | ||
6 | # def new | ||
7 | # super | ||
8 | # end | ||
9 | |||
10 | # POST /resource | ||
11 | # def create | ||
12 | # super | ||
13 | # end | ||
14 | |||
15 | # GET /resource/edit | ||
16 | # def edit | ||
17 | # super | ||
18 | # end | ||
19 | |||
20 | # PUT /resource | ||
21 | # def update | ||
22 | # super | ||
23 | # end | ||
24 | |||
25 | # DELETE /resource | ||
26 | # def destroy | ||
27 | # super | ||
28 | # end | ||
29 | |||
30 | # GET /resource/cancel | ||
31 | # Forces the session data which is usually expired after sign | ||
32 | # in to be expired now. This is useful if the user wants to | ||
33 | # cancel oauth signing in/up in the middle of the process, | ||
34 | # removing all OAuth session data. | ||
35 | # def cancel | ||
36 | # super | ||
37 | # end | ||
38 | |||
39 | # protected | ||
40 | |||
41 | # If you have extra params to permit, append them to the sanitizer. | ||
42 | # def configure_sign_up_params | ||
43 | # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) | ||
44 | # end | ||
45 | |||
46 | # If you have extra params to permit, append them to the sanitizer. | ||
47 | # def configure_account_update_params | ||
48 | # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) | ||
49 | # end | ||
50 | |||
51 | # The path used after sign up. | ||
52 | # def after_sign_up_path_for(resource) | ||
53 | # super(resource) | ||
54 | # end | ||
55 | |||
56 | # The path used after sign up for inactive accounts. | ||
57 | # def after_inactive_sign_up_path_for(resource) | ||
58 | # super(resource) | ||
59 | # end | ||
60 | end | ||
diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb new file mode 100644 index 0000000..889fba5 --- /dev/null +++ b/app/controllers/users/sessions_controller.rb | |||
@@ -0,0 +1,26 @@ | |||
1 | class Users::SessionsController < Devise::SessionsController | ||
2 | layout "userdata" | ||
3 | # before_action :configure_sign_in_params, only: [:create] | ||
4 | |||
5 | # GET /resource/sign_in | ||
6 | # def new | ||
7 | # super | ||
8 | # end | ||
9 | |||
10 | # POST /resource/sign_in | ||
11 | # def create | ||
12 | # super | ||
13 | # end | ||
14 | |||
15 | # DELETE /resource/sign_out | ||
16 | # def destroy | ||
17 | # super | ||
18 | # end | ||
19 | |||
20 | # protected | ||
21 | |||
22 | # If you have extra params to permit, append them to the sanitizer. | ||
23 | # def configure_sign_in_params | ||
24 | # devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute]) | ||
25 | # end | ||
26 | end | ||
diff --git a/app/controllers/users/unlocks_controller.rb b/app/controllers/users/unlocks_controller.rb new file mode 100644 index 0000000..8b9ef86 --- /dev/null +++ b/app/controllers/users/unlocks_controller.rb | |||
@@ -0,0 +1,28 @@ | |||
1 | class Users::UnlocksController < Devise::UnlocksController | ||
2 | # GET /resource/unlock/new | ||
3 | # def new | ||
4 | # super | ||
5 | # end | ||
6 | |||
7 | # POST /resource/unlock | ||
8 | # def create | ||
9 | # super | ||
10 | # end | ||
11 | |||
12 | # GET /resource/unlock?unlock_token=abcdef | ||
13 | # def show | ||
14 | # super | ||
15 | # end | ||
16 | |||
17 | # protected | ||
18 | |||
19 | # The path used after sending unlock password instructions | ||
20 | # def after_sending_unlock_instructions_path_for(resource) | ||
21 | # super(resource) | ||
22 | # end | ||
23 | |||
24 | # The path used after unlocking the resource | ||
25 | # def after_unlock_path_for(resource) | ||
26 | # super(resource) | ||
27 | # end | ||
28 | end | ||
diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..b8bdae1 --- /dev/null +++ b/app/models/user.rb | |||
@@ -0,0 +1,6 @@ | |||
1 | class User < ApplicationRecord | ||
2 | # Include default devise modules. Others available are: | ||
3 | # :confirmable, :lockable, :timeoutable and :omniauthable | ||
4 | devise :database_authenticatable, | ||
5 | :recoverable, :rememberable, :trackable, :validatable | ||
6 | end | ||
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 0000000..2dc668f --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb | |||
@@ -0,0 +1,16 @@ | |||
1 | <h2>Resend confirmation instructions</h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | |||
6 | <div class="field"> | ||
7 | <%= f.label :email %><br /> | ||
8 | <%= f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %> | ||
9 | </div> | ||
10 | |||
11 | <div class="actions"> | ||
12 | <%= f.submit "Resend confirmation instructions" %> | ||
13 | </div> | ||
14 | <% end %> | ||
15 | |||
16 | <%= render "devise/shared/links" %> | ||
diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb new file mode 100644 index 0000000..dc55f64 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.erb | |||
@@ -0,0 +1,5 @@ | |||
1 | <p>Welcome <%= @email %>!</p> | ||
2 | |||
3 | <p>You can confirm your account email through the link below:</p> | ||
4 | |||
5 | <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p> | ||
diff --git a/app/views/devise/mailer/email_changed.html.erb b/app/views/devise/mailer/email_changed.html.erb new file mode 100644 index 0000000..32f4ba8 --- /dev/null +++ b/app/views/devise/mailer/email_changed.html.erb | |||
@@ -0,0 +1,7 @@ | |||
1 | <p>Hello <%= @email %>!</p> | ||
2 | |||
3 | <% if @resource.try(:unconfirmed_email?) %> | ||
4 | <p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p> | ||
5 | <% else %> | ||
6 | <p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p> | ||
7 | <% end %> | ||
diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb new file mode 100644 index 0000000..b41daf4 --- /dev/null +++ b/app/views/devise/mailer/password_change.html.erb | |||
@@ -0,0 +1,3 @@ | |||
1 | <p>Hello <%= @resource.email %>!</p> | ||
2 | |||
3 | <p>We're contacting you to notify you that your password has been changed.</p> | ||
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 0000000..f667dc1 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb | |||
@@ -0,0 +1,8 @@ | |||
1 | <p>Hello <%= @resource.email %>!</p> | ||
2 | |||
3 | <p>Someone has requested a link to change your password. You can do this through the link below.</p> | ||
4 | |||
5 | <p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p> | ||
6 | |||
7 | <p>If you didn't request this, please ignore this email.</p> | ||
8 | <p>Your password won't change until you access the link above and create a new one.</p> | ||
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 0000000..41e148b --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb | |||
@@ -0,0 +1,7 @@ | |||
1 | <p>Hello <%= @resource.email %>!</p> | ||
2 | |||
3 | <p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p> | ||
4 | |||
5 | <p>Click the link below to unlock your account:</p> | ||
6 | |||
7 | <p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p> | ||
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 0000000..6a796b0 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb | |||
@@ -0,0 +1,25 @@ | |||
1 | <h2>Change your password</h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | <%= f.hidden_field :reset_password_token %> | ||
6 | |||
7 | <div class="field"> | ||
8 | <%= f.label :password, "New password" %><br /> | ||
9 | <% if @minimum_password_length %> | ||
10 | <em>(<%= @minimum_password_length %> characters minimum)</em><br /> | ||
11 | <% end %> | ||
12 | <%= f.password_field :password, autofocus: true, autocomplete: "off" %> | ||
13 | </div> | ||
14 | |||
15 | <div class="field"> | ||
16 | <%= f.label :password_confirmation, "Confirm new password" %><br /> | ||
17 | <%= f.password_field :password_confirmation, autocomplete: "off" %> | ||
18 | </div> | ||
19 | |||
20 | <div class="actions"> | ||
21 | <%= f.submit "Change my password" %> | ||
22 | </div> | ||
23 | <% end %> | ||
24 | |||
25 | <%= render "devise/shared/links" %> | ||
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb new file mode 100644 index 0000000..3d6d11a --- /dev/null +++ b/app/views/devise/passwords/new.html.erb | |||
@@ -0,0 +1,16 @@ | |||
1 | <h2>Forgot your password?</h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | |||
6 | <div class="field"> | ||
7 | <%= f.label :email %><br /> | ||
8 | <%= f.email_field :email, autofocus: true %> | ||
9 | </div> | ||
10 | |||
11 | <div class="actions"> | ||
12 | <%= f.submit "Send me reset password instructions" %> | ||
13 | </div> | ||
14 | <% end %> | ||
15 | |||
16 | <%= render "devise/shared/links" %> | ||
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb new file mode 100644 index 0000000..1e66f3d --- /dev/null +++ b/app/views/devise/registrations/edit.html.erb | |||
@@ -0,0 +1,43 @@ | |||
1 | <h2>Edit <%= resource_name.to_s.humanize %></h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | |||
6 | <div class="field"> | ||
7 | <%= f.label :email %><br /> | ||
8 | <%= f.email_field :email, autofocus: true %> | ||
9 | </div> | ||
10 | |||
11 | <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> | ||
12 | <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div> | ||
13 | <% end %> | ||
14 | |||
15 | <div class="field"> | ||
16 | <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br /> | ||
17 | <%= f.password_field :password, autocomplete: "off" %> | ||
18 | <% if @minimum_password_length %> | ||
19 | <br /> | ||
20 | <em><%= @minimum_password_length %> characters minimum</em> | ||
21 | <% end %> | ||
22 | </div> | ||
23 | |||
24 | <div class="field"> | ||
25 | <%= f.label :password_confirmation %><br /> | ||
26 | <%= f.password_field :password_confirmation, autocomplete: "off" %> | ||
27 | </div> | ||
28 | |||
29 | <div class="field"> | ||
30 | <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br /> | ||
31 | <%= f.password_field :current_password, autocomplete: "off" %> | ||
32 | </div> | ||
33 | |||
34 | <div class="actions"> | ||
35 | <%= f.submit "Update" %> | ||
36 | </div> | ||
37 | <% end %> | ||
38 | |||
39 | <h3>Cancel my account</h3> | ||
40 | |||
41 | <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p> | ||
42 | |||
43 | <%= link_to "Back", :back %> | ||
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 0000000..5a238ce --- /dev/null +++ b/app/views/devise/registrations/new.html.erb | |||
@@ -0,0 +1,29 @@ | |||
1 | <h2>Sign up</h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | |||
6 | <div class="field"> | ||
7 | <%= f.label :email %><br /> | ||
8 | <%= f.email_field :email, autofocus: true %> | ||
9 | </div> | ||
10 | |||
11 | <div class="field"> | ||
12 | <%= f.label :password %> | ||
13 | <% if @minimum_password_length %> | ||
14 | <em>(<%= @minimum_password_length %> characters minimum)</em> | ||
15 | <% end %><br /> | ||
16 | <%= f.password_field :password, autocomplete: "off" %> | ||
17 | </div> | ||
18 | |||
19 | <div class="field"> | ||
20 | <%= f.label :password_confirmation %><br /> | ||
21 | <%= f.password_field :password_confirmation, autocomplete: "off" %> | ||
22 | </div> | ||
23 | |||
24 | <div class="actions"> | ||
25 | <%= f.submit "Sign up" %> | ||
26 | </div> | ||
27 | <% end %> | ||
28 | |||
29 | <%= render "devise/shared/links" %> | ||
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb new file mode 100644 index 0000000..e6a3e41 --- /dev/null +++ b/app/views/devise/shared/_links.html.erb | |||
@@ -0,0 +1,25 @@ | |||
1 | <%- if controller_name != 'sessions' %> | ||
2 | <%= link_to "Log in", new_session_path(resource_name) %><br /> | ||
3 | <% end -%> | ||
4 | |||
5 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %> | ||
6 | <%= link_to "Sign up", new_registration_path(resource_name) %><br /> | ||
7 | <% end -%> | ||
8 | |||
9 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> | ||
10 | <%= link_to "Forgot your password?", new_password_path(resource_name) %><br /> | ||
11 | <% end -%> | ||
12 | |||
13 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> | ||
14 | <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br /> | ||
15 | <% end -%> | ||
16 | |||
17 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> | ||
18 | <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br /> | ||
19 | <% end -%> | ||
20 | |||
21 | <%- if devise_mapping.omniauthable? %> | ||
22 | <%- resource_class.omniauth_providers.each do |provider| %> | ||
23 | <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br /> | ||
24 | <% end -%> | ||
25 | <% end -%> | ||
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb new file mode 100644 index 0000000..16586bc --- /dev/null +++ b/app/views/devise/unlocks/new.html.erb | |||
@@ -0,0 +1,16 @@ | |||
1 | <h2>Resend unlock instructions</h2> | ||
2 | |||
3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> | ||
4 | <%= devise_error_messages! %> | ||
5 | |||
6 | <div class="field"> | ||
7 | <%= f.label :email %><br /> | ||
8 | <%= f.email_field :email, autofocus: true %> | ||
9 | </div> | ||
10 | |||
11 | <div class="actions"> | ||
12 | <%= f.submit "Resend unlock instructions" %> | ||
13 | </div> | ||
14 | <% end %> | ||
15 | |||
16 | <%= render "devise/shared/links" %> | ||
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 55d7805..e9d8dfd 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml | |||
@@ -5,12 +5,24 @@ | |||
5 | = csrf_meta_tags | 5 | = csrf_meta_tags |
6 | = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' | 6 | = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' |
7 | = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' | 7 | = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' |
8 | %body | 8 | %body#main-body |
9 | - if flash[:alert] | ||
10 | %div#flash.flash-alert= flash[:alert] | ||
11 | - if flash[:notice] | ||
12 | %div#flash.flash-notice= flash[:notice] | ||
9 | #container | 13 | #container |
10 | #banner | 14 | #banner |
11 | %h1= link_to "Thoughts", root_url | 15 | %h1= link_to "Thoughts", root_url |
12 | #main | 16 | #main |
13 | #content= yield | 17 | #content= yield |
14 | #sidebar | 18 | #sidebar |
15 | %h2 I'm Fef. | 19 | .sidebar-module |
16 | %p I'm a computer science undergrad at Carnegie Mellon University. I make a lot of things, including Twitter bots. I really like Pokémon, and I write about it a lot. | 20 | %h2 I'm Fef. |
21 | %p I'm a computer science undergrad at Carnegie Mellon University. I make a lot of things, including Twitter bots. I really like Pokémon, and I write about it a lot. | ||
22 | .sidebar-module | ||
23 | %h2 Meta | ||
24 | %ul | ||
25 | - if not user_signed_in? | ||
26 | %li= link_to "Log in", new_user_session_path | ||
27 | - if user_signed_in? | ||
28 | %li= link_to "Log out", destroy_user_session_path, method: :delete | ||
diff --git a/app/views/layouts/userdata.html.haml b/app/views/layouts/userdata.html.haml new file mode 100644 index 0000000..f6e3b57 --- /dev/null +++ b/app/views/layouts/userdata.html.haml | |||
@@ -0,0 +1,18 @@ | |||
1 | !!! 5 | ||
2 | %html | ||
3 | %head | ||
4 | %title Thoughts | ||
5 | = csrf_meta_tags | ||
6 | = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' | ||
7 | = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' | ||
8 | %body#userdata-body | ||
9 | #userdata-container | ||
10 | - if flash[:alert] | ||
11 | #userdata-flash.userdata-flash-alert | ||
12 | %span.userdata-flash-tag ERROR: | ||
13 | = flash.alert | ||
14 | - if flash[:notice] | ||
15 | #userdata-flash.userdata-flash-notice | ||
16 | %span.userdata-flash-tag NOTICE: | ||
17 | = flash.notice | ||
18 | = yield | ||
diff --git a/app/views/users/sessions/.new.html.haml.swo b/app/views/users/sessions/.new.html.haml.swo new file mode 100644 index 0000000..85950d9 --- /dev/null +++ b/app/views/users/sessions/.new.html.haml.swo | |||
Binary files differ | |||
diff --git a/app/views/users/sessions/new.html.haml b/app/views/users/sessions/new.html.haml new file mode 100644 index 0000000..fbdf8be --- /dev/null +++ b/app/views/users/sessions/new.html.haml | |||
@@ -0,0 +1,15 @@ | |||
1 | #userdata-form | ||
2 | = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| | ||
3 | .field | ||
4 | = f.label :login | ||
5 | = f.text_field :login, autofocus: true | ||
6 | .field | ||
7 | = f.label :password | ||
8 | = f.password_field :password, autocomplete: "off" | ||
9 | .remember-me-field | ||
10 | = f.check_box :remember_me | ||
11 | = f.label :remember_me | ||
12 | .submit-field | ||
13 | = f.submit "Log in" | ||
14 | .userdata-link= link_to "Forgot your password?", new_password_path(resource_name) | ||
15 | .userdata-link= link_to "← Back to thoughts", root_url | ||
diff --git a/config/environments/development.rb b/config/environments/development.rb index 5187e22..1b0c4b3 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb | |||
@@ -51,4 +51,6 @@ Rails.application.configure do | |||
51 | # Use an evented file watcher to asynchronously detect changes in source code, | 51 | # Use an evented file watcher to asynchronously detect changes in source code, |
52 | # routes, locales, etc. This feature depends on the listen gem. | 52 | # routes, locales, etc. This feature depends on the listen gem. |
53 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker | 53 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker |
54 | |||
55 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } | ||
54 | end | 56 | end |
diff --git a/config/environments/production.rb b/config/environments/production.rb index 3606f65..03d15d1 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb | |||
@@ -45,7 +45,7 @@ Rails.application.configure do | |||
45 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] | 45 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] |
46 | 46 | ||
47 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. | 47 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. |
48 | # config.force_ssl = true | 48 | config.force_ssl = true |
49 | 49 | ||
50 | # Use the lowest log level to ensure availability of diagnostic information | 50 | # Use the lowest log level to ensure availability of diagnostic information |
51 | # when problems arise. | 51 | # when problems arise. |
@@ -66,6 +66,8 @@ Rails.application.configure do | |||
66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. | 66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. |
67 | # config.action_mailer.raise_delivery_errors = false | 67 | # config.action_mailer.raise_delivery_errors = false |
68 | 68 | ||
69 | config.action_mailer.default_url_options = { host: 'feffernoo.se' } | ||
70 | |||
69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to | 71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to |
70 | # the I18n.default_locale when a translation cannot be found). | 72 | # the I18n.default_locale when a translation cannot be found). |
71 | config.i18n.fallbacks = true | 73 | config.i18n.fallbacks = true |
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb new file mode 100644 index 0000000..f85c0a6 --- /dev/null +++ b/config/initializers/devise.rb | |||
@@ -0,0 +1,278 @@ | |||
1 | # Use this hook to configure devise mailer, warden hooks and so forth. | ||
2 | # Many of these configuration options can be set straight in your model. | ||
3 | Devise.setup do |config| | ||
4 | # The secret key used by Devise. Devise uses this key to generate | ||
5 | # random tokens. Changing this key will render invalid all existing | ||
6 | # confirmation, reset password and unlock tokens in the database. | ||
7 | # Devise will use the `secret_key_base` as its `secret_key` | ||
8 | # by default. You can change it below and use your own secret key. | ||
9 | # config.secret_key = 'f85d289a63b03808f899604ae6f3b1ba93430a8a7e9a5c0ee817471e4d4e201f000e8d42386392d4c24add7b4e2f0e011ea491c1febb57b37301e63b67f0ed60' | ||
10 | |||
11 | # ==> Mailer Configuration | ||
12 | # Configure the e-mail address which will be shown in Devise::Mailer, | ||
13 | # note that it will be overwritten if you use your own mailer class | ||
14 | # with default "from" parameter. | ||
15 | config.mailer_sender = 'no-reply@feffernoo.se' | ||
16 | |||
17 | # Configure the class responsible to send e-mails. | ||
18 | # config.mailer = 'Devise::Mailer' | ||
19 | |||
20 | # Configure the parent class responsible to send e-mails. | ||
21 | # config.parent_mailer = 'ActionMailer::Base' | ||
22 | |||
23 | # ==> ORM configuration | ||
24 | # Load and configure the ORM. Supports :active_record (default) and | ||
25 | # :mongoid (bson_ext recommended) by default. Other ORMs may be | ||
26 | # available as additional gems. | ||
27 | require 'devise/orm/active_record' | ||
28 | |||
29 | # ==> Configuration for any authentication mechanism | ||
30 | # Configure which keys are used when authenticating a user. The default is | ||
31 | # just :email. You can configure it to use [:username, :subdomain], so for | ||
32 | # authenticating a user, both parameters are required. Remember that those | ||
33 | # parameters are used only when authenticating and not when retrieving from | ||
34 | # session. If you need permissions, you should implement that in a before filter. | ||
35 | # You can also supply a hash where the value is a boolean determining whether | ||
36 | # or not authentication should be aborted when the value is not present. | ||
37 | # config.authentication_keys = [:email] | ||
38 | config.authentication_keys = [:login] | ||
39 | |||
40 | # Configure parameters from the request object used for authentication. Each entry | ||
41 | # given should be a request method and it will automatically be passed to the | ||
42 | # find_for_authentication method and considered in your model lookup. For instance, | ||
43 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. | ||
44 | # The same considerations mentioned for authentication_keys also apply to request_keys. | ||
45 | # config.request_keys = [] | ||
46 | |||
47 | # Configure which authentication keys should be case-insensitive. | ||
48 | # These keys will be downcased upon creating or modifying a user and when used | ||
49 | # to authenticate or find a user. Default is :email. | ||
50 | config.case_insensitive_keys = [] | ||
51 | |||
52 | # Configure which authentication keys should have whitespace stripped. | ||
53 | # These keys will have whitespace before and after removed upon creating or | ||
54 | # modifying a user and when used to authenticate or find a user. Default is :email. | ||
55 | config.strip_whitespace_keys = [:login] | ||
56 | |||
57 | # Tell if authentication through request.params is enabled. True by default. | ||
58 | # It can be set to an array that will enable params authentication only for the | ||
59 | # given strategies, for example, `config.params_authenticatable = [:database]` will | ||
60 | # enable it only for database (email + password) authentication. | ||
61 | # config.params_authenticatable = true | ||
62 | |||
63 | # Tell if authentication through HTTP Auth is enabled. False by default. | ||
64 | # It can be set to an array that will enable http authentication only for the | ||
65 | # given strategies, for example, `config.http_authenticatable = [:database]` will | ||
66 | # enable it only for database authentication. The supported strategies are: | ||
67 | # :database = Support basic authentication with authentication key + password | ||
68 | # config.http_authenticatable = false | ||
69 | |||
70 | # If 401 status code should be returned for AJAX requests. True by default. | ||
71 | # config.http_authenticatable_on_xhr = true | ||
72 | |||
73 | # The realm used in Http Basic Authentication. 'Application' by default. | ||
74 | # config.http_authentication_realm = 'Application' | ||
75 | |||
76 | # It will change confirmation, password recovery and other workflows | ||
77 | # to behave the same regardless if the e-mail provided was right or wrong. | ||
78 | # Does not affect registerable. | ||
79 | # config.paranoid = true | ||
80 | |||
81 | # By default Devise will store the user in session. You can skip storage for | ||
82 | # particular strategies by setting this option. | ||
83 | # Notice that if you are skipping storage for all authentication paths, you | ||
84 | # may want to disable generating routes to Devise's sessions controller by | ||
85 | # passing skip: :sessions to `devise_for` in your config/routes.rb | ||
86 | config.skip_session_storage = [:http_auth] | ||
87 | |||
88 | # By default, Devise cleans up the CSRF token on authentication to | ||
89 | # avoid CSRF token fixation attacks. This means that, when using AJAX | ||
90 | # requests for sign in and sign up, you need to get a new CSRF token | ||
91 | # from the server. You can disable this option at your own risk. | ||
92 | # config.clean_up_csrf_token_on_authentication = true | ||
93 | |||
94 | # When false, Devise will not attempt to reload routes on eager load. | ||
95 | # This can reduce the time taken to boot the app but if your application | ||
96 | # requires the Devise mappings to be loaded during boot time the application | ||
97 | # won't boot properly. | ||
98 | # config.reload_routes = true | ||
99 | |||
100 | # ==> Configuration for :database_authenticatable | ||
101 | # For bcrypt, this is the cost for hashing the password and defaults to 11. If | ||
102 | # using other algorithms, it sets how many times you want the password to be hashed. | ||
103 | # | ||
104 | # Limiting the stretches to just one in testing will increase the performance of | ||
105 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use | ||
106 | # a value less than 10 in other environments. Note that, for bcrypt (the default | ||
107 | # algorithm), the cost increases exponentially with the number of stretches (e.g. | ||
108 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). | ||
109 | config.stretches = Rails.env.test? ? 1 : 11 | ||
110 | |||
111 | # Set up a pepper to generate the hashed password. | ||
112 | # config.pepper = '371cc1e0f4d476a1969326be1ae6e43e8959b187b04be1b39225325a9429541174c0de9ddb3cf270dbf03d7df0711c744b82ca8d9fd27f69a09bf8162d262f80' | ||
113 | |||
114 | # Send a notification to the original email when the user's email is changed. | ||
115 | # config.send_email_changed_notification = false | ||
116 | |||
117 | # Send a notification email when the user's password is changed. | ||
118 | # config.send_password_change_notification = false | ||
119 | |||
120 | # ==> Configuration for :confirmable | ||
121 | # A period that the user is allowed to access the website even without | ||
122 | # confirming their account. For instance, if set to 2.days, the user will be | ||
123 | # able to access the website for two days without confirming their account, | ||
124 | # access will be blocked just in the third day. Default is 0.days, meaning | ||
125 | # the user cannot access the website without confirming their account. | ||
126 | # config.allow_unconfirmed_access_for = 2.days | ||
127 | |||
128 | # A period that the user is allowed to confirm their account before their | ||
129 | # token becomes invalid. For example, if set to 3.days, the user can confirm | ||
130 | # their account within 3 days after the mail was sent, but on the fourth day | ||
131 | # their account can't be confirmed with the token any more. | ||
132 | # Default is nil, meaning there is no restriction on how long a user can take | ||
133 | # before confirming their account. | ||
134 | # config.confirm_within = 3.days | ||
135 | |||
136 | # If true, requires any email changes to be confirmed (exactly the same way as | ||
137 | # initial account confirmation) to be applied. Requires additional unconfirmed_email | ||
138 | # db field (see migrations). Until confirmed, new email is stored in | ||
139 | # unconfirmed_email column, and copied to email column on successful confirmation. | ||
140 | config.reconfirmable = true | ||
141 | |||
142 | # Defines which key will be used when confirming an account | ||
143 | # config.confirmation_keys = [:email] | ||
144 | |||
145 | # ==> Configuration for :rememberable | ||
146 | # The time the user will be remembered without asking for credentials again. | ||
147 | # config.remember_for = 2.weeks | ||
148 | |||
149 | # Invalidates all the remember me tokens when the user signs out. | ||
150 | config.expire_all_remember_me_on_sign_out = true | ||
151 | |||
152 | # If true, extends the user's remember period when remembered via cookie. | ||
153 | # config.extend_remember_period = false | ||
154 | |||
155 | # Options to be passed to the created cookie. For instance, you can set | ||
156 | # secure: true in order to force SSL only cookies. | ||
157 | # config.rememberable_options = {} | ||
158 | |||
159 | # ==> Configuration for :validatable | ||
160 | # Range for password length. | ||
161 | config.password_length = 6..128 | ||
162 | |||
163 | # Email regex used to validate email formats. It simply asserts that | ||
164 | # one (and only one) @ exists in the given string. This is mainly | ||
165 | # to give user feedback and not to assert the e-mail validity. | ||
166 | config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ | ||
167 | |||
168 | # ==> Configuration for :timeoutable | ||
169 | # The time you want to timeout the user session without activity. After this | ||
170 | # time the user will be asked for credentials again. Default is 30 minutes. | ||
171 | # config.timeout_in = 30.minutes | ||
172 | |||
173 | # ==> Configuration for :lockable | ||
174 | # Defines which strategy will be used to lock an account. | ||
175 | # :failed_attempts = Locks an account after a number of failed attempts to sign in. | ||
176 | # :none = No lock strategy. You should handle locking by yourself. | ||
177 | # config.lock_strategy = :failed_attempts | ||
178 | |||
179 | # Defines which key will be used when locking and unlocking an account | ||
180 | # config.unlock_keys = [:email] | ||
181 | |||
182 | # Defines which strategy will be used to unlock an account. | ||
183 | # :email = Sends an unlock link to the user email | ||
184 | # :time = Re-enables login after a certain amount of time (see :unlock_in below) | ||
185 | # :both = Enables both strategies | ||
186 | # :none = No unlock strategy. You should handle unlocking by yourself. | ||
187 | # config.unlock_strategy = :both | ||
188 | |||
189 | # Number of authentication tries before locking an account if lock_strategy | ||
190 | # is failed attempts. | ||
191 | # config.maximum_attempts = 20 | ||
192 | |||
193 | # Time interval to unlock the account if :time is enabled as unlock_strategy. | ||
194 | # config.unlock_in = 1.hour | ||
195 | |||
196 | # Warn on the last attempt before the account is locked. | ||
197 | # config.last_attempt_warning = true | ||
198 | |||
199 | # ==> Configuration for :recoverable | ||
200 | # | ||
201 | # Defines which key will be used when recovering the password for an account | ||
202 | # config.reset_password_keys = [:email] | ||
203 | |||
204 | # Time interval you can reset your password with a reset password key. | ||
205 | # Don't put a too small interval or your users won't have the time to | ||
206 | # change their passwords. | ||
207 | config.reset_password_within = 6.hours | ||
208 | |||
209 | # When set to false, does not sign a user in automatically after their password is | ||
210 | # reset. Defaults to true, so a user is signed in automatically after a reset. | ||
211 | # config.sign_in_after_reset_password = true | ||
212 | |||
213 | # ==> Configuration for :encryptable | ||
214 | # Allow you to use another hashing or encryption algorithm besides bcrypt (default). | ||
215 | # You can use :sha1, :sha512 or algorithms from others authentication tools as | ||
216 | # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 | ||
217 | # for default behavior) and :restful_authentication_sha1 (then you should set | ||
218 | # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). | ||
219 | # | ||
220 | # Require the `devise-encryptable` gem when using anything other than bcrypt | ||
221 | # config.encryptor = :sha512 | ||
222 | |||
223 | # ==> Scopes configuration | ||
224 | # Turn scoped views on. Before rendering "sessions/new", it will first check for | ||
225 | # "users/sessions/new". It's turned off by default because it's slower if you | ||
226 | # are using only default views. | ||
227 | # config.scoped_views = false | ||
228 | |||
229 | # Configure the default scope given to Warden. By default it's the first | ||
230 | # devise role declared in your routes (usually :user). | ||
231 | # config.default_scope = :user | ||
232 | |||
233 | # Set this configuration to false if you want /users/sign_out to sign out | ||
234 | # only the current scope. By default, Devise signs out all scopes. | ||
235 | # config.sign_out_all_scopes = true | ||
236 | |||
237 | # ==> Navigation configuration | ||
238 | # Lists the formats that should be treated as navigational. Formats like | ||
239 | # :html, should redirect to the sign in page when the user does not have | ||
240 | # access, but formats like :xml or :json, should return 401. | ||
241 | # | ||
242 | # If you have any extra navigational formats, like :iphone or :mobile, you | ||
243 | # should add them to the navigational formats lists. | ||
244 | # | ||
245 | # The "*/*" below is required to match Internet Explorer requests. | ||
246 | # config.navigational_formats = ['*/*', :html] | ||
247 | |||
248 | # The default HTTP method used to sign out a resource. Default is :delete. | ||
249 | config.sign_out_via = :delete | ||
250 | |||
251 | # ==> OmniAuth | ||
252 | # Add a new OmniAuth provider. Check the wiki for more information on setting | ||
253 | # up on your models and hooks. | ||
254 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' | ||
255 | |||
256 | # ==> Warden configuration | ||
257 | # If you want to use other strategies, that are not supported by Devise, or | ||
258 | # change the failure app, you can configure them inside the config.warden block. | ||
259 | # | ||
260 | # config.warden do |manager| | ||
261 | # manager.intercept_401 = false | ||
262 | # manager.default_strategies(scope: :user).unshift :some_external_strategy | ||
263 | # end | ||
264 | |||
265 | # ==> Mountable engine configurations | ||
266 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine | ||
267 | # is mountable, there are some extra configurations to be taken into account. | ||
268 | # The following options are available, assuming the engine is mounted as: | ||
269 | # | ||
270 | # mount MyEngine, at: '/my_engine' | ||
271 | # | ||
272 | # The router that invoked `devise_for`, in the example above, would be: | ||
273 | # config.router_name = :my_engine | ||
274 | # | ||
275 | # When using OmniAuth, Devise cannot automatically set OmniAuth path, | ||
276 | # so you need to do it manually. For the users scope, it would be: | ||
277 | # config.omniauth_path_prefix = '/my_engine/users/auth' | ||
278 | end | ||
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml new file mode 100644 index 0000000..0b8f130 --- /dev/null +++ b/config/locales/devise.en.yml | |||
@@ -0,0 +1,64 @@ | |||
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n | ||
2 | |||
3 | en: | ||
4 | devise: | ||
5 | confirmations: | ||
6 | confirmed: "Your email address has been successfully confirmed." | ||
7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." | ||
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." | ||
9 | failure: | ||
10 | already_authenticated: "You are already signed in." | ||
11 | inactive: "Your account is not activated yet." | ||
12 | invalid: "Invalid %{authentication_keys} or password." | ||
13 | locked: "Your account is locked." | ||
14 | last_attempt: "You have one more attempt before your account is locked." | ||
15 | not_found_in_database: "Invalid %{authentication_keys} or password." | ||
16 | timeout: "Your session expired. Please sign in again to continue." | ||
17 | unauthenticated: "You need to sign in or sign up before continuing." | ||
18 | unconfirmed: "You have to confirm your email address before continuing." | ||
19 | mailer: | ||
20 | confirmation_instructions: | ||
21 | subject: "Confirmation instructions" | ||
22 | reset_password_instructions: | ||
23 | subject: "Reset password instructions" | ||
24 | unlock_instructions: | ||
25 | subject: "Unlock instructions" | ||
26 | email_changed: | ||
27 | subject: "Email Changed" | ||
28 | password_change: | ||
29 | subject: "Password Changed" | ||
30 | omniauth_callbacks: | ||
31 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." | ||
32 | success: "Successfully authenticated from %{kind} account." | ||
33 | passwords: | ||
34 | 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." | ||
35 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." | ||
36 | 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." | ||
37 | updated: "Your password has been changed successfully. You are now signed in." | ||
38 | updated_not_active: "Your password has been changed successfully." | ||
39 | registrations: | ||
40 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." | ||
41 | signed_up: "Welcome! You have signed up successfully." | ||
42 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." | ||
43 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." | ||
44 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." | ||
45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." | ||
46 | updated: "Your account has been updated successfully." | ||
47 | sessions: | ||
48 | signed_in: "Signed in successfully." | ||
49 | signed_out: "Signed out successfully." | ||
50 | already_signed_out: "Signed out successfully." | ||
51 | unlocks: | ||
52 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." | ||
53 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." | ||
54 | unlocked: "Your account has been unlocked successfully. Please sign in to continue." | ||
55 | errors: | ||
56 | messages: | ||
57 | already_confirmed: "was already confirmed, please try signing in" | ||
58 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" | ||
59 | expired: "has expired, please request a new one" | ||
60 | not_found: "not found" | ||
61 | not_locked: "was not locked" | ||
62 | not_saved: | ||
63 | one: "1 error prohibited this %{resource} from being saved:" | ||
64 | other: "%{count} errors prohibited this %{resource} from being saved:" | ||
diff --git a/config/routes.rb b/config/routes.rb index 64b02aa..9c94f8a 100644 --- a/config/routes.rb +++ b/config/routes.rb | |||
@@ -1,5 +1,6 @@ | |||
1 | Rails.application.routes.draw do | 1 | Rails.application.routes.draw do |
2 | # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html | 2 | devise_for :users, controllers: { sessions: 'users/sessions' } |
3 | |||
3 | root "records#index" | 4 | root "records#index" |
4 | 5 | ||
5 | get 'says/:slug', to: 'entries#show' | 6 | get 'says/:slug', to: 'entries#show' |
diff --git a/db/migrate/20170625151955_devise_create_users.rb b/db/migrate/20170625151955_devise_create_users.rb new file mode 100644 index 0000000..799f225 --- /dev/null +++ b/db/migrate/20170625151955_devise_create_users.rb | |||
@@ -0,0 +1,44 @@ | |||
1 | class DeviseCreateUsers < ActiveRecord::Migration[5.1] | ||
2 | def change | ||
3 | create_table :users do |t| | ||
4 | ## Database authenticatable | ||
5 | t.string :login, null: false, default: "" | ||
6 | t.string :email, null: false, default: "" | ||
7 | t.string :encrypted_password, null: false, default: "" | ||
8 | |||
9 | ## Recoverable | ||
10 | t.string :reset_password_token | ||
11 | t.datetime :reset_password_sent_at | ||
12 | |||
13 | ## Rememberable | ||
14 | t.datetime :remember_created_at | ||
15 | |||
16 | ## Trackable | ||
17 | t.integer :sign_in_count, default: 0, null: false | ||
18 | t.datetime :current_sign_in_at | ||
19 | t.datetime :last_sign_in_at | ||
20 | t.string :current_sign_in_ip | ||
21 | t.string :last_sign_in_ip | ||
22 | |||
23 | ## Confirmable | ||
24 | # t.string :confirmation_token | ||
25 | # t.datetime :confirmed_at | ||
26 | # t.datetime :confirmation_sent_at | ||
27 | # t.string :unconfirmed_email # Only if using reconfirmable | ||
28 | |||
29 | ## Lockable | ||
30 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts | ||
31 | # t.string :unlock_token # Only if unlock strategy is :email or :both | ||
32 | # t.datetime :locked_at | ||
33 | |||
34 | |||
35 | t.timestamps null: false | ||
36 | end | ||
37 | |||
38 | add_index :users, :login, unique: true | ||
39 | add_index :users, :email, unique: true | ||
40 | add_index :users, :reset_password_token, unique: true | ||
41 | # add_index :users, :confirmation_token, unique: true | ||
42 | # add_index :users, :unlock_token, unique: true | ||
43 | end | ||
44 | end | ||
diff --git a/db/schema.rb b/db/schema.rb index 6eca6ad..b690393 100644 --- a/db/schema.rb +++ b/db/schema.rb | |||
@@ -10,7 +10,7 @@ | |||
10 | # | 10 | # |
11 | # It's strongly recommended that you check this file into your version control system. | 11 | # It's strongly recommended that you check this file into your version control system. |
12 | 12 | ||
13 | ActiveRecord::Schema.define(version: 20170625004938) do | 13 | ActiveRecord::Schema.define(version: 20170625151955) do |
14 | 14 | ||
15 | create_table "entries", force: :cascade do |t| | 15 | create_table "entries", force: :cascade do |t| |
16 | t.string "title" | 16 | t.string "title" |
@@ -31,4 +31,23 @@ ActiveRecord::Schema.define(version: 20170625004938) do | |||
31 | t.index ["recordable_type", "recordable_id"], name: "index_records_on_recordable_type_and_recordable_id" | 31 | t.index ["recordable_type", "recordable_id"], name: "index_records_on_recordable_type_and_recordable_id" |
32 | end | 32 | end |
33 | 33 | ||
34 | create_table "users", force: :cascade do |t| | ||
35 | t.string "login", default: "", null: false | ||
36 | t.string "email", default: "", null: false | ||
37 | t.string "encrypted_password", default: "", null: false | ||
38 | t.string "reset_password_token" | ||
39 | t.datetime "reset_password_sent_at" | ||
40 | t.datetime "remember_created_at" | ||
41 | t.integer "sign_in_count", default: 0, null: false | ||
42 | t.datetime "current_sign_in_at" | ||
43 | t.datetime "last_sign_in_at" | ||
44 | t.string "current_sign_in_ip" | ||
45 | t.string "last_sign_in_ip" | ||
46 | t.datetime "created_at", null: false | ||
47 | t.datetime "updated_at", null: false | ||
48 | t.index ["email"], name: "index_users_on_email", unique: true | ||
49 | t.index ["login"], name: "index_users_on_login", unique: true | ||
50 | t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true | ||
51 | end | ||
52 | |||
34 | end | 53 | end |
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..80aed36 --- /dev/null +++ b/test/fixtures/users.yml | |||
@@ -0,0 +1,11 @@ | |||
1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html | ||
2 | |||
3 | # This model initially had no columns defined. If you add columns to the | ||
4 | # model remove the '{}' from the fixture names and add the columns immediately | ||
5 | # below each fixture, per the syntax in the comments below | ||
6 | # | ||
7 | one: {} | ||
8 | # column: value | ||
9 | # | ||
10 | two: {} | ||
11 | # column: value | ||
diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000..82f61e0 --- /dev/null +++ b/test/models/user_test.rb | |||
@@ -0,0 +1,7 @@ | |||
1 | require 'test_helper' | ||
2 | |||
3 | class UserTest < ActiveSupport::TestCase | ||
4 | # test "the truth" do | ||
5 | # assert true | ||
6 | # end | ||
7 | end | ||