I have a group, which I can attach to other modules. The group can have a parent group:
schema "groups" do
field :name, :string
field :deleted, :boolean
belongs_to :parent, Group
has_many :users_groups, UserGroup, foreign_key: :group_id
timestamps()
end
Via user_groups i Can attach users. Now I want to filter, if the user is allowed to see the attached module. I made a check, to see if the user is inside the attached group:
def get_visible_module(module, user_id) do
case module.group do
nil -> module
_ ->
case module.group.users_groups do
nil -> module
_ ->
val = Enum.filter(module.group.users_groups, fn(x)->
x.user_id == user_id
end)
case val do
[] ->
case false do
true -> module
false -> nil
end
_ -> module
end
end
end
end
This may be not the best code, but I am still learning, so improvements to this part are also welcome :)
Now my problem is to add a recursion to check, if the user_id is attached via user_group to a group, which is attached via the parent_id. I am stucked at this point. For the understanding: A module has a group attached. Only the user in the group or in the group attached via parent_id are allowed to see the module. Groups are structered as a tree, so I need to eager load the parent group and check if the user_group contains the user and check every parent-group too.
Hope it is understandable. THX
Here is a rough skeleton which adapts the naming of your source code. It should give you an idea on how to make a recursion in elixir.
# Exit case when a module has no more parent
def get_visible_module(module, nil, user_id) do
user_in_groups?(module.group.users_groups, user_id)
end
# Case when the module has a parent_id
def get_visible_module(module, parent_id, user_id) do
# check the groups for user_id permission followed by the recusive part
user_in_groups?(module.group.users_groups, user_id) and get_visible_module(parent_module, parent_module.parent_id, user_id)
end
# checks if the user is in the group
defp user_in_groups?(users_groups, user_id) do
# check if the use is in one of the groups
true
end
As @bla already mentioned you should try to use pattern matching to clean up your code and reduce the nesting level of your code.