Skip to content

Commit b6cea6a

Browse files
committed
Adding in lib and other files
1 parent d7aeaaa commit b6cea6a

16 files changed

Lines changed: 609 additions & 0 deletions

app/controllers/sessions.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# require 'lib/authenticated_system_controller'
2+
require File.join(File.dirname(__FILE__), '..', '..', "lib", "authenticated_system", "authenticated_dependencies")
3+
class Sessions < Application
4+
5+
skip_before :login_required
6+
7+
def new
8+
render
9+
end
10+
11+
def create
12+
self.current_user = User.authenticate(params[:login], params[:password])
13+
if logged_in?
14+
if params[:remember_me] == "1"
15+
self.current_user.remember_me
16+
cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
17+
end
18+
redirect_back_or_default('/')
19+
else
20+
render :new
21+
end
22+
end
23+
24+
def destroy
25+
self.current_user.forget_me if logged_in?
26+
cookies.delete :auth_token
27+
reset_session
28+
redirect_back_or_default('/')
29+
end
30+
31+
end

app/controllers/users.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require File.join(File.dirname(__FILE__), '..', '..', "lib", "authenticated_system", "authenticated_dependencies")
2+
class Users < Application
3+
provides :xml
4+
5+
skip_before :login_required
6+
7+
def new
8+
only_provides :html
9+
@user = User.new(params[:user] || {})
10+
display @user
11+
end
12+
13+
def create
14+
cookies.delete :auth_token
15+
16+
@user = User.new(params[:user])
17+
if @user.save
18+
redirect_back_or_default('/')
19+
else
20+
render :new
21+
end
22+
end
23+
24+
end

app/views/sessions/new.html.erb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<% form_tag :action => url(:login) do -%>
2+
<p><label for="login">Login</label><br/>
3+
<%= text_field :name => "login" %></p>
4+
5+
<p><label for="password">Password</label><br/>
6+
<%= password_field :name => "password" %></p>
7+
8+
<!-- Uncomment this if you want this functionality
9+
<p><label for="remember_me">Remember me:</label>
10+
<%= checkbox_field :name => 'remember_me' %></p>
11+
-->
12+
13+
<p><%= submit_button 'Log in' %></p>
14+
<% end -%>

