summaryrefslogtreecommitdiffstats
path: root/app/models/token.rb
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2017-01-12 20:34:08 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2017-01-12 20:34:08 +0000
commit5d4b5fd1f68ab7aef4ef43d82d3cb378079aed31 (patch)
tree10d251b22cac78cd65f25df5450d2b78e3a91260 /app/models/token.rb
parent309c6cec861baad8d363a9e23864707cdeaa317f (diff)
downloadredmine-5d4b5fd1f68ab7aef4ef43d82d3cb378079aed31.tar.gz
redmine-5d4b5fd1f68ab7aef4ef43d82d3cb378079aed31.zip
Allow "stay logged in" from multiple browsers (#10840).
Patch by Gregor Schmidt. git-svn-id: http://svn.redmine.org/redmine/trunk@16174 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/models/token.rb')
-rw-r--r--app/models/token.rb60
1 files changed, 56 insertions, 4 deletions
diff --git a/app/models/token.rb b/app/models/token.rb
index a5ca18aa4..796622053 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -25,18 +25,70 @@ class Token < ActiveRecord::Base
cattr_accessor :validity_time
self.validity_time = 1.day
+ class << self
+ attr_reader :actions
+
+ def add_action(name, options)
+ options.assert_valid_keys(:max_instances, :validity_time)
+ @actions ||= {}
+ @actions[name.to_s] = options
+ end
+ end
+
+ add_action :api, max_instances: 1, validity_time: nil
+ add_action :autologin, max_instances: 10, validity_time: Proc.new { Setting.autologin.to_i.days }
+ add_action :feeds, max_instances: 1, validity_time: nil
+ add_action :recovery, max_instances: 1, validity_time: Proc.new { Token.validity_time }
+ add_action :register, max_instances: 1, validity_time: Proc.new { Token.validity_time }
+ add_action :session, max_instances: 10, validity_time: nil
+
def generate_new_token
self.value = Token.generate_token_value
end
# Return true if token has expired
def expired?
- return Time.now > self.created_on + self.class.validity_time
+ return created_on < self.class.invalid_when_created_before(action)
+ end
+
+ def max_instances
+ Token.actions.has_key?(action) ? Token.actions[action][:max_instances] : 1
+ end
+
+ def self.invalid_when_created_before(action = nil)
+ if Token.actions.has_key?(action)
+ validity_time = Token.actions[action][:validity_time]
+ validity_time = validity_time.call(action) if validity_time.respond_to? :call
+ else
+ validity_time = self.validity_time
+ end
+
+ if validity_time.nil?
+ 0
+ else
+ Time.now - validity_time
+ end
end
# Delete all expired tokens
def self.destroy_expired
- Token.where("action NOT IN (?) AND created_on < ?", ['feeds', 'api', 'session'], Time.now - validity_time).delete_all
+ t = Token.arel_table
+
+ # Unknown actions have default validity_time
+ condition = t[:action].not_in(self.actions.keys).and(t[:created_on].lt(invalid_when_created_before))
+
+ self.actions.each do |action, options|
+ validity_time = invalid_when_created_before(action)
+
+ # Do not delete tokens, which don't become invalid
+ next if validity_time.nil?
+
+ condition = condition.or(
+ t[:action].eq(action).and(t[:created_on].lt(validity_time))
+ )
+ end
+
+ Token.where(condition).delete_all
end
# Returns the active user who owns the key for the given action
@@ -80,8 +132,8 @@ class Token < ActiveRecord::Base
def delete_previous_tokens
if user
scope = Token.where(:user_id => user.id, :action => action)
- if action == 'session'
- ids = scope.order(:updated_on => :desc).offset(9).ids
+ if max_instances > 1
+ ids = scope.order(:updated_on => :desc).offset(max_instances - 1).ids
if ids.any?
Token.delete(ids)
end