added authentication via devise

This commit is contained in:
danielvincent 2010-06-12 21:56:50 -07:00
parent 8ecaf240e6
commit eaeafd3240
26 changed files with 322 additions and 373 deletions

View file

@ -32,3 +32,5 @@ gem "mocha"
gem 'rspec-rails', ">= 2.0.0.beta.8"
# gem 'webrat'
#end
gem "devise", :git => "git://github.com/plataformatec/devise.git"

View file

@ -1,2 +0,0 @@
class UserSessionsController < ApplicationController
end

View file

@ -1,19 +1,9 @@
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
@users = User.all
end
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = "Successfully created user."
redirect_to users_url
else
render :action => 'new'
end
end
end

View file

@ -1,11 +1,9 @@
class User
include Mongoid::Document
field :password
field :name
validates :password, :presence => true
validates :name, :presence =>true
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end

View file

@ -1,8 +0,0 @@
class UserSession
include Mongoid::Document
def authenticates(name, password)
user = User.first(:conditions => {:name => name, :password => password})
self.save unless user.nil?
end
end

View file

@ -0,0 +1,9 @@
%h2 Resend confirmation instructions
= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name)) do |f|
= devise_error_messages!
%p
= f.label :email
%br/
= f.text_field :email
%p= f.submit "Resend confirmation instructions"
= render :partial => "devise/shared/links"

View file

@ -0,0 +1,4 @@
%p
Welcome #{@resource.email}!
%p You can confirm your account through the link below:
%p= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)

View file

@ -0,0 +1,6 @@
%p
Hello #{@resource.email}!
%p Someone has requested a link to change your password, and you can do this through the link below.
%p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_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.

View file

@ -0,0 +1,5 @@
%p
Hello #{@resource.email}!
%p Your account has been locked due to an excessive amount 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 => @resource.unlock_token)

View file

@ -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
%p
= f.label :password
%br/
= f.password_field :password
%p
= f.label :password_confirmation
%br/
= f.password_field :password_confirmation
%p= f.submit "Change my password"
= render :partial => "devise/shared/links"

View file

@ -0,0 +1,9 @@
%h2 Forgot your password?
= form_for(resource, :as => resource_name, :url => password_path(resource_name)) do |f|
= devise_error_messages!
%p
= f.label :email
%br/
= f.text_field :email
%p= f.submit "Send me reset password instructions"
= render :partial => "devise/shared/links"

View file

