forked from technoweenie/restful-authentication
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit of the restful_authentication plugin
git-svn-id: http://svn.techno-weenie.net/projects/plugins/restful_authentication@1477 567b1171-46fb-0310-a4c9-b4bef9110e78
- Loading branch information
technoweenie
committed
Aug 1, 2006
0 parents
commit 2366199
Showing
22 changed files
with
868 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Restful Authentication Generator | ||
==== | ||
|
||
This is a basic restful authentication generator for rails, taken from acts as authenticated. Currently it requires Rails 1.2 (or edge). | ||
|
||
To use: | ||
|
||
./script/generate authenticated user sessions | ||
|
||
The first parameter specifies the model that gets created in signup (typically a user or account model). A model with migration is created, | ||
as well as a basic controller with the create method. | ||
|
||
The second parameter specifies the sessions controller name. This is the controller that handles the actual login/logout function on the site. | ||
|
||
You can pass --skip_migration to skip the user migration. | ||
|
||
From here, you will need to add the resource routes in config/routes.rb. | ||
|
||
map.resources :users, :sessions | ||
|
||
Generate your mailer: | ||
|
||
./script/generate authenticated_mailer user | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
require 'rake' | ||
require 'rake/testtask' | ||
require 'rake/rdoctask' | ||
|
||
desc 'Default: run unit tests.' | ||
task :default => :test | ||
|
||
desc 'Test the restful_authentication plugin.' | ||
Rake::TestTask.new(:test) do |t| | ||
t.libs << 'lib' | ||
t.pattern = 'test/**/*_test.rb' | ||
t.verbose = true | ||
end | ||
|
||
desc 'Generate documentation for the restful_authentication plugin.' | ||
Rake::RDocTask.new(:rdoc) do |rdoc| | ||
rdoc.rdoc_dir = 'rdoc' | ||
rdoc.title = 'RestfulAuthentication' | ||
rdoc.options << '--line-numbers' << '--inline-source' | ||
rdoc.rdoc_files.include('README') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
./script/generate authenticated USERMODEL CONTROLLERNAME |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
class AuthenticatedGenerator < Rails::Generator::NamedBase | ||
attr_reader :controller_name, | ||
:controller_class_path, | ||
:controller_file_path, | ||
:controller_class_nesting, | ||
:controller_class_nesting_depth, | ||
:controller_class_name, | ||
:controller_singular_name, | ||
:controller_plural_name | ||
alias_method :controller_file_name, :controller_singular_name | ||
alias_method :controller_table_name, :controller_plural_name | ||
attr_reader :model_controller_name, | ||
:model_controller_class_path, | ||
:model_controller_file_path, | ||
:model_controller_class_nesting, | ||
:model_controller_class_nesting_depth, | ||
:model_controller_class_name, | ||
:model_controller_singular_name, | ||
:model_controller_plural_name | ||
alias_method :model_controller_file_name, :model_controller_singular_name | ||
alias_method :model_controller_table_name, :model_controller_plural_name | ||
|
||
def initialize(runtime_args, runtime_options = {}) | ||
super | ||
|
||
@controller_name = args.shift | ||
@model_controller_name = @name.pluralize | ||
|
||
# sessions controller | ||
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name) | ||
@controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name) | ||
|
||
if @controller_class_nesting.empty? | ||
@controller_class_name = @controller_class_name_without_nesting | ||
else | ||
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}" | ||
end | ||
|
||
# model controller | ||
base_name, @model_controller_class_path, @model_controller_file_path, @model_controller_class_nesting, @model_controller_class_nesting_depth = extract_modules(@model_controller_name) | ||
@model_controller_class_name_without_nesting, @model_controller_singular_name, @model_controller_plural_name = inflect_names(base_name) | ||
|
||
if @model_controller_class_nesting.empty? | ||
@model_controller_class_name = @model_controller_class_name_without_nesting | ||
else | ||
@model_controller_class_name = "#{@model_controller_class_nesting}::#{@model_controller_class_name_without_nesting}" | ||
end | ||
end | ||
|
||
def manifest | ||
recorded_session = record do |m| | ||
# Check for class naming collisions. | ||
m.class_collisions controller_class_path, "#{controller_class_name}Controller", # Sessions Controller | ||
"#{controller_class_name}Helper" | ||
m.class_collisions model_controller_class_path, "#{model_controller_class_name}Controller", # Model Controller | ||
"#{model_controller_class_name}Helper" | ||
m.class_collisions class_path, "#{class_name}" | ||
m.class_collisions [], 'AuthenticatedSystem', 'AuthenticatedTestHelper' | ||
|
||
# Controller, helper, views, and test directories. | ||
m.directory File.join('app/models', class_path) | ||
m.directory File.join('app/controllers', controller_class_path) | ||
m.directory File.join('app/controllers', model_controller_class_path) | ||
m.directory File.join('app/helpers', controller_class_path) | ||
m.directory File.join('app/views', controller_class_path, controller_file_name) | ||
m.directory File.join('test/functional', controller_class_path) | ||
m.directory File.join('app/controllers', model_controller_class_path) | ||
m.directory File.join('app/helpers', model_controller_class_path) | ||
m.directory File.join('app/views', model_controller_class_path, model_controller_file_name) | ||
m.directory File.join('test/functional', model_controller_class_path) | ||
m.directory File.join('test/unit', class_path) | ||
|
||
m.template 'model.rb', | ||
File.join('app/models', | ||
class_path, | ||
"#{file_name}.rb") | ||
|
||
m.template 'controller.rb', | ||
File.join('app/controllers', | ||
controller_class_path, | ||
"#{controller_file_name}_controller.rb") | ||
|
||
m.template 'model_controller.rb', | ||
File.join('app/controllers', | ||
model_controller_class_path, | ||
"#{model_controller_file_name}_controller.rb") | ||
|
||
m.template 'authenticated_system.rb', | ||
File.join('lib', 'authenticated_system.rb') | ||
|
||
m.template 'authenticated_test_helper.rb', | ||
File.join('lib', 'authenticated_test_helper.rb') | ||
|
||
m.template 'functional_test.rb', | ||
File.join('test/functional', | ||
controller_class_path, | ||
"#{controller_file_name}_controller_test.rb") | ||
|
||
m.template 'model_functional_test.rb', | ||
File.join('test/functional', | ||
model_controller_class_path, | ||
"#{model_controller_file_name}_controller_test.rb") | ||
|
||
m.template 'helper.rb', | ||
File.join('app/helpers', | ||
controller_class_path, | ||
"#{controller_file_name}_helper.rb") | ||
|
||
m.template 'model_helper.rb', | ||
File.join('app/helpers', | ||
model_controller_class_path, | ||
"#{model_controller_file_name}_helper.rb") | ||
|
||
m.template 'unit_test.rb', | ||
File.join('test/unit', | ||
class_path, | ||
"#{file_name}_test.rb") | ||
|
||
m.template 'fixtures.yml', | ||
File.join('test/fixtures', | ||
"#{table_name}.yml") | ||
|
||
# Controller templates | ||
m.template 'login.rhtml', File.join('app/views', controller_class_path, controller_file_name, "new.rhtml") | ||
m.template 'signup.rhtml', File.join('app/views', model_controller_class_path, model_controller_file_name, "new.rhtml") | ||
|
||
unless options[:skip_migration] | ||
m.migration_template 'migration.rb', 'db/migrate', :assigns => { | ||
:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}" | ||
}, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" | ||
end | ||
end | ||
|
||
puts | ||
puts ("-" * 70) | ||
puts "Don't forget the restful routes in config.routes.rb" | ||
puts | ||
puts " map.resources :#{model_controller_file_name}, :#{controller_file_name}" | ||
puts | ||
puts "Try these for some familiar login URLs if you like:" | ||
puts | ||
puts " map.signup '/signup', :controller => '#{model_controller_file_name}', :action => 'new'" | ||
puts " map.login '/login', :controller => '#{controller_file_name}', :action => 'new'" | ||
puts " map.logout '/logout', :controller => '#{controller_file_name}', :action => 'destroy'" | ||
puts | ||
puts ("-" * 70) | ||
puts | ||
|
||
recorded_session | ||
end | ||
|
||
protected | ||
# Override with your own usage banner. | ||
def banner | ||
"Usage: #{$0} authenticated ModelName ControllerName" | ||
end | ||
end |
131 changes: 131 additions & 0 deletions
131
generators/authenticated/templates/authenticated_system.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
module AuthenticatedSystem | ||
protected | ||
# Returns true or false if the user is logged in. | ||
# Preloads @current_<%= file_name %> with the user model if they're logged in. | ||
def logged_in? | ||
(@current_<%= file_name %> ||= session[:<%= file_name %>] ? <%= class_name %>.find_by_id(session[:<%= file_name %>]) : :false).is_a?(<%= class_name %>) | ||
end | ||
# Accesses the current <%= file_name %> from the session. | ||
def current_<%= file_name %> | ||
@current_<%= file_name %> if logged_in? | ||
end | ||
|
||
# Store the given <%= file_name %> in the session. | ||
def current_<%= file_name %>=(new_<%= file_name %>) | ||
session[:<%= file_name %>] = new_<%= file_name %>.nil? ? nil : new_<%= file_name %>.id | ||
@current_<%= file_name %> = new_<%= file_name %> | ||
end | ||
|
||
# Check if the <%= file_name %> is authorized. | ||
# | ||
# Override this method in your controllers if you want to restrict access | ||
# to only a few actions or if you want to check if the <%= file_name %> | ||
# has the correct rights. | ||
# | ||
# Example: | ||
# | ||
# # only allow nonbobs | ||
# def authorize? | ||
# current_<%= file_name %>.login != "bob" | ||
# end | ||
def authorized? | ||
true | ||
end | ||
|
||
# Filter method to enforce a login requirement. | ||
# | ||
# To require logins for all actions, use this in your controllers: | ||
# | ||
# before_filter :login_required | ||
# | ||
# To require logins for specific actions, use this in your controllers: | ||
# | ||
# before_filter :login_required, :only => [ :edit, :update ] | ||
# | ||
# To skip this in a subclassed controller: | ||
# | ||
# skip_before_filter :login_required | ||
# | ||
def login_required | ||
username, passwd = get_auth_data | ||
self.current_<%= file_name %> ||= <%= class_name %>.authenticate(username, passwd) || :false if username && passwd | ||
logged_in? && authorized? ? true : access_denied | ||
end | ||
|
||
# Redirect as appropriate when an access request fails. | ||
# | ||
# The default action is to redirect to the login screen. | ||
# | ||
# Override this method in your controllers if you want to have special | ||
# behavior in case the <%= file_name %> is not authorized | ||
# to access the requested action. For example, a popup window might | ||
# simply close itself. | ||
def access_denied | ||
respond_to do |accepts| | ||
accepts.html do | ||
store_location | ||
redirect_to :controller => '<%= controller_file_name %>', :action => 'login' | ||
end | ||
accepts.xml do | ||
headers["Status"] = "Unauthorized" | ||
headers["WWW-Authenticate"] = %(Basic realm="Web Password") | ||
render :text => "Could't authenticate you", :status => '401 Unauthorized' | ||
end | ||
end | ||
false | ||
end | ||
|
||
# Store the URI of the current request in the session. | ||
# | ||
# We can return to this location by calling #redirect_back_or_default. | ||
def store_location | ||
session[:return_to] = request.request_uri | ||
end | ||
|
||
# Redirect to the URI stored by the most recent store_location call or | ||
# to the passed default. | ||
def redirect_back_or_default(default) | ||
session[:return_to] ? redirect_to_url(session[:return_to]) : redirect_to(default) | ||
session[:return_to] = nil | ||
end | ||
|
||
# Inclusion hook to make #current_<%= file_name %> and #logged_in? | ||
# available as ActionView helper methods. | ||
def self.included(base) | ||
base.send :helper_method, :current_<%= file_name %>, :logged_in? | ||
end | ||
|
||
# When called with before_filter :login_from_cookie will check for an :auth_token | ||
# cookie and log the user back in if apropriate | ||
def login_from_cookie | ||
return unless cookies[:auth_token] && !logged_in? | ||
user = <%= class_name %>.find_by_remember_token(cookies[:auth_token]) | ||
if user && user.remember_token? | ||
user.remember_me | ||
self.current_<%= file_name %> = user | ||
cookies[:auth_token] = { :value => self.current_<%= file_name %>.remember_token , :expires => self.current_<%= file_name %>.remember_token_expires_at } | ||
flash[:notice] = "Logged in successfully" | ||
end | ||
end | ||
|
||
private | ||
# gets BASIC auth info | ||
def get_auth_data | ||
user, pass = nil, nil | ||
# extract authorisation credentials | ||
if request.env.has_key? 'X-HTTP_AUTHORIZATION' | ||
# try to get it where mod_rewrite might have put it | ||
authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split | ||
elsif request.env.has_key? 'HTTP_AUTHORIZATION' | ||
# this is the regular location | ||
authdata = request.env['HTTP_AUTHORIZATION'].to_s.split | ||
end | ||
|
||
# at the moment we only support basic authentication | ||
if authdata && authdata[0] == 'Basic' | ||
user, pass = Base64.decode64(authdata[1]).split(':')[0..1] | ||
end | ||
return [user, pass] | ||
end | ||
end |
Oops, something went wrong.