Permalink
Browse files

Released v0.10.0

  • Loading branch information...
1 parent ae1d3bb commit 35f14bafffbb64936e0c05dd7628872816248635 @binarylogic binarylogic committed Oct 27, 2008
View
@@ -1,3 +1,11 @@
+== 0.10.0 released 2008-10-24
+
+* Do not allow instantiation if the session has not been activated with a controller object. Just like ActiveRecord won't let you do anything without a DB connection.
+* Abstracted controller implementation to allow for rails, merb, etc adapters. So this is not confined to the rails framework.
+* Removed create and update methods and added save, like ActiveRecord.
+* after_validation should be able to change the result if it adds errors on callbacks.
+* Completed tests.
+
== 0.9.1 released 2008-10-24
* Changed scope to id. Makes more sense to call it an id and fits better with the ActiveRecord model.
View
@@ -1,7 +1,8 @@
CHANGELOG.rdoc
init.rb
lib/authgasm/acts_as_authentic.rb
-lib/authgasm/controller.rb
+lib/authgasm/controller_adapters/abstract_adapter.rb
+lib/authgasm/controller_adapters/rails_adapter.rb
lib/authgasm/session/active_record_trickery.rb
lib/authgasm/session/base.rb
lib/authgasm/session/callbacks.rb
@@ -77,6 +78,7 @@ test_app/script/server
test_app/test/fixtures/users.yml
test_app/test/functional/user_sessions_controller_test.rb
test_app/test/functional/users_controller_test.rb
+test_app/test/integration/user_sesion_stories_test.rb
+test_app/test/integration/user_session_test.rb
test_app/test/test_helper.rb
-test_app/test/unit/ass_test.rb
test_app/test/unit/user_test.rb
View
@@ -19,7 +19,7 @@ What if your user sessions controller could look just like your other controller
def create
@user_session = UserSession.new(params[:user_session])
- if @user_session.create
+ if @user_session.save
redirect_to account_url
else
render :action => :new
@@ -134,6 +134,8 @@ Authgasm tries to check the state of the record before creating the session. If
What's neat about this is that these are checked upon any type of login. When logging in explicitly, by cookie, session, or basic http auth. So if you mark a user inactive in the middle of their session they wont be logged back in next time they refresh the page. Giving you complete control.
+Need Authgasm to check your own "state"? No problem, check out the hooks section below. Add in a before_validation or after_validation to do your own checking.
+
== Hooks / Callbacks
Just like ActiveRecord you can create your own hooks / callbacks so that you can do whatever you want when certain actions are performed. Here they are:
@@ -142,11 +144,27 @@ Just like ActiveRecord you can create your own hooks / callbacks so that you can
after_create
before_destroy
after_destroy
+ before_save
+ after_save
before_update
after_update
before_validation
after_validation
+== Errors
+
+The errors in Authgasm work JUST LIKE ActiveRecord. In fact, it uses the exact same ActiveRecord errors class. Use it the same way:
+
+ class UserSession
+ before_validation :check_if_awesome
+
+ private
+ def check_if_awesome
+ errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
+ errors.add_to_base("You must be awesome to log in") unless record.awesome?
+ end
+ end
+
== Automatic Session Updating
This is one of my favorite features that I think its pretty cool. It's things like this that make a library great and let you know you are on the right track.
@@ -183,7 +201,7 @@ When things come together like this I think its a sign that you are doing someth
You're asking: "why would I want multiple sessions?". Take this example:
-You have an app where users login and then need to re-login to view / change their billing information. Similar to how Apples' me.com works, if you've ever used it. What you could do is have the user login with their normal session, then have an entirely new session that represents their "secure" session. But wait, this is 2 users sessions. No problem:
+You have an app where users login and then need to re-login to view / change their billing information. Similar to how Apple's me.com works. What you could do is have the user login with their normal session, then have an entirely new session that represents their "secure" session. But wait, this is 2 users sessions. No problem:
# regular user session
@user_session = UserSession.new
@@ -202,9 +220,13 @@ This will keep everything separate. The :secure session will store its info in a
For more information on ids checkout Authgasm::Session::Base#initialize
+== What about [insert framework here]?
+
+As of now, authgasm supports rails right out of the box. But I designed authgasm to be framework agnostic. The only thing stopping Authgasm from being implemented in merb, or any other framework, is a simple adapter. I have not had the opportunity to use Authgasm in anything other than rails. If you want to use this in merb or any other framework take a look at authgasm/controller/rails_adapter.rb.
+
== How it works
-Interested in how all of this all works? Basically a before_filter is automatically set in your controller which lets Authgasm know about the current controller object. This allows Authgasm to set sessions, cookies, login via basic http auth, etc. If you are using rails in a multiple thread environment, don't worry. I kept that in mind and made this is thread safe.
+Interested in how all of this all works? Basically a before_filter is automatically set in your controller which lets Authgasm know about the current controller object. This allows Authgasm to set sessions, cookies, login via basic http auth, etc. If you are using rails in a multiple thread environment, don't worry. I kept that in mind and made this thread safe.
From there it is pretty simple. When you try to create a new session the record is authenticated and then all of the session / cookie magic is done for you. The sky is the limit.
View
@@ -1,2 +1 @@
-require "digest/sha2"
require "authgasm"
View
@@ -1,5 +1,8 @@
+require "digest/sha2"
require File.dirname(__FILE__) + "/authgasm/version"
-require File.dirname(__FILE__) + "/authgasm/controller"
+
+require File.dirname(__FILE__) + "/authgasm/controller_adapters/rails_adapter" if defined?(Rails)
+
require File.dirname(__FILE__) + "/authgasm/sha256_crypto_provider"
require File.dirname(__FILE__) + "/authgasm/acts_as_authentic"
require File.dirname(__FILE__) + "/authgasm/session/active_record_trickery"
@@ -1,5 +1,5 @@
module Authgasm
- module ActsAsAuthenticated # :nodoc:
+ module ActsAsAuthentic # :nodoc:
def self.included(base)
base.extend(ClassMethods)
end
@@ -20,6 +20,7 @@ module ClassMethods
# Class method name Description
# User.unique_token returns unique token generated by your :crypto_provider
# User.crypto_provider The class that you set in your :crypto_provider option
+ # User.forget_all! Resets all records so they will not be remembered on their next visit. Basically makes their cookies invalid
#
# Named Scopes
# User.logged_in Find all users who are logged in, based on your :logged_in_timeout option
@@ -31,6 +32,7 @@ module ClassMethods
# user.valid_password?(pass) Based on the valid of :password_field. Determines if the password passed is valid. The password could be encrypted or raw.
# user.randomize_password! Basically resets the password to a random password using only letters and numbers
# user.logged_in? Based on the :logged_in_timeout option. Tells you if the user is logged in or not
+ # user.forget! Changes their remember token, making their cookie invalid.
#
# === Options
# * <tt>session_class:</tt> default: "#{name}Session", the related session class. Used so that you don't have to repeat yourself here. A lot of the configuration will be based off of the configuration values of this class.
@@ -107,6 +109,17 @@ def self.unique_token
def self.crypto_provider
#{options[:crypto_provider]}
end
+
+ def self.forget_all!
+ # Paginate these to save on memory
+ records = nil
+ i = 0
+ begin
+ records = find(:all, :limit => 50, :offset => i)
+ records.each { |record| records.update_attribute(:#{options[:remember_token_field]}, unique_token) }
+ i += 50
+ end while !records.blank?
+ end
end_eval
# Instance methods
@@ -125,12 +138,13 @@ def #{options[:password_field]}=(pass)
return if pass.blank?
self.tried_to_set_#{options[:password_field]} = true
@#{options[:password_field]} = pass
- salt = [Array.new(6) {rand(256).chr}.join].pack("m").chomp
self.#{options[:remember_token_field]} = self.class.unique_token
- self.#{options[:password_salt_field]}, self.#{options[:crypted_password_field]} = salt, crypto_provider.encrypt(@#{options[:password_field]} + salt)
+ self.#{options[:password_salt_field]} = self.class.unique_token
+ self.#{options[:crypted_password_field]} = crypto_provider.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]})
end
def valid_#{options[:password_field]}?(attempted_password)
+ return false if attempted_password.blank?
attempted_password == #{options[:crypted_password_field]} || #{options[:crypted_password_field]} == crypto_provider.encrypt(attempted_password + #{options[:password_salt_field]})
end
end_eval
@@ -145,6 +159,7 @@ def #{options[:password_field]}=(pass)
end
def valid_#{options[:password_field]}?(attemtped_password)
+ return false if attempted_password.blank?
attempted_password == #{options[:crypted_password_field]} || #{options[:crypted_password_field]} = crypto_provider.decrypt(attempted_password)
end
end_eval
@@ -158,6 +173,10 @@ def crypto_provider
self.class.crypto_provider
end
+ def forget!
+ update_attribute(:#{options[:remember_token_field]}, self.class.unique_token)
+ end
+
def randomize_#{options[:password_field]}!
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
newpass = ""
@@ -166,6 +185,13 @@ def randomize_#{options[:password_field]}!
self.confirm_#{options[:password_field]} = newpass
end
+ def save_from_session(*args)
+ @saving_from_session = true
+ result = save(*args)
+ @saving_from_session = false
+ result
+ end
+
protected
def create_sessions!
return if !#{options[:session_class]}.activated? || #{options[:session_ids].inspect}.blank?
@@ -183,7 +209,7 @@ def create_sessions!
end
def update_sessions!
- return if !#{options[:session_class]}.activated?
+ return if @saving_from_session || !#{options[:session_class]}.activated?
#{options[:session_ids].inspect}.each do |session_id|
session = #{options[:session_class]}.find(*[session_id].compact)
@@ -192,7 +218,7 @@ def update_sessions!
next if !session || session.record != self
# We know we are logged in and this is our record, update the session
- session.update
+ session.save
end
end
@@ -215,4 +241,4 @@ def validate_password
end
end
-ActiveRecord::Base.send(:include, Authgasm::ActsAsAuthenticated)
+ActiveRecord::Base.send(:include, Authgasm::ActsAsAuthentic)
View
@@ -1,16 +0,0 @@
-module Authgasm
- # = Controller
- # Adds a before_filter to set the controller object so that Authgasm can do its session and cookie magic
- module Controller
- def self.included(klass) # :nodoc:
- klass.prepend_before_filter :set_controller
- end
-
- private
- def set_controller
- Authgasm::Session::Base.controller = self
- end
- end
-end
-
-ActionController::Base.send(:include, Authgasm::Controller)
@@ -0,0 +1,25 @@
+module Authgasm
+ module ControllerAdapters # :nodoc:
+ # = Abstract Adapter
+ # Allows you to use Authgasm in any framework you want, not just rails. See tha RailsAdapter for an example of how to adapter Authgasm to work with your framework.
+ class AbstractAdapter
+ attr_accessor :controller
+
+ def initialize(controller)
+ self.controller = controller
+ end
+
+ def authenticate_with_http_basic(*args, &block)
+ end
+
+ def cookies
+ end
+
+ def request
+ end
+
+ def session
+ end
+ end
+ end
+end
@@ -0,0 +1,39 @@
+module Authgasm
+ module ControllerAdapters
+ # = Rails Adapter
+ # Adapts authgasm to work with rails. The point is to close the gap between what authgasm expects and what the rails controller object
+ # provides. Similar to how ActiveRecord has an adapter for MySQL, PostgreSQL, SQLite, etc.
+ class RailsAdapter < AbstractAdapter
+ def authenticate_with_http_basic(*args, &block)
+ controller.authenticate_with_http_basic(*args, &block)
+ end
+
+ def cookies
+ controller.send(:cookies)
+ end
+
+ def request
+ controller.request
+ end
+
+ def session
+ controller.session
+ end
+ end
+
+ # = Rails Implementation
+ # Lets Authgasm know about the controller object, AKA "activates" authgasm.
+ module RailsImplementation
+ def self.included(klass) # :nodoc:
+ klass.prepend_before_filter :set_controller
+ end
+
+ private
+ def set_controller
+ Authgasm::Session::Base.controller = RailsAdapter.new(self)
+ end
+ end
+ end
+end
+
+ActionController::Base.send(:include, Authgasm::ControllerAdapters::RailsImplementation)
@@ -18,7 +18,7 @@ def human_attribute_name(attribute_key_name, options = {})
module InstanceMethods # :nodoc:
def new_record?
- true
+ new_session?
end
end
end
Oops, something went wrong.

0 comments on commit 35f14ba

Please sign in to comment.