From 68f39cf5d67ba0480c4cc2c7d5e17477f82fddc6 Mon Sep 17 00:00:00 2001 From: echarp Date: Fri, 10 Jan 2014 16:35:58 +0100 Subject: [PATCH] L'authentification avec devise et un hash basique est en place --- app/assets/stylesheets/events.css.sass | 2 +- app/assets/stylesheets/list.css.sass | 2 +- app/assets/stylesheets/sessions.css.sass | 43 +++++++++++++++++++ app/controllers/events_controller.rb | 6 +-- app/controllers/moderations_controller.rb | 1 + app/controllers/users_controller.rb | 2 +- app/models/event.rb | 1 - app/models/user.rb | 33 ++++++++++++++ app/views/devise/confirmations/new.html.haml | 9 ++++ .../confirmation_instructions.html.haml | 4 ++ .../reset_password_instructions.html.haml | 6 +++ .../mailer/unlock_instructions.html.haml | 5 +++ app/views/devise/passwords/edit.html.haml | 14 ++++++ app/views/devise/passwords/new.html.haml | 9 ++++ app/views/devise/registrations/edit.html.haml | 30 +++++++++++++ app/views/devise/registrations/new.html.haml | 17 ++++++++ app/views/devise/sessions/new.html.haml | 19 ++++++++ app/views/devise/shared/_links.haml | 19 ++++++++ app/views/devise/unlocks/new.html.haml | 9 ++++ app/views/events/_form.html.haml | 4 +- app/views/events/new.html.haml | 2 +- app/views/moderations/index.html.haml | 2 + config/locales/fr.yml | 12 +++++- config/routes.rb | 1 + test/controllers/users_controller_test.rb | 15 ++++++- test/fixtures/users.yml | 9 ++-- test/models/user_test.rb | 23 +++++++++- 27 files changed, 278 insertions(+), 21 deletions(-) create mode 100644 app/assets/stylesheets/sessions.css.sass create mode 100644 app/views/devise/confirmations/new.html.haml create mode 100644 app/views/devise/mailer/confirmation_instructions.html.haml create mode 100644 app/views/devise/mailer/reset_password_instructions.html.haml create mode 100644 app/views/devise/mailer/unlock_instructions.html.haml create mode 100644 app/views/devise/passwords/edit.html.haml create mode 100644 app/views/devise/passwords/new.html.haml create mode 100644 app/views/devise/registrations/edit.html.haml 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.haml create mode 100644 app/views/devise/unlocks/new.html.haml diff --git a/app/assets/stylesheets/events.css.sass b/app/assets/stylesheets/events.css.sass index f3cb4ce9..41b853d2 100644 --- a/app/assets/stylesheets/events.css.sass +++ b/app/assets/stylesheets/events.css.sass @@ -145,7 +145,7 @@ table.calendar a color: #8F4900 -form +.events form .field, .actions text-align: left margin-left: 2px diff --git a/app/assets/stylesheets/list.css.sass b/app/assets/stylesheets/list.css.sass index b4371dcb..2aee74e5 100644 --- a/app/assets/stylesheets/list.css.sass +++ b/app/assets/stylesheets/list.css.sass @@ -23,7 +23,7 @@ table.list font-weight: normal text-decoration: none &:hover - text-shadow: 0px 0px 16px black + @include text-shadow(2px 2px 1px lightblue) &:before padding: 0.5em font-size: 20px diff --git a/app/assets/stylesheets/sessions.css.sass b/app/assets/stylesheets/sessions.css.sass new file mode 100644 index 00000000..a31209a6 --- /dev/null +++ b/app/assets/stylesheets/sessions.css.sass @@ -0,0 +1,43 @@ +@import "compass" + +.sessions + form + margin: 1em auto + display: inline-block + .field, .actions + text-align: left + margin-left: 2px + margin-bottom: 2px !important + * + vertical-align: middle + p.helper + margin: 1px 5px 1px 6.6em + line-height: 0.9em + label + width: 8em + display: inline-block + text-align: right + &:after + content: ':' + input, textarea, select + color: black + margin: 3px 0 + border: 1px solid #868686 + padding: 0.2em 0.8em + font-size: larger + font-family: georgia, serif + background-color: #FFB + @include border-radius(0.8em) + &:focus + background-color: #F0F8FF !important + input[type=submit] + border: none + font-size: x-large + @include box-shadow(0 0 1em lightblue) + @include text-shadow(1px 1px 1px white) + .actions + margin-left: 6.75em + margin-bottom: 10px + + .logout + margin: 2em auto diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 479997ed..85bf7cd6 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -36,8 +36,8 @@ class EventsController < InheritedResources::Base # This is a special case, required to handle the region attribute with same foreign key name @event.region = Region.find(params[:event][:region]) - if (params[:visu]) - render action: 'new' + if params[:visu] + render action: :new return end @@ -57,7 +57,7 @@ class EventsController < InheritedResources::Base def update if params[:visu] @event.attributes = params[:event] - render action: 'edit' + render action: :edit return end diff --git a/app/controllers/moderations_controller.rb b/app/controllers/moderations_controller.rb index b7019065..f0fbd8ea 100644 --- a/app/controllers/moderations_controller.rb +++ b/app/controllers/moderations_controller.rb @@ -1,4 +1,5 @@ class ModerationsController < InheritedResources::Base + before_filter :authenticate_user! before_action :set_event, only: [:show, :edit, :update, :destroy] def index diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a73b6df5..81c2e74c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -69,6 +69,6 @@ class UsersController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def user_params - params.require(:user).permit(:login, :email, :lastname, :firstname) + params.require(:user).permit(:login, :email, :lastname, :firstname, :password) end end diff --git a/app/models/event.rb b/app/models/event.rb index 51d0ae80..e0422193 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -29,7 +29,6 @@ class Event < ActiveRecord::Base self.decision_time = Date.today end - def same_day? start_time.to_date == end_time.to_date end diff --git a/app/models/user.rb b/app/models/user.rb index e77bf44b..d1e25b2c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,36 @@ +require 'digest/md5' + class User < ActiveRecord::Base + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable and :omniauthable + devise :database_authenticatable, authentication_keys: [:login] + #, :registerable, :validatable + has_many :notes + + def encrypted_password=(pass) + write_attribute :password, pass + end + + def encrypted_password + read_attribute :password + end + + def self.find_first_by_auth_conditions(warden_conditions) + conditions = warden_conditions.dup + if login = conditions.delete(:login) + where(conditions).where(["login = :value", { value: login }]).first + else + where(conditions).first + end + end + + def valid_password?(password) + encrypted_password == password_digest(password) + end + + protected + def password_digest(password) + Digest::MD5.hexdigest password + end end diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml new file mode 100644 index 00000000..88c63737 --- /dev/null +++ b/app/views/devise/confirmations/new.html.haml @@ -0,0 +1,9 @@ +%h2 Resend confirmation instructions += form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| + = devise_error_messages! + %div + = f.label :email + %br/ + = f.email_field :email, :autofocus => true + %div= f.submit "Resend confirmation instructions" += render "devise/shared/links" diff --git a/app/views/devise/mailer/confirmation_instructions.html.haml b/app/views/devise/mailer/confirmation_instructions.html.haml new file mode 100644 index 00000000..dfa5989a --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.haml @@ -0,0 +1,4 @@ +%p + Welcome #{@email}! +%p You can confirm your account email through the link below: +%p= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) diff --git a/app/views/devise/mailer/reset_password_instructions.html.haml b/app/views/devise/mailer/reset_password_instructions.html.haml new file mode 100644 index 00000000..eda27ee3 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.haml @@ -0,0 +1,6 @@ +%p + Hello #{@resource.email}! +%p Someone has requested a link to change your password. You can do this through the link below. +%p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) +%p If you didn't request this, please ignore this email. +%p 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.haml b/app/views/devise/mailer/unlock_instructions.html.haml new file mode 100644 index 00000000..47f55a54 --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.haml @@ -0,0 +1,5 @@ +%p + Hello #{@resource.email}! +%p Your account has been locked due to an excessive number of unsuccessful sign in attempts. +%p Click the link below to unlock your account: +%p= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @token) diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml new file mode 100644 index 00000000..85156881 --- /dev/null +++ b/app/views/devise/passwords/edit.html.haml @@ -0,0 +1,14 @@ +%h2 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 + %div + = f.label :password, "New password" + %br/ + = f.password_field :password, :autofocus => true + %div + = f.label :password_confirmation, "Confirm new password" + %br/ + = f.password_field :password_confirmation + %div= f.submit "Change my password" += render "devise/shared/links" diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml new file mode 100644 index 00000000..591033be --- /dev/null +++ b/app/views/devise/passwords/new.html.haml @@ -0,0 +1,9 @@ +%h2 Forgot your password? += form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| + = devise_error_messages! + %div + = f.label :email + %br/ + = f.email_field :email, :autofocus => true + %div= f.submit "Send me reset password instructions" += render "devise/shared/links" diff --git a/app/views/devise/registrations/edit.html.haml b/app/views/devise/registrations/edit.html.haml new file mode 100644 index 00000000..74491142 --- /dev/null +++ b/app/views/devise/registrations/edit.html.haml @@ -0,0 +1,30 @@ +%h2 + 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! + %div + = f.label :email + %br/ + = f.email_field :email, :autofocus => true + - if devise_mapping.confirmable? && resource.pending_reconfirmation? + %div + Currently waiting confirmation for: #{resource.unconfirmed_email} + %div + = f.label :password + %i (leave blank if you don't want to change it) + %br/ + = f.password_field :password, :autocomplete => "off" + %div + = f.label :password_confirmation + %br/ + = f.password_field :password_confirmation + %div + = f.label :current_password + %i (we need your current password to confirm your changes) + %br/ + = f.password_field :current_password + %div= f.submit "Update" +%h3 Cancel my account +%p + 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..521431c0 --- /dev/null +++ b/app/views/devise/registrations/new.html.haml @@ -0,0 +1,17 @@ +%h2 Sign up += form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| + = devise_error_messages! + %div + = f.label :email + %br/ + = f.email_field :email, :autofocus => true + %div + = f.label :password + %br/ + = f.password_field :password + %div + = f.label :password_confirmation + %br/ + = f.password_field :password_confirmation + %div= 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..d78e429d --- /dev/null +++ b/app/views/devise/sessions/new.html.haml @@ -0,0 +1,19 @@ +%h2=t '.title' + += form_for resource, as: resource_name, url: session_path(resource_name) do |f| + %div.field + = f.label :login + = f.text_field :login, autofocus: true + + %div.field + = f.label :password + = f.password_field :password + + - if devise_mapping.rememberable? + %div + = f.check_box :remember_me + = f.label :remember_me + + %div= f.submit t('.sign_in') + += render "devise/shared/links" diff --git a/app/views/devise/shared/_links.haml b/app/views/devise/shared/_links.haml new file mode 100644 index 00000000..f763fdcf --- /dev/null +++ b/app/views/devise/shared/_links.haml @@ -0,0 +1,19 @@ +- if controller_name != 'sessions' + = link_to "Sign in", new_session_path(resource_name) + %br/ +- if devise_mapping.registerable? && controller_name != 'registrations' + = link_to "Sign up", new_registration_path(resource_name) + %br/ +- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' + = link_to "Forgot your password?", new_password_path(resource_name) + %br/ +- if devise_mapping.confirmable? && controller_name != 'confirmations' + = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) + %br/ +- 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) + %br/ +- 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) + %br/ diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml new file mode 100644 index 00000000..d3c87d07 --- /dev/null +++ b/app/views/devise/unlocks/new.html.haml @@ -0,0 +1,9 @@ +%h2 Resend unlock instructions += form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| + = devise_error_messages! + %div + = f.label :email + %br/ + = f.email_field :email, :autofocus => true + %div= f.submit "Resend unlock instructions" += render "devise/shared/links" diff --git a/app/views/events/_form.html.haml b/app/views/events/_form.html.haml index f2732e6f..2ccfac43 100644 --- a/app/views/events/_form.html.haml +++ b/app/views/events/_form.html.haml @@ -1,4 +1,4 @@ -= form_for @event, url: moderation_path(@event) do |f| += form_for @event do |f| - if @event.errors.any? #error_explanation %h2= "#{pluralize(@event.errors.count, "error")} prohibited this event from being saved:" @@ -62,7 +62,7 @@ .field = f.label Event.human_attribute_name :region = f.select :region, - options_from_collection_for_select(Region.all, 'id', 'name', @event.region.id) + options_from_collection_for_select(Region.all, 'id', 'name', @event.region && @event.region.id) .field = f.label Event.human_attribute_name :locality = f.select :locality, diff --git a/app/views/events/new.html.haml b/app/views/events/new.html.haml index d257aa04..cddabdea 100644 --- a/app/views/events/new.html.haml +++ b/app/views/events/new.html.haml @@ -2,7 +2,7 @@ - if @event && params[:visu] %hr/ - = render file: 'show' + = render file: '/events/show' %hr/ = render 'form' diff --git a/app/views/moderations/index.html.haml b/app/views/moderations/index.html.haml index 61915bbe..16c7c6da 100644 --- a/app/views/moderations/index.html.haml +++ b/app/views/moderations/index.html.haml @@ -47,3 +47,5 @@ =t '.posted_by', author: "#{note.author.firstname} #{note.author.lastname}", date: l(note.date, format: :at) + +.logout= link_to t('logout'), destroy_user_session_path, method: :delete diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f07bfc93..41a40637 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -4,6 +4,7 @@ fr: validate: Valider refuse: Refuser destroy: Supprimer + logout: Se déconnecter attributes: id: ID @@ -26,7 +27,7 @@ fr: lug: Gull attributes: user: - login: Identifiant + login: Login password: Mot de passe lastname: Nom firstname: Prénom @@ -145,3 +146,12 @@ fr: moderation: Modération preview: Prévisualisation de l'évènement edit: Édition de l'évènement + users: + sign_in: + title: Identification + + devise: + sessions: + new: + title: Identification + sign_in: Identifier diff --git a/config/routes.rb b/config/routes.rb index 24cfa2df..0efdbdd1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,6 +11,7 @@ AgendaDuLibreRails::Application.routes.draw do get 'ical.php' => 'events#index', format: :ics get ':format.php' => 'events#index' + devise_for :users, path: '', path_names: {sign_in: 'login', sign_out: 'logout'} devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index df87e4f2..540bcf85 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -18,7 +18,13 @@ class UsersControllerTest < ActionController::TestCase test "should create user" do assert_difference('User.count') do - post :create, user: { email: @user.email, firstname: @user.firstname, lastname: @user.lastname, login: @user.login } + post :create, user: { + email: 'original@example.com', + firstname: @user.firstname, + lastname: @user.lastname, + login: @user.login, + password: 'abcdefghijklmnopqrstuvwxyz' + } end assert_redirected_to user_path(assigns(:user)) @@ -35,7 +41,12 @@ class UsersControllerTest < ActionController::TestCase end test "should update user" do - patch :update, id: @user, user: { email: @user.email, firstname: @user.firstname, lastname: @user.lastname, login: @user.login } + patch :update, id: @user, user: { + email: @user.email, + firstname: @user.firstname, + lastname: @user.lastname, + login: @user.login + } assert_redirected_to user_path(assigns(:user)) end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 0bf1b515..17627694 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,10 +1,7 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below - one: email: one@example.com + firstname: first + lastname: last + login: aNiceLogin two: email: two@example.com diff --git a/test/models/user_test.rb b/test/models/user_test.rb index cec65f21..3b9c137b 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -1,7 +1,26 @@ require 'test_helper' class UserTest < ActiveSupport::TestCase - test "the truth" do - assert true + test "basic user" do + @user = User.new( + email: 'original@example.com', + firstname: 'first', + lastname: 'last', + login: 'login', + password: 'abcdefghijklmnopqrstuvwxyz' + ) + assert_not_nil @user + assert_equal 'c3fcd3d76192e4007dfb496cca67e13b', @user.encrypted_password + end + + test "the password" do + @user = User.new( + email: 'original@example.com', + firstname: 'first', + lastname: 'last', + login: 'login', + password: 'abcdefghijklmnopqrstuvwxyz' + ) + assert @user.valid_password? 'abcdefghijklmnopqrstuvwxyz' end end