mirror of
https://gitea.invidious.io/iv-org/invidious.git
synced 2024-08-15 00:53:41 +00:00
Add support for partial POST to '/api/v1/auth/preferences'
This commit is contained in:
parent
ac957db6d1
commit
da48bbf312
3 changed files with 195 additions and 29 deletions
|
@ -1880,7 +1880,7 @@ post "/data_control" do |env|
|
||||||
end
|
end
|
||||||
|
|
||||||
if body["preferences"]?
|
if body["preferences"]?
|
||||||
user.preferences = Preferences.from_json(body["preferences"].to_json)
|
user.preferences = Preferences.from_json(body["preferences"].to_json, user.preferences)
|
||||||
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", user.preferences.to_json, user.email)
|
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", user.preferences.to_json, user.email)
|
||||||
end
|
end
|
||||||
when "import_youtube"
|
when "import_youtube"
|
||||||
|
@ -4468,7 +4468,7 @@ post "/api/v1/auth/preferences" do |env|
|
||||||
user = env.get("user").as(User)
|
user = env.get("user").as(User)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
preferences = Preferences.from_json(env.request.body || "{}")
|
preferences = Preferences.from_json(env.request.body || "{}", user.preferences)
|
||||||
rescue
|
rescue
|
||||||
preferences = user.preferences
|
preferences = user.preferences
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,49 +1,49 @@
|
||||||
macro db_mapping(mapping)
|
macro db_mapping(mapping)
|
||||||
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_a
|
def to_a
|
||||||
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_type_tuple
|
def self.to_type_tuple
|
||||||
return { {{*mapping.keys.map { |id| "#{id}" }}} }
|
return { {{*mapping.keys.map { |id| "#{id}" }}} }
|
||||||
end
|
end
|
||||||
|
|
||||||
DB.mapping( {{mapping}} )
|
DB.mapping( {{mapping}} )
|
||||||
end
|
end
|
||||||
|
|
||||||
macro json_mapping(mapping)
|
macro json_mapping(mapping)
|
||||||
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_a
|
def to_a
|
||||||
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
||||||
end
|
end
|
||||||
|
|
||||||
JSON.mapping( {{mapping}} )
|
patched_json_mapping( {{mapping}} )
|
||||||
YAML.mapping( {{mapping}} )
|
YAML.mapping( {{mapping}} )
|
||||||
end
|
end
|
||||||
|
|
||||||
macro yaml_mapping(mapping)
|
macro yaml_mapping(mapping)
|
||||||
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_a
|
def to_a
|
||||||
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
return [ {{*mapping.keys.map { |id| "@#{id}".id }}} ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_tuple
|
def to_tuple
|
||||||
return { {{*mapping.keys.map { |id| "@#{id}".id }}} }
|
return { {{*mapping.keys.map { |id| "@#{id}".id }}} }
|
||||||
end
|
end
|
||||||
|
|
||||||
YAML.mapping({{mapping}})
|
YAML.mapping({{mapping}})
|
||||||
end
|
end
|
||||||
|
|
||||||
macro templated(filename, template = "template")
|
macro templated(filename, template = "template")
|
||||||
render "src/invidious/views/#{{{filename}}}.ecr", "src/invidious/views/#{{{template}}}.ecr"
|
render "src/invidious/views/#{{{filename}}}.ecr", "src/invidious/views/#{{{template}}}.ecr"
|
||||||
end
|
end
|
||||||
|
|
||||||
macro rendered(filename)
|
macro rendered(filename)
|
||||||
render "src/invidious/views/#{{{filename}}}.ecr"
|
render "src/invidious/views/#{{{filename}}}.ecr"
|
||||||
end
|
end
|
||||||
|
|
166
src/invidious/helpers/patch_mapping.cr
Normal file
166
src/invidious/helpers/patch_mapping.cr
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
# Overloads https://github.com/crystal-lang/crystal/blob/0.28.0/src/json/from_json.cr#L24
|
||||||
|
def Object.from_json(string_or_io, default) : self
|
||||||
|
parser = JSON::PullParser.new(string_or_io)
|
||||||
|
new parser, default
|
||||||
|
end
|
||||||
|
|
||||||
|
# Adds configurable 'default' to
|
||||||
|
macro patched_json_mapping(_properties_, strict = false)
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
{% _properties_[key] = {type: value} unless value.is_a?(HashLiteral) || value.is_a?(NamedTupleLiteral) %}
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
{% _properties_[key][:key_id] = key.id.gsub(/\?$/, "") %}
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
@{{value[:key_id]}} : {{value[:type]}}{{ (value[:nilable] ? "?" : "").id }}
|
||||||
|
|
||||||
|
{% if value[:setter] == nil ? true : value[:setter] %}
|
||||||
|
def {{value[:key_id]}}=(_{{value[:key_id]}} : {{value[:type]}}{{ (value[:nilable] ? "?" : "").id }})
|
||||||
|
@{{value[:key_id]}} = _{{value[:key_id]}}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:getter] == nil ? true : value[:getter] %}
|
||||||
|
def {{key.id}} : {{value[:type]}}{{ (value[:nilable] ? "?" : "").id }}
|
||||||
|
@{{value[:key_id]}}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:presence] %}
|
||||||
|
@{{value[:key_id]}}_present : Bool = false
|
||||||
|
|
||||||
|
def {{value[:key_id]}}_present?
|
||||||
|
@{{value[:key_id]}}_present
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
def initialize(%pull : ::JSON::PullParser, default = nil)
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
%var{key.id} = nil
|
||||||
|
%found{key.id} = false
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
%location = %pull.location
|
||||||
|
begin
|
||||||
|
%pull.read_begin_object
|
||||||
|
rescue exc : ::JSON::ParseException
|
||||||
|
raise ::JSON::MappingError.new(exc.message, self.class.to_s, nil, *%location, exc)
|
||||||
|
end
|
||||||
|
while %pull.kind != :end_object
|
||||||
|
%key_location = %pull.location
|
||||||
|
key = %pull.read_object_key
|
||||||
|
case key
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
when {{value[:key] || value[:key_id].stringify}}
|
||||||
|
%found{key.id} = true
|
||||||
|
begin
|
||||||
|
%var{key.id} =
|
||||||
|
{% if value[:nilable] || value[:default] != nil %} %pull.read_null_or { {% end %}
|
||||||
|
|
||||||
|
{% if value[:root] %}
|
||||||
|
%pull.on_key!({{value[:root]}}) do
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:converter] %}
|
||||||
|
{{value[:converter]}}.from_json(%pull)
|
||||||
|
{% elsif value[:type].is_a?(Path) || value[:type].is_a?(Generic) %}
|
||||||
|
{{value[:type]}}.new(%pull)
|
||||||
|
{% else %}
|
||||||
|
::Union({{value[:type]}}).new(%pull)
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:root] %}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:nilable] || value[:default] != nil %} } {% end %}
|
||||||
|
rescue exc : ::JSON::ParseException
|
||||||
|
raise ::JSON::MappingError.new(exc.message, self.class.to_s, {{value[:key] || value[:key_id].stringify}}, *%key_location, exc)
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
else
|
||||||
|
{% if strict %}
|
||||||
|
raise ::JSON::MappingError.new("Unknown JSON attribute: #{key}", self.class.to_s, nil, *%key_location, nil)
|
||||||
|
{% else %}
|
||||||
|
%pull.skip
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
%pull.read_next
|
||||||
|
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
{% unless value[:nilable] || value[:default] != nil %}
|
||||||
|
if %var{key.id}.nil? && !%found{key.id} && !::Union({{value[:type]}}).nilable?
|
||||||
|
raise ::JSON::MappingError.new("Missing JSON attribute: {{(value[:key] || value[:key_id]).id}}", self.class.to_s, nil, *%location, nil)
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:nilable] %}
|
||||||
|
{% if value[:default] != nil %}
|
||||||
|
@{{value[:key_id]}} = %found{key.id} ? %var{key.id} : (default.responds_to?(:{{value[:key_id]}}) ? default.{{value[:key_id]}} : {{value[:default]}})
|
||||||
|
{% else %}
|
||||||
|
@{{value[:key_id]}} = %var{key.id}
|
||||||
|
{% end %}
|
||||||
|
{% elsif value[:default] != nil %}
|
||||||
|
@{{value[:key_id]}} = %var{key.id}.nil? ? (default.responds_to?(:{{value[:key_id]}}) ? default.{{value[:key_id]}} : {{value[:default]}}) : %var{key.id}
|
||||||
|
{% else %}
|
||||||
|
@{{value[:key_id]}} = (%var{key.id}).as({{value[:type]}})
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:presence] %}
|
||||||
|
@{{value[:key_id]}}_present = %found{key.id}
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_json(json : ::JSON::Builder)
|
||||||
|
json.object do
|
||||||
|
{% for key, value in _properties_ %}
|
||||||
|
_{{value[:key_id]}} = @{{value[:key_id]}}
|
||||||
|
|
||||||
|
{% unless value[:emit_null] %}
|
||||||
|
unless _{{value[:key_id]}}.nil?
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
json.field({{value[:key] || value[:key_id].stringify}}) do
|
||||||
|
{% if value[:root] %}
|
||||||
|
{% if value[:emit_null] %}
|
||||||
|
if _{{value[:key_id]}}.nil?
|
||||||
|
nil.to_json(json)
|
||||||
|
else
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
json.object do
|
||||||
|
json.field({{value[:root]}}) do
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:converter] %}
|
||||||
|
if _{{value[:key_id]}}
|
||||||
|
{{ value[:converter] }}.to_json(_{{value[:key_id]}}, json)
|
||||||
|
else
|
||||||
|
nil.to_json(json)
|
||||||
|
end
|
||||||
|
{% else %}
|
||||||
|
_{{value[:key_id]}}.to_json(json)
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% if value[:root] %}
|
||||||
|
{% if value[:emit_null] %}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
{% unless value[:emit_null] %}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue