Module: Permissable::Member::InstanceMethods

Defined in:
lib/permissable/member.rb

Overview

This module includes methods that should exist on ALL members.

Instance Method Summary collapse

Instance Method Details

#allow_permission_with_methodObject

Find our permission override if available



116
# File 'lib/permissable/member.rb', line 116

def allow_permission_with_method; self.class.permissable_options[:allow_permission_with_method]; end

#can!(methods, resources) ⇒ Object

Assign permissions to a member if they don’t already exist. TODO: There has to be a friendlier way to mass assign permissions to roles rather than looping each one for existence and then saving separately.



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
# File 'lib/permissable/member.rb', line 38

def can!(methods, resources)
  
  # This method should return all of the new permissions that were created, so we build a 
  # response array to return
  result_response = []
  
  # Load all permissions fresh so we can kill dupes.
  saved_permissions = Permission.all
  # Store new permissions in an array so we can squeeze into one transaction.
  permissions_to_add    = []
  permissions_to_update = []
  
  [resources].flatten.each do |resource|
    
    # Kind of unecessary but since some methods allow you to specify a Classname directly, this just
    # safegaurds against trying to do the same here.
    next if resource.is_a?(Class)
    
    # Get the member identifier for this resource
    identifier = member_identifier(resource)
    
    [methods].flatten.each do |method|
      
      resource_type = (resource.respond_to?(:base_class) ? resource.base_class.to_s : resource.class.base_class.to_s)
      
      # Create a new permission for each member (once if its self, multiple times if its associated)
      [identifier[:member_id]].flatten.each do |member_id|              
        perm = saved_permissions.detect{ |p| p.member_id == member_id && p.member_type == identifier[:member_type] && p.resource_id == resource.id && p.resource_type == resource_type }  || Permission.new(:member_id => member_id, :member_type => identifier[:member_type])
        perm.permission_type = method.to_s.downcase
        perm.resource        = resource if perm.new_record?
        (perm.new_record?) ? (permissions_to_add << perm) : (permissions_to_update << perm)
      end
    end
  end
  
  
  unless permissions_to_add.empty?
    attrs = permissions_to_add.first.attributes.keys.collect{ |k| k.to_s }
    sql_insert = "INSERT INTO `permissions` (`#{attrs.join("`,`")}`) VALUES"
    sql_values = []
    permissions_to_add.each do |perm|
      vals = []
      attrs.each{ |a| vals << ((a == "created_at" || a == "updated_at") ? DateTime.now.utc.strftime("%Y-%m-%d %H:%M:%S") : ((a == "id") ? "NULL" : perm.send(a.to_sym))) }
      sql_values << "('#{vals.join("','")}')"
    end        
    Permission.connection.execute("#{sql_insert} #{sql_values.join(',')}")
  end
  
  unless permissions_to_update.empty?
    permissions_to_update.each do |perm|
      Permission.update_all(['permission_type = ?', perm.permission_type ], ['id = ?', perm.id])
    end
  end
  
end

#can?(methods, resource, chain = true) ⇒ Boolean

The can? method returns a boolen value specifying whether or not this member can perform the specific method on resource

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/permissable/member.rb', line 16

def can?(methods, resource, chain = true)
  unless allow_permission_with_method.nil?
    if self.respond_to? "#{allow_permission_with_method}"
      return true if (send "#{allow_permission_with_method}")
    end
  end
  
  if chain
    methods = [methods].flatten.collect{ |m| m.to_sym }
    methods = find_methods_from_chain(methods)
  end
  
  permissions_for?(resource, methods)
  
end

#cannot?(method, resource) ⇒ Boolean

Alias to can? to get the inverse.

Returns:

  • (Boolean)


33
# File 'lib/permissable/member.rb', line 33

def cannot?(method, resource); !can?(method, resource); end

#lookup_permissions!Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/permissable/member.rb', line 124

def lookup_permissions!

  resource_types = self.class.permissable_resources.collect{ |r| r.to_s.classify }
  member_ids   = []
  member_types = []
  
  resource_types.each do |type|
    identifier = member_identifier(type)
    member_ids   << identifier[:member_id]
    member_types << identifier[:member_type]
  end
  
  member_ids   = member_ids.uniq; member_types = member_types.uniq;
  member_ids   = member_ids.first unless member_ids.size > 1
  member_types = member_types.first unless member_types.size > 1
  
  @permissions_cache ||= PermissionsCache.new(Permission.where(:member_id => member_ids, :member_type => member_types, :resource_type => resource_types).all)
  
end

#member_identifier(resource) ⇒ Object

This sets the member information for our permission lookup based on the current resource scope. These attributes correspond to the correct member_id and member_type in our permissions table.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/permissable/member.rb', line 96

def member_identifier(resource)
  
  @member_identifier ||= {}
  scope = fetch_scope(resource)
  
  return @member_identifier[scope] unless @member_identifier[scope].nil?
  return { :member_id => self.id, :member_type => self.class.to_s } unless permissable_associations.has_key?(scope)
  
  @association_scopes ||= {}
  assoc_key = permissable_associations[scope]
  @association_scopes[assoc_key] ||= send("#{assoc_key}".to_sym)
  assoc = @association_scopes[assoc_key]
  
  @member_identifier[scope] = { :member_id => (assoc.is_a?(Array) ? assoc.collect{ |a| a.id } : assoc.id ), :member_type => assoc_key.to_s.classify }
  
end

#permissable_associationsObject

Provide an instance method to our associations



114
# File 'lib/permissable/member.rb', line 114

def permissable_associations; self.class.permissable_associations || {}; end

#permission_chainObject

See if there is a permissions chain



118
# File 'lib/permissable/member.rb', line 118

def permission_chain; self.class.permissable_options[:permission_chain] || {}; end

#permissions_for(resource) ⇒ Object



120
121
122
# File 'lib/permissable/member.rb', line 120

def permissions_for(resource)
  fetch_permissions_for(resource).all.collect{ |perm| perm.permission_type.to_sym }
end