concord-consortium/lara

View on GitHub
app/models/ability.rb

Summary

Maintainability
C
1 day
Test Coverage
A
92%
class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here.
    #
    # See the wiki for details:
    # https://github.com/ryanb/cancan/wiki/Defining-Abilities

    user ||= User.new # guest user (not logged in)

    if user.admin?
      # Admins can do everything
      can :manage, :all

    elsif user.is_project_admin?
      can :create, Glossary
      can :duplicate, Glossary
      can :export, Glossary
      can :import, Glossary
      can :manage, Glossary do |glossary|
        user.id == glossary.user_id || user.project_admin_of?(glossary.project)
      end
      can :read, Glossary

      can :create, InteractivePage
      can :manage, InteractivePage do |page|
        user.id == page.lightweight_activity.user_id || user.project_admin_of?(page.lightweight_activity.project)
      end

      can :create, LightweightActivity
      can :duplicate, LightweightActivity do |activity|
        user.id == activity.user_id || user.project_admin_of?(activity.project) || (!activity.is_locked && ['public', 'hidden'].include?(activity.publication_status))
      end
      can :export, LightweightActivity do |activity|
        user.id == activity.user_id || user.project_admin_of?(activity.project) || (!activity.is_locked && ['public', 'hidden'].include?(activity.publication_status))
      end
      can :import, LightweightActivity
      can :manage, LightweightActivity do |activity|
        user.id == activity.user_id || user.project_admin_of?(activity.project)
      end

      can :create, LinkedPageItem
      can :manage, LinkedPageItem do |linked_page_item|
        activity = linked_page_item.primary.interactive_page.lightweight_activity
        user.id == activity.user_id || user.project_admin_of?(activity.project)
      end

      can :create, PageItem
      can :manage, PageItem do |page_item|
        activity = page_item.interactive_page.lightweight_activity
        user.id == activity.user_id || user.project_admin_of?(activity.project)
      end

      can :create, Plugin
      can :manage, Plugin do |plugin|
        user.id == plugin.plugin_scope.user_id || user.project_admin_of?(plugin.plugin_scope.project)
      end

      can :manage, Project do |project|
        user.project_admin_of?(project)
      end

      can :create, Sequence
      can :duplicate, Sequence do |sequence|
        user.id == sequence.user_id || user.project_admin_of?(sequence.project) || ['public', 'hidden'].include?(sequence.publication_status)
      end
      can :export, Sequence do |sequence|
        user.id == sequence.user_id || user.project_admin_of?(sequence.project) || ['public', 'hidden'].include?(sequence.publication_status)
      end
      can :import, Sequence
      can :manage, Sequence do |sequence|
        user.id == sequence.user_id || user.project_admin_of?(sequence.project)
      end

    elsif user.author?
      # Authors can do the following, organized by model
      can :create, Glossary
      can :duplicate, Glossary
      can :export, Glossary
      can :import, Glossary
      can :manage, Glossary, :user_id => user.id
      can :read, Glossary

      can :create, InteractivePage
      can :manage, InteractivePage, :lightweight_activity => { :user_id => user.id }

      can :create, LightweightActivity
      can :duplicate, LightweightActivity, :is_locked => false, :publication_status => ['public', 'hidden']
      can :export, LightweightActivity, :is_locked => false, :publication_status => ['public', 'hidden']
      can :import, LightweightActivity
      can :manage, LightweightActivity, :user_id => user.id

      can :create, LinkedPageItem
      can :manage, LinkedPageItem, :primary => { :interactive_page => { :interactive_page => { :lightweight_activity => { :user_id => user.id } } } }

      can :create, PageItem
      can :manage, PageItem, :interactive_page => { :lightweight_activity => { :user_id => user.id } }

      can :create, Plugin
      can :manage, Plugin do |plugin|
        plugin.plugin_scope.user_id == user.id
      end

      can :create, Sequence
      can :duplicate, Sequence, :publication_status => ['public', 'hidden']
      can :export, Sequence
      can :import, Sequence
      can :manage, Sequence, :user_id => user.id
    end

    # Everyone (author and regular user) can update glossaries they own.
    can :update, Glossary do |glossary|
      user.id == glossary.user_id || user.project_admin_of?(glossary.project)
    end
    # Everyone (author and regular user) can update activities they own.
    can :update, LightweightActivity do |activity|
      user.id == activity.user_id || user.project_admin_of?(activity.project)
    end
    # Everyone (author and regular user) can update pages in the activities they own.
    can :update, InteractivePage do |page|
      user.id == page.lightweight_activity.user_id || user.project_admin_of?(page.lightweight_activity)
    end
    # Everyone (author and regular user) can update sequences they own.
    can :update, Sequence do |sequence|
      user.id == sequence.user_id || user.project_admin_of?(sequence.project)
    end
    # Everyone (author and regular user) can read public, hidden and archived sequences or activities.
    ['public', 'hidden', 'archive'].each do |allowed_status|
      can :read, Sequence do |sequence|
        sequence.publication_status == allowed_status || user.project_admin_of?(sequence.project)
      end
      can :read, LightweightActivity do |activity|
        activity.publication_status == allowed_status || user.project_admin_of?(activity.project)
      end
      can :read, InteractivePage do |page|
        page.lightweight_activity.publication_status == allowed_status || user.project_admin_of?(page.lightweight_activity)
      end
    end
    can :about, Project
    can :help, Project
    can :contact_us, Project

    can :access, Run do |run|
      admin_owner_or_anon_run(user, run)
    end

    can :access, SequenceRun do |sequence_run|
      admin_owner_or_anon_run(user, sequence_run)
    end

    can [:show, :update], InteractiveRunState do |interactive_run_state|
      # admins can do anything, unowned runs can be read/written by anyone, owned runs only by their owner or their collaborators
      run = interactive_run_state.run
      allowed = user.admin? || run.user.nil? || (user == run.user)
      if !allowed && run.collaboration_run
        allowed = run.collaboration_run.runs.where(activity_id: run.activity, user_id: user).length > 0
      end
      allowed
    end
  end

  private

  def admin_owner_or_anon_run(user, run)
    if user.admin?
      true
    elsif user.new_record?
      # We're currently anonymous
      run.user_id.nil?
    else
      run.user_id == user.id
    end
  end
end