summaryrefslogtreecommitdiff
path: root/lib/generators/nifty/authentication
diff options
context:
space:
mode:
Diffstat (limited to 'lib/generators/nifty/authentication')
-rw-r--r--lib/generators/nifty/authentication/USAGE50
-rw-r--r--lib/generators/nifty/authentication/authentication_generator.rb154
-rw-r--r--lib/generators/nifty/authentication/templates/authlogic_session.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/controller_authentication.rb60
-rw-r--r--lib/generators/nifty/authentication/templates/fixtures.yml24
-rw-r--r--lib/generators/nifty/authentication/templates/migration.rb20
-rw-r--r--lib/generators/nifty/authentication/templates/sessions_controller.rb41
-rw-r--r--lib/generators/nifty/authentication/templates/sessions_helper.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb39
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/user.rb83
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb56
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb40
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/user.rb85
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb61
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb36
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/user.rb88
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb53
-rw-r--r--lib/generators/nifty/authentication/templates/user.rb38
-rw-r--r--lib/generators/nifty/authentication/templates/users_controller.rb32
-rw-r--r--lib/generators/nifty/authentication/templates/users_helper.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/_form.html.erb20
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/edit.html.erb3
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/login.html.erb30
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/signup.html.erb5
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/_form.html.haml16
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/edit.html.haml3
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/login.html.haml26
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/signup.html.haml5
28 files changed, 1074 insertions, 0 deletions
diff --git a/lib/generators/nifty/authentication/USAGE b/lib/generators/nifty/authentication/USAGE
new file mode 100644
index 0000000..89f0a64
--- /dev/null
+++ b/lib/generators/nifty/authentication/USAGE
@@ -0,0 +1,50 @@
+Description:
+ Generates a user model, users controller, and sessions controller. The
+ users controller handles the registration and the sessions controller
+ handles authentication. This is similar to restful_authentication, but
+ simpler.
+
+ IMPORTANT: This generator uses the "title" helper method which is generated
+ by the nifty_layout generator. You may want to run that generator first.
+
+Usage:
+ If you do not pass any arguments, the model name will default to "user", and
+ the authentication controller will default to "session". You can override
+ each of these respectively by passing one or two arguments. Either name can
+ be CamelCased or under_scored.
+
+ Make sure to setup the authlogic gem if you are using that option.
+
+ gem "authlogic" # in Gemfile
+
+Examples:
+ rails generate nifty:authentication
+
+ Creates user model, users_controller, and sessions_controller.
+
+ rails generate nifty:authentication account
+
+ Creates account model, accounts_controller, and sessions_controller.
+
+ rails generate nifty:authentication Account UserSession
+
+ Creates account model, accounts_controller, and user_sessions_controller.
+
+Methods:
+ There are several methods generated which you can use in your application.
+ Here's a common example of what you might add to your layout.
+
+ <% if logged_in? %>
+ Welcome <%= current_user.username %>! Not you?
+ <%= link_to "Log out", logout_path %>
+ <% else %>
+ <%= link_to "Sign up", signup_path %> or
+ <%= link_to "log in", login_path %>.
+ <% end %>
+
+ You can also restrict unregistered users from accessing a controller using
+ a before filter. For example.
+
+ before_filter :login_required, :except => [:index, :show]
+
+ See the generated file lib/authentication.rb for details. \ No newline at end of file
diff --git a/lib/generators/nifty/authentication/authentication_generator.rb b/lib/generators/nifty/authentication/authentication_generator.rb
new file mode 100644
index 0000000..d4dcbde
--- /dev/null
+++ b/lib/generators/nifty/authentication/authentication_generator.rb
@@ -0,0 +1,154 @@
+require 'generators/nifty'
+require 'rails/generators/migration'
+
+module Nifty
+ module Generators
+ class AuthenticationGenerator < Base
+ include Rails::Generators::Migration
+
+ argument :user_name, :type => :string, :default => 'user', :banner => 'user_name'
+ argument :session_name, :type => :string, :default => '[[DEFAULT]]', :banner => 'sessions_controller_name'
+
+ class_option :testunit, :desc => 'Use test/unit for test files.', :group => 'Test framework', :type => :boolean
+ class_option :rspec, :desc => 'Use RSpec for test files.', :group => 'Test framework', :type => :boolean
+ class_option :shoulda, :desc => 'Use shoulda for test files.', :group => 'Test framework', :type => :boolean
+
+ class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean
+ class_option :authlogic, :desc => 'Use Authlogic for authentication.', :type => :boolean
+
+ def add_gems
+ add_gem "bcrypt-ruby", :require => "bcrypt"
+ add_gem "mocha", :group => :test
+ end
+
+ def create_model_files
+ template 'user.rb', "app/models/#{user_singular_name}.rb"
+ template 'authlogic_session.rb', "app/models/#{user_singular_name}_session.rb" if options.authlogic?
+ end
+
+ def create_controller_files
+ template 'users_controller.rb', "app/controllers/#{user_plural_name}_controller.rb"
+ template 'sessions_controller.rb', "app/controllers/#{session_plural_name}_controller.rb"
+ end
+
+ def create_helper_files
+ template 'users_helper.rb', "app/helpers/#{user_plural_name}_helper.rb"
+ template 'sessions_helper.rb', "app/helpers/#{session_plural_name}_helper.rb"
+ end
+
+ def create_view_files
+ template "views/#{view_language}/signup.html.#{view_language}", "app/views/#{user_plural_name}/new.html.#{view_language}"
+ template "views/#{view_language}/edit.html.#{view_language}", "app/views/#{user_plural_name}/edit.html.#{view_language}"
+ template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{user_plural_name}/_form.html.#{view_language}"
+ template "views/#{view_language}/login.html.#{view_language}", "app/views/#{session_plural_name}/new.html.#{view_language}"
+ end
+
+ def create_lib_files
+ template 'controller_authentication.rb', 'lib/controller_authentication.rb'
+ end
+
+ def create_routes
+ route "resources #{user_plural_name.to_sym.inspect}"
+ route "resources #{session_plural_name.to_sym.inspect}"
+ route "match 'login' => '#{session_plural_name}#new', :as => :login"
+ route "match 'logout' => '#{session_plural_name}#destroy', :as => :logout"
+ route "match 'signup' => '#{user_plural_name}#new', :as => :signup"
+ route "match '#{user_singular_name}/edit' => '#{user_plural_name}#edit', :as => :edit_current_#{user_singular_name}"
+ end
+
+ def create_migration
+ migration_template 'migration.rb', "db/migrate/create_#{user_plural_name}.rb"
+ end
+
+ def load_and_include_authentication
+ inject_into_class "config/application.rb", "Application", " config.autoload_paths << \"\#{config.root}/lib\""
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " include ControllerAuthentication\n"
+ end
+
+ def create_test_files
+ if test_framework == :rspec
+ template 'fixtures.yml', "spec/fixtures/#{user_plural_name}.yml"
+ template 'tests/rspec/user.rb', "spec/models/#{user_singular_name}_spec.rb"
+ template 'tests/rspec/users_controller.rb', "spec/controllers/#{user_plural_name}_controller_spec.rb"
+ template 'tests/rspec/sessions_controller.rb', "spec/controllers/#{session_plural_name}_controller_spec.rb"
+ else
+ template 'fixtures.yml', "test/fixtures/#{user_plural_name}.yml"
+ template "tests/#{test_framework}/user.rb", "test/unit/#{user_singular_name}_test.rb"
+ template "tests/#{test_framework}/users_controller.rb", "test/functional/#{user_plural_name}_controller_test.rb"
+ template "tests/#{test_framework}/sessions_controller.rb", "test/functional/#{session_plural_name}_controller_test.rb"
+ end
+ end
+
+ private
+
+ def session_name
+ @_session_name ||= @session_name == '[[DEFAULT]]' ?
+ (options.authlogic? ? user_name + '_session' : 'session') :
+ @session_name
+ end
+
+ def user_singular_name
+ user_name.underscore
+ end
+
+ def user_plural_name
+ user_singular_name.pluralize
+ end
+
+ def user_class_name
+ user_name.camelize
+ end
+
+ def user_plural_class_name
+ user_plural_name.camelize
+ end
+
+ def session_singular_name
+ session_name.underscore
+ end
+
+ def session_plural_name
+ session_singular_name.pluralize
+ end
+
+ def session_class_name
+ session_name.camelize
+ end
+
+ def session_plural_class_name
+ session_plural_name.camelize
+ end
+
+ def view_language
+ options.haml? ? 'haml' : 'erb'
+ end
+
+ def test_framework
+ return @test_framework if defined?(@test_framework)
+ if options.testunit?
+ return @test_framework = :testunit
+ elsif options.rspec?
+ return @test_framework = :rspec
+ elsif options.shoulda?
+ return @test_framework = :shoulda
+ else
+ return @test_framework = File.exist?(destination_path('spec')) ? :rspec : :testunit
+ end
+ end
+
+ def destination_path(path)
+ File.join(destination_root, path)
+ end
+
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
+ # Implement the required interface for Rails::Generators::Migration.
+ def self.next_migration_number(dirname) #:nodoc:
+ if ActiveRecord::Base.timestamped_migrations
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
+ else
+ "%.3d" % (current_migration_number(dirname) + 1)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/authlogic_session.rb b/lib/generators/nifty/authentication/templates/authlogic_session.rb
new file mode 100644
index 0000000..676cfd0
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/authlogic_session.rb
@@ -0,0 +1,2 @@
+class <%= session_class_name %> < Authlogic::Session::Base
+end
diff --git a/lib/generators/nifty/authentication/templates/controller_authentication.rb b/lib/generators/nifty/authentication/templates/controller_authentication.rb
new file mode 100644
index 0000000..6d34ab0
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/controller_authentication.rb
@@ -0,0 +1,60 @@
+# This module is included in your application controller which makes
+# several methods available to all controllers and views. Here's a
+# common example you might add to your application layout file.
+#
+# <%% if logged_in? %>
+# Welcome <%%= current_<%= user_singular_name %>.username %>.
+# <%%= link_to "Edit profile", edit_current_<%= user_singular_name %>_path %> or
+# <%%= link_to "Log out", logout_path %>
+# <%% else %>
+# <%%= link_to "Sign up", signup_path %> or
+# <%%= link_to "log in", login_path %>.
+# <%% end %>
+#
+# You can also restrict unregistered users from accessing a controller using
+# a before filter. For example.
+#
+# before_filter :login_required, :except => [:index, :show]
+module ControllerAuthentication
+ def self.included(controller)
+ controller.send :helper_method, :current_<%= user_singular_name %>, :logged_in?, :redirect_to_target_or_default
+ end
+
+<%- if options[:authlogic] -%>
+ def current_<%= session_singular_name %>
+ return @current_<%= session_singular_name %> if defined?(@current_<%= session_singular_name %>)
+ @current_<%= session_singular_name %> = <%= session_class_name %>.find
+ end
+
+ def current_<%= user_singular_name %>
+ return @current_<%= user_singular_name %> if defined?(@current_<%= user_singular_name %>)
+ @current_<%= user_singular_name %> = current_<%= session_singular_name %> && current_<%= session_singular_name %>.record
+ end
+<%- else -%>
+ def current_<%= user_singular_name %>
+ @current_<%= user_singular_name %> ||= <%= user_class_name %>.find(session[:<%= user_singular_name %>_id]) if session[:<%= user_singular_name %>_id]
+ end
+<%- end -%>
+
+ def logged_in?
+ current_<%= user_singular_name %>
+ end
+
+ def login_required
+ unless logged_in?
+ store_target_location
+ redirect_to login_url, :alert => "You must first log in or sign up before accessing this page."
+ end
+ end
+
+ def redirect_to_target_or_default(default, *args)
+ redirect_to(session[:return_to] || default, *args)
+ session[:return_to] = nil
+ end
+
+ private
+
+ def store_target_location
+ session[:return_to] = request.url
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/fixtures.yml b/lib/generators/nifty/authentication/templates/fixtures.yml
new file mode 100644
index 0000000..c52532b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/fixtures.yml
@@ -0,0 +1,24 @@
+# password: "secret"
+foo:
+ username: foo
+ email: foo@example.com
+<%- if options[:authlogic] -%>
+ persistence_token: d5ddba13ed4408ea2b0a12ab18ed2d2eda086279736bdc121ca726a11f1e4b99217d9c534c2cc4ebb22729349c8c5fdbe1529e1f2c3c5859c62ef4dd9feea25c
+ crypted_password: 3d16c326648cccafe3d4b4cb024475c381dda92f430dfedf6f933e1f61203bacb6bae2437849bdb43b06be335e23790e4aa03902b3c28c3bbbbe27d501e521f3
+ password_salt: n6z_wtpWoIsHgQb5IcFd
+<%- else -%>
+ password_hash: 3488f5f7efecab14b91eb96169e5e1ee518a569f
+ password_salt: bef65e058905c379436d80d1a32e7374b139e7b0
+<%- end -%>
+
+bar:
+ username: bar
+ email: bar@example.com
+<%- if options[:authlogic] -%>
+ persistence_token: 19e074bd7cb506ab3e7e53e41f24f0ab3221c8cb68111f4c1aa43965114ad734233979a50a9463537487cdca18c279ac91c4bc83693d589625d446493322394c
+ crypted_password: 3bc9f4113ca645a186765df3d31a9352d0067bf2304ba0cdd6b08a7f3d58c6668ab1762fa3e76aef466ea2ff188399d8e6c40244fa59312bb4112292dac9f7f0
+ password_salt: UiAh9ejabnKRxqsiK0xO
+<%- else -%>
+ password_hash: 3488f5f7efecab14b91eb96169e5e1ee518a569f
+ password_salt: bef65e058905c379436d80d1a32e7374b139e7b0
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/migration.rb b/lib/generators/nifty/authentication/templates/migration.rb
new file mode 100644
index 0000000..c945df3
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/migration.rb
@@ -0,0 +1,20 @@
+class Create<%= user_plural_class_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= user_plural_name %> do |t|
+ t.string :username
+ t.string :email
+ <%- if options[:authlogic] -%>
+ t.string :persistence_token
+ t.string :crypted_password
+ <%- else -%>
+ t.string :password_hash
+ <%- end -%>
+ t.string :password_salt
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :<%= user_plural_name %>
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/sessions_controller.rb b/lib/generators/nifty/authentication/templates/sessions_controller.rb
new file mode 100644
index 0000000..65e77c1
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/sessions_controller.rb
@@ -0,0 +1,41 @@
+class <%= session_plural_class_name %>Controller < ApplicationController
+<%- if options[:authlogic] -%>
+ def new
+ @<%= session_singular_name %> = <%= session_class_name %>.new
+ end
+
+ def create
+ @<%= session_singular_name %> = <%= session_class_name %>.new(params[:<%= session_singular_name %>])
+ if @<%= session_singular_name %>.save
+ redirect_to_target_or_default root_url, :notice => "Logged in successfully."
+ else
+ render :new
+ end
+ end
+
+ def destroy
+ @<%= session_singular_name %> = <%= session_class_name %>.find
+ @<%= session_singular_name %>.destroy
+ redirect_to root_url, :notice => "You have been logged out."
+ end
+<%- else -%>
+ def new
+ end
+
+ def create
+ <%= user_singular_name %> = <%= user_class_name %>.authenticate(params[:login], params[:password])
+ if <%= user_singular_name %>
+ session[:<%= user_singular_name %>_id] = <%= user_singular_name %>.id
+ redirect_to_target_or_default root_url, :notice => "Logged in successfully."
+ else
+ flash.now[:alert] = "Invalid login or password."
+ render :new
+ end
+ end
+
+ def destroy
+ session[:<%= user_singular_name %>_id] = nil
+ redirect_to root_url, :notice => "You have been logged out."
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/sessions_helper.rb b/lib/generators/nifty/authentication/templates/sessions_helper.rb
new file mode 100644
index 0000000..0958537
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/sessions_helper.rb
@@ -0,0 +1,2 @@
+module <%= session_plural_class_name %>Helper
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb
new file mode 100644
index 0000000..e0953cc
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb
@@ -0,0 +1,39 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= session_plural_class_name %>Controller do
+ fixtures :all
+ render_views
+
+ it "new action should render new template" do
+ get :new
+ response.should render_template(:new)
+ end
+
+<%- if options[:authlogic] -%>
+ it "create action should render new template when authentication is invalid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ response.should render_template(:new)
+ <%= session_class_name %>.find.should be_nil
+ end
+
+ it "create action should redirect when authentication is valid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ response.should redirect_to(root_url)
+ <%= session_class_name %>.find.<%= user_singular_name %>.should == <%= user_plural_name %>(:foo)
+ end
+<%- else -%>
+ it "create action should render new template when authentication is invalid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ response.should render_template(:new)
+ session['<%= user_singular_name %>_id'].should be_nil
+ end
+
+ it "create action should redirect when authentication is valid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ response.should redirect_to(root_url)
+ session['<%= user_singular_name %>_id'].should == <%= user_class_name %>.first.id
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/user.rb b/lib/generators/nifty/authentication/templates/tests/rspec/user.rb
new file mode 100644
index 0000000..a3f7e92
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/user.rb
@@ -0,0 +1,83 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= user_class_name %> do
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_class_name %>.new(attributes)
+ end
+
+ before(:each) do
+ <%= user_class_name %>.delete_all
+ end
+
+ it "should be valid" do
+ new_<%= user_singular_name %>.should be_valid
+ end
+
+ it "should require username" do
+ new_<%= user_singular_name %>(:username => '').should have(1).error_on(:username)
+ end
+
+ it "should require password" do
+ new_<%= user_singular_name %>(:password => '').should have(1).error_on(:password)
+ end
+
+ it "should require well formed email" do
+ new_<%= user_singular_name %>(:email => 'foo@bar@example.com').should have(1).error_on(:email)
+ end
+
+ it "should validate uniqueness of email" do
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ new_<%= user_singular_name %>(:email => 'bar@example.com').should have(1).error_on(:email)
+ end
+
+ it "should validate uniqueness of username" do
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ new_<%= user_singular_name %>(:username => 'uniquename').should have(1).error_on(:username)
+ end
+
+ it "should not allow odd characters in username" do
+ new_<%= user_singular_name %>(:username => 'odd ^&(@)').should have(1).error_on(:username)
+ end
+
+ it "should validate password is longer than 3 characters" do
+ new_<%= user_singular_name %>(:password => 'bad').should have(1).error_on(:password)
+ end
+
+ it "should require matching password confirmation" do
+ new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').should have(1).error_on(:password)
+ end
+
+ it "should generate password hash and salt on create" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ <%= user_singular_name %>.password_hash.should_not be_nil
+ <%= user_singular_name %>.password_salt.should_not be_nil
+ end
+
+ it "should authenticate by username" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ <%= user_class_name %>.authenticate('foobar', 'secret').should == <%= user_singular_name %>
+ end
+
+ it "should authenticate by email" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ <%= user_class_name %>.authenticate('foo@bar.com', 'secret').should == <%= user_singular_name %>
+ end
+
+ it "should not authenticate bad username" do
+ <%= user_class_name %>.authenticate('nonexisting', 'secret').should be_nil
+ end
+
+ it "should not authenticate bad password" do
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ <%= user_class_name %>.authenticate('foobar', 'badpassword').should be_nil
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb
new file mode 100644
index 0000000..60bcff9
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb
@@ -0,0 +1,56 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= user_plural_class_name %>Controller do
+ fixtures :all
+ render_views
+
+ it "new action should render new template" do
+ get :new
+ response.should render_template(:new)
+ end
+
+ it "create action should render new template when model is invalid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ response.should render_template(:new)
+ end
+
+ it "create action should redirect when model is valid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ response.should redirect_to(root_url)
+ <%- unless options[:authlogic] -%>
+ session['<%= user_singular_name %>_id'].should == assigns['<%= user_singular_name %>'].id
+ <%- end -%>
+ end
+
+ it "edit action should redirect when not logged in" do
+ get :edit, :id => "ignored"
+ response.should redirect_to(login_url)
+ end
+
+ it "edit action should render edit template" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ response.should render_template(:edit)
+ end
+
+ it "update action should redirect when not logged in" do
+ put :update, :id => "ignored"
+ response.should redirect_to(login_url)
+ end
+
+ it "update action should render edit template when <%= user_singular_name %> is invalid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ response.should render_template(:edit)
+ end
+
+ it "update action should redirect when <%= user_singular_name %> is valid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ response.should redirect_to(root_url)
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb
new file mode 100644
index 0000000..e2f9005
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb
@@ -0,0 +1,40 @@
+require 'test_helper'
+
+class <%= session_plural_class_name %>ControllerTest < ActionController::TestCase
+ context "new action" do
+ should "render new template" do
+ get :new
+ assert_template 'new'
+ end
+ end
+
+ context "create action" do
+ <%- if options[:authlogic] -%>
+ should "render new template when authentication is invalid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ assert_template 'new'
+ assert_nil <%= session_class_name %>.find
+ end
+
+ should "redirect when authentication is valid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ assert_redirected_to root_url
+ assert_equal <%= user_plural_name %>(:foo), <%= session_class_name %>.find.<%= user_singular_name %>
+ end
+ <%- else -%>
+ should "render new template when authentication is invalid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ assert_template 'new'
+ assert_nil session['<%= user_singular_name %>_id']
+ end
+
+ should "redirect when authentication is valid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ assert_redirected_to root_url
+ assert_equal <%= user_class_name %>.first.id, session['<%= user_singular_name %>_id']
+ end
+ <%- end -%>
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb
new file mode 100644
index 0000000..beb8bf4
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb
@@ -0,0 +1,85 @@
+require 'test_helper'
+
+class <%= user_class_name %>Test < ActiveSupport::TestCase
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_singular_name %> = <%= user_class_name %>.new(attributes)
+ <%= user_singular_name %>.valid? # run validations
+ <%= user_singular_name %>
+ end
+
+ def setup
+ <%= user_class_name %>.delete_all
+ end
+
+ should "be valid" do
+ assert new_<%= user_singular_name %>.valid?
+ end
+
+ should "require username" do
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:username => '').errors[:username]
+ end
+
+ should "require password" do
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:password => '').errors[:password]
+ end
+
+ should "require well formed email" do
+ assert_equal ["is invalid"], new_<%= user_singular_name %>(:email => 'foo@bar@example.com').errors[:email]
+ end
+
+ should "validate uniqueness of email" do
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:email => 'bar@example.com').errors[:email]
+ end
+
+ should "validate uniqueness of username" do
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:username => 'uniquename').errors[:username]
+ end
+
+ should "not allow odd characters in username" do
+ assert_equal ["should only contain letters, numbers, or .-_@"], new_<%= user_singular_name %>(:username => 'odd ^&(@)').errors[:username]
+ end
+
+ should "validate password is longer than 3 characters" do
+ assert_equal ["is too short (minimum is 4 characters)"], new_<%= user_singular_name %>(:password => 'bad').errors[:password]
+ end
+
+ should "require matching password confirmation" do
+ assert_equal ["doesn't match confirmation"], new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').errors[:password]
+ end
+
+ should "generate password hash and salt on create" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ assert <%= user_singular_name %>.password_hash
+ assert <%= user_singular_name %>.password_salt
+ end
+
+ should "authenticate by username" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foobar', 'secret')
+ end
+
+ should "authenticate by email" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foo@bar.com', 'secret')
+ end
+
+ should "not authenticate bad username" do
+ assert_nil <%= user_class_name %>.authenticate('nonexisting', 'secret')
+ end
+
+ should "not authenticate bad password" do
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ assert_nil <%= user_class_name %>.authenticate('foobar', 'badpassword')
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb
new file mode 100644
index 0000000..1728329
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb
@@ -0,0 +1,61 @@
+require 'test_helper'
+
+class <%= user_plural_class_name %>ControllerTest < ActionController::TestCase
+ context "new action" do
+ should "render new template" do
+ get :new
+ assert_template 'new'
+ end
+ end
+
+ context "create action" do
+ should "render new template when <%= user_singular_name %> is invalid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ should "redirect when <%= user_singular_name %> is valid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to root_url
+ <%- unless options[:authlogic] -%>
+ assert_equal assigns['<%= user_singular_name %>'].id, session['<%= user_singular_name %>_id']
+ <%- end -%>
+ end
+ end
+
+ context "edit action" do
+ should "redirect when not logged in" do
+ get :edit, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ should "render edit template" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ assert_template 'edit'
+ end
+ end
+
+ context "update action" do
+ should "redirect when not logged in" do
+ put :update, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ should "render edit template when <%= user_singular_name %> is invalid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ should "redirect when <%= user_singular_name %> is valid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ assert_redirected_to root_url
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb
new file mode 100644
index 0000000..fe2a65b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb
@@ -0,0 +1,36 @@
+require 'test_helper'
+
+class <%= session_plural_class_name %>ControllerTest < ActionController::TestCase
+ def test_new
+ get :new
+ assert_template 'new'
+ end
+
+<%- if options[:authlogic] -%>
+ def test_create_invalid
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ assert_template 'new'
+ assert_nil <%= session_class_name %>.find
+ end
+
+ def test_create_valid
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ assert_redirected_to root_url
+ assert_equal <%= user_plural_name %>(:foo), <%= session_class_name %>.find.<%= user_singular_name %>
+ end
+<%- else -%>
+ def test_create_invalid
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ assert_template 'new'
+ assert_nil session['<%= user_singular_name %>_id']
+ end
+
+ def test_create_valid
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ assert_redirected_to root_url
+ assert_equal <%= user_class_name %>.first.id, session['<%= user_singular_name %>_id']
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/user.rb b/lib/generators/nifty/authentication/templates/tests/testunit/user.rb
new file mode 100644
index 0000000..c036cf1
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/user.rb
@@ -0,0 +1,88 @@
+require 'test_helper'
+
+class <%= user_class_name %>Test < ActiveSupport::TestCase
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_singular_name %> = <%= user_class_name %>.new(attributes)
+ <%= user_singular_name %>.valid? # run validations
+ <%= user_singular_name %>
+ end
+
+ def setup
+ <%= user_class_name %>.delete_all
+ end
+
+ def test_valid
+ assert new_<%= user_singular_name %>.valid?
+ end
+
+ def test_require_username
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:username => '').errors[:username]
+ end
+
+ def test_require_password
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:password => '').errors[:password]
+ end
+
+ def test_require_well_formed_email
+ assert_equal ["is invalid"], new_<%= user_singular_name %>(:email => 'foo@bar@example.com').errors[:email]
+ end
+
+ def test_validate_uniqueness_of_email
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:email => 'bar@example.com').errors[:email]
+ end
+
+ def test_validate_uniqueness_of_username
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:username => 'uniquename').errors[:username]
+ end
+
+ def test_validate_odd_characters_in_username
+ assert_equal ["should only contain letters, numbers, or .-_@"], new_<%= user_singular_name %>(:username => 'odd ^&(@)').errors[:username]
+ end
+
+ def test_validate_password_length
+ assert_equal ["is too short (minimum is 4 characters)"], new_<%= user_singular_name %>(:password => 'bad').errors[:password]
+ end
+
+ def test_require_matching_password_confirmation
+ assert_equal ["doesn't match confirmation"], new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').errors[:password]
+ end
+
+ def test_generate_password_hash_and_salt_on_create
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ assert <%= user_singular_name %>.password_hash
+ assert <%= user_singular_name %>.password_salt
+ end
+
+ def test_authenticate_by_username
+ <%= user_class_name %>.delete_all
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foobar', 'secret')
+ end
+
+ def test_authenticate_by_email
+ <%= user_class_name %>.delete_all
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foo@bar.com', 'secret')
+ end
+
+ def test_authenticate_bad_username
+ assert_nil <%= user_class_name %>.authenticate('nonexisting', 'secret')
+ end
+
+ def test_authenticate_bad_password
+ <%= user_class_name %>.delete_all
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ assert_nil <%= user_class_name %>.authenticate('foobar', 'badpassword')
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb
new file mode 100644
index 0000000..ef8a3f7
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb
@@ -0,0 +1,53 @@
+require 'test_helper'
+
+class <%= user_plural_class_name %>ControllerTest < ActionController::TestCase
+ def test_new
+ get :new
+ assert_template 'new'
+ end
+
+ def test_create_invalid
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ def test_create_valid
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to root_url
+ <%- unless options[:authlogic] -%>
+ assert_equal assigns['<%= user_singular_name %>'].id, session['<%= user_singular_name %>_id']
+ <%- end -%>
+ end
+
+ def test_edit_without_user
+ get :edit, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ def test_edit
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ def test_update_without_user
+ put :update, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ def test_update_invalid
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ def test_update_valid
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ assert_redirected_to root_url
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/user.rb b/lib/generators/nifty/authentication/templates/user.rb
new file mode 100644
index 0000000..ec18524
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/user.rb
@@ -0,0 +1,38 @@
+class <%= user_class_name %> < ActiveRecord::Base
+<%- if options[:authlogic] -%>
+ acts_as_authentic
+<%- else -%>
+ # new columns need to be added here to be writable through mass assignment
+ attr_accessible :username, :email, :password, :password_confirmation
+
+ attr_accessor :password
+ before_save :prepare_password
+
+ validates_presence_of :username
+ validates_uniqueness_of :username, :email, :allow_blank => true
+ validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"
+ validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
+ validates_presence_of :password, :on => :create
+ validates_confirmation_of :password
+ validates_length_of :password, :minimum => 4, :allow_blank => true
+
+ # login can be either username or email address
+ def self.authenticate(login, pass)
+ <%= user_singular_name %> = find_by_username(login) || find_by_email(login)
+ return <%= user_singular_name %> if <%= user_singular_name %> && <%= user_singular_name %>.password_hash == <%= user_singular_name %>.encrypt_password(pass)
+ end
+
+ def encrypt_password(pass)
+ BCrypt::Engine.hash_secret(pass, password_salt)
+ end
+
+ private
+
+ def prepare_password
+ unless password.blank?
+ self.password_salt = BCrypt::Engine.generate_salt
+ self.password_hash = encrypt_password(password)
+ end
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/users_controller.rb b/lib/generators/nifty/authentication/templates/users_controller.rb
new file mode 100644
index 0000000..2faed00
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/users_controller.rb
@@ -0,0 +1,32 @@
+class <%= user_plural_class_name %>Controller < ApplicationController
+ before_filter :login_required, :except => [:new, :create]
+
+ def new
+ @<%= user_singular_name %> = <%= user_class_name %>.new
+ end
+
+ def create
+ @<%= user_singular_name %> = <%= user_class_name %>.new(params[:<%= user_singular_name %>])
+ if @<%= user_singular_name %>.save
+ <%- unless options[:authlogic] -%>
+ session[:<%= user_singular_name %>_id] = @<%= user_singular_name %>.id
+ <%- end -%>
+ redirect_to root_url, :notice => "Thank you for signing up! You are now logged in."
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @<%= user_singular_name %> = current_<%= user_singular_name %>
+ end
+
+ def update
+ @<%= user_singular_name %> = current_<%= user_singular_name %>
+ if @<%= user_singular_name %>.update_attributes(params[:<%= user_singular_name %>])
+ redirect_to root_url, :notice => "Your profile has been updated."
+ else
+ render :edit
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/users_helper.rb b/lib/generators/nifty/authentication/templates/users_helper.rb
new file mode 100644
index 0000000..7eb9040
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/users_helper.rb
@@ -0,0 +1,2 @@
+module <%= user_plural_class_name %>Helper
+end
diff --git a/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb b/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb
new file mode 100644
index 0000000..4e1c47d
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb
@@ -0,0 +1,20 @@
+<%%= form_for @<%= user_singular_name %> do |f| %>
+ <%%= f.error_messages %>
+ <div class="field">
+ <%%= f.label :username %>
+ <%%= f.text_field :username %>
+ </div>
+ <div class="field">
+ <%%= f.label :email, "Email Address" %>
+ <%%= f.text_field :email %>
+ </div>
+ <div class="field">
+ <%%= f.label :password %>
+ <%%= f.password_field :password %>
+ </div>
+ <div class="field">
+ <%%= f.label :password_confirmation, "Confirm Password" %>
+ <%%= f.password_field :password_confirmation %>
+ </div>
+ <div class="actions"><%%= f.submit (@<%= user_singular_name %>.new_record? ? "Sign up" : "Update") %></div>
+<%% end %>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb b/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb
new file mode 100644
index 0000000..75de67e
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb
@@ -0,0 +1,3 @@
+<%% title "Update Profile" %>
+
+<%%= render "form" %>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/login.html.erb b/lib/generators/nifty/authentication/templates/views/erb/login.html.erb
new file mode 100644
index 0000000..1cbc428
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/login.html.erb
@@ -0,0 +1,30 @@
+<%% title "Log in" %>
+
+<p>Don't have an account? <%%= link_to "Sign up!", signup_path %></p>
+
+<%- if options[:authlogic] -%>
+<%%= form_for @<%= session_singular_name %> do |f| %>
+ <%%= f.error_messages %>
+ <div class="field">
+ <%%= f.label :username %>
+ <%%= f.text_field :username %>
+ </div>
+ <div class="field">
+ <%%= f.label :password %>
+ <%%= f.password_field :password %>
+ </div>
+ <div class="actions"><%%= f.submit "Log in" %></div>
+<%% end %>
+<%- else -%>
+<%%= form_tag <%= session_plural_name %>_path do %>
+ <div class="field">
+ <%%= label_tag :login, "Username or Email Address" %>
+ <%%= text_field_tag :login, params[:login] %>
+ </div>
+ <div class="field">
+ <%%= label_tag :password %>
+ <%%= password_field_tag :password %>
+ </div>
+ <div class="actions"><%%= submit_tag "Log in" %></div>
+<%% end %>
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb b/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb
new file mode 100644
index 0000000..6f282b5
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb
@@ -0,0 +1,5 @@
+<%% title "Sign up" %>
+
+<p>Already have an account? <%%= link_to "Log in", login_path %>.</p>
+
+<%%= render "form" %>
diff --git a/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml b/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml
new file mode 100644
index 0000000..992ee9c
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml
@@ -0,0 +1,16 @@
+= form_for @<%= user_singular_name %> do |f|
+ = f.error_messages
+ .field
+ = f.label :username
+ = f.text_field :username
+ .field
+ = f.label :email, "Email Address"
+ = f.text_field :email
+ .field
+ = f.label :password
+ = f.password_field :password
+ .field
+ = f.label :password_confirmation, "Confirm Password"
+ = f.password_field :password_confirmation
+ .actions
+ = f.submit (@<%= user_singular_name %>.new_record? ? "Sign up" : "Update")
diff --git a/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml b/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml
new file mode 100644
index 0000000..4b43a3b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml
@@ -0,0 +1,3 @@
+- title "Sign up"
+
+= render "form"
diff --git a/lib/generators/nifty/authentication/templates/views/haml/login.html.haml b/lib/generators/nifty/authentication/templates/views/haml/login.html.haml
new file mode 100644
index 0000000..22fc95b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/login.html.haml
@@ -0,0 +1,26 @@
+- title "Log in"
+
+%p== Don't have an account? #{link_to "Sign up!", signup_path}
+
+<%- if options[:authlogic] -%>
+= form_for @<%= session_singular_name %> do |f|
+ = f.error_messages
+ .field
+ = f.label :username
+ = f.text_field :username
+ .field
+ = f.label :password
+ = f.password_field :password
+ .actions
+ = f.submit "Log in"
+<%- else -%>
+- form_tag <%= session_plural_name %>_path do
+ .field
+ = label_tag :login, "Username or Email Address"
+ = text_field_tag :login, params[:login]
+ .field
+ = label_tag :password
+ = password_field_tag :password
+ .actions
+ = submit_tag "Log in"
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml b/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml
new file mode 100644
index 0000000..dc75c13
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml
@@ -0,0 +1,5 @@
+- title "Sign up"
+
+%p== Already have an account? #{link_to "Log in", login_path}.
+
+= render "form"