zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

commit 6cb36010f9aadfdf833131b4e6b0b7744d9e1d69
parent 1a5ce574399d1e862d80412ee88a9ef38ff96779
Author: sir fish <dev@srf.sh>
Date:   Mon, 17 Oct 2022 14:16:20 +0000

Merge pull request #25 from dyne/srfsh/filter

Add resource name filters
Diffstat:
Msrc/zenflows/db/filter.ex | 23++++++++++++++++++++++-
Msrc/zenflows/vf/person/filter.ex | 47+++++++++++++----------------------------------
Msrc/zenflows/vf/proposal/filter.ex | 43++++++++++++++++++++++---------------------
Msrc/zenflows/vf/proposal/type.ex | 2++
4 files changed, 59 insertions(+), 56 deletions(-)

diff --git a/src/zenflows/db/filter.ex b/src/zenflows/db/filter.ex @@ -18,11 +18,32 @@ defmodule Zenflows.DB.Filter do @moduledoc "Filtering helpers for Filter modules." +alias Ecto.Changeset + @type params() :: %{atom() => term()} -@type error() :: {:error, Ecto.Changeset.t()} +@type error() :: {:error, Changeset.t()} @type result() :: {:ok, Ecto.Query.t()} | error() def escape_like(v) do Regex.replace(~r/\\|%|_/, v, &"\\#{&1}") end + +@doc """ +Changeset helper to check that `a` and `b` are not provided at the same time. +""" +@spec check_xor(Changeset.t(), atom(), atom()) :: Changeset.t() +def check_xor(cset, a, b) do + x = Changeset.get_change(cset, a) + y = Changeset.get_change(cset, b) + + if x && y do + msg = "can't provide both" + + cset + |> Changeset.add_error(a, msg) + |> Changeset.add_error(b, msg) + else + cset + end +end end diff --git a/src/zenflows/vf/person/filter.ex b/src/zenflows/vf/person/filter.ex @@ -41,52 +41,31 @@ end @spec f(Query.t(), {atom(), term()}) :: Query.t() defp f(q, {:name, v}), do: where(q, [x], ilike(x.name, ^"%#{Filter.escape_like(v)}%")) +defp f(q, {:or_name, v}), + do: or_where(q, [x], ilike(x.name, ^"%#{Filter.escape_like(v)}%")) defp f(q, {:user, v}), do: where(q, [x], ilike(x.user, ^"%#{Filter.escape_like(v)}%")) -defp f(q, {:user_or_name, v}) do - v = "%#{Filter.escape_like(v)}%" - where(q, [x], ilike(x.user, ^v) or ilike(x.name, ^v)) -end +defp f(q, {:or_user, v}), + do: or_where(q, [x], ilike(x.user, ^"%#{Filter.escape_like(v)}%")) embedded_schema do field :name, :string + field :or_name, :string field :user, :string - field :user_or_name, :string + field :or_user, :string end +@cast ~w[name or_name user or_user]a + @spec chgset(params()) :: Changeset.t() defp chgset(params) do %__MODULE__{} - |> Changeset.cast(params, ~w[name user user_or_name]a) + |> Changeset.cast(params, @cast) |> Validate.name(:name) + |> Validate.name(:or_name) |> Validate.name(:user) - |> Validate.name(:user_or_name) - |> user_or_name_mutex() -end - -# Validate that `user_or_name` is mutually exclusive with either `user` -# or `name`. -@spec user_or_name_mutex(Changeset.t()) :: Changeset.t() -defp user_or_name_mutex(cset) do - name = Changeset.get_change(cset, :name) - user = Changeset.get_change(cset, :user) - user_or_name = Changeset.get_change(cset, :user_or_name) - - cond do - user_or_name && user -> - msg = "user-or-name and user can't be used together" - cset - |> Changeset.add_error(:user_or_name, msg) - |> Changeset.add_error(:user, msg) - - user_or_name && name -> - msg = "user-or-name and name can't be used together" - cset - |> Changeset.add_error(:user_or_name, msg) - |> Changeset.add_error(:name, msg) - - true -> - cset - end + |> Validate.name(:or_user) + |> Filter.check_xor(:name, :or_name) + |> Filter.check_xor(:user, :or_user) end end diff --git a/src/zenflows/vf/proposal/filter.ex b/src/zenflows/vf/proposal/filter.ex @@ -67,7 +67,17 @@ end defp f(q, {:or_primary_intents_resource_inventoried_as_classified_as, v}) do q |> join(:primary_intents_resource_inventoried_as) - |> where([primary_intents_resource_inventoried_as: r], fragment("? @> ?", r.classified_as, ^v)) + |> or_where([primary_intents_resource_inventoried_as: r], fragment("? @> ?", r.classified_as, ^v)) +end +defp f(q, {:primary_intents_resource_inventoried_as_name, v}) do + q + |> join(:primary_intents_resource_inventoried_as) + |> where([primary_intents_resource_inventoried_as: r], ilike(r.name, ^"%#{Filter.escape_like(v)}%")) +end +defp f(q, {:or_primary_intents_resource_inventoried_as_name, v}) do + q + |> join(:primary_intents_resource_inventoried_as) + |> or_where([primary_intents_resource_inventoried_as: r], ilike(r.name, ^"%#{Filter.escape_like(v)}%")) end # join primary_intents @@ -92,6 +102,8 @@ embedded_schema do field :or_primary_intents_resource_inventoried_as_primary_accountable, {:array, ID} field :primary_intents_resource_inventoried_as_classified_as, {:array, :string} field :or_primary_intents_resource_inventoried_as_classified_as, {:array, :string} + field :primary_intents_resource_inventoried_as_name, :string + field :or_primary_intents_resource_inventoried_as_name, :string end @cast ~w[ @@ -101,6 +113,8 @@ end or_primary_intents_resource_inventoried_as_primary_accountable primary_intents_resource_inventoried_as_classified_as or_primary_intents_resource_inventoried_as_classified_as + primary_intents_resource_inventoried_as_name + or_primary_intents_resource_inventoried_as_name ]a @spec chgset(params()) :: Changeset.t() @@ -113,28 +127,15 @@ defp chgset(params) do |> Validate.class(:or_primary_intents_resource_inventoried_as_primary_accountable) |> Validate.class(:primary_intents_resource_inventoried_as_classified_as) |> Validate.class(:or_primary_intents_resource_inventoried_as_classified_as) - |> check_xor(:primary_intents_resource_inventoried_as_conforms_to, + |> Validate.name(:primary_intents_resource_inventoried_name) + |> Validate.name(:or_primary_intents_resource_inventoried_name) + |> Filter.check_xor(:primary_intents_resource_inventoried_as_conforms_to, :or_primary_intents_resource_inventoried_as_conforms_to) - |> check_xor(:primary_intents_resource_inventoried_as_primary_accountable, + |> Filter.check_xor(:primary_intents_resource_inventoried_as_primary_accountable, :or_primary_intents_resource_inventoried_as_primary_accountable) - |> check_xor(:primary_intents_resource_inventoried_as_classified_as, + |> Filter.check_xor(:primary_intents_resource_inventoried_as_classified_as, :or_primary_intents_resource_inventoried_as_classified_as) -end - -# Check that `a` and `b` are not provided at the same time. -@spec check_xor(Changeset.t(), atom(), atom()) :: Changeset.t() -defp check_xor(cset, a, b) do - x = Changeset.get_change(cset, a) - y = Changeset.get_change(cset, b) - - if x && y do - msg = "can't provide both" - - cset - |> Changeset.add_error(a, msg) - |> Changeset.add_error(b, msg) - else - cset - end + |> Filter.check_xor(:primary_intents_resource_inventoried_as_name, + :or_primary_intents_resource_inventoried_as_name) end end diff --git a/src/zenflows/vf/proposal/type.ex b/src/zenflows/vf/proposal/type.ex @@ -137,6 +137,8 @@ input_object :proposal_filter_params do field :or_primary_intents_resource_inventoried_as_primary_accountable, list_of(non_null(:id)) field :primary_intents_resource_inventoried_as_classified_as, list_of(non_null(:uri)) field :or_primary_intents_resource_inventoried_as_classified_as, list_of(non_null(:uri)) + field :primary_intents_resource_inventoried_as_name, :string + field :or_primary_intents_resource_inventoried_as_name, :string end object :query_proposal do