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
TRIGGER_CLASS_PATTERN =

Parse trigger className pattern: a normal identifier, OR one of Parse Server's @-prefixed pseudo-classes (@File for file triggers, @Connect for the connection-global LiveQuery trigger). The optional leading @ is the only relaxation; the rest stays path-safe (no /, ., or ..).

/\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.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/parse/api/path_segment.rb', line 91

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

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

Validate a className used in a webhook-trigger path (hooks/triggers/<className>/<trigger>). Same as identifier! but additionally accepts the @File / @Connect pseudo-classes that Parse Server uses for file and connection triggers. create_trigger carries the className in the request BODY (not the path), so it already accepts these; this keeps fetch / update / delete symmetric with create.

Parameters:

  • value

    the className to validate.

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

    human-readable name for error messages.

Returns:

  • (String)

    the validated className.

Raises:

  • (ArgumentError)

    if blank or otherwise fails the pattern.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/parse/api/path_segment.rb', line 66

def trigger_class_name!(value, kind: "class name")
  s = value.to_s
  if s.empty?
    raise ArgumentError, "#{kind} must not be empty"
  end
  unless TRIGGER_CLASS_PATTERN.match?(s)
    raise ArgumentError,
      "#{kind} #{s.inspect} contains characters that are not allowed in " \
      "a Parse trigger class name. Names must match " \
      "/\\A@?[A-Za-z_][A-Za-z0-9_]*\\z/ (an identifier, optionally an " \
      "@-prefixed pseudo-class such as @File or @Connect)."
  end
  s
end