Class: Etna::Route

Inherits:
Object
  • Object
show all
Includes:
Instrumentation
Defined in:
lib/etna/route.rb

Constant Summary collapse

NAMED_PARAM =
/:([\w]+)/
GLOB_PARAM =
/\*([\w]+)$/
PARAM_TYPES =
[ NAMED_PARAM, GLOB_PARAM ]
UNSAFE =
/[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Instrumentation

#has_yabeda?, included, #increment_it, #time_it, #with_yabeda_tags

Constructor Details

#initialize(method, route, options, &block) ⇒ Route

Returns a new instance of Route.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/etna/route.rb', line 14

def initialize(method, route, options, &block)
  @method = method
  @action = options[:action]
  @auth = options[:auth]
  @name = route_name(options)
  @route = route.gsub(/\A(?=[^\/])/, '/')
  @block = block
  @match_ext = options[:match_ext]
  @log_redact_keys = options[:log_redact_keys]
  @dont_log = options[:dont_log]
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/etna/route.rb', line 12

def name
  @name
end

Class Method Details

.encode_path_component(path_component) ⇒ Object



58
59
60
61
62
# File 'lib/etna/route.rb', line 58

def self.encode_path_component(path_component)
  form_encoded = URI.encode_www_form_component(path_component)
  # Because of issues #1005, #1006, #1197
  form_encoded.gsub('+', '%20')
end

.path(route, params = nil, &block) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/etna/route.rb', line 46

def self.path(route, params=nil, &block)
  if params
    PARAM_TYPES.reduce(route) do |path,pat|
      path.gsub(pat) do
        params[$1.to_sym].split('/').map { |c| block_given? ? yield(c) : Etna::Route.encode_path_component(c) }.join('/')
      end
    end
  else
    route
  end
end

Instance Method Details

#call(app, request) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/etna/route.rb', line 77

def call(app, request)
  update_params(request)

  tags = {}
  if @action
    tags[:controller], tags[:action] = @action.split('#')
  elsif @name
    tags[:action] = @name
  else
    tags[:action] = @route
  end

  params = request.env['rack.request.params']
  user = request.env['etna.user']
  tags[:user_hash] = user ? hash_user_email(user.email) : 'unknown'
  if params && (params.include?(:project_name) || params.include?('project_name'))
    tags[:project_name] = params[:project_name] || params['project_name']
  end

  with_yabeda_tags(tags) do
    increment_it { Yabeda.etna.visits }
    process_call(app, request)
  end
end

#has_user_constraint?(constraint) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/etna/route.rb', line 159

def has_user_constraint?(constraint)
  @auth && @auth[:user] && @auth[:user][constraint]
end

#hash_user_email(email) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/etna/route.rb', line 102

def hash_user_email(email)
  secret = Etna::Application.instance.config(:user_hash_secret) || 'notsosecret'
  digest = email + secret + Date.today.to_s

  if @name
    digest += @name.to_s
  else
    digest += @route.to_s
  end

  Digest::MD5.hexdigest(digest)
end

#ignore_janus?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/etna/route.rb', line 155

def ignore_janus?
  @auth && @auth[:ignore_janus]
end

#matches?(request) ⇒ Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/etna/route.rb', line 35

def matches?(request)
  @method == request.request_method && request.path.match(route_regexp)
end

#noauth?Boolean

the route does not require authorization

Returns:

  • (Boolean)


151
152
153
# File 'lib/etna/route.rb', line 151

def noauth?
  @auth && @auth[:noauth]
end

#partsObject



68
69
70
71
72
73
74
75
# File 'lib/etna/route.rb', line 68

def parts
  part_list = PARAM_TYPES.map do |pat|
    "(?:#{pat.source})"
  end
  @route.scan(
    /(?:#{part_list.join('|')})/
  ).flatten.compact
end

#path(params = nil, &block) ⇒ Object



64
65
66
# File 'lib/etna/route.rb', line 64

def path(params=nil, &block)
  self.class.path(@route, params, &block)
end

#process_call(app, request) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/etna/route.rb', line 115

def process_call(app, request)
  unless authorized?(request)
    if cc_available?(request)
      if request.content_type == 'application/json'
        return [ 403, { 'Content-Type' => 'application/json' }, [ { error: 'You are forbidden from performing this action, but you can visit the project home page and request access.' }.to_json ] ]
      else
        return cc_redirect(request)
      end
    end

    return [ 403, { 'Content-Type' => 'application/json' }, [ { error: 'You are forbidden from performing this action.' }.to_json ] ]
  end

  request.env['etna.redact_keys'] = @log_redact_keys
  request.env['etna.dont_log'] = @dont_log

  if @action
    controller, action = @action.split('#')
    controller_class = Kernel.const_get(
      :"#{controller.camel_case}Controller"
    )
    logger = request.env['etna.logger']
    user = request.env['etna.user']

    return controller_class.new(request, action).response
  elsif @block
    application = Etna::Application.find(app.class).class
    controller_class = application.const_defined?(:Controller) ? application.const_get(:Controller) : Etna::Controller

    controller_class.new(request).response(&@block)
  end
end

#to_hashObject



26
27
28
29
30
31
32
33
# File 'lib/etna/route.rb', line 26

def to_hash
  {
    method: @method,
    route: @route,
    name: @name.to_s,
    params: parts
  }.compact
end