From 7641726677014d6bb2722cb3f5cbc6326629b3a1 Mon Sep 17 00:00:00 2001 From: nilsding Date: Fri, 1 Aug 2014 15:27:08 +0200 Subject: [PATCH] added authentication and everything --- Gemfile | 1 + Gemfile.lock | 2 ++ app/assets/javascripts/application.coffee | 1 + app/assets/stylesheets/application.css.scss | 4 +++ app/controllers/application_controller.rb | 10 ++++++ app/helpers/application_helper.rb | 16 ++++++++++ app/models/user.rb | 26 +++++++++++++++- app/views/devise/confirmations/new.html.erb | 12 +++++++ .../mailer/confirmation_instructions.html.erb | 5 +++ .../reset_password_instructions.html.erb | 8 +++++ .../mailer/unlock_instructions.html.erb | 7 +++++ app/views/devise/passwords/edit.html.erb | 16 ++++++++++ app/views/devise/passwords/new.html.erb | 12 +++++++ app/views/devise/registrations/edit.html.erb | 31 +++++++++++++++++++ app/views/devise/registrations/new.html.haml | 15 +++++++++ app/views/devise/sessions/new.html.haml | 15 +++++++++ app/views/devise/shared/_links.erb | 25 +++++++++++++++ app/views/devise/unlocks/new.html.erb | 12 +++++++ app/views/layouts/_header.html.haml | 26 ++++++++++++++++ app/views/layouts/_messages.html.haml | 6 ++++ app/views/layouts/application.html.haml | 17 ++++------ app/views/static/about.html.haml | 2 ++ app/views/static/index.html.haml | 2 ++ config/initializers/devise.rb | 6 ++-- config/locales/devise.en.yml | 4 +-- ...20140801103309_add_screen_name_to_users.rb | 6 ++++ db/schema.rb | 4 ++- 27 files changed, 273 insertions(+), 18 deletions(-) create mode 100644 app/views/devise/confirmations/new.html.erb create mode 100644 app/views/devise/mailer/confirmation_instructions.html.erb create mode 100644 app/views/devise/mailer/reset_password_instructions.html.erb create mode 100644 app/views/devise/mailer/unlock_instructions.html.erb create mode 100644 app/views/devise/passwords/edit.html.erb create mode 100644 app/views/devise/passwords/new.html.erb create mode 100644 app/views/devise/registrations/edit.html.erb create mode 100644 app/views/devise/registrations/new.html.haml create mode 100644 app/views/devise/sessions/new.html.haml create mode 100644 app/views/devise/shared/_links.erb create mode 100644 app/views/devise/unlocks/new.html.erb create mode 100644 app/views/layouts/_header.html.haml create mode 100644 app/views/layouts/_messages.html.haml create mode 100644 db/migrate/20140801103309_add_screen_name_to_users.rb diff --git a/Gemfile b/Gemfile index 347f3e93..a25e45a0 100644 --- a/Gemfile +++ b/Gemfile @@ -46,3 +46,4 @@ gem 'will_paginate' gem 'will_paginate-bootstrap' gem 'http_accept_language' gem 'devise' +gem 'bootstrap_form' diff --git a/Gemfile.lock b/Gemfile.lock index d408c931..bca0cc26 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,6 +31,7 @@ GEM bcrypt (3.1.7) bootstrap-sass (3.2.0.1) sass (~> 3.2) + bootstrap_form (2.1.1) bootswatch-rails (3.2.0) railties (>= 3.1) builder (3.2.2) @@ -140,6 +141,7 @@ PLATFORMS DEPENDENCIES bootstrap-sass (~> 3.2.0.1) + bootstrap_form bootswatch-rails (~> 3.2.0) coffee-rails (~> 4.0.0) devise diff --git a/app/assets/javascripts/application.coffee b/app/assets/javascripts/application.coffee index a37af364..4294d310 100644 --- a/app/assets/javascripts/application.coffee +++ b/app/assets/javascripts/application.coffee @@ -1,4 +1,5 @@ #= require jquery #= require jquery_ujs #= require turbolinks +#= require bootstrap #= require_tree . diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 0aceec67..87984a7f 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -1,3 +1,7 @@ +/* + *= require rails_bootstrap_forms + *= require_self + */ @import "bootswatch/flatly/variables"; @import "bootstrap"; body { padding-top: $navbar-height; } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e1..fbe8b9d1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,14 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + before_filter :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:screen_name, :email, :password, :password_confirmation, :remember_me) } + devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :screen_name, :email, :password, :remember_me) } + devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:screen_name, :email, :password, :password_confirmation, :current_password) } + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be794..0f01df3d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,18 @@ module ApplicationHelper + def nav_entry(body, path) + content_tag(:li, link_to(body, path), class: ('active' if current_page? path)) + end + + ## + # + def bootstrap_color c + case c + when "error", "alert" + "danger" + when "notice" + "info" + else + c + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index c8220270..6ed77699 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,5 +2,29 @@ class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :trackable, + :validatable, :authentication_keys => [:login] + +# attr_accessor :login + + SCREEN_NAME_REGEX = /\A[a-zA-Z0-9_]{1,16}\z/ + + validates :screen_name, presence: true, format: { with: SCREEN_NAME_REGEX }, uniqueness: { case_sensitive: false } + + def login=(login) + @login = login + end + + def login + @login || self.screen_name || self.email + end + + def self.find_first_by_auth_conditions(warden_conditions) + conditions = warden_conditions.dup + if login = conditions.delete(:login) + where(conditions).where(["lower(screen_name) = :value OR lower(email) = :value", { :value => login.downcase }]).first + else + where(conditions).first + end + end end diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 00000000..434fe000 --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb @@ -0,0 +1,12 @@ +

