summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzul <azul@riseup.net>2016-05-01 10:55:33 -0300
committerAzul <azul@riseup.net>2016-05-18 20:07:41 +0200
commite05a1b0f5ae40a2aa17976b3009cd563b8e4660a (patch)
tree77774fd7e70211febaf3a15c6e3b3e7340843c11
parenta1b494e334406660a1f49fb7de9b043493809640 (diff)
api: allow version bumping - bump to 2
-rw-r--r--app/controllers/api/certs_controller.rb (renamed from app/controllers/v1/certs_controller.rb)2
-rw-r--r--app/controllers/api/configs_controller.rb (renamed from app/controllers/v1/configs_controller.rb)2
-rw-r--r--app/controllers/api/identities_controller.rb (renamed from app/controllers/v1/identities_controller.rb)2
-rw-r--r--app/controllers/api/messages_controller.rb (renamed from app/controllers/v1/messages_controller.rb)2
-rw-r--r--app/controllers/api/services_controller.rb (renamed from app/controllers/v1/services_controller.rb)2
-rw-r--r--app/controllers/api/sessions_controller.rb (renamed from app/controllers/v1/sessions_controller.rb)2
-rw-r--r--app/controllers/api/smtp_certs_controller.rb (renamed from app/controllers/v1/smtp_certs_controller.rb)2
-rw-r--r--app/controllers/api/users_controller.rb (renamed from app/controllers/v1/users_controller.rb)2
-rw-r--r--app/views/api/sessions/new.json.erb (renamed from app/views/v1/sessions/new.json.erb)0
-rw-r--r--config/routes.rb6
-rw-r--r--test/functional/api/certs_controller_test.rb (renamed from test/functional/v1/certs_controller_test.rb)2
-rw-r--r--test/functional/api/identities_controller_test.rb (renamed from test/functional/v1/identities_controller_test.rb)2
-rw-r--r--test/functional/api/messages_controller_test.rb (renamed from test/functional/v1/messages_controller_test.rb)2
-rw-r--r--test/functional/api/services_controller_test.rb (renamed from test/functional/v1/services_controller_test.rb)2
-rw-r--r--test/functional/api/sessions_controller_test.rb (renamed from test/functional/v1/sessions_controller_test.rb)2
-rw-r--r--test/functional/api/smtp_certs_controller_test.rb (renamed from test/functional/v1/smtp_certs_controller_test.rb)2
-rw-r--r--test/functional/api/token_auth_test.rb (renamed from test/functional/configs_controller_with_static_tokens_test.rb)4
-rw-r--r--test/functional/api/users_controller_test.rb (renamed from test/functional/v1/users_controller_test.rb)2
-rw-r--r--test/integration/api/cert_test.rb11
-rw-r--r--test/integration/api/signup_test.rb2
-rw-r--r--test/integration/api/smtp_cert_test.rb14
-rw-r--r--test/integration/api/srp_test.rb18
-rw-r--r--test/integration/api/token_auth_test.rb2
-rw-r--r--test/integration/api/update_account_test.rb2
-rw-r--r--test/integration/browser/account_livecycle_test.rb.orig153
-rw-r--r--test/integration/browser/security_test.rb2
-rw-r--r--test/support/api_integration_test.rb4
27 files changed, 211 insertions, 37 deletions
diff --git a/app/controllers/v1/certs_controller.rb b/app/controllers/api/certs_controller.rb
index ffa6e35..46a84d3 100644
--- a/app/controllers/v1/certs_controller.rb
+++ b/app/controllers/api/certs_controller.rb
@@ -1,4 +1,4 @@
-class V1::CertsController < ApiController
+class Api::CertsController < ApiController
before_filter :require_login, :unless => :anonymous_access_allowed?
before_filter :require_enabled
diff --git a/app/controllers/v1/configs_controller.rb b/app/controllers/api/configs_controller.rb
index f0b284e..55ceb4f 100644
--- a/app/controllers/v1/configs_controller.rb
+++ b/app/controllers/api/configs_controller.rb
@@ -1,4 +1,4 @@
-class V1::ConfigsController < ApiController
+class Api::ConfigsController < ApiController
include ControllerExtension::JsonFile
before_filter :require_login, :unless => :anonymous_access_allowed?
diff --git a/app/controllers/v1/identities_controller.rb b/app/controllers/api/identities_controller.rb
index 4efd1f5..ab2ac00 100644
--- a/app/controllers/v1/identities_controller.rb
+++ b/app/controllers/api/identities_controller.rb
@@ -1,4 +1,4 @@
-module V1
+module Api
class IdentitiesController < ApiController
before_filter :token_authenticate
before_filter :require_monitor
diff --git a/app/controllers/v1/messages_controller.rb b/app/controllers/api/messages_controller.rb
index c0ca0c7..a69a40a 100644
--- a/app/controllers/v1/messages_controller.rb
+++ b/app/controllers/api/messages_controller.rb
@@ -1,4 +1,4 @@
-module V1
+module Api
class MessagesController < ApiController
before_filter :require_login
diff --git a/app/controllers/v1/services_controller.rb b/app/controllers/api/services_controller.rb
index 523eb44..da2774b 100644
--- a/app/controllers/v1/services_controller.rb
+++ b/app/controllers/api/services_controller.rb
@@ -1,4 +1,4 @@
-class V1::ServicesController < ApiController
+class Api::ServicesController < ApiController
before_filter :require_login, :unless => :anonymous_access_allowed?
diff --git a/app/controllers/v1/sessions_controller.rb b/app/controllers/api/sessions_controller.rb
index a343d9b..c8deb7a 100644
--- a/app/controllers/v1/sessions_controller.rb
+++ b/app/controllers/api/sessions_controller.rb
@@ -1,4 +1,4 @@
-module V1
+module Api
class SessionsController < ApiController
before_filter :require_login, only: :destroy
diff --git a/app/controllers/v1/smtp_certs_controller.rb b/app/controllers/api/smtp_certs_controller.rb
index 5760645..d9eab7d 100644
--- a/app/controllers/v1/smtp_certs_controller.rb
+++ b/app/controllers/api/smtp_certs_controller.rb
@@ -1,4 +1,4 @@
-class V1::SmtpCertsController < ApiController
+class Api::SmtpCertsController < ApiController
before_filter :require_login
before_filter :require_email_account
diff --git a/app/controllers/v1/users_controller.rb b/app/controllers/api/users_controller.rb
index 6640d10..e64d21f 100644
--- a/app/controllers/v1/users_controller.rb
+++ b/app/controllers/api/users_controller.rb
@@ -1,4 +1,4 @@
-module V1
+module Api
class UsersController < ApiController
include ControllerExtension::FetchUser
diff --git a/app/views/v1/sessions/new.json.erb b/app/views/api/sessions/new.json.erb
index 36154b8..36154b8 100644
--- a/app/views/v1/sessions/new.json.erb
+++ b/app/views/api/sessions/new.json.erb
diff --git a/config/routes.rb b/config/routes.rb
index be3b3be..a1a5b3c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -24,10 +24,10 @@ LeapWeb::Application.routes.draw do
get '/provider.json' => 'static_config#provider'
- namespace "api", { module: "v1",
- path: "/1/",
+ namespace "api", { module: "api",
+ path: "/:version/",
defaults: {format: 'json'},
- :constraints => { :id => /[^\/]+(?=\.json\z)|[^\/]+/ }
+ :constraints => { :id => /[^\/]+(?=\.json\z)|[^\/]+/, :version => /[12]/ }
} do
resources :sessions, :only => [:new, :create, :update]
delete "logout" => "sessions#destroy", :as => "logout"
diff --git a/test/functional/v1/certs_controller_test.rb b/test/functional/api/certs_controller_test.rb
index 04c1c86..137ed92 100644
--- a/test/functional/v1/certs_controller_test.rb
+++ b/test/functional/api/certs_controller_test.rb
@@ -1,6 +1,6 @@
require_relative '../../test_helper'
-class V1::CertsControllerTest < ActionController::TestCase
+class Api::CertsControllerTest < ActionController::TestCase
test "create unlimited cert without login" do
with_config allow_anonymous_certs: true do
diff --git a/test/functional/v1/identities_controller_test.rb b/test/functional/api/identities_controller_test.rb
index 6410c44..e803ee7 100644
--- a/test/functional/v1/identities_controller_test.rb
+++ b/test/functional/api/identities_controller_test.rb
@@ -1,6 +1,6 @@
require_relative '../../test_helper'
-class V1::IdentitiesControllerTest < ActionController::TestCase
+class Api::IdentitiesControllerTest < ActionController::TestCase
test "api monitor can fetch identity" do
monitor_auth do
diff --git a/test/functional/v1/messages_controller_test.rb b/test/functional/api/messages_controller_test.rb
index f37cca0..01641d4 100644
--- a/test/functional/v1/messages_controller_test.rb
+++ b/test/functional/api/messages_controller_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class V1::MessagesControllerTest < ActionController::TestCase
+class Api::MessagesControllerTest < ActionController::TestCase
setup do
@user = FactoryGirl.build(:user)
diff --git a/test/functional/v1/services_controller_test.rb b/test/functional/api/services_controller_test.rb
index 039eb27..b1dc9f3 100644
--- a/test/functional/v1/services_controller_test.rb
+++ b/test/functional/api/services_controller_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class V1::ServicesControllerTest < ActionController::TestCase
+class Api::ServicesControllerTest < ActionController::TestCase
test "anonymous user gets login required service info" do
get :show, format: :json
diff --git a/test/functional/v1/sessions_controller_test.rb b/test/functional/api/sessions_controller_test.rb
index 8bb6acd..0633578 100644
--- a/test/functional/v1/sessions_controller_test.rb
+++ b/test/functional/api/sessions_controller_test.rb
@@ -3,7 +3,7 @@ require 'test_helper'
# This is a simple controller unit test.
# We're stubbing out both warden and srp.
# There's an integration test testing the full rack stack and srp
-class V1::SessionsControllerTest < ActionController::TestCase
+class Api::SessionsControllerTest < ActionController::TestCase
setup do
@request.env['HTTP_HOST'] = 'api.lvh.me'
diff --git a/test/functional/v1/smtp_certs_controller_test.rb b/test/functional/api/smtp_certs_controller_test.rb
index 1b03995..2142675 100644
--- a/test/functional/v1/smtp_certs_controller_test.rb
+++ b/test/functional/api/smtp_certs_controller_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class V1::SmtpCertsControllerTest < ActionController::TestCase
+class Api::SmtpCertsControllerTest < ActionController::TestCase
test "no smtp cert without login" do
with_config allow_anonymous_certs: true do
diff --git a/test/functional/configs_controller_with_static_tokens_test.rb b/test/functional/api/token_auth_test.rb
index 79739fe..17a4775 100644
--- a/test/functional/configs_controller_with_static_tokens_test.rb
+++ b/test/functional/api/token_auth_test.rb
@@ -5,8 +5,8 @@
require 'test_helper'
-class ConfigsControllerWithStaticTokensTest < ActionController::TestCase
- tests V1::ConfigsController
+class Api::TokenAuthTest < ActionController::TestCase
+ tests Api::ConfigsController
def test_login_via_api_token
with_config(:allow_anonymous_certs => false) do
diff --git a/test/functional/v1/users_controller_test.rb b/test/functional/api/users_controller_test.rb
index 3f7bad3..bc2e312 100644
--- a/test/functional/v1/users_controller_test.rb
+++ b/test/functional/api/users_controller_test.rb
@@ -1,6 +1,6 @@
require_relative '../../test_helper'
-class V1::UsersControllerTest < ActionController::TestCase
+class Api::UsersControllerTest < ActionController::TestCase
test "user can change settings" do
user = find_record :user
diff --git a/test/integration/api/cert_test.rb b/test/integration/api/cert_test.rb
index 772901d..289d3c6 100644
--- a/test/integration/api/cert_test.rb
+++ b/test/integration/api/cert_test.rb
@@ -5,7 +5,7 @@ class CertTest < ApiIntegrationTest
test "retrieve eip cert" do
login
- get '/1/cert', {}, RACK_ENV
+ get cert_url, {}, RACK_ENV
assert_text_response
assert_response_includes "BEGIN RSA PRIVATE KEY"
assert_response_includes "END RSA PRIVATE KEY"
@@ -14,13 +14,13 @@ class CertTest < ApiIntegrationTest
end
test "fetching certs requires login by default" do
- get '/1/cert', {}, RACK_ENV
+ get cert_url, {}, RACK_ENV
assert_login_required
end
test "retrieve anonymous eip cert" do
with_config allow_anonymous_certs: true do
- get '/1/cert', {}, RACK_ENV
+ get cert_url, {}, RACK_ENV
assert_text_response
assert_response_includes "BEGIN RSA PRIVATE KEY"
assert_response_includes "END RSA PRIVATE KEY"
@@ -28,4 +28,9 @@ class CertTest < ApiIntegrationTest
assert_response_includes "END CERTIFICATE"
end
end
+
+ def cert_url
+ "/#{api_version}/cert"
+ end
+
end
diff --git a/test/integration/api/signup_test.rb b/test/integration/api/signup_test.rb
index 7216496..dc24420 100644
--- a/test/integration/api/signup_test.rb
+++ b/test/integration/api/signup_test.rb
@@ -1,4 +1,4 @@
-require_relative '../../test_helper'
+require 'test_helper'
require_relative 'srp_test'
class SignupTest < SrpTest
diff --git a/test/integration/api/smtp_cert_test.rb b/test/integration/api/smtp_cert_test.rb
index 681d509..53382c1 100644
--- a/test/integration/api/smtp_cert_test.rb
+++ b/test/integration/api/smtp_cert_test.rb
@@ -11,7 +11,7 @@ class SmtpCertTest < ApiIntegrationTest
test "retrieve smtp cert" do
@user = FactoryGirl.create :user, effective_service_level_code: 2, :invite_code => @testcode.invite_code
login
- post '/1/smtp_cert', {}, RACK_ENV
+ post smtp_cert_url, {}, RACK_ENV
assert_text_response
assert_response_includes "BEGIN RSA PRIVATE KEY"
assert_response_includes "END RSA PRIVATE KEY"
@@ -22,7 +22,7 @@ class SmtpCertTest < ApiIntegrationTest
test "cert and key" do
@user = FactoryGirl.create :user, effective_service_level_code: 2, :invite_code => @testcode.invite_code
login
- post '/1/smtp_cert', {}, RACK_ENV
+ post smtp_cert_url, {}, RACK_ENV
assert_text_response
cert = OpenSSL::X509::Certificate.new(get_response.body)
key = OpenSSL::PKey::RSA.new(get_response.body)
@@ -34,7 +34,7 @@ class SmtpCertTest < ApiIntegrationTest
test "fingerprint is stored with identity" do
@user = FactoryGirl.create :user, effective_service_level_code: 2, :invite_code => @testcode.invite_code
login
- post '/1/smtp_cert', {}, RACK_ENV
+ post smtp_cert_url, {}, RACK_ENV
assert_text_response
cert = OpenSSL::X509::Certificate.new(get_response.body)
fingerprint = OpenSSL::Digest::SHA1.hexdigest(cert.to_der).scan(/../).join(':')
@@ -48,14 +48,18 @@ class SmtpCertTest < ApiIntegrationTest
test "fetching smtp certs requires email account" do
login
- post '/1/smtp_cert', {}, RACK_ENV
+ post smtp_cert_url, {}, RACK_ENV
assert_access_denied
end
test "no anonymous smtp certs" do
with_config allow_anonymous_certs: true do
- post '/1/smtp_cert', {}, RACK_ENV
+ post smtp_cert_url, {}, RACK_ENV
assert_login_required
end
end
+
+ def smtp_cert_url
+ "/#{api_version}/smtp_cert"
+ end
end
diff --git a/test/integration/api/srp_test.rb b/test/integration/api/srp_test.rb
index 463abcd..b9605f9 100644
--- a/test/integration/api/srp_test.rb
+++ b/test/integration/api/srp_test.rb
@@ -14,7 +14,7 @@ class SrpTest < RackTest
# this test wraps the api and implements the interface the ruby-srp client.
def handshake(login, aa)
- post "http://api.lvh.me:3000/1/sessions.json",
+ post api_url("sessions.json"),
:login => login,
'A' => aa,
:format => :json
@@ -27,7 +27,7 @@ class SrpTest < RackTest
end
def validate(m)
- put "http://api.lvh.me:3000/1/sessions/" + @login + '.json',
+ put api_url("sessions/#{@login}.json"),
:client_auth => m,
:format => :json
return JSON.parse(last_response.body)
@@ -39,7 +39,7 @@ class SrpTest < RackTest
def register_user(login = "integration_test", password = 'srp, verify me!', invite_code = @testcode.invite_code)
cleanup_user(login)
- post 'http://api.lvh.me:3000/1/users.json',
+ post api_url('users.json'),
user_params(login: login, password: password, invite_code: invite_code)
assert(@user = User.find_by_login(login), 'user should have been created: %s' % last_response_errors)
@login = login
@@ -47,7 +47,7 @@ class SrpTest < RackTest
end
def update_user(params)
- put "http://api.lvh.me:3000/1/users/" + @user.id + '.json',
+ put api_url("users/#{@user.id}.json"),
user_params(params),
auth_headers
end
@@ -68,7 +68,7 @@ class SrpTest < RackTest
end
def logout(params=nil, headers=nil)
- delete "http://api.lvh.me:3000/1/logout.json",
+ delete api_url("logout.json"),
params || {format: :json},
headers || auth_headers
end
@@ -112,4 +112,12 @@ class SrpTest < RackTest
rescue
""
end
+
+ def api_url(path)
+ "http://api.lvh.me:3000/#{api_version}/#{path}"
+ end
+
+ def api_version
+ 2
+ end
end
diff --git a/test/integration/api/token_auth_test.rb b/test/integration/api/token_auth_test.rb
index 3b83f23..7b20b00 100644
--- a/test/integration/api/token_auth_test.rb
+++ b/test/integration/api/token_auth_test.rb
@@ -1,4 +1,4 @@
-require_relative '../../test_helper'
+require 'test_helper'
require_relative 'srp_test'
class TokenAuthTest < SrpTest
diff --git a/test/integration/api/update_account_test.rb b/test/integration/api/update_account_test.rb
index 16bbb8c..1492006 100644
--- a/test/integration/api/update_account_test.rb
+++ b/test/integration/api/update_account_test.rb
@@ -14,7 +14,7 @@ class UpdateAccountTest < SrpTest
test "require token" do
authenticate
- put "http://api.lvh.me:3000/1/users/" + @user.id + '.json',
+ put "http://api.lvh.me:3000/2/users/" + @user.id + '.json',
user_params(password: "No! Verify me instead.")
assert_login_required
end
diff --git a/test/integration/browser/account_livecycle_test.rb.orig b/test/integration/browser/account_livecycle_test.rb.orig
new file mode 100644
index 0000000..d1f800b
--- /dev/null
+++ b/test/integration/browser/account_livecycle_test.rb.orig
@@ -0,0 +1,153 @@
+require 'test_helper'
+
+class AccountLivecycleTest < BrowserIntegrationTest
+
+ teardown do
+ Identity.destroy_all_orphaned
+ end
+
+ test "signup successfully when invited" do
+ username, password = submit_signup
+ assert page.has_content?("Welcome #{username}")
+ click_on 'Log Out'
+ assert page.has_content?("Log In")
+ assert_equal '/', current_path
+ assert user = User.find_by_login(username)
+ user.account.destroy
+ end
+
+ test "signup successfully without invitation" do
+ with_config invite_required: false do
+
+ username ||= "test_#{SecureRandom.urlsafe_base64}".downcase
+ password ||= SecureRandom.base64
+
+ visit '/users/new'
+ fill_in 'Username', with: username
+ fill_in 'Password', with: password
+ fill_in 'Password confirmation', with: password
+ click_on 'Sign Up'
+
+ assert page.has_content?("Welcome #{username}")
+ end
+ end
+
+ test "signup with username ending in dot json" do
+ username = Faker::Internet.user_name + '.json'
+ submit_signup username
+ assert page.has_content?("Welcome #{username}")
+ end
+
+ test "signup with reserved username" do
+ username = 'certmaster'
+ submit_signup username
+ assert page.has_content?("is reserved.")
+ end
+
+ test "successful login" do
+ username, password = submit_signup
+ click_on 'Log Out'
+ attempt_login(username, password)
+ assert page.has_content?("Welcome #{username}")
+ within('.sidenav li.active') do
+ assert page.has_content?("Overview")
+ end
+ User.find_by_login(username).account.destroy
+ end
+
+ test "failed login" do
+ visit '/'
+ attempt_login("username", "wrong password")
+ assert_invalid_login(page)
+ end
+
+ test "account destruction" do
+ username, password = submit_signup
+
+ click_on I18n.t('account_settings')
+ click_on I18n.t('destroy_my_account')
+ assert page.has_content?(I18n.t('account_destroyed'))
+ assert_equal 1, Identity.by_address.key("#{username}@test.me").count
+ attempt_login(username, password)
+ assert_invalid_login(page)
+ end
+
+ test "handle blocked after account destruction" do
+ username, password = submit_signup
+ click_on I18n.t('account_settings')
+ click_on I18n.t('destroy_my_account')
+ submit_signup(username)
+ assert page.has_content?('has already been taken')
+ end
+
+ test "change pgp key" do
+ with_config user_actions: ['change_pgp_key'] do
+ pgp_key = FactoryGirl.build :pgp_key
+ login
+ click_on "Account Settings"
+ within('#update_pgp_key') do
+ fill_in 'Public key', with: pgp_key
+ click_on 'Save'
+ end
+ page.assert_selector 'input[value="Saving..."]'
+ # at some point we're done:
+ page.assert_no_selector 'input[value="Saving..."]'
+ assert page.has_field? 'Public key', with: pgp_key.to_s
+ @user.reload
+ assert_equal pgp_key, @user.public_key
+ end
+ end
+
+<<<<<<< HEAD:test/integration/browser/account_livecycle_test.rb
+=======
+
+ # trying to seed an invalid A for srp login
+ test "detects attempt to circumvent SRP" do
+ InviteCodeValidator.any_instance.stubs(:validate)
+
+ user = FactoryGirl.create :user
+ visit '/login'
+ fill_in 'Username', with: user.login
+ fill_in 'Password', with: "password"
+ inject_malicious_js
+ click_on 'Log In'
+ assert page.has_content?("Invalid random key")
+ assert page.has_no_content?("Welcome")
+ user.destroy
+ end
+
+ test "reports internal server errors" do
+ Api::UsersController.any_instance.stubs(:create).raises
+ submit_signup
+ assert page.has_content?("server failed")
+ end
+
+ test "does not render signup form without js" do
+ Capybara.current_driver = :rack_test # no js
+ visit '/signup'
+ assert page.has_no_content?("Username")
+ assert page.has_no_content?("Password")
+ end
+
+ test "does not render login form without js" do
+ Capybara.current_driver = :rack_test # no js
+ visit '/login'
+ assert page.has_no_content?("Username")
+ assert page.has_no_content?("Password")
+ end
+
+>>>>>>> api: allow version bumping - bump to 2:test/integration/browser/account_test.rb
+ def attempt_login(username, password)
+ click_on 'Log In'
+ fill_in 'Username', with: username
+ fill_in 'Password', with: password
+ click_on 'Log In'
+ end
+
+ def assert_invalid_login(page)
+ assert page.has_selector? '.btn-primary.disabled'
+ assert page.has_content? I18n.t(:invalid_user_pass)
+ assert page.has_no_selector? '.btn-primary.disabled'
+ end
+
+end
diff --git a/test/integration/browser/security_test.rb b/test/integration/browser/security_test.rb
index c13acd8..825d50b 100644
--- a/test/integration/browser/security_test.rb
+++ b/test/integration/browser/security_test.rb
@@ -22,7 +22,7 @@ class SecurityTest < BrowserIntegrationTest
end
test "reports internal server errors" do
- V1::UsersController.any_instance.stubs(:create).raises
+ Api::UsersController.any_instance.stubs(:create).raises
submit_signup
assert page.has_content?("server failed")
end
diff --git a/test/support/api_integration_test.rb b/test/support/api_integration_test.rb
index 3b3481b..cea480c 100644
--- a/test/support/api_integration_test.rb
+++ b/test/support/api_integration_test.rb
@@ -3,6 +3,10 @@ class ApiIntegrationTest < ActionDispatch::IntegrationTest
DUMMY_TOKEN = Token.new
RACK_ENV = {'HTTP_AUTHORIZATION' => %Q(Token token="#{DUMMY_TOKEN.to_s}")}
+ def api_version
+ 2
+ end
+
setup do
@testcode = InviteCode.new
@testcode.save!