ohauthcat 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +35 -0
- data/README.md +94 -0
- data/THIRD_PARTY_LICENSES +5 -0
- data/lib/ohauthcat/access_policy.rb +14 -0
- data/lib/ohauthcat/client.rb +333 -0
- data/lib/ohauthcat/errors.rb +98 -0
- data/lib/ohauthcat/generated.rb +2898 -0
- data/lib/ohauthcat/model.rb +129 -0
- data/lib/ohauthcat/models.rb +5127 -0
- data/lib/ohauthcat/passkey_helpers.rb +53 -0
- data/lib/ohauthcat/route.rb +6 -0
- data/lib/ohauthcat/sso_helpers.rb +100 -0
- data/lib/ohauthcat/standby.rb +129 -0
- data/lib/ohauthcat/version.rb +5 -0
- data/lib/ohauthcat/webhooks.rb +97 -0
- data/lib/ohauthcat.rb +20 -0
- metadata +58 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OhAuthCat
|
|
4
|
+
# Base of every generated model. A model wraps its JSON Hash, so unknown fields are kept and
|
|
5
|
+
# #to_h is always available as an escape hatch. Typed readers and writers use that Hash.
|
|
6
|
+
class Model
|
|
7
|
+
REGISTRY = {}
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
attr_reader :model_name, :fields, :required_fields
|
|
11
|
+
|
|
12
|
+
def model(name, required: [])
|
|
13
|
+
@model_name = name
|
|
14
|
+
@fields = {}
|
|
15
|
+
@required_fields = required.freeze
|
|
16
|
+
REGISTRY[name] = self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def field(member, json_name, desc)
|
|
20
|
+
@fields[json_name] = desc
|
|
21
|
+
define_method(member) { Model.decode(@json[json_name], desc) }
|
|
22
|
+
define_method(:"#{member}=") { |value| @json[json_name] = Model.encode(value) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Validates decoded JSON and wraps it.
|
|
26
|
+
def from_json(value)
|
|
27
|
+
Model.validate(value, "M#{model_name}", model_name, present: true)
|
|
28
|
+
new(value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def wrap(hash)
|
|
32
|
+
new(hash)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize(json = {})
|
|
37
|
+
@json = json.transform_keys(&:to_s)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The underlying JSON Hash: every field, including ones this SDK version does not know.
|
|
41
|
+
def to_h
|
|
42
|
+
@json
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def [](key)
|
|
46
|
+
@json[key.to_s]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def to_json(*args)
|
|
50
|
+
@json.to_json(*args)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ==(other)
|
|
54
|
+
other.is_a?(Model) && other.class == self.class && other.to_h == @json
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def inspect
|
|
58
|
+
"#<#{self.class.model_name} #{@json.keys.join(", ")}>"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.invalid(path)
|
|
62
|
+
::OhAuthCat::Error.new("The response does not match the API schema at #{path}", code: "response_invalid")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.validate(value, desc, path, present: true)
|
|
66
|
+
nullable = desc.start_with?("?")
|
|
67
|
+
d = nullable ? desc[1..] : desc
|
|
68
|
+
if value.nil?
|
|
69
|
+
return if nullable || !present
|
|
70
|
+
|
|
71
|
+
raise invalid(path)
|
|
72
|
+
end
|
|
73
|
+
case d[0]
|
|
74
|
+
when "s" then raise invalid(path) unless value.is_a?(String)
|
|
75
|
+
when "i" then raise invalid(path) unless value.is_a?(Integer)
|
|
76
|
+
when "n" then raise invalid(path) unless value.is_a?(Numeric)
|
|
77
|
+
when "b" then raise invalid(path) unless [true, false].include?(value)
|
|
78
|
+
when "j" then nil
|
|
79
|
+
when "L"
|
|
80
|
+
raise invalid(path) unless value.is_a?(Array)
|
|
81
|
+
|
|
82
|
+
value.each_with_index { |item, i| validate(item, d[1..], "#{path}[#{i}]") }
|
|
83
|
+
when "D"
|
|
84
|
+
raise invalid(path) unless value.is_a?(Hash)
|
|
85
|
+
|
|
86
|
+
value.each { |k, v| validate(v, d[1..], "#{path}.#{k}") }
|
|
87
|
+
when "M"
|
|
88
|
+
klass = REGISTRY[d[1..]]
|
|
89
|
+
raise invalid(path) unless klass && value.is_a?(Hash)
|
|
90
|
+
|
|
91
|
+
klass.required_fields.each { |f| raise invalid("#{path}.#{f}") unless value.key?(f) }
|
|
92
|
+
klass.fields.each do |name, field_desc|
|
|
93
|
+
next unless value.key?(name)
|
|
94
|
+
# Optional fields may be null even when the schema does not say so.
|
|
95
|
+
next if value[name].nil? && !klass.required_fields.include?(name)
|
|
96
|
+
|
|
97
|
+
validate(value[name], field_desc, "#{path}.#{name}")
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
raise invalid(path)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def self.decode(value, desc)
|
|
105
|
+
return value if value.nil?
|
|
106
|
+
|
|
107
|
+
d = desc.delete_prefix("?")
|
|
108
|
+
case d[0]
|
|
109
|
+
when "n" then value.is_a?(Numeric) ? value.to_f : value
|
|
110
|
+
when "L" then value.is_a?(Array) ? value.map { |item| decode(item, d[1..]) } : value
|
|
111
|
+
when "D" then value.is_a?(Hash) ? value.transform_values { |item| decode(item, d[1..]) } : value
|
|
112
|
+
when "M"
|
|
113
|
+
klass = REGISTRY[d[1..]]
|
|
114
|
+
klass && value.is_a?(Hash) ? klass.wrap(value) : value
|
|
115
|
+
else value
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Converts typed values (models, arrays, hashes) back into plain JSON values.
|
|
120
|
+
def self.encode(value)
|
|
121
|
+
case value
|
|
122
|
+
when Model then value.to_h
|
|
123
|
+
when Hash then value.to_h { |k, v| [k.to_s, encode(v)] }
|
|
124
|
+
when Array then value.map { |item| encode(item) }
|
|
125
|
+
else value
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|