Class: SolidObjects::Web::Application

Inherits:
Object
  • Object
show all
Extended by:
Router
Defined in:
lib/solid_objects/web/application.rb,
sig/generated/lib/solid_objects/web/application.rbs

Overview

The pages. Each route states the administration policy it needs, and call asks that policy before the handler runs, so a page cannot read the actor tables on behalf of an unauthorized request.

Constant Summary collapse

SCRIPT_PLACEHOLDER =

Returns:

  • (::String)
"!script-src!"
CONTENT_SECURITY_POLICY =

Returns:

  • (Object)
[
  "default-src 'self'",
  "base-uri 'self'",
  "form-action 'self'",
  "frame-ancestors 'none'",
  "img-src 'self' data:",
  "style-src 'self'",
  "script-src #{SCRIPT_PLACEHOLDER}",
  "connect-src 'self'",
  "object-src 'none'"
].join("; ").freeze
MAILBOX_MEMBERSHIPS =

Returns:

  • (Object)
%w[ready claimed].freeze
RECENT_LIMIT =

Returns:

  • (::Integer)
10
CHART_TYPE_LIMIT =

Returns:

  • (::Integer)
12

Instance Method Summary collapse

Methods included from Router

get, head, match, post, route, routes

Instance Method Details

#authorized?(action) ⇒ Boolean

RBS:

  • (Action) -> bool

Parameters:

Returns:

  • (Boolean)


196
197
198
199
200
201
202
203
204
# File 'lib/solid_objects/web/application.rb', line 196

def authorized?(action)
  policy = action.route.policy
  SolidObjects.configuration.authorize_administration.call(
    action: policy.fetch(:action),
    resource: policy.fetch(:resource),
    resource_id: action.route_params(:id),
    authorization_context: action
  )
end

#call(env) ⇒ Array[untyped]

RBS:

  • (Hash[String, untyped]) -> Array[untyped]

Parameters:

  • (Hash[String, untyped])

Returns:

  • (Array[untyped])


174
175
176
177
178
179
180
181
182
183
184
# File 'lib/solid_objects/web/application.rb', line 174

def call(env)
  route = self.class.match(env["REQUEST_METHOD"].to_s, env["PATH_INFO"].to_s)
  return not_found unless route

  action = Action.new(env:, route:)
  return forbidden unless authorized?(action)

  respond(action, catch(:halt) { action.call })
rescue Unauthorized
  forbidden
end

#content_security_policy(env) ⇒ String

The chart host is named only when one is configured, so a deployment that vendors the library or turns charts off never advertises a third party origin it does not use.

RBS:

  • (Hash[String, untyped]) -> String

Parameters:

  • (Hash[String, untyped])

Returns:

  • (String)


221
222
223
224
# File 'lib/solid_objects/web/application.rb', line 221

def content_security_policy(env)
  sources = [ "'self'", "'nonce-#{env[Web::NONCE_KEY]}'", Web.chart_library_origin ].compact
  CONTENT_SECURITY_POLICY.sub(SCRIPT_PLACEHOLDER, sources.join(" "))
end

#forbiddenArray[untyped]

RBS:

  • () -> Array[untyped]

Returns:

  • (Array[untyped])


234
235
236
# File 'lib/solid_objects/web/application.rb', line 234

def forbidden
  [ 403, { "content-type" => "text/plain" }, [ "Forbidden" ] ]
end

#not_foundArray[untyped]

The cascade header lets a host application serve its own 404 for a path below the mount that the dashboard does not define.

RBS:

  • () -> Array[untyped]

Returns:

  • (Array[untyped])


229
230
231
# File 'lib/solid_objects/web/application.rb', line 229

def not_found
  [ 404, { "content-type" => "text/plain", "x-cascade" => "pass" }, [ "Not Found" ] ]
end

#page_headers(env) ⇒ Hash[String, String]

RBS:

  • (Hash[String, untyped]) -> Hash[String, String]

Parameters:

  • (Hash[String, untyped])

Returns:

  • (Hash[String, String])


207
208
209
210
211
212
213
214
215
# File 'lib/solid_objects/web/application.rb', line 207

def page_headers(env)
  {
    "content-type" => "text/html; charset=utf-8",
    "cache-control" => "private, no-store",
    "content-security-policy" => content_security_policy(env),
    "x-content-type-options" => "nosniff",
    "referrer-policy" => "same-origin"
  }
end

#respond(action, result) ⇒ Array[untyped]

RBS:

  • (Action, untyped) -> Array[untyped]

Parameters:

Returns:

  • (Array[untyped])


189
190
191
192
193
# File 'lib/solid_objects/web/application.rb', line 189

def respond(action, result)
  return result if result.is_a?(Array)

  [ action.response_status, page_headers(action.env), [ result.to_s ] ]
end