ecto_ldap v0.2.8 Ecto.Ldap.Adapter
Allows talking to an LDAP directory as an Ecto data store.
Sample Configuration
use Mix.Config
config :my_app, MyApp.Repo,
adapter: Ecto.Ldap.Adapter,
hostname: "ldap.example.com",
base: "dc=example,dc=com",
port: 636,
ssl: true,
user_dn: "uid=sample_user,ou=users,dc=example,dc=com",
password: "password",
pool_size: 1
Currently ecto_ldap
does not support a pool_size
larger than 1
. If this
is a bottleneck for you, please open an issue.
Example schema
defmodule TestUser do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:dn, :string, autogenerate: false}
schema "users" do
field :objectClass, {:array, :string}
field :loginShell, :string
field :mail, :string
field :mobile, :string
field :skills, {:array, :string}
field :sn, :string
field :st, :string
field :startDate, Ecto.DateTime
field :uid, :string
field :jpegPhoto, :binary
end
def changeset(model, params \ :empty) do
model
|> cast(params, ~w(dn), ~w(objectClass loginShell mail mobile skills sn uid))
|> unique_constraint(:dn)
end
end
Example Usage
iex> require Ecto.Query
iex> Ecto.Query.from(u in TestUser, select: u.uid) |> TestRepo.all
["jeff.weiss", "manny"]
iex> TestRepo.all(TestUser, uid: "jeff.weiss") |> Enum.count
1
iex> TestRepo.get(TestUser, "uid=jeff.weiss,ou=users,dc=example,dc=com").mail
"jeff.weiss@example.com"
iex> TestRepo.get_by(TestUser, uid: "jeff.weiss").loginShell
"/bin/zsh"
iex> Ecto.Query.from(u in TestUser, where: u.st == "OR" and "elixir" in u.skills) |> TestRepo.all |> List.first |> Map.get(:uid)
"jeff.weiss"
iex> Ecto.Query.from(u in TestUser, where: like(u.sn, "%Weis%")) |> TestRepo.all |> List.first |> Map.get(:uid)
"jeff.weiss"
Summary
Functions
Convert from Ecto datatype to datatype that can be handled via eldap
Callback implementation for c:Ecto.Adapter.execute/6
Convert a value from its data-store representation to something that Ecto expects.
:id
fields are always returned unchanged
Callback implementation for c:Ecto.Adapter.prepare/2
Callback implementation for c:Ecto.Adapter.update/7
Functions
Convert from Ecto datatype to datatype that can be handled via eldap
.
nil
s are simply passed straight through regardless of Ecto datatype.
Examples
iex> Ecto.Ldap.Adapter.dump(:string, nil)
{:ok, nil}
iex> Ecto.Ldap.Adapter.dump(:datetime, nil)
{:ok, nil}
Strings are converted to Erlang character lists.
Examples
iex> Ecto.Ldap.Adapter.dump(:string, "bob")
{:ok, 'bob'}
iex> Ecto.Ldap.Adapter.dump(:string, "Sören")
{:ok, [83, 195, 182, 114, 101, 110]}
iex> Ecto.Ldap.Adapter.dump(:string, "José")
{:ok, [74, 111, 115, 195, 169]}
iex> Ecto.Ldap.Adapter.dump({:array, :string}, ["list", "of", "skills"])
{:ok, ['list', 'of', 'skills']}
iex> Ecto.Ldap.Adapter.dump(:integer, 3)
{:ok, 3}
iex> Ecto.Ldap.Adapter.dump(:string, :atom)
{:ok, 'atom'}
Ecto.DateTimes are converted to a stringified ASN.1 GeneralizedTime format in UTC. Currently, fractional seconds are truncated.
Examples
iex> Ecto.Ldap.Adapter.dump(Ecto.DateTime, {{2016, 4, 1}, {12, 34, 56, 789000}})
{:ok, '20160401123456Z'}
iex> Ecto.Ldap.Adapter.dump(Ecto.DateTime, {{2016, 4, 1}, {12, 34, 56, 0}})
{:ok, '20160401123456Z'}
Callback implementation for c:Ecto.Adapter.execute/6
.
Convert a value from its data-store representation to something that Ecto expects.
:id
fields are always returned unchanged.
Examples
iex> Ecto.Ldap.Adapter.load(:id, "uid=jeff.weiss,ou=users,dc=example,dc=com")
{:ok, "uid=jeff.weiss,ou=users,dc=example,dc=com"}
iex> Ecto.Ldap.Adapter.load(:id, 123456)
{:ok, 123456}
iex> Ecto.Ldap.Adapter.load(:id, nil)
{:ok, nil}
Given that LDAP uses ASN.1 GeneralizedTime for its datetime storage format, values
where the type is Ecto.DateTime
will be converted to a string and parsed as ASN.1
GeneralizedTime, assuming UTC ( "2016040112[34[56[.789]]]Z"
)
Examples
iex> Ecto.Ldap.Adapter.load(:datetime, ['20160401123456.789Z'])
{:ok, {{2016, 4, 1}, {12, 34, 56, 789000}}}
iex> Ecto.Ldap.Adapter.load(:datetime, ['20160401123456Z'])
{:ok, {{2016, 4, 1}, {12, 34, 56, 0}}}
iex> Ecto.Ldap.Adapter.load(:datetime, ['201604011234Z'])
{:ok, {{2016, 4, 1}, {12, 34, 0, 0}}}
iex> Ecto.Ldap.Adapter.load(:datetime, ['2016040112Z'])
{:ok, {{2016, 4, 1}, {12, 0, 0, 0}}}
iex> Ecto.Ldap.Adapter.load(Ecto.DateTime, ['20160401123456.789Z'])
{:ok, {{2016, 4, 1}, {12, 34, 56, 789000}}}
iex> Ecto.Ldap.Adapter.load(Ecto.DateTime, ['20160401123456Z'])
{:ok, {{2016, 4, 1}, {12, 34, 56, 0}}}
iex> Ecto.Ldap.Adapter.load(Ecto.DateTime, ['201604011234Z'])
{:ok, {{2016, 4, 1}, {12, 34, 0, 0}}}
iex> Ecto.Ldap.Adapter.load(Ecto.DateTime, ['2016040112Z'])
{:ok, {{2016, 4, 1}, {12, 0, 0, 0}}}
String and binary types will take the first element if the underlying LDAP attribute supports multiple values.
Examples
iex> Ecto.Ldap.Adapter.load(:string, nil)
{:ok, nil}
iex> Ecto.Ldap.Adapter.load(:binary, nil)
{:ok, nil}
iex> Ecto.Ldap.Adapter.load(:string, [83, 195, 182, 114, 101, 110])
{:ok, "Sören"}
iex> Ecto.Ldap.Adapter.load(:string, ['Home, home on the range', 'where the deer and the antelope play'])
{:ok, "Home, home on the range"}
iex> Ecto.Ldap.Adapter.load(:binary, [[1,2,3,4,5], [6,7,8,9,10]])
{:ok, <<1,2,3,4,5>>}
Array values will be each be converted
Examples
iex> Ecto.Ldap.Adapter.load({:array, :string}, [])
{:ok, []}
iex> Ecto.Ldap.Adapter.load({:array, :string}, ['Home, home on the range', 'where the deer and the antelope play'])
{:ok, ["Home, home on the range", "where the deer and the antelope play"]}