1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00
sinatra/rack-protection/lib/rack/protection/base.rb
Vasiliy 8ae87a87f3
Setup Rubocop (#1537)
* Initialize rubocop

* Style/StringLiterals: prefer single quotes

* Style/AndOr: use `&&` and `||`, instead of `and` and `or`

* Style/HashSyntax: use new hash syntax

* Layout/EmptyLineAfterGuardClause: add empty lines after guard clause

* Style/SingleLineMethods: temporary disable

It breaks layout of the code, it is better to fix it manually

* Style/Proc: prefer `proc` vs `Proc.new`

* Disable Lint/AmbiguousBlockAssociation

It affects proc definitions for sinatra DSL

* Disable Style/CaseEquality

* Lint/UnusedBlockArgument: put underscore in front of it

* Style/Alias: prefer alias vs alias_method in a class body

* Layout/EmptyLineBetweenDefs: add empty lines between defs

* Style/ParallelAssignment: don't use parallel assigment

* Style/RegexpLiteral: prefer %r for regular expressions

* Naming/UncommunicativeMethodParamName: fix abbrevs

* Style/PerlBackrefs: disable cop

* Layout/SpaceAfterComma: add missing spaces

* Style/Documentation: disable cop

* Style/FrozenStringLiteralComment: add frozen_string_literal

* Layout/AlignHash: align hash

* Layout/ExtraSpacing: allow for alignment

* Layout/SpaceAroundOperators: add missing spaces

* Style/Not: prefer `!` instead of `not`

* Style/GuardClause: add guard conditions

* Style/MutableConstant: freeze contants

* Lint/IneffectiveAccessModifier: disable cop

* Lint/RescueException: disable cop

* Style/SpecialGlobalVars: disable cop

* Layout/DotPosition: fix position of dot for multiline method chains

* Layout/SpaceInsideArrayLiteralBrackets: don't use spaces inside arrays

* Layout/SpaceInsideBlockBraces: add space for blocks

* Layout/SpaceInsideHashLiteralBraces: add spaces for hashes

* Style/FormatString: use format string syntax

* Style/StderrPuts: `warn` is preferable to `$stderr.puts`

* Bundler/DuplicatedGem: disable cop

* Layout/AlignArray: fix warning

* Lint/AssignmentInCondition: remove assignments from conditions

* Layout/IndentHeredoc: disable cop

* Layout/SpaceInsideParens: remove extra spaces

* Lint/UnusedMethodArgument: put underscore in front of unused arg

* Naming/RescuedExceptionsVariableName: use `e` for exceptions

* Style/CommentedKeyword: put comments before the method

* Style/FormatStringToken: disable cop

* Style/MultilineIfModifier: move condition before the method

* Style/SignalException: prefer `raise` to `fail`

* Style/SymbolArray: prefer %i for array of symbols

* Gemspec/OrderedDependencies: Use alphabetical order for dependencies

* Lint/UselessAccessModifier: disable cop

* Naming/HeredocDelimiterNaming: change delimiter's name

* Style/ClassCheck: prefer `is_a?` to `kind_of?`

* Style/ClassVars: disable cop

* Style/Encoding: remove coding comment

* Style/RedundantParentheses: remove extra parentheses

* Style/StringLiteralsInInterpolation: prefer singl quotes

* Layout/AlignArguments: fix alignment

* Layout/ClosingHeredocIndentation: align heredoc

* Layout/EmptyLineAfterMagicComment: add empty line

* Set RubyVersion for rubocop

* Lint/UselessAssignment: disable cop

* Style/EmptyLiteral: disable cop

Causes test failures

* Minor code-style fixes with --safe-auto-correct option

* Disable the rest of the cops that cause warnings

It would be easier to re-enable them in separate PRs

* Add rubocop check to the default Rake task

* Update to rubocop 1.32.0

* Rubocop updates for rack-protection and sinatra-contrib

* Disable Style/SlicingWithRange cop

* Make suggested updates

Co-authored-by: Jordan Owens <jkowens@gmail.com>
2022-07-31 08:56:44 -04:00

134 lines
3.3 KiB
Ruby

# frozen_string_literal: true
require 'rack/protection'
require 'rack/utils'
require 'digest'
require 'logger'
require 'uri'
module Rack
module Protection
class Base
DEFAULT_OPTIONS = {
reaction: :default_reaction, logging: true,
message: 'Forbidden', encryptor: Digest::SHA1,
session_key: 'rack.session', status: 403,
allow_empty_referrer: true,
report_key: 'protection.failed',
html_types: %w[text/html application/xhtml text/xml application/xml]
}
attr_reader :app, :options
def self.default_options(options)
define_method(:default_options) { super().merge(options) }
end
def self.default_reaction(reaction)
alias_method(:default_reaction, reaction)
end
def default_options
DEFAULT_OPTIONS
end
def initialize(app, options = {})
@app = app
@options = default_options.merge(options)
end
def safe?(env)
%w[GET HEAD OPTIONS TRACE].include? env['REQUEST_METHOD']
end
def accepts?(env)
raise NotImplementedError, "#{self.class} implementation pending"
end
def call(env)
unless accepts? env
instrument env
result = react env
end
result or app.call(env)
end
def react(env)
result = send(options[:reaction], env)
result if (Array === result) && (result.size == 3)
end
def warn(env, message)
return unless options[:logging]
l = options[:logger] || env['rack.logger'] || ::Logger.new(env['rack.errors'])
l.warn(message)
end
def instrument(env)
return unless (i = options[:instrumenter])
env['rack.protection.attack'] = self.class.name.split('::').last.downcase
i.instrument('rack.protection', env)
end
def deny(env)
warn env, "attack prevented by #{self.class}"
[options[:status], { 'Content-Type' => 'text/plain' }, [options[:message]]]
end
def report(env)
warn env, "attack reported by #{self.class}"
env[options[:report_key]] = true
end
def session?(env)
env.include? options[:session_key]
end
def session(env)
return env[options[:session_key]] if session? env
raise "you need to set up a session middleware *before* #{self.class}"
end
def drop_session(env)
session(env).clear if session? env
end
def referrer(env)
ref = env['HTTP_REFERER'].to_s
return if !options[:allow_empty_referrer] && ref.empty?
URI.parse(ref).host || Request.new(env).host
rescue URI::InvalidURIError
end
def origin(env)
env['HTTP_ORIGIN'] || env['HTTP_X_ORIGIN']
end
def random_string(secure = defined? SecureRandom)
secure ? SecureRandom.hex(16) : '%032x' % rand((2**128) - 1)
rescue NotImplementedError
random_string false
end
def encrypt(value)
options[:encryptor].hexdigest value.to_s
end
def secure_compare(a, b)
Rack::Utils.secure_compare(a.to_s, b.to_s)
end
alias default_reaction deny
def html?(headers)
return false unless (header = headers.detect { |k, _v| k.downcase == 'content-type' })
options[:html_types].include? header.last[%r{^\w+/\w+}]
end
end
end
end