abstract_auth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .rvmrc
5
+ *.sw[a|o|p]
6
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in abstract_auth.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ abstract_auth (0.0.1)
5
+ module_ext (~> 0.1.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ module_ext (0.1.0)
11
+ rake (0.8.7)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ abstract_auth!
18
+ module_ext (~> 0.1.0)
19
+ rake (~> 0.8.7)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 Ryan Cook and Quick Left, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ #AbstractAuth
2
+
3
+ ##A Short Story
4
+ One day you, Sir Lucius Leftfoot, are hacking your little heart out, and
5
+ you realize that you're writing the same code over and over again to for
6
+ your clients. So, you think to yourself, "What if I packaged this up all
7
+ nice-like and set it free in the world for all the other knightly
8
+ developers to use in their apps?" Quickly, you realize that you can't go
9
+ calling...
10
+
11
+ current_user.role? :king_of_the_hood
12
+
13
+ ...all willy-nilly to make sure you're dealing with an administrator of
14
+ the host application, even though that's the API you're used to using.
15
+ What's one to do when the authentication procedures of the end-use host
16
+ application are unknown? Have no fear - AbstractAuth is here to save
17
+ you!
18
+
19
+ ##Use Case
20
+
21
+ AbstractAuth is for developers creating reusable components (e.g. Rails
22
+ 3 Engine gems) that require authentication information from their host
23
+ applications. It aims to provide a consistent and configurable API that
24
+ you, the component creator, can setup and use, which the developer of the
25
+ host application will need to implement, so that you can properly secure
26
+ your functionality.
27
+
28
+ ##How It Works
29
+
30
+ AbstractAuth works by allowing the developers implementing your tools to
31
+ specify code blocks that will be executed to produce the desired
32
+ response. The blocks are executed when you call them, and in the context
33
+ in which you call them.
34
+
35
+ ##Examples
36
+
37
+ AbstractAuth will only step in if you instruct it to. Therefore, by
38
+ default, nothing will happen. Oh, you wanted something to happen? Try
39
+ this somewhere in a setup area of your app...
40
+
41
+ # Your setup code defining the API you expect your users to implement
42
+ AbstractAuth.setup do |config|
43
+ config.requires :authenticated_resource
44
+ end
45
+
46
+ Then, when you need it, you should be able to call `AbstractAuth.authenticated_resource`
47
+ and expect the host application to have provided the code that will
48
+ return to you the resource object that is currently authenticated (e.g.
49
+ User). How do you go about making sure a host application complies with
50
+ your every whim? In a Rails application, for instance, you could
51
+ instruct them to setup an abstract_auth.rb initializer in `config/initializers`
52
+
53
+ # The user's implementation of your desired API
54
+ AbstractAuth.implement :authenticated_resource do
55
+ current_user
56
+ end
57
+
58
+ We'll hold on to that fancy block of code and execute it at the right
59
+ time so that we're returning you exactly what you need.
60
+
61
+ Maybe, you want to create a separate login page with access to a
62
+ super-secret web page. The part of the process that's different here is
63
+ how you instruct your users to implement the desired functionality.
64
+ Continuing the Rails application example, say you setup the following
65
+ in your code...
66
+
67
+ # Your setup code defining the API you expect your users to implement
68
+ AbstractAuth.setup do |config|
69
+ config.requires :authenticate_resource, :authenticated_resource
70
+ end
71
+
72
+ Thus, a developer might implement the following...
73
+
74
+ # The user's implementation of your desired API
75
+ AbstractAuth.implement :authenticated_resource do
76
+
77
+ # A fancy helper method in the host app
78
+ current_user
79
+
80
+ end
81
+
82
+ # The user's implementation of your desired API
83
+ # Note the arguments
84
+ AbstractAuth.implement :authenticate_resource do |username,password|
85
+
86
+ # Your user's custom authentication procedure
87
+ User.fancy_authenticate(username,password)
88
+
89
+ end
90
+
91
+ Assuming everything goes as planned, you would be able to call...
92
+
93
+ AbstractAuth.invoke( :authenticate_resource , username , password )
94
+
95
+ ...to determine whether a resource was authenticated.
96
+
97
+ Finally, if you make a call to expected API that the host app has not
98
+ implemented, an `AbstractAuth::NotImplementedError` will be thrown.
99
+
100
+ ##Notes
101
+
102
+ Remember above, when I said that AbstractAuth will, by default, not
103
+ intrude on your code unless you set it up to do so? I lied just a
104
+ little bit. AbstractAuth does require another gem called ModuleExt,
105
+ which monkey-patches the Module class to add some convenience
106
+ attributes functions. Don't be mad.
107
+
108
+ ##License
109
+
110
+ MIT. See the LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ desc 'Gotta run those tests'
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/*_test.rb'
10
+ t.verbose = true
11
+ end
12
+
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "abstract_auth/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "abstract_auth"
7
+ s.version = AbstractAuth::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ryan Cook"]
10
+ s.email = ["ryan@quickleft.com"]
11
+ s.homepage = "https://github.com/cookrn/abstract_auth"
12
+ s.summary = %q{A gem to safely provide external application resources with a coherent and configurable API to a host application's authentication procedures.}
13
+ s.description = %q{A gem to safely provide external application resources with a coherent and configurable API to a host application's authentication procedures.}
14
+
15
+ s.rubyforge_project = "abstract_auth"
16
+
17
+ s.add_dependency "module_ext", "~> 0.1.0"
18
+ s.add_development_dependency "rake", "~> 0.8.7"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
@@ -0,0 +1,21 @@
1
+ module AbstractAuth
2
+
3
+ def self.requires(*args)
4
+ args.each do |required_api|
5
+ raise AbstractAuth::Errors::MalformedRequirementError.new('You must define a requirement with a symbol!') unless required_api.is_a?(Symbol)
6
+ @@requirements.push required_api
7
+ end
8
+ end
9
+
10
+ def self.implement( requirement , &blk )
11
+ raise AbstractAuth::Errors::MalformedImplementationError.new('You must define an implementation with a symbol!') unless requirement.is_a?(Symbol)
12
+ @@implementations.merge!( { requirement => blk } )
13
+ end
14
+
15
+ def self.invoke( method , *args )
16
+ raise AbstractAuth::Errors::NonRequiredImplementationCallError.new('The requested implementation was not required!') unless @@requirements.include?(method)
17
+ raise AbstractAuth::Errors::NotImplementedError.new('The requirement was not implemented!') unless @@implementations.has_key?(method)
18
+ @@implementations[method].call(args)
19
+ end
20
+
21
+ end
@@ -0,0 +1,16 @@
1
+ module AbstractAuth
2
+
3
+ module Errors
4
+
5
+ class MalformedImplementationError < StandardError; end
6
+
7
+ class MalformedRequirementError < StandardError; end
8
+
9
+ class NonRequiredImplementationCallError < StandardError; end
10
+
11
+ class NotImplementedError < StandardError; end
12
+
13
+ end
14
+
15
+ end
16
+
@@ -0,0 +1,3 @@
1
+ module AbstractAuth
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # Requires
2
+ require 'module_ext'
3
+
4
+ module AbstractAuth
5
+
6
+ # Autoloads
7
+ autoload :Errors , 'abstract_auth/errors'
8
+
9
+ # Requires
10
+ require 'abstract_auth/abstract_auth'
11
+
12
+ # Define our container to hold implemented APIs
13
+ mattr_accessor :implementations
14
+ @@implementations = {}
15
+
16
+ # Define our container to hold APIs required to be implemented
17
+ mattr_accessor :requirements
18
+ @@requirements = []
19
+
20
+ # Yield AbstractAuth on setup for fancy configuration
21
+ def self.setup
22
+ yield self
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,89 @@
1
+ require 'test_helper'
2
+
3
+ class AbstractAuthTest < Test::Unit::TestCase
4
+
5
+ def test_yields_self_on_setup
6
+ AbstractAuth.setup do |config|
7
+ assert_equal AbstractAuth , config
8
+ end
9
+ end
10
+
11
+ def test_only_use_symbols_to_define_requirements
12
+ assert_raise AbstractAuth::Errors::MalformedRequirementError do
13
+ AbstractAuth.setup do |config|
14
+ config.requires "bad_def"
15
+ end
16
+ end
17
+ end
18
+
19
+ def test_only_use_symbols_to_define_implementations
20
+ assert_raise AbstractAuth::Errors::MalformedImplementationError do
21
+ AbstractAuth.implement "bad_def" do
22
+ p "don't do this"
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_can_add_a_requirement
28
+ AbstractAuth.setup do |config|
29
+ config.requires :authenticated_user
30
+ end
31
+ assert AbstractAuth.requirements.include? :authenticated_user
32
+ end
33
+
34
+ def test_can_add_multiple_requirements
35
+ AbstractAuth.setup do |config|
36
+ config.requires :authenticated_user, :authenticated_admin
37
+ end
38
+ assert AbstractAuth.requirements.include? :authenticated_user
39
+ assert AbstractAuth.requirements.include? :authenticated_admin
40
+ end
41
+
42
+ def test_can_add_implementation
43
+ AbstractAuth.requires :authenticated_user
44
+ AbstractAuth.implement :authenticated_user do
45
+ TestUser.new
46
+ end
47
+ assert AbstractAuth.implementations.has_key? :authenticated_user
48
+ assert AbstractAuth.implementations[:authenticated_user].is_a? Proc
49
+ end
50
+
51
+ def test_cannot_call_non_required_methods
52
+ assert_raise AbstractAuth::Errors::NonRequiredImplementationCallError do
53
+ AbstractAuth.invoke :not_required_method
54
+ end
55
+ end
56
+
57
+ def test_cannot_call_non_implemented_methods
58
+ assert_raise AbstractAuth::Errors::NotImplementedError do
59
+ AbstractAuth.requires :a_sample_method
60
+ AbstractAuth.invoke :a_sample_method
61
+ end
62
+ end
63
+
64
+ def test_can_invoke_requirement
65
+ AbstractAuth.requires :authenticate_user
66
+ AbstractAuth.implement :authenticate_user do |user_id,password|
67
+ return TestUser.new(user_id,password)
68
+ end
69
+ new_user = AbstractAuth.invoke( :authenticate_user , 'ronald' , 'macdonald' )
70
+ assert new_user.is_a? TestUser
71
+ assert_equal 'ronald' , new_user.username
72
+ assert_equal 'macdonald' , new_user.password
73
+ end
74
+
75
+ end
76
+
77
+ class TestUser
78
+ def initialize(username,password)
79
+ @username = username
80
+ @password = password
81
+ end
82
+ def username
83
+ @username
84
+ end
85
+ def password
86
+ @password
87
+ end
88
+ end
89
+
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+ require 'abstract_auth'
3
+
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abstract_auth
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Cook
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-11 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: module_ext
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 27
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 0
34
+ version: 0.1.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 49
46
+ segments:
47
+ - 0
48
+ - 8
49
+ - 7
50
+ version: 0.8.7
51
+ type: :development
52
+ version_requirements: *id002
53
+ description: A gem to safely provide external application resources with a coherent and configurable API to a host application's authentication procedures.
54
+ email:
55
+ - ryan@quickleft.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - abstract_auth.gemspec
70
+ - lib/abstract_auth.rb
71
+ - lib/abstract_auth/abstract_auth.rb
72
+ - lib/abstract_auth/errors.rb
73
+ - lib/abstract_auth/version.rb
74
+ - test/abstract_auth_test.rb
75
+ - test/test_helper.rb
76
+ has_rdoc: true
77
+ homepage: https://github.com/cookrn/abstract_auth
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options: []
82
+
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ requirements: []
104
+
105
+ rubyforge_project: abstract_auth
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: A gem to safely provide external application resources with a coherent and configurable API to a host application's authentication procedures.
110
+ test_files:
111
+ - test/abstract_auth_test.rb
112
+ - test/test_helper.rb