doorkeeper-2.2.1/ 0000755 0000764 0000764 00000000000 12544753400 012713 5 ustar pravi pravi doorkeeper-2.2.1/spec/ 0000755 0000764 0000764 00000000000 12544753400 013645 5 ustar pravi pravi doorkeeper-2.2.1/spec/spec_helper.rb 0000644 0000764 0000764 00000000242 12544753400 016461 0 ustar pravi pravi $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../lib'))
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../app'))
doorkeeper-2.2.1/spec/factories.rb 0000644 0000764 0000764 00000001167 12544753400 016156 0 ustar pravi pravi FactoryGirl.define do
factory :access_grant, class: Doorkeeper::AccessGrant do
sequence(:resource_owner_id) { |n| n }
application
redirect_uri 'https://app.com/callback'
expires_in 100
scopes 'public write'
end
factory :access_token, class: Doorkeeper::AccessToken do
sequence(:resource_owner_id) { |n| n }
application
expires_in 2.hours
factory :clientless_access_token do
application nil
end
end
factory :application, class: Doorkeeper::Application do
sequence(:name) { |n| "Application #{n}" }
redirect_uri 'https://app.com/callback'
end
factory :user
end
doorkeeper-2.2.1/spec/routing/ 0000755 0000764 0000764 00000000000 12544753400 015334 5 ustar pravi pravi doorkeeper-2.2.1/spec/routing/scoped_routes_spec.rb 0000644 0000764 0000764 00000002262 12544753400 021553 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Scoped routes' do
it 'GET /scope/authorize routes to authorizations controller' do
expect(get('/scope/authorize')).to route_to('doorkeeper/authorizations#new')
end
it 'POST /scope/authorize routes to authorizations controller' do
expect(post('/scope/authorize')).to route_to('doorkeeper/authorizations#create')
end
it 'DELETE /scope/authorize routes to authorizations controller' do
expect(delete('/scope/authorize')).to route_to('doorkeeper/authorizations#destroy')
end
it 'POST /scope/token routes to tokens controller' do
expect(post('/scope/token')).to route_to('doorkeeper/tokens#create')
end
it 'GET /scope/applications routes to applications controller' do
expect(get('/scope/applications')).to route_to('doorkeeper/applications#index')
end
it 'GET /scope/authorized_applications routes to authorized applications controller' do
expect(get('/scope/authorized_applications')).to route_to('doorkeeper/authorized_applications#index')
end
it 'GET /scope/token/info route to authorzed tokeninfo controller' do
expect(get('/scope/token/info')).to route_to('doorkeeper/token_info#show')
end
end
doorkeeper-2.2.1/spec/routing/custom_controller_routes_spec.rb 0000644 0000764 0000764 00000005447 12544753400 024063 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Custom controller for routes' do
it 'GET /space/scope/authorize routes to custom authorizations controller' do
expect(get('/inner_space/scope/authorize')).to route_to('custom_authorizations#new')
end
it 'POST /space/scope/authorize routes to custom authorizations controller' do
expect(post('/inner_space/scope/authorize')).to route_to('custom_authorizations#create')
end
it 'DELETE /space/scope/authorize routes to custom authorizations controller' do
expect(delete('/inner_space/scope/authorize')).to route_to('custom_authorizations#destroy')
end
it 'POST /space/scope/token routes to tokens controller' do
expect(post('/inner_space/scope/token')).to route_to('custom_authorizations#create')
end
it 'GET /space/scope/applications routes to applications controller' do
expect(get('/inner_space/scope/applications')).to route_to('custom_authorizations#index')
end
it 'GET /space/scope/token/info routes to the token_info controller' do
expect(get('/inner_space/scope/token/info')).to route_to('custom_authorizations#show')
end
it 'GET /space/oauth/authorize routes to custom authorizations controller' do
expect(get('/space/oauth/authorize')).to route_to('custom_authorizations#new')
end
it 'POST /space/oauth/authorize routes to custom authorizations controller' do
expect(post('/space/oauth/authorize')).to route_to('custom_authorizations#create')
end
it 'DELETE /space/oauth/authorize routes to custom authorizations controller' do
expect(delete('/space/oauth/authorize')).to route_to('custom_authorizations#destroy')
end
it 'POST /space/oauth/token routes to tokens controller' do
expect(post('/space/oauth/token')).to route_to('custom_authorizations#create')
end
it 'POST /space/oauth/revoke routes to tokens controller' do
expect(post('/space/oauth/revoke')).to route_to('custom_authorizations#revoke')
end
it 'GET /space/oauth/applications routes to applications controller' do
expect(get('/space/oauth/applications')).to route_to('custom_authorizations#index')
end
it 'GET /space/oauth/token/info routes to the token_info controller' do
expect(get('/space/oauth/token/info')).to route_to('custom_authorizations#show')
end
it 'POST /outer_space/oauth/token is not be routable' do
expect(post('/outer_space/oauth/token')).not_to be_routable
end
it 'GET /outer_space/oauth/authorize routes to custom authorizations controller' do
expect(get('/outer_space/oauth/authorize')).to be_routable
end
it 'GET /outer_space/oauth/applications is not routable' do
expect(get('/outer_space/oauth/applications')).not_to be_routable
end
it 'GET /outer_space/oauth/token_info is not routable' do
expect(get('/outer_space/oauth/token/info')).not_to be_routable
end
end
doorkeeper-2.2.1/spec/routing/default_routes_spec.rb 0000644 0000764 0000764 00000002475 12544753400 021730 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Default routes' do
it 'GET /oauth/authorize routes to authorizations controller' do
expect(get('/oauth/authorize')).to route_to('doorkeeper/authorizations#new')
end
it 'POST /oauth/authorize routes to authorizations controller' do
expect(post('/oauth/authorize')).to route_to('doorkeeper/authorizations#create')
end
it 'DELETE /oauth/authorize routes to authorizations controller' do
expect(delete('/oauth/authorize')).to route_to('doorkeeper/authorizations#destroy')
end
it 'POST /oauth/token routes to tokens controller' do
expect(post('/oauth/token')).to route_to('doorkeeper/tokens#create')
end
it 'POST /oauth/revoke routes to tokens controller' do
expect(post('/oauth/revoke')).to route_to('doorkeeper/tokens#revoke')
end
it 'GET /oauth/applications routes to applications controller' do
expect(get('/oauth/applications')).to route_to('doorkeeper/applications#index')
end
it 'GET /oauth/authorized_applications routes to authorized applications controller' do
expect(get('/oauth/authorized_applications')).to route_to('doorkeeper/authorized_applications#index')
end
it 'GET /oauth/token/info route to authorzed tokeninfo controller' do
expect(get('/oauth/token/info')).to route_to('doorkeeper/token_info#show')
end
end
doorkeeper-2.2.1/spec/spec_helper_integration.rb 0000644 0000764 0000764 00000003306 12544753400 021070 0 ustar pravi pravi ENV['RAILS_ENV'] ||= 'test'
TABLE_NAME_PREFIX = ENV['table_name_prefix'] || nil
TABLE_NAME_SUFFIX = ENV['table_name_suffix'] || nil
orm = (ENV['BUNDLE_GEMFILE'] || '').match(/Gemfile\.(.+)\.rb/)
DOORKEEPER_ORM = (orm && orm[1] || :active_record).to_sym
$LOAD_PATH.unshift File.dirname(__FILE__)
require 'capybara/rspec'
require 'rspec/active_model/mocks'
require 'dummy/config/environment'
require 'rspec/rails'
require 'generator_spec/test_case'
require 'timecop'
require 'database_cleaner'
require 'pry'
Rails.logger.info "====> Doorkeeper.orm = #{Doorkeeper.configuration.orm.inspect}"
if Doorkeeper.configuration.orm == :active_record
Rails.logger.info "======> active_record.table_name_prefix = #{Rails.configuration.active_record.table_name_prefix.inspect}"
Rails.logger.info "======> active_record.table_name_suffix = #{Rails.configuration.active_record.table_name_suffix.inspect}"
end
Rails.logger.info "====> Rails version: #{Rails.version}"
Rails.logger.info "====> Ruby version: #{RUBY_VERSION}"
if [:mongoid2, :mongoid3, :mongoid4].include?(DOORKEEPER_ORM)
require "support/orm/mongoid"
else
require "support/orm/#{DOORKEEPER_ORM}"
end
ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../')
Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].each { |f| require f }
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
config.mock_with :rspec
config.infer_base_class_for_anonymous_controllers = false
config.include RSpec::Rails::RequestExampleGroup, type: :request
config.before do
DatabaseCleaner.start
Doorkeeper.configure { orm DOORKEEPER_ORM }
end
config.after do
DatabaseCleaner.clean
end
config.order = 'random'
end
doorkeeper-2.2.1/spec/requests/ 0000755 0000764 0000764 00000000000 12544753400 015520 5 ustar pravi pravi doorkeeper-2.2.1/spec/requests/applications/ 0000755 0000764 0000764 00000000000 12544753400 020206 5 ustar pravi pravi doorkeeper-2.2.1/spec/requests/applications/authorized_applications_spec.rb 0000644 0000764 0000764 00000001720 12544753400 026471 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Authorized applications' do
background do
@user = User.create!(name: 'Joe', password: 'sekret')
@client = client_exists(name: 'Amazing Client App')
resource_owner_is_authenticated @user
client_is_authorized @client, @user
end
scenario 'display user\'s authorized applications' do
visit '/oauth/authorized_applications'
i_should_see 'Amazing Client App'
end
scenario 'do not display other user\'s authorized applications' do
client = client_exists(name: 'Another Client App')
client_is_authorized client, User.create!(name: 'Joe', password: 'sekret')
visit '/oauth/authorized_applications'
i_should_not_see 'Another Client App'
end
scenario 'user revoke access to application' do
visit '/oauth/authorized_applications'
i_should_see 'Amazing Client App'
click_on 'Revoke'
i_should_see 'Application revoked'
i_should_not_see 'Amazing Client App'
end
end
doorkeeper-2.2.1/spec/requests/applications/applications_request_spec.rb 0000644 0000764 0000764 00000004452 12544753400 026010 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Adding applications' do
context 'in application form' do
background do
visit '/oauth/applications/new'
end
scenario 'adding a valid app' do
fill_in 'doorkeeper_application[name]', with: 'My Application'
fill_in 'doorkeeper_application[redirect_uri]',
with: 'https://example.com'
click_button 'Submit'
i_should_see 'Application created'
i_should_see 'My Application'
end
scenario 'adding invalid app' do
click_button 'Submit'
i_should_see 'Whoops! Check your form for possible errors'
end
end
end
feature 'Listing applications' do
background do
FactoryGirl.create :application, name: 'Oauth Dude'
FactoryGirl.create :application, name: 'Awesome App'
end
scenario 'application list' do
visit '/oauth/applications'
i_should_see 'Awesome App'
i_should_see 'Oauth Dude'
end
end
feature 'Show application' do
given :app do
FactoryGirl.create :application, name: 'Just another oauth app'
end
scenario 'visiting application page' do
visit "/oauth/applications/#{app.id}"
i_should_see 'Just another oauth app'
end
end
feature 'Edit application' do
let :app do
FactoryGirl.create :application, name: 'OMG my app'
end
background do
visit "/oauth/applications/#{app.id}/edit"
end
scenario 'updating a valid app' do
fill_in 'doorkeeper_application[name]', with: 'Serious app'
click_button 'Submit'
i_should_see 'Application updated'
i_should_see 'Serious app'
i_should_not_see 'OMG my app'
end
scenario 'updating an invalid app' do
fill_in 'doorkeeper_application[name]', with: ''
click_button 'Submit'
i_should_see 'Whoops! Check your form for possible errors'
end
end
feature 'Remove application' do
background do
@app = FactoryGirl.create :application
end
scenario 'deleting an application from list' do
visit '/oauth/applications'
i_should_see @app.name
within(:css, "tr#application_#{@app.id}") do
click_button 'Destroy'
end
i_should_see 'Application deleted'
i_should_not_see @app.name
end
scenario 'deleting an application from show' do
visit "/oauth/applications/#{@app.id}"
click_button 'Destroy'
i_should_see 'Application deleted'
end
end
doorkeeper-2.2.1/spec/requests/flows/ 0000755 0000764 0000764 00000000000 12544753400 016652 5 ustar pravi pravi doorkeeper-2.2.1/spec/requests/flows/implicit_grant_spec.rb 0000644 0000764 0000764 00000003422 12544753400 023217 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Implicit Grant Flow (feature spec)' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
config_is_set(:grant_flows, ["implicit"])
client_exists
create_resource_owner
sign_in
end
scenario 'resource owner authorizes the client' do
visit authorization_endpoint_url(client: @client, response_type: 'token')
click_on 'Authorize'
access_token_should_exist_for @client, @resource_owner
i_should_be_on_client_callback @client
end
end
describe 'Implicit Grant Flow (request spec)' do
before do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
config_is_set(:grant_flows, ["implicit"])
client_exists
create_resource_owner
end
context 'token reuse' do
it 'should return a new token each request' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(false)
token = client_is_authorized(@client, @resource_owner)
post "/oauth/authorize",
client_id: @client.uid,
state: '',
redirect_uri: @client.redirect_uri,
response_type: 'token',
commit: 'Authorize'
expect(response.location).not_to include(token.token)
end
it 'should return the same token if it is still accessible' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
token = client_is_authorized(@client, @resource_owner)
post "/oauth/authorize",
client_id: @client.uid,
state: '',
redirect_uri: @client.redirect_uri,
response_type: 'token',
commit: 'Authorize'
expect(response.location).to include(token.token)
end
end
end
doorkeeper-2.2.1/spec/requests/flows/authorization_code_errors_spec.rb 0000644 0000764 0000764 00000003767 12544753400 025514 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Authorization Code Flow Errors' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
client_exists
create_resource_owner
sign_in
end
after do
access_grant_should_not_exist
end
context 'when access was denied' do
scenario 'redirects with error' do
visit authorization_endpoint_url(client: @client)
click_on 'Deny'
i_should_be_on_client_callback @client
url_should_not_have_param 'code'
url_should_have_param 'error', 'access_denied'
url_should_have_param 'error_description', translated_error_message(:access_denied)
end
scenario 'redirects with state parameter' do
visit authorization_endpoint_url(client: @client, state: 'return-this')
click_on 'Deny'
i_should_be_on_client_callback @client
url_should_not_have_param 'code'
url_should_have_param 'state', 'return-this'
end
end
end
describe 'Authorization Code Flow Errors', 'after authorization' do
before do
client_exists
authorization_code_exists application: @client
end
it 'returns :invalid_grant error when posting an already revoked grant code' do
# First successful request
post token_endpoint_url(code: @authorization.token, client: @client)
# Second attempt with same token
expect do
post token_endpoint_url(code: @authorization.token, client: @client)
end.to_not change { Doorkeeper::AccessToken.count }
should_not_have_json 'access_token'
should_have_json 'error', 'invalid_grant'
should_have_json 'error_description', translated_error_message('invalid_grant')
end
it 'returns :invalid_grant error for invalid grant code' do
post token_endpoint_url(code: 'invalid', client: @client)
access_token_should_not_exist
should_not_have_json 'access_token'
should_have_json 'error', 'invalid_grant'
should_have_json 'error_description', translated_error_message('invalid_grant')
end
end
doorkeeper-2.2.1/spec/requests/flows/skip_authorization_spec.rb 0000644 0000764 0000764 00000004314 12544753400 024141 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Skip authorization form' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
client_exists
default_scopes_exist :public
optional_scopes_exist :write
end
context 'for previously authorized clients' do
background do
create_resource_owner
sign_in
end
scenario 'skips the authorization and return a new grant code' do
client_is_authorized(@client, @resource_owner, scopes: 'public')
visit authorization_endpoint_url(client: @client)
i_should_not_see 'Authorize'
client_should_be_authorized @client
i_should_be_on_client_callback @client
url_should_have_param 'code', Doorkeeper::AccessGrant.first.token
end
scenario 'does not skip authorization when scopes differ (new request has fewer scopes)' do
client_is_authorized(@client, @resource_owner, scopes: 'public write')
visit authorization_endpoint_url(client: @client, scope: 'public')
i_should_see 'Authorize'
end
scenario 'does not skip authorization when scopes differ (new request has more scopes)' do
client_is_authorized(@client, @resource_owner, scopes: 'public write')
visit authorization_endpoint_url(client: @client, scopes: 'public write email')
i_should_see 'Authorize'
end
scenario 'creates grant with new scope when scopes differ' do
client_is_authorized(@client, @resource_owner, scopes: 'public write')
visit authorization_endpoint_url(client: @client, scope: 'public')
click_on 'Authorize'
access_grant_should_have_scopes :public
end
scenario 'doesn not skip authorization when scopes are greater' do
client_is_authorized(@client, @resource_owner, scopes: 'public')
visit authorization_endpoint_url(client: @client, scope: 'public write')
i_should_see 'Authorize'
end
scenario 'creates grant with new scope when scopes are greater' do
client_is_authorized(@client, @resource_owner, scopes: 'public')
visit authorization_endpoint_url(client: @client, scope: 'public write')
click_on 'Authorize'
access_grant_should_have_scopes :public, :write
end
end
end
doorkeeper-2.2.1/spec/requests/flows/authorization_code_spec.rb 0000644 0000764 0000764 00000011011 12544753400 024075 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Authorization Code Flow' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
client_exists
create_resource_owner
sign_in
end
scenario 'resource owner authorizes the client' do
visit authorization_endpoint_url(client: @client)
click_on 'Authorize'
access_grant_should_exist_for(@client, @resource_owner)
i_should_be_on_client_callback(@client)
url_should_have_param('code', Doorkeeper::AccessGrant.first.token)
url_should_not_have_param('state')
url_should_not_have_param('error')
end
scenario 'resource owner authorizes using test url' do
@client.redirect_uri = Doorkeeper.configuration.native_redirect_uri
@client.save!
visit authorization_endpoint_url(client: @client)
click_on 'Authorize'
access_grant_should_exist_for(@client, @resource_owner)
i_should_see 'Authorization code:'
i_should_see Doorkeeper::AccessGrant.first.token
end
scenario 'resource owner authorizes the client with state parameter set' do
visit authorization_endpoint_url(client: @client, state: 'return-me')
click_on 'Authorize'
url_should_have_param('code', Doorkeeper::AccessGrant.first.token)
url_should_have_param('state', 'return-me')
end
scenario 'resource owner requests an access token with authorization code' do
skip 'TODO: need to add request helpers to this feature spec'
visit authorization_endpoint_url(client: @client)
click_on 'Authorize'
authorization_code = Doorkeeper::AccessGrant.first.token
post token_endpoint_url(code: authorization_code, client: @client)
access_token_should_exist_for(@client, @resource_owner)
should_not_have_json 'error'
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
should_have_json 'token_type', 'bearer'
should_have_json_within 'expires_in', Doorkeeper::AccessToken.first.expires_in, 1
end
context 'with scopes' do
background do
default_scopes_exist :public
optional_scopes_exist :write
end
scenario 'resource owner authorizes the client with default scopes' do
visit authorization_endpoint_url(client: @client)
click_on 'Authorize'
access_grant_should_exist_for(@client, @resource_owner)
access_grant_should_have_scopes :public
end
scenario 'resource owner authorizes the client with required scopes' do
visit authorization_endpoint_url(client: @client, scope: 'public write')
click_on 'Authorize'
access_grant_should_have_scopes :public, :write
end
scenario 'resource owner authorizes the client with required scopes (without defaults)' do
visit authorization_endpoint_url(client: @client, scope: 'write')
click_on 'Authorize'
access_grant_should_have_scopes :write
end
scenario 'new access token matches required scopes' do
skip 'TODO: need to add request helpers to this feature spec'
visit authorization_endpoint_url(client: @client, scope: 'public write')
click_on 'Authorize'
authorization_code = Doorkeeper::AccessGrant.first.token
post token_endpoint_url(code: authorization_code, client: @client)
access_token_should_exist_for(@client, @resource_owner)
access_token_should_have_scopes :public, :write
end
scenario 'returns new token if scopes have changed' do
skip 'TODO: need to add request helpers to this feature spec'
client_is_authorized(@client, @resource_owner, scopes: 'public write')
visit authorization_endpoint_url(client: @client, scope: 'public')
click_on 'Authorize'
authorization_code = Doorkeeper::AccessGrant.first.token
post token_endpoint_url(code: authorization_code, client: @client)
expect(Doorkeeper::AccessToken.count).to be(2)
should_have_json 'access_token', Doorkeeper::AccessToken.last.token
end
scenario 'resource owner authorizes the client with extra scopes' do
skip 'TODO: need to add request helpers to this feature spec'
client_is_authorized(@client, @resource_owner, scopes: 'public')
visit authorization_endpoint_url(client: @client, scope: 'public write')
click_on 'Authorize'
authorization_code = Doorkeeper::AccessGrant.first.token
post token_endpoint_url(code: authorization_code, client: @client)
expect(Doorkeeper::AccessToken.count).to be(2)
should_have_json 'access_token', Doorkeeper::AccessToken.last.token
access_token_should_have_scopes :public, :write
end
end
end
doorkeeper-2.2.1/spec/requests/flows/refresh_token_spec.rb 0000644 0000764 0000764 00000006635 12544753400 023061 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Refresh Token Flow' do
before do
Doorkeeper.configure do
orm DOORKEEPER_ORM
use_refresh_token
end
client_exists
end
context 'issuing a refresh token' do
before do
authorization_code_exists application: @client
end
it 'client gets the refresh token and refreshses it' do
post token_endpoint_url(code: @authorization.token, client: @client)
token = Doorkeeper::AccessToken.first
should_have_json 'access_token', token.token
should_have_json 'refresh_token', token.refresh_token
expect(@authorization.reload).to be_revoked
post refresh_token_endpoint_url(client: @client, refresh_token: token.refresh_token)
new_token = Doorkeeper::AccessToken.last
should_have_json 'access_token', new_token.token
should_have_json 'refresh_token', new_token.refresh_token
expect(token.token).not_to eq(new_token.token)
expect(token.refresh_token).not_to eq(new_token.refresh_token)
end
end
context 'refreshing the token' do
before do
@token = FactoryGirl.create(:access_token, application: @client, resource_owner_id: 1, use_refresh_token: true)
end
it 'client request a token with refresh token' do
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
should_have_json 'refresh_token', Doorkeeper::AccessToken.last.refresh_token
expect(@token.reload).to be_revoked
end
it 'client request a token with expired access token' do
@token.update_attribute :expires_in, -100
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
should_have_json 'refresh_token', Doorkeeper::AccessToken.last.refresh_token
expect(@token.reload).to be_revoked
end
it 'client gets an error for invalid refresh token' do
post refresh_token_endpoint_url(client: @client, refresh_token: 'invalid')
should_not_have_json 'refresh_token'
should_have_json 'error', 'invalid_grant'
end
it 'client gets an error for revoked acccess token' do
@token.revoke
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
should_not_have_json 'refresh_token'
should_have_json 'error', 'invalid_grant'
end
end
context 'refreshing the token with multiple sessions (devices)' do
before do
# enable password auth to simulate other devices
config_is_set(:grant_flows, ["password"])
config_is_set(:resource_owner_from_credentials) { User.authenticate! params[:username], params[:password] }
create_resource_owner
_another_token = post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
last_token.update_attribute :created_at, 5.seconds.ago
@token = FactoryGirl.create(:access_token, application: @client, resource_owner_id: @resource_owner.id, use_refresh_token: true)
@token.update_attribute :expires_in, -100
end
it 'client request a token after creating another token with the same user' do
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
should_have_json 'refresh_token', last_token.refresh_token
expect(@token.reload).to be_revoked
end
def last_token
Doorkeeper::AccessToken.last_authorized_token_for(
@client.id, @resource_owner.id
)
end
end
end
doorkeeper-2.2.1/spec/requests/flows/implicit_grant_errors_spec.rb 0000644 0000764 0000764 00000002025 12544753400 024611 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Implicit Grant Flow Errors' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
config_is_set(:grant_flows, ["implicit"])
client_exists
create_resource_owner
sign_in
end
after do
access_token_should_not_exist
end
[
[:client_id, :invalid_client],
[:redirect_uri, :invalid_redirect_uri]
].each do |error|
scenario "displays #{error.last.inspect} error for invalid #{error.first.inspect}" do
visit authorization_endpoint_url(client: @client, error.first => 'invalid', response_type: 'token')
i_should_not_see 'Authorize'
i_should_see_translated_error_message error.last
end
scenario "displays #{error.last.inspect} error when #{error.first.inspect} is missing" do
visit authorization_endpoint_url(client: @client, error.first => '', response_type: 'token')
i_should_not_see 'Authorize'
i_should_see_translated_error_message error.last
end
end
end
doorkeeper-2.2.1/spec/requests/flows/password_spec.rb 0000644 0000764 0000764 00000006130 12544753400 022053 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Resource Owner Password Credentials Flow not set up' do
before do
client_exists
create_resource_owner
end
context 'with valid user credentials' do
it 'doesn\'t issue new token' do
expect do
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
end.to_not change { Doorkeeper::AccessToken.count }
end
end
end
describe 'Resource Owner Password Credentials Flow' do
before do
config_is_set(:grant_flows, ["password"])
config_is_set(:resource_owner_from_credentials) { User.authenticate! params[:username], params[:password] }
client_exists
create_resource_owner
end
context 'with valid user credentials' do
it 'should issue new token' do
expect do
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
end.to change { Doorkeeper::AccessToken.count }.by(1)
token = Doorkeeper::AccessToken.first
should_have_json 'access_token', token.token
end
it 'should issue new token without client credentials' do
expect do
post password_token_endpoint_url(resource_owner: @resource_owner)
end.to change { Doorkeeper::AccessToken.count }.by(1)
token = Doorkeeper::AccessToken.first
should_have_json 'access_token', token.token
end
it 'should issue a refresh token if enabled' do
config_is_set(:refresh_token_enabled, true)
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
token = Doorkeeper::AccessToken.first
should_have_json 'refresh_token', token.refresh_token
end
it 'should return the same token if it is still accessible' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
client_is_authorized(@client, @resource_owner)
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
expect(Doorkeeper::AccessToken.count).to be(1)
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
end
end
context 'with invalid user credentials' do
it 'should not issue new token with bad password' do
expect do
post password_token_endpoint_url(client: @client,
resource_owner_username: @resource_owner.name,
resource_owner_password: 'wrongpassword')
end.to_not change { Doorkeeper::AccessToken.count }
end
it 'should not issue new token without credentials' do
expect do
post password_token_endpoint_url(client: @client)
end.to_not change { Doorkeeper::AccessToken.count }
end
end
context 'with invalid client credentials' do
it 'should not issue new token with bad client credentials' do
expect do
post password_token_endpoint_url(client_id: @client.uid,
client_secret: 'bad_secret',
resource_owner: @resource_owner)
end.to_not change { Doorkeeper::AccessToken.count }
end
end
end
doorkeeper-2.2.1/spec/requests/flows/revoke_token_spec.rb 0000644 0000764 0000764 00000013573 12544753400 022715 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Revoke Token Flow' do
before do
Doorkeeper.configure { orm DOORKEEPER_ORM }
end
context 'with default parameters' do
let(:client_application) { FactoryGirl.create :application }
let(:resource_owner) { User.create!(name: 'John', password: 'sekret') }
let(:authorization_access_token) do
FactoryGirl.create(:access_token,
application: client_application,
resource_owner_id: resource_owner.id,
use_refresh_token: true)
end
let(:headers) { { 'HTTP_AUTHORIZATION' => "Bearer #{authorization_access_token.token}" } }
context 'With invalid token to revoke' do
it 'client wants to revoke the given access token' do
post revocation_token_endpoint_url, { token: 'I_AM_AN_INVALIDE_TOKEN' }, headers
authorization_access_token.reload
# The authorization server responds with HTTP status code 200 if the token
# has been revoked successfully or if the client submitted an invalid token.
expect(response).to be_success
expect(authorization_access_token).to_not be_revoked
end
end
context 'The access token to revoke is the same than the authorization access token' do
let(:token_to_revoke) { authorization_access_token }
it 'client wants to revoke the given access token' do
post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
token_to_revoke.reload
authorization_access_token.reload
expect(response).to be_success
expect(token_to_revoke.revoked?).to be_truthy
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
end
it 'client wants to revoke the given access token using the POST query string' do
url_with_query_string = revocation_token_endpoint_url + '?' + Rack::Utils.build_query(token: token_to_revoke.token)
post url_with_query_string, {}, headers
token_to_revoke.reload
authorization_access_token.reload
expect(response).to be_success
expect(token_to_revoke.revoked?).to be_falsey
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
expect(authorization_access_token.revoked?).to be_falsey
end
end
context 'The access token to revoke app and owners are the same than the authorization access token' do
let(:token_to_revoke) do
FactoryGirl.create(:access_token,
application: client_application,
resource_owner_id: resource_owner.id,
use_refresh_token: true)
end
it 'client wants to revoke the given access token' do
post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
token_to_revoke.reload
authorization_access_token.reload
expect(response).to be_success
expect(token_to_revoke.revoked?).to be_truthy
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
expect(authorization_access_token.revoked?).to be_falsey
end
end
context 'The access token to revoke authorization owner is the same than the authorization access token' do
let(:other_client_application) { FactoryGirl.create :application }
let(:token_to_revoke) do
FactoryGirl.create(:access_token,
application: other_client_application,
resource_owner_id: resource_owner.id,
use_refresh_token: true)
end
it 'client wants to revoke the given access token' do
post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
token_to_revoke.reload
authorization_access_token.reload
expect(response).to be_success
expect(token_to_revoke.revoked?).to be_falsey
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
expect(authorization_access_token.revoked?).to be_falsey
end
end
context 'The access token to revoke app is the same than the authorization access token' do
let(:other_resource_owner) { User.create!(name: 'Matheo', password: 'pareto') }
let(:token_to_revoke) do
FactoryGirl.create(:access_token,
application: client_application,
resource_owner_id: other_resource_owner.id,
use_refresh_token: true)
end
it 'client wants to revoke the given access token' do
post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
token_to_revoke.reload
authorization_access_token.reload
expect(response).to be_success
expect(token_to_revoke.revoked?).to be_falsey
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
expect(authorization_access_token.revoked?).to be_falsey
end
end
context 'With valid refresh token to revoke' do
let(:token_to_revoke) do
FactoryGirl.create(:access_token,
application: client_application,
resource_owner_id: resource_owner.id,
use_refresh_token: true)
end
it 'client wants to revoke the given refresh token' do
post revocation_token_endpoint_url, { token: token_to_revoke.refresh_token, token_type_hint: 'refresh_token' }, headers
authorization_access_token.reload
token_to_revoke.reload
expect(response).to be_success
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
expect(authorization_access_token).to_not be_revoked
end
end
end
end
doorkeeper-2.2.1/spec/requests/flows/client_credentials_spec.rb 0000644 0000764 0000764 00000003464 12544753400 024053 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Client Credentials Request' do
let(:client) { FactoryGirl.create :application }
context 'a valid request' do
it 'authorizes the client and returns the token response' do
headers = authorization client.uid, client.secret
params = { grant_type: 'client_credentials' }
post '/oauth/token', params, headers
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
should_have_json_within 'expires_in', Doorkeeper.configuration.access_token_expires_in, 1
should_not_have_json 'scope'
should_not_have_json 'refresh_token'
should_not_have_json 'error'
should_not_have_json 'error_description'
end
context 'with scopes' do
before do
optional_scopes_exist :write
end
it 'adds the scope to the token an returns in the response' do
headers = authorization client.uid, client.secret
params = { grant_type: 'client_credentials', scope: 'write' }
post '/oauth/token', params, headers
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
should_have_json 'scope', 'write'
end
end
end
context 'an invalid request' do
it 'does not authorize the client and returns the error' do
headers = {}
params = { grant_type: 'client_credentials' }
post '/oauth/token', params, headers
should_have_json 'error', 'invalid_client'
should_have_json 'error_description', translated_error_message(:invalid_client)
should_not_have_json 'access_token'
expect(response.status).to eq(401)
end
end
def authorization(username, password)
credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
{ 'HTTP_AUTHORIZATION' => credentials }
end
end
doorkeeper-2.2.1/spec/requests/protected_resources/ 0000755 0000764 0000764 00000000000 12544753400 021603 5 ustar pravi pravi doorkeeper-2.2.1/spec/requests/protected_resources/metal_spec.rb 0000644 0000764 0000764 00000000643 12544753400 024247 0 ustar pravi pravi require 'spec_helper_integration'
describe 'ActionController::Metal API' do
before do
@client = FactoryGirl.create(:application)
@resource = User.create!(name: 'Joe', password: 'sekret')
@token = client_is_authorized(@client, @resource)
end
it 'client requests protected resource with valid token' do
get "/metal.json?access_token=#{@token.token}"
should_have_json 'ok', true
end
end
doorkeeper-2.2.1/spec/requests/protected_resources/private_api_spec.rb 0000644 0000764 0000764 00000005364 12544753400 025455 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Private API' do
background do
@client = FactoryGirl.create(:application)
@resource = User.create!(name: 'Joe', password: 'sekret')
@token = client_is_authorized(@client, @resource)
end
scenario 'client requests protected resource with valid token' do
with_access_token_header @token.token
visit '/full_protected_resources'
expect(page.body).to have_content('index')
end
scenario 'client requests protected resource with disabled header authentication' do
config_is_set :access_token_methods, [:from_access_token_param]
with_access_token_header @token.token
visit '/full_protected_resources'
response_status_should_be 401
end
scenario 'client attempts to request protected resource with invalid token' do
with_access_token_header 'invalid'
visit '/full_protected_resources'
response_status_should_be 401
end
scenario 'client attempts to request protected resource with expired token' do
@token.update_attribute :expires_in, -100 # expires token
with_access_token_header @token.token
visit '/full_protected_resources'
response_status_should_be 401
end
scenario 'client requests protected resource with permanent token' do
@token.update_attribute :expires_in, nil # never expires
with_access_token_header @token.token
visit '/full_protected_resources'
expect(page.body).to have_content('index')
end
scenario 'access token with no default scopes' do
Doorkeeper.configuration.instance_eval {
@default_scopes = Doorkeeper::OAuth::Scopes.from_array([:public])
@scopes = default_scopes + optional_scopes
}
@token.update_attribute :scopes, 'dummy'
with_access_token_header @token.token
visit '/full_protected_resources'
response_status_should_be 403
end
scenario 'access token with no allowed scopes' do
@token.update_attribute :scopes, nil
with_access_token_header @token.token
visit '/full_protected_resources/1.json'
response_status_should_be 403
end
scenario 'access token with one of allowed scopes' do
@token.update_attribute :scopes, 'admin'
with_access_token_header @token.token
visit '/full_protected_resources/1.json'
expect(page.body).to have_content('show')
end
scenario 'access token with another of allowed scopes' do
@token.update_attribute :scopes, 'write'
with_access_token_header @token.token
visit '/full_protected_resources/1.json'
expect(page.body).to have_content('show')
end
scenario 'access token with both allowed scopes' do
@token.update_attribute :scopes, 'write admin'
with_access_token_header @token.token
visit '/full_protected_resources/1.json'
expect(page.body).to have_content('show')
end
end
doorkeeper-2.2.1/spec/requests/endpoints/ 0000755 0000764 0000764 00000000000 12544753400 017523 5 ustar pravi pravi doorkeeper-2.2.1/spec/requests/endpoints/token_spec.rb 0000644 0000764 0000764 00000005005 12544753400 022202 0 ustar pravi pravi require 'spec_helper_integration'
describe 'Token endpoint' do
before do
client_exists
authorization_code_exists application: @client, scopes: 'public'
end
it 'respond with correct headers' do
post token_endpoint_url(code: @authorization.token, client: @client)
should_have_header 'Pragma', 'no-cache'
should_have_header 'Cache-Control', 'no-store'
should_have_header 'Content-Type', 'application/json; charset=utf-8'
end
it 'accepts client credentials with basic auth header' do
post token_endpoint_url(
code: @authorization.token,
redirect_uri: @client.redirect_uri
), {}, 'HTTP_AUTHORIZATION' => basic_auth_header_for_client(@client)
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
end
it 'returns null for expires_in when a permanent token is set' do
config_is_set(:access_token_expires_in, nil)
post token_endpoint_url(code: @authorization.token, client: @client)
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
should_not_have_json 'expires_in'
end
it 'returns unsupported_grant_type for invalid grant_type param' do
post token_endpoint_url(code: @authorization.token, client: @client, grant_type: 'nothing')
should_not_have_json 'access_token'
should_have_json 'error', 'unsupported_grant_type'
should_have_json 'error_description', translated_error_message('unsupported_grant_type')
end
it 'returns unsupported_grant_type for disabled grant flows' do
config_is_set(:grant_flows, ['implicit'])
post token_endpoint_url(code: @authorization.token, client: @client, grant_type: 'authorization_code')
should_not_have_json 'access_token'
should_have_json 'error', 'unsupported_grant_type'
should_have_json 'error_description', translated_error_message('unsupported_grant_type')
end
it 'returns unsupported_grant_type when refresh_token is not in use' do
post token_endpoint_url(code: @authorization.token, client: @client, grant_type: 'refresh_token')
should_not_have_json 'access_token'
should_have_json 'error', 'unsupported_grant_type'
should_have_json 'error_description', translated_error_message('unsupported_grant_type')
end
it 'returns invalid_request if grant_type is missing' do
post token_endpoint_url(code: @authorization.token, client: @client, grant_type: '')
should_not_have_json 'access_token'
should_have_json 'error', 'invalid_request'
should_have_json 'error_description', translated_error_message('invalid_request')
end
end
doorkeeper-2.2.1/spec/requests/endpoints/authorization_spec.rb 0000644 0000764 0000764 00000004231 12544753400 023762 0 ustar pravi pravi require 'spec_helper_integration'
feature 'Authorization endpoint' do
background do
config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
client_exists(name: 'MyApp')
end
scenario 'requires resource owner to be authenticated' do
visit authorization_endpoint_url(client: @client)
i_should_see 'Sign in'
i_should_be_on '/'
end
context 'with authenticated resource owner' do
background do
create_resource_owner
sign_in
end
scenario 'displays the authorization form' do
visit authorization_endpoint_url(client: @client)
i_should_see 'Authorize MyApp to use your account?'
end
scenario 'displays all requested scopes' do
default_scopes_exist :public
optional_scopes_exist :write
visit authorization_endpoint_url(client: @client, scope: 'public write')
i_should_see 'Access your public data'
i_should_see 'Update your data'
end
end
context 'with a invalid request' do
background do
create_resource_owner
sign_in
end
scenario 'displays the related error' do
visit authorization_endpoint_url(client: @client, response_type: '')
i_should_not_see 'Authorize'
i_should_see_translated_error_message :unsupported_response_type
end
scenario "displays unsupported_response_type error when using a disabled response type" do
config_is_set(:grant_flows, ['implicit'])
visit authorization_endpoint_url(client: @client, response_type: 'code')
i_should_not_see "Authorize"
i_should_see_translated_error_message :unsupported_response_type
end
end
context 'forgery protection enabled' do
background do
create_resource_owner
sign_in
end
scenario 'raises exception on forged requests' do
skip 'TODO: need to add request helpers to this feature spec'
allow_any_instance_of(ActionController::Base).to receive(:handle_unverified_request)
allowing_forgery_protection do
post "/oauth/authorize",
client_id: @client.uid,
redirect_uri: @client.redirect_uri,
response_type: 'code'
end
end
end
end
doorkeeper-2.2.1/spec/models/ 0000755 0000764 0000764 00000000000 12544753400 015130 5 ustar pravi pravi doorkeeper-2.2.1/spec/models/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 017267 5 ustar pravi pravi doorkeeper-2.2.1/spec/models/doorkeeper/access_token_spec.rb 0000644 0000764 0000764 00000030337 12544753400 023275 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper
describe AccessToken do
subject { FactoryGirl.build(:access_token) }
it { should be_valid }
it_behaves_like 'an accessible token'
it_behaves_like 'a revocable token'
it_behaves_like 'a unique token' do
let(:factory_name) { :access_token }
end
describe :generate_token do
it 'generates a token using the default method' do
FactoryGirl.create :access_token
token = FactoryGirl.create :access_token
expect(token.token).to be_a(String)
end
it 'generates a token using a custom object' do
module CustomGeneratorArgs
def self.generate(opts = {})
"custom_generator_token_#{opts[:resource_owner_id]}"
end
end
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::CustomGeneratorArgs"
end
token = FactoryGirl.create :access_token
expect(token.token).to match(%r{custom_generator_token_\d+})
end
it 'allows the custom generator to access the application details' do
module CustomGeneratorArgs
def self.generate(opts = {})
"custom_generator_token_#{opts[:application].name}"
end
end
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::CustomGeneratorArgs"
end
token = FactoryGirl.create :access_token
expect(token.token).to match(%r{custom_generator_token_Application \d+})
end
it 'allows the custom generator to access the scopes' do
module CustomGeneratorArgs
def self.generate(opts = {})
"custom_generator_token_#{opts[:scopes].count}_#{opts[:scopes]}"
end
end
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::CustomGeneratorArgs"
end
token = FactoryGirl.create :access_token, scopes: 'public write'
expect(token.token).to eq 'custom_generator_token_2_public write'
end
it 'allows the custom generator to access the expiry length' do
module CustomGeneratorArgs
def self.generate(opts = {})
"custom_generator_token_#{opts[:expires_in]}"
end
end
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::CustomGeneratorArgs"
end
token = FactoryGirl.create :access_token
expect(token.token).to eq 'custom_generator_token_7200'
end
it 'raises an error if the custom object does not support generate' do
module NoGenerate
end
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::NoGenerate"
end
expect { FactoryGirl.create :access_token }.to(
raise_error(Doorkeeper::Errors::UnableToGenerateToken))
end
it 'raises an error if the custom object does not exist' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator "Doorkeeper::NotReal"
end
expect { FactoryGirl.create :access_token }.to(
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound))
end
end
describe :refresh_token do
it 'has empty refresh token if it was not required' do
token = FactoryGirl.create :access_token
expect(token.refresh_token).to be_nil
end
it 'generates a refresh token if it was requested' do
token = FactoryGirl.create :access_token, use_refresh_token: true
expect(token.refresh_token).not_to be_nil
end
it 'is not valid if token exists' do
token1 = FactoryGirl.create :access_token, use_refresh_token: true
token2 = FactoryGirl.create :access_token, use_refresh_token: true
token2.send :write_attribute, :refresh_token, token1.refresh_token
expect(token2).not_to be_valid
end
it 'expects database to raise an error if refresh tokens are the same' do
token1 = FactoryGirl.create :access_token, use_refresh_token: true
token2 = FactoryGirl.create :access_token, use_refresh_token: true
expect do
token2.write_attribute :refresh_token, token1.refresh_token
token2.save(validate: false)
end.to raise_error
end
end
describe 'validations' do
it 'is valid without resource_owner_id' do
# For client credentials flow
subject.resource_owner_id = nil
should be_valid
end
end
describe '#same_credential?' do
context 'with default parameters' do
let(:resource_owner_id) { 100 }
let(:application) { FactoryGirl.create :application }
let(:default_attributes) do
{ application: application, resource_owner_id: resource_owner_id }
end
let(:access_token1) { FactoryGirl.create :access_token, default_attributes }
context 'the second token has the same owner and same app' do
let(:access_token2) { FactoryGirl.create :access_token, default_attributes }
it 'success' do
expect(access_token1.same_credential?(access_token2)).to be_truthy
end
end
context 'the second token has same owner and different app' do
let(:other_application) { FactoryGirl.create :application }
let(:access_token2) { FactoryGirl.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
it 'fail' do
expect(access_token1.same_credential?(access_token2)).to be_falsey
end
end
context 'the second token has different owner and different app' do
let(:other_application) { FactoryGirl.create :application }
let(:access_token2) { FactoryGirl.create :access_token, application: other_application, resource_owner_id: 42 }
it 'fail' do
expect(access_token1.same_credential?(access_token2)).to be_falsey
end
end
context 'the second token has different owner and same app' do
let(:access_token2) { FactoryGirl.create :access_token, application: application, resource_owner_id: 42 }
it 'fail' do
expect(access_token1.same_credential?(access_token2)).to be_falsey
end
end
end
end
describe '#acceptable?' do
context 'a token that is not accessible' do
let(:token) { FactoryGirl.create(:access_token, created_at: 6.hours.ago) }
it 'should return false' do
expect(token.acceptable?(nil)).to be false
end
end
context 'a token that has the incorrect scopes' do
let(:token) { FactoryGirl.create(:access_token) }
it 'should return false' do
expect(token.acceptable?(['public'])).to be false
end
end
context 'a token is acceptable with the correct scopes' do
let(:token) do
token = FactoryGirl.create(:access_token)
token[:scopes] = 'public'
token
end
it 'should return true' do
expect(token.acceptable?(['public'])).to be true
end
end
end
describe '.revoke_all_for' do
let(:resource_owner) { double(id: 100) }
let(:application) { FactoryGirl.create :application }
let(:default_attributes) do
{ application: application, resource_owner_id: resource_owner.id }
end
it 'revokes all tokens for given application and resource owner' do
FactoryGirl.create :access_token, default_attributes
AccessToken.revoke_all_for application.id, resource_owner
AccessToken.all.each do |token|
expect(token).to be_revoked
end
end
it 'matches application' do
FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
AccessToken.revoke_all_for application.id, resource_owner
expect(AccessToken.all).not_to be_empty
end
it 'matches resource owner' do
FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 90)
AccessToken.revoke_all_for application.id, resource_owner
expect(AccessToken.all).not_to be_empty
end
end
describe '.matching_token_for' do
let(:resource_owner_id) { 100 }
let(:application) { FactoryGirl.create :application }
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public write') }
let(:default_attributes) do
{
application: application,
resource_owner_id: resource_owner_id,
scopes: scopes.to_s
}
end
it 'returns only one token' do
token = FactoryGirl.create :access_token, default_attributes
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to eq(token)
end
it 'accepts resource owner as object' do
resource_owner = double(to_key: true, id: 100)
token = FactoryGirl.create :access_token, default_attributes
last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
expect(last_token).to eq(token)
end
it 'accepts nil as resource owner' do
token = FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: nil)
last_token = AccessToken.matching_token_for(application, nil, scopes)
expect(last_token).to eq(token)
end
it 'excludes revoked tokens' do
FactoryGirl.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches the application' do
FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches the resource owner' do
FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 2)
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches token with fewer scopes' do
FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public')
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches token with different scopes' do
FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public email')
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches token with more scopes' do
FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public write email')
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'matches application scopes' do
application = FactoryGirl.create :application, scopes: "private read"
FactoryGirl.create :access_token, default_attributes.merge(
application: application
)
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to be_nil
end
it 'returns the last created token' do
FactoryGirl.create :access_token, default_attributes.merge(created_at: 1.day.ago)
token = FactoryGirl.create :access_token, default_attributes
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
expect(last_token).to eq(token)
end
it 'returns as_json hash' do
token = FactoryGirl.create :access_token, default_attributes
token_hash = {
resource_owner_id: token.resource_owner_id,
scopes: token.scopes,
expires_in_seconds: token.expires_in_seconds,
application: { uid: token.application.uid },
created_at: token.created_at.to_i,
}
expect(token.as_json).to eq token_hash
end
end
end
end
doorkeeper-2.2.1/spec/models/doorkeeper/application_spec.rb 0000644 0000764 0000764 00000014464 12544753400 023142 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper
describe Application do
let(:require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', true) }
let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', false) }
let(:new_application) { FactoryGirl.build(:application) }
let(:uid) { SecureRandom.hex(8) }
let(:secret) { SecureRandom.hex(8) }
context 'application_owner is enabled' do
before do
Doorkeeper.configure do
orm DOORKEEPER_ORM
enable_application_owner
end
end
context 'application owner is not required' do
before(:each) do
unset_require_owner
end
it 'is valid given valid attributes' do
expect(new_application).to be_valid
end
end
context 'application owner is required' do
before(:each) do
require_owner
@owner = FactoryGirl.build_stubbed(:user)
end
it 'is invalid without an owner' do
expect(new_application).not_to be_valid
end
it 'is valid with an owner' do
new_application.owner = @owner
expect(new_application).to be_valid
end
end
end
it 'is invalid without a name' do
new_application.name = nil
expect(new_application).not_to be_valid
end
it 'generates uid on create' do
expect(new_application.uid).to be_nil
new_application.save
expect(new_application.uid).not_to be_nil
end
it 'generates uid on create unless one is set' do
new_application.uid = uid
new_application.save
expect(new_application.uid).to eq(uid)
end
it 'is invalid without uid' do
new_application.save
new_application.uid = nil
expect(new_application).not_to be_valid
end
it 'is invalid without redirect_uri' do
new_application.save
new_application.redirect_uri = nil
expect(new_application).not_to be_valid
end
it 'checks uniqueness of uid' do
app1 = FactoryGirl.create(:application)
app2 = FactoryGirl.create(:application)
app2.uid = app1.uid
expect(app2).not_to be_valid
end
it 'expects database to throw an error when uids are the same' do
app1 = FactoryGirl.create(:application)
app2 = FactoryGirl.create(:application)
app2.uid = app1.uid
expect { app2.save!(validate: false) }.to raise_error
end
it 'generate secret on create' do
expect(new_application.secret).to be_nil
new_application.save
expect(new_application.secret).not_to be_nil
end
it 'generate secret on create unless one is set' do
new_application.secret = secret
new_application.save
expect(new_application.secret).to eq(secret)
end
it 'is invalid without secret' do
new_application.save
new_application.secret = nil
expect(new_application).not_to be_valid
end
describe 'destroy related models on cascade' do
before(:each) do
new_application.save
end
it 'should destroy its access grants' do
FactoryGirl.create(:access_grant, application: new_application)
expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
end
it 'should destroy its access tokens' do
FactoryGirl.create(:access_token, application: new_application)
FactoryGirl.create(:access_token, application: new_application, revoked_at: Time.now)
expect do
new_application.destroy
end.to change { Doorkeeper::AccessToken.count }.by(-2)
end
end
describe :authorized_for do
let(:resource_owner) { double(:resource_owner, id: 10) }
it 'is empty if the application is not authorized for anyone' do
expect(Application.authorized_for(resource_owner)).to be_empty
end
it 'returns only application for a specific resource owner' do
FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id + 1)
token = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
expect(Application.authorized_for(resource_owner)).to eq([token.application])
end
it 'excludes revoked tokens' do
FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, revoked_at: 2.days.ago)
expect(Application.authorized_for(resource_owner)).to be_empty
end
it 'returns all applications that have been authorized' do
token1 = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
token2 = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
expect(Application.authorized_for(resource_owner)).to eq([token1.application, token2.application])
end
it 'returns only one application even if it has been authorized twice' do
application = FactoryGirl.create(:application)
FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, application: application)
FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, application: application)
expect(Application.authorized_for(resource_owner)).to eq([application])
end
it 'should fail to mass assign a new application', if: ::Rails::VERSION::MAJOR < 4 do
mass_assign = { name: 'Something',
redirect_uri: 'http://somewhere.com/something',
uid: 123,
secret: 'something' }
expect(Application.create(mass_assign).uid).not_to eq(123)
end
end
describe :authenticate do
it 'finds the application via uid/secret' do
app = FactoryGirl.create :application
authenticated = Application.by_uid_and_secret(app.uid, app.secret)
expect(authenticated).to eq(app)
end
end
if Doorkeeper.configuration.orm == :active_record
describe :scopes do
it 'fails on missing column with an upgrade notice' do
app = FactoryGirl.build :application
no_scopes_app = double(attributes: [])
allow(Application).to receive(:new).and_return(no_scopes_app)
expect { app.scopes }.to raise_error(
NameError,
/Missing column: `applications.scopes`/
)
end
end
end
end
end
doorkeeper-2.2.1/spec/models/doorkeeper/access_grant_spec.rb 0000644 0000764 0000764 00000001451 12544753400 023263 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper::AccessGrant do
subject { FactoryGirl.build(:access_grant) }
it { should be_valid }
it_behaves_like 'an accessible token'
it_behaves_like 'a revocable token'
it_behaves_like 'a unique token' do
let(:factory_name) { :access_grant }
end
describe 'validations' do
it 'is invalid without resource_owner_id' do
subject.resource_owner_id = nil
should_not be_valid
end
it 'is invalid without application_id' do
subject.application_id = nil
should_not be_valid
end
it 'is invalid without token' do
subject.save
subject.token = nil
should_not be_valid
end
it 'is invalid without expires_in' do
subject.expires_in = nil
should_not be_valid
end
end
end
doorkeeper-2.2.1/spec/validators/ 0000755 0000764 0000764 00000000000 12544753400 016015 5 ustar pravi pravi doorkeeper-2.2.1/spec/validators/redirect_uri_validator_spec.rb 0000644 0000764 0000764 00000004453 12544753400 024107 0 ustar pravi pravi require 'spec_helper_integration'
describe RedirectUriValidator do
subject do
FactoryGirl.create(:application)
end
it 'is valid when the uri is a uri' do
subject.redirect_uri = 'https://example.com/callback'
expect(subject).to be_valid
end
it 'accepts native redirect uri' do
subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
expect(subject).to be_valid
end
it 'rejects if test uri is disabled' do
allow(RedirectUriValidator).to receive(:native_redirect_uri).and_return(nil)
subject.redirect_uri = 'urn:some:test'
expect(subject).not_to be_valid
end
it 'is invalid when the uri is not a uri' do
subject.redirect_uri = ']'
expect(subject).not_to be_valid
expect(subject.errors[:redirect_uri].first).to eq('must be a valid URI.')
end
it 'is invalid when the uri is relative' do
subject.redirect_uri = '/abcd'
expect(subject).not_to be_valid
expect(subject.errors[:redirect_uri].first).to eq('must be an absolute URI.')
end
it 'is invalid when the uri has a fragment' do
subject.redirect_uri = 'https://example.com/abcd#xyz'
expect(subject).not_to be_valid
expect(subject.errors[:redirect_uri].first).to eq('cannot contain a fragment.')
end
it 'is invalid when the uri has a query parameter' do
subject.redirect_uri = 'https://example.com/abcd?xyz=123'
expect(subject).to be_valid
end
context 'force secured uri' do
it 'accepts an valid uri' do
subject.redirect_uri = 'https://example.com/callback'
expect(subject).to be_valid
end
it 'accepts native redirect uri' do
subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
expect(subject).to be_valid
end
it 'accepts a non secured protocol when disabled' do
subject.redirect_uri = 'http://example.com/callback'
allow(Doorkeeper.configuration).to receive(
:force_ssl_in_redirect_uri
).and_return(false)
expect(subject).to be_valid
end
it 'invalidates the uri when the uri does not use a secure protocol' do
subject.redirect_uri = 'http://example.com/callback'
expect(subject).not_to be_valid
error = subject.errors[:redirect_uri].first
expect(error).to eq('must be an HTTPS/SSL URI.')
end
end
end
doorkeeper-2.2.1/spec/support/ 0000755 0000764 0000764 00000000000 12544753400 015361 5 ustar pravi pravi doorkeeper-2.2.1/spec/support/dependencies/ 0000755 0000764 0000764 00000000000 12544753400 020007 5 ustar pravi pravi doorkeeper-2.2.1/spec/support/dependencies/factory_girl.rb 0000644 0000764 0000764 00000000064 12544753400 023020 0 ustar pravi pravi require 'factory_girl'
FactoryGirl.find_definitions
doorkeeper-2.2.1/spec/support/shared/ 0000755 0000764 0000764 00000000000 12544753400 016627 5 ustar pravi pravi doorkeeper-2.2.1/spec/support/shared/controllers_shared_context.rb 0000644 0000764 0000764 00000003150 12544753400 024613 0 ustar pravi pravi shared_context 'valid token', token: :valid do
let :token_string do
'1A2B3C4D'
end
let :token do
double(Doorkeeper::AccessToken, accessible?: true, includes_scope?: true, acceptable?: true)
end
before :each do
allow(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
end
end
shared_context 'invalid token', token: :invalid do
let :token_string do
'1A2B3C4D'
end
let :token do
double(Doorkeeper::AccessToken, accessible?: false, revoked?: false, expired?: false, includes_scope?: false, acceptable?: false)
end
before :each do
allow(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
end
end
shared_context 'authenticated resource owner' do
before do
user = double(:resource, id: 1)
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { user } }
end
end
shared_context 'not authenticated resource owner' do
before do
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to '/' } }
end
end
shared_context 'valid authorization request' do
let :authorization do
double(:authorization, valid?: true, authorize: true, success_redirect_uri: 'http://something.com/cb?code=token')
end
before do
allow(controller).to receive(:authorization) { authorization }
end
end
shared_context 'invalid authorization request' do
let :authorization do
double(:authorization, valid?: false, authorize: false, redirect_on_error?: false)
end
before do
allow(controller).to receive(:authorization) { authorization }
end
end
doorkeeper-2.2.1/spec/support/shared/models_shared_examples.rb 0000644 0000764 0000764 00000002561 12544753400 023667 0 ustar pravi pravi shared_examples 'an accessible token' do
describe :accessible? do
it 'is accessible if token is not expired' do
allow(subject).to receive(:expired?).and_return(false)
should be_accessible
end
it 'is not accessible if token is expired' do
allow(subject).to receive(:expired?).and_return(true)
should_not be_accessible
end
end
end
shared_examples 'a revocable token' do
describe :accessible? do
before { subject.save! }
it 'is accessible if token is not revoked' do
expect(subject).to be_accessible
end
it 'is not accessible if token is revoked' do
subject.revoke
expect(subject).not_to be_accessible
end
end
end
shared_examples 'a unique token' do
describe :token do
it 'is generated before validation' do
expect { subject.valid? }.to change { subject.token }.from(nil)
end
it 'is not valid if token exists' do
token1 = FactoryGirl.create factory_name
token2 = FactoryGirl.create factory_name
token2.token = token1.token
expect(token2).not_to be_valid
end
it 'expects database to throw an error when tokens are the same' do
token1 = FactoryGirl.create factory_name
token2 = FactoryGirl.create factory_name
token2.token = token1.token
expect do
token2.save!(validate: false)
end.to raise_error
end
end
end
doorkeeper-2.2.1/spec/support/orm/ 0000755 0000764 0000764 00000000000 12544753400 016156 5 ustar pravi pravi doorkeeper-2.2.1/spec/support/orm/mongoid.rb 0000644 0000764 0000764 00000000435 12544753400 020141 0 ustar pravi pravi DatabaseCleaner[:mongoid].strategy = :truncation
DatabaseCleaner[:mongoid].clean_with :truncation
RSpec.configure do |config|
config.before do
Doorkeeper::Application.create_indexes
Doorkeeper::AccessGrant.create_indexes
Doorkeeper::AccessToken.create_indexes
end
end
doorkeeper-2.2.1/spec/support/orm/mongo_mapper.rb 0000644 0000764 0000764 00000000456 12544753400 021173 0 ustar pravi pravi DatabaseCleaner[:mongo_mapper].strategy = :truncation
DatabaseCleaner[:mongo_mapper].clean_with :truncation
RSpec.configure do |config|
config.before :suite do
Doorkeeper::Application.create_indexes
Doorkeeper::AccessGrant.create_indexes
Doorkeeper::AccessToken.create_indexes
end
end
doorkeeper-2.2.1/spec/support/orm/active_record.rb 0000644 0000764 0000764 00000000153 12544753400 021313 0 ustar pravi pravi # load schema to in memory sqlite
ActiveRecord::Migration.verbose = false
load Rails.root + 'db/schema.rb'
doorkeeper-2.2.1/spec/support/helpers/ 0000755 0000764 0000764 00000000000 12544753400 017023 5 ustar pravi pravi doorkeeper-2.2.1/spec/support/helpers/request_spec_helper.rb 0000644 0000764 0000764 00000003332 12544753400 023412 0 ustar pravi pravi module RequestSpecHelper
def i_should_see(content)
expect(page).to have_content(content)
end
def i_should_not_see(content)
expect(page).to have_no_content(content)
end
def i_should_be_on(path)
expect(current_path).to eq(path)
end
def url_should_have_param(param, value)
expect(current_params[param]).to eq(value)
end
def url_should_not_have_param(param)
expect(current_params).not_to have_key(param)
end
def current_params
Rack::Utils.parse_query(current_uri.query)
end
def current_uri
URI.parse(page.current_url)
end
def should_have_header(header, value)
expect(headers[header]).to eq(value)
end
def with_access_token_header(token)
with_header 'Authorization', "Bearer #{token}"
end
def with_header(header, value)
page.driver.header header, value
end
def basic_auth_header_for_client(client)
ActionController::HttpAuthentication::Basic.encode_credentials client.uid, client.secret
end
def should_have_json(key, value)
expect(JSON.parse(response.body).fetch(key)).to eq(value)
end
def should_have_json_within(key, value, range)
expect(JSON.parse(response.body).fetch(key)).to be_within(range).of(value)
end
def should_not_have_json(key)
expect(JSON.parse(response.body)).not_to have_key(key)
end
def sign_in
visit '/'
click_on 'Sign in'
end
def i_should_see_translated_error_message(key)
i_should_see translated_error_message(key)
end
def translated_error_message(key)
I18n.translate key, scope: [:doorkeeper, :errors, :messages]
end
def response_status_should_be(status)
expect(page.driver.response.status.to_i).to eq(status)
end
end
RSpec.configuration.send :include, RequestSpecHelper
doorkeeper-2.2.1/spec/support/helpers/model_helper.rb 0000644 0000764 0000764 00000002474 12544753400 022016 0 ustar pravi pravi module ModelHelper
def client_exists(client_attributes = {})
@client = FactoryGirl.create(:application, client_attributes)
end
def create_resource_owner
@resource_owner = User.create!(name: 'Joe', password: 'sekret')
end
def authorization_code_exists(options = {})
@authorization = FactoryGirl.create(:access_grant, options)
end
def access_grant_should_exist_for(client, resource_owner)
grant = Doorkeeper::AccessGrant.first
expect(grant.application).to eq(client)
grant.resource_owner_id == resource_owner.id
end
def access_token_should_exist_for(client, resource_owner)
grant = Doorkeeper::AccessToken.first
expect(grant.application).to eq(client)
grant.resource_owner_id == resource_owner.id
end
def access_grant_should_not_exist
expect(Doorkeeper::AccessGrant.all).to be_empty
end
def access_token_should_not_exist
expect(Doorkeeper::AccessToken.all).to be_empty
end
def access_grant_should_have_scopes(*args)
grant = Doorkeeper::AccessGrant.first
expect(grant.scopes).to eq(Doorkeeper::OAuth::Scopes.from_array(args))
end
def access_token_should_have_scopes(*args)
grant = Doorkeeper::AccessToken.last
expect(grant.scopes).to eq(Doorkeeper::OAuth::Scopes.from_array(args))
end
end
RSpec.configuration.send :include, ModelHelper
doorkeeper-2.2.1/spec/support/helpers/url_helper.rb 0000644 0000764 0000764 00000004073 12544753400 021515 0 ustar pravi pravi module UrlHelper
def token_endpoint_url(options = {})
parameters = {
code: options[:code],
client_id: options[:client_id] || (options[:client] ? options[:client].uid : nil),
client_secret: options[:client_secret] || (options[:client] ? options[:client].secret : nil),
redirect_uri: options[:redirect_uri] || (options[:client] ? options[:client].redirect_uri : nil),
grant_type: options[:grant_type] || 'authorization_code'
}
"/oauth/token?#{build_query(parameters)}"
end
def password_token_endpoint_url(options = {})
parameters = {
code: options[:code],
client_id: options[:client_id] || (options[:client] ? options[:client].uid : nil),
client_secret: options[:client_secret] || (options[:client] ? options[:client].secret : nil),
username: options[:resource_owner_username] || (options[:resource_owner] ? options[:resource_owner].name : nil),
password: options[:resource_owner_password] || (options[:resource_owner] ? options[:resource_owner].password : nil),
grant_type: 'password'
}
"/oauth/token?#{build_query(parameters)}"
end
def authorization_endpoint_url(options = {})
parameters = {
client_id: options[:client_id] || options[:client].uid,
redirect_uri: options[:redirect_uri] || options[:client].redirect_uri,
response_type: options[:response_type] || 'code',
scope: options[:scope],
state: options[:state]
}.reject { |k, v| v.blank? }
"/oauth/authorize?#{build_query(parameters)}"
end
def refresh_token_endpoint_url(options = {})
parameters = {
refresh_token: options[:refresh_token],
client_id: options[:client_id] || options[:client].uid,
client_secret: options[:client_secret] || options[:client].secret,
grant_type: options[:grant_type] || 'refresh_token'
}
"/oauth/token?#{build_query(parameters)}"
end
def revocation_token_endpoint_url
'/oauth/revoke'
end
def build_query(hash)
Rack::Utils.build_query(hash)
end
end
RSpec.configuration.send :include, UrlHelper
doorkeeper-2.2.1/spec/support/helpers/config_helper.rb 0000644 0000764 0000764 00000000423 12544753400 022153 0 ustar pravi pravi module ConfigHelper
def config_is_set(setting, value = nil, &block)
setting_ivar = "@#{setting}"
value = block_given? ? block : value
Doorkeeper.configuration.instance_variable_set(setting_ivar, value)
end
end
RSpec.configuration.send :include, ConfigHelper
doorkeeper-2.2.1/spec/support/helpers/authorization_request_helper.rb 0000644 0000764 0000764 00000002635 12544753400 025365 0 ustar pravi pravi module AuthorizationRequestHelper
def resource_owner_is_authenticated(resource_owner = nil)
resource_owner ||= User.create!(name: 'Joe', password: 'sekret')
Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { resource_owner })
end
def resource_owner_is_not_authenticated
Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to('/sign_in') })
end
def default_scopes_exist(*scopes)
Doorkeeper.configuration.instance_variable_set(:@default_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
end
def optional_scopes_exist(*scopes)
Doorkeeper.configuration.instance_variable_set(:@optional_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
end
def client_should_be_authorized(client)
expect(client.access_grants.size).to eq(1)
end
def client_should_not_be_authorized(client)
expect(client.size).to eq(0)
end
def i_should_be_on_client_callback(client)
expect(client.redirect_uri).to eq("#{current_uri.scheme}://#{current_uri.host}#{current_uri.path}")
end
def allowing_forgery_protection(&block)
_original_value = ActionController::Base.allow_forgery_protection
ActionController::Base.allow_forgery_protection = true
block.call
ensure
ActionController::Base.allow_forgery_protection = _original_value
end
end
RSpec.configuration.send :include, AuthorizationRequestHelper
doorkeeper-2.2.1/spec/support/helpers/access_token_request_helper.rb 0000644 0000764 0000764 00000000550 12544753400 025120 0 ustar pravi pravi module AccessTokenRequestHelper
def client_is_authorized(client, resource_owner, access_token_attributes = {})
attributes = {
application: client,
resource_owner_id: resource_owner.id
}.merge(access_token_attributes)
FactoryGirl.create(:access_token, attributes)
end
end
RSpec.configuration.send :include, AccessTokenRequestHelper
doorkeeper-2.2.1/spec/dummy/ 0000755 0000764 0000764 00000000000 12544753400 015000 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/db/ 0000755 0000764 0000764 00000000000 12544753400 015365 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/db/schema.rb 0000644 0000764 0000764 00000005766 12544753400 017170 0 ustar pravi pravi # encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141209001746) do
create_table "oauth_access_grants", force: true do |t|
t.integer "resource_owner_id", null: false
t.integer "application_id", null: false
t.string "token", null: false
t.integer "expires_in", null: false
t.string "redirect_uri", limit: 2048, null: false
t.datetime "created_at", null: false
t.datetime "revoked_at"
t.string "scopes"
end
add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true
create_table "oauth_access_tokens", force: true do |t|
t.integer "resource_owner_id"
t.integer "application_id"
t.string "token", null: false
t.string "refresh_token"
t.integer "expires_in"
t.datetime "revoked_at"
t.datetime "created_at", null: false
t.string "scopes"
end
add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true
create_table "oauth_applications", force: true do |t|
t.string "name", null: false
t.string "uid", null: false
t.string "secret", null: false
t.string "redirect_uri", limit: 2048, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "owner_id"
t.string "owner_type"
t.string "scopes", default: "", null: false
end
add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true
create_table "users", force: true do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password"
end
end
doorkeeper-2.2.1/spec/dummy/db/migrate/ 0000755 0000764 0000764 00000000000 12544753400 017015 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb 0000644 0000764 0000764 00000000422 12544753400 026044 0 ustar pravi pravi class AddOwnerToApplication < ActiveRecord::Migration
def change
add_column :oauth_applications, :owner_id, :integer, null: true
add_column :oauth_applications, :owner_type, :string, null: true
add_index :oauth_applications, [:owner_id, :owner_type]
end
end
doorkeeper-2.2.1/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb 0000644 0000764 0000764 00000000243 12544753400 027561 0 ustar pravi pravi class AddScopesToOauthApplications < ActiveRecord::Migration
def change
add_column :oauth_applications, :scopes, :string, null: false, default: ''
end
end
doorkeeper-2.2.1/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb 0000644 0000764 0000764 00000000164 12544753400 025364 0 ustar pravi pravi class AddPasswordToUsers < ActiveRecord::Migration
def change
add_column :users, :password, :string
end
end
doorkeeper-2.2.1/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb 0000644 0000764 0000764 00000002540 12544753400 026030 0 ustar pravi pravi class CreateDoorkeeperTables < ActiveRecord::Migration
def change
create_table :oauth_applications do |t|
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false
t.string :redirect_uri, null: false, limit: 2048
t.timestamps
end
add_index :oauth_applications, :uid, unique: true
create_table :oauth_access_grants do |t|
t.integer :resource_owner_id, null: false
t.integer :application_id, null: false
t.string :token, null: false
t.integer :expires_in, null: false
t.string :redirect_uri, null: false, limit: 2048
t.datetime :created_at, null: false
t.datetime :revoked_at
t.string :scopes
end
add_index :oauth_access_grants, :token, unique: true
create_table :oauth_access_tokens do |t|
t.integer :resource_owner_id
t.integer :application_id
t.string :token, null: false
t.string :refresh_token
t.integer :expires_in
t.datetime :revoked_at
t.datetime :created_at, null: false
t.string :scopes
end
add_index :oauth_access_tokens, :token, unique: true
add_index :oauth_access_tokens, :resource_owner_id
add_index :oauth_access_tokens, :refresh_token, unique: true
end
end
doorkeeper-2.2.1/spec/dummy/db/migrate/20111122132257_create_users.rb 0000644 0000764 0000764 00000000223 12544753400 023460 0 ustar pravi pravi class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
doorkeeper-2.2.1/spec/dummy/config/ 0000755 0000764 0000764 00000000000 12544753400 016245 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/config/environment.rb 0000644 0000764 0000764 00000000225 12544753400 021135 0 ustar pravi pravi # Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
Dummy::Application.initialize!
doorkeeper-2.2.1/spec/dummy/config/mongo.yml 0000644 0000764 0000764 00000000306 12544753400 020106 0 ustar pravi pravi defaults: &defaults
host: 127.0.0.1
port: 27017
development:
<<: *defaults
database: doorkeeper-mongomapper-development
test:
<<: *defaults
database: doorkeeper-mongomapper-test-suite
doorkeeper-2.2.1/spec/dummy/config/locales/ 0000755 0000764 0000764 00000000000 12544753400 017667 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/config/locales/doorkeeper.en.yml 0000644 0000764 0000764 00000000147 12544753400 023154 0 ustar pravi pravi en:
doorkeeper:
scopes:
public: "Access your public data"
write: "Update your data"
doorkeeper-2.2.1/spec/dummy/config/environments/ 0000755 0000764 0000764 00000000000 12544753400 020774 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/config/environments/test.rb 0000644 0000764 0000764 00000004302 12544753400 022277 0 ustar pravi pravi Dummy::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Configure static asset server for tests with Cache-Control for performance
config.static_cache_control = 'public, max-age=3600'
if Rails.version.to_i < 4
# Log error messages when you accidentally call methods on nil
config.whiny_nils = true
end
if Rails.version.to_i >= 4
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
config.i18n.enforce_available_locales = true
end
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
# config.action_mailer.delivery_method = :test
# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
config.eager_load = true
if DOORKEEPER_ORM == :active_record
config.active_record.table_name_prefix = TABLE_NAME_PREFIX.to_s
config.active_record.table_name_suffix = TABLE_NAME_SUFFIX.to_s
end
end
doorkeeper-2.2.1/spec/dummy/config/environments/production.rb 0000644 0000764 0000764 00000004205 12544753400 023510 0 ustar pravi pravi Dummy::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Use a different logger for distributed setups
# config.logger = SyslogLogger.new
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
config.eager_load = true
end
doorkeeper-2.2.1/spec/dummy/config/environments/development.rb 0000644 0000764 0000764 00000001757 12544753400 023655 0 ustar pravi pravi Dummy::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
# config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
config.eager_load = false
end
doorkeeper-2.2.1/spec/dummy/config/boot.rb 0000644 0000764 0000764 00000000376 12544753400 017543 0 ustar pravi pravi require 'rubygems'
require 'bundler/setup'
orm = ENV['BUNDLE_GEMFILE'].match(/Gemfile\.(.+)\.rb/)
unless defined?(DOORKEEPER_ORM)
DOORKEEPER_ORM = (orm && orm[1]) || :active_record
end
$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
doorkeeper-2.2.1/spec/dummy/config/initializers/ 0000755 0000764 0000764 00000000000 12544753400 020753 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/config/initializers/session_store.rb 0000644 0000764 0000764 00000000627 12544753400 024204 0 ustar pravi pravi # Be sure to restart your server when you modify this file.
Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rails generate session_migration")
# Dummy::Application.config.session_store :active_record_store
doorkeeper-2.2.1/spec/dummy/config/initializers/secret_token.rb 0000644 0000764 0000764 00000001040 12544753400 023760 0 ustar pravi pravi # Be sure to restart your server when you modify this file.
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Dummy::Application.config.secret_key_base =
Dummy::Application.config.secret_token =
'c00157b5a1bb6181792f0f4a8a080485de7bab9987e6cf159dc74c4f0573345c1bfa713b5d756e1491fc0b098567e8a619e2f8d268eda86a20a720d05d633780'
doorkeeper-2.2.1/spec/dummy/config/initializers/wrap_parameters.rb 0000644 0000764 0000764 00000000721 12544753400 024474 0 ustar pravi pravi # Be sure to restart your server when you modify this file.
#
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
# Disable root element in JSON by default.
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end
doorkeeper-2.2.1/spec/dummy/config/initializers/doorkeeper.rb 0000644 0000764 0000764 00000010736 12544753400 023446 0 ustar pravi pravi Doorkeeper.configure do
# Change the ORM that doorkeeper will use.
# Currently supported options are :active_record, :mongoid2, :mongoid3,
# :mongoid4, :mongo_mapper
orm DOORKEEPER_ORM
# This block will be called to check whether the resource owner is authenticated or not.
resource_owner_authenticator do
# Put your resource owner authentication logic here.
User.where(id: session[:user_id]).first || redirect_to(root_url, alert: 'Needs sign in.')
end
# If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
# admin_authenticator do
# # Put your admin authentication logic here.
# # Example implementation:
# Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
# end
# Authorization Code expiration time (default 10 minutes).
# authorization_code_expires_in 10.minutes
# Access token expiration time (default 2 hours).
# If you want to disable expiration, set this to nil.
# access_token_expires_in 2.hours
# Reuse access token for the same resource owner within an application (disabled by default)
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
# reuse_access_token
# Issue access tokens with refresh token (disabled by default)
use_refresh_token
# Provide support for an owner to be assigned to each registered application (disabled by default)
# Optional parameter :confirmation => true (default false) if you want to enforce ownership of
# a registered application
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
# enable_application_owner :confirmation => false
# Define access token scopes for your provider
# For more information go to
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
default_scopes :public
optional_scopes :write, :update
# Change the way client credentials are retrieved from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
# Check out the wiki for more information on customization
# client_credentials :from_basic, :from_params
# Change the way access token is authenticated from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
# falls back to the `:access_token` or `:bearer_token` params from the `params` object.
# Check out the wiki for more information on customization
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
# Change the native redirect uri for client apps
# When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
#
# native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
# by default in non-development environments). OAuth2 delegates security in
# communication to the HTTPS protocol so it is wise to keep this enabled.
#
# force_ssl_in_redirect_uri !Rails.env.development?
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
#
# "authorization_code" => Authorization Code Grant Flow
# "implicit" => Implicit Grant Flow
# "password" => Resource Owner Password Credentials Grant Flow
# "client_credentials" => Client Credentials Grant Flow
#
# If not specified, Doorkeeper enables authorization_code and
# client_credentials.
#
# implicit and password grant flows have risks that you should understand
# before enabling:
# http://tools.ietf.org/html/rfc6819#section-4.4.2
# http://tools.ietf.org/html/rfc6819#section-4.4.3
#
# grant_flows %w(authorization_code client_credentials)
# Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step.
# For example if dealing with a trusted application.
# skip_authorization do |resource_owner, client|
# client.superapp? or resource_owner.admin?
# end
# WWW-Authenticate Realm (default "Doorkeeper").
realm "Doorkeeper"
end
doorkeeper-2.2.1/spec/dummy/config/initializers/backtrace_silencers.rb 0000644 0000764 0000764 00000000624 12544753400 025270 0 ustar pravi pravi # Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
doorkeeper-2.2.1/spec/dummy/config/database.yml 0000644 0000764 0000764 00000000343 12544753400 020534 0 ustar pravi pravi development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
test:
adapter: sqlite3
database: ":memory:"
timeout: 500
production:
adapter: sqlite3
database: ":memory:"
timeout: 500
doorkeeper-2.2.1/spec/dummy/config/routes.rb 0000644 0000764 0000764 00000002743 12544753400 020121 0 ustar pravi pravi Rails.application.routes.draw do
use_doorkeeper
use_doorkeeper scope: 'scope'
scope 'inner_space' do
use_doorkeeper scope: 'scope' do
controllers authorizations: 'custom_authorizations',
tokens: 'custom_authorizations',
applications: 'custom_authorizations',
token_info: 'custom_authorizations'
as authorizations: 'custom_auth',
tokens: 'custom_token',
token_info: 'custom_token_info'
end
end
scope 'space' do
use_doorkeeper do
controllers authorizations: 'custom_authorizations',
tokens: 'custom_authorizations',
applications: 'custom_authorizations',
token_info: 'custom_authorizations'
as authorizations: 'custom_auth',
tokens: 'custom_token',
token_info: 'custom_token_info'
end
end
scope 'outer_space' do
use_doorkeeper do
controllers authorizations: 'custom_authorizations',
tokens: 'custom_authorizations',
token_info: 'custom_authorizations'
as authorizations: 'custom_auth',
tokens: 'custom_token',
token_info: 'custom_token_info'
skip_controllers :tokens, :applications, :token_info
end
end
get 'metal.json' => 'metal#index'
get '/callback', to: 'home#callback'
get '/sign_in', to: 'home#sign_in'
resources :semi_protected_resources
resources :full_protected_resources
root to: 'home#index'
end
doorkeeper-2.2.1/spec/dummy/config/mongoid3.yml 0000644 0000764 0000764 00000000552 12544753400 020511 0 ustar pravi pravi development:
sessions:
default:
database: doorkeeper-mongoid3-development
hosts:
- localhost:27017
options:
consistency: :strong
safe: true
test:
sessions:
default:
database: doorkeeper-mongoid3-test
hosts:
- localhost:27017
options:
consistency: :strong
safe: true
doorkeeper-2.2.1/spec/dummy/config/mongoid2.yml 0000644 0000764 0000764 00000000314 12544753400 020504 0 ustar pravi pravi development:
database: doorkeeper-development
persist_in_safe_mode: true
autocreate_indexes: true
test:
database: doorkeeper-mongoid2-test
persist_in_safe_mode: true
autocreate_indexes: true
doorkeeper-2.2.1/spec/dummy/config/mongoid4.yml 0000644 0000764 0000764 00000000507 12544753400 020512 0 ustar pravi pravi development:
sessions:
default:
database: doorkeeper-mongoid4-development
hosts:
- localhost:27017
options:
write:
w: 1
test:
sessions:
default:
database: doorkeeper-mongoid4-test
hosts:
- localhost:27017
options:
write:
w: 1
doorkeeper-2.2.1/spec/dummy/config/application.rb 0000644 0000764 0000764 00000004064 12544753400 021101 0 ustar pravi pravi require File.expand_path('../boot', __FILE__)
require 'action_controller/railtie'
require 'sprockets/railtie'
Bundler.require :default
require 'yaml'
orm = if DOORKEEPER_ORM =~ /mongoid/
Mongoid.load!(File.join(File.dirname(File.expand_path(__FILE__)), "#{DOORKEEPER_ORM}.yml"))
:mongoid
else
DOORKEEPER_ORM
end
require "#{orm}/railtie"
module Dummy
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
if defined?(ActiveRecord) && Rails.version.to_i < 4
config.active_record.whitelist_attributes = true
end
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
config.i18n.load_path += Dir[Rails.root.join('../../', 'config/locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :en
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
I18n.enforce_available_locales = false
end
end
doorkeeper-2.2.1/spec/dummy/script/ 0000755 0000764 0000764 00000000000 12544753400 016304 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/script/rails 0000755 0000764 0000764 00000000447 12544753400 017351 0 ustar pravi pravi #!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
doorkeeper-2.2.1/spec/dummy/public/ 0000755 0000764 0000764 00000000000 12544753400 016256 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/public/422.html 0000644 0000764 0000764 00000001307 12544753400 017454 0 ustar pravi pravi
The change you wanted was rejected (422)
The change you wanted was rejected.
Maybe you tried to change something you didn't have access to.
doorkeeper-2.2.1/spec/dummy/public/500.html 0000644 0000764 0000764 00000001330 12544753400 017445 0 ustar pravi pravi
We're sorry, but something went wrong (500)
We're sorry, but something went wrong.
We've been notified about this issue and we'll take a look at it shortly.
doorkeeper-2.2.1/spec/dummy/public/favicon.ico 0000644 0000764 0000764 00000000000 12544753400 020365 0 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/public/404.html 0000644 0000764 0000764 00000001330 12544753400 017450 0 ustar pravi pravi
The page you were looking for doesn't exist (404)
The page you were looking for doesn't exist.
You may have mistyped the address or the page may have moved.
doorkeeper-2.2.1/spec/dummy/config.ru 0000644 0000764 0000764 00000000233 12544753400 016613 0 ustar pravi pravi # This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run Dummy::Application
doorkeeper-2.2.1/spec/dummy/app/ 0000755 0000764 0000764 00000000000 12544753400 015560 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/helpers/ 0000755 0000764 0000764 00000000000 12544753400 017222 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/helpers/application_helper.rb 0000644 0000764 0000764 00000000157 12544753400 023414 0 ustar pravi pravi module ApplicationHelper
def current_user
@current_user ||= User.find_by_id(session[:user_id])
end
end
doorkeeper-2.2.1/spec/dummy/app/models/ 0000755 0000764 0000764 00000000000 12544753400 017043 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/models/user.rb 0000644 0000764 0000764 00000001152 12544753400 020345 0 ustar pravi pravi case DOORKEEPER_ORM.to_s
when "active_record"
class User < ActiveRecord::Base
end
when /mongoid/
class User
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :password, type: String
end
when "mongo_mapper"
class User
include MongoMapper::Document
timestamps!
key :name, String
key :password, String
end
end
class User
if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
attr_accessible :name, :password
end
def self.authenticate!(name, password)
User.where(name: name, password: password).first
end
end
doorkeeper-2.2.1/spec/dummy/app/views/ 0000755 0000764 0000764 00000000000 12544753400 016715 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/views/layouts/ 0000755 0000764 0000764 00000000000 12544753400 020415 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/views/layouts/application.html.erb 0000644 0000764 0000764 00000000241 12544753400 024352 0 ustar pravi pravi
Dummy
<%= csrf_meta_tags %>
<%= link_to "Sign in", '/sign_in' %>
<%= yield %>
doorkeeper-2.2.1/spec/dummy/app/views/home/ 0000755 0000764 0000764 00000000000 12544753400 017645 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/views/home/index.html.erb 0000644 0000764 0000764 00000000000 12544753400 022377 0 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/controllers/ 0000755 0000764 0000764 00000000000 12544753400 020126 5 ustar pravi pravi doorkeeper-2.2.1/spec/dummy/app/controllers/semi_protected_resources_controller.rb 0000644 0000764 0000764 00000000346 12544753400 030021 0 ustar pravi pravi class SemiProtectedResourcesController < ApplicationController
before_filter :doorkeeper_authorize!, only: :index
def index
render text: 'protected index'
end
def show
render text: 'non protected show'
end
end
doorkeeper-2.2.1/spec/dummy/app/controllers/full_protected_resources_controller.rb 0000644 0000764 0000764 00000000427 12544753400 030026 0 ustar pravi pravi class FullProtectedResourcesController < ApplicationController
before_filter -> { doorkeeper_authorize! :write, :admin }, only: :show
before_filter :doorkeeper_authorize!, only: :index
def index
render text: 'index'
end
def show
render text: 'show'
end
end
doorkeeper-2.2.1/spec/dummy/app/controllers/metal_controller.rb 0000644 0000764 0000764 00000000413 12544753400 024016 0 ustar pravi pravi class MetalController < ActionController::Metal
include AbstractController::Callbacks
include ActionController::Head
include Doorkeeper::Rails::Helpers
before_filter :doorkeeper_authorize!
def index
self.response_body = { ok: true }.to_json
end
end
doorkeeper-2.2.1/spec/dummy/app/controllers/home_controller.rb 0000644 0000764 0000764 00000000576 12544753400 023656 0 ustar pravi pravi class HomeController < ApplicationController
def index
end
def sign_in
session[:user_id] = if Rails.env.development?
User.first || User.create!(name: 'Joe', password: 'sekret')
else
User.first
end
redirect_to '/'
end
def callback
render text: 'ok'
end
end
doorkeeper-2.2.1/spec/dummy/app/controllers/custom_authorizations_controller.rb 0000644 0000764 0000764 00000000311 12544753400 027366 0 ustar pravi pravi class CustomAuthorizationsController < ::ApplicationController
%w(index show new create edit update destroy).each do |action|
define_method action do
render nothing: true
end
end
end
doorkeeper-2.2.1/spec/dummy/app/controllers/application_controller.rb 0000644 0000764 0000764 00000000120 12544753400 025212 0 ustar pravi pravi class ApplicationController < ActionController::Base
protect_from_forgery
end
doorkeeper-2.2.1/spec/dummy/Rakefile 0000644 0000764 0000764 00000000416 12544753400 016446 0 ustar pravi pravi #!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Dummy::Application.load_tasks
doorkeeper-2.2.1/spec/generators/ 0000755 0000764 0000764 00000000000 12544753400 016016 5 ustar pravi pravi doorkeeper-2.2.1/spec/generators/migration_generator_spec.rb 0000644 0000764 0000764 00000000763 12544753400 023422 0 ustar pravi pravi require 'spec_helper_integration'
require 'generators/doorkeeper/migration_generator'
describe 'Doorkeeper::MigrationGenerator' do
include GeneratorSpec::TestCase
tests Doorkeeper::MigrationGenerator
destination ::File.expand_path('../tmp/dummy', __FILE__)
describe 'after running the generator' do
before :each do
prepare_destination
run_generator
end
it 'creates a migration' do
assert_migration 'db/migrate/create_doorkeeper_tables.rb'
end
end
end
doorkeeper-2.2.1/spec/generators/views_generator_spec.rb 0000644 0000764 0000764 00000001635 12544753400 022565 0 ustar pravi pravi require 'spec_helper_integration'
require 'generators/doorkeeper/views_generator'
describe Doorkeeper::Generators::ViewsGenerator do
include GeneratorSpec::TestCase
tests Doorkeeper::Generators::ViewsGenerator
destination File.expand_path('../tmp/dummy', __FILE__)
before :each do
prepare_destination
end
it 'create all views' do
run_generator
assert_file 'app/views/doorkeeper/applications/_form.html.erb'
assert_file 'app/views/doorkeeper/applications/edit.html.erb'
assert_file 'app/views/doorkeeper/applications/index.html.erb'
assert_file 'app/views/doorkeeper/applications/new.html.erb'
assert_file 'app/views/doorkeeper/applications/show.html.erb'
assert_file 'app/views/doorkeeper/authorizations/error.html.erb'
assert_file 'app/views/doorkeeper/authorizations/new.html.erb'
assert_file 'app/views/doorkeeper/authorized_applications/index.html.erb'
end
end
doorkeeper-2.2.1/spec/generators/install_generator_spec.rb 0000644 0000764 0000764 00000001740 12544753400 023073 0 ustar pravi pravi require 'spec_helper_integration'
require 'generators/doorkeeper/install_generator'
describe 'Doorkeeper::InstallGenerator' do
include GeneratorSpec::TestCase
tests Doorkeeper::InstallGenerator
destination ::File.expand_path('../tmp/dummy', __FILE__)
describe 'after running the generator' do
before :each do
prepare_destination
FileUtils.mkdir(::File.expand_path('config', Pathname(destination_root)))
FileUtils.mkdir(::File.expand_path('db', Pathname(destination_root)))
FileUtils.copy_file(::File.expand_path('../templates/routes.rb', __FILE__), ::File.expand_path('config/routes.rb', Pathname.new(destination_root)))
run_generator
end
it 'creates an initializer file' do
assert_file 'config/initializers/doorkeeper.rb'
end
it 'copies the locale file' do
assert_file 'config/locales/doorkeeper.en.yml'
end
it 'adds sample route' do
assert_file 'config/routes.rb', /use_doorkeeper/
end
end
end
doorkeeper-2.2.1/spec/generators/templates/ 0000755 0000764 0000764 00000000000 12544753400 020014 5 ustar pravi pravi doorkeeper-2.2.1/spec/generators/templates/routes.rb 0000644 0000764 0000764 00000000046 12544753400 021662 0 ustar pravi pravi Rails.application.routes.draw do
end
doorkeeper-2.2.1/spec/generators/application_owner_generator_spec.rb 0000644 0000764 0000764 00000001363 12544753400 025143 0 ustar pravi pravi require 'spec_helper_integration'
require 'generators/doorkeeper/application_owner_generator'
describe 'Doorkeeper::ApplicationOwnerGenerator' do
include GeneratorSpec::TestCase
tests Doorkeeper::ApplicationOwnerGenerator
destination ::File.expand_path('../tmp/dummy', __FILE__)
describe 'after running the generator' do
before :each do
prepare_destination
FileUtils.mkdir(::File.expand_path('config', Pathname(destination_root)))
FileUtils.copy_file(::File.expand_path('../templates/routes.rb', __FILE__), ::File.expand_path('config/routes.rb', Pathname.new(destination_root)))
run_generator
end
it 'creates a migration' do
assert_migration 'db/migrate/add_owner_to_application.rb'
end
end
end
doorkeeper-2.2.1/spec/lib/ 0000755 0000764 0000764 00000000000 12544753400 014413 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/server_spec.rb 0000644 0000764 0000764 00000003025 12544753400 017260 0 ustar pravi pravi require 'spec_helper'
require 'active_support/all'
require 'doorkeeper/errors'
require 'doorkeeper/server'
describe Doorkeeper::Server do
let(:fake_class) { double :fake_class }
subject do
described_class.new
end
describe '.authorization_request' do
it 'raises error when strategy does not exist' do
expect do
subject.authorization_request(:duh)
end.to raise_error(Doorkeeper::Errors::InvalidAuthorizationStrategy)
end
it 'raises error when strategy does not match phase' do
expect do
subject.token_request(:code)
end.to raise_error(Doorkeeper::Errors::InvalidTokenStrategy)
end
context 'when only Authorization Code strategy is enabled' do
before do
allow(Doorkeeper.configuration).
to receive(:grant_flows).
and_return(['authorization_code'])
end
it 'raises error when using the disabled Implicit strategy' do
expect do
subject.authorization_request(:token)
end.to raise_error(Doorkeeper::Errors::InvalidAuthorizationStrategy)
end
it 'raises error when using the disabled Client Credentials strategy' do
expect do
subject.token_request(:client_credentials)
end.to raise_error(Doorkeeper::Errors::InvalidTokenStrategy)
end
end
it 'builds the request with selected strategy' do
stub_const 'Doorkeeper::Request::Code', fake_class
expect(fake_class).to receive(:build).with(subject)
subject.authorization_request :code
end
end
end
doorkeeper-2.2.1/spec/lib/config_spec.rb 0000644 0000764 0000764 00000021211 12544753400 017214 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper, 'configuration' do
subject { Doorkeeper.configuration }
describe 'resource_owner_authenticator' do
it 'sets the block that is accessible via authenticate_resource_owner' do
block = proc {}
Doorkeeper.configure do
orm DOORKEEPER_ORM
resource_owner_authenticator &block
end
expect(subject.authenticate_resource_owner).to eq(block)
end
end
describe 'setup_orm_adapter' do
it 'adds specific error message to NameError exception' do
expect do
Doorkeeper.configure { orm 'hibernate' }
end.to raise_error(NameError, /ORM adapter not found \(hibernate\)/)
end
it 'does not change other exceptions' do
allow_any_instance_of(String).to receive(:classify) { raise NoMethodError }
expect do
Doorkeeper.configure { orm 'hibernate' }
end.to raise_error(NoMethodError, /ORM adapter not found \(hibernate\)/)
end
end
describe 'admin_authenticator' do
it 'sets the block that is accessible via authenticate_admin' do
block = proc {}
Doorkeeper.configure do
orm DOORKEEPER_ORM
admin_authenticator(&block)
end
expect(subject.authenticate_admin).to eq(block)
end
end
describe 'access_token_expires_in' do
it 'has 2 hours by default' do
expect(subject.access_token_expires_in).to eq(2.hours)
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_expires_in 4.hours
end
expect(subject.access_token_expires_in).to eq(4.hours)
end
it 'can be set to nil' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_expires_in nil
end
expect(subject.access_token_expires_in).to be_nil
end
end
describe 'scopes' do
it 'has default scopes' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
default_scopes :public
end
expect(subject.default_scopes).to include('public')
end
it 'has optional scopes' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
optional_scopes :write, :update
end
expect(subject.optional_scopes).to include('write', 'update')
end
it 'has all scopes' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
default_scopes :normal
optional_scopes :admin
end
expect(subject.scopes).to include('normal', 'admin')
end
end
describe 'use_refresh_token' do
it 'is false by default' do
expect(subject.refresh_token_enabled?).to be_falsey
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
use_refresh_token
end
expect(subject.refresh_token_enabled?).to be_truthy
end
it "does not includes 'refresh_token' in authorization_response_types" do
expect(subject.token_grant_types).not_to include 'refresh_token'
end
context "is enabled" do
before do
Doorkeeper.configure {
orm DOORKEEPER_ORM
use_refresh_token
}
end
it "includes 'refresh_token' in authorization_response_types" do
expect(subject.token_grant_types).to include 'refresh_token'
end
end
end
describe 'client_credentials' do
it 'has defaults order' do
expect(subject.client_credentials_methods).to eq([:from_basic, :from_params])
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
client_credentials :from_digest, :from_params
end
expect(subject.client_credentials_methods).to eq([:from_digest, :from_params])
end
end
describe 'force_ssl_in_redirect_uri' do
it 'is true by default in non-development environments' do
expect(subject.force_ssl_in_redirect_uri).to be_truthy
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
force_ssl_in_redirect_uri(false)
end
expect(subject.force_ssl_in_redirect_uri).to be_falsey
end
end
describe 'access_token_credentials' do
it 'has defaults order' do
expect(subject.access_token_methods).to eq([:from_bearer_authorization, :from_access_token_param, :from_bearer_param])
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_methods :from_access_token_param, :from_bearer_param
end
expect(subject.access_token_methods).to eq([:from_access_token_param, :from_bearer_param])
end
end
describe 'enable_application_owner' do
it 'is disabled by default' do
expect(Doorkeeper.configuration.enable_application_owner?).not_to be_truthy
end
context 'when enabled without confirmation' do
before do
Doorkeeper.configure do
orm DOORKEEPER_ORM
enable_application_owner
end
end
it 'adds support for application owner' do
expect(Doorkeeper::Application.new).to respond_to :owner
end
it 'Doorkeeper.configuration.confirm_application_owner? returns false' do
expect(Doorkeeper.configuration.confirm_application_owner?).not_to be_truthy
end
end
context 'when enabled with confirmation set to true' do
before do
Doorkeeper.configure do
orm DOORKEEPER_ORM
enable_application_owner confirmation: true
end
end
it 'adds support for application owner' do
expect(Doorkeeper::Application.new).to respond_to :owner
end
it 'Doorkeeper.configuration.confirm_application_owner? returns true' do
expect(Doorkeeper.configuration.confirm_application_owner?).to be_truthy
end
end
end
describe 'realm' do
it 'is \'Doorkeeper\' by default' do
expect(Doorkeeper.configuration.realm).to eq('Doorkeeper')
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
realm 'Example'
end
expect(subject.realm).to eq('Example')
end
end
describe "grant_flows" do
it "is set to all grant flows by default" do
expect(Doorkeeper.configuration.grant_flows).
to eq(%w(authorization_code client_credentials))
end
it "can change the value" do
Doorkeeper.configure {
orm DOORKEEPER_ORM
grant_flows [ 'authorization_code', 'implicit' ]
}
expect(subject.grant_flows).to eq ['authorization_code', 'implicit']
end
context "when including 'authorization_code'" do
before do
Doorkeeper.configure {
orm DOORKEEPER_ORM
grant_flows ['authorization_code']
}
end
it "includes 'code' in authorization_response_types" do
expect(subject.authorization_response_types).to include 'code'
end
it "includes 'authorization_code' in token_grant_types" do
expect(subject.token_grant_types).to include 'authorization_code'
end
end
context "when including 'implicit'" do
before do
Doorkeeper.configure {
orm DOORKEEPER_ORM
grant_flows ['implicit']
}
end
it "includes 'token' in authorization_response_types" do
expect(subject.authorization_response_types).to include 'token'
end
end
context "when including 'password'" do
before do
Doorkeeper.configure {
orm DOORKEEPER_ORM
grant_flows ['password']
}
end
it "includes 'password' in token_grant_types" do
expect(subject.token_grant_types).to include 'password'
end
end
context "when including 'client_credentials'" do
before do
Doorkeeper.configure {
orm DOORKEEPER_ORM
grant_flows ['client_credentials']
}
end
it "includes 'client_credentials' in token_grant_types" do
expect(subject.token_grant_types).to include 'client_credentials'
end
end
end
it 'raises an exception when configuration is not set' do
old_config = Doorkeeper.configuration
Doorkeeper.module_eval do
@config = nil
end
expect do
Doorkeeper.configuration
end.to raise_error Doorkeeper::MissingConfiguration
Doorkeeper.module_eval do
@config = old_config
end
end
describe 'access_token_generator' do
it 'is \'Doorkeeper::OAuth::Helpers::UniqueToken\' by default' do
expect(Doorkeeper.configuration.access_token_generator).to(
eq('Doorkeeper::OAuth::Helpers::UniqueToken')
)
end
it 'can change the value' do
Doorkeeper.configure do
orm DOORKEEPER_ORM
access_token_generator 'Example'
end
expect(subject.access_token_generator).to eq('Example')
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/ 0000755 0000764 0000764 00000000000 12544753400 015533 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/oauth/invalid_token_response_spec.rb 0000644 0000764 0000764 00000001426 12544753400 023641 0 ustar pravi pravi require 'spec_helper'
require 'active_model'
require 'doorkeeper'
require 'doorkeeper/oauth/invalid_token_response'
module Doorkeeper::OAuth
describe InvalidTokenResponse do
describe '#name' do
it { expect(subject.name).to eq(:invalid_token) }
end
describe '#status' do
it { expect(subject.status).to eq(:unauthorized) }
end
describe :from_access_token do
it 'revoked' do
response = InvalidTokenResponse.from_access_token double(revoked?: true, expired?: true)
expect(response.description).to include('revoked')
end
it 'expired' do
response = InvalidTokenResponse.from_access_token double(revoked?: false, expired?: true)
expect(response.description).to include('expired')
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/authorization/ 0000755 0000764 0000764 00000000000 12544753400 020433 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/oauth/authorization/uri_builder_spec.rb 0000644 0000764 0000764 00000002625 12544753400 024304 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/string'
require 'uri'
require 'rack/utils'
require 'doorkeeper/oauth/authorization/uri_builder'
module Doorkeeper::OAuth::Authorization
describe URIBuilder do
subject { Object.new.class.send :include, URIBuilder }
describe :uri_with_query do
it 'returns the uri with query' do
uri = subject.uri_with_query 'http://example.com/', parameter: 'value'
expect(uri).to eq('http://example.com/?parameter=value')
end
it 'rejects nil values' do
uri = subject.uri_with_query 'http://example.com/', parameter: ''
expect(uri).to eq('http://example.com/?')
end
it 'preserves original query parameters' do
uri = subject.uri_with_query 'http://example.com/?query1=value', parameter: 'value'
expect(uri).to match(/query1=value/)
expect(uri).to match(/parameter=value/)
end
end
describe :uri_with_fragment do
it 'returns uri with parameters as fragments' do
uri = subject.uri_with_fragment 'http://example.com/', parameter: 'value'
expect(uri).to eq('http://example.com/#parameter=value')
end
it 'preserves original query parameters' do
uri = subject.uri_with_fragment 'http://example.com/?query1=value1', parameter: 'value'
expect(uri).to eq('http://example.com/?query1=value1#parameter=value')
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_credentials/ 0000755 0000764 0000764 00000000000 12544753400 021366 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/oauth/client_credentials/issuer_spec.rb 0000644 0000764 0000764 00000004564 12544753400 024250 0 ustar pravi pravi require 'spec_helper'
require 'active_support/all'
require 'doorkeeper/oauth/client_credentials/issuer'
class Doorkeeper::OAuth::ClientCredentialsRequest
describe Issuer do
let(:creator) { double :acces_token_creator }
let(:server) do
double(
:server,
access_token_expires_in: 100,
custom_access_token_expires_in: ->(_app) { nil }
)
end
let(:validation) { double :validation, valid?: true }
subject { Issuer.new(server, validation) }
describe :create do
let(:client) { double :client, id: 'some-id' }
let(:scopes) { 'some scope' }
it 'creates and sets the token' do
expect(creator).to receive(:call).and_return('token')
subject.create client, scopes, creator
expect(subject.token).to eq('token')
end
it 'creates with correct token parameters' do
expect(creator).to receive(:call).with(
client,
scopes,
expires_in: 100,
use_refresh_token: false
)
subject.create client, scopes, creator
end
it 'has error set to :server_error if creator fails' do
expect(creator).to receive(:call).and_return(false)
subject.create client, scopes, creator
expect(subject.error).to eq(:server_error)
end
context 'when validation fails' do
before do
allow(validation).to receive(:valid?).and_return(false)
allow(validation).to receive(:error).and_return(:validation_error)
expect(creator).not_to receive(:create)
end
it 'has error set from validation' do
subject.create client, scopes, creator
expect(subject.error).to eq(:validation_error)
end
it 'returns false' do
expect(subject.create(client, scopes, creator)).to be_falsey
end
end
context 'with custom expirations' do
let(:custom_ttl) { 1233 }
let(:server) do
double(
:server,
custom_access_token_expires_in: ->(_app) { custom_ttl }
)
end
it 'creates with correct token parameters' do
expect(creator).to receive(:call).with(
client,
scopes,
expires_in: custom_ttl,
use_refresh_token: false
)
subject.create client, scopes, creator
end
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_credentials/creator_spec.rb 0000644 0000764 0000764 00000001132 12544753400 024361 0 ustar pravi pravi require 'spec_helper_integration'
class Doorkeeper::OAuth::ClientCredentialsRequest
describe Creator do
let(:client) { FactoryGirl.create :application }
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public') }
it 'creates a new token' do
expect do
subject.call(client, scopes)
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'returns false if creation fails' do
expect(Doorkeeper::AccessToken).to receive(:create).and_return(false)
created = subject.call(client, scopes)
expect(created).to be_falsey
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_credentials/validation_spec.rb 0000644 0000764 0000764 00000004245 12544753400 025064 0 ustar pravi pravi require 'spec_helper'
require 'active_support/all'
require 'doorkeeper/oauth/client_credentials/validation'
class Doorkeeper::OAuth::ClientCredentialsRequest
describe Validation do
let(:server) { double :server, scopes: nil }
let(:application) { double scopes: nil }
let(:client) { double application: application }
let(:request) { double :request, client: client, scopes: nil }
subject { Validation.new(server, request) }
it 'is valid with valid request' do
expect(subject).to be_valid
end
it 'is invalid when client is not present' do
allow(request).to receive(:client).and_return(nil)
expect(subject).not_to be_valid
end
context 'with scopes' do
it 'is invalid when scopes are not included in the server' do
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email'
allow(server).to receive(:scopes).and_return(server_scopes)
allow(request).to receive(:scopes).and_return(
Doorkeeper::OAuth::Scopes.from_string 'invalid')
expect(subject).not_to be_valid
end
context 'with application scopes' do
it 'is valid when scopes are included in the application' do
application_scopes = Doorkeeper::OAuth::Scopes.from_string 'app'
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email app'
allow(application).to receive(:scopes).and_return(application_scopes)
allow(server).to receive(:scopes).and_return(server_scopes)
allow(request).to receive(:scopes).and_return(application_scopes)
expect(subject).to be_valid
end
it 'is invalid when scopes are not included in the application' do
application_scopes = Doorkeeper::OAuth::Scopes.from_string 'app'
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email app'
allow(application).to receive(:scopes).and_return(application_scopes)
allow(server).to receive(:scopes).and_return(server_scopes)
allow(request).to receive(:scopes).and_return(
Doorkeeper::OAuth::Scopes.from_string 'email')
expect(subject).not_to be_valid
end
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/refresh_token_request_spec.rb 0000644 0000764 0000764 00000007615 12544753400 023511 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe RefreshTokenRequest do
let(:server) do
double :server,
access_token_expires_in: 2.minutes,
custom_access_token_expires_in: -> (_oauth_client) { nil }
end
let(:refresh_token) do
FactoryGirl.create(:access_token, use_refresh_token: true)
end
let(:client) { refresh_token.application }
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
subject { RefreshTokenRequest.new server, refresh_token, credentials }
it 'issues a new token for the client' do
expect do
subject.authorize
end.to change { client.access_tokens.count }.by(1)
expect(client.reload.access_tokens.last.expires_in).to eq(120)
end
it 'issues a new token for the client with custom expires_in' do
server = double :server,
access_token_expires_in: 2.minutes,
custom_access_token_expires_in: ->(_oauth_client) { 1234 }
RefreshTokenRequest.new(server, refresh_token, credentials).authorize
expect(client.reload.access_tokens.last.expires_in).to eq(1234)
end
it 'revokes the previous token' do
expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
end
it 'requires the refresh token' do
subject.refresh_token = nil
subject.validate
expect(subject.error).to eq(:invalid_request)
end
it 'requires credentials to be valid if provided' do
subject.client = nil
subject.validate
expect(subject.error).to eq(:invalid_client)
end
it "requires the token's client and current client to match" do
subject.client = FactoryGirl.create(:application)
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'rejects revoked tokens' do
refresh_token.revoke
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'accepts expired tokens' do
refresh_token.expires_in = -1
refresh_token.save
subject.validate
expect(subject).to be_valid
end
context 'clientless access tokens' do
let!(:refresh_token) { FactoryGirl.create(:clientless_access_token, use_refresh_token: true) }
subject { RefreshTokenRequest.new server, refresh_token, nil }
it 'issues a new token without a client' do
expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
end
end
context 'with scopes' do
let(:refresh_token) do
FactoryGirl.create :access_token,
use_refresh_token: true,
scopes: 'public write'
end
let(:parameters) { {} }
subject { RefreshTokenRequest.new server, refresh_token, credentials, parameters }
it 'transfers scopes from the old token to the new token' do
subject.authorize
expect(Doorkeeper::AccessToken.last.scopes).to eq([:public, :write])
end
it 'reduces scopes to the provided scopes' do
parameters[:scopes] = 'public'
subject.authorize
expect(Doorkeeper::AccessToken.last.scopes).to eq([:public])
end
it 'validates that scopes are included in the original access token' do
parameters[:scopes] = 'public update'
subject.validate
expect(subject.error).to eq(:invalid_scope)
end
it 'uses params[:scope] in favor of scopes if present (valid)' do
parameters[:scopes] = 'public update'
parameters[:scope] = 'public'
subject.authorize
expect(Doorkeeper::AccessToken.last.scopes).to eq([:public])
end
it 'uses params[:scope] in favor of scopes if present (invalid)' do
parameters[:scopes] = 'public'
parameters[:scope] = 'public update'
subject.validate
expect(subject.error).to eq(:invalid_scope)
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/token_request_spec.rb 0000644 0000764 0000764 00000005352 12544753400 021767 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe TokenRequest do
let :application do
scopes = double(all: ['public'])
double(:application, id: 9990, scopes: scopes)
end
let :pre_auth do
double(
:pre_auth,
client: application,
redirect_uri: 'http://tst.com/cb',
state: nil,
scopes: Scopes.from_string('public'),
error: nil,
authorizable?: true
)
end
let :owner do
double :owner, id: 7866
end
subject do
TokenRequest.new(pre_auth, owner)
end
it 'creates an access token' do
expect do
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'returns a code response' do
expect(subject.authorize).to be_a(CodeResponse)
end
it 'does not create token when not authorizable' do
allow(pre_auth).to receive(:authorizable?).and_return(false)
expect do
subject.authorize
end.to_not change { Doorkeeper::AccessToken.count }
end
it 'returns a error response' do
allow(pre_auth).to receive(:authorizable?).and_return(false)
expect(subject.authorize).to be_a(ErrorResponse)
end
context 'with custom expirations' do
before do
Doorkeeper.configure do
orm DOORKEEPER_ORM
custom_access_token_expires_in do |_oauth_client|
1234
end
end
end
it 'should use the custom ttl' do
subject.authorize
token = Doorkeeper::AccessToken.first
expect(token.expires_in).to eq(1234)
end
end
context 'token reuse' do
it 'creates a new token if there are no matching tokens' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
expect do
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'creates a new token if scopes do not match' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
FactoryGirl.create(:access_token, application_id: pre_auth.client.id,
resource_owner_id: owner.id, scopes: '')
expect do
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'skips token creation if there is a matching one' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
FactoryGirl.create(:access_token, application_id: pre_auth.client.id,
resource_owner_id: owner.id, scopes: 'public')
expect do
subject.authorize
end.to_not change { Doorkeeper::AccessToken.count }
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/pre_authorization_spec.rb 0000644 0000764 0000764 00000010504 12544753400 022640 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe PreAuthorization do
let(:server) {
server = Doorkeeper.configuration
allow(server).to receive(:default_scopes).and_return(Scopes.new)
allow(server).to receive(:scopes).and_return(Scopes.from_string('public profile'))
server
}
let(:application) do
application = double :application
allow(application).to receive(:scopes).and_return(Scopes.from_string(''))
application
end
let(:client) do
double :client, redirect_uri: 'http://tst.com/auth', application: application
end
let :attributes do
{
response_type: 'code',
redirect_uri: 'http://tst.com/auth',
state: 'save-this'
}
end
subject do
PreAuthorization.new(server, client, attributes)
end
it 'is authorizable when request is valid' do
expect(subject).to be_authorizable
end
it 'accepts code as response type' do
subject.response_type = 'code'
expect(subject).to be_authorizable
end
it 'accepts token as response type' do
allow(server).to receive(:grant_flows).and_return(['implicit'])
subject.response_type = 'token'
expect(subject).to be_authorizable
end
context 'when using default grant flows' do
it 'accepts "code" as response type' do
subject.response_type = 'code'
expect(subject).to be_authorizable
end
it 'accepts "token" as response type' do
allow(server).to receive(:grant_flows).and_return(['implicit'])
subject.response_type = 'token'
expect(subject).to be_authorizable
end
end
context 'when authorization code grant flow is disabled' do
before do
allow(server).to receive(:grant_flows).and_return(['implicit'])
end
it 'does not accept "code" as response type' do
subject.response_type = 'code'
expect(subject).not_to be_authorizable
end
end
context 'when implicit grant flow is disabled' do
before do
allow(server).to receive(:grant_flows).and_return(['authorization_code'])
end
it 'does not accept "token" as response type' do
subject.response_type = 'token'
expect(subject).not_to be_authorizable
end
end
context 'client application does not restrict valid scopes' do
it 'accepts valid scopes' do
subject.scope = 'public'
expect(subject).to be_authorizable
end
it 'rejects (globally) non-valid scopes' do
subject.scope = 'invalid'
expect(subject).not_to be_authorizable
end
end
context 'client application restricts valid scopes' do
let(:application) do
application = double :application
allow(application).to receive(:scopes).and_return(Scopes.from_string('public nonsense'))
application
end
it 'accepts valid scopes' do
subject.scope = 'public'
expect(subject).to be_authorizable
end
it 'rejects (globally) non-valid scopes' do
subject.scope = 'invalid'
expect(subject).not_to be_authorizable
end
it 'rejects (application level) non-valid scopes' do
subject.scope = 'profile'
expect(subject).to_not be_authorizable
end
end
it 'uses default scopes when none is required' do
allow(server).to receive(:default_scopes).and_return(Scopes.from_string('default'))
subject.scope = nil
expect(subject.scope).to eq('default')
expect(subject.scopes).to eq(Scopes.from_string('default'))
end
it 'accepts test uri' do
subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
expect(subject).to be_authorizable
end
it 'matches the redirect uri against client\'s one' do
subject.redirect_uri = 'http://nothesame.com'
expect(subject).not_to be_authorizable
end
it 'stores the state' do
expect(subject.state).to eq('save-this')
end
it 'rejects if response type is not allowed' do
subject.response_type = 'whops'
expect(subject).not_to be_authorizable
end
it 'requires an existing client' do
subject.client = nil
expect(subject).not_to be_authorizable
end
it 'requires a redirect uri' do
subject.redirect_uri = nil
expect(subject).not_to be_authorizable
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/error_response_spec.rb 0000644 0000764 0000764 00000003601 12544753400 022141 0 ustar pravi pravi require 'spec_helper'
require 'active_model'
require 'doorkeeper/oauth/error'
require 'doorkeeper/oauth/error_response'
module Doorkeeper::OAuth
describe ErrorResponse do
describe '#status' do
it 'should have a status of unauthorized' do
expect(subject.status).to eq(:unauthorized)
end
end
describe :from_request do
it 'has the error from request' do
error = ErrorResponse.from_request double(error: :some_error)
expect(error.name).to eq(:some_error)
end
it 'ignores state if request does not respond to state' do
error = ErrorResponse.from_request double(error: :some_error)
expect(error.state).to be_nil
end
it 'has state if request responds to state' do
error = ErrorResponse.from_request double(error: :some_error, state: :hello)
expect(error.state).to eq(:hello)
end
end
it 'ignores empty error values' do
subject = ErrorResponse.new(error: :some_error, state: nil)
expect(subject.body).not_to have_key(:state)
end
describe '.body' do
subject { ErrorResponse.new(name: :some_error, state: :some_state).body }
describe '#body' do
it { should have_key(:error) }
it { should have_key(:error_description) }
it { should have_key(:state) }
end
end
describe '.authenticate_info' do
let(:error_response) { ErrorResponse.new(name: :some_error, state: :some_state) }
subject { error_response.authenticate_info }
it { should include("realm=\"#{error_response.realm}\"") }
it { should include("error=\"#{error_response.name}\"") }
it { should include("error_description=\"#{error_response.description}\"") }
end
describe '.headers' do
subject { ErrorResponse.new(name: :some_error, state: :some_state).headers }
it { should include 'WWW-Authenticate' }
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/helpers/ 0000755 0000764 0000764 00000000000 12544753400 017175 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/oauth/helpers/uri_checker_spec.rb 0000644 0000764 0000764 00000006433 12544753400 023025 0 ustar pravi pravi require 'spec_helper'
require 'uri'
require 'doorkeeper/oauth/helpers/uri_checker'
module Doorkeeper::OAuth::Helpers
describe URIChecker do
describe '.valid?' do
it 'is valid for valid uris' do
uri = 'http://app.co'
expect(URIChecker.valid?(uri)).to be_truthy
end
it 'is valid if include path param' do
uri = 'http://app.co/path'
expect(URIChecker.valid?(uri)).to be_truthy
end
it 'is valid if include query param' do
uri = 'http://app.co/?query=1'
expect(URIChecker.valid?(uri)).to be_truthy
end
it 'is invalid if uri includes fragment' do
uri = 'http://app.co/test#fragment'
expect(URIChecker.valid?(uri)).to be_falsey
end
it 'is invalid if scheme is missing' do
uri = 'app.co'
expect(URIChecker.valid?(uri)).to be_falsey
end
it 'is invalid if is a relative uri' do
uri = '/abc/123'
expect(URIChecker.valid?(uri)).to be_falsey
end
it 'is invalid if is not a url' do
uri = 'http://'
expect(URIChecker.valid?(uri)).to be_falsey
end
end
describe '.matches?' do
it 'is true if both url matches' do
uri = client_uri = 'http://app.co/aaa'
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
end
it 'ignores query parameter on comparsion' do
uri = 'http://app.co/?query=hello'
client_uri = 'http://app.co'
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
end
it 'doesn\'t allow non-matching domains through' do
uri = 'http://app.abc/?query=hello'
client_uri = 'http://app.co'
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
end
it 'doesn\'t allow non-matching domains that don\'t start at the beginning' do
uri = 'http://app.co/?query=hello'
client_uri = 'http://example.com?app.co=test'
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
end
end
describe '.valid_for_authorization?' do
it 'is true if valid and matches' do
uri = client_uri = 'http://app.co/aaa'
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
end
it 'is false if valid and mismatches' do
uri = 'http://app.co/aaa'
client_uri = 'http://app.co/bbb'
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
end
it 'is true if valid and included in array' do
uri = 'http://app.co/aaa'
client_uri = "http://example.com/bbb\nhttp://app.co/aaa"
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
end
it 'is false if valid and not included in array' do
uri = 'http://app.co/aaa'
client_uri = "http://example.com/bbb\nhttp://app.co/cc"
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
end
it 'is true if valid and matches' do
uri = client_uri = 'http://app.co/aaa'
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be true
end
it 'is false if invalid' do
uri = client_uri = 'http://app.co/aaa?waffles=abc'
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/helpers/scope_checker_spec.rb 0000644 0000764 0000764 00000003575 12544753400 023343 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/helpers/scope_checker'
require 'doorkeeper/oauth/scopes'
module Doorkeeper::OAuth::Helpers
describe ScopeChecker, '.valid?' do
let(:server_scopes) { Doorkeeper::OAuth::Scopes.new }
it 'is valid if scope is present' do
server_scopes.add :scope
expect(ScopeChecker.valid?('scope', server_scopes)).to be_truthy
end
it 'is invalid if includes tabs space' do
expect(ScopeChecker.valid?("\tsomething", server_scopes)).to be_falsey
end
it 'is invalid if scope is not present' do
expect(ScopeChecker.valid?(nil, server_scopes)).to be_falsey
end
it 'is invalid if scope is blank' do
expect(ScopeChecker.valid?(' ', server_scopes)).to be_falsey
end
it 'is invalid if includes return space' do
expect(ScopeChecker.valid?("scope\r", server_scopes)).to be_falsey
end
it 'is invalid if includes new lines' do
expect(ScopeChecker.valid?("scope\nanother", server_scopes)).to be_falsey
end
it 'is invalid if any scope is not included in server scopes' do
expect(ScopeChecker.valid?('scope another', server_scopes)).to be_falsey
end
context 'with application_scopes' do
let(:server_scopes) do
Doorkeeper::OAuth::Scopes.from_string 'common svr'
end
let(:application_scopes) do
Doorkeeper::OAuth::Scopes.from_string 'common'
end
it 'is valid if scope is included in the server and the application' do
expect(ScopeChecker.valid?(
'common',
server_scopes,
application_scopes
)).to be_truthy
end
it 'is invalid if any scope is not included in the application' do
expect(ScopeChecker.valid?(
'svr',
server_scopes,
application_scopes
)).to be_falsey
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/helpers/unique_token_spec.rb 0000644 0000764 0000764 00000001007 12544753400 023240 0 ustar pravi pravi require 'spec_helper'
require 'doorkeeper/oauth/helpers/unique_token'
module Doorkeeper::OAuth::Helpers
describe UniqueToken do
let :generator do
->(size) { 'a' * size }
end
it 'is able to customize the generator method' do
token = UniqueToken.generate(generator: generator)
expect(token).to eq('a' * 32)
end
it 'is able to customize the size of the token' do
token = UniqueToken.generate(generator: generator, size: 2)
expect(token).to eq('aa')
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/token_spec.rb 0000644 0000764 0000764 00000007160 12544753400 020216 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/token'
module Doorkeeper
unless defined?(AccessToken)
class AccessToken
end
end
module OAuth
describe Token do
describe :from_request do
let(:request) { double.as_null_object }
let(:method) do
->(request) { return 'token-value' }
end
it 'accepts anything that responds to #call' do
expect(method).to receive(:call).with(request)
Token.from_request request, method
end
it 'delegates methods received as symbols to Token class' do
expect(Token).to receive(:from_params).with(request)
Token.from_request request, :from_params
end
it 'stops at the first credentials found' do
not_called_method = double
expect(not_called_method).not_to receive(:call)
Token.from_request request, ->(r) {}, method, not_called_method
end
it 'returns the credential from extractor method' do
credentials = Token.from_request request, method
expect(credentials).to eq('token-value')
end
end
describe :from_access_token_param do
it 'returns token from access_token parameter' do
request = double parameters: { access_token: 'some-token' }
token = Token.from_access_token_param(request)
expect(token).to eq('some-token')
end
end
describe :from_bearer_param do
it 'returns token from bearer_token parameter' do
request = double parameters: { bearer_token: 'some-token' }
token = Token.from_bearer_param(request)
expect(token).to eq('some-token')
end
end
describe :from_bearer_authorization do
it 'returns token from capitalized authorization bearer' do
request = double authorization: 'Bearer SomeToken'
token = Token.from_bearer_authorization(request)
expect(token).to eq('SomeToken')
end
it 'returns token from lowercased authorization bearer' do
request = double authorization: 'bearer SomeToken'
token = Token.from_bearer_authorization(request)
expect(token).to eq('SomeToken')
end
it 'does not return token if authorization is not bearer' do
request = double authorization: 'MAC SomeToken'
token = Token.from_bearer_authorization(request)
expect(token).to be_blank
end
end
describe :from_basic_authorization do
it 'returns token from capitalized authorization basic' do
request = double authorization: "Basic #{Base64.encode64 'SomeToken:'}"
token = Token.from_basic_authorization(request)
expect(token).to eq('SomeToken')
end
it 'returns token from lowercased authorization basic' do
request = double authorization: "basic #{Base64.encode64 'SomeToken:'}"
token = Token.from_basic_authorization(request)
expect(token).to eq('SomeToken')
end
it 'does not return token if authorization is not basic' do
request = double authorization: "MAC #{Base64.encode64 'SomeToken:'}"
token = Token.from_basic_authorization(request)
expect(token).to be_blank
end
end
describe :authenticate do
let(:finder) { double :finder }
it 'calls the finder if token was found' do
token = ->(r) { 'token' }
expect(AccessToken).to receive(:by_token).with('token')
Token.authenticate double, token
end
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/authorization_code_request_spec.rb 0000644 0000764 0000764 00000004415 12544753400 024540 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe AuthorizationCodeRequest do
let(:server) do
double :server,
access_token_expires_in: 2.days,
refresh_token_enabled?: false,
custom_access_token_expires_in: ->(_app) { nil }
end
let(:grant) { FactoryGirl.create :access_grant }
let(:client) { grant.application }
subject do
AuthorizationCodeRequest.new server, grant, client, redirect_uri: client.redirect_uri
end
it 'issues a new token for the client' do
expect do
subject.authorize
end.to change { client.access_tokens.count }.by(1)
end
it "issues the token with same grant's scopes" do
subject.authorize
expect(Doorkeeper::AccessToken.last.scopes).to eq(grant.scopes)
end
it 'revokes the grant' do
expect do
subject.authorize
end.to change { grant.reload.accessible? }
end
it 'requires the grant to be accessible' do
grant.revoke
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'requires the grant' do
subject.grant = nil
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'requires the client' do
subject.client = nil
subject.validate
expect(subject.error).to eq(:invalid_client)
end
it 'requires the redirect_uri' do
subject.redirect_uri = nil
subject.validate
expect(subject.error).to eq(:invalid_request)
end
it "matches the redirect_uri with grant's one" do
subject.redirect_uri = 'http://other.com'
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it "matches the client with grant's one" do
subject.client = FactoryGirl.create :application
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'skips token creation if there is a matching one' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
FactoryGirl.create(:access_token, application_id: client.id,
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
expect do
subject.authorize
end.to_not change { Doorkeeper::AccessToken.count }
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client/ 0000755 0000764 0000764 00000000000 12544753400 017011 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/oauth/client/methods_spec.rb 0000644 0000764 0000764 00000003002 12544753400 022006 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/client'
class Doorkeeper::OAuth::Client
describe 'Methods' do
let(:client_id) { 'some-uid' }
let(:client_secret) { 'some-secret' }
subject do
Class.new do
include Methods
end.new
end
describe :from_params do
it 'returns credentials from parameters when Authorization header is not available' do
request = double parameters: { client_id: client_id, client_secret: client_secret }
uid, secret = subject.from_params(request)
expect(uid).to eq('some-uid')
expect(secret).to eq('some-secret')
end
it 'is blank when there are no credentials' do
request = double parameters: {}
uid, secret = subject.from_params(request)
expect(uid).to be_blank
expect(secret).to be_blank
end
end
describe :from_basic do
let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
it 'decodes the credentials' do
request = double authorization: "Basic #{credentials}"
uid, secret = subject.from_basic(request)
expect(uid).to eq('some-uid')
expect(secret).to eq('some-secret')
end
it 'is blank if Authorization is not Basic' do
request = double authorization: "#{credentials}"
uid, secret = subject.from_basic(request)
expect(uid).to be_blank
expect(secret).to be_blank
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client/credentials_spec.rb 0000644 0000764 0000764 00000002755 12544753400 022656 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/client'
class Doorkeeper::OAuth::Client
describe Credentials do
it 'is blank when any of the credentials is blank' do
expect(Credentials.new(nil, 'something')).to be_blank
expect(Credentials.new('something', nil)).to be_blank
end
describe :from_request do
let(:request) { double.as_null_object }
let(:method) do
->(_request) { return 'uid', 'secret' }
end
it 'accepts anything that responds to #call' do
expect(method).to receive(:call).with(request)
Credentials.from_request request, method
end
it 'delegates methods received as symbols to Credentials class' do
expect(Credentials).to receive(:from_params).with(request)
Credentials.from_request request, :from_params
end
it 'stops at the first credentials found' do
not_called_method = double
expect(not_called_method).not_to receive(:call)
Credentials.from_request request, ->(_) {}, method, not_called_method
end
it 'returns new Credentials' do
credentials = Credentials.from_request request, method
expect(credentials).to be_a(Credentials)
end
it 'returns uid and secret from extractor method' do
credentials = Credentials.from_request request, method
expect(credentials.uid).to eq('uid')
expect(credentials.secret).to eq('secret')
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/token_response_spec.rb 0000644 0000764 0000764 00000004513 12544753400 022133 0 ustar pravi pravi require 'spec_helper'
require 'doorkeeper/oauth/token_response'
module Doorkeeper::OAuth
describe TokenResponse do
subject { TokenResponse.new(double.as_null_object) }
it 'includes access token response headers' do
headers = subject.headers
expect(headers.fetch('Cache-Control')).to eq('no-store')
expect(headers.fetch('Pragma')).to eq('no-cache')
end
it 'status is ok' do
expect(subject.status).to eq(:ok)
end
describe '.body' do
let(:access_token) do
double :access_token,
token: 'some-token',
expires_in: '3600',
expires_in_seconds: '300',
scopes_string: 'two scopes',
refresh_token: 'some-refresh-token',
token_type: 'bearer',
created_at: 0
end
subject { TokenResponse.new(access_token).body }
it 'includes :access_token' do
expect(subject['access_token']).to eq('some-token')
end
it 'includes :token_type' do
expect(subject['token_type']).to eq('bearer')
end
# expires_in_seconds is returned as `expires_in` in order to match
# the OAuth spec (section 4.2.2)
it 'includes :expires_in' do
expect(subject['expires_in']).to eq('300')
end
it 'includes :scope' do
expect(subject['scope']).to eq('two scopes')
end
it 'includes :refresh_token' do
expect(subject['refresh_token']).to eq('some-refresh-token')
end
it 'includes :created_at' do
expect(subject['created_at']).to eq(0)
end
end
describe '.body filters out empty values' do
let(:access_token) do
double :access_token,
token: 'some-token',
expires_in_seconds: '',
scopes_string: '',
refresh_token: '',
token_type: 'bearer',
created_at: 0
end
subject { TokenResponse.new(access_token).body }
it 'includes :expires_in' do
expect(subject['expires_in']).to be_nil
end
it 'includes :scope' do
expect(subject['scope']).to be_nil
end
it 'includes :refresh_token' do
expect(subject['refresh_token']).to be_nil
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/forbidden_token_response_spec.rb 0000644 0000764 0000764 00000001123 12544753400 024141 0 ustar pravi pravi require 'spec_helper'
require 'active_model'
require 'doorkeeper'
require 'doorkeeper/oauth/forbidden_token_response'
module Doorkeeper::OAuth
describe ForbiddenTokenResponse do
describe '#name' do
it { expect(subject.name).to eq(:invalid_scope) }
end
describe '#status' do
it { expect(subject.status).to eq(:forbidden) }
end
describe :from_scopes do
it 'should have a list of acceptable scopes' do
response = ForbiddenTokenResponse.from_scopes(["public"])
expect(response.description).to include('public')
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_spec.rb 0000644 0000764 0000764 00000002560 12544753400 020353 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/client'
module Doorkeeper::OAuth
describe Client do
describe :find do
let(:method) { double }
it 'finds the client via uid' do
client = double
expect(method).to receive(:call).with('uid').and_return(client)
expect(Client.find('uid', method)).to be_a(Client)
end
it 'returns nil if client was not found' do
expect(method).to receive(:call).with('uid').and_return(nil)
expect(Client.find('uid', method)).to be_nil
end
end
describe :authenticate do
it 'returns the authenticated client via credentials' do
credentials = Client::Credentials.new('some-uid', 'some-secret')
authenticator = double
expect(authenticator).to receive(:call).with('some-uid', 'some-secret').and_return(double)
expect(Client.authenticate(credentials, authenticator)).to be_a(Client)
end
it 'returns nil if client was not authenticated' do
credentials = Client::Credentials.new('some-uid', 'some-secret')
authenticator = double
expect(authenticator).to receive(:call).with('some-uid', 'some-secret').and_return(nil)
expect(Client.authenticate(credentials, authenticator)).to be_nil
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/code_request_spec.rb 0000644 0000764 0000764 00000002115 12544753400 021553 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe CodeRequest do
let(:pre_auth) do
double(
:pre_auth,
client: double(:application, id: 9990),
redirect_uri: 'http://tst.com/cb',
scopes: nil,
state: nil,
error: nil,
authorizable?: true
)
end
let(:owner) { double :owner, id: 8900 }
subject do
CodeRequest.new(pre_auth, owner)
end
it 'creates an access grant' do
expect do
subject.authorize
end.to change { Doorkeeper::AccessGrant.count }.by(1)
end
it 'returns a code response' do
expect(subject.authorize).to be_a(CodeResponse)
end
it 'does not create grant when not authorizable' do
allow(pre_auth).to receive(:authorizable?).and_return(false)
expect do
subject.authorize
end.to_not change { Doorkeeper::AccessGrant.count }
end
it 'returns a error response' do
allow(pre_auth).to receive(:authorizable?).and_return(false)
expect(subject.authorize).to be_a(ErrorResponse)
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/error_spec.rb 0000644 0000764 0000764 00000000765 12544753400 020233 0 ustar pravi pravi require 'spec_helper'
require 'active_support/i18n'
require 'doorkeeper/oauth/error'
module Doorkeeper::OAuth
describe Error do
subject { Error.new(:some_error, :some_state) }
it { should respond_to(:name) }
it { should respond_to(:state) }
describe :description do
it 'is translated from translation messages' do
expect(I18n).to receive(:translate).with(:some_error, scope: [:doorkeeper, :errors, :messages])
subject.description
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/scopes_spec.rb 0000644 0000764 0000764 00000007302 12544753400 020370 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/string'
require 'doorkeeper/oauth/scopes'
module Doorkeeper::OAuth
describe Scopes do
describe '#add' do
it 'allows you to add scopes with symbols' do
subject.add :public
expect(subject.all).to eq(['public'])
end
it 'allows you to add scopes with strings' do
subject.add 'public'
expect(subject.all).to eq(['public'])
end
it 'do not add already included scopes' do
subject.add :public
subject.add :public
expect(subject.all).to eq(['public'])
end
end
describe '#exists' do
before do
subject.add :public
end
it 'returns true if scope with given name is present' do
expect(subject.exists?('public')).to be_truthy
end
it 'returns false if scope with given name does not exist' do
expect(subject.exists?('other')).to be_falsey
end
it 'handles symbols' do
expect(subject.exists?(:public)).to be_truthy
expect(subject.exists?(:other)).to be_falsey
end
end
describe '.from_string' do
let(:string) { 'public write' }
subject { Scopes.from_string(string) }
it { should be_a(Scopes) }
describe '#all' do
it 'should be an array of the expected scopes' do
scopes_array = subject.all
expect(scopes_array.size).to eq(2)
expect(scopes_array).to include('public')
expect(scopes_array).to include('write')
end
end
end
describe '#+' do
it 'can add to another scope object' do
scopes = Scopes.from_string('public') + Scopes.from_string('admin')
expect(scopes.all).to eq(%w(public admin))
end
it 'does not change the existing object' do
origin = Scopes.from_string('public')
new_scope = origin + Scopes.from_string('admin')
expect(origin.to_s).to eq('public')
end
it 'raises an error if cannot handle addition' do
expect do
Scopes.from_string('public') + 'admin'
end.to raise_error(NoMethodError)
end
end
describe '#==' do
it 'is equal to another set of scopes' do
expect(Scopes.from_string('public')).to eq(Scopes.from_string('public'))
end
it 'is equal to another set of scopes with no particular order' do
expect(Scopes.from_string('public write')).to eq(Scopes.from_string('write public'))
end
it 'differs from another set of scopes when scopes are not the same' do
expect(Scopes.from_string('public write')).not_to eq(Scopes.from_string('write'))
end
end
describe '#has_scopes?' do
subject { Scopes.from_string('public admin') }
it 'returns true when at least one scope is included' do
expect(subject.has_scopes?(Scopes.from_string('public'))).to be_truthy
end
it 'returns true when all scopes are included' do
expect(subject.has_scopes?(Scopes.from_string('public admin'))).to be_truthy
end
it 'is true if all scopes are included in any order' do
expect(subject.has_scopes?(Scopes.from_string('admin public'))).to be_truthy
end
it 'is false if no scopes are included' do
expect(subject.has_scopes?(Scopes.from_string('notexistent'))).to be_falsey
end
it 'returns false when any scope is not included' do
expect(subject.has_scopes?(Scopes.from_string('public nope'))).to be_falsey
end
it 'is false if no scopes are included even for existing ones' do
expect(subject.has_scopes?(Scopes.from_string('public admin notexistent'))).to be_falsey
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_credentials_request_spec.rb 0000644 0000764 0000764 00000006647 12544753400 024512 0 ustar pravi pravi require 'spec_helper'
require 'active_support/all'
require 'active_model'
require 'doorkeeper/oauth/client_credentials_request'
module Doorkeeper::OAuth
describe ClientCredentialsRequest do
let(:server) do
double(
default_scopes: nil,
custom_access_token_expires_in: ->(_app) { nil }
)
end
let(:application) { double :application, scopes: Scopes.from_string('') }
let(:client) { double :client, application: application }
let(:token_creator) { double :issuer, create: true, token: double }
subject { ClientCredentialsRequest.new(server, client) }
before do
subject.issuer = token_creator
end
it 'issues an access token for the current client' do
expect(token_creator).to receive(:create).with(client, nil)
subject.authorize
end
it 'has successful response when issue was created' do
subject.authorize
expect(subject.response).to be_a(TokenResponse)
end
context 'if issue was not created' do
before do
subject.issuer = double create: false, error: :invalid
end
it 'has an error response' do
subject.authorize
expect(subject.response).to be_a(Doorkeeper::OAuth::ErrorResponse)
end
it 'delegates the error to issuer' do
subject.authorize
expect(subject.error).to eq(:invalid)
end
end
context 'with scopes' do
let(:default_scopes) { Doorkeeper::OAuth::Scopes.from_string('public email') }
before do
allow(server).to receive(:default_scopes).and_return(default_scopes)
end
it 'issues an access token with default scopes if none was requested' do
expect(token_creator).to receive(:create).with(client, default_scopes)
subject.authorize
end
it 'issues an access token with requested scopes' do
subject = ClientCredentialsRequest.new(server, client, scope: 'email')
subject.issuer = token_creator
expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string('email'))
subject.authorize
end
end
context 'with restricted client' do
let(:default_scopes) do
Doorkeeper::OAuth::Scopes.from_string('public email')
end
let(:server_scopes) do
Doorkeeper::OAuth::Scopes.from_string('public email phone')
end
let(:client_scopes) do
Doorkeeper::OAuth::Scopes.from_string('public phone')
end
before do
allow(server).to receive(:default_scopes).and_return(default_scopes)
allow(server).to receive(:scopes).and_return(server_scopes)
allow(server).to receive(:access_token_expires_in).and_return(100)
allow(application).to receive(:scopes).and_return(client_scopes)
allow(client).to receive(:id).and_return(nil)
end
it 'delegates the error to issuer if no scope was requested' do
subject = ClientCredentialsRequest.new(server, client)
subject.authorize
expect(subject.response).to be_a(Doorkeeper::OAuth::ErrorResponse)
expect(subject.error).to eq(:invalid_scope)
end
it 'issues an access token with requested scopes' do
subject = ClientCredentialsRequest.new(server, client, scope: 'phone')
subject.authorize
expect(subject.response).to be_a(Doorkeeper::OAuth::TokenResponse)
expect(subject.response.token.scopes_string).to eq('phone')
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/client_credentials_integration_spec.rb 0000644 0000764 0000764 00000001364 12544753400 025334 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe ClientCredentialsRequest do
let(:server) { Doorkeeper.configuration }
context 'with a valid request' do
let(:client) { FactoryGirl.create :application }
it 'issues an access token' do
request = ClientCredentialsRequest.new(server, client, {})
expect do
request.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
end
describe 'with an invalid request' do
it 'does not issue an access token' do
request = ClientCredentialsRequest.new(server, nil, {})
expect do
request.authorize
end.to_not change { Doorkeeper::AccessToken.count }
end
end
end
end
doorkeeper-2.2.1/spec/lib/oauth/password_access_token_request_spec.rb 0000644 0000764 0000764 00000005425 12544753400 025233 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper::OAuth
describe PasswordAccessTokenRequest do
let(:server) do
double(
:server,
default_scopes: Doorkeeper::OAuth::Scopes.new,
access_token_expires_in: 2.hours,
refresh_token_enabled?: false,
custom_access_token_expires_in: ->(_app) { nil }
)
end
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
let(:client) { FactoryGirl.create(:application) }
let(:owner) { double :owner, id: 99 }
subject do
PasswordAccessTokenRequest.new(server, credentials, owner)
end
it 'issues a new token for the client' do
expect do
subject.authorize
end.to change { client.access_tokens.count }.by(1)
end
it 'issues a new token without a client' do
expect do
subject.credentials = nil
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'does not issue a new token with an invalid client' do
expect do
subject.client = nil
subject.authorize
end.to_not change { Doorkeeper::AccessToken.count }
expect(subject.error).to eq(:invalid_client)
end
it 'requires the owner' do
subject.resource_owner = nil
subject.validate
expect(subject.error).to eq(:invalid_grant)
end
it 'optionally accepts the client' do
subject.credentials = nil
expect(subject).to be_valid
end
it 'creates token even when there is already one (default)' do
FactoryGirl.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
expect do
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
end
it 'skips token creation if there is already one' do
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
FactoryGirl.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
expect do
subject.authorize
end.to_not change { Doorkeeper::AccessToken.count }
end
describe 'with scopes' do
subject do
PasswordAccessTokenRequest.new(server, client, owner, scope: 'public')
end
it 'validates the current scope' do
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('another'))
subject.validate
expect(subject.error).to eq(:invalid_scope)
end
it 'creates the token with scopes' do
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('public'))
expect do
subject.authorize
end.to change { Doorkeeper::AccessToken.count }.by(1)
expect(Doorkeeper::AccessToken.last.scopes).to include('public')
end
end
end
end
doorkeeper-2.2.1/spec/lib/models/ 0000755 0000764 0000764 00000000000 12544753400 015676 5 ustar pravi pravi doorkeeper-2.2.1/spec/lib/models/revocable_spec.rb 0000644 0000764 0000764 00000001777 12544753400 021213 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/object/blank'
require 'doorkeeper/models/concerns/revocable'
describe 'Revocable' do
subject do
Class.new do
include Doorkeeper::Models::Revocable
end.new
end
describe :revoke do
it 'updates :revoked_at attribute with current time' do
clock = double now: double
expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now)
subject.revoke(clock)
end
end
describe :revoked? do
it 'is revoked if :revoked_at has passed' do
allow(subject).to receive(:revoked_at).and_return(DateTime.now - 1000)
expect(subject).to be_revoked
end
it 'is not revoked if :revoked_at has not passed' do
allow(subject).to receive(:revoked_at).and_return(DateTime.now + 1000)
expect(subject).not_to be_revoked
end
it 'is not revoked if :revoked_at is not set' do
allow(subject).to receive(:revoked_at).and_return(nil)
expect(subject).not_to be_revoked
end
end
end
doorkeeper-2.2.1/spec/lib/models/expirable_spec.rb 0000644 0000764 0000764 00000002626 12544753400 021216 0 ustar pravi pravi require 'spec_helper'
require 'timecop'
require 'active_support/time'
require 'doorkeeper/models/concerns/expirable'
describe 'Expirable' do
subject do
Class.new do
include Doorkeeper::Models::Expirable
end.new
end
before do
allow(subject).to receive(:created_at).and_return(1.minute.ago)
end
describe :expired? do
it 'is not expired if time has not passed' do
allow(subject).to receive(:expires_in).and_return(2.minutes)
expect(subject).not_to be_expired
end
it 'is expired if time has passed' do
allow(subject).to receive(:expires_in).and_return(10.seconds)
expect(subject).to be_expired
end
it 'is not expired if expires_in is not set' do
allow(subject).to receive(:expires_in).and_return(nil)
expect(subject).not_to be_expired
end
end
describe :expires_in_seconds do
it 'should return the amount of time remaining until the token is expired' do
allow(subject).to receive(:expires_in).and_return(2.minutes)
expect(subject.expires_in_seconds).to eq(60)
end
it 'should return 0 when expired' do
allow(subject).to receive(:expires_in).and_return(30.seconds)
expect(subject.expires_in_seconds).to eq(0)
end
it 'should return nil when expires_in is nil' do
allow(subject).to receive(:expires_in).and_return(nil)
expect(subject.expires_in_seconds).to be_nil
end
end
end
doorkeeper-2.2.1/spec/lib/models/scopes_spec.rb 0000644 0000764 0000764 00000002057 12544753400 020535 0 ustar pravi pravi require 'spec_helper'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/object/blank'
require 'doorkeeper/oauth/scopes'
require 'doorkeeper/models/concerns/scopes'
describe 'Doorkeeper::Models::Scopes' do
subject do
Class.new(Hash) do
include Doorkeeper::Models::Scopes
end.new
end
before do
subject[:scopes] = 'public admin'
end
describe :scopes do
it 'is a `Scopes` class' do
expect(subject.scopes).to be_a(Doorkeeper::OAuth::Scopes)
end
it 'includes scopes' do
expect(subject.scopes).to include('public')
end
end
describe :scopes_string do
it 'is a `Scopes` class' do
expect(subject.scopes_string).to eq('public admin')
end
end
describe :includes_scope? do
it 'should return true if at least one scope is included' do
expect(subject.includes_scope?('public', 'private')).to be true
end
it 'should return false if no scopes are included' do
expect(subject.includes_scope?('teacher', 'student')).to be false
end
end
end
doorkeeper-2.2.1/spec/lib/doorkeeper_spec.rb 0000644 0000764 0000764 00000001542 12544753400 020113 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper do
describe 'authenticate' do
let(:token) { double('Token') }
let(:request) { double('ActionDispatch::Request') }
before do
allow(Doorkeeper::OAuth::Token).to receive(:authenticate).
with(request, *token_strategies) { token }
end
context 'with specific access token strategies' do
let(:token_strategies) { [:first_way, :second_way] }
it 'authenticates the token from the request' do
expect(Doorkeeper.authenticate(request, token_strategies)).to eq(token)
end
end
context 'with default access token strategies' do
let(:token_strategies) { Doorkeeper.configuration.access_token_methods }
it 'authenticates the token from the request' do
expect(Doorkeeper.authenticate(request)).to eq(token)
end
end
end
end
doorkeeper-2.2.1/spec/controllers/ 0000755 0000764 0000764 00000000000 12544753400 016213 5 ustar pravi pravi doorkeeper-2.2.1/spec/controllers/authorizations_controller_spec.rb 0000644 0000764 0000764 00000013725 12544753400 025110 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
include AuthorizationRequestHelper
def fragments(param)
fragment = URI.parse(response.location).fragment
Rack::Utils.parse_query(fragment)[param]
end
def translated_error_message(key)
I18n.translate key, scope: [:doorkeeper, :errors, :messages]
end
let(:client) { FactoryGirl.create :application }
let(:user) { User.create!(name: 'Joe', password: 'sekret') }
before do
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["implicit"])
allow(controller).to receive(:current_resource_owner).and_return(user)
end
describe 'POST #create' do
before do
post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
end
it 'redirects after authorization' do
expect(response).to be_redirect
end
it 'redirects to client redirect uri' do
expect(response.location).to match(%r{^#{client.redirect_uri}})
end
it 'includes access token in fragment' do
expect(fragments('access_token')).to eq(Doorkeeper::AccessToken.first.token)
end
it 'includes token type in fragment' do
expect(fragments('token_type')).to eq('bearer')
end
it 'includes token expiration in fragment' do
expect(fragments('expires_in').to_i).to eq(2.hours.to_i)
end
it 'issues the token for the current client' do
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
end
it 'issues the token for the current resource owner' do
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
end
end
describe 'POST #create with errors' do
before do
default_scopes_exist :public
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri
end
it 'redirects after authorization' do
expect(response).to be_redirect
end
it 'redirects to client redirect uri' do
expect(response.location).to match(%r{^#{client.redirect_uri}})
end
it 'does not include access token in fragment' do
expect(fragments('access_token')).to be_nil
end
it 'includes error in fragment' do
expect(fragments('error')).to eq('invalid_scope')
end
it 'includes error description in fragment' do
expect(fragments('error_description')).to eq(translated_error_message(:invalid_scope))
end
it 'does not issue any access token' do
expect(Doorkeeper::AccessToken.all).to be_empty
end
end
describe 'POST #create with application already authorized' do
it 'returns the existing access token in a fragment'
end
describe 'GET #new' do
before do
get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
end
it 'renders new template' do
expect(response).to render_template(:new)
end
end
describe 'GET #new token request with native url and skip_authorization true' do
before do
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
true
end)
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
end
it 'should redirect immediately' do
expect(response).to be_redirect
expect(response.location).to match(/oauth\/token\/info\?access_token=/)
end
it 'should not issue a grant' do
expect(Doorkeeper::AccessGrant.count).to be 0
end
it 'should issue a token' do
expect(Doorkeeper::AccessToken.count).to be 1
end
end
describe 'GET #new code request with native url and skip_authorization true' do
before do
allow(Doorkeeper.configuration).to receive(:grant_flows).
and_return(%w(authorization_code))
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
true
end)
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
get :new, client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri
end
it 'should redirect immediately' do
expect(response).to be_redirect
expect(response.location).to match(/oauth\/authorize\//)
end
it 'should issue a grant' do
expect(Doorkeeper::AccessGrant.count).to be 1
end
it 'should not issue a token' do
expect(Doorkeeper::AccessToken.count).to be 0
end
end
describe 'GET #new with skip_authorization true' do
before do
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
true
end)
get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
end
it 'should redirect immediately' do
expect(response).to be_redirect
expect(response.location).to match(%r{^#{client.redirect_uri}})
end
it 'should issue a token' do
expect(Doorkeeper::AccessToken.count).to be 1
end
it 'includes token type in fragment' do
expect(fragments('token_type')).to eq('bearer')
end
it 'includes token expiration in fragment' do
expect(fragments('expires_in').to_i).to eq(2.hours.to_i)
end
it 'issues the token for the current client' do
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
end
it 'issues the token for the current resource owner' do
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
end
end
describe 'GET #new with errors' do
before do
default_scopes_exist :public
get :new, an_invalid: 'request'
end
it 'does not redirect' do
expect(response).to_not be_redirect
end
it 'renders error template' do
expect(response).to render_template(:error)
end
it 'does not issue any token' do
expect(Doorkeeper::AccessGrant.count).to eq 0
expect(Doorkeeper::AccessToken.count).to eq 0
end
end
end
doorkeeper-2.2.1/spec/controllers/applications_controller_spec.rb 0000644 0000764 0000764 00000003456 12544753400 024513 0 ustar pravi pravi require 'spec_helper_integration'
module Doorkeeper
describe ApplicationsController do
context 'when admin is not authenticated' do
before do
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(proc do
redirect_to main_app.root_url
end)
end
it 'redirects as set in Doorkeeper.authenticate_admin' do
get :index
expect(response).to redirect_to(controller.main_app.root_url)
end
it 'does not create application' do
expect do
post :create, doorkeeper_application: {
name: 'Example',
redirect_uri: 'https://example.com' }
end.to_not change { Doorkeeper::Application.count }
end
end
context 'when admin is authenticated' do
before do
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(arg) { true })
end
it 'creates application' do
expect do
post :create, doorkeeper_application: {
name: 'Example',
redirect_uri: 'https://example.com' }
end.to change { Doorkeeper::Application.count }.by(1)
expect(response).to be_redirect
end
it 'does not allow mass assignment of uid or secret' do
application = FactoryGirl.create(:application)
put :update, id: application.id, doorkeeper_application: {
uid: '1A2B3C4D',
secret: '1A2B3C4D' }
expect(application.reload.uid).not_to eq '1A2B3C4D'
end
it 'updates application' do
application = FactoryGirl.create(:application)
put :update, id: application.id, doorkeeper_application: {
name: 'Example',
redirect_uri: 'https://example.com' }
expect(application.reload.name).to eq 'Example'
end
end
end
end
doorkeeper-2.2.1/spec/controllers/token_info_controller_spec.rb 0000644 0000764 0000764 00000003071 12544753400 024151 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper::TokenInfoController do
describe 'when requesting tokeninfo with valid token' do
let(:doorkeeper_token) { FactoryGirl.create(:access_token) }
before(:each) do
allow(controller).to receive(:doorkeeper_token) { doorkeeper_token }
end
def do_get
get :show
end
describe 'successful request' do
it 'responds with tokeninfo' do
do_get
expect(response.body).to eq(doorkeeper_token.to_json)
end
it 'responds with a 200 status' do
do_get
expect(response.status).to eq 200
end
end
describe 'invalid token response' do
before(:each) do
allow(controller).to receive(:doorkeeper_token).and_return(nil)
end
it 'responds with 401 when doorkeeper_token is not valid' do
do_get
expect(response.status).to eq 401
expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
end
it 'responds with 401 when doorkeeper_token is invalid, expired or revoked' do
allow(controller).to receive(:doorkeeper_token).and_return(doorkeeper_token)
allow(doorkeeper_token).to receive(:accessible?).and_return(false)
do_get
expect(response.status).to eq 401
expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
end
it 'responds body message for error' do
do_get
expect(response.body).to eq(Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json)
end
end
end
end
doorkeeper-2.2.1/spec/controllers/protected_resources_controller_spec.rb 0000644 0000764 0000764 00000012523 12544753400 026103 0 ustar pravi pravi require 'spec_helper_integration'
module ControllerActions
def index
render text: 'index'
end
def show
render text: 'show'
end
end
describe 'doorkeeper authorize filter' do
context 'accepts token code specified as' do
controller do
before_filter :doorkeeper_authorize!
def index
render text: 'index'
end
end
let(:token_string) { '1A2BC3' }
let(:token) do
double(Doorkeeper::AccessToken, acceptable?: true)
end
it 'access_token param' do
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
get :index, access_token: token_string
end
it 'bearer_token param' do
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
get :index, bearer_token: token_string
end
it 'Authorization header' do
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
get :index
end
it 'different kind of Authorization header' do
expect(Doorkeeper::AccessToken).not_to receive(:by_token)
request.env['HTTP_AUTHORIZATION'] = "MAC #{token_string}"
get :index
end
it 'does not change Authorization header value' do
expect(Doorkeeper::AccessToken).to receive(:by_token).exactly(2).times.and_return(token)
request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
get :index
controller.send(:remove_instance_variable, :@_doorkeeper_token)
get :index
end
end
context 'defined for all actions' do
controller do
before_filter :doorkeeper_authorize!
include ControllerActions
end
context 'with valid token', token: :valid do
it 'allows into index action' do
get :index, access_token: token_string
expect(response).to be_success
end
it 'allows into show action' do
get :show, id: '4', access_token: token_string
expect(response).to be_success
end
end
context 'with invalid token', token: :invalid do
it 'does not allow into index action' do
get :index, access_token: token_string
expect(response.status).to eq 401
expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
end
it 'does not allow into show action' do
get :show, id: '4', access_token: token_string
expect(response.status).to eq 401
expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
end
end
end
context 'defined with scopes' do
controller do
before_filter -> { doorkeeper_authorize! :write }
include ControllerActions
end
let(:token_string) { '1A2DUWE' }
it 'allows if the token has particular scopes' do
token = double(Doorkeeper::AccessToken, accessible?: true, scopes: %w(write public))
expect(token).to receive(:acceptable?).with([:write]).and_return(true)
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
get :index, access_token: token_string
expect(response).to be_success
end
it 'does not allow if the token does not include given scope' do
token = double(Doorkeeper::AccessToken, accessible?: true, scopes: ['public'], revoked?: false, expired?: false)
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
expect(token).to receive(:acceptable?).with([:write]).and_return(false)
get :index, access_token: token_string
expect(response.status).to eq 403
expect(response.header).to_not include('WWW-Authenticate')
end
end
context 'when custom unauthorized render options are configured' do
controller do
before_filter :doorkeeper_authorize!
include ControllerActions
end
context 'with a JSON custom render', token: :invalid do
before do
expect(controller).to receive(:doorkeeper_unauthorized_render_options).and_return(json: ActiveSupport::JSON.encode(error: 'Unauthorized'))
end
it 'it renders a custom JSON response', token: :invalid do
get :index, access_token: token_string
expect(response.status).to eq 401
expect(response.content_type).to eq('application/json')
expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
parsed_body = JSON.parse(response.body)
expect(parsed_body).not_to be_nil
expect(parsed_body['error']).to eq('Unauthorized')
end
end
context 'with a text custom render', token: :invalid do
before do
expect(controller).to receive(:doorkeeper_unauthorized_render_options).and_return(text: 'Unauthorized')
end
it 'it renders a custom JSON response', token: :invalid do
get :index, access_token: token_string
expect(response.status).to eq 401
expect(response.content_type).to eq('text/html')
expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
expect(response.body).to eq('Unauthorized')
end
end
end
context 'defined for all actions' do
controller {}
it 'it renders a custom JSON response' do
expect do
controller.class.doorkeeper_for
end.to raise_error(
Doorkeeper::Errors::DoorkeeperError,
/`doorkeeper_for` no longer available/
)
end
end
end
doorkeeper-2.2.1/spec/controllers/tokens_controller_spec.rb 0000644 0000764 0000764 00000002707 12544753400 023326 0 ustar pravi pravi require 'spec_helper_integration'
describe Doorkeeper::TokensController do
describe 'when authorization has succeeded' do
let :token do
double(:token, authorize: true)
end
before do
allow(controller).to receive(:token) { token }
end
it 'returns the authorization' do
skip 'verify need of these specs'
expect(token).to receive(:authorization)
post :create
end
end
describe 'when authorization has failed' do
it 'returns the error response' do
token = double(:token, authorize: false)
allow(controller).to receive(:token) { token }
post :create
expect(response.status).to eq 401
expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
end
end
describe 'when revoke authorization has failed' do
# http://tools.ietf.org/html/rfc7009#section-2.2
it 'returns no error response' do
token = double(:token, authorize: false)
allow(controller).to receive(:token) { token }
post :revoke
expect(response.status).to eq 200
end
end
describe 'authorize response memoization' do
it "memoizes the result of the authorization" do
strategy = double(:strategy, authorize: true)
expect(strategy).to receive(:authorize).once
allow(controller).to receive(:strategy) { strategy }
allow(controller).to receive(:create) do
controller.send :authorize_response
end
post :create
end
end
end
doorkeeper-2.2.1/.hound.yml 0000644 0000764 0000764 00000000156 12544753400 014633 0 ustar pravi pravi LineLength:
Exclude:
- spec/**/*
StringLiterals:
Enabled: false
TrailingBlankLines:
Enabled: true
doorkeeper-2.2.1/.rspec 0000644 0000764 0000764 00000000011 12544753400 014020 0 ustar pravi pravi --colour
doorkeeper-2.2.1/RELEASING.md 0000644 0000764 0000764 00000001122 12544753400 014542 0 ustar pravi pravi # Releasing doorkeeper
1. Update `lib/doorkeeper/version.rb` file accordingly.
2. Update `NEWS.md` to reflect the changes since last release.
3. Commit changes. There shouldn’t be code changes, and thus CI doesn’t need to
run, you can then add “[ci skip]” to the commit message.
4. Tag the release: `git tag vVERSION`
5. Push changes: `git push --tags`
6. Build and publish the gem:
```bash
gem build doorkeeper.gemspec
gem push doorkeeper-*.gem
```
7. Announce the new release, making sure to say “thank you” to the contributors
who helped shape this version!
doorkeeper-2.2.1/CONTRIBUTING.md 0000644 0000764 0000764 00000001754 12544753400 015153 0 ustar pravi pravi # Contributing
We love pull requests from everyone. By participating in this project, you agree
to abide by the thoughtbot [code of conduct].
[code of conduct]: https://thoughtbot.com/open-source-code-of-conduct
Fork, then clone the repo:
git clone git@github.com:your-username/doorkeeper.git
Set up Ruby dependencies via Bundler
bundle install
Make sure the tests pass:
rake
Make your change.
Write tests.
Follow our [style guide][style].
Make the tests pass:
[style]: https://github.com/thoughtbot/guides/tree/master/style
rake
Write a [good commit message][commit].
Push to your fork.
[Submit a pull request][pr].
[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[pr]: https://github.com/doorkeeper-gem/doorkeeper/compare/
If [Hound] catches style violations,
fix them.
[hound]: https://houndci.com
Wait for us.
We try to at least comment on pull requests within one business day.
We may suggest changes.
Thank you for your contribution!
doorkeeper-2.2.1/.travis.yml 0000644 0000764 0000764 00000001277 12544753400 015033 0 ustar pravi pravi language: ruby
sudo: false
cache: bundler
rvm:
- 2.0
- 2.1
- 2.2
env:
- rails=3.2.0
- rails=4.1.0
- rails=4.2.0
gemfile:
- Gemfile
- gemfiles/Gemfile.mongoid2.rb
- gemfiles/Gemfile.mongoid3.rb
- gemfiles/Gemfile.mongoid4.rb
- gemfiles/Gemfile.mongo_mapper.rb
services:
- mongodb
matrix:
exclude:
- env: rails=3.2.0
rvm: 2.2
- gemfile: gemfiles/Gemfile.mongoid2.rb
env: rails=4.1.0
- gemfile: gemfiles/Gemfile.mongoid2.rb
env: rails=4.2.0
- gemfile: gemfiles/Gemfile.mongoid3.rb
env: rails=4.1.0
- gemfile: gemfiles/Gemfile.mongoid3.rb
env: rails=4.2.0
- gemfile: gemfiles/Gemfile.mongoid4.rb
env: rails=3.2.0
doorkeeper-2.2.1/vendor/ 0000755 0000764 0000764 00000000000 12544753400 014210 5 ustar pravi pravi doorkeeper-2.2.1/vendor/assets/ 0000755 0000764 0000764 00000000000 12544753400 015512 5 ustar pravi pravi doorkeeper-2.2.1/vendor/assets/stylesheets/ 0000755 0000764 0000764 00000000000 12544753400 020066 5 ustar pravi pravi doorkeeper-2.2.1/vendor/assets/stylesheets/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 022225 5 ustar pravi pravi doorkeeper-2.2.1/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css 0000755 0000764 0000764 00000306721 12544753400 025552 0 ustar pravi pravi /*!
* Bootstrap v3.1.0 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.428571429;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../../../../../../../Downloads/bootstrap-3.1.0/dist/fonts/glyphicons-halflings-regular.eot);src:url(../../../../../../../Downloads/bootstrap-3.1.0/dist/fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../../../../../../../Downloads/bootstrap-3.1.0/dist/fonts/glyphicons-halflings-regular.woff) format('woff'),url(../../../../../../../Downloads/bootstrap-3.1.0/dist/fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../../../../../../../Downloads/bootstrap-3.1.0/dist/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group .list-group-item:first-child{border-top:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel>.list-group:first-child .list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tfoot>tr:first-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tfoot>tr:first-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>td{border-top:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}
doorkeeper-2.2.1/config/ 0000755 0000764 0000764 00000000000 12544753400 014160 5 ustar pravi pravi doorkeeper-2.2.1/config/locales/ 0000755 0000764 0000764 00000000000 12544753400 015602 5 ustar pravi pravi doorkeeper-2.2.1/config/locales/en.yml 0000644 0000764 0000764 00000012517 12544753400 016735 0 ustar pravi pravi en:
activerecord:
attributes:
doorkeeper/application:
name: 'Name'
redirect_uri: 'Redirect URI'
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
fragment_present: 'cannot contain a fragment.'
invalid_uri: 'must be a valid URI.'
relative_uri: 'must be an absolute URI.'
secured_uri: 'must be an HTTPS/SSL URI.'
mongoid:
attributes:
doorkeeper/application:
name: 'Name'
redirect_uri: 'Redirect URI'
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
fragment_present: 'cannot contain a fragment.'
invalid_uri: 'must be a valid URI.'
relative_uri: 'must be an absolute URI.'
secured_uri: 'must be an HTTPS/SSL URI.'
mongo_mapper:
attributes:
doorkeeper/application:
name: 'Name'
redirect_uri: 'Redirect URI'
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
fragment_present: 'cannot contain a fragment.'
invalid_uri: 'must be a valid URI.'
relative_uri: 'must be an absolute URI.'
secured_uri: 'must be an HTTPS/SSL URI.'
doorkeeper:
applications:
confirmations:
destroy: 'Are you sure?'
buttons:
edit: 'Edit'
destroy: 'Destroy'
submit: 'Submit'
cancel: 'Cancel'
authorize: 'Authorize'
form:
error: 'Whoops! Check your form for possible errors'
help:
redirect_uri: 'Use one line per URI'
native_redirect_uri: 'Use %{native_redirect_uri} for local tests'
edit:
title: 'Edit application'
index:
title: 'Your applications'
new: 'New Application'
name: 'Name'
callback_url: 'Callback URL'
new:
title: 'New Application'
show:
title: 'Application: %{name}'
application_id: 'Application Id'
secret: 'Secret'
callback_urls: 'Callback urls'
actions: 'Actions'
authorizations:
buttons:
authorize: 'Authorize'
deny: 'Deny'
error:
title: 'An error has occurred'
new:
title: 'Authorize required'
prompt: 'Authorize %{client_name} to use your account?'
able_to: 'This application will be able to'
show:
title: 'Authorization code'
authorized_applications:
confirmations:
revoke: 'Are you sure?'
buttons:
revoke: 'Revoke'
index:
title: 'Your authorized applications'
application: 'Application'
created_at: 'Created At'
date_format: '%Y-%m-%d %H:%M:%S'
errors:
messages:
# Common error messages
invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
invalid_redirect_uri: 'The redirect uri included is not valid.'
unauthorized_client: 'The client is not authorized to perform this request using this method.'
access_denied: 'The resource owner or authorization server denied the request.'
invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
#configuration error messages
credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfiged.'
# Access grant errors
unsupported_response_type: 'The authorization server does not support this response type.'
# Access token errors
invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
# Password Access token errors
invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
invalid_token:
revoked: "The access token was revoked"
expired: "The access token expired"
unknown: "The access token is invalid"
flash:
applications:
create:
notice: 'Application created.'
destroy:
notice: 'Application deleted.'
update:
notice: 'Application updated.'
authorized_applications:
destroy:
notice: 'Application revoked.'
layouts:
admin:
nav:
oauth2_provider: 'OAuth2 Provider'
applications: 'Applications'
application:
title: 'OAuth authorize required' doorkeeper-2.2.1/doorkeeper.gemspec 0000644 0000764 0000764 00000002337 12544753400 016424 0 ustar pravi pravi $:.push File.expand_path("../lib", __FILE__)
require "doorkeeper/version"
Gem::Specification.new do |s|
s.name = "doorkeeper"
s.version = Doorkeeper::VERSION
s.authors = ["Felipe Elias Philipp", "Tute Costa"]
s.email = %w(tutecosta@gmail.com)
s.homepage = "https://github.com/doorkeeper-gem/doorkeeper"
s.summary = "OAuth 2 provider for Rails and Grape"
s.description = "Doorkeeper is an OAuth 2 provider for Rails and Grape."
s.license = 'MIT'
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n")
s.require_paths = ["lib"]
s.add_dependency "railties", ">= 3.2"
s.add_development_dependency "sqlite3", "~> 1.3.5"
s.add_development_dependency "rspec-rails", "~> 3.2.0"
s.add_development_dependency "capybara", "~> 2.3.0"
s.add_development_dependency "generator_spec", "~> 0.9.0"
s.add_development_dependency "factory_girl", "~> 4.5.0"
s.add_development_dependency "timecop", "~> 0.7.0"
s.add_development_dependency "database_cleaner", "~> 1.3.0"
s.add_development_dependency "rspec-activemodel-mocks", "~> 1.0.0"
s.add_development_dependency "bcrypt-ruby", "~> 3.0.1"
s.add_development_dependency "pry", "~> 0.10.0"
end
doorkeeper-2.2.1/README.md 0000644 0000764 0000764 00000031563 12544753400 014202 0 ustar pravi pravi # Doorkeeper - awesome oauth provider for your Rails app.
[](https://travis-ci.org/doorkeeper-gem/doorkeeper)
[](https://gemnasium.com/applicake/doorkeeper)
[](https://codeclimate.com/github/applicake/doorkeeper)
[](https://rubygems.org/gems/doorkeeper)
Doorkeeper is a gem that makes it easy to introduce OAuth 2 provider
functionality to your Rails or Grape application.
[PR 567]: https://github.com/doorkeeper-gem/doorkeeper/pull/567
## Documentation valid for `master` branch
Please check the documentation for the version of doorkeeper you are using in:
https://github.com/doorkeeper-gem/doorkeeper/releases.
## Table of Contents
- [Useful links](#useful-links)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Active Record](#active-record)
- [Mongoid / MongoMapper](#mongoid--mongomapper)
- [Mongoid indexes](#mongoid-indexes)
- [MongoMapper indexes](#mongomapper-indexes)
- [Routes](#routes)
- [Authenticating](#authenticating)
- [Internationalization (I18n)](#internationalization-i18n)
- [Protecting resources with OAuth (a.k.a your API endpoint)](#protecting-resources-with-oauth-aka-your-api-endpoint)
- [Protect your API with OAuth when using Grape](#protect-your-api-with-oauth-when-using-grape)
- [Route Constraints and other integrations](#route-constraints-and-other-integrations)
- [Access Token Scopes](#access-token-scopes)
- [Custom Access Token Generator](#custom-access-token-generator)
- [Authenticated resource owner](#authenticated-resource-owner)
- [Applications list](#applications-list)
- [Other customizations](#other-customizations)
- [Upgrading](#upgrading)
- [Development](#development)
- [Contributing](#contributing)
- [Other resources](#other-resources)
- [Wiki](#wiki)
- [Live demo](#live-demo)
- [Screencast](#screencast)
- [Client applications](#client-applications)
- [Contributors](#contributors)
- [IETF Standards](#ietf-standards)
- [License](#license)
## Useful links
- For documentation, please check out our [wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki)
- For general questions, please post it in [stack overflow](http://stackoverflow.com/questions/tagged/doorkeeper)
## Requirements
- Ruby >= 2.0.0
- Rails >= 3.2
- ORM ActiveRecord, Mongoid, MongoMapper
## Installation
Put this in your Gemfile:
``` ruby
gem 'doorkeeper'
```
Run the installation generator with:
rails generate doorkeeper:install
This will install the doorkeeper initializer into `config/initializers/doorkeeper.rb`.
## Configuration
### Active Record
By default doorkeeper is configured to use active record, so to start you have
to generate the migration tables:
rails generate doorkeeper:migration
Don't forget to run the migration with:
rake db:migrate
### Mongoid / MongoMapper
Doorkeeper currently supports MongoMapper, Mongoid 2 and 3. To start using it,
you have to set the `orm` configuration:
``` ruby
Doorkeeper.configure do
orm :mongoid2 # or :mongoid3, :mongoid4, :mongo_mapper
end
```
#### Mongoid indexes
Make sure you create indexes for doorkeeper models. You can do this either by
running `rake db:mongoid:create_indexes` or (if you're using Mongoid 2) by
adding `autocreate_indexes: true` to your `config/mongoid.yml`
#### MongoMapper indexes
Generate the `db/indexes.rb` file and create indexes for the doorkeeper models:
rails generate doorkeeper:mongo_mapper:indexes
rake db:index
### Routes
The installation script will also automatically add the Doorkeeper routes into
your app, like this:
``` ruby
Rails.application.routes.draw do
use_doorkeeper
# your routes
end
```
This will mount following routes:
GET /oauth/authorize/:code
GET /oauth/authorize
POST /oauth/authorize
PUT /oauth/authorize
DELETE /oauth/authorize
POST /oauth/token
POST /oauth/revoke
resources /oauth/applications
GET /oauth/authorized_applications
DELETE /oauth/authorized_applications/:id
GET /oauth/token/info
For more information on how to customize routes, check out [this page on the
wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
### Authenticating
You need to configure Doorkeeper in order to provide `resource_owner` model
and authentication block `initializers/doorkeeper.rb`
``` ruby
Doorkeeper.configure do
resource_owner_authenticator do
User.find_by_id(session[:current_user_id]) || redirect_to(login_url)
end
end
```
This code is run in the context of your application so you have access to your
models, session or routes helpers. However, since this code is not run in the
context of your application's `ApplicationController` it doesn't have access to
the methods defined over there.
You may want to check other ways of authentication
[here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Authenticating-using-Clearance-or-DIY).
### Internationalization (I18n)
See language files in [the I18n repository](https://github.com/doorkeeper-gem/doorkeeper-i18n).
## Protecting resources with OAuth (a.k.a your API endpoint)
To protect your API with OAuth, you just need to setup `before_action`s
specifying the actions you want to protect. For example:
``` ruby
class Api::V1::ProductsController < Api::V1::ApiController
before_action :doorkeeper_authorize! # Require access token for all actions
# your actions
end
```
You can pass any option `before_action` accepts, such as `if`, `only`,
`except`, and others.
### Protect your API with OAuth when using Grape
As of [PR 567] doorkeeper has helpers for Grape. One of them is
`doorkeeper_authorize!` and can be used in a similar way as an example above.
Note that you have to use `require 'doorkeeper/grape/helpers'` and
`helpers Doorkeeper::Grape::Helpers`.
For more information about integration with Grape see the [Wiki].
[PR 567]: https://github.com/doorkeeper-gem/doorkeeper/pull/567
[Wiki]: https://github.com/doorkeeper-gem/doorkeeper/wiki/Grape-Integration
``` ruby
require 'doorkeeper/grape/helpers'
module API
module V1
class Users < Grape::API
helpers Doorkeeper::Grape::Helpers
before do
doorkeeper_authorize!
end
# ...
end
end
end
```
### Route Constraints and other integrations
You can leverage the `Doorkeeper.authenticate` facade to easily extract a
`Doorkeeper::OAuth::Token` based on the current request. You can then ensure
that token is still good, find its associated `#resource_owner_id`, etc.
```ruby
module Constraint
class Authenticated
def matches?(request)
token = Doorkeeper.authenticate(request)
token && token.accessible?
end
end
end
```
For more information about integration and other integrations, check out [the
related wiki
page](https://github.com/doorkeeper-gem/doorkeeper/wiki/ActionController::Metal-with-doorkeeper).
### Access Token Scopes
You can also require the access token to have specific scopes in certain
actions:
First configure the scopes in `initializers/doorkeeper.rb`
```ruby
Doorkeeper.configure do
default_scopes :public # if no scope was requested, this will be the default
optional_scopes :admin, :write
end
```
And in your controllers:
```ruby
class Api::V1::ProductsController < Api::V1::ApiController
before_action -> { doorkeeper_authorize! :public }, only: :index
before_action only: [:create, :update, :destroy] do
doorkeeper_authorize! :admin, :write
end
end
```
Please note that there is a logical OR between multiple required scopes. In
above example, `doorkeeper_authorize! :admin, :write` means that the access
token is required to have either `:admin` scope or `:write` scope, but not need
have both of them.
If want to require the access token to have multiple scopes at the same time,
use multiple `doorkeeper_authorize!`, for example:
```ruby
class Api::V1::ProductsController < Api::V1::ApiController
before_action -> { doorkeeper_authorize! :public }, only: :index
before_action only: [:create, :update, :destroy] do
doorkeeper_authorize! :admin
doorkeeper_authorize! :write
end
end
```
In above example, a client can call `:create` action only if its access token
have both `:admin` and `:write` scopes.
### Custom Access Token Generator
By default a 32 bit access token will be generated. If you require a custom
token, such as [JWT](http://jwt.io), specify an object that responds to
`.generate(options = {})` and returns a string to be used as the token.
```ruby
Doorkeeper.configure do
access_token_generator "Doorkeeper::JWT"
end
```
JWT token support is available with
[Doorkeeper-JWT](https://github.com/chriswarren/doorkeeper-jwt).
### Authenticated resource owner
If you want to return data based on the current resource owner, in other
words, the access token owner, you may want to define a method in your
controller that returns the resource owner instance:
``` ruby
class Api::V1::CredentialsController < Api::V1::ApiController
before_action :doorkeeper_authorize!
respond_to :json
# GET /me.json
def me
respond_with current_resource_owner
end
private
# Find the user that owns the access token
def current_resource_owner
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
end
```
In this example, we're returning the credentials (`me.json`) of the access
token owner.
### Applications list
By default, the applications list (`/oauth/applications`) is public available.
To protect the endpoint you should uncomment these lines:
```ruby
# config/initializers/doorkeeper.rb
Doorkeeper.configure do
admin_authenticator do |routes|
Admin.find_by_id(session[:admin_id]) || redirect_to(routes.new_admin_session_url)
end
end
```
The logic is the same as the `resource_owner_authenticator` block. **Note:**
since the application list is just a scaffold, it's recommended to either
customize the controller used by the list or skip the controller at all. For
more information see the page [in the
wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
## Other customizations
- [Associate users to OAuth applications (ownership)](https://github.com/doorkeeper-gem/doorkeeper/wiki/Associate-users-to-OAuth-applications-%28ownership%29)
- [CORS - Cross Origin Resource Sharing](https://github.com/doorkeeper-gem/doorkeeper/wiki/%5BCORS%5D-Cross-Origin-Resource-Sharing)
## Upgrading
If you want to upgrade doorkeeper to a new version, check out the [upgrading
notes](https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-versions)
and take a look at the
[changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/master/CHANGELOG.md).
## Development
To run the local engine server:
```
bundle install
bundle exec rails server
````
By default, it uses the latest Rails version with ActiveRecord. To run the
tests with a specific ORM and Rails version:
```
rails=4.2.0 orm=active_record bundle exec rake
```
Or you might prefer to run `script/run_all` to integrate against all ORMs.
## Contributing
Want to contribute and don't know where to start? Check out [features we're
missing](https://github.com/doorkeeper-gem/doorkeeper/wiki/Supported-Features),
create [example
apps](https://github.com/doorkeeper-gem/doorkeeper/wiki/Example-Applications),
integrate the gem with your app and let us know!
Also, check out our [contributing guidelines
page](https://github.com/doorkeeper-gem/doorkeeper/wiki/Contributing).
## Other resources
### Wiki
You can find everything about doorkeeper in our [wiki
here](https://github.com/doorkeeper-gem/doorkeeper/wiki).
### Live demo
Check out this [live demo](http://doorkeeper-provider.herokuapp.com) hosted on
heroku. For more demos check out [the
wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Example-Applications).
### Screencast
Check out this screencast from [railscasts.com](http://railscasts.com/): [#353
OAuth with
Doorkeeper](http://railscasts.com/episodes/353-oauth-with-doorkeeper)
### Client applications
After you set up the provider, you may want to create a client application to
test the integration. Check out these [client
examples](https://github.com/doorkeeper-gem/doorkeeper/wiki/Example-Applications)
in our wiki or follow this [tutorial
here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-your-provider-with-OAuth2-gem).
### Contributors
Thanks to all our [awesome
contributors](https://github.com/doorkeeper-gem/doorkeeper/contributors)!
### IETF Standards
* [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
* [OAuth 2.0 Threat Model and Security Considerations](http://tools.ietf.org/html/rfc6819)
### License
MIT License. Copyright 2011 Applicake.
[http://applicake.com](http://applicake.com)
doorkeeper-2.2.1/CHANGELOG.md 0000644 0000764 0000764 00000000125 12544753400 014522 0 ustar pravi pravi Moved to [NEWS.md](https://github.com/doorkeeper-gem/doorkeeper/blob/master/NEWS.md)
doorkeeper-2.2.1/app/ 0000755 0000764 0000764 00000000000 12544753400 013473 5 ustar pravi pravi doorkeeper-2.2.1/app/assets/ 0000755 0000764 0000764 00000000000 12544753400 014775 5 ustar pravi pravi doorkeeper-2.2.1/app/assets/stylesheets/ 0000755 0000764 0000764 00000000000 12544753400 017351 5 ustar pravi pravi doorkeeper-2.2.1/app/assets/stylesheets/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 021510 5 ustar pravi pravi doorkeeper-2.2.1/app/assets/stylesheets/doorkeeper/application.css 0000644 0000764 0000764 00000001620 12544753400 024524 0 ustar pravi pravi /*
*= require doorkeeper/bootstrap.min
*
*= require_self
*= require_tree .
*/
body {
background-color: #eee;
font-size: 14px;
}
#container {
background-color: #fff;
border: 1px solid #999;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6px;
-webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
box-shadow: 0 3px 20px rgba(0, 0, 0, 0.3);
margin: 2em auto;
max-width: 600px;
outline: 0;
padding: 1em;
width: 80%;
}
.page-header {
margin-top: 20px;
}
#oauth-permissions {
width: 260px;
}
.actions {
border-top: 1px solid #eee;
margin-top: 1em;
padding-top: 9px;
}
.actions > form > .btn {
margin-top: 5px;
}
.separator {
color: #eee;
padding: 0 .5em;
}
.inline_block {
display: inline-block;
}
#oauth {
margin-bottom: 1em;
}
#oauth > .btn {
width: 7em;
}
td {
vertical-align: middle !important;
}
doorkeeper-2.2.1/app/assets/stylesheets/doorkeeper/admin/ 0000755 0000764 0000764 00000000000 12544753400 022600 5 ustar pravi pravi doorkeeper-2.2.1/app/assets/stylesheets/doorkeeper/admin/application.css 0000644 0000764 0000764 00000000240 12544753400 025611 0 ustar pravi pravi /*
*= require doorkeeper/bootstrap.min
*
*= require_self
*= require_tree .
*/
body {
padding-top: 60px;
}
td {
vertical-align: middle !important;
}
doorkeeper-2.2.1/app/helpers/ 0000755 0000764 0000764 00000000000 12544753400 015135 5 ustar pravi pravi doorkeeper-2.2.1/app/helpers/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 017274 5 ustar pravi pravi doorkeeper-2.2.1/app/helpers/doorkeeper/dashboard_helper.rb 0000644 0000764 0000764 00000000667 12544753400 023120 0 ustar pravi pravi module Doorkeeper::DashboardHelper
def doorkeeper_errors_for(object, method)
if object.errors[method].present?
object.errors[method].map do |msg|
content_tag(:span, class: 'help-block') do
msg.capitalize
end
end.reduce(&:join).html_safe
end
end
def doorkeeper_submit_path(application)
application.persisted? ? oauth_application_path(application) : oauth_applications_path
end
end
doorkeeper-2.2.1/app/views/ 0000755 0000764 0000764 00000000000 12544753400 014630 5 ustar pravi pravi doorkeeper-2.2.1/app/views/layouts/ 0000755 0000764 0000764 00000000000 12544753400 016330 5 ustar pravi pravi doorkeeper-2.2.1/app/views/layouts/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 020467 5 ustar pravi pravi doorkeeper-2.2.1/app/views/layouts/doorkeeper/admin.html.erb 0000644 0000764 0000764 00000001776 12544753400 023227 0 ustar pravi pravi
Doorkeeper
<%= stylesheet_link_tag "doorkeeper/admin/application" %>
<%= csrf_meta_tags %>
doorkeeper-2.2.1/app/validators/ 0000755 0000764 0000764 00000000000 12544753400 015643 5 ustar pravi pravi doorkeeper-2.2.1/app/validators/redirect_uri_validator.rb 0000644 0000764 0000764 00000002003 12544753400 022710 0 ustar pravi pravi require 'uri'
class RedirectUriValidator < ActiveModel::EachValidator
def self.native_redirect_uri
Doorkeeper.configuration.native_redirect_uri
end
def validate_each(record, attribute, value)
if value.blank?
record.errors.add(attribute, :blank)
else
value.split.each do |val|
uri = ::URI.parse(val)
return if native_redirect_uri?(uri)
record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
record.errors.add(attribute, :relative_uri) if uri.scheme.nil? || uri.host.nil?
record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
end
end
rescue URI::InvalidURIError
record.errors.add(attribute, :invalid_uri)
end
private
def native_redirect_uri?(uri)
self.class.native_redirect_uri.present? && uri.to_s == self.class.native_redirect_uri.to_s
end
def invalid_ssl_uri?(uri)
forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
forces_ssl && uri.try(:scheme) != 'https'
end
end
doorkeeper-2.2.1/app/controllers/ 0000755 0000764 0000764 00000000000 12544753400 016041 5 ustar pravi pravi doorkeeper-2.2.1/app/controllers/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 020200 5 ustar pravi pravi doorkeeper-2.2.1/app/controllers/doorkeeper/authorized_applications_controller.rb 0000644 0000764 0000764 00000000746 12544753400 027723 0 ustar pravi pravi module Doorkeeper
class AuthorizedApplicationsController < Doorkeeper::ApplicationController
before_filter :authenticate_resource_owner!
def index
@applications = Application.authorized_for(current_resource_owner)
end
def destroy
AccessToken.revoke_all_for params[:id], current_resource_owner
redirect_to oauth_authorized_applications_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy])
end
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/token_info_controller.rb 0000644 0000764 0000764 00000000636 12544753400 025130 0 ustar pravi pravi module Doorkeeper
class TokenInfoController < Doorkeeper::ApplicationMetalController
def show
if doorkeeper_token && doorkeeper_token.accessible?
render json: doorkeeper_token, status: :ok
else
error = OAuth::ErrorResponse.new(name: :invalid_request)
response.headers.merge!(error.headers)
render json: error.body, status: error.status
end
end
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/application_controller.rb 0000644 0000764 0000764 00000000417 12544753400 025275 0 ustar pravi pravi module Doorkeeper
class ApplicationController < ActionController::Base
include Helpers::Controller
if ::Rails.version.to_i < 4
protect_from_forgery
else
protect_from_forgery with: :exception
end
helper 'doorkeeper/dashboard'
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/applications_controller.rb 0000644 0000764 0000764 00000002674 12544753400 025467 0 ustar pravi pravi module Doorkeeper
class ApplicationsController < Doorkeeper::ApplicationController
layout 'doorkeeper/admin'
before_filter :authenticate_admin!
before_filter :set_application, only: [:show, :edit, :update, :destroy]
def index
@applications = Application.all
end
def new
@application = Application.new
end
def create
@application = Application.new(application_params)
if @application.save
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
redirect_to oauth_application_url(@application)
else
render :new
end
end
def update
if @application.update_attributes(application_params)
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :update])
redirect_to oauth_application_url(@application)
else
render :edit
end
end
def destroy
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy]) if @application.destroy
redirect_to oauth_applications_url
end
private
def set_application
@application = Application.find(params[:id])
end
def application_params
if params.respond_to?(:permit)
params.require(:doorkeeper_application).permit(:name, :redirect_uri)
else
params[:doorkeeper_application].slice(:name, :redirect_uri) rescue nil
end
end
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/authorizations_controller.rb 0000644 0000764 0000764 00000002574 12544753400 026063 0 ustar pravi pravi module Doorkeeper
class AuthorizationsController < Doorkeeper::ApplicationController
before_filter :authenticate_resource_owner!
def new
if pre_auth.authorizable?
if skip_authorization? || matching_token?
auth = authorization.authorize
redirect_to auth.redirect_uri
else
render :new
end
else
render :error
end
end
# TODO: Handle raise invalid authorization
def create
redirect_or_render authorization.authorize
end
def destroy
redirect_or_render authorization.deny
end
private
def matching_token?
AccessToken.matching_token_for pre_auth.client,
current_resource_owner.id,
pre_auth.scopes
end
def redirect_or_render(auth)
if auth.redirectable?
redirect_to auth.redirect_uri
else
render json: auth.body, status: auth.status
end
end
def pre_auth
@pre_auth ||= OAuth::PreAuthorization.new(Doorkeeper.configuration,
server.client_via_uid,
params)
end
def authorization
@authorization ||= strategy.request
end
def strategy
@strategy ||= server.authorization_request pre_auth.response_type
end
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/application_metal_controller.rb 0000644 0000764 0000764 00000000577 12544753400 026466 0 ustar pravi pravi module Doorkeeper
class ApplicationMetalController < ActionController::Metal
MODULES = [
ActionController::RackDelegation,
ActionController::Instrumentation,
AbstractController::Rendering,
ActionController::Rendering,
ActionController::Renderers::All,
Helpers::Controller
]
MODULES.each do |mod|
include mod
end
end
end
doorkeeper-2.2.1/app/controllers/doorkeeper/tokens_controller.rb 0000644 0000764 0000764 00000002676 12544753400 024306 0 ustar pravi pravi module Doorkeeper
class TokensController < Doorkeeper::ApplicationMetalController
def create
response = authorize_response
self.headers.merge! response.headers
self.response_body = response.body.to_json
self.status = response.status
rescue Errors::DoorkeeperError => e
handle_token_exception e
end
# OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
def revoke
# The authorization server first validates the client credentials
if doorkeeper_token && doorkeeper_token.accessible?
# Doorkeeper does not use the token_type_hint logic described in the RFC 7009
# due to the refresh token implementation that is a field in the access token model.
revoke_token(request.POST['token']) if request.POST['token']
end
# The authorization server responds with HTTP status code 200 if the
# token has been revoked successfully or if the client submitted an invalid token
render json: {}, status: 200
end
private
def revoke_token(token)
token = AccessToken.by_token(token) || AccessToken.by_refresh_token(token)
if token && doorkeeper_token.same_credential?(token)
token.revoke
true
else
false
end
end
def strategy
@strategy ||= server.token_request params[:grant_type]
end
def authorize_response
@authorize_response ||= strategy.authorize
end
end
end
doorkeeper-2.2.1/Gemfile 0000644 0000764 0000764 00000000144 12544753400 014205 0 ustar pravi pravi ENV['rails'] ||= '4.2.0'
source 'https://rubygems.org'
gem 'rails', "~> #{ENV['rails']}"
gemspec
doorkeeper-2.2.1/metadata.yml 0000644 0000764 0000764 00000051423 12544753400 015223 0 ustar pravi pravi --- !ruby/object:Gem::Specification
name: doorkeeper
version: !ruby/object:Gem::Version
version: 2.2.1
platform: ruby
authors:
- Felipe Elias Philipp
- Tute Costa
autorequire:
bindir: bin
cert_chain: []
date: 2015-05-05 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: railties
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '3.2'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '3.2'
- !ruby/object:Gem::Dependency
name: sqlite3
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.3.5
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.3.5
- !ruby/object:Gem::Dependency
name: rspec-rails
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 3.2.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 3.2.0
- !ruby/object:Gem::Dependency
name: capybara
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 2.3.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 2.3.0
- !ruby/object:Gem::Dependency
name: generator_spec
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.9.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.9.0
- !ruby/object:Gem::Dependency
name: factory_girl
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 4.5.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 4.5.0
- !ruby/object:Gem::Dependency
name: timecop
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.7.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.7.0
- !ruby/object:Gem::Dependency
name: database_cleaner
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.3.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.3.0
- !ruby/object:Gem::Dependency
name: rspec-activemodel-mocks
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.0.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 1.0.0
- !ruby/object:Gem::Dependency
name: bcrypt-ruby
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 3.0.1
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 3.0.1
- !ruby/object:Gem::Dependency
name: pry
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.10.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: 0.10.0
description: Doorkeeper is an OAuth 2 provider for Rails and Grape.
email:
- tutecosta@gmail.com
executables: []
extensions: []
extra_rdoc_files: []
files:
- ".gitignore"
- ".hound.yml"
- ".rspec"
- ".travis.yml"
- CHANGELOG.md
- CONTRIBUTING.md
- Gemfile
- MIT-LICENSE
- NEWS.md
- README.md
- RELEASING.md
- Rakefile
- app/assets/stylesheets/doorkeeper/admin/application.css
- app/assets/stylesheets/doorkeeper/application.css
- app/controllers/doorkeeper/application_controller.rb
- app/controllers/doorkeeper/application_metal_controller.rb
- app/controllers/doorkeeper/applications_controller.rb
- app/controllers/doorkeeper/authorizations_controller.rb
- app/controllers/doorkeeper/authorized_applications_controller.rb
- app/controllers/doorkeeper/token_info_controller.rb
- app/controllers/doorkeeper/tokens_controller.rb
- app/helpers/doorkeeper/dashboard_helper.rb
- app/validators/redirect_uri_validator.rb
- app/views/doorkeeper/applications/_delete_form.html.erb
- app/views/doorkeeper/applications/_form.html.erb
- app/views/doorkeeper/applications/edit.html.erb
- app/views/doorkeeper/applications/index.html.erb
- app/views/doorkeeper/applications/new.html.erb
- app/views/doorkeeper/applications/show.html.erb
- app/views/doorkeeper/authorizations/error.html.erb
- app/views/doorkeeper/authorizations/new.html.erb
- app/views/doorkeeper/authorizations/show.html.erb
- app/views/doorkeeper/authorized_applications/_delete_form.html.erb
- app/views/doorkeeper/authorized_applications/index.html.erb
- app/views/layouts/doorkeeper/admin.html.erb
- app/views/layouts/doorkeeper/application.html.erb
- config/locales/en.yml
- doorkeeper.gemspec
- gemfiles/Gemfile.common.rb
- gemfiles/Gemfile.mongo_mapper.rb
- gemfiles/Gemfile.mongoid2.rb
- gemfiles/Gemfile.mongoid3.rb
- gemfiles/Gemfile.mongoid4.rb
- lib/doorkeeper.rb
- lib/doorkeeper/config.rb
- lib/doorkeeper/engine.rb
- lib/doorkeeper/errors.rb
- lib/doorkeeper/generators/doorkeeper/mongo_mapper/indexes_generator.rb
- lib/doorkeeper/generators/doorkeeper/mongo_mapper/templates/indexes.rb
- lib/doorkeeper/grape/authorization_decorator.rb
- lib/doorkeeper/grape/helpers.rb
- lib/doorkeeper/helpers/controller.rb
- lib/doorkeeper/models/access_grant_mixin.rb
- lib/doorkeeper/models/access_token_mixin.rb
- lib/doorkeeper/models/application_mixin.rb
- lib/doorkeeper/models/concerns/accessible.rb
- lib/doorkeeper/models/concerns/expirable.rb
- lib/doorkeeper/models/concerns/ownership.rb
- lib/doorkeeper/models/concerns/revocable.rb
- lib/doorkeeper/models/concerns/scopes.rb
- lib/doorkeeper/oauth/authorization/code.rb
- lib/doorkeeper/oauth/authorization/token.rb
- lib/doorkeeper/oauth/authorization/uri_builder.rb
- lib/doorkeeper/oauth/authorization_code_request.rb
- lib/doorkeeper/oauth/client.rb
- lib/doorkeeper/oauth/client/credentials.rb
- lib/doorkeeper/oauth/client/methods.rb
- lib/doorkeeper/oauth/client_credentials/creator.rb
- lib/doorkeeper/oauth/client_credentials/issuer.rb
- lib/doorkeeper/oauth/client_credentials/validation.rb
- lib/doorkeeper/oauth/client_credentials_request.rb
- lib/doorkeeper/oauth/code_request.rb
- lib/doorkeeper/oauth/code_response.rb
- lib/doorkeeper/oauth/error.rb
- lib/doorkeeper/oauth/error_response.rb
- lib/doorkeeper/oauth/forbidden_token_response.rb
- lib/doorkeeper/oauth/helpers/scope_checker.rb
- lib/doorkeeper/oauth/helpers/unique_token.rb
- lib/doorkeeper/oauth/helpers/uri_checker.rb
- lib/doorkeeper/oauth/invalid_token_response.rb
- lib/doorkeeper/oauth/password_access_token_request.rb
- lib/doorkeeper/oauth/pre_authorization.rb
- lib/doorkeeper/oauth/refresh_token_request.rb
- lib/doorkeeper/oauth/request_concern.rb
- lib/doorkeeper/oauth/scopes.rb
- lib/doorkeeper/oauth/token.rb
- lib/doorkeeper/oauth/token_request.rb
- lib/doorkeeper/oauth/token_response.rb
- lib/doorkeeper/orm/active_record.rb
- lib/doorkeeper/orm/active_record/access_grant.rb
- lib/doorkeeper/orm/active_record/access_token.rb
- lib/doorkeeper/orm/active_record/application.rb
- lib/doorkeeper/orm/mongo_mapper.rb
- lib/doorkeeper/orm/mongo_mapper/access_grant.rb
- lib/doorkeeper/orm/mongo_mapper/access_token.rb
- lib/doorkeeper/orm/mongo_mapper/application.rb
- lib/doorkeeper/orm/mongoid2.rb
- lib/doorkeeper/orm/mongoid2/access_grant.rb
- lib/doorkeeper/orm/mongoid2/access_token.rb
- lib/doorkeeper/orm/mongoid2/application.rb
- lib/doorkeeper/orm/mongoid2/concerns/scopes.rb
- lib/doorkeeper/orm/mongoid3.rb
- lib/doorkeeper/orm/mongoid3/access_grant.rb
- lib/doorkeeper/orm/mongoid3/access_token.rb
- lib/doorkeeper/orm/mongoid3/application.rb
- lib/doorkeeper/orm/mongoid3/concerns/scopes.rb
- lib/doorkeeper/orm/mongoid4.rb
- lib/doorkeeper/orm/mongoid4/access_grant.rb
- lib/doorkeeper/orm/mongoid4/access_token.rb
- lib/doorkeeper/orm/mongoid4/application.rb
- lib/doorkeeper/orm/mongoid4/concerns/scopes.rb
- lib/doorkeeper/rails/helpers.rb
- lib/doorkeeper/rails/routes.rb
- lib/doorkeeper/rails/routes/mapper.rb
- lib/doorkeeper/rails/routes/mapping.rb
- lib/doorkeeper/request.rb
- lib/doorkeeper/request/authorization_code.rb
- lib/doorkeeper/request/client_credentials.rb
- lib/doorkeeper/request/code.rb
- lib/doorkeeper/request/password.rb
- lib/doorkeeper/request/refresh_token.rb
- lib/doorkeeper/request/token.rb
- lib/doorkeeper/server.rb
- lib/doorkeeper/validations.rb
- lib/doorkeeper/version.rb
- lib/generators/doorkeeper/application_owner_generator.rb
- lib/generators/doorkeeper/application_scopes_generator.rb
- lib/generators/doorkeeper/install_generator.rb
- lib/generators/doorkeeper/migration_generator.rb
- lib/generators/doorkeeper/templates/README
- lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb
- lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb
- lib/generators/doorkeeper/templates/initializer.rb
- lib/generators/doorkeeper/templates/migration.rb
- lib/generators/doorkeeper/views_generator.rb
- spec/controllers/applications_controller_spec.rb
- spec/controllers/authorizations_controller_spec.rb
- spec/controllers/protected_resources_controller_spec.rb
- spec/controllers/token_info_controller_spec.rb
- spec/controllers/tokens_controller_spec.rb
- spec/dummy/Rakefile
- spec/dummy/app/controllers/application_controller.rb
- spec/dummy/app/controllers/custom_authorizations_controller.rb
- spec/dummy/app/controllers/full_protected_resources_controller.rb
- spec/dummy/app/controllers/home_controller.rb
- spec/dummy/app/controllers/metal_controller.rb
- spec/dummy/app/controllers/semi_protected_resources_controller.rb
- spec/dummy/app/helpers/application_helper.rb
- spec/dummy/app/models/user.rb
- spec/dummy/app/views/home/index.html.erb
- spec/dummy/app/views/layouts/application.html.erb
- spec/dummy/config.ru
- spec/dummy/config/application.rb
- spec/dummy/config/boot.rb
- spec/dummy/config/database.yml
- spec/dummy/config/environment.rb
- spec/dummy/config/environments/development.rb
- spec/dummy/config/environments/production.rb
- spec/dummy/config/environments/test.rb
- spec/dummy/config/initializers/backtrace_silencers.rb
- spec/dummy/config/initializers/doorkeeper.rb
- spec/dummy/config/initializers/secret_token.rb
- spec/dummy/config/initializers/session_store.rb
- spec/dummy/config/initializers/wrap_parameters.rb
- spec/dummy/config/locales/doorkeeper.en.yml
- spec/dummy/config/mongo.yml
- spec/dummy/config/mongoid2.yml
- spec/dummy/config/mongoid3.yml
- spec/dummy/config/mongoid4.yml
- spec/dummy/config/routes.rb
- spec/dummy/db/migrate/20111122132257_create_users.rb
- spec/dummy/db/migrate/20120312140401_add_password_to_users.rb
- spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb
- spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb
- spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb
- spec/dummy/db/schema.rb
- spec/dummy/public/404.html
- spec/dummy/public/422.html
- spec/dummy/public/500.html
- spec/dummy/public/favicon.ico
- spec/dummy/script/rails
- spec/factories.rb
- spec/generators/application_owner_generator_spec.rb
- spec/generators/install_generator_spec.rb
- spec/generators/migration_generator_spec.rb
- spec/generators/templates/routes.rb
- spec/generators/views_generator_spec.rb
- spec/lib/config_spec.rb
- spec/lib/doorkeeper_spec.rb
- spec/lib/models/expirable_spec.rb
- spec/lib/models/revocable_spec.rb
- spec/lib/models/scopes_spec.rb
- spec/lib/oauth/authorization/uri_builder_spec.rb
- spec/lib/oauth/authorization_code_request_spec.rb
- spec/lib/oauth/client/credentials_spec.rb
- spec/lib/oauth/client/methods_spec.rb
- spec/lib/oauth/client_credentials/creator_spec.rb
- spec/lib/oauth/client_credentials/issuer_spec.rb
- spec/lib/oauth/client_credentials/validation_spec.rb
- spec/lib/oauth/client_credentials_integration_spec.rb
- spec/lib/oauth/client_credentials_request_spec.rb
- spec/lib/oauth/client_spec.rb
- spec/lib/oauth/code_request_spec.rb
- spec/lib/oauth/error_response_spec.rb
- spec/lib/oauth/error_spec.rb
- spec/lib/oauth/forbidden_token_response_spec.rb
- spec/lib/oauth/helpers/scope_checker_spec.rb
- spec/lib/oauth/helpers/unique_token_spec.rb
- spec/lib/oauth/helpers/uri_checker_spec.rb
- spec/lib/oauth/invalid_token_response_spec.rb
- spec/lib/oauth/password_access_token_request_spec.rb
- spec/lib/oauth/pre_authorization_spec.rb
- spec/lib/oauth/refresh_token_request_spec.rb
- spec/lib/oauth/scopes_spec.rb
- spec/lib/oauth/token_request_spec.rb
- spec/lib/oauth/token_response_spec.rb
- spec/lib/oauth/token_spec.rb
- spec/lib/server_spec.rb
- spec/models/doorkeeper/access_grant_spec.rb
- spec/models/doorkeeper/access_token_spec.rb
- spec/models/doorkeeper/application_spec.rb
- spec/requests/applications/applications_request_spec.rb
- spec/requests/applications/authorized_applications_spec.rb
- spec/requests/endpoints/authorization_spec.rb
- spec/requests/endpoints/token_spec.rb
- spec/requests/flows/authorization_code_errors_spec.rb
- spec/requests/flows/authorization_code_spec.rb
- spec/requests/flows/client_credentials_spec.rb
- spec/requests/flows/implicit_grant_errors_spec.rb
- spec/requests/flows/implicit_grant_spec.rb
- spec/requests/flows/password_spec.rb
- spec/requests/flows/refresh_token_spec.rb
- spec/requests/flows/revoke_token_spec.rb
- spec/requests/flows/skip_authorization_spec.rb
- spec/requests/protected_resources/metal_spec.rb
- spec/requests/protected_resources/private_api_spec.rb
- spec/routing/custom_controller_routes_spec.rb
- spec/routing/default_routes_spec.rb
- spec/routing/scoped_routes_spec.rb
- spec/spec_helper.rb
- spec/spec_helper_integration.rb
- spec/support/dependencies/factory_girl.rb
- spec/support/helpers/access_token_request_helper.rb
- spec/support/helpers/authorization_request_helper.rb
- spec/support/helpers/config_helper.rb
- spec/support/helpers/model_helper.rb
- spec/support/helpers/request_spec_helper.rb
- spec/support/helpers/url_helper.rb
- spec/support/orm/active_record.rb
- spec/support/orm/mongo_mapper.rb
- spec/support/orm/mongoid.rb
- spec/support/shared/controllers_shared_context.rb
- spec/support/shared/models_shared_examples.rb
- spec/validators/redirect_uri_validator_spec.rb
- vendor/assets/stylesheets/doorkeeper/bootstrap.min.css
homepage: https://github.com/doorkeeper-gem/doorkeeper
licenses:
- MIT
metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
rubygems_version: 2.4.5
signing_key:
specification_version: 4
summary: OAuth 2 provider for Rails and Grape
test_files:
- spec/controllers/applications_controller_spec.rb
- spec/controllers/authorizations_controller_spec.rb
- spec/controllers/protected_resources_controller_spec.rb
- spec/controllers/token_info_controller_spec.rb
- spec/controllers/tokens_controller_spec.rb
- spec/dummy/Rakefile
- spec/dummy/app/controllers/application_controller.rb
- spec/dummy/app/controllers/custom_authorizations_controller.rb
- spec/dummy/app/controllers/full_protected_resources_controller.rb
- spec/dummy/app/controllers/home_controller.rb
- spec/dummy/app/controllers/metal_controller.rb
- spec/dummy/app/controllers/semi_protected_resources_controller.rb
- spec/dummy/app/helpers/application_helper.rb
- spec/dummy/app/models/user.rb
- spec/dummy/app/views/home/index.html.erb
- spec/dummy/app/views/layouts/application.html.erb
- spec/dummy/config.ru
- spec/dummy/config/application.rb
- spec/dummy/config/boot.rb
- spec/dummy/config/database.yml
- spec/dummy/config/environment.rb
- spec/dummy/config/environments/development.rb
- spec/dummy/config/environments/production.rb
- spec/dummy/config/environments/test.rb
- spec/dummy/config/initializers/backtrace_silencers.rb
- spec/dummy/config/initializers/doorkeeper.rb
- spec/dummy/config/initializers/secret_token.rb
- spec/dummy/config/initializers/session_store.rb
- spec/dummy/config/initializers/wrap_parameters.rb
- spec/dummy/config/locales/doorkeeper.en.yml
- spec/dummy/config/mongo.yml
- spec/dummy/config/mongoid2.yml
- spec/dummy/config/mongoid3.yml
- spec/dummy/config/mongoid4.yml
- spec/dummy/config/routes.rb
- spec/dummy/db/migrate/20111122132257_create_users.rb
- spec/dummy/db/migrate/20120312140401_add_password_to_users.rb
- spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb
- spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb
- spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb
- spec/dummy/db/schema.rb
- spec/dummy/public/404.html
- spec/dummy/public/422.html
- spec/dummy/public/500.html
- spec/dummy/public/favicon.ico
- spec/dummy/script/rails
- spec/factories.rb
- spec/generators/application_owner_generator_spec.rb
- spec/generators/install_generator_spec.rb
- spec/generators/migration_generator_spec.rb
- spec/generators/templates/routes.rb
- spec/generators/views_generator_spec.rb
- spec/lib/config_spec.rb
- spec/lib/doorkeeper_spec.rb
- spec/lib/models/expirable_spec.rb
- spec/lib/models/revocable_spec.rb
- spec/lib/models/scopes_spec.rb
- spec/lib/oauth/authorization/uri_builder_spec.rb
- spec/lib/oauth/authorization_code_request_spec.rb
- spec/lib/oauth/client/credentials_spec.rb
- spec/lib/oauth/client/methods_spec.rb
- spec/lib/oauth/client_credentials/creator_spec.rb
- spec/lib/oauth/client_credentials/issuer_spec.rb
- spec/lib/oauth/client_credentials/validation_spec.rb
- spec/lib/oauth/client_credentials_integration_spec.rb
- spec/lib/oauth/client_credentials_request_spec.rb
- spec/lib/oauth/client_spec.rb
- spec/lib/oauth/code_request_spec.rb
- spec/lib/oauth/error_response_spec.rb
- spec/lib/oauth/error_spec.rb
- spec/lib/oauth/forbidden_token_response_spec.rb
- spec/lib/oauth/helpers/scope_checker_spec.rb
- spec/lib/oauth/helpers/unique_token_spec.rb
- spec/lib/oauth/helpers/uri_checker_spec.rb
- spec/lib/oauth/invalid_token_response_spec.rb
- spec/lib/oauth/password_access_token_request_spec.rb
- spec/lib/oauth/pre_authorization_spec.rb
- spec/lib/oauth/refresh_token_request_spec.rb
- spec/lib/oauth/scopes_spec.rb
- spec/lib/oauth/token_request_spec.rb
- spec/lib/oauth/token_response_spec.rb
- spec/lib/oauth/token_spec.rb
- spec/lib/server_spec.rb
- spec/models/doorkeeper/access_grant_spec.rb
- spec/models/doorkeeper/access_token_spec.rb
- spec/models/doorkeeper/application_spec.rb
- spec/requests/applications/applications_request_spec.rb
- spec/requests/applications/authorized_applications_spec.rb
- spec/requests/endpoints/authorization_spec.rb
- spec/requests/endpoints/token_spec.rb
- spec/requests/flows/authorization_code_errors_spec.rb
- spec/requests/flows/authorization_code_spec.rb
- spec/requests/flows/client_credentials_spec.rb
- spec/requests/flows/implicit_grant_errors_spec.rb
- spec/requests/flows/implicit_grant_spec.rb
- spec/requests/flows/password_spec.rb
- spec/requests/flows/refresh_token_spec.rb
- spec/requests/flows/revoke_token_spec.rb
- spec/requests/flows/skip_authorization_spec.rb
- spec/requests/protected_resources/metal_spec.rb
- spec/requests/protected_resources/private_api_spec.rb
- spec/routing/custom_controller_routes_spec.rb
- spec/routing/default_routes_spec.rb
- spec/routing/scoped_routes_spec.rb
- spec/spec_helper.rb
- spec/spec_helper_integration.rb
- spec/support/dependencies/factory_girl.rb
- spec/support/helpers/access_token_request_helper.rb
- spec/support/helpers/authorization_request_helper.rb
- spec/support/helpers/config_helper.rb
- spec/support/helpers/model_helper.rb
- spec/support/helpers/request_spec_helper.rb
- spec/support/helpers/url_helper.rb
- spec/support/orm/active_record.rb
- spec/support/orm/mongo_mapper.rb
- spec/support/orm/mongoid.rb
- spec/support/shared/controllers_shared_context.rb
- spec/support/shared/models_shared_examples.rb
- spec/validators/redirect_uri_validator_spec.rb
doorkeeper-2.2.1/lib/ 0000755 0000764 0000764 00000000000 12544753400 013461 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper.rb 0000644 0000764 0000764 00000004331 12544753400 016146 0 ustar pravi pravi require 'doorkeeper/version'
require 'doorkeeper/engine'
require 'doorkeeper/config'
require 'doorkeeper/errors'
require 'doorkeeper/server'
require 'doorkeeper/request'
require 'doorkeeper/validations'
require 'doorkeeper/oauth/authorization/code'
require 'doorkeeper/oauth/authorization/token'
require 'doorkeeper/oauth/authorization/uri_builder'
require 'doorkeeper/oauth/helpers/scope_checker'
require 'doorkeeper/oauth/helpers/uri_checker'
require 'doorkeeper/oauth/helpers/unique_token'
require 'doorkeeper/oauth/scopes'
require 'doorkeeper/oauth/error'
require 'doorkeeper/oauth/code_response'
require 'doorkeeper/oauth/token_response'
require 'doorkeeper/oauth/error_response'
require 'doorkeeper/oauth/pre_authorization'
require 'doorkeeper/oauth/request_concern'
require 'doorkeeper/oauth/authorization_code_request'
require 'doorkeeper/oauth/refresh_token_request'
require 'doorkeeper/oauth/password_access_token_request'
require 'doorkeeper/oauth/client_credentials_request'
require 'doorkeeper/oauth/code_request'
require 'doorkeeper/oauth/token_request'
require 'doorkeeper/oauth/client'
require 'doorkeeper/oauth/token'
require 'doorkeeper/oauth/invalid_token_response'
require 'doorkeeper/oauth/forbidden_token_response'
require 'doorkeeper/models/concerns/scopes'
require 'doorkeeper/models/concerns/expirable'
require 'doorkeeper/models/concerns/revocable'
require 'doorkeeper/models/concerns/accessible'
require 'doorkeeper/models/access_grant_mixin'
require 'doorkeeper/models/access_token_mixin'
require 'doorkeeper/models/application_mixin'
require 'doorkeeper/helpers/controller'
require 'doorkeeper/rails/routes'
require 'doorkeeper/rails/helpers'
require 'doorkeeper/orm/active_record'
require 'doorkeeper/orm/mongo_mapper'
require 'doorkeeper/orm/mongoid2'
require 'doorkeeper/orm/mongoid3'
require 'doorkeeper/orm/mongoid4'
module Doorkeeper
def self.configured?
@config.present?
end
def self.database_installed?
[AccessToken, AccessGrant, Application].all? { |model| model.table_exists? }
end
def self.installed?
configured? && database_installed?
end
def self.authenticate(request, methods = Doorkeeper.configuration.access_token_methods)
OAuth::Token.authenticate(request, *methods)
end
end
doorkeeper-2.2.1/lib/generators/ 0000755 0000764 0000764 00000000000 12544753400 015632 5 ustar pravi pravi doorkeeper-2.2.1/lib/generators/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 017771 5 ustar pravi pravi doorkeeper-2.2.1/lib/generators/doorkeeper/install_generator.rb 0000644 0000764 0000764 00000000672 12544753400 024037 0 ustar pravi pravi class Doorkeeper::InstallGenerator < ::Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)
desc 'Installs Doorkeeper.'
def install
template 'initializer.rb', 'config/initializers/doorkeeper.rb'
copy_file File.expand_path('../../../../config/locales/en.yml', __FILE__), 'config/locales/doorkeeper.en.yml'
route 'use_doorkeeper'
readme 'README'
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/migration_generator.rb 0000644 0000764 0000764 00000000724 12544753400 024360 0 ustar pravi pravi require 'rails/generators/active_record'
class Doorkeeper::MigrationGenerator < ::Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)
desc 'Installs Doorkeeper migration file.'
def install
migration_template 'migration.rb', 'db/migrate/create_doorkeeper_tables.rb'
end
def self.next_migration_number(dirname)
ActiveRecord::Generators::Base.next_migration_number(dirname)
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/application_scopes_generator.rb 0000644 0000764 0000764 00000001636 12544753400 026251 0 ustar pravi pravi require 'rails/generators/active_record'
class Doorkeeper::ApplicationScopesGenerator < Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)
desc 'Copies ActiveRecord migrations to handle upgrade to doorkeeper 2'
def self.next_migration_number(path)
ActiveRecord::Generators::Base.next_migration_number(path)
end
def application_scopes
if oauth_applications_exists? && !scopes_column_exists?
migration_template(
'add_scopes_to_oauth_applications.rb',
'db/migrate/add_scopes_to_oauth_applications.rb'
)
end
end
private
def scopes_column_exists?
ActiveRecord::Base.connection.column_exists?(
:oauth_applications,
:scopes
)
end
# Might be running this before install
def oauth_applications_exists?
ActiveRecord::Base.connection.table_exists? :oauth_applications
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/application_owner_generator.rb 0000644 0000764 0000764 00000001035 12544753400 026100 0 ustar pravi pravi require 'rails/generators/active_record'
class Doorkeeper::ApplicationOwnerGenerator < Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)
desc 'Provide support for client application ownership.'
def application_owner
migration_template(
'add_owner_to_application_migration.rb',
'db/migrate/add_owner_to_application.rb'
)
end
def self.next_migration_number(dirname)
ActiveRecord::Generators::Base.next_migration_number(dirname)
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/templates/ 0000755 0000764 0000764 00000000000 12544753400 021767 5 ustar pravi pravi doorkeeper-2.2.1/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb 0000644 0000764 0000764 00000000243 12544753400 031067 0 ustar pravi pravi class AddScopesToOauthApplications < ActiveRecord::Migration
def change
add_column :oauth_applications, :scopes, :string, null: false, default: ''
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/templates/migration.rb 0000644 0000764 0000764 00000002576 12544753400 024317 0 ustar pravi pravi class CreateDoorkeeperTables < ActiveRecord::Migration
def change
create_table :oauth_applications do |t|
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false
t.text :redirect_uri, null: false
t.string :scopes, null: false, default: ''
t.timestamps
end
add_index :oauth_applications, :uid, unique: true
create_table :oauth_access_grants do |t|
t.integer :resource_owner_id, null: false
t.integer :application_id, null: false
t.string :token, null: false
t.integer :expires_in, null: false
t.text :redirect_uri, null: false
t.datetime :created_at, null: false
t.datetime :revoked_at
t.string :scopes
end
add_index :oauth_access_grants, :token, unique: true
create_table :oauth_access_tokens do |t|
t.integer :resource_owner_id
t.integer :application_id
t.string :token, null: false
t.string :refresh_token
t.integer :expires_in
t.datetime :revoked_at
t.datetime :created_at, null: false
t.string :scopes
end
add_index :oauth_access_tokens, :token, unique: true
add_index :oauth_access_tokens, :resource_owner_id
add_index :oauth_access_tokens, :refresh_token, unique: true
end
end
doorkeeper-2.2.1/lib/generators/doorkeeper/templates/README 0000644 0000764 0000764 00000001523 12544753400 022650 0 ustar pravi pravi ===============================================================================
There is a setup that you need to do before you can use doorkeeper.
Step 1.
Go to config/initializers/doorkeeper.rb and configure
resource_owner_authenticator block.
Step 2.
Choose the ORM:
If you want to use ActiveRecord run:
rails generate doorkeeper:migration
And run
rake db:migrate
If you want to use Mongoid, configure the orm in initializers/doorkeeper.rb:
# Mongoid
Doorkeeper.configure do
orm :mongoid
end
If you want to use MongoMapper, configure the orm in
initializers/doorkeeper.rb:
# MongoMapper
Doorkeeper.configure do
orm :mongo_mapper
end
And run
rails generate doorkeeper:mongo_mapper:indexes
rake db:index
Step 3.
That's it, that's all. Enjoy!
===============================================================================
doorkeeper-2.2.1/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb 0000644 0000764 0000764 00000000421 12544753400 031411 0 ustar pravi pravi class AddOwnerToApplication < ActiveRecord::Migration
def change
add_column :oauth_applications, :owner_id, :integer, null: true
add_column :oauth_applications, :owner_type, :string, null: true
add_index :oauth_applications, [:owner_id, :owner_type]
end
end doorkeeper-2.2.1/lib/generators/doorkeeper/templates/initializer.rb 0000644 0000764 0000764 00000011706 12544753400 024644 0 ustar pravi pravi Doorkeeper.configure do
# Change the ORM that doorkeeper will use.
# Currently supported options are :active_record, :mongoid2, :mongoid3,
# :mongoid4, :mongo_mapper
orm :active_record
# This block will be called to check whether the resource owner is authenticated or not.
resource_owner_authenticator do
fail "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
# Put your resource owner authentication logic here.
# Example implementation:
# User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
end
# If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
# admin_authenticator do
# # Put your admin authentication logic here.
# # Example implementation:
# Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
# end
# Authorization Code expiration time (default 10 minutes).
# authorization_code_expires_in 10.minutes
# Access token expiration time (default 2 hours).
# If you want to disable expiration, set this to nil.
# access_token_expires_in 2.hours
# Assign a custom TTL for implicit grants.
# custom_access_token_expires_in do |oauth_client|
# oauth_client.application.additional_settings.implicit_oauth_expiration
# end
# Use a custom class for generating the access token.
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
# access_token_generator "::Doorkeeper::JWT"
# Reuse access token for the same resource owner within an application (disabled by default)
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
# reuse_access_token
# Issue access tokens with refresh token (disabled by default)
# use_refresh_token
# Provide support for an owner to be assigned to each registered application (disabled by default)
# Optional parameter :confirmation => true (default false) if you want to enforce ownership of
# a registered application
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
# enable_application_owner :confirmation => false
# Define access token scopes for your provider
# For more information go to
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
# default_scopes :public
# optional_scopes :write, :update
# Change the way client credentials are retrieved from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
# Check out the wiki for more information on customization
# client_credentials :from_basic, :from_params
# Change the way access token is authenticated from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
# falls back to the `:access_token` or `:bearer_token` params from the `params` object.
# Check out the wiki for more information on customization
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
# Change the native redirect uri for client apps
# When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
#
# native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
# by default in non-development environments). OAuth2 delegates security in
# communication to the HTTPS protocol so it is wise to keep this enabled.
#
# force_ssl_in_redirect_uri !Rails.env.development?
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
#
# "authorization_code" => Authorization Code Grant Flow
# "implicit" => Implicit Grant Flow
# "password" => Resource Owner Password Credentials Grant Flow
# "client_credentials" => Client Credentials Grant Flow
#
# If not specified, Doorkeeper enables authorization_code and
# client_credentials.
#
# implicit and password grant flows have risks that you should understand
# before enabling:
# http://tools.ietf.org/html/rfc6819#section-4.4.2
# http://tools.ietf.org/html/rfc6819#section-4.4.3
#
# grant_flows %w(authorization_code client_credentials)
# Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step.
# For example if dealing with a trusted application.
# skip_authorization do |resource_owner, client|
# client.superapp? or resource_owner.admin?
# end
# WWW-Authenticate Realm (default "Doorkeeper").
# realm "Doorkeeper"
end
doorkeeper-2.2.1/lib/generators/doorkeeper/views_generator.rb 0000644 0000764 0000764 00000000636 12544753400 023526 0 ustar pravi pravi module Doorkeeper
module Generators
class ViewsGenerator < ::Rails::Generators::Base
source_root File.expand_path('../../../../app/views', __FILE__)
desc 'Copies default Doorkeeper views and layouts to your application.'
def manifest
directory 'doorkeeper', 'app/views/doorkeeper'
directory 'layouts/doorkeeper', 'app/views/layouts/doorkeeper'
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 015620 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/errors.rb 0000644 0000764 0000764 00000000615 12544753400 017463 0 ustar pravi pravi module Doorkeeper
module Errors
class DoorkeeperError < StandardError
end
class InvalidAuthorizationStrategy < DoorkeeperError
end
class InvalidTokenStrategy < DoorkeeperError
end
class MissingRequestStrategy < DoorkeeperError
end
class UnableToGenerateToken < DoorkeeperError
end
class TokenGeneratorNotFound < DoorkeeperError
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/validations.rb 0000644 0000764 0000764 00000001074 12544753400 020464 0 ustar pravi pravi module Doorkeeper
module Validations
extend ActiveSupport::Concern
attr_accessor :error
def validate
@error = nil
self.class.validations.each do |validation|
break if @error
@error = validation.last unless send("validate_#{validation.first}")
end
end
def valid?
validate
@error.nil?
end
module ClassMethods
def validate(attribute, options = {})
validations << [attribute, options[:error]]
end
def validations
@validations ||= []
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request.rb 0000644 0000764 0000764 00000001652 12544753400 017641 0 ustar pravi pravi require 'doorkeeper/request/authorization_code'
require 'doorkeeper/request/client_credentials'
require 'doorkeeper/request/code'
require 'doorkeeper/request/password'
require 'doorkeeper/request/refresh_token'
require 'doorkeeper/request/token'
module Doorkeeper
module Request
module_function
def authorization_strategy(strategy)
get_strategy strategy, Doorkeeper.configuration.authorization_response_types
rescue NameError
raise Errors::InvalidAuthorizationStrategy
end
def token_strategy(strategy)
get_strategy strategy, Doorkeeper.configuration.token_grant_types
rescue NameError
raise Errors::InvalidTokenStrategy
end
def get_strategy(strategy, available)
fail Errors::MissingRequestStrategy unless strategy.present?
fail NameError unless available.include?(strategy.to_s)
"Doorkeeper::Request::#{strategy.to_s.camelize}".constantize
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/ 0000755 0000764 0000764 00000000000 12544753400 017310 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/request/password.rb 0000644 0000764 0000764 00000001137 12544753400 021501 0 ustar pravi pravi module Doorkeeper
module Request
class Password
def self.build(server)
new(server.credentials, server.resource_owner, server)
end
attr_accessor :credentials, :resource_owner, :server
def initialize(credentials, resource_owner, server)
@credentials, @resource_owner, @server = credentials, resource_owner, server
end
def request
@request ||= OAuth::PasswordAccessTokenRequest.new(Doorkeeper.configuration, credentials, resource_owner, server.parameters)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/token.rb 0000644 0000764 0000764 00000000724 12544753400 020760 0 ustar pravi pravi module Doorkeeper
module Request
class Token
def self.build(server)
new(server.context.send(:pre_auth), server)
end
attr_accessor :pre_auth, :server
def initialize(pre_auth, server)
@pre_auth, @server = pre_auth, server
end
def request
@request ||= OAuth::TokenRequest.new(pre_auth, server.current_resource_owner)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/refresh_token.rb 0000644 0000764 0000764 00000001136 12544753400 022474 0 ustar pravi pravi module Doorkeeper
module Request
class RefreshToken
def self.build(server)
new(server.current_refresh_token, server.credentials, server)
end
attr_accessor :refresh_token, :credentials, :server
def initialize(refresh_token, credentials, server)
@refresh_token, @credentials, @server = refresh_token, credentials, server
end
def request
@request ||= OAuth::RefreshTokenRequest.new(Doorkeeper.configuration, refresh_token, credentials, server.parameters)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/code.rb 0000644 0000764 0000764 00000000722 12544753400 020550 0 ustar pravi pravi module Doorkeeper
module Request
class Code
def self.build(server)
new(server.context.send(:pre_auth), server)
end
attr_accessor :pre_auth, :server
def initialize(pre_auth, server)
@pre_auth, @server = pre_auth, server
end
def request
@request ||= OAuth::CodeRequest.new(pre_auth, server.current_resource_owner)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/client_credentials.rb 0000644 0000764 0000764 00000000737 12544753400 023477 0 ustar pravi pravi module Doorkeeper
module Request
class ClientCredentials
def self.build(server)
new(server.client, server)
end
attr_accessor :client, :server
def initialize(client, server)
@client, @server = client, server
end
def request
@request ||= OAuth::ClientCredentialsRequest.new(Doorkeeper.configuration, client, server.parameters)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/request/authorization_code.rb 0000644 0000764 0000764 00000001022 12544753400 023522 0 ustar pravi pravi module Doorkeeper
module Request
class AuthorizationCode
def self.build(server)
new(server.grant, server.client, server)
end
attr_accessor :grant, :client, :server
def initialize(grant, client, server)
@grant, @client, @server = grant, client, server
end
def request
@request ||= OAuth::AuthorizationCodeRequest.new(Doorkeeper.configuration, grant, client, server.parameters)
end
def authorize
request.authorize
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/ 0000755 0000764 0000764 00000000000 12544753400 016415 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/ 0000755 0000764 0000764 00000000000 12544753400 020135 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/access_grant.rb 0000644 0000764 0000764 00000001067 12544753400 023122 0 ustar pravi pravi require 'doorkeeper/orm/mongoid4/concerns/scopes'
module Doorkeeper
class AccessGrant
include Mongoid::Document
include Mongoid::Timestamps
include AccessGrantMixin
include Models::Mongoid4::Scopes
self.store_in collection: :oauth_access_grants
field :resource_owner_id, type: BSON::ObjectId
field :application_id, type: BSON::ObjectId
field :token, type: String
field :expires_in, type: Integer
field :redirect_uri, type: String
field :revoked_at, type: DateTime
index({ token: 1 }, { unique: true })
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/access_token.rb 0000644 0000764 0000764 00000001703 12544753400 023124 0 ustar pravi pravi require 'doorkeeper/orm/mongoid4/concerns/scopes'
module Doorkeeper
class AccessToken
include Mongoid::Document
include Mongoid::Timestamps
include AccessTokenMixin
include Models::Mongoid4::Scopes
self.store_in collection: :oauth_access_tokens
field :resource_owner_id, type: BSON::ObjectId
field :application_id, type: BSON::ObjectId
field :token, type: String
field :refresh_token, type: String
field :expires_in, type: Integer
field :revoked_at, type: DateTime
index({ token: 1 }, { unique: true })
index({ refresh_token: 1 }, { unique: true, sparse: true })
def self.delete_all_for(application_id, resource_owner)
where(application_id: application_id,
resource_owner_id: resource_owner.id).delete_all
end
private_class_method :delete_all_for
def self.order_method
:order_by
end
def self.created_at_desc
[:created_at, :desc]
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/application.rb 0000644 0000764 0000764 00000001207 12544753400 022765 0 ustar pravi pravi module Doorkeeper
class Application
include Mongoid::Document
include Mongoid::Timestamps
include Models::Mongoid4::Scopes
include ApplicationMixin
self.store_in collection: :oauth_applications
field :name, type: String
field :uid, type: String
field :secret, type: String
field :redirect_uri, type: String
index({ uid: 1 }, { unique: true })
has_many :authorized_tokens, class_name: 'Doorkeeper::AccessToken'
def self.authorized_for(resource_owner)
ids = AccessToken.where(resource_owner_id: resource_owner.id, revoked_at: nil).map(&:application_id)
find(ids)
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/concerns/ 0000755 0000764 0000764 00000000000 12544753400 021747 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4/concerns/scopes.rb 0000644 0000764 0000764 00000000466 12544753400 023576 0 ustar pravi pravi module Doorkeeper
module Models
module Mongoid4
module Scopes
extend ActiveSupport::Concern
included do
field :scopes, type: String
end
def scopes=(value)
write_attribute :scopes, value if value.present?
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongo_mapper/ 0000755 0000764 0000764 00000000000 12544753400 021100 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongo_mapper/access_grant.rb 0000644 0000764 0000764 00000001003 12544753400 024053 0 ustar pravi pravi module Doorkeeper
class AccessGrant
include MongoMapper::Document
include AccessGrantMixin
safe
timestamps!
set_collection_name 'oauth_access_grants'
key :resource_owner_id, ObjectId
key :application_id, ObjectId
key :token, String
key :scopes, String
key :expires_in, Integer
key :redirect_uri, String
key :revoked_at, DateTime
def self.create_indexes
ensure_index :token, unique: true
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongo_mapper/access_token.rb 0000644 0000764 0000764 00000001707 12544753400 024073 0 ustar pravi pravi module Doorkeeper
class AccessToken
include MongoMapper::Document
include AccessTokenMixin
safe
timestamps!
set_collection_name 'oauth_access_tokens'
key :resource_owner_id, ObjectId
key :application_id, ObjectId
key :token, String
key :refresh_token, String
key :expires_in, Integer
key :revoked_at, DateTime
key :scopes, String
def self.last
self.sort(:created_at).last
end
def self.delete_all_for(application_id, resource_owner)
delete_all(application_id: application_id,
resource_owner_id: resource_owner.id)
end
private_class_method :delete_all_for
def self.create_indexes
ensure_index :token, unique: true
ensure_index [[:refresh_token, 1]], unique: true, sparse: true
end
def self.order_method
:sort
end
def self.created_at_desc
:created_at.desc
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongo_mapper/application.rb 0000644 0000764 0000764 00000001254 12544753400 023732 0 ustar pravi pravi module Doorkeeper
class Application
include MongoMapper::Document
include ApplicationMixin
safe
timestamps!
set_collection_name 'oauth_applications'
many :authorized_tokens, class_name: 'Doorkeeper::AccessToken'
key :name, String
key :uid, String
key :secret, String
key :redirect_uri, String
key :scopes, String
def self.authorized_for(resource_owner)
ids = AccessToken.where(
resource_owner_id: resource_owner.id,
revoked_at: nil
).map(&:application_id)
find(ids)
end
def self.create_indexes
ensure_index :uid, unique: true
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid4.rb 0000644 0000764 0000764 00000001004 12544753400 020455 0 ustar pravi pravi module Doorkeeper
module Orm
module Mongoid4
def self.initialize_models!
require 'doorkeeper/orm/mongoid4/access_grant'
require 'doorkeeper/orm/mongoid4/access_token'
require 'doorkeeper/orm/mongoid4/application'
end
def self.initialize_application_owner!
require 'doorkeeper/models/concerns/ownership'
Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
end
def self.check_requirements!(_config); end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/ 0000755 0000764 0000764 00000000000 12544753400 020134 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/access_grant.rb 0000644 0000764 0000764 00000001105 12544753400 023112 0 ustar pravi pravi require 'doorkeeper/orm/mongoid3/concerns/scopes'
module Doorkeeper
class AccessGrant
include Mongoid::Document
include Mongoid::Timestamps
include AccessGrantMixin
include Models::Mongoid3::Scopes
self.store_in collection: :oauth_access_grants
field :resource_owner_id, type: Moped::BSON::ObjectId
field :application_id, type: Moped::BSON::ObjectId
field :token, type: String
field :expires_in, type: Integer
field :redirect_uri, type: String
field :revoked_at, type: DateTime
index({ token: 1 }, { unique: true })
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/access_token.rb 0000644 0000764 0000764 00000001721 12544753400 023123 0 ustar pravi pravi require 'doorkeeper/orm/mongoid3/concerns/scopes'
module Doorkeeper
class AccessToken
include Mongoid::Document
include Mongoid::Timestamps
include AccessTokenMixin
include Models::Mongoid3::Scopes
self.store_in collection: :oauth_access_tokens
field :resource_owner_id, type: Moped::BSON::ObjectId
field :application_id, type: Moped::BSON::ObjectId
field :token, type: String
field :refresh_token, type: String
field :expires_in, type: Integer
field :revoked_at, type: DateTime
index({ token: 1 }, { unique: true })
index({ refresh_token: 1 }, { unique: true, sparse: true })
def self.delete_all_for(application_id, resource_owner)
where(application_id: application_id,
resource_owner_id: resource_owner.id).delete_all
end
private_class_method :delete_all_for
def self.order_method
:order_by
end
def self.created_at_desc
[:created_at, :desc]
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/application.rb 0000644 0000764 0000764 00000001207 12544753400 022764 0 ustar pravi pravi module Doorkeeper
class Application
include Mongoid::Document
include Mongoid::Timestamps
include Models::Mongoid3::Scopes
include ApplicationMixin
self.store_in collection: :oauth_applications
field :name, type: String
field :uid, type: String
field :secret, type: String
field :redirect_uri, type: String
index({ uid: 1 }, { unique: true })
has_many :authorized_tokens, class_name: 'Doorkeeper::AccessToken'
def self.authorized_for(resource_owner)
ids = AccessToken.where(resource_owner_id: resource_owner.id, revoked_at: nil).map(&:application_id)
find(ids)
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/concerns/ 0000755 0000764 0000764 00000000000 12544753400 021746 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3/concerns/scopes.rb 0000644 0000764 0000764 00000001420 12544753400 023564 0 ustar pravi pravi module Doorkeeper
module Models
module Mongoid3
module Scopes
extend ActiveSupport::Concern
# It's strange that if not define these after included will raise error
# in Mongoid 2 and 3, but 4 works well see:
# https://travis-ci.org/jasl/doorkeeper/builds/31586902
included do
def scopes
OAuth::Scopes.from_string(self[:scopes])
end
def scopes_string
self[:scopes]
end
def includes_scope?(*required_scopes)
required_scopes.blank? || required_scopes.any? { |s| scopes.exists?(s.to_s) }
end
def scopes=(value)
write_attribute :scopes, value if value.present?
end
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid3.rb 0000644 0000764 0000764 00000001004 12544753400 020454 0 ustar pravi pravi module Doorkeeper
module Orm
module Mongoid3
def self.initialize_models!
require 'doorkeeper/orm/mongoid3/access_grant'
require 'doorkeeper/orm/mongoid3/access_token'
require 'doorkeeper/orm/mongoid3/application'
end
def self.initialize_application_owner!
require 'doorkeeper/models/concerns/ownership'
Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
end
def self.check_requirements!(_config); end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2.rb 0000644 0000764 0000764 00000001004 12544753400 020453 0 ustar pravi pravi module Doorkeeper
module Orm
module Mongoid2
def self.initialize_models!
require 'doorkeeper/orm/mongoid2/access_grant'
require 'doorkeeper/orm/mongoid2/access_token'
require 'doorkeeper/orm/mongoid2/application'
end
def self.initialize_application_owner!
require 'doorkeeper/models/concerns/ownership'
Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
end
def self.check_requirements!(_config); end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/ 0000755 0000764 0000764 00000000000 12544753400 020133 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/access_grant.rb 0000644 0000764 0000764 00000001031 12544753400 023107 0 ustar pravi pravi require 'doorkeeper/orm/mongoid2/concerns/scopes'
module Doorkeeper
class AccessGrant
include Mongoid::Document
include Mongoid::Timestamps
include AccessGrantMixin
include Models::Mongoid2::Scopes
self.store_in :oauth_access_grants
field :resource_owner_id, type: Integer
field :application_id, type: BSON::ObjectId
field :token, type: String
field :expires_in, type: Integer
field :redirect_uri, type: String
field :revoked_at, type: DateTime
index :token, unique: true
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/access_token.rb 0000644 0000764 0000764 00000001632 12544753400 023123 0 ustar pravi pravi require 'doorkeeper/orm/mongoid2/concerns/scopes'
module Doorkeeper
class AccessToken
include Mongoid::Document
include Mongoid::Timestamps
include AccessTokenMixin
include Models::Mongoid2::Scopes
self.store_in :oauth_access_tokens
field :resource_owner_id, type: Integer
field :application_id, type: BSON::ObjectId
field :token, type: String
field :refresh_token, type: String
field :expires_in, type: Integer
field :revoked_at, type: DateTime
index :token, unique: true
index :refresh_token, unique: true, sparse: true
def self.delete_all_for(application_id, resource_owner)
where(application_id: application_id,
resource_owner_id: resource_owner.id).delete_all
end
private_class_method :delete_all_for
def self.order_method
:order_by
end
def self.created_at_desc
[:created_at, :desc]
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/application.rb 0000644 0000764 0000764 00000001160 12544753400 022761 0 ustar pravi pravi module Doorkeeper
class Application
include Mongoid::Document
include Mongoid::Timestamps
include Models::Mongoid2::Scopes
include ApplicationMixin
self.store_in :oauth_applications
field :name, type: String
field :uid, type: String
field :secret, type: String
field :redirect_uri, type: String
index :uid, unique: true
has_many :authorized_tokens, class_name: 'Doorkeeper::AccessToken'
def self.authorized_for(resource_owner)
ids = AccessToken.where(resource_owner_id: resource_owner.id, revoked_at: nil).map(&:application_id)
find(ids)
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/concerns/ 0000755 0000764 0000764 00000000000 12544753400 021745 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/mongoid2/concerns/scopes.rb 0000644 0000764 0000764 00000001420 12544753400 023563 0 ustar pravi pravi module Doorkeeper
module Models
module Mongoid2
module Scopes
extend ActiveSupport::Concern
# It's strange that if not define these after included will raise error
# in Mongoid 2 and 3, but 4 works well see:
# https://travis-ci.org/jasl/doorkeeper/builds/31586902
included do
def scopes
OAuth::Scopes.from_string(self[:scopes])
end
def scopes_string
self[:scopes]
end
def includes_scope?(*required_scopes)
required_scopes.blank? || required_scopes.any? { |s| scopes.exists?(s.to_s) }
end
def scopes=(value)
write_attribute :scopes, value if value.present?
end
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/active_record/ 0000755 0000764 0000764 00000000000 12544753400 021226 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/orm/active_record/access_grant.rb 0000644 0000764 0000764 00000000276 12544753400 024214 0 ustar pravi pravi module Doorkeeper
class AccessGrant < ActiveRecord::Base
include AccessGrantMixin
self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}".to_sym
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/active_record/access_token.rb 0000644 0000764 0000764 00000001003 12544753400 024206 0 ustar pravi pravi module Doorkeeper
class AccessToken < ActiveRecord::Base
include AccessTokenMixin
self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}".to_sym
def self.delete_all_for(application_id, resource_owner)
where(application_id: application_id,
resource_owner_id: resource_owner.id).delete_all
end
private_class_method :delete_all_for
def self.order_method
:order
end
def self.created_at_desc
'created_at desc'
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/active_record/application.rb 0000644 0000764 0000764 00000001543 12544753400 024061 0 ustar pravi pravi module Doorkeeper
class Application < ActiveRecord::Base
include ApplicationMixin
self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}".to_sym
if ActiveRecord::VERSION::MAJOR >= 4
has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
else
has_many :authorized_tokens, class_name: 'AccessToken', conditions: { revoked_at: nil }
end
has_many :authorized_applications, through: :authorized_tokens, source: :application
def self.column_names_with_table
self.column_names.map { |c| "#{table_name}.#{c}" }
end
def self.authorized_for(resource_owner)
joins(:authorized_applications).
where(AccessToken.table_name => { resource_owner_id: resource_owner.id, revoked_at: nil }).
group(column_names_with_table.join(','))
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/mongo_mapper.rb 0000644 0000764 0000764 00000001023 12544753400 021421 0 ustar pravi pravi module Doorkeeper
module Orm
module MongoMapper
def self.initialize_models!
require 'doorkeeper/orm/mongo_mapper/access_grant'
require 'doorkeeper/orm/mongo_mapper/access_token'
require 'doorkeeper/orm/mongo_mapper/application'
end
def self.initialize_application_owner!
require 'doorkeeper/models/concerns/ownership'
Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
end
def self.check_requirements!(_config); end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/orm/active_record.rb 0000644 0000764 0000764 00000002436 12544753400 021560 0 ustar pravi pravi module Doorkeeper
module Orm
module ActiveRecord
def self.initialize_models!
require 'doorkeeper/orm/active_record/access_grant'
require 'doorkeeper/orm/active_record/access_token'
require 'doorkeeper/orm/active_record/application'
if Doorkeeper.configuration.active_record_options[:establish_connection]
[Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |c|
c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
end
end
end
def self.initialize_application_owner!
require 'doorkeeper/models/concerns/ownership'
Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
end
def self.check_requirements!(_config)
if ::ActiveRecord::Base.connected? &&
::ActiveRecord::Base.connection.table_exists?(
Doorkeeper::Application.table_name
)
unless Doorkeeper::Application.new.attributes.include?("scopes")
fail <<-MSG.squish
[doorkeeper] Missing column: `oauth_applications.scopes`.
Run `rails generate doorkeeper:application_scopes
&& rake db:migrate` to add it.
MSG
end
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/version.rb 0000644 0000764 0000764 00000000052 12544753400 017627 0 ustar pravi pravi module Doorkeeper
VERSION = '2.2.1'
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/ 0000755 0000764 0000764 00000000000 12544753400 016740 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/oauth/code_request.rb 0000644 0000764 0000764 00000001417 12544753400 021752 0 ustar pravi pravi module Doorkeeper
module OAuth
class CodeRequest
attr_accessor :pre_auth, :resource_owner, :client
def initialize(pre_auth, resource_owner)
@pre_auth = pre_auth
@client = pre_auth.client
@resource_owner = resource_owner
end
def authorize
if pre_auth.authorizable?
auth = Authorization::Code.new(pre_auth, resource_owner)
auth.issue_token
@response = CodeResponse.new pre_auth, auth
else
@response = ErrorResponse.from_request pre_auth
end
end
def deny
pre_auth.error = :access_denied
ErrorResponse.from_request pre_auth,
redirect_uri: pre_auth.redirect_uri
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/error_response.rb 0000644 0000764 0000764 00000003172 12544753400 022337 0 ustar pravi pravi module Doorkeeper
module OAuth
class ErrorResponse
include OAuth::Authorization::URIBuilder
include OAuth::Helpers
def self.from_request(request, attributes = {})
state = request.state if request.respond_to?(:state)
new(attributes.merge(name: request.error, state: state))
end
delegate :name, :description, :state, to: :@error
def initialize(attributes = {})
@error = OAuth::Error.new(*attributes.values_at(:name, :state))
@redirect_uri = attributes[:redirect_uri]
@response_on_fragment = attributes[:response_on_fragment]
end
def body
{
error: name,
error_description: description,
state: state
}.reject { |_, v| v.blank? }
end
def status
:unauthorized
end
def redirectable?
name != :invalid_redirect_uri && name != :invalid_client &&
!URIChecker.native_uri?(@redirect_uri)
end
def redirect_uri
if @response_on_fragment
uri_with_fragment @redirect_uri, body
else
uri_with_query @redirect_uri, body
end
end
def authenticate_info
%(Bearer realm="#{realm}", error="#{name}", error_description="#{description}")
end
def headers
{ 'Cache-Control' => 'no-store',
'Pragma' => 'no-cache',
'Content-Type' => 'application/json; charset=utf-8',
'WWW-Authenticate' => authenticate_info }
end
protected
delegate :realm, to: :configuration
def configuration
Doorkeeper.configuration
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/token.rb 0000644 0000764 0000764 00000003253 12544753400 020410 0 ustar pravi pravi module Doorkeeper
module OAuth
class Token
module Methods
def from_access_token_param(request)
request.parameters[:access_token]
end
def from_bearer_param(request)
request.parameters[:bearer_token]
end
def from_bearer_authorization(request)
pattern = /^Bearer /i
header = request.authorization
token_from_header(header, pattern) if match?(header, pattern)
end
def from_basic_authorization(request)
pattern = /^Basic /i
header = request.authorization
token_from_basic_header(header, pattern) if match?(header, pattern)
end
private
def token_from_basic_header(header, pattern)
encoded_header = token_from_header(header, pattern)
token, _ = decode_basic_credentials(encoded_header)
token
end
def decode_basic_credentials(encoded_header)
Base64.decode64(encoded_header).split(/:/, 2)
end
def token_from_header(header, pattern)
header.gsub pattern, ''
end
def match?(header, pattern)
header && header.match(pattern)
end
end
extend Methods
def self.from_request(request, *methods)
methods.inject(nil) do |credentials, method|
method = self.method(method) if method.is_a?(Symbol)
credentials = method.call(request)
break credentials unless credentials.blank?
end
end
def self.authenticate(request, *methods)
if token = from_request(request, *methods)
AccessToken.by_token(token)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/authorization/ 0000755 0000764 0000764 00000000000 12544753400 021640 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/oauth/authorization/uri_builder.rb 0000644 0000764 0000764 00000001307 12544753400 024473 0 ustar pravi pravi module Doorkeeper
module OAuth
module Authorization
module URIBuilder
include Rack::Utils
extend self
def uri_with_query(url, parameters = {})
uri = URI.parse(url)
original_query = parse_query(uri.query)
uri.query = build_query(original_query.merge(parameters))
uri.to_s
end
def uri_with_fragment(url, parameters = {})
uri = URI.parse(url)
uri.fragment = build_query(parameters)
uri.to_s
end
def build_query(parameters = {})
parameters = parameters.reject { |k, v| v.blank? }
super parameters
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/authorization/token.rb 0000644 0000764 0000764 00000002746 12544753400 023316 0 ustar pravi pravi module Doorkeeper
module OAuth
module Authorization
class Token
attr_accessor :pre_auth, :resource_owner, :token
def initialize(pre_auth, resource_owner)
@pre_auth = pre_auth
@resource_owner = resource_owner
end
def self.access_token_expires_in(server, pre_auth_or_oauth_client)
if expiration = custom_expiration(server, pre_auth_or_oauth_client)
expiration
else
server.access_token_expires_in
end
end
def issue_token
@token ||= AccessToken.find_or_create_for(
pre_auth.client,
resource_owner.id,
pre_auth.scopes,
self.class.access_token_expires_in(configuration, pre_auth),
false
)
end
def native_redirect
{
controller: 'doorkeeper/token_info',
action: :show,
access_token: token.token
}
end
private
def self.custom_expiration(server, pre_auth_or_oauth_client)
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
pre_auth_or_oauth_client.client
else
pre_auth_or_oauth_client
end
server.custom_access_token_expires_in.call(oauth_client)
end
def configuration
Doorkeeper.configuration
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/authorization/code.rb 0000644 0000764 0000764 00000001454 12544753400 023103 0 ustar pravi pravi module Doorkeeper
module OAuth
module Authorization
class Code
attr_accessor :pre_auth, :resource_owner, :token
def initialize(pre_auth, resource_owner)
@pre_auth = pre_auth
@resource_owner = resource_owner
end
def issue_token
@token ||= AccessGrant.create!(
application_id: pre_auth.client.id,
resource_owner_id: resource_owner.id,
expires_in: configuration.authorization_code_expires_in,
redirect_uri: pre_auth.redirect_uri,
scopes: pre_auth.scopes.to_s
)
end
def native_redirect
{ action: :show, code: token.token }
end
def configuration
Doorkeeper.configuration
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client_credentials/ 0000755 0000764 0000764 00000000000 12544753400 022573 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/oauth/client_credentials/issuer.rb 0000644 0000764 0000764 00000001671 12544753400 024437 0 ustar pravi pravi require 'doorkeeper/oauth/client_credentials/validation'
module Doorkeeper
module OAuth
class ClientCredentialsRequest
class Issuer
attr_accessor :token, :validation, :error
def initialize(server, validation)
@server, @validation = server, validation
end
def create(client, scopes, creator = Creator.new)
if validation.valid?
@token = create_token(client, scopes, creator)
@error = :server_error unless @token
else
@token = false
@error = validation.error
end
@token
end
private
def create_token(client, scopes, creator)
ttl = Authorization::Token.access_token_expires_in(@server, client)
creator.call(
client,
scopes,
use_refresh_token: false,
expires_in: ttl
)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client_credentials/creator.rb 0000644 0000764 0000764 00000000465 12544753400 024564 0 ustar pravi pravi module Doorkeeper
module OAuth
class ClientCredentialsRequest
class Creator
def call(client, scopes, attributes = {})
AccessToken.create(attributes.merge(
application_id: client.id,
scopes: scopes.to_s
))
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client_credentials/validation.rb 0000644 0000764 0000764 00000002061 12544753400 025251 0 ustar pravi pravi require 'doorkeeper/validations'
require 'doorkeeper/oauth/scopes'
require 'doorkeeper/oauth/helpers/scope_checker'
module Doorkeeper
module OAuth
class ClientCredentialsRequest
class Validation
include Validations
include OAuth::Helpers
validate :client, error: :invalid_client
validate :scopes, error: :invalid_scope
def initialize(server, request)
@server, @request, @client = server, request, request.client
validate
end
private
def validate_client
@client.present?
end
def validate_scopes
return true unless @request.scopes.present?
application_scopes = if @client.present?
@client.application.scopes
else
''
end
ScopeChecker.valid?(
@request.scopes.to_s,
@server.scopes,
application_scopes
)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/password_access_token_request.rb 0000644 0000764 0000764 00000002446 12544753400 025426 0 ustar pravi pravi module Doorkeeper
module OAuth
class PasswordAccessTokenRequest
include Validations
include OAuth::RequestConcern
include OAuth::Helpers
validate :client, error: :invalid_client
validate :resource_owner, error: :invalid_grant
validate :scopes, error: :invalid_scope
attr_accessor :server, :resource_owner, :credentials, :access_token
attr_accessor :client
def initialize(server, credentials, resource_owner, parameters = {})
@server = server
@resource_owner = resource_owner
@credentials = credentials
@original_scopes = parameters[:scope]
if credentials
@client = Application.by_uid_and_secret credentials.uid,
credentials.secret
end
end
private
def before_successful_response
find_or_create_access_token(client, resource_owner.id, scopes, server)
end
def validate_scopes
return true unless @original_scopes.present?
ScopeChecker.valid? @original_scopes, server.scopes, client.try(:scopes)
end
def validate_resource_owner
!!resource_owner
end
def validate_client
!credentials || !!client
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client_credentials_request.rb 0000644 0000764 0000764 00000001601 12544753400 024666 0 ustar pravi pravi require 'doorkeeper/oauth/client_credentials/creator'
require 'doorkeeper/oauth/client_credentials/issuer'
require 'doorkeeper/oauth/client_credentials/validation'
module Doorkeeper
module OAuth
class ClientCredentialsRequest
include Validations
include OAuth::RequestConcern
attr_accessor :issuer, :server, :client, :original_scopes
attr_reader :response
alias :error_response :response
delegate :error, to: :issuer
def issuer
@issuer ||= Issuer.new(server, Validation.new(server, self))
end
def initialize(server, client, parameters = {})
@client, @server = client, server
@response = nil
@original_scopes = parameters[:scope]
end
def access_token
issuer.token
end
private
def valid?
issuer.create(client, scopes)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/token_request.rb 0000644 0000764 0000764 00000001757 12544753400 022167 0 ustar pravi pravi module Doorkeeper
module OAuth
class TokenRequest
attr_accessor :pre_auth, :resource_owner, :client
def initialize(pre_auth, resource_owner)
@pre_auth = pre_auth
@client = pre_auth.client
@resource_owner = resource_owner
end
def authorize
if pre_auth.authorizable?
auth = Authorization::Token.new(pre_auth, resource_owner)
auth.issue_token
@response = CodeResponse.new pre_auth,
auth,
response_on_fragment: true
else
@response = error_response
end
end
def deny
pre_auth.error = :access_denied
error_response
end
private
def error_response
ErrorResponse.from_request pre_auth,
redirect_uri: pre_auth.redirect_uri,
response_on_fragment: true
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/helpers/ 0000755 0000764 0000764 00000000000 12544753400 020402 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/oauth/helpers/scope_checker.rb 0000644 0000764 0000764 00000002426 12544753400 023530 0 ustar pravi pravi module Doorkeeper
module OAuth
module Helpers
module ScopeChecker
class Validator
attr_reader :parsed_scopes, :scope_str
def initialize(scope_str, server_scopes, application_scopes)
@parsed_scopes = OAuth::Scopes.from_string(scope_str)
@scope_str = scope_str
@valid_scopes = valid_scopes(server_scopes, application_scopes)
end
def valid?
scope_str.present? &&
scope_str !~ /[\n|\r|\t]/ &&
@valid_scopes.has_scopes?(parsed_scopes)
end
def match?
valid? && parsed_scopes.has_scopes?(@valid_scopes)
end
private
def valid_scopes(server_scopes, application_scopes)
if application_scopes.present?
server_scopes & application_scopes
else
server_scopes
end
end
end
def self.valid?(scope_str, server_scopes, application_scopes = nil)
Validator.new(scope_str, server_scopes, application_scopes).valid?
end
def self.match?(scope_str, server_scopes, application_scopes = nil)
Validator.new(scope_str, server_scopes, application_scopes).match?
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/helpers/uri_checker.rb 0000644 0000764 0000764 00000001435 12544753400 023215 0 ustar pravi pravi module Doorkeeper
module OAuth
module Helpers
module URIChecker
def self.valid?(url)
uri = as_uri(url)
uri.fragment.nil? && !uri.host.nil? && !uri.scheme.nil?
rescue URI::InvalidURIError
false
end
def self.matches?(url, client_url)
url, client_url = as_uri(url), as_uri(client_url)
url.query = nil
url == client_url
end
def self.valid_for_authorization?(url, client_url)
valid?(url) && client_url.split.any? { |other_url| matches?(url, other_url) }
end
def self.as_uri(url)
URI.parse(url)
end
def self.native_uri?(url)
url == Doorkeeper.configuration.native_redirect_uri
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/helpers/unique_token.rb 0000644 0000764 0000764 00000000534 12544753400 023437 0 ustar pravi pravi module Doorkeeper
module OAuth
module Helpers
module UniqueToken
def self.generate(options = {})
generator_method = options.delete(:generator) || SecureRandom.method(:hex)
token_size = options.delete(:size) || 32
generator_method.call(token_size)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/refresh_token_request.rb 0000644 0000764 0000764 00000004314 12544753400 023675 0 ustar pravi pravi module Doorkeeper
module OAuth
class RefreshTokenRequest
include Validations
include OAuth::RequestConcern
include OAuth::Helpers
validate :token_presence, error: :invalid_request
validate :token, error: :invalid_grant
validate :client, error: :invalid_client
validate :client_match, error: :invalid_grant
validate :scope, error: :invalid_scope
attr_accessor :access_token, :client, :credentials, :refresh_token,
:server
def initialize(server, refresh_token, credentials, parameters = {})
@server = server
@refresh_token = refresh_token
@credentials = credentials
@original_scopes = parameters[:scope] || parameters[:scopes]
@refresh_token_parameter = parameters[:refresh_token]
if credentials
@client = Application.by_uid_and_secret credentials.uid,
credentials.secret
end
end
private
attr_reader :refresh_token_parameter
def before_successful_response
refresh_token.revoke
create_access_token
end
def default_scopes
refresh_token.scopes
end
def create_access_token
expires_in = Authorization::Token.access_token_expires_in(
server,
client
)
@access_token = AccessToken.create!(
application_id: refresh_token.application_id,
resource_owner_id: refresh_token.resource_owner_id,
scopes: scopes.to_s,
expires_in: expires_in,
use_refresh_token: true)
end
def validate_token_presence
refresh_token.present? || refresh_token_parameter.present?
end
def validate_token
refresh_token.present? && !refresh_token.revoked?
end
def validate_client
!credentials || !!client
end
def validate_client_match
!client || refresh_token.application_id == client.id
end
def validate_scope
if @original_scopes.present?
ScopeChecker.valid?(@original_scopes, refresh_token.scopes)
else
true
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/token_response.rb 0000644 0000764 0000764 00000001355 12544753400 022327 0 ustar pravi pravi module Doorkeeper
module OAuth
class TokenResponse
attr_accessor :token
def initialize(token)
@token = token
end
def body
{
'access_token' => token.token,
'token_type' => token.token_type,
'expires_in' => token.expires_in_seconds,
'refresh_token' => token.refresh_token,
'scope' => token.scopes_string,
'created_at' => token.created_at.to_i,
}.reject { |_, value| value.blank? }
end
def status
:ok
end
def headers
{ 'Cache-Control' => 'no-store',
'Pragma' => 'no-cache',
'Content-Type' => 'application/json; charset=utf-8' }
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/request_concern.rb 0000644 0000764 0000764 00000002154 12544753400 022466 0 ustar pravi pravi module Doorkeeper
module OAuth
module RequestConcern
def authorize
validate
if valid?
before_successful_response
@response = TokenResponse.new(access_token)
after_successful_response
@response
else
@response = ErrorResponse.from_request(self)
end
end
def scopes
@scopes ||= if @original_scopes.present?
OAuth::Scopes.from_string(@original_scopes)
else
default_scopes
end
end
def default_scopes
server.default_scopes
end
def valid?
error.nil?
end
def find_or_create_access_token(client, resource_owner_id, scopes, server)
@access_token = AccessToken.find_or_create_for(
client,
resource_owner_id,
scopes,
Authorization::Token.access_token_expires_in(server, client),
server.refresh_token_enabled?)
end
def before_successful_response
end
def after_successful_response
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/scopes.rb 0000644 0000764 0000764 00000002254 12544753400 020564 0 ustar pravi pravi module Doorkeeper
module OAuth
class Scopes
include Enumerable
include Comparable
def self.from_string(string)
string ||= ''
new.tap do |scope|
scope.add(*string.split)
end
end
def self.from_array(array)
new.tap do |scope|
scope.add(*array)
end
end
delegate :each, :empty?, to: :@scopes
def initialize
@scopes = []
end
def exists?(scope)
@scopes.include? scope.to_s
end
def add(*scopes)
@scopes.push(*scopes.map(&:to_s))
@scopes.uniq!
end
def all
@scopes
end
def to_s
@scopes.join(' ')
end
def has_scopes?(scopes)
scopes.all? { |s| exists?(s) }
end
def +(other)
if other.is_a? Scopes
self.class.from_array(self.all + other.all)
else
super(other)
end
end
def <=>(other)
self.map(&:to_s).sort <=> other.map(&:to_s).sort
end
def &(other)
other_array = other.present? ? other.all : []
self.class.from_array(all & other_array)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/error.rb 0000644 0000764 0000764 00000000305 12544753400 020414 0 ustar pravi pravi module Doorkeeper
module OAuth
class Error < Struct.new(:name, :state)
def description
I18n.translate name, scope: [:doorkeeper, :errors, :messages]
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/code_response.rb 0000644 0000764 0000764 00000002034 12544753400 022114 0 ustar pravi pravi module Doorkeeper
module OAuth
class CodeResponse
include OAuth::Authorization::URIBuilder
include OAuth::Helpers
attr_accessor :pre_auth, :auth, :response_on_fragment
def initialize(pre_auth, auth, options = {})
@pre_auth, @auth = pre_auth, auth
@response_on_fragment = options[:response_on_fragment]
end
def redirectable?
true
end
def redirect_uri
if URIChecker.native_uri? pre_auth.redirect_uri
auth.native_redirect
else
if response_on_fragment
uri_with_fragment(
pre_auth.redirect_uri,
access_token: auth.token.token,
token_type: auth.token.token_type,
expires_in: auth.token.expires_in,
state: pre_auth.state
)
else
uri_with_query pre_auth.redirect_uri,
code: auth.token.token,
state: pre_auth.state
end
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/invalid_token_response.rb 0000644 0000764 0000764 00000001450 12544753400 024031 0 ustar pravi pravi module Doorkeeper
module OAuth
class InvalidTokenResponse < ErrorResponse
def self.from_access_token(access_token, attributes = {})
reason = case
when access_token.try(:revoked?)
:revoked
when access_token.try(:expired?)
:expired
else
:unknown
end
new(attributes.merge(reason: reason))
end
def initialize(attributes = {})
super(attributes.merge(name: :invalid_token, state: :unauthorized))
@reason = attributes[:reason] || :unknown
end
def description
scope = { scope: [:doorkeeper, :errors, :messages, :invalid_token] }
@description ||= I18n.translate @reason, scope
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client/ 0000755 0000764 0000764 00000000000 12544753400 020216 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/oauth/client/methods.rb 0000644 0000764 0000764 00000000663 12544753400 022213 0 ustar pravi pravi module Doorkeeper
module OAuth
class Client
module Methods
def from_params(request)
request.parameters.values_at(:client_id, :client_secret)
end
def from_basic(request)
authorization = request.authorization
if authorization.present? && authorization =~ /^Basic (.*)/m
Base64.decode64($1).split(/:/, 2)
end
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client/credentials.rb 0000644 0000764 0000764 00000001063 12544753400 023040 0 ustar pravi pravi module Doorkeeper
module OAuth
class Client
class Credentials < Struct.new(:uid, :secret)
extend Methods
def self.from_request(request, *credentials_methods)
credentials_methods.inject(nil) do |credentials, method|
method = self.method(method) if method.is_a?(Symbol)
credentials = Credentials.new *method.call(request)
break credentials unless credentials.blank?
end
end
def blank?
uid.blank? || secret.blank?
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/forbidden_token_response.rb 0000644 0000764 0000764 00000001261 12544753400 024337 0 ustar pravi pravi module Doorkeeper
module OAuth
class ForbiddenTokenResponse < ErrorResponse
def self.from_scopes(scopes, attributes = {})
new(attributes.merge(scopes: scopes))
end
def initialize(attributes = {})
super(attributes.merge(name: :invalid_scope, state: :forbidden))
@scopes = attributes[:scopes]
end
def status
:forbidden
end
def headers
headers = super
headers.delete 'WWW-Authenticate'
headers
end
def description
scope = { scope: [:doorkeeper, :scopes] }
@description ||= @scopes.map { |r| I18n.translate r, scope }.join('\n')
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/client.rb 0000644 0000764 0000764 00000001367 12544753400 020552 0 ustar pravi pravi require 'doorkeeper/oauth/client/methods'
require 'doorkeeper/oauth/client/credentials'
module Doorkeeper
module OAuth
class Client
attr_accessor :application
delegate :id, :name, :uid, :redirect_uri, :scopes, to: :@application
def initialize(application)
@application = application
end
def self.find(uid, method = Application.method(:by_uid))
if application = method.call(uid)
new(application)
end
end
def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
return false if credentials.blank?
if application = method.call(credentials.uid, credentials.secret)
new(application)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/pre_authorization.rb 0000644 0000764 0000764 00000003237 12544753400 023040 0 ustar pravi pravi module Doorkeeper
module OAuth
class PreAuthorization
include Validations
validate :response_type, error: :unsupported_response_type
validate :client, error: :invalid_client
validate :scopes, error: :invalid_scope
validate :redirect_uri, error: :invalid_redirect_uri
attr_accessor :server, :client, :response_type, :redirect_uri, :state
attr_writer :scope
def initialize(server, client, attrs = {})
@server = server
@client = client
@response_type = attrs[:response_type]
@redirect_uri = attrs[:redirect_uri]
@scope = attrs[:scope]
@state = attrs[:state]
end
def authorizable?
valid?
end
def scopes
Scopes.from_string scope
end
def scope
@scope.presence || server.default_scopes.to_s
end
def error_response
OAuth::ErrorResponse.from_request(self)
end
private
def validate_response_type
server.authorization_response_types.include? response_type
end
def validate_client
client.present?
end
def validate_scopes
return true unless scope.present?
Helpers::ScopeChecker.valid?(
scope,
server.scopes,
client.application.scopes
)
end
# TODO: test uri should be matched against the client's one
def validate_redirect_uri
return false unless redirect_uri.present?
Helpers::URIChecker.native_uri?(redirect_uri) ||
Helpers::URIChecker.valid_for_authorization?(redirect_uri, client.redirect_uri)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/oauth/authorization_code_request.rb 0000644 0000764 0000764 00000002366 12544753400 024736 0 ustar pravi pravi module Doorkeeper
module OAuth
class AuthorizationCodeRequest
include Validations
include OAuth::RequestConcern
validate :attributes, error: :invalid_request
validate :client, error: :invalid_client
validate :grant, error: :invalid_grant
validate :redirect_uri, error: :invalid_grant
attr_accessor :server, :grant, :client, :redirect_uri, :access_token
def initialize(server, grant, client, parameters = {})
@server = server
@client = client
@grant = grant
@redirect_uri = parameters[:redirect_uri]
end
private
def before_successful_response
grant.revoke
find_or_create_access_token(grant.application,
grant.resource_owner_id,
grant.scopes,
server)
end
def validate_attributes
redirect_uri.present?
end
def validate_client
!!client
end
def validate_grant
return false unless grant && grant.application_id == client.id
grant.accessible?
end
def validate_redirect_uri
grant.redirect_uri == redirect_uri
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/helpers/ 0000755 0000764 0000764 00000000000 12544753400 017262 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/helpers/controller.rb 0000644 0000764 0000764 00000003352 12544753400 021775 0 ustar pravi pravi module Doorkeeper
module Helpers
module Controller
extend ActiveSupport::Concern
private
def authenticate_resource_owner!
current_resource_owner
end
def current_resource_owner
instance_eval(&Doorkeeper.configuration.authenticate_resource_owner)
end
def resource_owner_from_credentials
instance_eval(&Doorkeeper.configuration.resource_owner_from_credentials)
end
def authenticate_admin!
instance_eval(&Doorkeeper.configuration.authenticate_admin)
end
def server
@server ||= Server.new(self)
end
def doorkeeper_token
@token ||= OAuth::Token.authenticate request, *config_methods
end
def config_methods
@methods ||= Doorkeeper.configuration.access_token_methods
end
def get_error_response_from_exception(exception)
error_name = case exception
when Errors::InvalidTokenStrategy
:unsupported_grant_type
when Errors::InvalidAuthorizationStrategy
:unsupported_response_type
when Errors::MissingRequestStrategy
:invalid_request
end
OAuth::ErrorResponse.new name: error_name, state: params[:state]
end
def handle_token_exception(exception)
error = get_error_response_from_exception exception
self.headers.merge! error.headers
self.response_body = error.body.to_json
self.status = error.status
end
def skip_authorization?
!!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/config.rb 0000644 0000764 0000764 00000017414 12544753400 017421 0 ustar pravi pravi module Doorkeeper
class MissingConfiguration < StandardError
def initialize
super('Configuration for doorkeeper missing. Do you have doorkeeper initializer?')
end
end
def self.configure(&block)
@config = Config::Builder.new(&block).build
setup_orm_adapter
setup_orm_models
setup_application_owner if @config.enable_application_owner?
check_requirements
end
def self.configuration
@config || (fail MissingConfiguration.new)
end
def self.check_requirements
@orm_adapter.check_requirements!(configuration)
end
def self.setup_orm_adapter
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
rescue NameError => e
fail e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.squish
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
trying to load it.
You probably need to add the related gem for this adapter to work with
doorkeeper.
ERROR_MSG
end
def self.setup_orm_models
@orm_adapter.initialize_models!
end
def self.setup_application_owner
@orm_adapter.initialize_application_owner!
end
class Config
class Builder
def initialize(&block)
@config = Config.new
instance_eval(&block)
end
def build
@config
end
def enable_application_owner(opts = {})
@config.instance_variable_set('@enable_application_owner', true)
confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
end
def confirm_application_owner
@config.instance_variable_set('@confirm_application_owner', true)
end
def default_scopes(*scopes)
@config.instance_variable_set('@default_scopes', OAuth::Scopes.from_array(scopes))
end
def optional_scopes(*scopes)
@config.instance_variable_set('@optional_scopes', OAuth::Scopes.from_array(scopes))
end
def client_credentials(*methods)
@config.instance_variable_set('@client_credentials', methods)
end
def access_token_methods(*methods)
@config.instance_variable_set('@access_token_methods', methods)
end
def use_refresh_token
@config.instance_variable_set('@refresh_token_enabled', true)
end
def realm(realm)
@config.instance_variable_set('@realm', realm)
end
def reuse_access_token
@config.instance_variable_set("@reuse_access_token", true)
end
def force_ssl_in_redirect_uri(boolean)
@config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
end
def access_token_generator(access_token_generator)
@config.instance_variable_set(
'@access_token_generator', access_token_generator
)
end
end
module Option
# Defines configuration option
#
# When you call option, it defines two methods. One method will take place
# in the +Config+ class and the other method will take place in the
# +Builder+ class.
#
# The +name+ parameter will set both builder method and config attribute.
# If the +:as+ option is defined, the builder method will be the specified
# option while the config attribute will be the +name+ parameter.
#
# If you want to introduce another level of config DSL you can
# define +builder_class+ parameter.
# Builder should take a block as the initializer parameter and respond to function +build+
# that returns the value of the config attribute.
#
# ==== Options
#
# * [:+as+] Set the builder method that goes inside +configure+ block
# * [+:default+] The default value in case no option was set
#
# ==== Examples
#
# option :name
# option :name, as: :set_name
# option :name, default: 'My Name'
# option :scopes builder_class: ScopesBuilder
#
def option(name, options = {})
attribute = options[:as] || name
attribute_builder = options[:builder_class]
Builder.instance_eval do
define_method name do |*args, &block|
# TODO: is builder_class option being used?
value = unless attribute_builder
block ? block : args.first
else
attribute_builder.new(&block).build
end
@config.instance_variable_set(:"@#{attribute}", value)
end
end
define_method attribute do |*args|
if instance_variable_defined?(:"@#{attribute}")
instance_variable_get(:"@#{attribute}")
else
options[:default]
end
end
public attribute
end
def extended(base)
base.send(:private, :option)
end
end
extend Option
option :resource_owner_authenticator,
as: :authenticate_resource_owner,
default: (lambda do |_routes|
logger.warn(I18n.translate('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
nil
end)
option :admin_authenticator,
as: :authenticate_admin,
default: ->(_routes) {}
option :resource_owner_from_credentials,
default: (lambda do |_routes|
warn(I18n.translate('doorkeeper.errors.messages.credential_flow_not_configured'))
nil
end)
option :skip_authorization, default: ->(_routes) {}
option :access_token_expires_in, default: 7200
option :custom_access_token_expires_in, default: lambda { |_app| nil }
option :authorization_code_expires_in, default: 600
option :orm, default: :active_record
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
option :active_record_options, default: {}
option :realm, default: 'Doorkeeper'
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
option :grant_flows, default: %w(authorization_code client_credentials)
option :access_token_generator, default: "Doorkeeper::OAuth::Helpers::UniqueToken"
attr_reader :reuse_access_token
def refresh_token_enabled?
!!@refresh_token_enabled
end
def enable_application_owner?
!!@enable_application_owner
end
def confirm_application_owner?
!!@confirm_application_owner
end
def default_scopes
@default_scopes ||= OAuth::Scopes.new
end
def optional_scopes
@optional_scopes ||= OAuth::Scopes.new
end
def scopes
@scopes ||= default_scopes + optional_scopes
end
def client_credentials_methods
@client_credentials ||= [:from_basic, :from_params]
end
def access_token_methods
@access_token_methods ||= [:from_bearer_authorization, :from_access_token_param, :from_bearer_param]
end
def realm
@realm ||= 'Doorkeeper'
end
def authorization_response_types
@authorization_response_types ||= calculate_authorization_response_types
end
def token_grant_types
@token_grant_types ||= calculate_token_grant_types
end
private
# Determines what values are acceptable for 'response_type' param in
# authorization request endpoint, and return them as an array of strings.
#
def calculate_authorization_response_types
types = []
types << 'code' if grant_flows.include? 'authorization_code'
types << 'token' if grant_flows.include? 'implicit'
types
end
# Determines what values are acceptable for 'grant_type' param token
# request endpoint, and return them in array.
#
def calculate_token_grant_types
types = grant_flows - ['implicit']
types << 'refresh_token' if refresh_token_enabled?
types
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/engine.rb 0000644 0000764 0000764 00000001016 12544753400 017410 0 ustar pravi pravi module Doorkeeper
class Engine < Rails::Engine
initializer "doorkeeper.params.filter" do |app|
app.config.filter_parameters += [:client_secret, :code, :token]
end
initializer "doorkeeper.locales" do |app|
app.config.i18n.fallbacks = [:en]
end
initializer "doorkeeper.routes" do
Doorkeeper::Rails::Routes.install!
end
initializer "doorkeeper.helpers" do
ActiveSupport.on_load(:action_controller) do
include Doorkeeper::Rails::Helpers
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/ 0000755 0000764 0000764 00000000000 12544753400 017103 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/models/access_token_mixin.rb 0000644 0000764 0000764 00000010615 12544753400 023300 0 ustar pravi pravi module Doorkeeper
module AccessTokenMixin
extend ActiveSupport::Concern
include OAuth::Helpers
include Models::Expirable
include Models::Revocable
include Models::Accessible
include Models::Scopes
included do
belongs_to :application,
class_name: 'Doorkeeper::Application',
inverse_of: :access_tokens
validates :token, presence: true, uniqueness: true
validates :refresh_token, uniqueness: true, if: :use_refresh_token?
attr_writer :use_refresh_token
if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
attr_accessible :application_id, :resource_owner_id, :expires_in,
:scopes, :use_refresh_token
end
before_validation :generate_token, on: :create
before_validation :generate_refresh_token,
on: :create,
if: :use_refresh_token?
end
module ClassMethods
def by_token(token)
where(token: token.to_s).limit(1).to_a.first
end
def by_refresh_token(refresh_token)
where(refresh_token: refresh_token.to_s).first
end
def revoke_all_for(application_id, resource_owner)
where(application_id: application_id,
resource_owner_id: resource_owner.id,
revoked_at: nil).
map(&:revoke)
end
def matching_token_for(application, resource_owner_or_id, scopes)
resource_owner_id = if resource_owner_or_id.respond_to?(:to_key)
resource_owner_or_id.id
else
resource_owner_or_id
end
token = last_authorized_token_for(application.try(:id), resource_owner_id)
if token && scopes_match?(token.scopes, scopes, application.try(:scopes))
token
end
end
def scopes_match?(token_scopes, param_scopes, app_scopes)
(!token_scopes.present? && !param_scopes.present?) ||
Doorkeeper::OAuth::Helpers::ScopeChecker.match?(
token_scopes.to_s,
param_scopes,
app_scopes
)
end
def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
if Doorkeeper.configuration.reuse_access_token
access_token = matching_token_for(application, resource_owner_id, scopes)
if access_token && !access_token.expired?
return access_token
end
end
create!(
application_id: application.try(:id),
resource_owner_id: resource_owner_id,
scopes: scopes.to_s,
expires_in: expires_in,
use_refresh_token: use_refresh_token
)
end
def last_authorized_token_for(application_id, resource_owner_id)
where(application_id: application_id,
resource_owner_id: resource_owner_id,
revoked_at: nil).
send(order_method, created_at_desc).
limit(1).
to_a.
first
end
end
def token_type
'bearer'
end
def use_refresh_token?
!!@use_refresh_token
end
def as_json(_options = {})
{
resource_owner_id: resource_owner_id,
scopes: scopes,
expires_in_seconds: expires_in_seconds,
application: { uid: application.try(:uid) },
created_at: created_at.to_i,
}
end
# It indicates whether the tokens have the same credential
def same_credential?(access_token)
application_id == access_token.application_id &&
resource_owner_id == access_token.resource_owner_id
end
def acceptable?(scopes)
accessible? && includes_scope?(*scopes)
end
private
def generate_refresh_token
write_attribute :refresh_token, UniqueToken.generate
end
def generate_token
generator = Doorkeeper.configuration.access_token_generator.constantize
self.token = generator.generate(resource_owner_id: resource_owner_id,
scopes: scopes, application: application,
expires_in: expires_in)
rescue NoMethodError
raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
rescue NameError
raise Errors::TokenGeneratorNotFound, "#{generator} not found"
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/access_grant_mixin.rb 0000644 0000764 0000764 00000001654 12544753400 023276 0 ustar pravi pravi module Doorkeeper
module AccessGrantMixin
extend ActiveSupport::Concern
include OAuth::Helpers
include Models::Expirable
include Models::Revocable
include Models::Accessible
include Models::Scopes
included do
belongs_to :application, class_name: 'Doorkeeper::Application', inverse_of: :access_grants
if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
attr_accessible :resource_owner_id, :application_id, :expires_in, :redirect_uri, :scopes
end
validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
validates :token, uniqueness: true
before_validation :generate_token, on: :create
end
module ClassMethods
def by_token(token)
where(token: token.to_s).limit(1).to_a.first
end
end
private
def generate_token
self.token = UniqueToken.generate
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/application_mixin.rb 0000644 0000764 0000764 00000003024 12544753400 023136 0 ustar pravi pravi module Doorkeeper
module ApplicationMixin
extend ActiveSupport::Concern
include OAuth::Helpers
include Models::Scopes
included do
has_many :access_grants, dependent: :destroy, class_name: 'Doorkeeper::AccessGrant'
has_many :access_tokens, dependent: :destroy, class_name: 'Doorkeeper::AccessToken'
validates :name, :secret, :uid, presence: true
validates :uid, uniqueness: true
validates :redirect_uri, redirect_uri: true
before_validation :generate_uid, :generate_secret, on: :create
if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
attr_accessible :name, :redirect_uri
end
end
module ClassMethods
def by_uid_and_secret(uid, secret)
where(uid: uid.to_s, secret: secret.to_s).limit(1).to_a.first
end
def by_uid(uid)
where(uid: uid.to_s).limit(1).to_a.first
end
end
alias_method :original_scopes, :scopes
def scopes
if has_scopes?
original_scopes
else
fail NameError, "Missing column: `applications.scopes`.", <<-MSG.squish
If you are using ActiveRecord run `rails generate doorkeeper:application_scopes
&& rake db:migrate` to add it.
MSG
end
end
private
def has_scopes?
Doorkeeper.configuration.orm != :active_record ||
Application.new.attributes.include?("scopes")
end
def generate_uid
self.uid ||= UniqueToken.generate
end
def generate_secret
self.secret ||= UniqueToken.generate
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/concerns/ 0000755 0000764 0000764 00000000000 12544753400 020715 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/models/concerns/expirable.rb 0000644 0000764 0000764 00000000723 12544753400 023217 0 ustar pravi pravi module Doorkeeper
module Models
module Expirable
def expired?
expires_in && Time.now > expired_time
end
def expires_in_seconds
return nil if expires_in.nil?
expires = (created_at + expires_in.seconds) - Time.now
expires_sec = expires.seconds.round(0)
expires_sec > 0 ? expires_sec : 0
end
private
def expired_time
created_at + expires_in.seconds
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/concerns/revocable.rb 0000644 0000764 0000764 00000000371 12544753400 023205 0 ustar pravi pravi module Doorkeeper
module Models
module Revocable
def revoke(clock = DateTime)
update_attribute :revoked_at, clock.now
end
def revoked?
!!(revoked_at && revoked_at <= DateTime.now)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/concerns/ownership.rb 0000644 0000764 0000764 00000000527 12544753400 023264 0 ustar pravi pravi module Doorkeeper
module Models
module Ownership
extend ActiveSupport::Concern
included do
belongs_to :owner, polymorphic: true
validates :owner, presence: true, if: :validate_owner?
end
def validate_owner?
Doorkeeper.configuration.confirm_application_owner?
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/concerns/accessible.rb 0000644 0000764 0000764 00000000211 12544753400 023331 0 ustar pravi pravi module Doorkeeper
module Models
module Accessible
def accessible?
!expired? && !revoked?
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/models/concerns/scopes.rb 0000644 0000764 0000764 00000000530 12544753400 022534 0 ustar pravi pravi module Doorkeeper
module Models
module Scopes
def scopes
OAuth::Scopes.from_string(self[:scopes])
end
def scopes_string
self[:scopes]
end
def includes_scope?(*required_scopes)
required_scopes.blank? || required_scopes.any? { |s| scopes.exists?(s.to_s) }
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/server.rb 0000644 0000764 0000764 00000002344 12544753400 017456 0 ustar pravi pravi module Doorkeeper
class Server
attr_accessor :context
def initialize(context = nil)
@context = context
end
def authorization_request(strategy)
klass = Request.authorization_strategy strategy
klass.build self
end
def token_request(strategy)
klass = Request.token_strategy strategy
klass.build self
end
# TODO: context should be the request
def parameters
context.request.parameters
end
def client
@client ||= OAuth::Client.authenticate(credentials)
end
def client_via_uid
@client_via_uid ||= OAuth::Client.find(parameters[:client_id])
end
def current_resource_owner
context.send :current_resource_owner
end
def current_refresh_token
AccessToken.by_refresh_token(parameters[:refresh_token])
end
def grant
AccessGrant.by_token(parameters[:code])
end
# TODO: Use configuration and evaluate proper context on block
def resource_owner
context.send :resource_owner_from_credentials
end
def credentials
methods = Doorkeeper.configuration.client_credentials_methods
@credentials ||= OAuth::Client::Credentials.from_request(context.request, *methods)
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/grape/ 0000755 0000764 0000764 00000000000 12544753400 016716 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/grape/authorization_decorator.rb 0000644 0000764 0000764 00000000572 12544753400 024211 0 ustar pravi pravi module Doorkeeper
module Grape
class AuthorizationDecorator < SimpleDelegator
def parameters
params
end
def authorization
env = __getobj__.env
env['HTTP_AUTHORIZATION'] ||
env['X-HTTP_AUTHORIZATION'] ||
env['X_HTTP_AUTHORIZATION'] ||
env['REDIRECT_X_HTTP_AUTHORIZATION']
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/grape/helpers.rb 0000644 0000764 0000764 00000002367 12544753400 020715 0 ustar pravi pravi require 'doorkeeper/grape/authorization_decorator'
module Doorkeeper
module Grape
module Helpers
extend ::Grape::API::Helpers
include Doorkeeper::Rails::Helpers
# endpoint specific scopes > parameter scopes > default scopes
def doorkeeper_authorize!(*scopes)
endpoint_scopes = env['api.endpoint'].options[:route_options][:scopes]
scopes = if endpoint_scopes
Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
elsif scopes && !scopes.empty?
Doorkeeper::OAuth::Scopes.from_array(scopes)
end
super(*scopes)
end
def doorkeeper_render_error_with(error)
status_code = case error.status
when :unauthorized
401
when :forbidden
403
end
error!({ error: error.description }, status_code)
end
private
def doorkeeper_token
@_doorkeeper_token ||= OAuth::Token.authenticate(
decorated_request,
*Doorkeeper.configuration.access_token_methods
)
end
def decorated_request
AuthorizationDecorator.new(request)
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/generators/ 0000755 0000764 0000764 00000000000 12544753400 017771 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/generators/doorkeeper/ 0000755 0000764 0000764 00000000000 12544753400 022130 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/generators/doorkeeper/mongo_mapper/ 0000755 0000764 0000764 00000000000 12544753400 024613 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/generators/doorkeeper/mongo_mapper/indexes_generator.rb 0000644 0000764 0000764 00000000506 12544753400 030646 0 ustar pravi pravi module Doorkeeper
module MongoMapper
class IndexesGenerator < ::Rails::Generators::Base
source_root File.expand_path('templates', __FILE__)
desc "'Creates an indexes file for use with MongoMapper's rake db:index'"
def install
template 'indexes.rb', 'db/indexes.rb'
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/generators/doorkeeper/mongo_mapper/templates/ 0000755 0000764 0000764 00000000000 12544753400 026611 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/generators/doorkeeper/mongo_mapper/templates/indexes.rb 0000644 0000764 0000764 00000000165 12544753400 030577 0 ustar pravi pravi Doorkeeper::Application.create_indexes
Doorkeeper::AccessGrant.create_indexes
Doorkeeper::AccessToken.create_indexes
doorkeeper-2.2.1/lib/doorkeeper/rails/ 0000755 0000764 0000764 00000000000 12544753400 016732 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/rails/routes/ 0000755 0000764 0000764 00000000000 12544753400 020253 5 ustar pravi pravi doorkeeper-2.2.1/lib/doorkeeper/rails/routes/mapping.rb 0000644 0000764 0000764 00000001554 12544753400 022240 0 ustar pravi pravi module Doorkeeper
module Rails
class Routes
class Mapping
attr_accessor :controllers, :as, :skips
def initialize
@controllers = {
authorizations: 'doorkeeper/authorizations',
applications: 'doorkeeper/applications',
authorized_applications: 'doorkeeper/authorized_applications',
tokens: 'doorkeeper/tokens',
token_info: 'doorkeeper/token_info'
}
@as = {
authorizations: :authorization,
tokens: :token,
token_info: :token_info
}
@skips = []
end
def [](routes)
{
controllers: @controllers[routes],
as: @as[routes]
}
end
def skipped?(controller)
@skips.include?(controller)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/rails/routes/mapper.rb 0000644 0000764 0000764 00000001123 12544753400 022061 0 ustar pravi pravi module Doorkeeper
module Rails
class Routes
class Mapper
def initialize(mapping = Mapping.new)
@mapping = mapping
end
def map(&block)
self.instance_eval(&block) if block
@mapping
end
def controllers(controller_names = {})
@mapping.controllers.merge!(controller_names)
end
def skip_controllers(*controller_names)
@mapping.skips = controller_names
end
def as(alias_names = {})
@mapping.as.merge!(alias_names)
end
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/rails/routes.rb 0000644 0000764 0000764 00000004757 12544753400 020615 0 ustar pravi pravi require 'doorkeeper/rails/routes/mapping'
require 'doorkeeper/rails/routes/mapper'
module Doorkeeper
module Rails
class Routes
module Helper
# TODO: options hash is not being used
def use_doorkeeper(options = {}, &block)
Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
end
end
def self.install!
ActionDispatch::Routing::Mapper.send :include, Doorkeeper::Rails::Routes::Helper
end
attr_accessor :routes
def initialize(routes, &block)
@routes, @block = routes, block
end
def generate_routes!(options)
@mapping = Mapper.new.map(&@block)
routes.scope options[:scope] || 'oauth', as: 'oauth' do
map_route(:authorizations, :authorization_routes)
map_route(:tokens, :token_routes)
map_route(:tokens, :revoke_routes)
map_route(:applications, :application_routes)
map_route(:authorized_applications, :authorized_applications_routes)
map_route(:token_info, :token_info_routes)
end
end
private
def map_route(name, method)
unless @mapping.skipped?(name)
send method, @mapping[name]
end
end
def authorization_routes(mapping)
routes.resource(
:authorization,
path: 'authorize',
only: [:create, :destroy],
as: mapping[:as],
controller: mapping[:controllers]
) do
routes.get '/:code', action: :show, on: :member
routes.get '/', action: :new, on: :member
end
end
def token_routes(mapping)
routes.resource(
:token,
path: 'token',
only: [:create], as: mapping[:as],
controller: mapping[:controllers]
)
end
def revoke_routes(mapping)
routes.post 'revoke', controller: mapping[:controllers], action: :revoke
end
def token_info_routes(mapping)
routes.resource(
:token_info,
path: 'token/info',
only: [:show], as: mapping[:as],
controller: mapping[:controllers]
)
end
def application_routes(mapping)
routes.resources :doorkeeper_applications, controller: mapping[:controllers], as: :applications, path: 'applications'
end
def authorized_applications_routes(mapping)
routes.resources :authorized_applications, only: [:index, :destroy], controller: mapping[:controllers]
end
end
end
end
doorkeeper-2.2.1/lib/doorkeeper/rails/helpers.rb 0000644 0000764 0000764 00000004606 12544753400 020727 0 ustar pravi pravi module Doorkeeper
module Rails
module Helpers
extend ActiveSupport::Concern
def doorkeeper_authorize!(*scopes)
@_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
if !valid_doorkeeper_token?
doorkeeper_render_error
end
end
def doorkeeper_unauthorized_render_options
nil
end
def doorkeeper_forbidden_render_options
nil
end
def valid_doorkeeper_token?
doorkeeper_token && doorkeeper_token.acceptable?(@_doorkeeper_scopes)
end
private
def doorkeeper_render_error
error = doorkeeper_error
headers.merge! error.headers.reject { |k| "Content-Type" == k }
doorkeeper_render_error_with(error)
end
def doorkeeper_render_error_with(error)
options = doorkeeper_render_options || {}
if options.blank?
head error.status
else
options[:status] = error.status
options[:layout] = false if options[:layout].nil?
render options
end
end
def doorkeeper_error
if doorkeeper_invalid_token_response?
OAuth::InvalidTokenResponse.from_access_token(doorkeeper_token)
else
OAuth::ForbiddenTokenResponse.from_scopes(@_doorkeeper_scopes)
end
end
def doorkeeper_render_options
if doorkeeper_invalid_token_response?
doorkeeper_unauthorized_render_options
else
doorkeeper_forbidden_render_options
end
end
def doorkeeper_invalid_token_response?
!doorkeeper_token || !doorkeeper_token.accessible?
end
def doorkeeper_token
@_doorkeeper_token ||= OAuth::Token.authenticate(
request,
*Doorkeeper.configuration.access_token_methods
)
end
module ClassMethods
def doorkeeper_for(*_args)
fail(
Errors::DoorkeeperError,
"`doorkeeper_for` no longer available",
<<-eos
\nStarting in version 2.0.0 of doorkeeper gem, `doorkeeper_for` is no longer
available. Please change `doorkeeper_for` calls in your application with:
before_action :doorkeeper_authorize!
For more information check the README:
https://github.com/doorkeeper-gem/doorkeeper#protecting-resources-with-oauth-aka-your-api-endpoint\n
eos
)
end
end
end
end
end
doorkeeper-2.2.1/gemfiles/ 0000755 0000764 0000764 00000000000 12544753400 014506 5 ustar pravi pravi doorkeeper-2.2.1/gemfiles/Gemfile.mongoid2.rb 0000644 0000764 0000764 00000000165 12544753400 020122 0 ustar pravi pravi gemfile = 'gemfiles/Gemfile.common.rb'
instance_eval IO.read(gemfile), gemfile
gem 'mongoid', '~> 2'
gem 'bson_ext'
doorkeeper-2.2.1/gemfiles/Gemfile.mongo_mapper.rb 0000644 0000764 0000764 00000000162 12544753400 021064 0 ustar pravi pravi gemfile = 'gemfiles/Gemfile.common.rb'
instance_eval IO.read(gemfile), gemfile
gem 'mongo_mapper'
gem 'bson_ext'
doorkeeper-2.2.1/gemfiles/Gemfile.mongoid3.rb 0000644 0000764 0000764 00000000146 12544753400 020122 0 ustar pravi pravi gemfile = 'gemfiles/Gemfile.common.rb'
instance_eval IO.read(gemfile), gemfile
gem 'mongoid', '~> 3'
doorkeeper-2.2.1/gemfiles/Gemfile.common.rb 0000644 0000764 0000764 00000000160 12544753400 017667 0 ustar pravi pravi ENV['rails'] ||= '4.2.0'
source 'https://rubygems.org'
gem 'rails', "~> #{ENV['rails']}"
gemspec path: '../'
doorkeeper-2.2.1/gemfiles/Gemfile.mongoid4.rb 0000644 0000764 0000764 00000000146 12544753400 020123 0 ustar pravi pravi gemfile = 'gemfiles/Gemfile.common.rb'
instance_eval IO.read(gemfile), gemfile
gem 'mongoid', '~> 4'
doorkeeper-2.2.1/Rakefile 0000644 0000764 0000764 00000000634 12544753400 014363 0 ustar pravi pravi require 'bundler/setup'
require 'rspec/core/rake_task'
desc 'Default: run specs.'
task :default => :spec
desc "Run all specs"
RSpec::Core::RakeTask.new(:spec) do |config|
config.verbose = false
end
namespace :doorkeeper do
desc "Install doorkeeper in dummy app"
task :install do
cd 'spec/dummy'
system 'bundle exec rails g doorkeeper:install --force'
end
end
Bundler::GemHelper.install_tasks
doorkeeper-2.2.1/MIT-LICENSE 0000644 0000764 0000764 00000002057 12544753400 014353 0 ustar pravi pravi Copyright 2011 Applicake. http://applicake.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
doorkeeper-2.2.1/NEWS.md 0000644 0000764 0000764 00000042552 12544753400 014021 0 ustar pravi pravi # News
User-visible changes worth mentioning.
---
## 2.2.1
- [#636] `custom_access_token_expires_in` bugfixes
- [#641] syntax error fix (Issue #612)
- [#633] Send extra details to Custom Token Generator
- [#628] Refactor: improve orm adapters to ease extension
- [#637] Upgrade to rspec to 3.2
## 2.2.0 - 2015-04-19
- [#611] Allow custom access token generators to be used
- [#632] Properly fallback to `default_scopes` when no scope is specified
- [#622] Clarify that there is a logical OR between scopes for authorizing
- [#635] Upgrade to rspec 3
- [#627] i18n fallbacks to english
- Moved CHANGELOG to NEWS.md
## 2.1.4 - 2015-03-27
- [#595] HTTP spec: Add `scope` for refresh token scope param
- [#596] Limit scopes in app scopes for client credentials
- [#567] Add Grape helpers for easier integration with Grape framework
- [#606] Add custom access token expiration support for Client Credentials flow
## 2.1.3 - 2015-03-01
- [#588] Fixes scopes_match? bug that skipped authorization form in some cases
## 2.1.2 - 2015-02-25
- [#574] Remove unused update authorization route.
- [#576] Filter out sensitive parameters from logs.
- [#582] The Authorization HTTP header fields are now case insensitive.
- [#583] Database connection bugfix in certain scenarios.
- Testing improvements
## 2.1.1 - 2015-02-06
- Remove `wildcard_redirect_url` option
- [#481] Customize token flow OAuth expirations with a config lambda
- [#568] TokensController: Memoize strategy.authorize_response result to enable
subclasses to use the response object.
- [#571] Fix database initialization issues in some configurations.
- Documentation improvements
## 2.1.0 - 2015-01-13
- [#540] Include `created_at` in response.
- [#538] Check application-level scopes in client_credentials and password flow.
- [5596227] Check application scopes in AccessToken when present. Fixes a bug in
doorkeeper 2.0.0 and 2.0.1 referring to application specific scopes.
- [#534] Internationalizes doorkeeper views.
- [#545] Ensure there is a connection to the database before checking for
missing columns
- [#546] Use `Doorkeeper::` prefix when referencing `Application` to avoid
possible application model name conflict.
- [#538] Test with Rails ~> 4.2.
### Potentially backward incompatible changes
- Enable by default `authorization_code` and `client_credentials` grant flows.
Disables implicit and password grant flows by default.
- [#510, #544, 722113f] Revoked refresh token response bugfix.
## 2.0.1 - 2014-12-17
- [#525, #526, #527] Fix `ActiveRecord::NoDatabaseError` on gem load.
## 2.0.0 - 2014-12-16
### Backward incompatible changes
- [#448] Removes `doorkeeper_for` helper. Now we use
`before_action :doorkeeper_authorize!`.
- [#469] Allow client applications to restrict the set of allowable scopes.
Fixes #317. `oauth_applications` relation needs a new `scopes` string column,
non nullable, which defaults to an empty string. To add the column run:
```
rails generate doorkeeper:application_scopes
```
If you’d rather do it by hand, your ActiveRecord migration should contain:
```ruby
add_column :oauth_applications, :scopes, :string, null: false, default: ‘’
```
### Removed deprecations
- Removes `test_redirect_uri` option. It is now called `native_redirect_uri`.
- [#446] Removes `mount Doorkeeper::Engine`. Now we use `use_doorkeeper`.
### Others
- [#484] Performance improvement - avoid performing order_by when not required.
- [#450] When password is invalid in Password Credentials Grant, Doorkeeper
returned 'invalid_resource_owner' instead of 'invalid_grant', as the spec
declares. Fixes #444.
- [#452] Allows `revoked_at` to be set in the future, for future expiry.
Rationale: https://github.com/doorkeeper-gem/doorkeeper/pull/452#issuecomment-51431459
- [#480] For Implicit grant flow, access tokens can now be reused. Fixes #421.
- [#491] Reworks of @jasl's #454 and #478. ORM refactor that allows doorkeeper
to be extended more easily with unsupported ORMs. It also marks the boundaries
between shared model code and ORM specifics inside of the gem.
- [#496] Tests with Rails 4.2.
- [#489] Adds `force_ssl_in_redirect_uri` to force the usage of the HTTPS
protocol in non-native redirect uris.
- [#516] SECURITY: Adds `protect_from_forgery` to `Doorkeeper::ApplicationController`
- [#518] Fix random failures in mongodb.
---
## 1.4.2 - 2015-03-02
- [#576] Filter out sensitive parameters from logs
## 1.4.1 - 2014-12-17
- [#516] SECURITY: Adds `protect_from_forgery` to `Doorkeeper::ApplicationController`
## 1.4.0 - 2014-07-31
- internals
- [#427] Adds specs expectations.
- [#428] Error response refactor.
- [#417] Moves token validation into Access Token class.
- [#439] Removes redundant module includes.
- [#443] TokensController and TokenInfoController inherit from ActionController::Metal
- bug
- [#418] fixes #243, requests with insufficient scope now respond 403 instead
of 401. (API change)
- [#438] fixes #398, native redirect for implicit token grant bug.
- [#440] namespace fixes
- enhancements
- [#432] Keeps query parameters
## 1.3.1 - 2014-07-06
- enhancements
- [#405] Adds facade to more easily get the token from a request in a route
constraint.
- [#415] Extend Doorkeeper TokenResponse with an `after_successful_response`
callback that allows handling of `response` object.
- internals
- [#409] Deprecates `test_redirect_uri` in favor of `native_redirect_uri`.
See discussion in: [#351].
- [#411] Clean rspec deprecations. General test improvements.
- [#412] rspec line width can go longer than 80 (hound CI config).
- bug
- [#413] fixes #340, routing scope is now taken into account in redirect.
- [#401] and [#425] application is not required any longer for access_token.
## 1.3.0 - 2014-05-23
- enhancements
- [#387] Adds reuse_access_token configuration option.
## 1.2.0 - 2014-05-02
- enhancements
- [#376] Allow users to enable basic header authorization for access tokens.
- [#374] Token revocation implementation [RFC 7009]
- [#295] Only enable specific grant flows.
- internals
- [#381] Locale source fix.
- [#380] Renames `errors_for` to `doorkeeper_errors_for`.
- [#390] Style adjustments in accordance with Ruby Style Guide form
Thoughtbot.
## 1.1.0 - 2014-03-29
- enhancements
- [#336] mongoid4 support.
- [#372] Allow users to set ActiveRecord table_name_prefix/suffix options
- internals
- [#343] separate OAuth's admin and user end-point to different layouts, upgrade theme to Bootstrap 3.1.
- [#348] Move render_options in filter after `@error` has been set
## 1.0.0 - 2014-01-13
- bug (spec)
- [#228] token response `expires_in` value is now in seconds, relative to
request time
- [#296] client is optional for password grant type.
- [#319] If client credentials are present on password grant type they are validated
- [#326] If client credentials are present in refresh token they are validated
- [#326] If authenticated client does not match original client that
obtained a refresh token it responds `invalid_grant` instead of
`invalid_client`. Previous usage was invalid according to Section 5.2 of
the spec.
- [#329] access tokens' `scopes` string wa being compared against
`default_scopes` symbols, always unauthorizing.
- [#318] Include "WWW-Authenticate" header with Unauthorized responses
- enhancements
- [#293] Adds ActionController::Instrumentation in TokensController
- [#298] Support for multiple redirect_uris added.
- [#313] `AccessToken.revoke_all_for` actually revokes all non-revoked
tokens for an application/owner instead of deleting them.
- [#333] Rails 4.1 support
- internals
- Removes jQuery dependency [fixes #300] [PR #312 is related]
- [#294] Client uid and secret will be generated only if not present.
- [#316] Test warnings addressed.
- [#338] Rspec 3 syntax.
---
## 0.7.4 - 2013-12-01
- bug
- Symbols instead of strings for user input.
## 0.7.3 - 2013-10-04
- enhancements
- [#204] Allow to overwrite scope in routes
- internals
- Returns only present keys in Token Response (may imply a backwards
incompatible change). https://github.com/doorkeeper-gem/doorkeeper/issues/220
- bug
- [#290] Support for Rails 4 when 'protected_attributes' gem is present.
## 0.7.2 - 2013-09-11
- enhancements
- [#272] Allow issuing multiple access_tokens for one user/application for multiple devices
- [#170] Increase length of allowed redirect URIs
- [#239] Do not try to load unavailable Request class for the current phase.
- [#273] Relax jquery-rails gem dependency
## 0.7.1 - 2013-08-30
- bug
- [#269] Rails 3.2 raised `ActiveModel::MassAssignmentSecurity::Error`.
## 0.7.0 - 2013-08-21
- enhancements
- [#229] Rails 4!
- internals
- [#203] Changing table name to be specific in column_names_with_table
- [#215] README update
- [#227] Use Rails.config.paths["config/routes"] instead of assuming "config/routes.rb" exists
- [#262] Add jquery as gem dependency
- [#263] Add a configuration for ActiveRecord.establish_connection
- Deprecation and Ruby warnings (PRs merged outside of GitHub).
## 0.6.7 - 2013-01-13
- internals
- [#188] Add IDs to the show views for integration testing [@egtann](https://github.com/egtann)
## 0.6.6 - 2013-01-04
- enhancements
- [#187] Raise error if configuration is not set
## 0.6.5 - 2012-12-26
- enhancements
- [#184] Vendor the Bootstrap CSS [@tylerhunt](https://github.com/tylerhunt)
## 0.6.4 - 2012-12-15
- bug
- [#180] Add localization to authorized_applications destroy notice [@aalvarado](https://github.com/aalvarado)
## 0.6.3 - 2012-12-07
- bugfixes
- [#163] Error response content-type header should be application/json [@ggayan](https://github.com/ggayan)
- [#175] Make token.expires_in_seconds return nil when expires_in is nil [@miyagawa](https://github.com/miyagawa)
- enhancements
- [#166, #172, #174] Behavior to automatically authorize based on a configured proc
- internals
- [#168] Using expectation syntax for controller specs [@rdsoze](https://github.com/rdsoze)
## 0.6.2 - 2012-11-10
- bugfixes
- [#162] Remove ownership columns from base migration template [@rdsoze](https://github.com/rdsoze)
## 0.6.1 - 2012-11-07
- bugfixes
- [#160] Removed |routes| argument from initializer authenticator blocks
- documentation
- [#160] Fixed description of context of authenticator blocks
## 0.6.0 - 2012-11-05
- enhancements
- Mongoid `orm` configuration accepts only :mongoid2 or :mongoid3
- Authorization endpoint does not redirect in #new action anymore. It wasn't specified by OAuth spec
- TokensController now inherits from ActionController::Metal. There might be performance upgrades
- Add link to authorization in Applications scaffold
- [#116] MongoMapper support [@carols10cents](https://github.com/carols10cents)
- [#122] Mongoid3 support [@petergoldstein](https://github.com/petergoldstein)
- [#150] Introduce test redirect uri for applications
- bugfixes
- [#157] Response token status should be `:ok`, not `:success` [@theycallmeswift](https://github.com/theycallmeswift)
- [#159] Remove ActionView::Base.field_error_proc override (fixes #145)
- internals
- Update development dependencies
- Several refactorings
- Rails/ORM are easily swichable with env vars (rails and orm)
- Travis now tests against Mongoid v2
## 0.5.0 - 2012-10-20
Official support for rubinius was removed.
- enhancements
- Configure the way access token is retrieved from request (default to bearer header)
- Authorization Code expiration time is now configurable
- Add support for mongoid
- [#78, #128, #137, #138] Application Ownership
- [#92] Allow users to skip controllers
- [#99] Remove deprecated warnings for data-* attributes [@towerhe](https://github.com/towerhe)
- [#101] Return existing access_token for PasswordAccessTokenRequest [@benoist](https://github.com/benoist)
- [#104] Changed access token scopes example code to default_scopes and optional_scopes [@amkirwan](https://github.com/amkirwan)
- [#107] Fix typos in initializer
- [#123] i18n for validator, flash messages [@petergoldstein](https://github.com/petergoldstein)
- [#140] ActiveRecord is the default value for the ORM [@petergoldstein](https://github.com/petergoldstein)
- internals
- [#112, #120] Replacing update_attribute with update_column to eliminate deprecation warnings [@rmoriz](https://github.com/rmoriz), [@petergoldstein](https://github.com/petergoldstein)
- [#121] Updating all development dependencies to recent versions. [@petergoldstein](https://github.com/petergoldstein)
- [#144] Adding MongoDB dependency to .travis.yml [@petergoldstein](https://github.com/petergoldstein)
- [#143] Displays errors for unconfigured error messages [@timgaleckas](https://github.com/timgaleckas)
- bugfixes
- [#102] Not returning 401 when access token generation fails [@cslew](https://github.com/cslew)
- [#125] Doorkeeper is using ActiveRecord version of as_json in ORM agnostic code [@petergoldstein](https://github.com/petergoldstein)
- [#142] Prevent double submission of password based authentication [@bdurand](https://github.com/bdurand)
- documentation
- [#141] Add rack-cors middleware to readme [@gottfrois](https://github.com/gottfrois)
## 0.4.2 - 2012-06-05
- bugfixes:
- [#94] Uninitialized Constant in Password Flow
## 0.4.1 - 2012-06-02
- enhancements:
- Backport: Move doorkeeper_for extension to Filter helper
## 0.4.0 - 2012-05-26
- deprecation
- Deprecate authorization_scopes
- database changes
- AccessToken#resource_owner_id is not nullable
- enhancements
- [#83] Add Resource Owner Password Credentials flow [@jaimeiniesta](https://github.com/jaimeiniesta)
- [#76] Allow token expiration to be disabled [@mattgreen](https://github.com/mattgreen)
- [#89] Configure the way client credentials are retrieved from request
- [#b6470a] Add Client Credentials flow
- internals
- [#2ece8d, #f93778] Introduce Client and ErrorResponse classes
## 0.3.4 - 2012-05-24
- Fix attr_accessible for rails 3.2.x
## 0.3.3 - 2012-05-07
- [#86] shrink gem package size
## 0.3.2 - 2012-04-29
- enhancements
- [#54] Ignore Authorization: headers that are not Bearer [@miyagawa](https://github.com/miyagawa)
- [#58, #64] Add destroy action to applications endpoint [@jaimeiniesta](https://github.com/jaimeiniesta), [@davidfrey](https://github.com/davidfrey)
- [#63] TokensController responds with `401 unauthorized` [@jaimeiniesta](https://github.com/jaimeiniesta)
- [#67, #72] Fix for mass-assignment [@cicloid](https://github.com/cicloid)
- internals
- [#49] Add Gemnasium status image to README [@laserlemon](https://github.com/laserlemon)
- [#50] Fix typos [@tomekw](https://github.com/tomekw)
- [#51] Updated the factory_girl_rails dependency, fix expires_in response which returned a float number instead of integer [@antekpiechnik](https://github.com/antekpiechnik)
- [#62] Typos, .gitignore [@jaimeiniesta](https://github.com/jaimeiniesta)
- [#65] Change _path redirections to _url redirections [@jaimeiniesta](https://github.com/jaimeiniesta)
- [#75] Fix unknown method #authenticate_admin! [@mattgreen](https://github.com/mattgreen)
- Remove application link in authorized app view
## 0.3.1 - 2012-02-17
- enhancements
- [#48] Add if, else options to doorkeeper_for
- Add views generator
- internals
- Namespace models
## 0.3.0 - 2012-02-11
- enhancements
- [#17, #31] Add support for client credentials in basic auth header [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
- [#28] Add indices to migration [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
- [#29] Allow doorkeeper to run with rails 3.2 [@john-griffin](https://github.com/john-griffin)
- [#30] Improve client's redirect uri validation [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
- [#32] Add token (implicit grant) flow [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
- [#34] Add support for custom unathorized responses [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
- [#36] Remove repetitions from the Authorised Applications view [@carvil](https://github.com/carvil)
- When user revoke an application, all tokens for that application are revoked
- Error messages now can be translated
- Install generator copies the error messages localization file
- internals
- Fix deprecation warnings in ActiveSupport::Base64
- Remove deprecation in doorkeeper_for that handles hash arguments
- Depends on railties instead of whole rails framework
- CI now integrates with rails 3.1 and 3.2
## 0.2.0 - 2011-12-17
- enhancements
- [#4] Add authorized applications endpoint
- [#5, #11] Add access token scopes
- [#10] Add access token expiration by default
- [#9, #12] Add refresh token flow
- internals
- [#7] Improve configuration options with :default
- Improve configuration options with :builder
- Refactor config class
- Improve coverage of authorization request integration
- bug fixes
- [#6, #20] Fix access token response headers
- Fix issue with state parameter
- deprecation
- deprecate :only and :except options in doorkeeper_for
## 0.1.1 - 2011-11-30
- enhancements
- [#3] Authorization code must be short lived and single use
- [#2] Improve views provided by doorkeeper
- [#1] Skips authorization form if the client has been authorized by the resource owner
- Improve readme
- bugfixes
- Fix issue when creating the access token (wrong client id)
## 0.1.0 - 2011-11-25
- Authorization Code flow
- OAuth applications endpoint
doorkeeper-2.2.1/.gitignore 0000644 0000764 0000764 00000000244 12544753400 014703 0 ustar pravi pravi .bundle/
.rbx
*.rbc
log/*.log
pkg/
spec/dummy/db/*.sqlite3
spec/dummy/log/*.log
spec/dummy/tmp/
Gemfile.lock
gemfiles/*.lock
spec/generators/tmp
.rvmrc
*.swp
.idea