Updated spec environment. Working on digest authentication.

This commit is contained in:
Blake Watters
2011-03-14 21:12:37 -04:00
parent b22dd054b6
commit a400eb73f1
16 changed files with 2713 additions and 54 deletions

View File

@@ -1,7 +1,7 @@
source "http://rubygems.org"
gem "rake"
gem "uispecrunner", ">= 0.4.0"
gem "uispecrunner", ">= 0.4.2"
gem "bundler", "~> 1.0.0"
gem "sinatra", ">= 1.2.0"
gem "shotgun", ">= 0.9"

View File

@@ -16,7 +16,7 @@ GEM
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
tilt (1.2.2)
uispecrunner (0.4.0)
uispecrunner (0.4.2)
open4 (= 1.0.1)
PLATFORMS
@@ -28,7 +28,7 @@ DEPENDENCIES
shotgun (>= 0.9)
sinatra (>= 1.2.0)
thin (>= 1.2.8)
uispecrunner (>= 0.4.0)
uispecrunner (>= 0.4.2)
METADATA
version: 1.0.6

View File

@@ -167,6 +167,8 @@
259D53B8132854A900897272 /* RKSpecResponseLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 259D5135132854A700897272 /* RKSpecResponseLoader.m */; };
259D5535132854A900897272 /* UISpec+UISpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 259D53A2132854A800897272 /* UISpec+UISpecRunner.m */; };
259D5558132856D800897272 /* libUISpec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 259D5557132856D700897272 /* libUISpec.a */; };
259D56B5132E706D00897272 /* RKAuthenticationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 259D56B4132E706D00897272 /* RKAuthenticationSpec.m */; };
259D56BC132E84B300897272 /* RKSpecEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 259D56BB132E84B300897272 /* RKSpecEnvironment.m */; };
3F032A7910FFB89100F35142 /* RKCat.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F032A7810FFB89100F35142 /* RKCat.m */; };
3F032AA810FFBBCD00F35142 /* RKHouse.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F032AA710FFBBCD00F35142 /* RKHouse.m */; };
3F032AAB10FFBC1F00F35142 /* RKResident.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F032AAA10FFBC1F00F35142 /* RKResident.m */; };
@@ -463,6 +465,8 @@
259D53A2132854A800897272 /* UISpec+UISpecRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UISpec+UISpecRunner.m"; sourceTree = "<group>"; };
259D5548132856A400897272 /* UISpec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UISpec.xcodeproj; path = UISpec/xcode/UISpec/UISpec.xcodeproj; sourceTree = "<group>"; };
259D5557132856D700897272 /* libUISpec.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libUISpec.a; sourceTree = SOURCE_ROOT; };
259D56B4132E706D00897272 /* RKAuthenticationSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKAuthenticationSpec.m; sourceTree = "<group>"; };
259D56BB132E84B300897272 /* RKSpecEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKSpecEnvironment.m; sourceTree = "<group>"; };
25E075981279D9AB00B22EC9 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
3F032A7710FFB89100F35142 /* RKCat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKCat.h; sourceTree = "<group>"; };
3F032A7810FFB89100F35142 /* RKCat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKCat.m; sourceTree = "<group>"; };
@@ -917,6 +921,7 @@
259D51111328547000897272 /* RKParamsAttachmentSpec.m */,
259D51121328547000897272 /* RKRequestSpec.m */,
259D51131328547000897272 /* RKResponseSpec.m */,
259D56B4132E706D00897272 /* RKAuthenticationSpec.m */,
);
path = Network;
sourceTree = "<group>";
@@ -953,6 +958,7 @@
259D53A1132854A800897272 /* UISpec+UISpecRunner.h */,
259D53A2132854A800897272 /* UISpec+UISpecRunner.m */,
259D5557132856D700897272 /* libUISpec.a */,
259D56BB132E84B300897272 /* RKSpecEnvironment.m */,
);
path = Runner;
sourceTree = "<group>";
@@ -1496,6 +1502,8 @@
259D53B6132854A900897272 /* main.m in Sources */,
259D53B8132854A900897272 /* RKSpecResponseLoader.m in Sources */,
259D5535132854A900897272 /* UISpec+UISpecRunner.m in Sources */,
259D56B5132E706D00897272 /* RKAuthenticationSpec.m in Sources */,
259D56BC132E84B300897272 /* RKSpecEnvironment.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1886,9 +1894,9 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/UIKit.framework/Headers/UIKit.h";
HEADER_SEARCH_PATHS = (
Build,
Specs/Runner/OCMock/Headers,
Specs/Runner/UISpec/headers,
Build,
);
INFOPLIST_FILE = "Specs/Runner/UISpec-Info.plist";
INSTALL_PATH = "$(HOME)/Applications";
@@ -1924,9 +1932,9 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/UIKit.framework/Headers/UIKit.h";
HEADER_SEARCH_PATHS = (
Build,
Specs/Runner/OCMock/Headers,
Specs/Runner/UISpec/headers,
Build,
);
INFOPLIST_FILE = "Specs/Runner/UISpec-Info.plist";
INSTALL_PATH = "$(HOME)/Applications";

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,6 @@
//
#import "RKSpecEnvironment.h"
#import "RKObjectManager.h"
#import "RKHuman.h"
@interface RKManagedObjectSpec : NSObject <UISpec> {

View File

@@ -0,0 +1,63 @@
//
// RKAuthenticationSpec.m
// RestKit
//
// Created by Blake Watters on 3/14/11.
// Copyright 2011 Two Toasters. All rights reserved.
//
#import "RKSpecEnvironment.h"
#import "RKClient.h"
static NSString* const RKAuthenticationSpecUsername = @"restkit";
static NSString* const RKAuthenticationSpecPassword = @"authentication";
@interface RKAuthenticationSpec : NSObject <UISpec> {
}
@end
@implementation RKAuthenticationSpec
- (void)itShouldAccessUnprotectedResourcePaths {
RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader];
RKClient* client = [RKClient clientWithBaseURL:RKSpecGetBaseURL()];
[client get:@"/authentication/none" delegate:loader];
[loader waitForResponse];
[expectThat([loader.response isOK]) should:be(YES)];
}
- (void)itShouldAuthenticateViaHTTPAuthBasic {
RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader];
RKClient* client = [RKClient clientWithBaseURL:RKSpecGetBaseURL()];
client.username = RKAuthenticationSpecUsername;
client.password = RKAuthenticationSpecPassword;
[client get:@"/authentication/basic" delegate:loader];
[loader waitForResponse];
[expectThat([loader.response isOK]) should:be(YES)];
}
- (void)itShouldFailAuthenticationWithInvalidCredentialsForHTTPAuthBasic {
RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader];
RKClient* client = [RKClient clientWithBaseURL:RKSpecGetBaseURL()];
client.username = RKAuthenticationSpecUsername;
client.password = @"INVALID";
[client get:@"/authentication/basic" delegate:loader];
[loader waitForResponse];
[expectThat([loader.response isOK]) should:be(NO)];
[expectThat([loader.response statusCode]) should:be(0)];
[expectThat([loader.failureError code]) should:be(NSURLErrorUserCancelledAuthentication)];
}
- (void)itShouldAuthenticateViaHTTPAuthDigest {
RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader];
RKClient* client = [RKClient clientWithBaseURL:RKSpecGetBaseURL()];
client.username = RKAuthenticationSpecUsername;
client.password = RKAuthenticationSpecPassword;
[client get:@"/authentication/digest" delegate:loader];
[loader waitForResponse];
[expectThat([loader.response isOK]) should:be(YES)];
}
@end

View File

@@ -7,7 +7,6 @@
//
#import "RKSpecEnvironment.h"
#import <RestKit/RestKit.h>
@interface RKClientSpec : NSObject <UISpec> {
}

View File

@@ -7,10 +7,7 @@
//
#import "RKSpecEnvironment.h"
#import "RKDynamicRouter.h"
#import "RKHuman.h"
#import "RKObjectManager.h"
#import "RKManagedObjectStore.h"
@interface RKDynamicRouterSpec : NSObject <UISpec> {
}

View File

@@ -12,11 +12,15 @@
#import "UIExpectation.h"
#import <OCMock/OCMock.h>
//#import <RestKit/RestKit.h>
//#import <RestKit/CoreData/CoreData.h>
#import "RestKit.h"
#import "RKSpecResponseLoader.h"
////////////////////////////////////////////////////////////////////////////
// OCMock - For some reason this macro is incorrect. Note the use of __typeof
#undef OCMOCK_VALUE
#define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof(variable))]
// The Base URL for the Spec server. See Specs/Server/
NSString* RKSpecGetBaseURL();

View File

@@ -0,0 +1,18 @@
//
// RKSpecEnvironment.m
// RestKit
//
// Created by Blake Watters on 3/14/11.
// Copyright 2011 Two Toasters. All rights reserved.
//
#import "RKSpecEnvironment.h"
NSString* RKSpecGetBaseURL() {
char* ipAddress = getenv("RESTKIT_IP_ADDRESS");
if (NULL == ipAddress) {
ipAddress = "localhost";
}
return [NSString stringWithFormat:@"http://%s:4567", ipAddress];
}

View File

@@ -32,6 +32,9 @@
@property (nonatomic, assign) NSTimeInterval timeout;
// Return a new auto-released loader
+ (RKSpecResponseLoader*)responseLoader;
// Wait for a response to load
- (void)waitForResponse;
- (void)loadResponse:(id)response;

View File

@@ -17,10 +17,14 @@
@synthesize success = _success;
@synthesize timeout = _timeout;
+ (RKSpecResponseLoader*)responseLoader {
return [[[self alloc] init] autorelease];
}
- (id)init {
self = [super init];
if (self) {
_timeout = 100;
_timeout = 3;
_awaitingResponse = NO;
}
@@ -54,16 +58,29 @@
_success = YES;
}
- (void)loadError:(NSError*)error {
NSLog(@"Error: %@", error);
_awaitingResponse = NO;
_success = NO;
_failureError = [error retain];
}
- (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response {
NSLog(@"Loaded response: %@", response);
[self loadResponse:response];
}
- (void)request:(RKRequest *)request didFailLoadWithError:(NSError *)error {
[self loadError:error];
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
NSLog(@"Response: %@", [objectLoader.response bodyAsString]);
[self loadResponse:objects];
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error; {
NSLog(@"Error: %@", error);
_awaitingResponse = NO;
_success = NO;
_failureError = [error retain];
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error; {
[self loadError:error];
}
@end

View File

@@ -0,0 +1,2 @@
require 'restkit/network/authentication'
require 'restkit/object_mapping/model'

View File

@@ -0,0 +1,50 @@
module RestKit
module Network
class Authentication < Sinatra::Base
AUTH_USERNAME = 'restkit'
AUTH_PASSWORD = 'authentication'
helpers do
def protected!
unless authorized?
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
def authorized?
@auth ||= Rack::Auth::Basic::Request.new(request.env)
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['admin', 'admin']
end
end
get '/authentication/none' do
"Success!"
end
get '/authentication/basic' do
@auth ||= Rack::Auth::Basic::Request.new(request.env)
unless @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [AUTH_USERNAME, AUTH_PASSWORD]
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
get '/authentication/digest' do
# TODO..
@auth = Rack::Auth::Digest::Request.new(request.env)
unless @auth.provided? && @auth.digest? && @auth.credentials && @auth.credentials == [AUTH_USERNAME, AUTH_PASSWORD]
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
# do |username|
# username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil
#end
# app.realm = realm
# app.opaque = 'this-should-be-secret'
# app.passwords_hashed = true
end
end
end
end

View File

@@ -0,0 +1,25 @@
# TODO: Move this out somewhere/somehow...
# Replace with ActiveModel or something???
class Model
def self.attributes(*attributes)
@attributes ||= []
@attributes += attributes
attributes.each { |attr| attr_accessor attr }
end
def self.defined_attributes
@attributes
end
def initialize(options = {})
options.each { |k,v| self.send("#{k}=", v) }
end
def to_hash
self.class.defined_attributes.inject({}) { |hash, attr| hash[attr] = self.send(attr); hash }
end
def to_json
JSON.generate(self.to_hash)
end
end

View File

@@ -2,53 +2,36 @@
# RestKit Spec Server
require 'rubygems'
require 'sinatra'
#require 'sinatra'
require 'sinatra/base'
require 'json'
require 'ruby-debug'
Debugger.start
# TODO: Push the lib directory onto the include path...
# Import the RestKit Spec server
$: << File.join(File.expand_path(File.dirname(__FILE__)), 'lib')
require 'restkit'
# TODO: Move this out somewhere/somehow...
# Replace with ActiveModel or something???
class Model
def self.attributes(*attributes)
@attributes ||= []
@attributes += attributes
attributes.each { |attr| attr_accessor attr }
end
def self.defined_attributes
@attributes
end
def initialize(options = {})
options.each { |k,v| self.send("#{k}=", v) }
end
def to_hash
self.class.defined_attributes.inject({}) { |hash, attr| hash[attr] = self.send(attr); hash }
end
def to_json
JSON.generate(self.to_hash)
end
end
# TODO: Factor me out...
class Human < Model
attributes :id, :name, :sex, :age, :birthday, :created_at, :updated_at
end
class RestKit::SpecServer < Sinatra::Base
self.app_file = __FILE__
use RestKit::Network::Authentication
configure do
set :logging, true
set :dump_errors, true
end
post '/photo' do
content_type 'application/json'
"OK"
end
# TODO: Move to object_mapping dir
get '/humans/1' do
content_type 'application/json'
JSON.generate(:human => Human.new(:name => 'Blake Watters').to_hash)
@@ -58,14 +41,6 @@ class RestKit::SpecServer < Sinatra::Base
content_type 'application/json'
JSON.generate([{:human => Human.new(:name => 'Blake Watters').to_hash}, {:human => Human.new(:name => "Other").to_hash}])
end
# TODO: Factor these out...
get '/authentication/basic' do
end
get '/authentication/digest' do
end
# start the server if ruby file executed directly
run! if app_file == $0