# frozen_string_literal: true class Ability include CanCan::Ability def initialize(member) anon_abilities(member) member_abilities(member) if member.present? admin_abilities(member) if member.present? && member.role?(:admin) end def anon_abilities(_member) # See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities # everyone can do these things, even non-logged in can :read, :all can :read, Follow can :followers, Follow # Everyone can see the charts can :timeline, Garden can :sunniness, Crop can :planted_from, Crop can :harvested_for, Crop # except these, which don't make sense if you're not logged in cannot :read, Notification cannot :read, Authentication # and nobody should be able to view this except admins cannot :read, Role # nobody should be able to view unapproved crops unless they # are wranglers or admins cannot :read, Crop can :read, Crop, approval_status: "approved" # scientific names should only be viewable if associated crop is approved cannot :read, ScientificName can :read, ScientificName do |sn| sn.crop.approved? end # ... same for alternate names cannot :read, AlternateName can :read, AlternateName do |an| an.crop.approved? end cannot :create, GardenType cannot :update, GardenType cannot :destroy, GardenType end def member_abilities(member) return unless member # members can see even rejected or pending crops if they requested it can :read, Crop, requester_id: member.id can :requested, Crop # see list of crops they've requested # managing your own user settings can :update, Member, id: member.id # can read/delete notifications that were sent to them can :read, Notification, recipient_id: member.id can :destroy, Notification, recipient_id: member.id can :reply, Notification, recipient_id: member.id # can send a private message to anyone but themselves # note: sadly, we can't test for this from the view, but it works # for the model/controller can :create, Notification do |n| n.recipient_id != member.id end # NOTE: we don't support update for notifications # only crop wranglers can create/edit/destroy crops if member.role? :crop_wrangler can :wrangle, Crop can :manage, Crop can :manage, CropCompanion can :manage, ScientificName can :manage, AlternateName can :openfarm, Crop can :gbif, Crop end # any member can create a crop provisionally can :create, Crop # can create & destroy their own authentications against other sites. can :create, Authentication can :destroy, Authentication, member_id: member.id # anyone can create a post, like, or comment on a post, # but only the author can edit/destroy it. can :create, Post can :update, Post, author_id: member.id can :destroy, Post, author_id: member.id can :create, Like can :destroy, Like, member_id: member.id can :create, Comment can :update, Comment, author_id: member.id can :destroy, Comment, author_id: member.id # same deal for gardens and plantings can :create, Garden can :update, Garden, owner_id: member.id can :destroy, Garden, owner_id: member.id can :create, Planting can :update, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' } can :destroy, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' } can :update, Planting do |planting| planting.garden.garden_collaborators.where(member_id: member.id).any? end can :transplant, Planting, garden: { owner_id: member.id } can :transplant, Planting do |planting| planting.garden.garden_collaborators.where(member_id: member.id).any? end can :destroy, Planting do |planting| planting.garden.garden_collaborators.where(member_id: member.id).any? end can :create, GardenCollaborator, garden: { owner_id: member.id } can :update, GardenCollaborator, garden: { owner_id: member.id } can :destroy, GardenCollaborator, garden: { owner_id: member.id } can :create, Activity can :update, Activity, owner_id: member.id can :destroy, Activity, owner_id: member.id can :update, Activity do |activity| activity.garden&.garden_collaborators&.where(member_id: member.id)&.any? end can :destroy, Activity do |activity| activity.garden&.garden_collaborators&.where(member_id: member.id)&.any? end can :create, Harvest can :update, Harvest, owner_id: member.id can :destroy, Harvest, owner_id: member.id can :update, Harvest, owner_id: member.id, planting: { owner_id: member.id } can :destroy, Harvest, owner_id: member.id, planting: { owner_id: member.id } can :update, Harvest do |harvest| harvest.planting&.garden&.garden_collaborators&.where(member_id: member.id)&.any? end can :destroy, Harvest do |harvest| harvest.planting&.garden&.garden_collaborators&.where(member_id: member.id)&.any? end can :create, Photo can :update, Photo, owner_id: member.id can :destroy, Photo, owner_id: member.id can :create, Seed can :update, Seed, owner_id: member.id can :destroy, Seed, owner_id: member.id can :create, Seed, owner_id: member.id, parent_planting: { owner_id: member.id } can :update, Seed, owner_id: member.id, parent_planting: { owner_id: member.id } can :destroy, Seed, owner_id: member.id, parent_planting: { owner_id: member.id } # following/unfollowing permissions can :create, Follow cannot :create, Follow, followed_id: member.id # can't follow yourself can :destroy, Follow cannot :destroy, Follow, followed_id: member.id # can't unfollow yourself cannot :create, GardenType cannot :update, GardenType cannot :destroy, GardenType end def admin_abilities(member) return unless member.role? :admin can :read, :all can :manage, :all # can't delete plant parts if they have harvests associated with them cannot :destroy, PlantPart can :destroy, PlantPart do |pp| pp.harvests.empty? end # Admins can't delete themselves cannot :destroy, Member can :destroy, Member do |other_member| other_member&.id != member.id end end end