app/views/users/new.html.erb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<%= error_messages_for @user %>
2+
<% form_for @user, :action => url(:users) do %>
3+
<p>
4+
<%= text_control :login, :label => "Login" %>
5+
</p>
6+
<p>
7+
<%= text_control :email, :label => "Email" %>
8+
</p>
9+
<p>
10+
<%= password_control :password, :label => "Password" %>
11+
</p>
12+
<p>
13+
<%= password_control :password_confirmation, :label => "Password Confirmation" %>
14+
</p>
15+
<p>
16+
<%= submit_button "Sign up" %>
17+
</p>
18+
<% end %>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require 'merb_helpers'
2+
3+
base = File.dirname(__FILE__)
4+
5+
%w(authenticated_routes authenticated_system_controller authenticated_system_model authenticated_system_orm_map).each do |f|
6+
require File.join(base, f)
7+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Put the correct routes in place
2+
module AuthenticatedSystem
3+
def self.add_routes
4+
Merb::BootLoader.after_app_loads do
5+
Merb::Router.prepend do |r|
6+
r.match("/login").to(:controller => "Sessions", :action => "create").name(:login)
7+
r.match("/logout").to(:controller => "Sessions", :action => "destroy").name(:logout)
8+
r.match("/users/activate/:activation_code").to(:controller => "Users", :action => "activate").name(:user_activation)
9+
r.resources :users
10+
end
11+
end
12+
end
13+
end
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
module AuthenticatedSystem
2+
module Controller
3+
protected
4+
# Returns true or false if the user is logged in.
5+
# Preloads @current_user with the user model if they're logged in.
6+
def logged_in?
7+
current_user != :false
8+
end
9+
10+
# Accesses the current user from the session. Set it to :false if login fails
11+
# so that future calls do not hit the database.
12+
def current_user
13+
@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie || :false)
14+
end
15+
16+
# Store the given user in the session.
17+
def current_user=(new_user)
18+
session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id
19+
@current_user = new_user
20+
end
21+
22+
# Check if the user is authorized
23+
#
24+
# Override this method in your controllers if you want to restrict access
25+
# to only a few actions or if you want to check if the user
26+
# has the correct rights.
27+
#
28+
# Example:
29+
#
30+
# # only allow nonbobs
31+
# def authorized?
32+
# current_user.login != "bob"
33+
# end
34+
def authorized?
35+
logged_in?
36+
end
37+
38+
# Filter method to enforce a login requirement.
39+
#
40+
# To require logins for all actions, use this in your controllers:
41+
#
42+
# before_filter :login_required
43+
#
44+
# To require logins for specific actions, use this in your controllers:
45+
#
46+
# before_filter :login_required, :only => [ :edit, :update ]
47+
#
48+
# To skip this in a subclassed controller:
49+
#
50+
# skip_before_filter :login_required
51+
#
52+
def login_required
53+
authorized? || throw(:halt, :access_denied)
54+
end
55+
56+
# Redirect as appropriate when an access request fails.
57+
#
58+
# The default action is to redirect to the login screen.
59+
#
60+
# Override this method in your controllers if you want to have special
61+
# behavior in case the user is not authorized
62+
# to access the requested action. For example, a popup window might
63+
# simply close itself.
64+
def access_denied
65+
case content_type
66+
when :html
67+
store_location
68+
redirect url(:login)
69+
when :xml
70+
headers["Status"] = "Unauthorized"
71+
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
72+
set_status(401)
73+
render :text => "Couldn't authenticate you"
74+
end
75+
end
76+
77+
# Store the URI of the current request in the session.
78+
#
79+
# We can return to this location by calling #redirect_back_or_default.
80+
def store_location
81+
session[:return_to] = request.uri
82+
end
83+
84+
# Redirect to the URI stored by the most recent store_location call or
85+
# to the passed default.
86+
def redirect_back_or_default(default)
87+
loc = session[:return_to] || default
88+
session[:return_to] = nil
89+
redirect loc
90+
end
91+
92+
# Inclusion hook to make #current_user and #logged_in?
93+
# available as ActionView helper methods.
94+
# def self.included(base)
95+
# base.send :helper_method, :current_user, :logged_in?
96+
# end
97+
98+
# Called from #current_user. First attempt to login by the user id stored in the session.
99+
def login_from_session
100+
self.current_user = User.find_authenticated_model_with_id(session[:user]) if session[:user]
101+
end
102+
103+
# Called from #current_user. Now, attempt to login by basic authentication information.
104+
def login_from_basic_auth
105+
username, passwd = get_auth_data
106+
self.current_user = User.authenticate(username, passwd) if username && passwd
107+
end
108+
109+
# Called from #current_user. Finaly, attempt to login by an expiring token in the cookie.
110+
def login_from_cookie
111+
user = cookies[:auth_token] && User.find_authenticated_model_with_remember_token(cookies[:auth_token])
112+
if user && user.remember_token?
113+
user.remember_me
114+
cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at }
115+
self.current_user = user
116+
end
117+
end
118+
119+
def reset_session
120+
session.data.each{|k,v| session.data.delete(k)}
121+
end
122+
123+
private
124+
@@http_auth_headers = %w(Authorization HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION)
125+
126+
# gets BASIC auth info
127+
def get_auth_data
128+
auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
129+
auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
130+
return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
131+
end
132+
end
133+
end
134+
135+
Merb::BootLoader.after_app_loads do
136+
Application.send(:include, AuthenticatedSystem::Controller)
137+
end
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
module AuthenticatedSystem
3+
module Model
4+
5+
def self.included(base)
6+
base.send(:include, InstanceMethods)
7+
base.send(:extend, ClassMethods)
8+
base.send(:extend, AuthenticatedSystem::OrmMap )
9+
end
10+
11+
module InstanceMethods
12+
def authenticated?(password)
13+
crypted_password == encrypt(password)
14+
end
15+
16+
# before filter
17+
def encrypt_password
18+
return if password.blank?
19+
self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
20+
self.crypted_password = encrypt(password)
21+
end
22+
23+
# Encrypts the password with the user salt
24+
def encrypt(password)
25+
self.class.encrypt(password, salt)
26+
end
27+
28+
def remember_token?
29+
remember_token_expires_at && DateTime.now < DateTime.parse(remember_token_expires_at.to_s)
30+
end
31+
32+
def remember_me_until(time)
33+
self.remember_token_expires_at = time
34+
self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
35+
save
36+
end
37+
38+
def remember_me_for(time)
39+
remember_me_until (Time.now + time)
40+
end
41+
42+
# These create and unset the fields required for remembering users between browser closes
43+
# Default of 2 weeks
44+
def remember_me
45+
remember_me_for (Merb::Const::WEEK * 2)
46+
end
47+
48+
def forget_me
49+
self.remember_token_expires_at = nil
50+
self.remember_token = nil
51+
self.save
52+
end
53+
54+
protected
55+
56+
def password_required?
57+
crypted_password.blank? || !password.blank?
58+
end
59+
60+
end
61+
62+
module ClassMethods
63+
# Encrypts some data with the salt.
64+
def encrypt(password, salt)
65+
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
66+
end
67+
68+
# Authenticates a user by their login name and unencrypted password. Returns the user or nil.
69+
def authenticate(login, password)
70+
u = find_activated_authenticated_model_with_login(login) # need to get the salt
71+
u && u.authenticated?(password) ? u : nil
72+
end
73+
end
74+
75+
76+
end
77+
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module AuthenticatedSystem
2+
module OrmMap
3+
4+
def find_authenticated_model_with_id(id)
5+
User.first(:id => id)
6+
end
7+
8+
def find_authenticated_model_with_remember_token(rt)
9+
User.first(:remember_token => rt)
10+
end
11+
12+
def find_activated_authenticated_model_with_login(login)
13+
if User.instance_methods.include?("activated_at")
14+
User.first(:login => login, :activated_at.not => nil)
15+
else
16+
User.first(:login => login)
17+
end
18+
end
19+
20+
def find_activated_authenticated_model(activation_code)
21+
User.first(:activation_code => activation_code)
22+
end
23+
24+
def find_with_conditions(conditions)
25+
User.first(conditions)
26+
end
27+
28+
# A method to assist with specs
29+
def clear_database_table
30+
User.auto_migrate!
31+
end
32+
end
33+
34+
end

0 commit comments

Comments
 (0)