diff --git a/lib/travis/api/app/access_token.rb b/lib/travis/api/app/access_token.rb index a8e324b9..b3e62e5f 100644 --- a/lib/travis/api/app/access_token.rb +++ b/lib/travis/api/app/access_token.rb @@ -4,7 +4,7 @@ require 'securerandom' class Travis::Api::App class AccessToken DEFAULT_SCOPES = [:public, :private] - attr_reader :token, :scopes, :user_id, :app_id + attr_reader :token, :scopes, :user_id, :app_id, :expires_in def self.create(options = {}) new(options).tap(&:save) @@ -25,6 +25,12 @@ class Travis::Api::App raise ArgumentError, 'must supply either user_id or user' unless options.key?(:user) ^ options.key?(:user_id) raise ArgumentError, 'must supply app_id' unless options.key?(:app_id) + begin + @expires_in = Integer(options[:expires_in]) if options[:expires_in] + rescue ArgumentError + raise ArgumentError, 'expires_in must be of integer type' + end + @app_id = Integer(options[:app_id]) @scopes = Array(options[:scopes] || options[:scope] || DEFAULT_SCOPES).map(&:to_sym) @user = options[:user] @@ -37,6 +43,11 @@ class Travis::Api::App redis.del(key) redis.rpush(key, [user_id, app_id, *scopes].map(&:to_s)) redis.set(reuse_key, token) + + if expires_in + redis.expire(reuse_key, expires_in) + redis.expire(key, expires_in) + end end def user @@ -68,7 +79,7 @@ class Travis::Api::App private def reuse_token - redis.get(reuse_key) + redis.get(reuse_key) unless expires_in end def reuse_key diff --git a/spec/unit/access_token_spec.rb b/spec/unit/access_token_spec.rb new file mode 100644 index 00000000..846b0d9d --- /dev/null +++ b/spec/unit/access_token_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Travis::Api::App::AccessToken do + it 'errors out on wrong type of :expires_in argument' do + expect { + described_class.new(app_id: 1, user_id: 2, expires_in: 'foo') + }.to raise_error(ArgumentError, 'expires_in must be of integer type') + end + + it 'allows to skip expires_in' do + expect { + described_class.new(app_id: 1, user_id: 2, expires_in: nil) + }.to_not raise_error(ArgumentError) + end + + it 'does not reuse token if expires_in is set' do + token = described_class.new(app_id: 1, user_id: 2).tap(&:save) + new_token = described_class.new(app_id: 1, user_id: 2, expires_in: 10) + + token.token.should_not == new_token.token + end + + it 'expires the token after given period of time' do + token = described_class.new(app_id: 1, user_id: 2, expires_in: 1).tap(&:save) + + described_class.find_by_token(token.token).should_not be_nil + + sleep 1.5 + + described_class.find_by_token(token.token).should be_nil + end +end