Ensure version increments
This commit is contained in:
parent
affd255daf
commit
56e3d11807
5 changed files with 92 additions and 35 deletions
|
@ -13,21 +13,22 @@ defmodule Pleroma.Akkoma.FrontendSettingProfile do
|
|||
field(:frontend_name, :string, primary_key: true)
|
||||
field(:profile_name, :string, primary_key: true)
|
||||
field(:settings, :map)
|
||||
field(:version, :integer, default: 1)
|
||||
field(:version, :integer)
|
||||
timestamps()
|
||||
end
|
||||
|
||||
def changeset(%__MODULE__{} = struct, attrs) do
|
||||
struct
|
||||
|> cast(attrs, [:user_id, :frontend_name, :profile_name, :settings])
|
||||
|> validate_required([:user_id, :frontend_name, :profile_name, :settings])
|
||||
|> cast(attrs, [:user_id, :frontend_name, :profile_name, :settings, :version])
|
||||
|> validate_required([:user_id, :frontend_name, :profile_name, :settings, :version])
|
||||
|> validate_length(:frontend_name, min: 1, max: 255)
|
||||
|> validate_length(:profile_name, min: 1, max: 255)
|
||||
|> validate_version()
|
||||
|> validate_version(struct)
|
||||
|> validate_number(:version, greater_than: 0)
|
||||
|> validate_settings_length(Config.get([:instance, :max_frontend_settings_json_chars]))
|
||||
end
|
||||
|
||||
def create_or_update(%User{} = user, frontend_name, profile_name, settings) do
|
||||
def create_or_update(%User{} = user, frontend_name, profile_name, settings, version) do
|
||||
struct =
|
||||
case get_by_user_and_frontend_name_and_profile_name(user, frontend_name, profile_name) do
|
||||
nil ->
|
||||
|
@ -42,7 +43,8 @@ def create_or_update(%User{} = user, frontend_name, profile_name, settings) do
|
|||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings
|
||||
settings: settings,
|
||||
version: version
|
||||
})
|
||||
|> Repo.insert_or_update()
|
||||
end
|
||||
|
@ -80,12 +82,14 @@ defp validate_settings_length(
|
|||
end
|
||||
end
|
||||
|
||||
defp validate_version(%Ecto.Changeset{changes: %{version: version}} = changeset) do
|
||||
IO.inspect(changeset)
|
||||
if version < 1 do
|
||||
add_error(changeset, :version, "must be greater than 0")
|
||||
defp validate_version(changeset, %{version: nil}), do: changeset
|
||||
|
||||
defp validate_version(%Ecto.Changeset{changes: %{version: version}} = changeset, %{version: prev_version}) do
|
||||
if version != prev_version + 1 do
|
||||
add_error(changeset, :version, "must be incremented by 1")
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -44,8 +44,8 @@ def list_profiles(conn, %{frontend_name: frontend_name}) do
|
|||
end
|
||||
|
||||
@doc "PUT /api/v1/akkoma/frontend_settings/:frontend_name/:profile_name"
|
||||
def update_profile(conn, %{frontend_name: frontend_name, profile_name: profile_name, settings: settings}) do
|
||||
with {:ok, profile} <- FrontendSettingProfile.create_or_update(conn.assigns.user, frontend_name, profile_name, settings) do
|
||||
def update_profile(%{body_params: %{settings: settings, version: version}} = conn, %{frontend_name: frontend_name, profile_name: profile_name}) do
|
||||
with {:ok, profile} <- FrontendSettingProfile.create_or_update(conn.assigns.user, frontend_name, profile_name, settings, version) do
|
||||
conn
|
||||
|> json(profile.settings)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
defmodule Pleroma.Web.ApiSpec.FrontendSettingsOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
@spec open_api_operation(atom) :: Operation.t()
|
||||
def open_api_operation(action) do
|
||||
|
@ -51,10 +52,12 @@ def update_profile_operation() do
|
|||
operationId: "AkkomaAPI.FrontendSettingsController.update_profile_operation",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
parameters: [frontend_name_param(), profile_name_param()],
|
||||
requestBody: request_body_param,
|
||||
requestBody: profile_body_param(),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Translation", "application/json", %Schema{type: :object})
|
||||
Operation.response("Settings", "application/json", %Schema{type: :object}),
|
||||
422 =>
|
||||
Operation.response("Invalid", "application/json", %Schema{type: :object})
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -74,6 +77,27 @@ def profile_name_param do
|
|||
end
|
||||
|
||||
def profile_body_param do
|
||||
request_body("Settings", %Schema{type: :object}, required: true),
|
||||
request_body("Settings",
|
||||
%Schema{
|
||||
title: "Frontend Setting Profile",
|
||||
type: :object,
|
||||
required: [:version, :settings],
|
||||
properties: %{
|
||||
version: %Schema{
|
||||
type: :integer,
|
||||
description: "Version of the profile, must increment by 1 each time",
|
||||
example: 1
|
||||
},
|
||||
settings: %Schema{
|
||||
type: :object,
|
||||
description: "Settings of the profile",
|
||||
example: %{
|
||||
theme: "dark",
|
||||
locale: "en"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
required: true)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,8 @@ test "valid" do
|
|||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings
|
||||
settings: settings,
|
||||
version: 1
|
||||
}
|
||||
|
||||
assert %{valid?: true} = FrontendSettingProfile.changeset(struct, attrs)
|
||||
|
@ -35,7 +36,8 @@ test "when settings is too long" do
|
|||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings
|
||||
settings: settings,
|
||||
version: 1
|
||||
}
|
||||
|
||||
assert %{valid?: false, errors: [settings: {"is too long", _}]} =
|
||||
|
@ -53,7 +55,8 @@ test "when frontend name is too short" do
|
|||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings
|
||||
settings: settings,
|
||||
version: 1
|
||||
}
|
||||
|
||||
assert %{valid?: false, errors: [frontend_name: {"can't be blank", _}]} =
|
||||
|
@ -71,12 +74,32 @@ test "when profile name is too short" do
|
|||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings
|
||||
settings: settings,
|
||||
version: 1
|
||||
}
|
||||
|
||||
assert %{valid?: false, errors: [profile_name: {"can't be blank", _}]} =
|
||||
FrontendSettingProfile.changeset(struct, attrs)
|
||||
end
|
||||
|
||||
test "when version is negative" do
|
||||
user = insert(:user)
|
||||
frontend_name = "test"
|
||||
profile_name = "test"
|
||||
settings = %{"test" => "test"}
|
||||
struct = %FrontendSettingProfile{}
|
||||
|
||||
attrs = %{
|
||||
user_id: user.id,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: settings,
|
||||
version: -1
|
||||
}
|
||||
|
||||
assert %{valid?: false, errors: [version: {"must be greater than %{number}", _}]} =
|
||||
FrontendSettingProfile.changeset(struct, attrs)
|
||||
end
|
||||
end
|
||||
|
||||
describe "create_or_update/2" do
|
||||
|
@ -91,7 +114,8 @@ test "it should create a new record" do
|
|||
user,
|
||||
frontend_name,
|
||||
profile_name,
|
||||
settings
|
||||
settings,
|
||||
1
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -104,7 +128,8 @@ test "it should update a record" do
|
|||
user: user,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: %{"test" => "test"}
|
||||
settings: %{"test" => "test"},
|
||||
version: 1
|
||||
)
|
||||
|
||||
settings = %{"test" => "test2"}
|
||||
|
@ -114,7 +139,8 @@ test "it should update a record" do
|
|||
user,
|
||||
frontend_name,
|
||||
profile_name,
|
||||
settings
|
||||
settings,
|
||||
2
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -128,14 +154,16 @@ test "it should return all records" do
|
|||
user: user,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: "profileA",
|
||||
settings: %{"test" => "test"}
|
||||
settings: %{"test" => "test"},
|
||||
version: 1
|
||||
)
|
||||
|
||||
insert(:frontend_setting_profile,
|
||||
user: user,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: "profileB",
|
||||
settings: %{"test" => "test"}
|
||||
settings: %{"test" => "test"},
|
||||
version: 1
|
||||
)
|
||||
|
||||
assert [%FrontendSettingProfile{profile_name: "profileA"}, %{profile_name: "profileB"}] =
|
||||
|
@ -153,7 +181,8 @@ test "it should return a record" do
|
|||
user: user,
|
||||
frontend_name: frontend_name,
|
||||
profile_name: profile_name,
|
||||
settings: %{"test" => "test"}
|
||||
settings: %{"test" => "test"},
|
||||
version: 1
|
||||
)
|
||||
|
||||
assert %FrontendSettingProfile{profile_name: "profileA"} =
|
||||
|
|
|
@ -46,25 +46,25 @@ test "it returns 200 if found" do
|
|||
describe "PUT /api/v1/akkoma/frontend_settings/:frontend_name/:profile_name" do
|
||||
test "puts a config" do
|
||||
%{conn: conn, user: user} = oauth_access(["write"])
|
||||
|
||||
settings = %{"test" => "test2"}
|
||||
response =
|
||||
conn
|
||||
|> put("/api/v1/akkoma/frontend_settings/test/test1", %{"settings" => %{"test" => "test2"}, "version" => 1})
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/akkoma/frontend_settings/test/test1", %{"settings" => settings, "version" => 1})
|
||||
|> json_response_and_validate_schema(200)
|
||||
assert response == %{"test" => "test2"}
|
||||
%FrontendSettingProfile{settings: settings} = FrontendSettingProfile.get_by_user_and_frontend_name_and_profile_name(user, "test", "test1")
|
||||
|
||||
assert response == settings
|
||||
assert %FrontendSettingProfile{settings: ^settings} = FrontendSettingProfile.get_by_user_and_frontend_name_and_profile_name(user, "test", "test1")
|
||||
end
|
||||
|
||||
test "refuses to overwrite a newer config" do
|
||||
%{conn: conn, user: user} = oauth_access(["write"])
|
||||
insert(:frontend_setting_profile, user: user, frontend_name: "test", profile_name: "test1", settings: %{"test" => "test"}, version: 2)
|
||||
response =
|
||||
conn
|
||||
|> put("/api/v1/akkoma/frontend_settings/test/test1", %{"settings" => %{"test" => "test2"}, "version" => 1})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response == %{"test" => "test2"}
|
||||
%FrontendSettingProfile{settings: settings} = FrontendSettingProfile.get_by_user_and_frontend_name_and_profile_name(user, "test", "test1")
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/akkoma/frontend_settings/test/test1", %{"settings" => %{"test" => "test2"}, "version" => 1})
|
||||
|> json_response_and_validate_schema(422)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue