Class: Ability

Inherits:
Object
  • Object
show all
Includes:
CanCan::Ability
Defined in:
app/models/ability.rb

Overview

This ability class defines the basic structure for our role-based authorization system.

You can either override it completely or use the following method to defined your own rights.

# app/model/ability.rb
require_dependency YourPlatform::Engine.root.join('app/models/ability').to_s

module AbilityDefinitions
  def rights_for_local_admins
    super
    can :do, :amazing_things
  end
end

class Ability
  prepend AbilityDefinitions
end

For an extensive example, have a look at: github.com/fiedl/wingolfsplattform/blob/master/app/models/ability.rb

Instance Method Summary collapse

Constructor Details

#initialize(user, params = {}, options = {}) ⇒ Ability

Returns a new instance of Ability.



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
# File 'app/models/ability.rb', line 27

def initialize(user, params = {}, options = {})
  # Define abilities for the passed in user here. For example:
  #
  #   user ||= User.new # guest user (not logged in)
  #   if user.admin?
  #     can :manage, :all
  #   else
  #     can :read, :all
  #   end
  #
  # The first argument to `can` is the action you are giving the user 
  # permission to do.
  # If you pass :manage it will apply to every action. Other common actions
  # here are :read, :create, :update and :destroy.
  #
  # The second argument is the resource the user can perform the action on. 
  # If you pass :all it will apply to every resource. Otherwise pass a Ruby
  # class of the resource.
  #
  # The third argument is an optional hash of conditions to further filter the
  # objects.
  # For example, here the user can only update published articles.
  #
  #   can :update, Article, :published => true
  #
  # See the wiki for details:
  # https://github.com/ryanb/cancan/wiki/Defining-Abilities

  # Attention: Check outside whether the user's role allowes that preview!
  # Currently, this is done in ApplicationController#current_ability.
  #
  @preview_as = options[:preview_as] 
  @preview_as = nil if @preview_as.blank?
  @role = options[:role].try(:to_s)

  @read_only_mode = options[:read_only_mode]
  @params = params
  @user = user
      
  if user
    if user.global_admin? and view_as?(:global_admin)
      rights_for_global_admins
    end
    if user.admin_of_anything? and view_as?(:admin)
      rights_for_local_admins
    end
    if view_as?([:officer, :admin])
      rights_for_local_officers
    end
    if Role.of(user).global_officer? and view_as?([:global_officer, :officer, :admin])
      rights_for_global_officers
    end
    if user.developer?
      rights_for_developers
    end
    rights_for_signed_in_users
  end
  rights_for_everyone

end

Instance Method Details

#paramsObject



104
105
106
# File 'app/models/ability.rb', line 104

def params
  @params
end

#preview_asObject



98
99
100
# File 'app/models/ability.rb', line 98

def preview_as
  @preview_as
end

#read_only_mode?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'app/models/ability.rb', line 101

def read_only_mode?
  @read_only_mode
end

#rights_for_developersObject



114
115
116
# File 'app/models/ability.rb', line 114

def rights_for_developers
  can :use, Rack::MiniProfiler
end

#rights_for_everyoneObject



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'app/models/ability.rb', line 289

def rights_for_everyone
  # Imprint
  # Make sure all users (even if not logged in) can read the imprint.
  #
  can :read, Page.find_imprint
  
  # Listing Events and iCalendar (ICS) Export:
  #
  # There are event lists on public websites and webcal feeds.
  # Therefore the user might not be logged in through a regular
  # session. Some public feeds can be seen by anyone. Other
  # feeds require an auth token.
  # 
  can :index_events, Group do |group|
    # Any registered user (identified by an auth token)
    # can index the events of any group.
    params[:token].present? && UserAccount.find_by_auth_token(params[:token])
  end
  can :index_events, User do |other_user|
    # To index the events relevant to a certain user,
    # one has to provide the correct auth token that corresponds
    # to that user.
    params[:token].present? && (UserAccount.find_by_auth_token(params[:token]) == other_user.)
  end
  can :index_public_events, :all
  
  # Nobody can destroy events that are older than 10 minutes.
  cannot :destroy, Event do |event|
    event.created_at < 10.minutes.ago
  end
  
end

#rights_for_global_adminsObject



118
119
120
121
122
123
124
125
# File 'app/models/ability.rb', line 118

def rights_for_global_admins
  if read_only_mode?
    can :read, :all
    can :index, :all
  else
    can :manage, :all
  end
end

#rights_for_global_officersObject



189
190
191
192
193
194
195
196
197
198
# File 'app/models/ability.rb', line 189

def rights_for_global_officers
  can :export_member_list, Group
  if not read_only_mode?
    can [:create_post, :create_post_for], Group
    can [:create_event, :create_event_for], Group
    can [:update, :destroy], Event do |event|
      event.contact_people.include? user
    end
  end
end

#rights_for_local_adminsObject



127
128
129
130
131
132
133
# File 'app/models/ability.rb', line 127

def rights_for_local_admins
  if not read_only_mode?
    can :manage, Group do |group|
      group.admins_of_self_and_ancestors.include? user
    end
  end
end

