Module: ZeroAuthorization::Engine

Defined in:
lib/zero_authorization/engine.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/zero_authorization/engine.rb', line 3

def self.included(base)
  puts "Initializing ZeroAuthorization for #{base.name}"

  base.extend(ClassMethods)

  # Initializing authentication mode. Options are
  # :strict =>'raise exception and deny operation if not authorized' ,
  # :warning => 'display only warning without exception' [DEFAULT],
  # :superficial =>'allow operation without authorization'
  base.send(:initialize_authorization_mode)

  # Applying restriction on methods
  base.send(:initialize_methods_restriction)

  # Applying restriction on crud write operations
  base.send(:before_save, :is_zero_authorized_4_save)
  base.send(:before_create, :is_zero_authorized_4_create)
  base.send(:before_update, :is_zero_authorized_4_update)
  base.send(:before_destroy, :is_zero_authorized_4_destroy)


  private

  # Authorization for authorization mode :strict
  def authorize_strictly(action)
    role = ZeroAuthorization::Role.role
    raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_strictly but role not available' if role.nil?

    if zero_authorized_core(role, action)
      return true
    else
      raise ZeroAuthorization::Exceptions::NotAuthorized.new(role), "Not authorized to execute #{action} on #{self.class.name}."
    end

    false
  end

  # Authorization for authorization mode :warning
  def authorize_with_warning(action)
    role = ZeroAuthorization::Role.role
    raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_with_warning but role not available' if role.nil?

    if zero_authorized_core(role, action)
      return true
    else
      logger.debug 'ERROR: ZeroAuthorization: Not authorized to perform activity.'
      self.errors.add(:authorization_error, 'occurred, Unauthorized to perform this activity')
    end

    false
  end

  # Authorization for authorization mode :superficial
  def authorize_superficially(action)
    logger.debug 'ZeroAuthorizationMode: superficial. By passing authorization.'
    return true
  end

  # Return authorization mode
  def zero_authorized_checker(action)
    if self.class.authorization_mode == :strict
      return authorize_strictly(action)
    elsif self.class.authorization_mode == :warning
      return authorize_with_warning(action)
    elsif self.class.authorization_mode == :superficial
      return authorize_superficially(action)
    else
      raise ZeroAuthorization::Exceptions::InvalidAuthorizationMode
    end
  end

  # Core of authorization after reading/parsing rule set for current role
  # Rules for rule-sets execution (Precedence: from top to bottom)
  # Rule 00: If no rule-sets are available for 'can do' and 'cant do' then is authorized true '(with warning message)'.
  # Rule 01: If role can't do 'anything' or can do 'nothing' then is authorized false.
  # Rule 02: If role can't do 'nothing' or can do 'anything' then is authorized true.
  # Rule 03: If role can't do 'specified' method and given 'evaluate' method returns true then is authorized false.
  # Rule 04: If role can't do 'specified' method and given 'evaluate' method returns false then is authorized true.
  # Rule 05: If role can   do 'specified' method and given 'evaluate' method returns true then is authorized true.
  # Rule 06: If role can   do 'specified' method and given 'evaluate' method returns false then is authorized false.
  # Rule 07: If role can't do 'specified' method then is authorized false.
  # Rule 08: If role can   do 'specified' method then is authorized true.
  def zero_authorized_core(role, action)
    can_rights = role.can_do_rights(self.class.name)
    can_rights_names = can_rights.keys
    cant_rights = role.cant_do_rights(self.class.name)
    cant_rights_names = cant_rights.keys

    if can_rights.empty? and cant_rights.empty? #Rule 00
      _temp_i = "#{self.class.name} is exempted from ZeroAuthorization. To enable back, try adding rule-set(s) in role_n_privileges.yml"
      puts _temp_i
      Rails.logger.info _temp_i
      return true
    end
    return false if cant_rights_names.include?(:anything) or can_rights_names.include?(:nothing) #Rule 01
    return true if cant_rights_names.include?(:nothing) or can_rights_names.include?(:anything) #Rule 02
    return (self.send(cant_rights[action.to_sym]) ? false : true) unless cant_rights[action.to_sym].nil? # Rule 03 and Rule 04
    return (self.send(can_rights[action.to_sym]) ? true : false) unless can_rights[action.to_sym].nil? # Rule 05 and Rule 06
    return false if cant_rights_names.include?(action.to_sym) # Rule 07
    return true if can_rights_names.include?(action.to_sym) # Rule 08

    raise ZeroAuthorization::Exceptions::ExecutingUnreachableCode
  end

  def is_zero_authorized_4_save
    zero_authorized_checker(:save)
  end

  def is_zero_authorized_4_create
    zero_authorized_checker(:create)
  end

  def is_zero_authorized_4_update
    zero_authorized_checker(:update)
  end

  def is_zero_authorized_4_destroy
    zero_authorized_checker(:destroy)
  end
end

Instance Method Details

