Module: Parse::API::PathSegment

Defined in:
lib/parse/api/path_segment.rb

Overview

Helpers for safely interpolating user-controlled segments into REST paths. Every site that builds a request URL via raw string interpolation (‘“functions/#name”`, `“schemas/#className”`, etc.) should route the name through one of these helpers first so a caller passing `“../classes/_User?where=%7B%7D”` cannot traverse to a different endpoint and read it with whatever credentials the outer request was authorized to send.

Constant Summary collapse

IDENTIFIER_PATTERN =

Parse identifier pattern: starts with a letter or underscore (Parse uses leading underscore for system classes like ‘_User`, `_Session`, `_Role`), then alphanumerics and underscores. Matches the documented Parse class/field/function/job naming rules.

/\A[A-Za-z_][A-Za-z0-9_]*\z/.freeze

Class Method Summary collapse

Class Method Details

.file!(value, kind: "filename") ⇒ String

Validate and percent-encode a less-restrictive path segment, used for file names which can contain hyphens, periods, and other filename-safe characters but must never contain a literal ‘/`, `..`, or NUL/control characters.

Parameters:

  • value

    the segment to validate.

  • kind (String) (defaults to: "filename")

    human-readable name for error messages.

Returns:

  • (String)

    percent-encoded segment safe for path interpolation.

Raises:

  • (ArgumentError)

    if blank, contains a slash, is a path- traversal token, or contains control characters.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/parse/api/path_segment.rb', line 58

def file!(value, kind: "filename")
  s = value.to_s
  if s.empty?
    raise ArgumentError, "#{kind} must not be empty"
  end
  if s.include?("/") || s == ".." || s == "."
    raise ArgumentError,
      "#{kind} #{s.inspect} contains path-traversal characters " \
      "(`/`, `.`, or `..`). Names must be a single path segment."
  end
  if s.match?(/[\x00-\x1F\x7F]/)
    raise ArgumentError, "#{kind} #{s.inspect} contains control characters"
  end
  URI.encode_www_form_component(s)
end

.identifier!(value, kind: "name") ⇒ String

Validate a Parse identifier (class name, function name, job name, field name) and return it unchanged. Identifiers are already path-safe under the strict pattern, so no percent-encoding is needed; we just refuse anything that violates the shape.

Parameters:

  • value

    the identifier to validate (anything responding to ‘to_s`).

  • kind (String) (defaults to: "name")

    human-readable name for error messages.

Returns:

  • (String)

    the validated identifier.

Raises:

  • (ArgumentError)

    if blank, contains a slash, contains a dot, or otherwise fails the pattern.



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/parse/api/path_segment.rb', line 35

def identifier!(value, kind: "name")
  s = value.to_s
  if s.empty?
    raise ArgumentError, "#{kind} must not be empty"
  end
  unless IDENTIFIER_PATTERN.match?(s)
    raise ArgumentError,
      "#{kind} #{s.inspect} contains characters that are not allowed in " \
      "a Parse identifier. Names must match /\\A[A-Za-z_][A-Za-z0-9_]*\\z/."
  end
  s
end