Newer
Older
dmpopidor / app / models / role.rb
# == Schema Information
#
# Table name: roles
#
#  id         :integer          not null, primary key
#  access     :integer          default(0), not null
#  active     :boolean          default(TRUE)
#  created_at :datetime
#  updated_at :datetime
#  plan_id    :integer
#  user_id    :integer
#
# Indexes
#
#  index_roles_on_plan_id  (plan_id)
#  index_roles_on_user_id  (user_id)
#
# Foreign Keys
#
#  fk_rails_...  (plan_id => plans.id)
#  fk_rails_...  (user_id => users.id)
#

class Role < ActiveRecord::Base

  include FlagShihTzu
  include ValidationMessages
  include ValidationValues

  # =============
  # = Constants =
  # =============

  # Returns a hash of hashes where each key represents an access level
  # (e.g. see access_level method to understand the integers)
  #
  # This method becomes useful for generating template messages (e.g.
  # permissions change notification mailer)
  ACCESS_LEVEL_MESSAGES = {
    5 => {
      type: _('reviewer'),
      placeholder1: _('read the plan and provide feedback.'),
      placeholder2: nil
    },
    3 => {
      type: _('co-owner'),
      placeholder1: _('write and edit the plan in a collaborative manner.'),
      placeholder2: _('You can also grant rights to other collaborators.')
    },
    2 => {
      type: _('editor'),
      placeholder1: _('write and edit the plan in a collaborative manner.'),
      placeholder2: nil,
    },
    1 => {
      type: _('read-only'),
      placeholder1: _('read the plan and leave comments.'),
      placeholder2: nil,
    }
  }

  # ================
  # = Associations =
  # ================

  belongs_to :user

  belongs_to :plan

  ##
  # Define Bit Field Values
  # Column access
  has_flags 1 => :creator,            # 1
            2 => :administrator,      # 2
            3 => :editor,             # 4
            4 => :commenter,          # 8
            5 => :reviewer,           # 16
            column: 'access'

  # ===============
  # = Validations =
  # ===============

  validates :user, presence: { message: PRESENCE_MESSAGE }

  validates :plan, presence: { message: PRESENCE_MESSAGE }

  validates :active, inclusion: { in: BOOLEAN_VALUES,
                                  message: INCLUSION_MESSAGE }

  validates :access, presence: { message: PRESENCE_MESSAGE },
                     numericality: { greater_than: 0, only_integer: true,
                                     message: _("can't be less than zero") }

  # =============
  # = Callbacks =
  # =============

  # TODO: Push this down to the DB constraints
  after_initialize :set_defaults

  ##
  # Roles with given FlagShihTzu access flags
  #
  # flags - One or more symbols that represent access flags
  #
  # Return ActiveRecord::Relation
  scope :with_access_flags, -> (*flags) {
    bad_flag = flags.detect { |flag| !flag.in?(flag_mapping['access'].keys) }
    raise ArgumentError, "Unkown access flag '#{bad_flag}'" if bad_flag
    access_values = flags.map { |flag| sql_in_for_flag(flag.to_sym, 'access') }
                         .flatten
                         .uniq
    where(access: access_values)
  }

  # ===========================
  # = Public instance methods =
  # ===========================


  # The access level for the current project group:
  # - 5 if the user is a reviewer
  # - 3 if the user is an administrator
  # - 2 if the user is an editor
  # - 1 if the user can only read
  # used to facilliatte formtastic
  #
  # Returns Integer
  def access_level
    if self.reviewer?
      return 5
    elsif self.administrator?
      return 3
    elsif self.editor?
      return 2
    elsif self.commenter?
      return 1
    end
  end

  def access_level=(value)
    self.commenter     = value.to_i >= 1
    self.editor        = value.to_i >= 2
    self.administrator = value.to_i >= 3
  end

  alias :set_access_level :access_level=

  deprecate :set_access_level,
              deprecator: Cleanup::Deprecators::SetDeprecator.new


  def set_defaults
    self.active = true if self.new_record?
  end

end

# -----------------------------------------------------
# Bitwise key
# -----------------------------------------------------
# 01 - creator
# 02 - administrator
# 03 - creator + administrator
# 04 - editor
# 05 - creator + editor
# 06 - administraor + editor
# 07 - creator + editor + administrator
# 08 - commenter
# 09 - creator + commenter
# 10 - administrator + commenter
# 11 - creator + administrator + commenter
# 12 - editor + commenter
# 13 - creator + editor + commenter
# 14 - administrator + editor + commenter
# 15 - creator + administrator + editor + commenter
# 16 - reviewer
# 17 - creator + reviewer
# 18 - administrator + reviewer
# 19 - creator + administrator + reviewer
# 20 - editor + reviewer
# 21 - creator + editor + reviewer
# 22 - administraor + editor + reviewer
# 23 - creator + editor + administrator + reviewer
# 24 - commenter + reviewer
# 25 - creator + commenter + reviewer
# 26 - administrator + commenter + reviewer
# 27 - creator + administrator + commenter + reviewer
# 28 - editor + commenter + reviewer
# 29 - creator + editor + commenter + reviewer
# 30 - administrator + editor + commenter + reviewer
# 31 - creator + administrator + editor + commenter + reviewer