defmodule ElixirLdap.Search do @moduledoc """ Documentation for ElixirLdap.Search """ import ElixirLdap.Collation collation_define @doc """ """ defp is_collation_rule?(collation_rule) do Enum.any?(ElixirLdap.Collation.collation_rules, fn(rule) -> rule == collation_rule end) end @doc """ """ defp to_listchar_atom_key(dn_list) do Enum.map_join(dn_list, ",", fn({key, value}) -> to_string(key) <> "=" <> value end) end @doc """ Search base dn all entry. Search by base dn set in config file. ## Example ElixirLdap.Search.search_base_all(handle) """ def search_base_all(handle) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base_all(handle, base) end @doc """ Search base dn all entry. Use the base DN of the argument. Argument base dn is list. ## Example ElixirLdap.Search.search_base_all(handle, "ou=Server,dc=corporation,dc=home,dc=local") """ def search_base_all(handle, base) when is_list(base) do if is_tuple(List.first(base)) do search_base_all(handle, to_listchar_atom_key(base)) else search_base(handle, base, [filter: :present, type: "objectClass"]) end end @doc """ Search base dn all entry. Use the base DN of the argument. ## Example ElixirLdap.Search.search_base_all(handle, 'ou=Server,dc=corporation,dc=home,dc=local') """ def search_base_all(handle, base) do search_base(handle, base, [filter: :present, type: "objectClass"]) end @doc """ """ def search_single_level_all(handle) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level_all(handle, base) end def search_single_level_all(handle, base) when is_list(base) do if is_tuple(List.first(base)) do search_single_level_all(handle, to_listchar_atom_key(base)) else search_single_level(handle, base, [filter: :present, type: "objectClass"]) end end def search_single_level_all(handle, base) do search_single_level(handle, base, [filter: :present, type: "objectClass"]) end @doc """ """ def search_subtree_all(handle) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree_all(handle, base) end def search_subtree_all(handle, base) when is_list(base) do if is_tuple(List.first(base)) do search_subtree_all(handle, to_listchar_atom_key(base)) else search_subtree(handle, base, [filter: :present, type: "objectClass"]) end end def search_subtree_all(handle, base) do search_subtree(handle, base, [filter: :present, type: "objectClass"]) end @doc """ search base dn entry. Filter will search for equal. ## Exsample ElixirLdap.Search.search_base(handle, [filter: :equal, field: 'ou', name: 'Server']) """ def search_base(handle, [filter: :equal, field: field, name: name]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :equal, field: field, name: name]) end @doc """ search base dn entry. Filter will search for equal. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_base(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :equal, field: 'ou', name: 'Server']) """ def search_base(handle, base, [filter: :equal, field: field, name: name]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), equality_match(field, name), :eldap.derefAlways(), false, search_timeout) end @doc """ search base dn entry. Filter will search on attribute type presence. ## Exsample ElixirLdap.Search.search_base(handle, [filter: :present, type: 'ou']) """ def search_base(handle, [filter: :present, type: type]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :present, type: type]) end @doc """ search base dn entry. Filter will search on attribute type presence. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_base(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :present, type: 'ou']) """ def search_base(handle, base, [filter: :present, type: type]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), present(type), :eldap.derefAlways(), false, search_timeout) end @doc """ search base dn entry. Filter will search greater number. ## Exsample ElixirLdap.Search.search_base(handle, [filter: :greater, type: 'age', value: "22") """ def search_base(handle, [filter: :greater, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :greater, type: type, value: value]) end @doc """ search base dn entry. Filter will search greater number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_base(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :greater, type: 'age', value: "22") """ def search_base(handle, base, [filter: :greater, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), greater_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end @doc """ search base dn entry. Filter will search less number. ## Exsample ElixirLdap.Search.search_base(handle, [filter: :less, type: 'age', value: "22") """ def search_base(handle, [filter: :less, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :less, type: type, value: value]) end @doc """ search base dn entry. Filter will search less number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_base(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :less, type: 'age', value: "22") """ def search_base(handle, base, [filter: :less, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), less_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end def search_base(handle, [filter: :approx, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :approx, type: type, value: value]) end def search_base(handle, base, [filter: :approx, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), approx_match(type, value), :eldap.derefAlways(), false, search_timeout) end def search_base(handle, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) end def search_base(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), extensible_match(value, type, rule, dn_attribute), :eldap.derefAlways(), false, search_timeout) end def search_base(handle, [filter: :strings, type: type, value: value]) when is_tuple(value) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_base(handle, base, [filter: :strings, type: type, value: value]) end def search_base(handle, base, [filter: :strings, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.baseObject(), substrings(type, value), :eldap.derefAlways(), false, search_timeout) end def search_base(_, argument) when is_list(argument) do raise "search base could not be matched. Please check the argument" end def search_base(_, _, argument) when is_list(argument) do raise "search base could not be matched. Please check the argument" end @doc """ search single level entry. Filter will search for equal. ## Exsample ElixirLdap.Search.search_single_level(handle, [filter: :equal, field: 'ou', name: 'Server']) """ def search_single_level(handle, [filter: :equal, field: field, name: name]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :equal, field: field, name: name]) end @doc """ search single level entry. Filter will search for equal. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_single_level(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :equal, field: 'ou', name: 'Server']) """ def search_single_level(handle, base, [filter: :equal, field: field, name: name]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), equality_match(field, name), :eldap.derefAlways(), false, search_timeout) end @doc """ search single level entry. Filter will search on attribute type presence. ## Exsample ElixirLdap.Search.search_single_level(handle, [filter: :present, type: 'ou']) """ def search_single_level(handle, [filter: :present, type: type]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :present, type: type]) end @doc """ search single level entry. Filter will search on attribute type presence. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_single_level(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :present, type: 'ou']) """ def search_single_level(handle, base, [filter: :present, type: type]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), present(type), :eldap.derefAlways(), false, search_timeout) end @doc """ search single level entry. Filter will search greater number. ## Exsample ElixirLdap.Search.search_single_level(handle, [filter: :greater, type: 'age', value: "22") """ def search_single_level(handle, [filter: :greater, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :greater, type: type, value: value]) end @doc """ search single level entry. Filter will search greater number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_single_level(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :greater, type: 'age', value: "22"]) """ def search_single_level(handle, base, [filter: :greater, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), greater_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end @doc """ search single level entry. Filter will search less number. ## Exsample ElixirLdap.Search.search_single_level(handle, [filter: :less, type: 'age', value: "22") """ def search_single_level(handle, [filter: :less, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :less, type: type, value: value]) end @doc """ search single level entry. Filter will search less number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_single_level(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :less, type: 'age', value: "22"]) """ def search_single_level(handle, base, [filter: :less, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), less_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end def search_single_level(handle, [filter: :approx, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :approx, type: type, value: value]) end def search_single_level(handle, base, [filter: :approx, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), approx_match(type, value), :eldap.derefAlways(), false, search_timeout) end def search_single_level(handle, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) end def search_single_level(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), extensible_match(value, type, rule, dn_attribute), :eldap.derefAlways(), false, search_timeout) end def search_single_level(handle, [filter: :strings, type: type, value: value]) when is_tuple(value) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_single_level(handle, base, [filter: :strings, type: type, value: value]) end def search_single_level(handle, base, [filter: :strings, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.singleLevel(), substrings(type, value), :eldap.derefAlways(), false, search_timeout) end @doc """ search sub tree entry. Filter will search for equal. ## Exsample ElixirLdap.Search.search_subtree(handle, [filter: :equal, field: 'ou', name: 'Server']) """ def search_subtree(handle, [filter: :equal, field: field, name: name]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :equal, field: field, name: name]) end @doc """ search sub tree entry. Filter will search for equal. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_subtree(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :equal, field: 'ou', name: 'Server']) """ def search_subtree(handle, base, [filter: :equal, field: field, name: name]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), equality_match(field, name), :eldap.derefAlways(), false, search_timeout) end @doc """ search sub tree entry. Filter will search on attribute type presence. ## Exsample ElixirLdap.Search.search_subtree(handle, [filter: :present, type: 'ou']) """ def search_subtree(handle, [filter: :present, type: type]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :present, type: type]) end @doc """ search sub tree entry. Filter will search on attribute type presence. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_subtree(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :present, type: 'ou']) """ def search_subtree(handle, base, [filter: :present, type: type]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), present(type), :eldap.derefAlways(), false, search_timeout) end @doc """ search sub tree entry. Filter will search greater number. ## Exsample ElixirLdap.Search.search_subtree(handle, [filter: :greater, type: 'age', value: "22"]) """ def search_subtree(handle, [filter: :greater, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :greater, type: type, value: value]) end @doc """ search sub tree entry. Filter will search greater number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_subtree(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :greater, type: 'age', value: "22"]) """ def search_subtree(handle, base, [filter: :greater, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), greater_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end @doc """ search sub tree entry. Filter will search less number. ## Exsample ElixirLdap.Search.search_subtree(handle, [filter: :greater, type: 'age', value: "22"]) """ def search_subtree(handle, [filter: :less, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :less, type: type, value: value]) end @doc """ search sub tree entry. Filter will search less number. Use the base DN of the argument. ## Exsample ElixirLdap.Search.search_subtree(handle, 'ou=People,dc=corporation,dc=home,dc=local', [filter: :greater, type: 'age', value: "22"]) """ def search_subtree(handle, base, [filter: :less, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), less_or_equal(type, value), :eldap.derefAlways(), false, search_timeout) end def search_subtree(handle, [filter: :approx, type: type, value: value]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :approx, type: type, value: value]) end def search_subtree(handle, base, [filter: :approx, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), approx_match(type, value), :eldap.derefAlways(), false, search_timeout) end def search_subtree(handle, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) end def search_subtree(handle, base, [filter: :extensible, value: value, type: type, rule: rule, dn_attributes: dn_attribute]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), extensible_match(value, type, rule, dn_attribute), :eldap.derefAlways(), false, search_timeout) end def search_subtree(handle, [filter: :strings, type: type, value: value]) when is_tuple(value) do base = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:base) search_subtree(handle, base, [filter: :strings, type: type, value: value]) end def search_subtree(handle, base, [filter: :strings, type: type, value: value]) do search_timeout = Application.get_env(:elixir_ldap, :settings) |> Keyword.get(:search_time) || 0 search(handle, base, :eldap.wholeSubtree(), substrings(type, value), :eldap.derefAlways(), false, search_timeout) end @doc """ search filter equality match ## Exsample ElixirLdap.Serach.equality_match("cn", "User01") """ def equality_match(field, name) do :eldap.equalityMatch(to_charlist(field), to_charlist(name)) end @doc """ search filter attribute ## Exsample ElixirLdap.Serach.present("telephoneNumber") """ def present(type) do :eldap.present(to_charlist(type)) end @doc """ search filter greater number ## Exsample ElixirLdap.Serach.greater_or_equal("age", "22") """ def greater_or_equal(type, value) do :eldap.greaterOrEqual(to_charlist(type), to_charlist(value)) end @doc """ search filter less number ## Exsample ElixirLdap.Serach.less_or_equal("age", "22") """ def less_or_equal(type, value) do :eldap.lessOrEqual(to_charlist(type), to_charlist(value)) end @doc """ """ def approx_match(type, value) do :eldap.approxMatch(to_charlist(type), to_charlist(value)) end @doc """ """ def extensible_match(match_value, type, matching_rule, dn_attributes \\ false) do if !is_collation_rule?(matching_rule) do raise "not collation rule : " <> matching_rule end :eldap.extensibleMatch(to_charlist(match_value), [type: type, matchingRule: matching_rule, dnAttributes: dn_attributes]) end @doc """ """ def substrings(type, value) when is_list(value) do lists = Enum.map(value, fn({atom, sub}) -> {atom, to_charlist(sub)} end) :eldap.substrings(to_charlist(type), lists) end @doc """ """ def substrings(type, {atom, sub}) do substrings(type, [{atom, sub}]) end @doc """ and search filter """ def with_and(filters) do :eldap.and(filters) end @doc """ or search filter """ def with_or(filters) do :eldap.or(filters) end @doc """ not search filter """ def with_not(filters) do :eldap.not(filters) end @doc """ """ def search(handle, base, scope, filter, deref, types_only \\ false, timeout \\ 0) def search(handle, base, scope, filter, deref, types_only, timeout) when is_list(base) do if is_tuple(List.first(base)) do search(handle, [ base: to_charlist(to_listchar_atom_key(base)), scope: scope, filter: filter, deref: deref, types_only: types_only, timeout: timeout ]) else search(handle, [ base: to_charlist(base), scope: scope, filter: filter, deref: deref, types_only: types_only, timeout: timeout ]) end end def search(handle, base, scope, filter, deref, types_only, timeout) do search(handle, [ base: to_charlist(base), scope: scope, filter: filter, deref: deref, types_only: types_only, timeout: timeout ]) end def search(handle, options) when is_list(options) do case :eldap.search(handle, options) do {:ok, result} -> result = ElixirLdap.SearchResult.from_record(result) {:ok, result.entries |> Enum.map(fn(x) -> ElixirLdap.Entry.from_record(x) end)} {_, message} -> {:error, message} end end end