abstract_auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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