summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2015-03-11 01:12:23 -0700
committerelijah <elijah@riseup.net>2015-03-17 22:36:27 -0700
commit9266c3ac58404894539e25e514d8d8a6775c701f (patch)
tree3beaa846b37aecdf933763564710c2e1042c03a3 /app/models
parenta777c4c677e8cbd4f91c66a29ee1ecb347c5b8ab (diff)
add support for rotating tokens and sessions databases, and for a special tmp db for test users.
Diffstat (limited to 'app/models')
-rw-r--r--app/models/account.rb23
-rw-r--r--app/models/temporary_user.rb78
-rw-r--r--app/models/token.rb13
-rw-r--r--app/models/user.rb2
4 files changed, 100 insertions, 16 deletions
diff --git a/app/models/account.rb b/app/models/account.rb
index e60a356..af470ed 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -20,7 +20,7 @@ class Account
user = nil
user = User.new(attrs)
user.save
- if user.persisted?
+ if !user.tmp? && user.persisted?
identity = user.identity
identity.user_id = user.id
identity.save
@@ -52,10 +52,12 @@ class Account
def destroy(destroy_identity=false)
return unless @user
- if destroy_identity == false
- Identity.disable_all_for(@user)
- else
- Identity.destroy_all_for(@user)
+ if !user.tmp?
+ if destroy_identity == false
+ Identity.disable_all_for(@user)
+ else
+ Identity.destroy_all_for(@user)
+ end
end
@user.destroy
end
@@ -84,12 +86,11 @@ class Account
end
def self.creation_problem?(user, identity)
- user.nil? ||
- !user.persisted? ||
- identity.nil? ||
- !identity.persisted? ||
- user.errors.any? ||
- identity.errors.any?
+ return true if user.nil? || !user.persisted? || user.errors.any?
+ if !user.tmp?
+ return true if identity.nil? || !identity.persisted? || identity.errors.any?
+ end
+ return false
end
# You can hook into the account lifecycle from different engines using
diff --git a/app/models/temporary_user.rb b/app/models/temporary_user.rb
new file mode 100644
index 0000000..87800ed
--- /dev/null
+++ b/app/models/temporary_user.rb
@@ -0,0 +1,78 @@
+#
+# For users with login '*test_user*', we don't want to store these documents in
+# the main users db. This is because we create and destroy a lot of test
+# users. This weirdness of using a different db for some users breaks a lot of
+# things, such as associations. However, this is OK for now since we don't need
+# those for running the frequent nagios tests.
+#
+# This module is included in user.rb. This will only work if it is included
+# after designs are defined, otherwise, the design definition will overwrite
+# find_by_login().
+#
+
+module TemporaryUser
+ extend ActiveSupport::Concern
+ include CouchRest::Model::DatabaseMethod
+
+ USER_DB = 'users'
+ TMP_USER_DB = 'tmp_users'
+ TMP_LOGIN = 'test_user'
+
+ included do
+ use_database_method :db_name
+
+ # since the original find_by_login is dynamically created with
+ # instance_eval, it appears that we also need to use instance eval to
+ # override it.
+ instance_eval <<-EOS, __FILE__, __LINE__ + 1
+ def find_by_login(*args)
+ if args.grep(/#{TMP_LOGIN}/).any?
+ by_login.database(tmp_database).key(*args).first()
+ else
+ by_login.key(*args).first()
+ end
+ end
+ EOS
+ end
+
+ module ClassMethods
+ def get(id, db = database)
+ super(id, db) || super(id, tmp_database)
+ end
+ alias :find :get
+
+ # calls db_name(TMP_LOGIN), then creates a CouchRest::Database
+ # from the name
+ def tmp_database
+ choose_database(TMP_LOGIN)
+ end
+
+ def db_name(login=nil)
+ if !login.nil? && login.include?(TMP_LOGIN)
+ TMP_USER_DB
+ else
+ USER_DB
+ end
+ end
+
+ # create the tmp db if it doesn't exist.
+ # requires admin access.
+ def create_tmp_database!
+ design_doc.sync!(tmp_database.tap{|db|db.create!})
+ end
+ end
+
+ #
+ # this gets called each and every time a User object needs to
+ # access the database.
+ #
+ def db_name
+ self.class.db_name(self.login)
+ end
+
+ # returns true if this User instance is stored in tmp db.
+ def tmp?
+ !login.nil? && login.include?(TMP_LOGIN)
+ end
+
+end
diff --git a/app/models/token.rb b/app/models/token.rb
index ff2ad12..4afd275 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -1,8 +1,15 @@
require 'digest/sha2'
class Token < CouchRest::Model::Base
+ def self.expires_after
+ APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after]
+ end
- use_database :tokens
+ include CouchRest::Model::Rotation
+ rotate_database :tokens,
+ :every => 1.month,
+ :timestamp_field => :last_seen_at,
+ :timeout => self.expires_after.to_i # in minutes
belongs_to :user
@@ -23,10 +30,6 @@ class Token < CouchRest::Model::Base
self.find Digest::SHA512.hexdigest(token)
end
- def self.expires_after
- APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after]
- end
-
def self.expired
return [] unless expires_after
by_last_seen_at.endkey(expires_after.minutes.ago)
diff --git a/app/models/user.rb b/app/models/user.rb
index 9ac7d3d..52e20dd 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -42,6 +42,8 @@ class User < CouchRest::Model::Base
view :by_created_at
end # end of design
+ include TemporaryUser # MUST come after designs are defined.
+
def self.login_starts_with(query)
self.by_login.startkey(query).endkey(query + "\ufff0")
end