Skip to content

Commit

Permalink
Added skeleton for oa-identity as well as the basics for the model mi…
Browse files Browse the repository at this point in the history
…xin.
  • Loading branch information
Michael Bleigh committed May 2, 2011
1 parent b2bcc84 commit 5225b20
Show file tree
Hide file tree
Showing 17 changed files with 208 additions and 250 deletions.
2 changes: 1 addition & 1 deletion .rspec
@@ -1,2 +1,2 @@
--format=nested
--colour
--format=nested
8 changes: 1 addition & 7 deletions Gemfile
@@ -1,9 +1,3 @@
source "http://rubygems.org"

gem 'oa-core', :path => File.expand_path('../../oa-core/', __FILE__)

# Will automatically pull in this gem and all its
# dependencies specified in the gemspec
gem 'oa-identity', :path => File.expand_path("..", __FILE__)

eval File.read(File.join(File.dirname(__FILE__), '../development_dependencies.rb'))
gemspec
19 changes: 0 additions & 19 deletions LICENSE

This file was deleted.

66 changes: 28 additions & 38 deletions README.markdown
@@ -1,51 +1,41 @@
# OmniAuth::Identity
# OmniAuth Identity

`OmniAuth::Identity` brings a traditional e-mail/login based sign in
flow to OmniAuth without sacrificing the simplicity and pattern
employed by OmniAuth's external authenticating brethren. It allows
users to create "identities" that consist of a user's basic info,
a login key, and a password.

## Installation

To install omniauth as a suite of gems:

gem install omniauth

To install just the login/password flow in the "identity" gem:

gem install oa-identity
The OmniAuth Identity gem provides a way for applications to utilize a
traditional login/password based authentication system without the need
to give up the simple authentication flow provided by OmniAuth. Identity
is designed on purpose to be as featureless as possible: it provides the
basic construct for user management and then gets out of the way.

## Usage

You can use `OmniAuth::Identity` just like any other provider: that's
the whole point!
You use `oa-identity` just like you would any other OmniAuth provider:
as a Rack middleware. The basic setup would look something like this:

use OmniAuth::Builder do
provider :identity, :key => :email, :attributes => [:name, :email, :location]
provider :identity
end

Now your users will be able to create or sign into an identity by
visiting `/auth/identity`. Once they have done so, your application
will receive a callback at `/auth/identity/callback` just like it
would with any other OmniAuth strategy.

## ORMs
Next, you need to create a model that will be able to persist the
information provided by the user. By default, this model should be a
class called `Identity` and should respond to the following API:

`OmniAuth::Identity` supports multiple ORMs:
Identity.create(
:name => 'x',
:password => 'y',
:confirm_password => 'y'
)

* ActiveRecord
* MongoMapper
identity = Identity.authenticate('key', 'password')
# => Identity instance if correct
# => false if incorrect

By default, it will try to detect which if any of the ORMs your app
is using in the order specified above. You can also explicitly set
the ORM by making this call before you instantiate the middleware:
identity.user_info # => {'name' => '...', 'nickname' => '...'}
identity.uid # => must be unique to the application

require 'omniauth/identity/orm/ormname'
To make things easier, you can inherit your model from the ones provided
for popular ORMs which will automatically provide the default setup
necessary. For example:

Where `ormname` is the same as the **gem name** of the ORM you would
like to use.

To implement a custom ORM, it's quite simple. You simply need to define
the `OmniAuth::Identity` class such that it adheres to the interface set
forth in `OmniAuth::Identity::Interface`.
class Identity < OmniAuth::Identity::Model::ActiveRecord
login_key :nickname
end
12 changes: 3 additions & 9 deletions Rakefile
@@ -1,14 +1,8 @@
require 'rubygems'
require 'bundler'
Bundler.setup
require 'rake'

require 'mg'
MG.new('oa-identity.gemspec')
Bundler::GemHelper.install_tasks

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |s|
s.rspec_opts = "--format=#{ENV['RSPEC_FORMAT'] || 'nested'} --colour"
end
RSpec::Core::RakeTask.new(:spec)

task :default => :spec
task :test => :spec
1 change: 0 additions & 1 deletion autotest/discover.rb

This file was deleted.

1 change: 1 addition & 0 deletions lib/oa-identity.rb
@@ -0,0 +1 @@
require 'omniauth/identity'
7 changes: 6 additions & 1 deletion lib/omniauth/identity.rb
Expand Up @@ -6,7 +6,12 @@ module Strategies
end

module Identity
autoload :Model, 'omniauth/identity/model'

module Models
autoload :ActiveRecord, 'omniauth/identity/models/active_record'
# autoload :MongoMapper, 'omniauth/identity/models/mongo_mapper'
# autoload :Mongoid, 'omniauth/identity/models/mongoid'
end
end
end

23 changes: 0 additions & 23 deletions lib/omniauth/identity/interface.rb

This file was deleted.

66 changes: 66 additions & 0 deletions lib/omniauth/identity/model.rb
@@ -0,0 +1,66 @@
module OmniAuth
module Identity
# This module provides an includable interface for implementing the
# necessary API for OmniAuth Identity to properly locate identities
# and provide all necessary information. All methods marked as
# abstract must be implemented in the including class for things to
# work properly.
module Model
def self.included(base)
base.extend ClassMethods
end

