SpeciesFileGroup/taxonworks

View on GitHub
app/models/georeference.rb

Summary

Maintainability
C
1 day
Test Coverage

Possible SQL injection
Open

    Georeference.joins(:geographic_item).where(q1)
Severity: Critical
Found in app/models/georeference.rb by brakeman

Injection is #1 on the 2013 OWASP Top Ten web security risks. SQL injection is when a user is able to manipulate a value which is used unsafely inside a SQL query. This can lead to data leaks, data loss, elevation of privilege, and other unpleasant outcomes.

Brakeman focuses on ActiveRecord methods dealing with building SQL statements.

A basic (Rails 2.x) example looks like this:

User.first(:conditions => "username = '#{params[:username]}'")

Brakeman would produce a warning like this:

Possible SQL injection near line 30: User.first(:conditions => ("username = '#{params[:username]}'"))

The safe way to do this query is to use a parameterized query:

User.first(:conditions => ["username = ?", params[:username]])

Brakeman also understands the new Rails 3.x way of doing things (and local variables and concatenation):

username = params[:user][:name].downcase
password = params[:user][:password]

User.first.where("username = '" + username + "' AND password = '" + password + "'")

This results in this kind of warning:

Possible SQL injection near line 37:
User.first.where((((("username = '" + params[:user][:name].downcase) + "' AND password = '") + params[:user][:password]) + "'"))

See the Ruby Security Guide for more information and Rails-SQLi.org for many examples of SQL injection in Rails.

Possible SQL injection
Open

    Georeference.where(collecting_event: CollectingEvent.where(query))
Severity: Minor
Found in app/models/georeference.rb by brakeman

Injection is #1 on the 2013 OWASP Top Ten web security risks. SQL injection is when a user is able to manipulate a value which is used unsafely inside a SQL query. This can lead to data leaks, data loss, elevation of privilege, and other unpleasant outcomes.

Brakeman focuses on ActiveRecord methods dealing with building SQL statements.

A basic (Rails 2.x) example looks like this:

User.first(:conditions => "username = '#{params[:username]}'")

Brakeman would produce a warning like this:

Possible SQL injection near line 30: User.first(:conditions => ("username = '#{params[:username]}'"))

The safe way to do this query is to use a parameterized query:

User.first(:conditions => ["username = ?", params[:username]])

Brakeman also understands the new Rails 3.x way of doing things (and local variables and concatenation):

username = params[:user][:name].downcase
password = params[:user][:password]

User.first.where("username = '" + username + "' AND password = '" + password + "'")

This results in this kind of warning:

Possible SQL injection near line 37:
User.first.where((((("username = '" + params[:user][:name].downcase) + "' AND password = '") + params[:user][:password]) + "'"))

See the Ruby Security Guide for more information and Rails-SQLi.org for many examples of SQL injection in Rails.

Class Georeference has 33 methods (exceeds 20 allowed). Consider refactoring.
Open

class Georeference < ApplicationRecord
  include Housekeeping
  include Shared::Notes
  include Shared::Tags
  include Shared::IsData