#authorize_strictly(action) ⇒ Object

Authorization for authorization mode :strict



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/zero_authorization/engine.rb', line 27

def authorize_strictly(action)
  role = ZeroAuthorization::Role.role
  raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_strictly but role not available' if role.nil?

  if zero_authorized_core(role, action)
    return true
  else
    raise ZeroAuthorization::Exceptions::NotAuthorized.new(role), "Not authorized to execute #{action} on #{self.class.name}."
  end

  false
end

#authorize_superficially(action) ⇒ Object

Authorization for authorization mode :superficial



56
57
58
59
# File 'lib/zero_authorization/engine.rb', line 56

def authorize_superficially(action)
  logger.debug 'ZeroAuthorizationMode: superficial. By passing authorization.'
  return true
end

#authorize_with_warning(action) ⇒ Object

Authorization for authorization mode :warning



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/zero_authorization/engine.rb', line 41

def authorize_with_warning(action)
  role = ZeroAuthorization::Role.role
  raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_with_warning but role not available' if role.nil?

  if zero_authorized_core(role, action)
    return true
  else
    logger.debug 'ERROR: ZeroAuthorization: Not authorized to perform activity.'
    self.errors.add(:authorization_error, 'occurred, Unauthorized to perform this activity')
  end

  false
end

#is_zero_authorized_4_createObject



111
112
113
# File 'lib/zero_authorization/engine.rb', line 111

def is_zero_authorized_4_create
  zero_authorized_checker(:create)
end

#is_zero_authorized_4_destroyObject



119
120
121
# File 'lib/zero_authorization/engine.rb', line 119

def is_zero_authorized_4_destroy
  zero_authorized_checker(:destroy)
end

#is_zero_authorized_4_saveObject



107
108
109
# File 'lib/zero_authorization/engine.rb', line 107

def is_zero_authorized_4_save
  zero_authorized_checker(:save)
end

#is_zero_authorized_4_updateObject



115
116
117
# File 'lib/zero_authorization/engine.rb', line 115

def is_zero_authorized_4_update
  zero_authorized_checker(:update)
end

#zero_authorized_checker(action) ⇒ Object

Return authorization mode



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/zero_authorization/engine.rb', line 62

def zero_authorized_checker(action)
  if self.class.authorization_mode == :strict
    return authorize_strictly(action)
  elsif self.class.authorization_mode == :warning
    return authorize_with_warning(action)
  elsif self.class.authorization_mode == :superficial
    return authorize_superficially(action)
  else
    raise ZeroAuthorization::Exceptions::InvalidAuthorizationMode
  end
end

#zero_authorized_core(role, action) ⇒ Object

Core of authorization after reading/parsing rule set for current role Rules for rule-sets execution (Precedence: from top to bottom) Rule 00: If no rule-sets are available for ‘can do’ and ‘cant do’ then is authorized true ‘(with warning message)’. Rule 01: If role can’t do ‘anything’ or can do ‘nothing’ then is authorized false. Rule 02: If role can’t do ‘nothing’ or can do ‘anything’ then is authorized true. Rule 03: If role can’t do ‘specified’ method and given ‘evaluate’ method returns true then is authorized false. Rule 04: If role can’t do ‘specified’ method and given ‘evaluate’ method returns false then is authorized true. Rule 05: If role can do ‘specified’ method and given ‘evaluate’ method returns true then is authorized true. Rule 06: If role can do ‘specified’ method and given ‘evaluate’ method returns false then is authorized false. Rule 07: If role can’t do ‘specified’ method then is authorized false. Rule 08: If role can do ‘specified’ method then is authorized true.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/zero_authorization/engine.rb', line 85

def zero_authorized_core(role, action)
  can_rights = role.can_do_rights(self.class.name)
  can_rights_names = can_rights.keys
  cant_rights = role.cant_do_rights(self.class.name)
  cant_rights_names = cant_rights.keys

  if can_rights.empty? and cant_rights.empty? #Rule 00
    _temp_i = "#{self.class.name} is exempted from ZeroAuthorization. To enable back, try adding rule-set(s) in role_n_privileges.yml"
    puts _temp_i
    Rails.logger.info _temp_i
    return true
  end
  return false if cant_rights_names.include?(:anything) or can_rights_names.include?(:nothing) #Rule 01
  return true if cant_rights_names.include?(:nothing) or can_rights_names.include?(:anything) #Rule 02
  return (self.send(cant_rights[action.to_sym]) ? false : true) unless cant_rights[action.to_sym].nil? # Rule 03 and Rule 04
  return (self.send(can_rights[action.to_sym]) ? true : false) unless can_rights[action.to_sym].nil? # Rule 05 and Rule 06
  return false if cant_rights_names.include?(action.to_sym) # Rule 07
  return true if can_rights_names.include?(action.to_sym) # Rule 08

  raise ZeroAuthorization::Exceptions::ExecutingUnreachableCode
end