module ClassMethods
# Locate an identity given its unique login key.
#
# @abstract
# @param [String] key The unique login key.
# @return [Model] An instance of the identity model class.
def locate(key)
raise NotImplementedError
end

# Authenticate a user with the given key and password.
#
# @param [String] key The unique login key provided for a given identity.
# @param [String] password The presumed password for the identity.
# @return [Model] An instance of the identity model class.
def authenticate(key, password)
locate(key).authenticate(password)
end
end

# Returns self if the provided password is correct, false
# otherwise.
#
# @abstract
# @param [String] password The password to check.
# @return [self or false] Self if authenticated, false if not.
def authenticate(password)
raise NotImplementedError
end

SCHEMA_ATTRIBUTES = %w(name email nickname first_name last_name location description image phone)
# A hash of as much of the standard OmniAuth schema as is stored
# in this particular model. By default, this will call instance
# methods for each of the attributes it needs in turn, ignoring
# any for which `#respond_to?` is `false`.
#
# If `first_name`, `nickname`, and/or `last_name` is provided but
# `name` is not, it will be automatically calculated.
#
# @return [Hash] A string-keyed hash of user information.
def user_info
info = SCHEMA_ATTRIBUTES.inject({}) do |hash,attribute|
hash[attribute] = send(attribute) if respond_to?(attribute)
hash
end

info['name'] ||= [info['first_name'], info['last_name']].join(' ').strip if info['first_name'] || info['last_name']
info['name'] ||= info['nickname']

info
end
end
end
end
11 changes: 11 additions & 0 deletions lib/omniauth/identity/models/active_record.rb
@@ -0,0 +1,11 @@
require 'active_record'

module OmniAuth
module Identity
module Models
class ActiveRecord << ::ActiveRecord::Base
include OmniAuth::Identity::Model
end
end
end
end
27 changes: 0 additions & 27 deletions lib/omniauth/identity/orm/mongo_mapper.rb

This file was deleted.

36 changes: 0 additions & 36 deletions lib/omniauth/strategies/identity.rb
@@ -1,43 +1,7 @@
require 'omniauth/identity'

module OmniAuth
module Strategies
class Identity
include OmniAuth::Strategy

def initialize(app, options = {}, &block)
options[:key] ||= 'nickname'
super(app, :identity, options, &block)
end

def request_phase
OmniAuth::Form.build(:title => (self.options[:title] || 'Identify Yourself'), :url => callback_path) do
text_field 'Login', 'key'
password_field 'Password', 'password'

html <<-HTML
<a id='toggle_register' href='javascript:document.getElementById("toggle_register").style.display="none";document.getElementById("register").style.display = "block"'>Create a New Identity</a>
HTML

fieldset("Create Identity", :id => 'register', :style => 'display:none;') do
password_field 'Repeat Password', 'register[password_confirmation]'
text_field 'E-Mail', 'register[email]'
text_field 'Name', 'register[name]'
end
end.to_response
end

def callback_phase
if auth_hash
super
else
fail!(:invalid_credentials)
end
end

def auth_hash
@hash ||= OmniAuth::Identity::Model.identify(options[:key],request.params['key'],request.params['password'])
end
end
end
end
41 changes: 23 additions & 18 deletions oa-identity.gemspec
@@ -1,21 +1,26 @@
require 'rubygems'

version = File.open(File.dirname(__FILE__) + '/../VERSION', 'r').read.strip
# -*- encoding: utf-8 -*-
require File.expand_path('../../lib/omniauth/version', __FILE__)

Gem::Specification.new do |gem|
gem.name = "oa-identity"
gem.version = version
gem.summary = %Q{Login and password authentication for OmniAuth.}
gem.description = %Q{Login and password authentication for OmniAuth.}
gem.email = "michael@intridea.com"
gem.homepage = "http://github.com/intridea/omniauth"
gem.authors = ["Michael Bleigh"]

gem.files = Dir.glob("{lib}/**/*") + %w(README.rdoc LICENSE)

gem.add_dependency 'oa-core', version
gem.add_dependency 'activesupport', '~> 3.0.0'
gem.add_dependency 'uuid'

eval File.read(File.join(File.dirname(__FILE__), '../development_dependencies.rb'))
gem.add_runtime_dependency 'oa-core', OmniAuth::Version::STRING
gem.add_development_dependency 'maruku', '~> 0.6'
gem.add_development_dependency 'simplecov', '~> 0.4'
gem.add_development_dependency 'rack-test', '~> 0.5'
gem.add_development_dependency 'rake', '~> 0.8'
gem.add_development_dependency 'rspec', '~> 2.5'
gem.add_development_dependency 'yard', '~> 0.6'
gem.add_development_dependency 'ZenTest', '~> 4.5'
gem.name = 'oa-identity'
gem.version = OmniAuth::Version::STRING
gem.description = %q{Internal authentication handlers for OmniAuth.}
gem.summary = gem.description
gem.email = ['michael@intridea.com', 'sferik@gmail.com']
gem.homepage = 'http://github.com/intridea/omniauth'
gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober']
gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
gem.files = `git ls-files`.split("\n")
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
gem.require_paths = ['lib']
gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
end

0 comments on commit 5225b20

Please sign in to comment.