Permalink
Browse files

added additional tests, removed validator and replaced with validatab…

…le mix in
  • Loading branch information...
1 parent fd181a3 commit 208001b6b2fcafa79e057c9fa45e596f7c819038 @aeden aeden committed Aug 4, 2008
View
8 README
@@ -1,7 +1,13 @@
+== About
+
RSAML is a SAML implementation in Ruby. RSAML currently implements the elements defined in the SAML-Core 2.0 specification by defining an object model that mimics the structure of SAML. Method names and attributes have been made ruby-friendly and documentation is provided for each class and method. In certain cases the SAML specification is referenced directly and should be considered the final say whenever a question arises regarding SAML implementation.
Concrete requests:
* RSAML::Protocol::Query::AuthnQuery (Authentication query)
* RSAML::Protocol::Query::AttributeQuery (Attribute query)
-* RSAML::Protocol::Query::AuthzDecisionQuery (Authorization query)
+* RSAML::Protocol::Query::AuthzDecisionQuery (Authorization query)
+
+== A note on the implementation
+
+RSAML is implemented in a very verbose fashion. While there are probably ways to reduce the code footprint using meta programming and other Rubyisms, I've attempted to stick to an implementation style that is easy to follow for non-rubyists and rubyists alike. Additionally I am striving for a comprehensive test suite that can be used to verify conformance to the SAML 2.0 specification.
View
@@ -20,7 +20,7 @@
require 'rsaml/ext/string'
require 'rsaml/encrypted'
-require 'rsaml/validator'
+require 'rsaml/validatable'
require 'rsaml/errors'
require 'rsaml/action'
@@ -12,7 +12,7 @@ def self.namespaces
'Read','Write','Execute','Delete','Control','~Read','~Write','~Execute','~Delete','~Control'
]),
:ghpp => ActionNamespace.new('urn:oasis:names:tc:SAML:1.0:action:ghpp', [
- 'Get','Head','Put','Post'
+ 'GET','HEAD','PUT','POST'
]),
:unix => UnixActionNamespace.new
}
View
@@ -2,6 +2,7 @@ module RSAML #:nodoc:
# Contains any additional information that the SAML authority wishes to provide. This information MAY be
# ignored by applications without affecting either the semantics or the validity of the assertion.
class Advice
+ include Validatable
# Contains a mixture of zero or more Assertion, EncryptedAssertion, assertion IDs, and assertion URIs.
# May also contain custom objects that produce namespace-qualified XML for non-SAML elements.
def assertions
View
@@ -45,6 +45,8 @@ def to_xml(xml=Builder::XmlMarkup.new)
# An assertion is a package of information that supplies zero or more statements made by a SAML
# authority.
class Assertion
+ include Validatable
+
# SAML assertions are usually made about a subject, however the subject is optional
attr_accessor :subject
@@ -109,11 +111,6 @@ def assert
end
end
- # Return true if the assertion is structurally valid
- def valid?
- Validator.valid?(self)
- end
-
# Validate the assertion. This validates the structural integrity of the assertion, not the
# validity of the assertion itself. To "assert" the assertion use the assert method.
def validate
View
@@ -0,0 +1,21 @@
+module RSAML
+ # Module that can be mixed in to any class to provide a :valid? method. This method
+ # will look for a :validate method and invoke it, catching any ValidationError exceptions
+ # and return either true if the SAML object is structurally valid or false if it isn't.
+ module Validatable
+ attr_accessor :verbose
+ # Return true if the object is valid. Only objects with a validate method will
+ # be checked for validity.
+ def valid?
+ if respond_to?(:validate)
+ begin
+ validate
+ rescue ValidationError => e
+ puts "Validation failed: #{e.message}" if verbose
+ return false
+ end
+ end
+ return true
+ end
+ end
+end
View
@@ -1,24 +0,0 @@
-module RSAML #:nodoc:
- # The validator class provides a valid? method that will invoke the validate
- # method on the target object and rescue a ValidationError. If a ValidationError
- # is raised then this method will return false, otherwise it will return true.
- class Validator
- class << self
- attr_accessor :verbose
- end
-
- # Return true if the object is valid. Only objects with a validate method will
- # be checked for validity.
- def self.valid?(o)
- if o.respond_to?(:validate)
- begin
- o.validate
- rescue ValidationError => e
- puts "Validation failed: #{e.message}" if verbose
- return false
- end
- end
- return true
- end
- end
-end
@@ -1,44 +1,74 @@
require File.dirname(__FILE__) + '/test_helper'
class ActionNamespaceTest < Test::Unit::TestCase
+ context "the ActionNamespace class" do
+ should "define all of the namespaces in the SAML 2.0 specification" do
+ namespace_uris = ActionNamespace.namespaces.values.collect { |ns| ns.uri }
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:rwedc')
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:rwedc-negation')
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:ghpp')
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:unix')
+ end
+ end
context "the rwdec namespace" do
setup do
@action_namespace = ActionNamespace.namespaces[:rwedc]
+ @expected_actions = ['Read','Write','Execute','Delete','Control']
end
should "have the correct uri" do
assert_equal 'urn:oasis:names:tc:SAML:1.0:action:rwedc', @action_namespace.uri
end
+ should "return the uri when to_s is invoked" do
+ assert_equal @action_namespace.uri, @action_namespace.to_s
+ end
should "have the correct actions" do
- assert_equal [
- 'Read','Write','Execute','Delete','Control'
- ], @action_namespace.action_names
+ assert_equal @expected_actions, @action_namespace.action_names
+ end
+ should "return true for a valid action" do
+ @expected_actions.each do |action|
+ assert @action_namespace.valid_action?(action)
+ end
+ end
+ should "return false for an invalid action" do
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
end
end
context "the rwdec-negation namespace" do
setup do
@action_namespace = ActionNamespace.namespaces[:rwedc_negation]
+ @expected_actions = [
+ 'Read','Write','Execute','Delete','Control',
+ '~Read','~Write','~Execute','~Delete','~Control'
+ ]
end
should "have the correct uri" do
assert_equal 'urn:oasis:names:tc:SAML:1.0:action:rwedc-negation', @action_namespace.uri
end
should "have the correct actions" do
- assert_equal [
- 'Read','Write','Execute','Delete','Control',
- '~Read','~Write','~Execute','~Delete','~Control'
- ], @action_namespace.action_names
+ assert_equal @expected_actions, @action_namespace.action_names
+ end
+ should "return true for a valid action" do
+ @expected_actions.each do |action|
+ assert @action_namespace.valid_action?(action)
+ end
+ end
+ should "return false for an invalid action" do
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
end
end
context "the ghpp namespace" do
setup do
@action_namespace = ActionNamespace.namespaces[:ghpp]
+ @expected_actions = ['GET','HEAD','PUT','POST']
end
should "have the correct uri" do
assert_equal 'urn:oasis:names:tc:SAML:1.0:action:ghpp', @action_namespace.uri
end
should "have the correct actions" do
- assert_equal [
- 'Get','Head','Put','Post'
- ], @action_namespace.action_names
+ assert_equal @expected_actions, @action_namespace.action_names
+ end
+ should "return false for an invalid action" do
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
end
end
context "the unix file permissions namespace" do
@@ -48,6 +78,8 @@ class ActionNamespaceTest < Test::Unit::TestCase
should "have the correct uri" do
assert_equal 'urn:oasis:names:tc:SAML:1.0:action:unix', @action_namespace.uri
end
- should_eventually "have the correct actions"
+ should_eventually "have the correct actions" do
+
+ end
end
end
View
@@ -13,5 +13,19 @@ class ActionTest < Test::Unit::TestCase
assert_match(/<saml:Action Namespace="#{@action.namespace}"/, @action.to_xml)
end
end
+ context "when validating" do
+ should "raise an error if no value is provided" do
+ assert_raise ValidationError do
+ @action.value = nil
+ @action.validate
+ end
+ end
+ should "raise an error if the value is not in the specified namespace" do
+ assert_raise ValidationError do
+ @action.value = 'PUT'
+ @action.validate
+ end
+ end
+ end
end
end
View
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class AdviceTest < Test::Unit::TestCase
+ context "an advice" do
+ setup { @advice = Advice.new }
+ should "have 0 assertions by default" do
+ assert @advice.assertions.empty?
+ end
+ should "be valid if all assertions are valid" do
+ assert @advice.valid?
+ end
+ context "when producing xml" do
+ should "produce an empty advice tag when there are no assertions" do
+ assert_match(/<saml:Advice><\/saml:Advice>/, @advice.to_xml)
+ end
+ end
+ end
+end

0 comments on commit 208001b

Please sign in to comment.