Allow user to edit some fields of an item only?

I have a schema with a number of fields, :a, :b and :c. I want the user to be able to edit the field :a only but not be able to edit field :b nor :c, how can I achieve that?

this behavior can be controlled by an admin, so he can allow him to edit :b instead of :a

One standard approach for this is to split the changeset function into two (names are arbitrary):

  • user_changeset - casts only :a
  • admin_changeset - casts :a, :b, :c

Then either choose which one to call in the controller based on current_user, or have totally separate controllers for admins vs regular users.

2 Likes

thanks for the suggestion,

so this might be a generated list of opts given to cast/4

array = [:a]
array = if condition? do
  array ++ [:b]
else
  array
end

then

cast(changeset, attrs, array)

do you have any suggestions?

Yes, stop calling a list an array…

I don’t see You passing current_user… cast should be inside the changeset function

Something like passing a cast array could work, but it has nothing to do with @al2o3cr recommendation.

You should focus on what the changeset function does, not the cast function

1 Like

A typical changeset will cast parameters as well as validating them so trying to over-abstract by passing lists of keys isn’t a good path.

Instead, make separate functions:

def basic_changeset(data, attrs) do
  data
  |> cast(attrs, [:a])
  |> validate_required([:a])
end

def admin_changeset(data, attrs) do
  data
  |> basic_changeset(attrs)
  |> cast(attrs, [:b, :c])
  |> validate_required([:c])
end