Resend confirmation instructions

+ +<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :screen_name %>
+ <%= f.email_field :screen_name, autofocus: true %>
+ +
<%= f.submit "Resend confirmation instructions" %>
+<% end %> + +<%= 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 00000000..39b47121 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.erb @@ -0,0 +1,5 @@ +

Welcome <%= @screen_name %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

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 00000000..f667dc12 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +

Hello <%= @resource.email %>!

+ +

Someone has requested a link to change your password. You can do this through the link below.

+ +

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

+ +

If you didn't request this, please ignore this email.

+

Your password won't change until you access the link above and create a new one.

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 00000000..41e148bf --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @resource.email %>!

+ +

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

+ +

Click the link below to unlock your account:

+ +

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 00000000..55350988 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,16 @@ +

Change your password

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> + <%= devise_error_messages! %> + <%= f.hidden_field :reset_password_token %> + +
<%= f.label :password, "New password" %>
+ <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
+ +
<%= f.label :password_confirmation, "Confirm new password" %>
+ <%= f.password_field :password_confirmation, autocomplete: "off" %>
+ +
<%= f.submit "Change my password" %>
+<% end %> + +<%= 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 00000000..208e7a40 --- /dev/null +++ b/app/views/devise/passwords/new.html.erb @@ -0,0 +1,12 @@ +

Forgot your password?

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :screen_name %>
+ <%= f.email_field :screen_name, autofocus: true %>
+ +
<%= f.submit "Send me reset password instructions" %>
+<% end %> + +<%= 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 00000000..c6356a0e --- /dev/null +++ b/app/views/devise/registrations/edit.html.erb @@ -0,0 +1,31 @@ +

Edit <%= resource_name.to_s.humanize %>

