Files

197 lines
7.3 KiB
Ruby

# 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 :layout, Garden
can :sunniness, Crop
can :planted_from, Crop
can :harvested_for, Crop
can :sowing_info, 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, crop: { approval_status: "approved" }
# ... same for alternate names
cannot :read, AlternateName
can :read, AlternateName, crop: { approval_status: "approved" }
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, CropJobTemplate
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
# Arranging the bed is really editing the plantings in it, so collaborators
# can do it too, as they can with the plantings themselves.
# CanCan tries the rules defined last first, so the collaborator rules come
# before the owner's: your own gardens and plantings, the usual case, are then
# settled without asking the database about collaborators each time.
can :update_layout, Garden, garden_collaborators: { member_id: member.id }
can :update_layout, Garden, owner_id: member.id
can %i(make_nursery stop_nursery), Garden, owner_id: member.id
can :create, Planting
can :update, Planting, garden: { garden_collaborators: { member_id: member.id } }
can :transplant, Planting, garden: { garden_collaborators: { member_id: member.id } }
can :destroy, Planting, garden: { garden_collaborators: { member_id: member.id } }
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 :transplant, Planting, garden: { owner_id: member.id }
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 :destroy, GardenCollaborator, member_id: member.id
can :create, Job
can :update, Job, owner_id: member.id
can :destroy, Job, owner_id: member.id
can :update, Job, garden: { garden_collaborators: { member_id: member.id } }
can :destroy, Job, garden: { garden_collaborators: { member_id: member.id } }
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, planting: { garden: { garden_collaborators: { member_id: member.id } } }
can :destroy, Harvest, planting: { garden: { garden_collaborators: { member_id: member.id } } }
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
# blocking/unblocking permissions
can :create, Block
cannot :create, Block, blocked_id: member.id # can't block yourself
can :destroy, Block, blocker_id: member.id # can only unblock your own blocks
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
# Jobs are a member's own notepad: admins change theirs, not other members'.
cannot %i(update destroy), Job
can :update, Job, owner_id: member.id
can :destroy, Job, owner_id: member.id
can :update, Job, garden: { garden_collaborators: { member_id: member.id } }
can :destroy, Job, garden: { garden_collaborators: { member_id: member.id } }
end
end