alterego 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Guardfile +21 -0
- data/README.rdoc +36 -8
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/alterego.gemspec +69 -0
- data/lib/alterego.rb +78 -1
- data/spec/alterego/alterego_spec.rb +48 -3
- data/spec/alterego/fixtures/error.json +6 -0
- data/spec/spec_helper.rb +5 -0
- metadata +22 -20
- data/lib/alterego/api.rb +0 -12
data/Guardfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
14
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
watch('config/routes.rb') { "spec/routing" }
|
17
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
18
|
+
# Capybara request specs
|
19
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
20
|
+
end
|
21
|
+
|
data/README.rdoc
CHANGED
@@ -1,22 +1,50 @@
|
|
1
1
|
= AlterEgo
|
2
2
|
|
3
|
-
AlterEgo is a Ruby gem for
|
4
|
-
|
5
|
-
== Requirements
|
6
|
-
|
7
|
-
You will need an {AlterEgo}[https://alteregoapp.com] account. More detailed instructions about generating API keys and granting access here...
|
3
|
+
AlterEgo is a Ruby gem for integrating {AlterEgo}[https://alteregoapp.com] two-factor authentication into your web application. You'll need an {AlterEgo account}[https://alteregoapp.com/#signupfree] in order to register your {register your app}[https://alteregoapp.com/app/register] and get your "App Authentication ID".
|
8
4
|
|
9
5
|
== Installation
|
10
6
|
|
11
7
|
(sudo) gem install alterego
|
12
8
|
|
13
|
-
==
|
9
|
+
== Authorizing Your Application
|
10
|
+
|
11
|
+
In order to use AlterEgo, users of your application will need to sign up for their own {AlterEgo account}[https://alteregoapp.com/#signupfree]. You will need your users to authorize the connection between your application and {AlterEgo}[https://alteregoapp.com] by simply redirecting them:
|
12
|
+
|
13
|
+
redirect_to AlterEgo.authorization_url("your_app_id", "https://yourapp.com/alterego/callback")
|
14
|
+
|
15
|
+
{AlterEgo}[https://alteregoapp.com] imposes the following requirements on the +redirect_url+ value to ensure security. Be sure that your +redirect_url+ meets the following requirements:
|
16
|
+
|
17
|
+
- Must be served via HTTPS.
|
18
|
+
- Must be under the same domain (or a subdomain of) the website entered when registering your application with {AlterEgo}[https://alteregoapp.com].
|
19
|
+
|
20
|
+
Once authorized successfully, a POST request will be sent to the +redirect_url+ with a "key" parameter containing the API key for that user's {AlterEgo}[https://alteregoapp.com] account. Be sure to store this key somewhere, as you will need it to run API requests later. If authorization fails for some reason, an "error" parameter will be present in the POST request, containing an error message.
|
21
|
+
|
22
|
+
if params[:key]
|
23
|
+
current_user.alter_ego_key = params[:key]
|
24
|
+
elsif params[:error]
|
25
|
+
flash[:alert] = params[:error]
|
26
|
+
end
|
27
|
+
|
28
|
+
== Authenticating With AlterEgo
|
29
|
+
|
30
|
+
Once your users have authorized your application and you have retrieved an API key for their account, you can easily integrate two-factor authentication. To authenticate using {AlterEgo}[https://alteregoapp.com] (either as part of an existing login process, or as a stand-alone authentication system) simply prompt the user to input a valid {AlterEgo}[https://alteregoapp.com] passcode and verify it:
|
31
|
+
|
32
|
+
passcode = params[:alter_ego_passcode]
|
33
|
+
if AlterEgo.password(current_user.alter_ego_key, passcode)
|
34
|
+
# Passcode is valid.
|
35
|
+
...
|
36
|
+
else
|
37
|
+
# Passcode is not valid.
|
38
|
+
...
|
39
|
+
end
|
14
40
|
|
15
|
-
|
41
|
+
{AlterEgo}[https://alteregoapp.com] does not provide any kind of error message or explanation as to why a passcode is not valid, so you will want to be sure and keep your error messages appropriately generic.
|
16
42
|
|
17
|
-
|
43
|
+
== Pinging The API
|
18
44
|
|
45
|
+
The {AlterEgo}[https://alteregoapp.com] API also has a method for pinging the API, in case you want to periodically check to ensure that your user's API keys are still valid. A successful ping to the API will always return "PONG!" as a response.
|
19
46
|
|
47
|
+
AlterEgo.ping(current_user.alter_ego_api_key)
|
20
48
|
|
21
49
|
== Contributing to AlterEgo
|
22
50
|
|
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ Jeweler::Tasks.new do |gem|
|
|
18
18
|
gem.homepage = "http://github.com/terra-firma/alterego"
|
19
19
|
gem.license = "MIT"
|
20
20
|
gem.summary = %Q{Ruby gem for interacting with the AlterEgo API.}
|
21
|
-
gem.description = %Q{AlterEgo is a Ruby gem
|
21
|
+
gem.description = %Q{AlterEgo is a Ruby gem for integrating two-factor authentication into your web application.}
|
22
22
|
gem.email = "brian@terra-firma-design.com"
|
23
23
|
gem.authors = ["Brian Getting"]
|
24
24
|
# dependencies defined in Gemfile
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/alterego.gemspec
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{alterego}
|
8
|
+
s.version = "0.0.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Brian Getting}]
|
12
|
+
s.date = %q{2011-10-17}
|
13
|
+
s.description = %q{AlterEgo is a Ruby gem for integrating two-factor authentication into your web application.}
|
14
|
+
s.email = %q{brian@terra-firma-design.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Guardfile",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"alterego.gemspec",
|
28
|
+
"lib/alterego.rb",
|
29
|
+
"spec/alterego/alterego_spec.rb",
|
30
|
+
"spec/alterego/fixtures/error.json",
|
31
|
+
"spec/spec_helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/terra-firma/alterego}
|
34
|
+
s.licenses = [%q{MIT}]
|
35
|
+
s.require_paths = [%q{lib}]
|
36
|
+
s.rubygems_version = %q{1.8.8}
|
37
|
+
s.summary = %q{Ruby gem for interacting with the AlterEgo API.}
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
s.specification_version = 3
|
41
|
+
|
42
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
44
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
45
|
+
s.add_development_dependency(%q<fakeweb>, [">= 0"])
|
46
|
+
s.add_development_dependency(%q<guard-rspec>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
48
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
49
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<json>, [">= 0"])
|
52
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
54
|
+
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
55
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
56
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<json>, [">= 0"])
|
61
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
63
|
+
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
64
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
65
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
66
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/lib/alterego.rb
CHANGED
@@ -3,4 +3,81 @@ require 'uri'
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'json'
|
5
5
|
|
6
|
-
|
6
|
+
class AlterEgo
|
7
|
+
|
8
|
+
API_URL = "https://alteregoapp.com/api"
|
9
|
+
AUTH_URL = "http://alteregoapp.com/account/authorize-app"
|
10
|
+
|
11
|
+
# Generate an AlterEgo +authorization_url+.
|
12
|
+
# Returns a URL to redirect users to so that they will be prompted
|
13
|
+
# to enter their AlterEgo username and password to authorize a
|
14
|
+
# connection between your application and their AlterEgo account.
|
15
|
+
#
|
16
|
+
# If authorized successfully, a POST request will be sent to the
|
17
|
+
# +redirect_url+ with a "key" parameter containing the API key for
|
18
|
+
# that user's AlterEgo account. Be sure to store this key somewhere,
|
19
|
+
# as you will need it to run API requests later.
|
20
|
+
#
|
21
|
+
# If authorization fails for some reason, an "error" parameter will
|
22
|
+
# be present in the POST request, containing an error message.
|
23
|
+
#
|
24
|
+
# == A note about callback URL's:
|
25
|
+
#
|
26
|
+
# AlterEgo imposes the following requirements on the +redirect_url+ value
|
27
|
+
# to ensure security. Be sure that your +redirect_url+ meets the following
|
28
|
+
# requirements:
|
29
|
+
#
|
30
|
+
# - Must be served via HTTPS.
|
31
|
+
# - Must be under the same domain (or a subdomain of) the website entered
|
32
|
+
# when registering your application with AlterEgo.
|
33
|
+
#
|
34
|
+
# == Example
|
35
|
+
#
|
36
|
+
# redirect_to AlterEgo.authorization_url("12345","https://example.com/callback")
|
37
|
+
#
|
38
|
+
def self.authorization_url(app_id, redirect_url)
|
39
|
+
# TODO: Encode the redirect_url.
|
40
|
+
"#{AUTH_URL}?id=#{app_id}&redirect_url=#{URI.escape(redirect_url, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Ping the AlterEgo API.
|
44
|
+
# Returns either "PONG!" (indicating a successful connection to the API) or
|
45
|
+
# an error.
|
46
|
+
#
|
47
|
+
# == Example
|
48
|
+
#
|
49
|
+
# AlterEgo.ping("valid_api_key")
|
50
|
+
#
|
51
|
+
def self.ping(key)
|
52
|
+
call("#{API_URL}/check/ping.json?key=#{key}")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Check an AlterEgo passcode.
|
56
|
+
# Returns +true+ if the passcode if valid, and +false+ if the passcode is not
|
57
|
+
# valid.
|
58
|
+
#
|
59
|
+
# == Example
|
60
|
+
#
|
61
|
+
# AlterEgo.password("valid_api_key", "passcode")
|
62
|
+
#
|
63
|
+
def self.password(key, passcode)
|
64
|
+
call("#{API_URL}/check/password.json?key=#{key}&pass=#{passcode}")
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def self.call(url) # :nodoc:
|
70
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
71
|
+
raise AlterEgo::APIError.new(response.body) if response.code.to_i == 500
|
72
|
+
return nil if response.body == ''
|
73
|
+
response.body
|
74
|
+
end
|
75
|
+
|
76
|
+
class APIError < StandardError
|
77
|
+
def initialize(response) # :nodoc:
|
78
|
+
error = JSON.parse(response)
|
79
|
+
super "<#{error['code']}> #{error['name']}: #{error['message']}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -1,7 +1,52 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
describe API do
|
3
|
+
describe AlterEgo do
|
5
4
|
|
5
|
+
describe "authorization_url" do
|
6
|
+
it "should require an app_id and redirect_url" do
|
7
|
+
expect {AlterEgo.authorization_url}.should raise_error(ArgumentError)
|
8
|
+
expect {AlterEgo.authorization_url(@app_id)}.should raise_error(ArgumentError)
|
9
|
+
expect {AlterEgo.authorization_url(@app_id, @callback_url)}.should_not raise_error(ArgumentError)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should generate an authorization URL" do
|
13
|
+
@callback_url = 'https://test.com/callback'
|
14
|
+
url = AlterEgo.authorization_url(@app_id, @callback_url)
|
15
|
+
url.should eq("#{AlterEgo::AUTH_URL}?id=#{@app_id}&redirect_url=#{URI.escape(@callback_url, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "API" do
|
20
|
+
API_URL = "http://alteregoapp.com:443/api/check"
|
21
|
+
|
22
|
+
it "should require a key when pinging" do
|
23
|
+
expect {AlterEgo.ping}.should raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return 'PONG!' when pinging successfully" do
|
27
|
+
FakeWeb.register_uri(:get, "#{API_URL}/ping.json?key=#{@api_key}", :body => "PONG!")
|
28
|
+
AlterEgo.ping(@api_key).should eq("PONG!")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should require a key and passcode when checking password" do
|
32
|
+
expect {AlterEgo.password}.should raise_error(ArgumentError)
|
33
|
+
expect {AlterEgo.password(@api_key)}.should raise_error(ArgumentError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return true when the passcode matches" do
|
37
|
+
FakeWeb.register_uri(:get, "#{API_URL}/password.json?key=#{@api_key}&pass=#{@passcode}", :body => "true")
|
38
|
+
AlterEgo.password(@api_key, @passcode).should eq("true")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return false when the passcode doesn't match" do
|
42
|
+
FakeWeb.register_uri(:get, "#{API_URL}/password.json?key=#{@api_key}&pass=#{@passcode}", :body => "false")
|
43
|
+
AlterEgo.password(@api_key, @passcode).should eq("false")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should respond to 500 errors from the API" do
|
47
|
+
FakeWeb.register_uri(:get, "#{API_URL}/password.json?key=#{@api_key}&pass=#{@passcode}", :body => @error, :status => ["500", "Internal Server Error"])
|
48
|
+
expect {AlterEgo.password(@api_key, @passcode)}.should raise_error(AlterEgo::APIError)
|
49
|
+
end
|
6
50
|
end
|
7
|
-
|
51
|
+
|
52
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,5 +6,10 @@ FakeWeb.allow_net_connect = false
|
|
6
6
|
RSpec.configure do |config|
|
7
7
|
config.before(:each) do
|
8
8
|
FakeWeb.clean_registry
|
9
|
+
@app_id = 'valid-app-id'
|
10
|
+
@api_key = 'valid-api-key'
|
11
|
+
@callback_url = 'https://example.com/callback'
|
12
|
+
@passcode = 'alter-ego-passcode'
|
13
|
+
@error = File.read(File.expand_path('spec/alterego/fixtures/error.json'))
|
9
14
|
end
|
10
15
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alterego
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &2153522520 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2153522520
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &2153520800 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.0.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2153520800
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: fakeweb
|
38
|
-
requirement: &
|
38
|
+
requirement: &2153518960 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2153518960
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: guard-rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &2153517220 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2153517220
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &2153515440 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.6.4
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2153515440
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &2153512980 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2153512980
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec
|
82
|
-
requirement: &
|
82
|
+
requirement: &2153510180 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,9 +87,9 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
91
|
-
description: AlterEgo is a Ruby gem
|
92
|
-
|
90
|
+
version_requirements: *2153510180
|
91
|
+
description: AlterEgo is a Ruby gem for integrating two-factor authentication into
|
92
|
+
your web application.
|
93
93
|
email: brian@terra-firma-design.com
|
94
94
|
executables: []
|
95
95
|
extensions: []
|
@@ -99,13 +99,15 @@ extra_rdoc_files:
|
|
99
99
|
files:
|
100
100
|
- .document
|
101
101
|
- Gemfile
|
102
|
+
- Guardfile
|
102
103
|
- LICENSE.txt
|
103
104
|
- README.rdoc
|
104
105
|
- Rakefile
|
105
106
|
- VERSION
|
107
|
+
- alterego.gemspec
|
106
108
|
- lib/alterego.rb
|
107
|
-
- lib/alterego/api.rb
|
108
109
|
- spec/alterego/alterego_spec.rb
|
110
|
+
- spec/alterego/fixtures/error.json
|
109
111
|
- spec/spec_helper.rb
|
110
112
|
homepage: http://github.com/terra-firma/alterego
|
111
113
|
licenses:
|
@@ -122,7 +124,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
124
|
version: '0'
|
123
125
|
segments:
|
124
126
|
- 0
|
125
|
-
hash:
|
127
|
+
hash: -3242706057364793623
|
126
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
129
|
none: false
|
128
130
|
requirements:
|