hpi-swt2/sport-portal

View on GitHub
app/models/ability.rb

Summary

Maintainability
A
0 mins
Test Coverage
class Ability
  include CanCan::Ability
  # 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.
  # You will usually be working with these four actions.
  # These aren't the same as the 7 RESTful actions in Rails!
  # CanCanCan automatically adds some convenient aliases for mapping the controller actions.
  # https://github.com/CanCanCommunity/cancancan/wiki/Action-Aliases
  #  `alias_action :index, :show, :to => :read`
  #  `alias_action :new, :to => :create`
  #  `alias_action :edit, :to => :update`
  #
  # 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/CanCanCommunity/cancancan/wiki/Defining-Abilities

  def initialize(user)
    alias_action :schedule, :overview, to: :read
    alias_action :update, :destroy, to: :modify
    alias_action :create_from_type, to: :create
    can :read, :all
    cannot :read, User
    cannot :read, Team, private: true
    cannot :index, User
    can :create, User
    if user.present?
      initialize_with_user(user)
    end
  end

  private

    def initialize_with_user(user)
      user_id = user.id

      # all
      can :create, :all

      # User
      can :show, User
      can [:modify, :edit_profile, :update_profile, :dashboard, :confirm_destroy, :notifications], User, id: user_id
      cannot :create, User

      # Event
      can [:create, :read, :update, :destroy], Event, owner_id: user_id
      can_join_event(user)
      can_leave_event(user)
      can :ranking, Event
      can [:schedule, :team_join], Event
      can_update_gameday(user)

      # Team
      can_crud_team(user_id)
      can_destroy_team(user)
      can_assign_ownership(user)
      can_delete_ownership(user)
      can_delete_membership(user)
      can_assign_membership_by_email(user)
      can_send_emails_to_team_members(user)

      # Match
      can_modify_match(user)
      cannot :destroy, Match

      if user.admin?
        can :manage, :all
      end

      can_confirm_scores(user)
    end

    def can_modify_match(user)
      can :modify, Match do |match|
        user.teams.where(id: match.teams).exists?
      end
    end

    def can_join_event(user)
      can :join, Event.active do |event|
        event.can_join?(user)
      end
    end

    def can_leave_event(user)
      can :leave, Event do |event|
        event.can_leave?(user)
      end
    end

    def can_update_gameday(user)
      can :update_gameday, Gameday, Gameday do |gameday|
        not (gameday.event.organizers & user.organizers).empty?
      end
    end

    def can_crud_team(user_id)
      can :read, Team, private: true, members: { id: user_id }
      can :update, Team, members: { id: user_id }
    end

    def can_destroy_team(user)
      can :destroy, Team, Team do |team|
        (team.owners.include? user) && (!team.associated_with_event?)
      end
    end

    def can_assign_membership_by_email(user)
      can :assign_membership_by_email, Team, Team do |team|
        ((team.members.include? user) || (team.owners.include? user)) && max_players_per_team_border_not_exceeded?(team, 1)
      end
    end

    def can_send_emails_to_team_members(user)
      can :send_emails_to_team_members, Team, members: { id: user.id }
    end

    def can_assign_ownership(user)
      can :assign_ownership, Team, Team do |team|
        team.owners.include? user
      end
    end

    def can_delete_membership(user)
      can :delete_membership, Team, Team do |team, team_member|
        user_id = user.id
        exist_owners_after_delete = Ability.number_of_owners_after_delete(team, team_member) > 0
        (((team.owners.include? user) && exist_owners_after_delete) || ((team.members.include? user) && (user_id == Integer(team_member)) && exist_owners_after_delete)) && min_players_per_team_border_not_exceeded?(team, 1)
      end
    end

    def can_delete_ownership(user)
      can :delete_ownership, Team, Team do |team|
        (team.owners.include? user) && team.has_multiple_owners?
      end
    end

    def self.number_of_owners_after_delete(team, team_member)
      owners = team.owners
      another_user = User.find(team_member)
      if owners.include? another_user
        owners_after_delete = owners - [another_user]
      else
        owners_after_delete = owners
      end
      owners_after_delete.length
    end

    def min_players_per_team_border_not_exceeded?(team, update_count)
      not_exceeded = true
      team.events.each do |event|
        not_exceeded = event.min_players_per_team <= team.members.count - update_count
      end
      not_exceeded
    end

    def max_players_per_team_border_not_exceeded?(team, update_count)
      not_exceeded = true
      team.events.each do |event|
        not_exceeded = event.max_players_per_team >= team.members.count + update_count
      end
      not_exceeded
    end

    def can_confirm_scores(user)
      can :confirm_scores, Match do |match|
        match.can_confirm_scores?(user)
      end
    end
end