+ +<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :screen_name %>
+ <%= f.email_field :screen_name, autofocus: true %>
+
<%= f.label :email %>
+ <%= f.email_field :email %>
+ + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %> + +
<%= f.label :password %> (leave blank if you don't want to change it)
+ <%= f.password_field :password, autocomplete: "off" %>
+ +
<%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation, autocomplete: "off" %>
+ +
<%= f.label :current_password %> (we need your current password to confirm your changes)
+ <%= f.password_field :current_password, autocomplete: "off" %>
+ +
<%= f.submit "Update" %>
+<% end %> + +

Cancel my account

+ +

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

+ +<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml new file mode 100644 index 00000000..80d46542 --- /dev/null +++ b/app/views/devise/registrations/new.html.haml @@ -0,0 +1,15 @@ +.container + %h1 Sign up + + = bootstrap_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| + = devise_error_messages! + + = f.text_field :screen_name, autofocus: true, label: "User name" + = f.email_field :email, autofocus: false, label: "Email address" + + = f.password_field :password, autocomplete: "off", label: "Password" + = f.password_field :password_confirmation, autocomplete: "off", label: "Confirm password" + + = f.submit "Sign up" + + = render "devise/shared/links" diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml new file mode 100644 index 00000000..a9721102 --- /dev/null +++ b/app/views/devise/sessions/new.html.haml @@ -0,0 +1,15 @@ +.container + %h1 Sign in + = render 'layouts/messages' + + = bootstrap_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| + + = f.text_field :login, autofocus: true, label: "User name" + = f.password_field :password, autocomplete: "off", label: "Password" + + - if devise_mapping.rememberable? + = f.check_box :remember_me + + = f.submit "Sign in" + + = render "devise/shared/links" \ No newline at end of file diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb new file mode 100644 index 00000000..d84bdde9 --- /dev/null +++ b/app/views/devise/shared/_links.erb @@ -0,0 +1,25 @@ +<%- if controller_name != 'sessions' %> + <%= link_to "Sign in", new_session_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to "Sign up", new_registration_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> + <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
+ <% end -%> +<% end -%> diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb new file mode 100644 index 00000000..6fb5612b --- /dev/null +++ b/app/views/devise/unlocks/new.html.erb @@ -0,0 +1,12 @@ +

Resend unlock instructions

+ +<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email, autofocus: true %>
+ +
<%= f.submit "Resend unlock instructions" %>
+<% end %> + +<%= render "devise/shared/links" %> diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml new file mode 100644 index 00000000..a2b69dea --- /dev/null +++ b/app/views/layouts/_header.html.haml @@ -0,0 +1,26 @@ +%nav.navbar.navbar-default.navbar-fixed-top{role: "navigation"} + .container + .navbar-header + %button.navbar-toggle{"data-target" => "#j2-main-navbar-collapse", "data-toggle" => "collapse", type: "button"} + %span.sr-only Toggle navigation + %span.icon-bar + %span.icon-bar + %span.icon-bar + %a.navbar-brand{href: "/"} justask2 + #j2-main-navbar-collapse.collapse.navbar-collapse + %ul.nav.navbar-nav + = nav_entry "Front", "/" + %ul.nav.navbar-nav.navbar-right + - if user_signed_in? + %li.dropdown + %a.dropdown-toggle{href: "#", "data-toggle" => "dropdown"} + thsdfjhkl + %b.caret + %ul.dropdown-menu + %li= link_to "Profile", edit_user_registration_path + %li= link_to "Settings", "#" + %li.divider + %li= link_to "Logout", destroy_user_session_path, method: :delete + - else + = nav_entry "Sign in", new_user_session_path + = nav_entry "Sign up", new_user_registration_path \ No newline at end of file diff --git a/app/views/layouts/_messages.html.haml b/app/views/layouts/_messages.html.haml new file mode 100644 index 00000000..b52216eb --- /dev/null +++ b/app/views/layouts/_messages.html.haml @@ -0,0 +1,6 @@ +- flash.each do |key, value| + .alert.alert-dismissible{class: "alert-#{bootstrap_color key}", role: "alert"} + %button.close{type: "button", "data-dismiss" => "alert"} + %span{"aria-hidden" => "true"} × + %span.sr-only Close + = value \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index b8afab45..11b2cb74 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -6,15 +6,10 @@ = javascript_include_tag 'application', 'data-turbolinks-track' => true = csrf_meta_tags %body - %nav.navbar.navbar-default.navbar-fixed-top{role: "navigation"} + = render 'layouts/header' + = yield + - if Rails.env.development? + %hr .container - .navbar-header - %button.navbar-toggle{"data-target" => "#j2-main-navbar-collapse", "data-toggle" => "collapse", type: "button"} - %span.sr-only Toggle navigation - %span.icon-bar - %span.icon-bar - %span.icon-bar - %a.navbar-brand{href: "/"} justask2 - #j2-main-navbar-collapse.collapse.navbar-collapse - %ul.nav.navbar-nav - = yield \ No newline at end of file + %p.text-danger EVIL DEBUG MODE OF DOOM ENABLED!!! + = debug params \ No newline at end of file diff --git a/app/views/static/about.html.haml b/app/views/static/about.html.haml index b04b359f..c9442551 100644 --- a/app/views/static/about.html.haml +++ b/app/views/static/about.html.haml @@ -1,3 +1,5 @@ .container %h1 Static#about + = render 'layouts/messages' + %p Find me in app/views/static/about.html.haml diff --git a/app/views/static/index.html.haml b/app/views/static/index.html.haml index 0193b40e..96e7563f 100644 --- a/app/views/static/index.html.haml +++ b/app/views/static/index.html.haml @@ -1,3 +1,5 @@ .container %h1 Static#index + = render 'layouts/messages' + %p Find me in app/views/static/index.html.haml \ No newline at end of file diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 882818f7..25c01509 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -29,7 +29,7 @@ Devise.setup do |config| # session. If you need permissions, you should implement that in a before filter. # You can also supply a hash where the value is a boolean determining whether # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [ :email ] + config.authentication_keys = [ :login ] # Configure parameters from the request object used for authentication. Each entry # given should be a request method and it will automatically be passed to the @@ -122,7 +122,7 @@ Devise.setup do |config| config.reconfirmable = true # Defines which key will be used when confirming an account - # config.confirmation_keys = [ :email ] + config.confirmation_keys = [ :screen_name ] # ==> Configuration for :rememberable # The time the user will be remembered without asking for credentials again. @@ -181,7 +181,7 @@ Devise.setup do |config| # ==> Configuration for :recoverable # # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [ :email ] + config.reset_password_keys = [ :screen_name ] # Time interval you can reset your password with a reset password key. # Don't put a too small interval or your users won't have the time to diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index abccdb08..3afc05cd 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -9,10 +9,10 @@ en: failure: already_authenticated: "You are already signed in." inactive: "Your account is not activated yet." - invalid: "Invalid email or password." + invalid: "Invalid user name or password." locked: "Your account is locked." last_attempt: "You have one more attempt before your account will be locked." - not_found_in_database: "Invalid email or password." + not_found_in_database: "Invalid user name or password." timeout: "Your session expired. Please sign in again to continue." unauthenticated: "You need to sign in or sign up before continuing." unconfirmed: "You have to confirm your account before continuing." diff --git a/db/migrate/20140801103309_add_screen_name_to_users.rb b/db/migrate/20140801103309_add_screen_name_to_users.rb new file mode 100644 index 00000000..dc4acf9a --- /dev/null +++ b/db/migrate/20140801103309_add_screen_name_to_users.rb @@ -0,0 +1,6 @@ +class AddScreenNameToUsers < ActiveRecord::Migration + def change + add_column :users, :screen_name, :string + add_index :users, :screen_name, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 80fd3caa..99ba3dda 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140801095807) do +ActiveRecord::Schema.define(version: 20140801103309) do create_table "users", force: true do |t| t.string "email", default: "", null: false @@ -26,9 +26,11 @@ ActiveRecord::Schema.define(version: 20140801095807) do t.string "last_sign_in_ip" t.datetime "created_at" t.datetime "updated_at" + t.string "screen_name" end add_index "users", ["email"], name: "index_users_on_email", unique: true add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + add_index "users", ["screen_name"], name: "index_users_on_screen_name", unique: true end