@ -0,0 +1,27 @@
%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!
%p
= f.label :email
%br/
= f.text_field :email
%p
= f.label :password
%i (leave blank if you don't want to change it)
%br/
= f.password_field :password
%p
= f.label :password_confirmation
%br/
= f.password_field :password_confirmation
%p
= f.label :current_password
%i (we need your current password to confirm your changes)
%br/
= f.password_field :current_password
%p= f.submit "Update"
%h3 Cancel my account
%p
Unhappy? #{link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete}.
= link_to "Back", :back

View file

@ -0,0 +1,17 @@
%h2 Sign up
= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
= devise_error_messages!
%p
= f.label :email
%br/
= f.text_field :email
%p
= f.label :password
%br/
= f.password_field :password
%p
= f.label :password_confirmation
%br/
= f.password_field :password_confirmation
%p= f.submit "Sign up"
= render :partial => "devise/shared/links"

View file

@ -0,0 +1,16 @@
%h2 Sign in
= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
%p
= f.label :email
%br/
= f.text_field :email
%p
= f.label :password
%br/
= f.password_field :password
- if devise_mapping.rememberable?
%p
= f.check_box :remember_me
= f.label :remember_me
%p= f.submit "Sign in"
= render :partial => "devise/shared/links"

View file

@ -0,0 +1,15 @@
- 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'
= 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/

View file

@ -0,0 +1,9 @@
%h2 Resend unlock instructions
= form_for(resource, :as => resource_name, :url => unlock_path(resource_name)) do |f|
= devise_error_messages!
%p
= f.label :email
%br/
= f.text_field :email
%p= f.submit "Resend unlock instructions"
= render :partial => "devise/shared/links"

View file

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Diaspora</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
</head>
<body>
<%= yield %>
</body>
</html>

View file

@ -12,6 +12,11 @@
%body
#container
- if user_signed_in?
= link_to "log out", destroy_user_session_path
- else
= link_to "login", new_user_session_path
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_#{name}"

View file

@ -0,0 +1,131 @@
# Use this hook to configure devise mailer, warden hooks and so forth. The first
# four configuration values can also be set straight in your models.
Devise.setup do |config|
# Configure the e-mail address which will be shown in DeviseMailer.
config.mailer_sender = "please-change-me@config-initializers-devise.com"
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default), :mongoid
# (bson_ext recommended) and :data_mapper (experimental).
require 'devise/orm/mongoid'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating an user. By default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating an user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# config.authentication_keys = [ :email ]
# Tell if authentication through request.params is enabled. True by default.
# config.params_authenticatable = true
# Tell if authentication through HTTP Basic Auth is enabled. True by default.
# config.http_authenticatable = true
# The realm used in Http Basic Authentication
# config.http_authentication_realm = "Application"
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
# using other encryptors, it sets how many times you want the password re-encrypted.
config.stretches = 10
# Define which will be the encryption algorithm. Devise also supports encryptors
# from others authentication tools as :clearance_sha1, :authlogic_sha512 (then
# you should set stretches above to 20 for default behavior) and :restful_authentication_sha1
# (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
config.encryptor = :bcrypt
# Setup a pepper to generate the encrypted password.
config.pepper = "065eb8798b181ff0ea2c5c16aee0ff8b70e04e2ee6bd6e08b49da46924223e39127d5335e466207d42bf2a045c12be5f90e92012a4f05f7fc6d9f3c875f4c95b"
# ==> Configuration for :confirmable
# The time you want to give your user to confirm his account. During this time
# he will be able to access your application without confirming. Default is nil.
# When confirm_within is zero, the user won't be able to sign in without confirming.
# You can use this to let your user access some features of your application
# without confirming the account, but blocking it after a certain period
# (ie 2 days).
# config.confirm_within = 2.days
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# ==> Configuration for :validatable
# Range for password length
# config.password_length = 6..20
# Regex to use to validate the email address
# config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again.
# config.timeout_in = 10.minutes
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# ==> Configuration for :token_authenticatable
# Defines name of the authentication token params key
# config.token_authentication_key = :auth_token
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "sessions/users/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = true
# By default, devise detects the role accessed based on the url. So whenever
# accessing "/users/sign_in", it knows you are accessing an User. This makes
# routes as "/sign_in" not possible, unless you tell Devise to use the default
# scope, setting true below.
# Note that devise does not generate default routes. You also have to
# specify them in config/routes.rb
# config.use_default_scope = true
# Configure the default scope used by Devise. By default it's the first devise
# role declared in your routes.
# config.default_scope = :user
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists. Default is [:html]
# config.navigational_formats = [:html, :iphone]
# ==> Warden configuration
# If you want to use other strategies, that are not (yet) supported by Devise,
# you can configure them inside the config.warden block. The example below
# allows you to setup OAuth, using http://github.com/roman/warden_oauth
#
# config.warden do |manager|
# manager.oauth(:twitter) do |twitter|
# twitter.consumer_secret = <YOUR CONSUMER SECRET>
# twitter.consumer_key = <YOUR CONSUMER KEY>
# twitter.options :site => 'http://twitter.com'
# end
# manager.default_strategies(:scope => :user).unshift :twitter_oauth
# end
end

View file