Severity: Minor
Found in app/models/georeference.rb - About 4 hrs to fix

    File georeference.rb has 296 lines of code (exceeds 250 allowed). Consider refactoring.
    Open

    class Georeference < ApplicationRecord
      include Housekeeping
      include Shared::Notes
      include Shared::Tags
      include Shared::IsData
    Severity: Minor
    Found in app/models/georeference.rb - About 3 hrs to fix

      Method check_error_geo_item_intersects_area has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.
      Open

        def check_error_geo_item_intersects_area
          # case 5.5
          retval = true
          if collecting_event.present?
            if error_geographic_item.present?
      Severity: Minor
      Found in app/models/georeference.rb - About 1 hr to fix

      Cognitive Complexity

      Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

      A method's cognitive complexity is based on a few simple rules:

      • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
      • Code is considered more complex for each "break in the linear flow of the code"
      • Code is considered more complex when "flow breaking structures are nested"

      Further reading

      Method error_box has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
      Open

        def error_box
          retval = nil
      
          if error_radius.nil?
            retval = error_geographic_item.dup unless error_geographic_item.nil?
      Severity: Minor
      Found in app/models/georeference.rb - About 45 mins to fix

      Cognitive Complexity

      Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

      A method's cognitive complexity is based on a few simple rules:

      • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
      • Code is considered more complex for each "break in the linear flow of the code"
      • Code is considered more complex when "flow breaking structures are nested"

      Further reading

      Method check_obj_inside_err_radius has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
      Open

        def check_obj_inside_err_radius
          # case 2
          retval = true
          # if !error_radius.blank? && geographic_item && geographic_item.geo_object
          unless error_radius.blank?
      Severity: Minor
      Found in app/models/georeference.rb - About 35 mins to fix

      Cognitive Complexity

      Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

      A method's cognitive complexity is based on a few simple rules:

      • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
      • Code is considered more complex for each "break in the linear flow of the code"
      • Code is considered more complex when "flow breaking structures are nested"

      Further reading

      Method check_obj_inside_area has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
      Open

        def check_obj_inside_area
          # case 6
          retval = true
          if collecting_event.present?
            if geographic_item.present? && collecting_event.geographic_area.present?
      Severity: Minor
      Found in app/models/georeference.rb - About 35 mins to fix

      Cognitive Complexity

      Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

      A method's cognitive complexity is based on a few simple rules:

      • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
      • Code is considered more complex for each "break in the linear flow of the code"
      • Code is considered more complex when "flow breaking structures are nested"

      Further reading

      Method check_error_geo_item_inside_area has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
      Open

        def check_error_geo_item_inside_area
          # case 5
          retval = true
          unless collecting_event.nil?
            unless error_geographic_item.nil?
      Severity: Minor
      Found in app/models/georeference.rb - About 25 mins to fix

      Cognitive Complexity

      Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

      A method's cognitive complexity is based on a few simple rules:

      • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
      • Code is considered more complex for each "break in the linear flow of the code"
      • Code is considered more complex when "flow breaking structures are nested"

      Further reading

      Avoid more than 3 levels of block nesting.
      Open

                unless collecting_event.geographic_area.nil?
                  retval = collecting_event.geographic_area.default_geographic_item
                             .contains?(error_geographic_item.geo_object)
                end
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for excessive nesting of conditional and looping constructs.

      You can configure if blocks are considered using the CountBlocks option. When set to false (the default) blocks are not counted towards the nesting level. Set to true to count blocks as well.

      The maximum level of nesting allowed is configurable.

      Avoid more than 3 levels of block nesting.
      Open

                if collecting_event.geographic_area.present?
                  retval = collecting_event.geographic_area.default_geographic_item
                             .intersects?(error_geographic_item.geo_object)
                end
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for excessive nesting of conditional and looping constructs.

      You can configure if blocks are considered using the CountBlocks option. When set to false (the default) blocks are not counted towards the nesting level. Set to true to count blocks as well.

      The maximum level of nesting allowed is configurable.

      Avoid more than 3 levels of block nesting.
      Open

                unless val.blank?
                  retval = val.contains?(geographic_item.geo_object)
                end
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for excessive nesting of conditional and looping constructs.

      You can configure if blocks are considered using the CountBlocks option. When set to false (the default) blocks are not counted towards the nesting level. Set to true to count blocks as well.

      The maximum level of nesting allowed is configurable.

      Avoid more than 3 levels of block nesting.
      Open

                case geographic_item.geo_object_type
                  when :point
                    retval = Utilities::Geo.error_box_for_point(geographic_item.geo_object, error_radius)
                  when :polygon, :multi_polygon
                    retval = geographic_item.geo_object
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for excessive nesting of conditional and looping constructs.

      You can configure if blocks are considered using the CountBlocks option. When set to false (the default) blocks are not counted towards the nesting level. Set to true to count blocks as well.

      The maximum level of nesting allowed is configurable.

      Specify an :inverse_of option.
      Open

        belongs_to :error_geographic_item, class_name: 'GeographicItem', foreign_key: :error_geographic_item_id
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop looks for has(one|many) and belongsto associations where Active Record can't automatically determine the inverse association because of a scope or the options used. Using the blog with order scope example below, traversing the a Blog's association in both directions with blog.posts.first.blog would cause the blog to be loaded from the database twice.

      :inverse_of must be manually specified for Active Record to use the associated object in memory, or set to false to opt-out. Note that setting nil does not stop Active Record from trying to determine the inverse automatically, and is not considered a valid value for this.

      Example:

      # good
      class Blog < ApplicationRecord
        has_many :posts
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end

      Example:

      # bad
      class Blog < ApplicationRecord
        has_many :posts, -> { order(published_at: :desc) }
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      class Blog < ApplicationRecord
        has_many(:posts,
                 -> { order(published_at: :desc) },
                 inverse_of: :blog)
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      class Blog < ApplicationRecord
        with_options inverse_of: :blog do
          has_many :posts, -> { order(published_at: :desc) }
        end
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      # When you don't want to use the inverse association.
      class Blog < ApplicationRecord
        has_many(:posts,
                 -> { order(published_at: :desc) },
                 inverse_of: false)
      end

      Example:

      # bad
      class Picture < ApplicationRecord
        belongs_to :imageable, polymorphic: true
      end
      
      class Employee < ApplicationRecord
        has_many :pictures, as: :imageable
      end
      
      class Product < ApplicationRecord
        has_many :pictures, as: :imageable
      end
      
      # good
      class Picture < ApplicationRecord
        belongs_to :imageable, polymorphic: true
      end
      
      class Employee < ApplicationRecord
        has_many :pictures, as: :imageable, inverse_of: :imageable
      end
      
      class Product < ApplicationRecord
        has_many :pictures, as: :imageable, inverse_of: :imageable
      end

      Example:

      # bad
      # However, RuboCop can not detect this pattern...
      class Physician < ApplicationRecord
        has_many :appointments
        has_many :patients, through: :appointments
      end
      
      class Appointment < ApplicationRecord
        belongs_to :physician
        belongs_to :patient
      end
      
      class Patient < ApplicationRecord
        has_many :appointments
        has_many :physicians, through: :appointments
      end
      
      # good
      class Physician < ApplicationRecord
        has_many :appointments
        has_many :patients, through: :appointments
      end
      
      class Appointment < ApplicationRecord
        belongs_to :physician, inverse_of: :appointments
        belongs_to :patient, inverse_of: :appointments
      end
      
      class Patient < ApplicationRecord
        has_many :appointments
        has_many :physicians, through: :appointments
      end

      @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses

      Specify an :inverse_of option.
      Open

        has_many :georeferencer_roles, -> { order('roles.position ASC') },
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop looks for has(one|many) and belongsto associations where Active Record can't automatically determine the inverse association because of a scope or the options used. Using the blog with order scope example below, traversing the a Blog's association in both directions with blog.posts.first.blog would cause the blog to be loaded from the database twice.

      :inverse_of must be manually specified for Active Record to use the associated object in memory, or set to false to opt-out. Note that setting nil does not stop Active Record from trying to determine the inverse automatically, and is not considered a valid value for this.

      Example:

      # good
      class Blog < ApplicationRecord
        has_many :posts
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end

      Example:

      # bad
      class Blog < ApplicationRecord
        has_many :posts, -> { order(published_at: :desc) }
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      class Blog < ApplicationRecord
        has_many(:posts,
                 -> { order(published_at: :desc) },
                 inverse_of: :blog)
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      class Blog < ApplicationRecord
        with_options inverse_of: :blog do
          has_many :posts, -> { order(published_at: :desc) }
        end
      end
      
      class Post < ApplicationRecord
        belongs_to :blog
      end
      
      # good
      # When you don't want to use the inverse association.
      class Blog < ApplicationRecord
        has_many(:posts,
                 -> { order(published_at: :desc) },
                 inverse_of: false)
      end

      Example:

      # bad
      class Picture < ApplicationRecord
        belongs_to :imageable, polymorphic: true
      end
      
      class Employee < ApplicationRecord
        has_many :pictures, as: :imageable
      end
      
      class Product < ApplicationRecord
        has_many :pictures, as: :imageable
      end
      
      # good
      class Picture < ApplicationRecord
        belongs_to :imageable, polymorphic: true
      end
      
      class Employee < ApplicationRecord
        has_many :pictures, as: :imageable, inverse_of: :imageable
      end
      
      class Product < ApplicationRecord
        has_many :pictures, as: :imageable, inverse_of: :imageable
      end

      Example:

      # bad
      # However, RuboCop can not detect this pattern...
      class Physician < ApplicationRecord
        has_many :appointments
        has_many :patients, through: :appointments
      end
      
      class Appointment < ApplicationRecord
        belongs_to :physician
        belongs_to :patient
      end
      
      class Patient < ApplicationRecord
        has_many :appointments
        has_many :physicians, through: :appointments
      end
      
      # good
      class Physician < ApplicationRecord
        has_many :appointments
        has_many :patients, through: :appointments
      end
      
      class Appointment < ApplicationRecord
        belongs_to :physician, inverse_of: :appointments
        belongs_to :patient, inverse_of: :appointments
      end
      
      class Patient < ApplicationRecord
        has_many :appointments
        has_many :physicians, through: :appointments
      end

      @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses

      Use if geographic_item.geo_object.present? instead of unless geographic_item.geo_object.blank?.
      Open

              unless geographic_item.geo_object.blank?
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      Use if val.present? instead of unless val.blank?.
      Open

                unless val.blank?
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      Use if error_radius.present? instead of unless error_radius.blank?.
      Open

            unless error_radius.blank? # rubocop:disable Style/IfUnlessModifier
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      Use if geographic_item.present? instead of unless geographic_item.blank?.
      Open

            unless geographic_item.blank?
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      Use error_radius.present? instead of !error_radius.blank?.
      Open

          if !error_radius.blank? &&
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      Use if error_radius.present? instead of unless error_radius.blank?.
      Open

          unless error_radius.blank?
      Severity: Minor
      Found in app/models/georeference.rb by rubocop

      This cop checks for code that can be written with simpler conditionals using Object#present? defined by Active Support.

      Interaction with Style/UnlessElse: The configuration of NotBlank will not produce an offense in the context of unless else if Style/UnlessElse is inabled. This is to prevent interference between the auto-correction of the two cops.

      Example: NotNilAndNotEmpty: true (default)

      # Converts usages of `!nil? && !empty?` to `present?`
      
      # bad
      !foo.nil? && !foo.empty?
      
      # bad
      foo != nil && !foo.empty?
      
      # good
      foo.present?

      Example: NotBlank: true (default)

      # Converts usages of `!blank?` to `present?`
      
      # bad
      !foo.blank?
      
      # bad
      not foo.blank?
      
      # good
      foo.present?

      Example: UnlessBlank: true (default)

      # Converts usages of `unless blank?` to `if present?`
      
      # bad
      something unless foo.blank?
      
      # good
      something if foo.present?

      TODO found
      Open

        #   !! We assume the radius calculation is always larger (TODO: do we?  discuss with Jim)
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      TODO found
      Open

        # TODO: cleanup, subclass, and calculate with SQL?
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      TODO found
      Open

        # TODO: or, (in the future) a string matching a geographic_area.name
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      TODO found
      Open

        # TODO: not yet sure what the params are going to look like. what is below just represents a guess
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      TODO found
      Open

        # TODO: parametrize to include gazeteer
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      TODO found
      Open

        # TODO: Arelize
      Severity: Minor
      Found in app/models/georeference.rb by fixme

      There are no issues that match your filters.

      Category
      Status