Class: Attio::OAuth::ScopeValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/attio/oauth/scope_validator.rb

Overview

Validates and manages OAuth scopes for Attio API

Defined Under Namespace

Classes: InvalidScopeError

Constant Summary collapse

SCOPE_DEFINITIONS =

Define all valid scopes with their descriptions

{
  # Record scopes
  "record:read" => "Read access to records",
  "record:write" => "Write access to records (includes read)",

  # Object scopes
  "object:read" => "Read access to objects and their configuration",
  "object:write" => "Write access to objects (includes read)",

  # List scopes
  "list:read" => "Read access to lists and list entries",
  "list:write" => "Write access to lists (includes read)",

  # Webhook scopes
  "webhook:read" => "Read access to webhooks",
  "webhook:write" => "Write access to webhooks (includes read)",

  # User scopes
  "user:read" => "Read access to workspace members",

  # Note scopes
  "note:read" => "Read access to notes",
  "note:write" => "Write access to notes (includes read)",

  # Attribute scopes
  "attribute:read" => "Read access to attributes",
  "attribute:write" => "Write access to attributes (includes read)",

  # Comment scopes
  "comment:read" => "Read access to comments",
  "comment:write" => "Write access to comments (includes read)",

  # Task scopes
  "task:read" => "Read access to tasks",
  "task:write" => "Write access to tasks (includes read)"
}.freeze
VALID_SCOPES =

Array of all valid scope strings

SCOPE_DEFINITIONS.keys.freeze
SCOPE_HIERARCHY =

Scope hierarchy - write scopes include read scopes

{
  "record:write" => ["record:read"],
  "object:write" => ["object:read"],
  "list:write" => ["list:read"],
  "webhook:write" => ["webhook:read"],
  "note:write" => ["note:read"],
  "attribute:write" => ["attribute:read"],
  "comment:write" => ["comment:read"],
  "task:write" => ["task:read"]
}.freeze

Class Method Summary collapse

Class Method Details

.description(scope) ⇒ String?

Get the description for a scope

Parameters:

  • scope (String)

    The scope to describe

Returns:

  • (String, nil)

    Description or nil if scope not found



92
93
94
# File 'lib/attio/oauth/scope_validator.rb', line 92

def description(scope)
  SCOPE_DEFINITIONS[scope.to_s]
end

.expand(scopes) ⇒ Object

Expand scopes to include all implied scopes



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/attio/oauth/scope_validator.rb', line 111

def expand(scopes)
  scopes = Array(scopes).map(&:to_s)
  expanded = Set.new(scopes)

  scopes.each do |scope|
    implied = SCOPE_HIERARCHY[scope] || []
    expanded.merge(implied)
  end

  expanded.to_a.sort
end

.group_by_resource(scopes) ⇒ Object

Group scopes by resource type



138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/attio/oauth/scope_validator.rb', line 138

def group_by_resource(scopes)
  scopes = Array(scopes).map(&:to_s)
  grouped = {}

  scopes.each do |scope|
    resource = scope.split(":").first
    grouped[resource] ||= []
    grouped[resource] << scope
  end

  grouped
end

.includes?(scopes, required_scope) ⇒ Boolean

Check if a set of scopes includes a specific permission

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/attio/oauth/scope_validator.rb', line 97

def includes?(scopes, required_scope)
  scopes = Array(scopes).map(&:to_s)
  required = required_scope.to_s

  return true if scopes.include?(required)

  # Check if any scope in the set provides the required scope
  scopes.any? do |scope|
    implied_scopes = SCOPE_HIERARCHY[scope] || []
    implied_scopes.include?(required)
  end
end

.minimize(scopes) ⇒ Object

Get minimal set of scopes (remove redundant read scopes)



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/attio/oauth/scope_validator.rb', line 124

def minimize(scopes)
  scopes = Array(scopes).map(&:to_s)
  minimized = scopes.dup

  SCOPE_HIERARCHY.each do |write_scope, read_scopes|
    if minimized.include?(write_scope)
      minimized -= read_scopes
    end
  end

  minimized.sort
end

.sufficient_for?(scopes, resource:, operation:) ⇒ Boolean

Check if scopes are sufficient for an operation

Returns:

  • (Boolean)


152
153
154
155
# File 'lib/attio/oauth/scope_validator.rb', line 152

def sufficient_for?(scopes, resource:, operation:)
  required_scope = "#{resource}:#{operation}"
  includes?(scopes, required_scope)
end

.valid?(scope) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/attio/oauth/scope_validator.rb', line 85

def valid?(scope)
  VALID_SCOPES.include?(scope.to_s)
end

.validate(scopes) ⇒ Array<String>

Validate that all provided scopes are valid

Parameters:

  • scopes (Array<String>, String)

    Scopes to validate

Returns:

  • (Array<String>)

    Validated scopes

Raises:



65
66
67
68
69
70
71
72
73
74
# File 'lib/attio/oauth/scope_validator.rb', line 65

def validate(scopes)
  scopes = Array(scopes).map(&:to_s)
  invalid_scopes = scopes - VALID_SCOPES

  unless invalid_scopes.empty?
    raise InvalidScopeError, "Invalid scopes: #{invalid_scopes.join(", ")}"
  end

  scopes
end

.validate!(scopes) ⇒ true

Validate scopes and return true if valid

Parameters:

  • scopes (Array<String>, String)

    Scopes to validate

Returns:

  • (true)

Raises:



80
81
82
83
# File 'lib/attio/oauth/scope_validator.rb', line 80

def validate!(scopes)
  validate(scopes)
  true
end