@ -0,0 +1,36 @@
en:
errors:
messages:
not_found: "not found"
already_confirmed: "was already confirmed"
not_locked: "was not locked"
devise:
failure:
unauthenticated: 'You need to sign in or sign up before continuing.'
unconfirmed: 'You have to confirm your account before continuing.'
locked: 'Your account is locked.'
invalid: 'Invalid email or password.'
invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.'
sessions:
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
updated: 'Your password was changed successfully. You are now signed in.'
confirmations:
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
confirmed: 'Your account was successfully confirmed. You are now signed in.'
registrations:
signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.'
updated: 'You updated your account successfully.'
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account was successfully unlocked. You are now signed in.'
mailer:
confirmation_instructions: 'Confirmation instructions'
reset_password_instructions: 'Reset password instructions'
unlock_instructions: 'Unlock Instructions'

View file

@ -1,4 +1,6 @@
Diaspora::Application.routes.draw do |map|
devise_for :users
resources :users
# The priority is based upon order of creation:
@ -57,4 +59,7 @@ Diaspora::Application.routes.draw do |map|
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
# match ':controller(/:action(/:id(.:format)))'
root :to => "users#index"
end

View file

@ -1,279 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails: Welcome aboard</title>
<style type="text/css" media="screen">
body {
margin: 0;
margin-bottom: 25px;
padding: 0;
background-color: #f0f0f0;
font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
font-size: 13px;
color: #333;
}
h1 {
font-size: 28px;
color: #000;
}
a {color: #03c}
a:hover {
background-color: #03c;
color: white;
text-decoration: none;
}
#page {
background-color: #f0f0f0;
width: 750px;
margin: 0;
margin-left: auto;
margin-right: auto;
}
#content {
float: left;
background-color: white;
border: 3px solid #aaa;
border-top: none;
padding: 25px;
width: 500px;
}
#sidebar {
float: right;
width: 175px;
}
#footer {
clear: both;
}
#header, #about, #getting-started {
padding-left: 75px;
padding-right: 30px;
}
#header {
background-image: url("images/rails.png");
background-repeat: no-repeat;
background-position: top left;
height: 64px;
}
#header h1, #header h2 {margin: 0}
#header h2 {
color: #888;
font-weight: normal;
font-size: 16px;
}
#about h3 {
margin: 0;
margin-bottom: 10px;
font-size: 14px;
}
#about-content {
background-color: #ffd;
border: 1px solid #fc0;
margin-left: -55px;
margin-right: -10px;
}
#about-content table {
margin-top: 10px;
margin-bottom: 10px;
font-size: 11px;
border-collapse: collapse;
}
#about-content td {
padding: 10px;
padding-top: 3px;
padding-bottom: 3px;
}
#about-content td.name {color: #555}
#about-content td.value {color: #000}
#about-content ul {
padding: 0;
list-style-type: none;
}
#about-content.failure {
background-color: #fcc;
border: 1px solid #f00;
}
#about-content.failure p {
margin: 0;
padding: 10px;
}
#getting-started {
border-top: 1px solid #ccc;
margin-top: 25px;
padding-top: 15px;
}
#getting-started h1 {
margin: 0;
font-size: 20px;
}
#getting-started h2 {
margin: 0;
font-size: 14px;
font-weight: normal;
color: #333;
margin-bottom: 25px;
}
#getting-started ol {
margin-left: 0;
padding-left: 0;
}
#getting-started li {
font-size: 18px;
color: #888;
margin-bottom: 25px;
}
#getting-started li h2 {
margin: 0;
font-weight: normal;
font-size: 18px;
color: #333;
}
#getting-started li p {
color: #555;
font-size: 13px;
}
#search {
margin: 0;
padding-top: 10px;
padding-bottom: 10px;
font-size: 11px;
}
#search input {
font-size: 11px;
margin: 2px;
}
#search-text {width: 170px}
#sidebar ul {
margin-left: 0;
padding-left: 0;
}
#sidebar ul h3 {
margin-top: 25px;
font-size: 16px;
padding-bottom: 10px;
border-bottom: 1px solid #ccc;
}
#sidebar li {
list-style-type: none;
}
#sidebar ul.links li {
margin-bottom: 5px;
}
</style>
<script type="text/javascript">
function about() {
info = document.getElementById('about-content');
if (window.XMLHttpRequest)
{ xhr = new XMLHttpRequest(); }
else
{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
xhr.open("GET","rails/info/properties",false);
xhr.send("");
info.innerHTML = xhr.responseText;
info.style.display = 'block'
}
function prepend() {
search = document.getElementById('search-text');
text = search.value;
search.value = 'site:rubyonrails.org ' + text;
}
window.onload = function() {
document.getElementById('search-text').value = '';
}
</script>
</head>
<body>
<div id="page">
<div id="sidebar">
<ul id="sidebar-items">
<li>
<form id="search" action="http://www.google.com/search" method="get" onSubmit="prepend();">
<input type="hidden" name="hl" value="en" />
<input type="text" id="search-text" name="q" value="site:rubyonrails.org " />
<input type="submit" value="Search" /> the Rails site
</form>
</li>
<li>
<h3>Join the community</h3>
<ul class="links">
<li><a href="http://www.rubyonrails.org/">Ruby on Rails</a></li>
<li><a href="http://weblog.rubyonrails.org/">Official weblog</a></li>
<li><a href="http://wiki.rubyonrails.org/">Wiki</a></li>
</ul>
</li>
<li>
<h3>Browse the documentation</h3>
<ul class="links">
<li><a href="http://api.rubyonrails.org/">Rails API</a></li>
<li><a href="http://stdlib.rubyonrails.org/">Ruby standard library</a></li>
<li><a href="http://corelib.rubyonrails.org/">Ruby core</a></li>
<li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
</ul>
</li>
</ul>
</div>
<div id="content">
<div id="header">
<h1>Welcome aboard</h1>
<h2>You&rsquo;re riding Ruby on Rails!</h2>
</div>
<div id="about">
<h3><a href="rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
<div id="about-content" style="display: none"></div>
</div>
<div id="getting-started">
<h1>Getting started</h1>
<h2>Here&rsquo;s how to get rolling:</h2>
<ol>
<li>
<h2>Use <code>rails generate</code> to create your models and controllers</h2>
<p>To see all available options, run it without parameters.</p>
</li>
<li>
<h2>Set up a default route and remove or rename this file</h2>
<p>Routes are set up in config/routes.rb.</p>
</li>
<li>
<h2>Create your database</h2>
<p>Run <code>rake db:migrate</code> to create your database. If you're not using SQLite (the default), edit <code>config/database.yml</code> with your username and password.</p>
</li>
</ol>
</div>
</div>
<div id="footer">&nbsp;</div>
</div>
</body>
</html>

View file

@ -1,17 +0,0 @@
class UserSessionsController < ApplicationController
def new
@user_sessions = UserSession.new
end
def create
@user_sessions = UserSession.new(params[:username, :password])
if @user_sessions.save
params[:user_logged_in] = params[:username]
flash[:notice] = "Successfully logged in."
redirect_to root_url
else
render :action => 'new'
end
end
end

View file

@ -1,19 +0,0 @@
require 'spec_helper'
describe UserSession do
before do
UserSession.delete_all
User.delete_all
end
it "should authenticate an existing user" do
user = User.create(:name => "billy", :password => "bob")
puts User.first.inspect
UserSession.new.authenticates(user.name, user.password).should be true
end
it "should not authenticate a foreign user" do
user = User.create(:name => "billy", :password => "bob")
UserSession.new.authenticates("not billy", "not bob").should be nil
end
end

4
spec/models/user_spec.rb Normal file
View file

@ -0,0 +1,4 @@
require 'spec_helper'
describe User do
end

View file

@ -1,14 +0,0 @@
require 'spec_helper'
describe User do
before do
User.delete_all
end
it 'should should have a valid name and password' do
pending "snow leopard issue with validation"
User.create
User.count.should == 0
end
end