#rights_for_local_officersObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'app/models/ability.rb', line 135

def rights_for_local_officers
  can :export_member_list, Group do |group|
    user.in? group.officers_of_self_and_ancestors
  end
  
  if not read_only_mode?
    # Group emails
    #
    can [:create_post, :create_post_for], Group do |group|
      user.in?(group.officers_of_self_and_ancestor_groups) || user.in?(group.corporation.try(:officers) || [])
    end
  
    # Local officers can create events in their groups.
    #
    can [:create_event, :create_event_for], Group do |group|
      user.in? group.officers_of_self_and_ancestor_groups
    end
    can [:update, :destroy], Event do |event|
      event.group && user.in?(event.group.officers_of_self_and_ancestor_groups)
    end
    can :update, Group do |group|
      group.has_flag?(:contact_people) && can?(:update, group.parent_events.first)
    end
    
    # Local officers of pages can edit their pages and sub-pages
    # as long as they are the authors or the pages have *no* author.
    #
    can :update, Page do |page|
      can?(:read, page) and page.officers_of_self_and_ancestors.include?(user) and (page.author == user or page.author.nil?)
    end
    
    # Local officers of pages can add attachments to the page and subpages
    # and modify their own attachments.
    #
    can :create_attachment_for, Page do |page|
      can?(:read, page) and page.officers_of_self_and_ancestors.include?(user)
    end
    can [:update, :destroy], Attachment do |attachment|
      can?(:read, attachment.parent) and 
      can?(:read, attachment) and 
      attachment.author == user
    end
    
    # Local officers can also modify any attachment of their own pages 
    # in order to review their own pages.
    #
    can [:update, :destroy], Attachment do |attachment|
      can?(:read, attachment.parent) and 
      can?(:read, attachment) and 
      (attachment.parent.respond_to?(:author) && attachment.parent.author == user)
    end
  end
end

#rights_for_signed_in_usersObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'app/models/ability.rb', line 200

def rights_for_signed_in_users
  can :read, :terms_of_use
  can :accept, :terms_of_use if not read_only_mode?
  
  # Regular users can read users that are not hidden.
  # And they can read themselves.
  #
  can :read, User, id: User.find_all_non_hidden.map(&:id)
  can :read, user
      
  if not read_only_mode?
    # Regular users can create, update or destroy own profile fields
    # that do not belong to the General section.
    #
    can [:create, :read, :update, :destroy], ProfileField do |field|
      field.profileable.nil? or # to allow creating fields
      ((field.profileable == user) and (field.type != 'ProfileFieldTypes::General'))
    end
    
    # They can change their first name, but not their surname.
    # 
    can [:update, :change_first_name, :change_alias], User, :id => user.id
    
    # They can change their password, i.e. modify their user account.
    #
    can :update, UserAccount, :user_id => user.id
    
    # Regular users can update their own validity ranges of memberships
    # in order to update their corporate vita.
    #
    can :update, UserGroupMembership do |user_group_membership|
      user_group_membership.user == user
    end
    
    # All attendees or contact poeple of events can upload
    # images for these events.
    #
    can :create_attachment_for, Event do |event|
      event.attendees.include?(user) or event.contact_people.include?(user)
    end
    can [:update, :destroy], Attachment do |attachment|
      attachment.author == user and
      attachment.parent.kind_of?(Event) and
      (attachment.parent.attendees.include?(user) or attachment.parent.contact_people.include?(user))
    end
  
    # If a user is contact person of an event, he can provide pages and
    # attachment for this event.
    # 
    can [:update, :create_page_for], Event do |event|
      event.contact_people.include? user
    end
    can [:update, :create_attachment_for], Page do |page|
      page.ancestor_events.map(&:contact_people).flatten.include? user
    end
  end
  
  can :read, Group do |group|
    # Regular users cannot see the former_members_parent groups
    # and their descendant groups.
    #
    not (group.has_flag?(:former_members_parent) || group.ancestor_groups.find_all_by_flag(:former_members_parent).count > 0)
  end
  
  can :read, Page do |page|
    page.group.nil? || page.group.members.include?(user)
  end
  can [:read, :download], Attachment do |attachment|
    attachment.parent.try(:group).nil? || attachment.parent.try(:group).try(:members).try(:include?, user)
  end
      
  # All users can join events.
  #
  can :read, Event
  if not read_only_mode?
    can :join, Event
    can :leave, Event
  end
  can :index, Event
  can :index_events, Group
  can :index_events, User do |other_user|
    other_user == user
  end

  # Name auto completion
  #
  can :autocomplete_title, User
end

#roleObject



110
111
112
# File 'app/models/ability.rb', line 110

def role
  @role.try(:to_s)
end

#userObject



107
108
109
# File 'app/models/ability.rb', line 107

def user
  @user
end

#view_asObject



95
96
97
# File 'app/models/ability.rb', line 95

def view_as
  preview_as.try(:to_sym)
end

#view_as?(role) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
# File 'app/models/ability.rb', line 88

def view_as?(role)
  (view_as.nil?) or (view_as.to_s == '') or if role.kind_of?(Array)
    view_as.in? role
  else
    view_as == role
  end
end