diff --git a/Ldap-Asn1-FromAsn1.html b/Ldap-Asn1-FromAsn1.html index ea03f07..e80ed1d 100644 --- a/Ldap-Asn1-FromAsn1.html +++ b/Ldap-Asn1-FromAsn1.html @@ -1,7 +1,7 @@ Ldap.Asn1.FromAsn1

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Asn1.FromAsn1

Description

This module contains convertions from ASN.1 to LDAP types.

Synopsis

Documentation

parseAsn1 :: FromAsn1 a => [ASN1] -> Maybe ([ASN1], a) Source

Convert a part of ASN.1 stream to a LDAP type returning the remainder of the stream.

class FromAsn1 a Source

ASN.1 stream parsers.

When it's relevant, instances include the part of RFC describing the encoding.

Minimal complete definition

fromAsn1

Instances

FromAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Asn1.FromAsn1

Description

This module contains convertions from ASN.1 to LDAP types.

Synopsis

Documentation

parseAsn1 :: FromAsn1 a => [ASN1] -> Maybe ([ASN1], a) Source

Convert a part of ASN.1 stream to a LDAP type returning the remainder of the stream.

class FromAsn1 a Source

ASN.1 stream parsers.

When it's relevant, instances include the part of RFC describing the encoding.

Minimal complete definition

fromAsn1

Instances

FromAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
FromAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded,
 
FromAsn1 Uri Source
URI ::= LDAPString
 
FromAsn1 ReferralUris Source
Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
diff --git a/Ldap-Asn1-ToAsn1.html b/Ldap-Asn1-ToAsn1.html
index 8e7c9ec..7870dfa 100644
--- a/Ldap-Asn1-ToAsn1.html
+++ b/Ldap-Asn1-ToAsn1.html
@@ -4,7 +4,7 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-ToAsn1.html"
 

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Asn1.ToAsn1

Description

This module contains convertions from LDAP types to ASN.1.

Various hacks are employed because "asn1-encoding" only encodes to DER, but LDAP demands BER-encoding. So, when a definition looks suspiciously different from the spec in the comment, that's why. I hope all that will be fixed - eventually.

Synopsis

Documentation

class ToAsn1 a where Source

Convert a LDAP type to ASN.1.

When it's relevant, instances include the part of RFC describing the encoding.

Methods

toAsn1 :: a -> Endo [ASN1] Source

Instances

ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+ eventually.

Synopsis

Documentation

class ToAsn1 a where Source

Convert a LDAP type to ASN.1.

When it's relevant, instances include the part of RFC describing the encoding.

Methods

toAsn1 :: a -> Endo [ASN1] Source

Instances

ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
 
ToAsn1 RelativeLdapDn Source
RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
 
ToAsn1 LdapDn Source
LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
diff --git a/Ldap-Asn1-Type.html b/Ldap-Asn1-Type.html
index efef296..6ce53f6 100644
--- a/Ldap-Asn1-Type.html
+++ b/Ldap-Asn1-Type.html
@@ -1,7 +1,7 @@
 Ldap.Asn1.Type

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellSafe
LanguageHaskell2010

Ldap.Asn1.Type

Synopsis

Documentation

data LdapMessage op Source

Message envelope. (Section 4.1.1.)

Instances

Eq op => Eq (LdapMessage op) Source 
Show op => Show (LdapMessage op) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
+

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellSafe
LanguageHaskell2010

Ldap.Asn1.Type

Synopsis

Documentation

data LdapMessage op Source

Message envelope. (Section 4.1.1.)

Instances

Eq op => Eq (LdapMessage op) Source 
Show op => Show (LdapMessage op) Source 
ToAsn1 op => ToAsn1 (LdapMessage op) Source
LDAPMessage ::= SEQUENCE {
      messageID       MessageID,
      protocolOp      CHOICE {
           bindRequest           BindRequest,
@@ -221,12 +221,12 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Asn1-Type.html");
 

newtype LdapString Source

The LDAPString is a notational convenience to indicate that, although strings of LDAPString type encode as ASN.1 OCTET STRING types, the [ISO10646] character set (a superset of [Unicode]) is used, encoded - following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.)

Constructors

LdapString Text 

Instances

Eq LdapString Source 
Show LdapString Source 
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
+ following the UTF-8 [RFC3629] algorithm. (Section 4.1.2.)

Constructors

LdapString Text 

Instances

Eq LdapString Source 
Show LdapString Source 
ToAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded
 
FromAsn1 LdapString Source
LDAPString ::= OCTET STRING -- UTF-8 encoded,
 

newtype LdapOid Source

The LDAPOID is a notational convenience to indicate that the permitted value of this string is a (UTF-8 encoded) dotted-decimal representation of an OBJECT IDENTIFIER. Although an LDAPOID is encoded as an OCTET STRING, values are limited to the definition of - <numericoid> given in Section 1.4 of [RFC4512].

Constructors

LdapOid Text 

Instances

Eq LdapOid Source 
Show LdapOid Source 
ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+ <numericoid> given in Section 1.4 of [RFC4512].

Constructors

LdapOid Text 

Instances

Eq LdapOid Source 
Show LdapOid Source 
ToAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
FromAsn1 LdapOid Source
LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
 
\ No newline at end of file diff --git a/Ldap-Client-Add.html b/Ldap-Client-Add.html index 19133a0..766ba28 100644 --- a/Ldap-Client-Add.html +++ b/Ldap-Client-Add.html @@ -1,7 +1,10 @@ Ldap.Client.Add

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Add

Description

Add operation.

This operation comes in four flavours:

Of those, the first one (add) is probably the most useful for the typical usecase.

Documentation

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

addEither :: Ldap -> Dn -> AttrList NonEmpty -> IO (Either ResponseError ()) Source

Perform the Add operation synchronously. Returns Left e where - e is a ResponseError on failures.

addAsync :: Ldap -> Dn -> AttrList NonEmpty -> IO (Async ()) Source

Perform the Add operation asynchronously. Call wait to wait - for its completion.

addAsyncSTM :: Ldap -> Dn -> AttrList NonEmpty -> STM (Async ()) Source

Perform the Add operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Add

Description

Add operation.

This operation comes in four flavours:

Of those, the first one (add) is probably the most useful for the typical usecase.

Documentation

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

addEither :: Ldap -> Dn -> AttrList NonEmpty -> IO (Either ResponseError ()) Source

Perform the Add operation synchronously. Returns Left e where + e is a ResponseError on failures.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

addAsync :: Ldap -> Dn -> AttrList NonEmpty -> IO (Async ()) Source

Perform the Add operation asynchronously. Call wait to wait + for its completion.

addAsyncSTM :: Ldap -> Dn -> AttrList NonEmpty -> STM (Async ()) Source

Perform the Add operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Bind.html b/Ldap-Client-Bind.html index 9a8fb01..9d38af0 100644 --- a/Ldap-Client-Bind.html +++ b/Ldap-Client-Bind.html @@ -1,7 +1,10 @@ Ldap.Client.Bind

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Bind

Description

Bind operation.

This operation comes in four flavours:

Of those, the first one (bind) is probably the most useful for the typical usecase.

Synopsis

Documentation

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) Source

Perform the Bind operation synchronously. Returns Left e where - e is a ResponseError on failures.

bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) Source

Perform the Bind operation asynchronously. Call wait to wait - for its completion.

bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) Source

Perform the Bind operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Bind

Description

Bind operation.

This operation comes in four flavours:

Of those, the first one (bind) is probably the most useful for the typical usecase.

Documentation

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) Source

Perform the Bind operation synchronously. Returns Left e where + e is a ResponseError on failures.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) Source

Perform the Bind operation asynchronously. Call wait to wait + for its completion.

bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) Source

Perform the Bind operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Compare.html b/Ldap-Client-Compare.html index 06780bb..9db2630 100644 --- a/Ldap-Client-Compare.html +++ b/Ldap-Client-Compare.html @@ -2,7 +2,10 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Client-Compare.html");}; //]]>

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Compare

Description

Compare operation.

This operation comes in four flavours:

Of those, the first one (compare) is probably the most useful for the - typical usecase.

Documentation

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

compareEither :: Ldap -> Dn -> Attr -> AttrValue -> IO (Either ResponseError Bool) Source

Perform the Compare operation synchronously. Returns Left e where - e is a ResponseError on failures.

compareAsync :: Ldap -> Dn -> Attr -> AttrValue -> IO (Async Bool) Source

Perform the Compare operation asynchronously. Call wait to wait - for its completion.

compareAsyncSTM :: Ldap -> Dn -> Attr -> AttrValue -> STM (Async Bool) Source

Perform the Compare operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file + typical usecase.

Documentation

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

compareEither :: Ldap -> Dn -> Attr -> AttrValue -> IO (Either ResponseError Bool) Source

Perform the Compare operation synchronously. Returns Left e where + e is a ResponseError on failures.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

compareAsync :: Ldap -> Dn -> Attr -> AttrValue -> IO (Async Bool) Source

Perform the Compare operation asynchronously. Call wait to wait + for its completion.

compareAsyncSTM :: Ldap -> Dn -> Attr -> AttrValue -> STM (Async Bool) Source

Perform the Compare operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Delete.html b/Ldap-Client-Delete.html index 63c44f9..c02c890 100644 --- a/Ldap-Client-Delete.html +++ b/Ldap-Client-Delete.html @@ -1,7 +1,10 @@ Ldap.Client.Delete

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Delete

Description

Delete operation.

This operation comes in four flavours:

Of those, the first one (delete) is probably the most useful for the typical usecase.

Synopsis

Documentation

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

deleteEither :: Ldap -> Dn -> IO (Either ResponseError ()) Source

Perform the Delete operation synchronously. Returns Left e where - e is a ResponseError on failures.

deleteAsync :: Ldap -> Dn -> IO (Async ()) Source

Perform the Delete operation asynchronously. Call wait to wait - for its completion.

deleteAsyncSTM :: Ldap -> Dn -> STM (Async ()) Source

Perform the Delete operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Delete

Description

Delete operation.

This operation comes in four flavours:

Of those, the first one (delete) is probably the most useful for the typical usecase.

Synopsis

Documentation

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

deleteEither :: Ldap -> Dn -> IO (Either ResponseError ()) Source

Perform the Delete operation synchronously. Returns Left e where + e is a ResponseError on failures.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

deleteAsync :: Ldap -> Dn -> IO (Async ()) Source

Perform the Delete operation asynchronously. Call wait to wait + for its completion.

deleteAsyncSTM :: Ldap -> Dn -> STM (Async ()) Source

Perform the Delete operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Extended.html b/Ldap-Client-Extended.html index 2fccba2..81c3cc8 100644 --- a/Ldap-Client-Extended.html +++ b/Ldap-Client-Extended.html @@ -1,7 +1,10 @@ Ldap.Client.Extended

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Extended

Description

Extended operation.

This operation comes in four flavours:

Of those, the first one (extended) is probably the most useful for the typical usecase.

Extended Operation

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) Source

Perform the Extended operation synchronously. Returns Left e where - e is a ResponseError on failures.

extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) Source

Perform the Extended operation asynchronously. Call wait to wait - for its completion.

extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) Source

Perform the Extended operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

StartTLS Operation

startTls :: Ldap -> IO () Source

An example of Extended Operation, cf. extended.

startTlsEither :: Ldap -> IO (Either ResponseError ()) Source

An example of Extended Operation, cf. extendedEither.

startTlsAsync :: Ldap -> IO (Async ()) Source

An example of Extended Operation, cf. extendedAsync.

startTlsAsyncSTM :: Ldap -> STM (Async ()) Source

An example of Extended Operation, cf. extendedAsyncSTM.

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Extended

Description

Extended operation.

This operation comes in four flavours:

Of those, the first one (extended) is probably the most useful for the typical usecase.

Extended Operation

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) Source

Perform the Extended operation synchronously. Returns Left e where + e is a ResponseError on failures.

extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) Source

Perform the Extended operation asynchronously. Call wait to wait + for its completion.

extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) Source

Perform the Extended operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

StartTLS Operation

startTls :: Ldap -> IO () Source

An example of Extended Operation, cf. extended.

startTlsEither :: Ldap -> IO (Either ResponseError ()) Source

An example of Extended Operation, cf. extendedEither.

startTlsAsync :: Ldap -> IO (Async ()) Source

An example of Extended Operation, cf. extendedAsync.

startTlsAsyncSTM :: Ldap -> STM (Async ()) Source

An example of Extended Operation, cf. extendedAsyncSTM.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Internal.html b/Ldap-Client-Internal.html index e92d5ff..cf58a07 100644 --- a/Ldap-Client-Internal.html +++ b/Ldap-Client-Internal.html @@ -1,12 +1,12 @@ Ldap.Client.Internal

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Internal

Synopsis

Documentation

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. - Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Constructors

Ldap 

Fields

client :: TQueue ClientMessage
 

Instances

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Internal

Synopsis

Documentation

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. + Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Constructors

Ldap 

Instances

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these values are in, e.g. NonEmpty.

Waiting for Request Completion

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was requested in! To give LDAP the chance to respond to it that transaction should commit. After that, applying waitSTM to the corresponding Async - starts to make sense.

Misc

type Response = NonEmpty InMessage Source

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

raise :: Exception e => Either e a -> IO a Source

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

unAttr :: Attr -> Text Source

Unbind operation

unbindAsync :: Ldap -> IO () Source

Terminate the connection to the Directory.

Note that unbindAsync does not return an Async, + starts to make sense.

Misc

type Response = NonEmpty InMessage Source

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

raise :: Exception e => Either e a -> IO a Source

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

Unbind operation

unbindAsync :: Ldap -> IO () Source

Terminate the connection to the Directory.

Note that unbindAsync does not return an Async, because LDAP server never responds to UnbindRequests, hence a call to wait on a hypothetical Async would have resulted in an exception anyway.

unbindAsyncSTM :: Ldap -> STM () Source

Terminate the connection to the Directory.

Note that unbindAsyncSTM does not return an Async, diff --git a/Ldap-Client-Modify.html b/Ldap-Client-Modify.html index 228acc1..abf6ff1 100644 --- a/Ldap-Client-Modify.html +++ b/Ldap-Client-Modify.html @@ -4,10 +4,13 @@ window.onload = function () {pageLoad();setSynopsis("mini_Ldap-Client-Modify.htm

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Modify

Description

Modify and Modify DN operations.

These operations come in four flavours:

Of those, the first one (modify / modifyDn) is probably the most - useful for the typical usecase.

Documentation

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) Source

Perform the Modify operation synchronously. Returns Left e where - e is a ResponseError on failures.

modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) Source

Perform the Modify operation asynchronously. Call wait to wait - for its completion.

modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) Source

Perform the Modify operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) Source

Perform the Modify DN operation synchronously. Returns Left e where - e is a ResponseError on failures.

modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) Source

Perform the Modify DN operation asynchronously. Call wait to wait - for its completion.

modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) Source

Perform the Modify DN operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

\ No newline at end of file + useful for the typical usecase.

Documentation

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) Source

Perform the Modify operation synchronously. Returns Left e where + e is a ResponseError on failures.

modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) Source

Perform the Modify operation asynchronously. Call wait to wait + for its completion.

modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) Source

Perform the Modify operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) Source

Perform the Modify DN operation synchronously. Returns Left e where + e is a ResponseError on failures.

modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) Source

Perform the Modify DN operation asynchronously. Call wait to wait + for its completion.

modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) Source

Perform the Modify DN operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client-Search.html b/Ldap-Client-Search.html index 5452b22..89e5fd7 100644 --- a/Ldap-Client-Search.html +++ b/Ldap-Client-Search.html @@ -1,12 +1,15 @@ Ldap.Client.Search

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Search

Description

Search operation.

This operation comes in four flavours:

Of those, the first one (search) is probably the most useful for the typical usecase.

Documentation

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

searchEither :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Either ResponseError [SearchEntry]) Source

Perform the Search operation synchronously. Returns Left e where - e is a ResponseError on failures.

searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) Source

Perform the Search operation asynchronously. Call wait to wait - for its completion.

searchAsyncSTM :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> STM (Async [SearchEntry]) Source

Perform the Search operation asynchronously.

Don't wait for its completion (with waitSTM) in the - same transaction you've performed it in.

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client.Search

Description

Search operation.

This operation comes in four flavours:

Of those, the first one (search) is probably the most useful for the typical usecase.

Documentation

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

searchEither :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Either ResponseError [SearchEntry]) Source

Perform the Search operation synchronously. Returns Left e where + e is a ResponseError on failures.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) Source

Perform the Search operation asynchronously. Call wait to wait + for its completion.

searchAsyncSTM :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> STM (Async [SearchEntry]) Source

Perform the Search operation asynchronously.

Don't wait for its completion (with waitSTM) in the + same transaction you've performed it in.

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. No limit if the value is 0 (default: 0).

time :: Int32 -> Mod Search Source

Maximum time (in seconds) allowed for the Search. No limit if the value is 0 (default: 0).

typesOnly :: Bool -> Mod Search Source

Whether Search results are to contain just attribute descriptions, or both attribute descriptions and values (default: False).

data DerefAliases Source

An indicator as to whether or not alias entries (as defined in [RFC4512]) are to be dereferenced during stages of the Search - operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 
\ No newline at end of file + operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

waitSTM :: Async a -> STM (Either ResponseError a) Source

Wait for operation completion inside STM.

Do not use this inside the same STM transaction the operation was + requested in! To give LDAP the chance to respond to it that transaction + should commit. After that, applying waitSTM to the corresponding Async + starts to make sense.

\ No newline at end of file diff --git a/Ldap-Client.html b/Ldap-Client.html index 0639c3f..d24c6f1 100644 --- a/Ldap-Client.html +++ b/Ldap-Client.html @@ -1,11 +1,11 @@ Ldap.Client

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client

Description

Pure Haskell LDAP client library.

Synopsis

Documentation

with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) Source

The entrypoint into LDAP.

It catches all LDAP-related exceptions.

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. - Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Instances

data LdapError Source

Various failures that can happen when working with LDAP.

Constructors

IOError IOError

Network failure.

ParseError ASN1Error

Invalid ASN.1 data received from the server.

ResponseError ResponseError

An LDAP operation failed.

DisconnectError Disconnect

Notice of Disconnection has been received.

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

data Async a Source

Asynchronous LDAP operation. Use wait or waitSTM to wait for its completion.

Instances

Bind

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

Search

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 

Search modifiers

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

Monoid (Mod a) Source 
Semigroup (Mod a) Source 

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Safe HaskellNone
LanguageHaskell2010

Ldap.Client

Description

Pure Haskell LDAP client library.

Synopsis

Documentation

with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) Source

The entrypoint into LDAP.

It catches all LDAP-related exceptions.

data Host Source

LDAP host.

Constructors

Plain String

Plain LDAP. Do not use!

Insecure String

LDAP over TLS without the certificate validity check. + Only use for testing!

Secure String

LDAP over TLS. Use!

data Ldap Source

A token. All functions that interact with the Directory require one.

Instances

data LdapError Source

Various failures that can happen when working with LDAP.

Constructors

IOError IOError

Network failure.

ParseError ASN1Error

Invalid ASN.1 data received from the server.

ResponseError ResponseError

An LDAP operation failed.

DisconnectError Disconnect

Notice of Disconnection has been received.

data ResponseError Source

Response indicates a failed operation.

Constructors

ResponseInvalid Request Response

LDAP server did not follow the protocol, so ldap-client couldn't make sense of the response.

ResponseErrorCode Request ResultCode Dn Text

The response contains a result code indicating failure and an error message.

Bind

newtype Password Source

User's password.

Constructors

Password ByteString 

bind :: Ldap -> Dn -> Password -> IO () Source

Perform the Bind operation synchronously. Raises ResponseError on failures.

Search

search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] Source

Perform the Search operation synchronously. Raises ResponseError on failures.

data SearchEntry Source

Entry found during the Search.

Constructors

SearchEntry !Dn !(AttrList []) 

Search modifiers

data Search Source

Search options. Use Mod to change some of those.

data Mod a Source

Search modifier. Combine using Semigroup and/or Monoid instance.

Instances

data Scope Source

Scope of the search to be performed.

Constructors

BaseObject

Constrained to the entry named by baseObject.

SingleLevel

Constrained to the immediate subordinates of the entry named by baseObject.

WholeSubtree

Constrained to the entry named by baseObject and to all its subordinates.

scope :: Scope -> Mod Search Source

Scope of the search (default: WholeSubtree).

size :: Int32 -> Mod Search Source

Maximum number of entries to be returned as a result of the Search. No limit if the value is 0 (default: 0).

time :: Int32 -> Mod Search Source

Maximum time (in seconds) allowed for the Search. No limit if the value is 0 (default: 0).

typesOnly :: Bool -> Mod Search Source

Whether Search results are to contain just attribute descriptions, or both attribute descriptions and values (default: False).

data DerefAliases Source

An indicator as to whether or not alias entries (as defined in [RFC4512]) are to be dereferenced during stages of the Search - operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

Modify

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

Add

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

Delete

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

ModifyDn

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

Compare

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

Extended

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

Waiting for completion

wait :: Async a -> IO (Either ResponseError a) Source

Wait for operation completion.

Miscellanous

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these - values are in, e.g. NonEmpty.

Re-exports

data NonEmpty a :: * -> *

Instances

Monad NonEmpty 
Functor NonEmpty 
MonadFix NonEmpty 
Applicative NonEmpty 
Foldable NonEmpty 
Traversable NonEmpty 
Generic1 NonEmpty 
MonadZip NonEmpty 
IsList (NonEmpty a) 
Eq a => Eq (NonEmpty a) 
Data a => Data (NonEmpty a) 
Ord a => Ord (NonEmpty a) 
Read a => Read (NonEmpty a) 
Show a => Show (NonEmpty a) 
Generic (NonEmpty a) 
NFData a => NFData (NonEmpty a) 
Hashable a => Hashable (NonEmpty a) 
ToAsn1 a => ToAsn1 (NonEmpty a) 
Semigroup (NonEmpty a) 
type Rep1 NonEmpty = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector Par1) (S1 NoSelector (Rec1 [])))) 
type Rep (NonEmpty a) = D1 D1NonEmpty (C1 C1_0NonEmpty ((:*:) (S1 NoSelector (Rec0 a)) (S1 NoSelector (Rec0 [a])))) 
type Item (NonEmpty a) = a 
\ No newline at end of file + operation.

Constructors

NeverDerefAliases

Do not dereference aliases in searching or in locating the base object of the Search.

DerefInSearching

While searching subordinates of the base object, dereference any alias within the search scope.

DerefFindingBaseObject

Dereference aliases in locating the base object of the Search.

DerefAlways

Dereference aliases both in searching and in locating the base object of the Search.

derefAliases :: DerefAliases -> Mod Search Source

Alias dereference policy (default: NeverDerefAliases).

data Filter Source

Conditions that must be fulfilled in order for the Search to match a given entry.

Constructors

Not !Filter

Filter does not match the entry

And !(NonEmpty Filter)

All filters match the entry

Or !(NonEmpty Filter)

Any filter matches the entry

Present !Attr

Attribute is present in the entry

!Attr := !AttrValue

Attribute's value is equal to the assertion

!Attr :>= !AttrValue

Attribute's value is equal to or greater than the assertion

!Attr :<= !AttrValue

Attribute's value is equal to or less than the assertion

!Attr :~= !AttrValue

Attribute's value approximately matches the assertion

!Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue)

Glob match

(Maybe Attr, Maybe Attr, Bool) ::= AttrValue

Extensible match

Modify

modify :: Ldap -> Dn -> [Operation] -> IO () Source

Perform the Modify operation synchronously. Raises ResponseError on failures.

data Operation Source

Type of modification being performed.

Constructors

Delete Attr [AttrValue]

Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed.

Add Attr [AttrValue]

Add values to the attribute, creating it if necessary.

Replace Attr [AttrValue]

Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty.

Add

add :: Ldap -> Dn -> AttrList NonEmpty -> IO () Source

Perform the Add operation synchronously. Raises ResponseError on failures.

Delete

delete :: Ldap -> Dn -> IO () Source

Perform the Delete operation synchronously. Raises ResponseError on failures.

ModifyDn

newtype RelativeDn Source

A component of Dn.

Constructors

RelativeDn Text 

modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () Source

Perform the Modify DN operation synchronously. Raises ResponseError on failures.

Compare

compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool Source

Perform the Compare operation synchronously. Raises ResponseError on failures.

Extended

newtype Oid Source

Globally unique LDAP object identifier.

Constructors

Oid Text 

Instances

extended :: Ldap -> Oid -> Maybe ByteString -> IO () Source

Perform the Extended operation synchronously. Raises ResponseError on failures.

Miscellanous

newtype Dn Source

Unique identifier of an LDAP entry.

Constructors

Dn Text 

Instances

newtype Attr Source

Attribute name.

Constructors

Attr Text 

type AttrValue = ByteString Source

Attribute value.

type AttrList f = [(Attr, f AttrValue)] Source

List of attributes and their values. f is the structure these + values are in, e.g. NonEmpty.

Re-exports

data NonEmpty a :: * -> *

Instances

\ No newline at end of file diff --git a/doc-index-A.html b/doc-index-A.html index cc1ecc1..90eb4e7 100644 --- a/doc-index-A.html +++ b/doc-index-A.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - A)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - A

Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index - A

Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client.Bind, Ldap.Client.Search, Ldap.Client.Modify, Ldap.Client.Add, Ldap.Client.Delete, Ldap.Client.Compare, Ldap.Client.Extended
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
\ No newline at end of file diff --git a/doc-index-All.html b/doc-index-All.html index feb22e6..ce083d3 100644 --- a/doc-index-All.html +++ b/doc-index-All.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index

::=Ldap.Client.Search, Ldap.Client
:<=Ldap.Client.Search, Ldap.Client
:=Ldap.Client.Search, Ldap.Client
:=*Ldap.Client.Search, Ldap.Client
:>=Ldap.Client.Search, Ldap.Client
:~=Ldap.Client.Search, Ldap.Client
Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
BaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
bindLdap.Client.Bind, Ldap.Client
bindAsyncLdap.Client.Bind
bindAsyncSTMLdap.Client.Bind
bindEitherLdap.Client.Bind
BindRequestLdap.Asn1.Type
BindResponseLdap.Asn1.Type
BusyLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
clientLdap.Client.Internal
ClientMessageLdap.Client.Internal
compareLdap.Client.Compare, Ldap.Client
compareAsyncLdap.Client.Compare
compareAsyncSTMLdap.Client.Compare
compareEitherLdap.Client.Compare
CompareFalseLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
CompareRequestLdap.Asn1.Type
CompareResponseLdap.Asn1.Type
CompareTrueLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConfidentialityRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConstraintViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Control 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Controls 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Delete 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
deleteLdap.Client.Delete, Ldap.Client
deleteAsyncLdap.Client.Delete
deleteAsyncSTMLdap.Client.Delete
deleteEitherLdap.Client.Delete
DeleteRequestLdap.Asn1.Type
DeleteResponseLdap.Asn1.Type
DerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
derefAliasesLdap.Client.Search, Ldap.Client
DerefAlwaysLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefFindingBaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefInSearchingLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DisconnectErrorLdap.Client
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
EntryAlreadyExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
EqualityMatchLdap.Asn1.Type
extendedLdap.Client.Extended, Ldap.Client
extendedAsyncLdap.Client.Extended
extendedAsyncSTMLdap.Client.Extended
extendedEitherLdap.Client.Extended
ExtendedRequestLdap.Asn1.Type
ExtendedResponseLdap.Asn1.Type
ExtensibleMatchLdap.Asn1.Type
Filter 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Search, Ldap.Client
FinalLdap.Asn1.Type
FromAsn1Ldap.Asn1.FromAsn1
GreaterOrEqualLdap.Asn1.Type
HostLdap.Client.Internal, Ldap.Client
Id 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
InappropriateAuthenticationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InappropriateMatchingLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InitialLdap.Asn1.Type
InsecureLdap.Client.Internal, Ldap.Client
InsufficientAccessRightsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IntermediateResponseLdap.Asn1.Type
InvalidAttributeSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidCredentialsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidDNSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IOErrorLdap.Client
Ldap 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal
LdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapErrorLdap.Client
LdapMessage 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ldapMessageControlsLdap.Asn1.Type
ldapMessageIdLdap.Asn1.Type
ldapMessageOpLdap.Asn1.Type
LdapOid 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapResult 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapString 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LessOrEqualLdap.Asn1.Type
LoopDetectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
MatchingRuleAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
MatchingRuleId 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ModLdap.Client.Search, Ldap.Client
modifyLdap.Client.Modify, Ldap.Client
modifyAsyncLdap.Client.Modify
modifyAsyncSTMLdap.Client.Modify
modifyDnLdap.Client.Modify, Ldap.Client
modifyDnAsyncLdap.Client.Modify
modifyDnAsyncSTMLdap.Client.Modify
modifyDnEitherLdap.Client.Modify
ModifyDnRequestLdap.Asn1.Type
ModifyDnResponseLdap.Asn1.Type
modifyEitherLdap.Client.Modify
ModifyRequestLdap.Asn1.Type
ModifyResponseLdap.Asn1.Type
NamingViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NeverDerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
NewLdap.Client.Internal
NonEmptyLdap.Client
NoSuchAttributeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NoSuchObjectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Not 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
NotAllowedOnNonLeafLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NotAllowedOnRDNLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassModsProhibitedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Oid 
1 (Type/Class)Ldap.Client.Extended, Ldap.Client
2 (Data Constructor)Ldap.Client.Extended, Ldap.Client
Operation 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Modify, Ldap.Client
OperationErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Or 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
OtherLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Bind, Ldap.Client
2 (Data Constructor)Ldap.Client.Bind, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Modify, Ldap.Client
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SaslBindInProgressLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ScopeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
scopeLdap.Client.Search, Ldap.Client
SearchLdap.Client.Search, Ldap.Client
searchLdap.Client.Search, Ldap.Client
searchAsyncLdap.Client.Search
searchAsyncSTMLdap.Client.Search
searchEitherLdap.Client.Search
SearchEntry 
1 (Type/Class)Ldap.Client.Search, Ldap.Client
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
SearchRequestLdap.Asn1.Type
SearchResultDoneLdap.Asn1.Type
SearchResultEntryLdap.Asn1.Type
SearchResultReferenceLdap.Asn1.Type
SecureLdap.Client.Internal, Ldap.Client
sendRequestLdap.Client.Internal
SimpleLdap.Asn1.Type
SingleLevelLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
sizeLdap.Client.Search, Ldap.Client
SizeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
startTlsLdap.Client.Extended
startTlsAsyncLdap.Client.Extended
startTlsAsyncSTMLdap.Client.Extended
startTlsEitherLdap.Client.Extended
StrongerAuthRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SubstringLdap.Asn1.Type
SubstringFilter 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
SubstringsLdap.Asn1.Type
SuccessLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
timeLdap.Client.Search, Ldap.Client
TimeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ToAsn1Ldap.Asn1.ToAsn1
toAsn1Ldap.Asn1.ToAsn1
typesOnlyLdap.Client.Search, Ldap.Client
unAttrLdap.Client.Internal
UnavailableLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
UnavailableCriticalExtensionLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unbindAsyncLdap.Client.Internal
unbindAsyncSTMLdap.Client.Internal
UnbindRequestLdap.Asn1.Type
UndefinedAttributeTypeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unIdLdap.Asn1.Type
UnwillingToPerformLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Uri 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
waitLdap.Client.Internal, Ldap.Client
waitSTMLdap.Client.Internal
WholeSubtreeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
withLdap.Client
\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

Index

::=Ldap.Client.Search, Ldap.Client
:<=Ldap.Client.Search, Ldap.Client
:=Ldap.Client.Search, Ldap.Client
:=*Ldap.Client.Search, Ldap.Client
:>=Ldap.Client.Search, Ldap.Client
:~=Ldap.Client.Search, Ldap.Client
Add 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
addLdap.Client.Add, Ldap.Client
addAsyncLdap.Client.Add
addAsyncSTMLdap.Client.Add
addEitherLdap.Client.Add
AddRequestLdap.Asn1.Type
AddResponseLdap.Asn1.Type
AdminLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AffectsMultipleDSAsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasDereferencingProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AliasProblemLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
And 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
AnyLdap.Asn1.Type
ApproxMatchLdap.Asn1.Type
AssertionValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AsyncLdap.Client.Internal, Ldap.Client.Bind, Ldap.Client.Search, Ldap.Client.Modify, Ldap.Client.Add, Ldap.Client.Delete, Ldap.Client.Compare, Ldap.Client.Extended
Attr 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
Attribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeDescription 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeOrValueExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
AttributeSelection 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValue 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttributeValueAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
AttrListLdap.Client.Internal, Ldap.Client
AttrValueLdap.Client.Internal, Ldap.Client
AuthenticationChoiceLdap.Asn1.Type
AuthMethodNotSupportedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
BaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
bindLdap.Client.Bind, Ldap.Client
bindAsyncLdap.Client.Bind
bindAsyncSTMLdap.Client.Bind
bindEitherLdap.Client.Bind
BindRequestLdap.Asn1.Type
BindResponseLdap.Asn1.Type
BusyLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
clientLdap.Client.Internal
ClientMessageLdap.Client.Internal
compareLdap.Client.Compare, Ldap.Client
compareAsyncLdap.Client.Compare
compareAsyncSTMLdap.Client.Compare
compareEitherLdap.Client.Compare
CompareFalseLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
CompareRequestLdap.Asn1.Type
CompareResponseLdap.Asn1.Type
CompareTrueLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConfidentialityRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ConstraintViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Control 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Controls 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Delete 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
deleteLdap.Client.Delete, Ldap.Client
deleteAsyncLdap.Client.Delete
deleteAsyncSTMLdap.Client.Delete
deleteEitherLdap.Client.Delete
DeleteRequestLdap.Asn1.Type
DeleteResponseLdap.Asn1.Type
DerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
derefAliasesLdap.Client.Search, Ldap.Client
DerefAlwaysLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefFindingBaseObjectLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DerefInSearchingLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
DisconnectErrorLdap.Client
Dn 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal, Ldap.Client
EntryAlreadyExistsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
EqualityMatchLdap.Asn1.Type
extendedLdap.Client.Extended, Ldap.Client
extendedAsyncLdap.Client.Extended
extendedAsyncSTMLdap.Client.Extended
extendedEitherLdap.Client.Extended
ExtendedRequestLdap.Asn1.Type
ExtendedResponseLdap.Asn1.Type
ExtensibleMatchLdap.Asn1.Type
Filter 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Search, Ldap.Client
FinalLdap.Asn1.Type
FromAsn1Ldap.Asn1.FromAsn1
GreaterOrEqualLdap.Asn1.Type
HostLdap.Client.Internal, Ldap.Client
Id 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
InappropriateAuthenticationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InappropriateMatchingLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InitialLdap.Asn1.Type
InsecureLdap.Client.Internal, Ldap.Client
InsufficientAccessRightsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IntermediateResponseLdap.Asn1.Type
InvalidAttributeSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidCredentialsLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
InvalidDNSyntaxLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
IOErrorLdap.Client
Ldap 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client.Internal
LdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapErrorLdap.Client
LdapMessage 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ldapMessageControlsLdap.Asn1.Type
ldapMessageIdLdap.Asn1.Type
ldapMessageOpLdap.Asn1.Type
LdapOid 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapResult 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LdapString 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
LessOrEqualLdap.Asn1.Type
LoopDetectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
MatchingRuleAssertion 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
MatchingRuleId 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
ModLdap.Client.Search, Ldap.Client
modifyLdap.Client.Modify, Ldap.Client
modifyAsyncLdap.Client.Modify
modifyAsyncSTMLdap.Client.Modify
modifyDnLdap.Client.Modify, Ldap.Client
modifyDnAsyncLdap.Client.Modify
modifyDnAsyncSTMLdap.Client.Modify
modifyDnEitherLdap.Client.Modify
ModifyDnRequestLdap.Asn1.Type
ModifyDnResponseLdap.Asn1.Type
modifyEitherLdap.Client.Modify
ModifyRequestLdap.Asn1.Type
ModifyResponseLdap.Asn1.Type
NamingViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NeverDerefAliasesLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
NewLdap.Client.Internal
NonEmptyLdap.Client
NoSuchAttributeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NoSuchObjectLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Not 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
NotAllowedOnNonLeafLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
NotAllowedOnRDNLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassModsProhibitedLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ObjectClassViolationLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Oid 
1 (Type/Class)Ldap.Client.Extended, Ldap.Client
2 (Data Constructor)Ldap.Client.Extended, Ldap.Client
Operation 
1 (Type/Class)Ldap.Asn1.Type
2 (Type/Class)Ldap.Client.Modify, Ldap.Client
OperationErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Or 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
OtherLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
parseAsn1Ldap.Asn1.FromAsn1
ParseErrorLdap.Client
PartialAttribute 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
PartialAttributeList 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Password 
1 (Type/Class)Ldap.Client.Bind, Ldap.Client
2 (Data Constructor)Ldap.Client.Bind, Ldap.Client
PlainLdap.Client.Internal, Ldap.Client
PortNumberLdap.Client.Internal, Ldap.Client
Present 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
ProtocolClientOpLdap.Asn1.Type
ProtocolErrorLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ProtocolServerOpLdap.Asn1.Type
raiseLdap.Client.Internal
ReferralLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ReferralUris 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
RelativeDn 
1 (Type/Class)Ldap.Client.Modify, Ldap.Client
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RelativeLdapDn 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
Replace 
1 (Data Constructor)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Client.Modify, Ldap.Client
RequestLdap.Client.Internal
ResponseLdap.Client.Internal
ResponseError 
1 (Type/Class)Ldap.Client.Internal, Ldap.Client
2 (Data Constructor)Ldap.Client
ResponseErrorCodeLdap.Client.Internal, Ldap.Client
ResponseInvalidLdap.Client.Internal, Ldap.Client
ResultCodeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SaslBindInProgressLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ScopeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
scopeLdap.Client.Search, Ldap.Client
SearchLdap.Client.Search, Ldap.Client
searchLdap.Client.Search, Ldap.Client
searchAsyncLdap.Client.Search
searchAsyncSTMLdap.Client.Search
searchEitherLdap.Client.Search
SearchEntry 
1 (Type/Class)Ldap.Client.Search, Ldap.Client
2 (Data Constructor)Ldap.Client.Search, Ldap.Client
SearchRequestLdap.Asn1.Type
SearchResultDoneLdap.Asn1.Type
SearchResultEntryLdap.Asn1.Type
SearchResultReferenceLdap.Asn1.Type
SecureLdap.Client.Internal, Ldap.Client
sendRequestLdap.Client.Internal
SimpleLdap.Asn1.Type
SingleLevelLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
sizeLdap.Client.Search, Ldap.Client
SizeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
startTlsLdap.Client.Extended
startTlsAsyncLdap.Client.Extended
startTlsAsyncSTMLdap.Client.Extended
startTlsEitherLdap.Client.Extended
StrongerAuthRequiredLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
SubstringLdap.Asn1.Type
SubstringFilter 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
SubstringsLdap.Asn1.Type
SuccessLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
timeLdap.Client.Search, Ldap.Client
TimeLimitExceededLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
ToAsn1Ldap.Asn1.ToAsn1
toAsn1Ldap.Asn1.ToAsn1
typesOnlyLdap.Client.Search, Ldap.Client
unAttrLdap.Client.Internal
UnavailableLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
UnavailableCriticalExtensionLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unbindAsyncLdap.Client.Internal
unbindAsyncSTMLdap.Client.Internal
UnbindRequestLdap.Asn1.Type
UndefinedAttributeTypeLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
unIdLdap.Asn1.Type
UnwillingToPerformLdap.Asn1.Type, Ldap.Client.Internal, Ldap.Client
Uri 
1 (Type/Class)Ldap.Asn1.Type
2 (Data Constructor)Ldap.Asn1.Type
waitLdap.Client.Internal, Ldap.Client.Bind, Ldap.Client.Search, Ldap.Client.Modify, Ldap.Client.Add, Ldap.Client.Delete, Ldap.Client.Compare, Ldap.Client.Extended
waitSTMLdap.Client.Internal, Ldap.Client.Bind, Ldap.Client.Search, Ldap.Client.Modify, Ldap.Client.Add, Ldap.Client.Delete, Ldap.Client.Compare, Ldap.Client.Extended
WholeSubtreeLdap.Asn1.Type, Ldap.Client.Search, Ldap.Client
withLdap.Client
\ No newline at end of file diff --git a/doc-index-W.html b/doc-index-W.html index 686aea4..7eed16c 100644 --- a/doc-index-W.html +++ b/doc-index-W.html @@ -1,4 +1,4 @@ ldap-client-0.1.0: Pure Haskell LDAP Client Library (Index - W)

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file +

ldap-client-0.1.0: Pure Haskell LDAP Client Library

\ No newline at end of file diff --git a/ldap-client.haddock b/ldap-client.haddock index 31ae62c..46e9bb7 100644 Binary files a/ldap-client.haddock and b/ldap-client.haddock differ diff --git a/mini_Ldap-Client-Add.html b/mini_Ldap-Client-Add.html index 3e317aa..a436d02 100644 --- a/mini_Ldap-Client-Add.html +++ b/mini_Ldap-Client-Add.html @@ -1,4 +1,4 @@ Ldap.Client.Add

Ldap.Client.Add

\ No newline at end of file +

Ldap.Client.Add

\ No newline at end of file diff --git a/mini_Ldap-Client-Bind.html b/mini_Ldap-Client-Bind.html index 196c4a7..2fd4666 100644 --- a/mini_Ldap-Client-Bind.html +++ b/mini_Ldap-Client-Bind.html @@ -1,4 +1,4 @@ Ldap.Client.Bind

Ldap.Client.Bind

\ No newline at end of file +

Ldap.Client.Bind

\ No newline at end of file diff --git a/mini_Ldap-Client-Compare.html b/mini_Ldap-Client-Compare.html index 432a0ba..6d469ca 100644 --- a/mini_Ldap-Client-Compare.html +++ b/mini_Ldap-Client-Compare.html @@ -1,4 +1,4 @@ Ldap.Client.Compare

Ldap.Client.Compare

\ No newline at end of file +

Ldap.Client.Compare

\ No newline at end of file diff --git a/mini_Ldap-Client-Delete.html b/mini_Ldap-Client-Delete.html index f046436..835ddf0 100644 --- a/mini_Ldap-Client-Delete.html +++ b/mini_Ldap-Client-Delete.html @@ -1,4 +1,4 @@ Ldap.Client.Delete

Ldap.Client.Delete

\ No newline at end of file +

Ldap.Client.Delete

\ No newline at end of file diff --git a/mini_Ldap-Client-Extended.html b/mini_Ldap-Client-Extended.html index 023931f..bdcdef3 100644 --- a/mini_Ldap-Client-Extended.html +++ b/mini_Ldap-Client-Extended.html @@ -1,4 +1,4 @@ Ldap.Client.Extended

Ldap.Client.Extended

\ No newline at end of file +

Ldap.Client.Extended

\ No newline at end of file diff --git a/mini_Ldap-Client-Modify.html b/mini_Ldap-Client-Modify.html index 3ca044d..a321b25 100644 --- a/mini_Ldap-Client-Modify.html +++ b/mini_Ldap-Client-Modify.html @@ -1,4 +1,4 @@ Ldap.Client.Modify

Ldap.Client.Modify

\ No newline at end of file +

Ldap.Client.Modify

\ No newline at end of file diff --git a/mini_Ldap-Client-Search.html b/mini_Ldap-Client-Search.html index d2af2f7..da7196a 100644 --- a/mini_Ldap-Client-Search.html +++ b/mini_Ldap-Client-Search.html @@ -1,4 +1,4 @@ Ldap.Client.Search

Ldap.Client.Search

\ No newline at end of file +

Ldap.Client.Search

\ No newline at end of file diff --git a/mini_Ldap-Client.html b/mini_Ldap-Client.html index 8dbfb4a..70e07df 100644 --- a/mini_Ldap-Client.html +++ b/mini_Ldap-Client.html @@ -1,4 +1,4 @@ Ldap.Client

Ldap.Client

data Host

data Ldap

data Async a

Bind

Search

Search modifiers

data Search

data Mod a

data Scope

data Filter

Modify

Add

Delete

ModifyDn

Compare

Extended

data Oid

Waiting for completion

Miscellanous

data Dn

data Attr

type AttrList f

Re-exports

data NonEmpty a

\ No newline at end of file +

Ldap.Client

data Host

data Ldap

Bind

Search

Search modifiers

data Search

data Mod a

data Scope

data Filter

Modify

Add

Delete

ModifyDn

Compare

Extended

data Oid

Miscellanous

data Dn

data Attr

type AttrList f

Re-exports

data NonEmpty a

\ No newline at end of file diff --git a/src/Ldap-Client-Add.html b/src/Ldap-Client-Add.html index 270ab9f..df682ea 100644 --- a/src/Ldap-Client-Add.html +++ b/src/Ldap-Client-Add.html @@ -23,55 +23,58 @@ module Ldap.Client.Add ( add , addEither - , addAsync - , addAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) + , Async + , addAsync + , addAsyncSTM + , wait + , waitSTM + ) where -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal +import Control.Monad.STM (STM, atomically) +import Data.List.NonEmpty (NonEmpty((:|))) - --- | Perform the Add operation synchronously. Raises 'ResponseError' on failures. -add :: Ldap -> Dn -> AttrList NonEmpty -> IO () -add l dn as = - raise =<< addEither l dn as - --- | Perform the Add operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -addEither :: Ldap -> Dn -> AttrList NonEmpty -> IO (Either ResponseError ()) -addEither l dn as = - wait =<< addAsync l dn as - --- | Perform the Add operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -addAsync :: Ldap -> Dn -> AttrList NonEmpty -> IO (Async ()) -addAsync l dn as = - atomically (addAsyncSTM l dn as) - --- | Perform the Add operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -addAsyncSTM :: Ldap -> Dn -> AttrList NonEmpty -> STM (Async ()) -addAsyncSTM l dn as = - let req = addRequest dn as in sendRequest l (addResult req) req - -addRequest :: Dn -> AttrList NonEmpty -> Request -addRequest (Dn dn) as = - Type.AddRequest (Type.LdapDn (Type.LdapString dn)) - (Type.AttributeList (map f as)) - where - f (Attr x, xs) = Type.Attribute (Type.AttributeDescription (Type.LdapString x)) - (fmap Type.AttributeValue xs) - -addResult :: Request -> Response -> Either ResponseError () -addResult req (Type.AddResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -addResult req res = Left (ResponseInvalid req res) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Perform the Add operation synchronously. Raises 'ResponseError' on failures. +add :: Ldap -> Dn -> AttrList NonEmpty -> IO () +add l dn as = + raise =<< addEither l dn as + +-- | Perform the Add operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +addEither :: Ldap -> Dn -> AttrList NonEmpty -> IO (Either ResponseError ()) +addEither l dn as = + wait =<< addAsync l dn as + +-- | Perform the Add operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +addAsync :: Ldap -> Dn -> AttrList NonEmpty -> IO (Async ()) +addAsync l dn as = + atomically (addAsyncSTM l dn as) + +-- | Perform the Add operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +addAsyncSTM :: Ldap -> Dn -> AttrList NonEmpty -> STM (Async ()) +addAsyncSTM l dn as = + let req = addRequest dn as in sendRequest l (addResult req) req + +addRequest :: Dn -> AttrList NonEmpty -> Request +addRequest (Dn dn) as = + Type.AddRequest (Type.LdapDn (Type.LdapString dn)) + (Type.AttributeList (map f as)) + where + f (Attr x, xs) = Type.Attribute (Type.AttributeDescription (Type.LdapString x)) + (fmap Type.AttributeValue xs) + +addResult :: Request -> Response -> Either ResponseError () +addResult req (Type.AddResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +addResult req res = Left (ResponseInvalid req res)
diff --git a/src/Ldap-Client-Bind.html b/src/Ldap-Client-Bind.html index f7f5cc1..0ae7f15 100644 --- a/src/Ldap-Client-Bind.html +++ b/src/Ldap-Client-Bind.html @@ -24,60 +24,63 @@ ( Password(..) , bind , bindEither - , bindAsync - , bindAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.ByteString (ByteString) -import Data.List.NonEmpty (NonEmpty((:|))) - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal + , Async + , bindAsync + , bindAsyncSTM + , wait + , waitSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.ByteString (ByteString) +import Data.List.NonEmpty (NonEmpty((:|))) - --- | User's password. -newtype Password = Password ByteString - deriving (Show, Eq) - --- | Perform the Bind operation synchronously. Raises 'ResponseError' on failures. -bind :: Ldap -> Dn -> Password -> IO () -bind l username password = - raise =<< bindEither l username password - --- | Perform the Bind operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) -bindEither l username password = - wait =<< bindAsync l username password - --- | Perform the Bind operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) -bindAsync l username password = - atomically (bindAsyncSTM l username password) - --- | Perform the Bind operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) -bindAsyncSTM l username password = - let req = bindRequest username password in sendRequest l (bindResult req) req - -bindRequest :: Dn -> Password -> Request -bindRequest (Dn username) (Password password) = - Type.BindRequest ldapVersion - (Type.LdapDn (Type.LdapString username)) - (Type.Simple password) - where - ldapVersion = 3 - -bindResult :: Request -> Response -> Either ResponseError () -bindResult req (Type.BindResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) _ :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -bindResult req res = Left (ResponseInvalid req res) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | User's password. +newtype Password = Password ByteString + deriving (Show, Eq) + +-- | Perform the Bind operation synchronously. Raises 'ResponseError' on failures. +bind :: Ldap -> Dn -> Password -> IO () +bind l username password = + raise =<< bindEither l username password + +-- | Perform the Bind operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +bindEither :: Ldap -> Dn -> Password -> IO (Either ResponseError ()) +bindEither l username password = + wait =<< bindAsync l username password + +-- | Perform the Bind operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +bindAsync :: Ldap -> Dn -> Password -> IO (Async ()) +bindAsync l username password = + atomically (bindAsyncSTM l username password) + +-- | Perform the Bind operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +bindAsyncSTM :: Ldap -> Dn -> Password -> STM (Async ()) +bindAsyncSTM l username password = + let req = bindRequest username password in sendRequest l (bindResult req) req + +bindRequest :: Dn -> Password -> Request +bindRequest (Dn username) (Password password) = + Type.BindRequest ldapVersion + (Type.LdapDn (Type.LdapString username)) + (Type.Simple password) + where + ldapVersion = 3 + +bindResult :: Request -> Response -> Either ResponseError () +bindResult req (Type.BindResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) _ :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +bindResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Compare.html b/src/Ldap-Client-Compare.html index 6f63061..f81bb63 100644 --- a/src/Ldap-Client-Compare.html +++ b/src/Ldap-Client-Compare.html @@ -24,56 +24,59 @@ module Ldap.Client.Compare ( compare , compareEither - , compareAsync - , compareAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) -import Prelude hiding (compare) - -import Ldap.Client.Internal -import qualified Ldap.Asn1.Type as Type + , Async + , compareAsync + , compareAsyncSTM + , wait + , waitSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.List.NonEmpty (NonEmpty((:|))) +import Prelude hiding (compare) - --- | Perform the Compare operation synchronously. Raises 'ResponseError' on failures. -compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool -compare l dn k v = - raise =<< compareEither l dn k v - --- | Perform the Compare operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -compareEither :: Ldap -> Dn -> Attr -> AttrValue -> IO (Either ResponseError Bool) -compareEither l dn k v = - wait =<< compareAsync l dn k v - --- | Perform the Compare operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -compareAsync :: Ldap -> Dn -> Attr -> AttrValue -> IO (Async Bool) -compareAsync l dn k v = - atomically (compareAsyncSTM l dn k v) - --- | Perform the Compare operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -compareAsyncSTM :: Ldap -> Dn -> Attr -> AttrValue -> STM (Async Bool) -compareAsyncSTM l dn k v = - let req = compareRequest dn k v in sendRequest l (compareResult req) req - -compareRequest :: Dn -> Attr -> AttrValue -> Request -compareRequest (Dn dn) (Attr k) v = - Type.CompareRequest (Type.LdapDn (Type.LdapString dn)) - (Type.AttributeValueAssertion - (Type.AttributeDescription (Type.LdapString k)) - (Type.AssertionValue v)) - -compareResult :: Request -> Response -> Either ResponseError Bool -compareResult req (Type.CompareResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) :| []) - | Type.CompareTrue <- code = Right True - | Type.CompareFalse <- code = Right False - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -compareResult req res = Left (ResponseInvalid req res) +import Ldap.Client.Internal +import qualified Ldap.Asn1.Type as Type + + +-- | Perform the Compare operation synchronously. Raises 'ResponseError' on failures. +compare :: Ldap -> Dn -> Attr -> AttrValue -> IO Bool +compare l dn k v = + raise =<< compareEither l dn k v + +-- | Perform the Compare operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +compareEither :: Ldap -> Dn -> Attr -> AttrValue -> IO (Either ResponseError Bool) +compareEither l dn k v = + wait =<< compareAsync l dn k v + +-- | Perform the Compare operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +compareAsync :: Ldap -> Dn -> Attr -> AttrValue -> IO (Async Bool) +compareAsync l dn k v = + atomically (compareAsyncSTM l dn k v) + +-- | Perform the Compare operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +compareAsyncSTM :: Ldap -> Dn -> Attr -> AttrValue -> STM (Async Bool) +compareAsyncSTM l dn k v = + let req = compareRequest dn k v in sendRequest l (compareResult req) req + +compareRequest :: Dn -> Attr -> AttrValue -> Request +compareRequest (Dn dn) (Attr k) v = + Type.CompareRequest (Type.LdapDn (Type.LdapString dn)) + (Type.AttributeValueAssertion + (Type.AttributeDescription (Type.LdapString k)) + (Type.AssertionValue v)) + +compareResult :: Request -> Response -> Either ResponseError Bool +compareResult req (Type.CompareResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) :| []) + | Type.CompareTrue <- code = Right True + | Type.CompareFalse <- code = Right False + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +compareResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Delete.html b/src/Ldap-Client-Delete.html index de4b288..ac8b547 100644 --- a/src/Ldap-Client-Delete.html +++ b/src/Ldap-Client-Delete.html @@ -23,51 +23,54 @@ module Ldap.Client.Delete ( delete , deleteEither - , deleteAsync - , deleteAsyncSTM - ) where - -import Control.Concurrent.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) + , Async + , deleteAsync + , deleteAsyncSTM + , wait + , waitSTM + ) where -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal +import Control.Concurrent.STM (STM, atomically) +import Data.List.NonEmpty (NonEmpty((:|))) - --- | Perform the Delete operation synchronously. Raises 'ResponseError' on failures. -delete :: Ldap -> Dn -> IO () -delete l dn = - raise =<< deleteEither l dn - --- | Perform the Delete operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -deleteEither :: Ldap -> Dn -> IO (Either ResponseError ()) -deleteEither l dn = - wait =<< deleteAsync l dn - --- | Perform the Delete operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -deleteAsync :: Ldap -> Dn -> IO (Async ()) -deleteAsync l dn = - atomically (deleteAsyncSTM l dn) - --- | Perform the Delete operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -deleteAsyncSTM :: Ldap -> Dn -> STM (Async ()) -deleteAsyncSTM l dn = - let req = deleteRequest dn in sendRequest l (deleteResult req) req - -deleteRequest :: Dn -> Request -deleteRequest (Dn dn) = - Type.DeleteRequest (Type.LdapDn (Type.LdapString dn)) - -deleteResult :: Request -> Response -> Either ResponseError () -deleteResult req (Type.DeleteResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -deleteResult req res = Left (ResponseInvalid req res) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Perform the Delete operation synchronously. Raises 'ResponseError' on failures. +delete :: Ldap -> Dn -> IO () +delete l dn = + raise =<< deleteEither l dn + +-- | Perform the Delete operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +deleteEither :: Ldap -> Dn -> IO (Either ResponseError ()) +deleteEither l dn = + wait =<< deleteAsync l dn + +-- | Perform the Delete operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +deleteAsync :: Ldap -> Dn -> IO (Async ()) +deleteAsync l dn = + atomically (deleteAsyncSTM l dn) + +-- | Perform the Delete operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +deleteAsyncSTM :: Ldap -> Dn -> STM (Async ()) +deleteAsyncSTM l dn = + let req = deleteRequest dn in sendRequest l (deleteResult req) req + +deleteRequest :: Dn -> Request +deleteRequest (Dn dn) = + Type.DeleteRequest (Type.LdapDn (Type.LdapString dn)) + +deleteResult :: Request -> Response -> Either ResponseError () +deleteResult req (Type.DeleteResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +deleteResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Extended.html b/src/Ldap-Client-Extended.html index 2b5dd47..22e3a34 100644 --- a/src/Ldap-Client-Extended.html +++ b/src/Ldap-Client-Extended.html @@ -32,80 +32,83 @@ , startTlsEither , startTlsAsync , startTlsAsyncSTM - ) where - -import Control.Monad ((<=<)) -import Control.Monad.STM (STM, atomically) -import Data.ByteString (ByteString) -import Data.List.NonEmpty (NonEmpty((:|))) -import Data.String (fromString) -import Data.Text (Text) - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal + , Async + , wait + , waitSTM + ) where + +import Control.Monad ((<=<)) +import Control.Monad.STM (STM, atomically) +import Data.ByteString (ByteString) +import Data.List.NonEmpty (NonEmpty((:|))) +import Data.String (fromString) +import Data.Text (Text) - --- | Globally unique LDAP object identifier. -newtype Oid = Oid Text - deriving (Show, Eq) - --- | Perform the Extended operation synchronously. Raises 'ResponseError' on failures. -extended :: Ldap -> Oid -> Maybe ByteString -> IO () -extended l oid mv = - raise =<< extendedEither l oid mv - --- | Perform the Extended operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) -extendedEither l oid mv = - wait =<< extendedAsync l oid mv - --- | Perform the Extended operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) -extendedAsync l oid mv = - atomically (extendedAsyncSTM l oid mv) - --- | Perform the Extended operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) -extendedAsyncSTM l oid mv = - let req = extendedRequest oid mv in sendRequest l (extendedResult req) req - -extendedRequest :: Oid -> Maybe ByteString -> Request -extendedRequest (Oid oid) = - Type.ExtendedRequest (Type.LdapOid oid) - -extendedResult :: Request -> Response -> Either ResponseError () -extendedResult req (Type.ExtendedResponse - (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString msg) _) _ _ :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -extendedResult req res = Left (ResponseInvalid req res) - - --- | An example of @Extended Operation@, cf. 'extended'. -startTls :: Ldap -> IO () -startTls = - raise <=< startTlsEither - --- | An example of @Extended Operation@, cf. 'extendedEither'. -startTlsEither :: Ldap -> IO (Either ResponseError ()) -startTlsEither = - wait <=< startTlsAsync - --- | An example of @Extended Operation@, cf. 'extendedAsync'. -startTlsAsync :: Ldap -> IO (Async ()) -startTlsAsync = - atomically . startTlsAsyncSTM - --- | An example of @Extended Operation@, cf. 'extendedAsyncSTM'. -startTlsAsyncSTM :: Ldap -> STM (Async ()) -startTlsAsyncSTM l = - extendedAsyncSTM l (Oid (fromString "1.3.6.1.4.1.1466.20037")) - Nothing +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Globally unique LDAP object identifier. +newtype Oid = Oid Text + deriving (Show, Eq) + +-- | Perform the Extended operation synchronously. Raises 'ResponseError' on failures. +extended :: Ldap -> Oid -> Maybe ByteString -> IO () +extended l oid mv = + raise =<< extendedEither l oid mv + +-- | Perform the Extended operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +extendedEither :: Ldap -> Oid -> Maybe ByteString -> IO (Either ResponseError ()) +extendedEither l oid mv = + wait =<< extendedAsync l oid mv + +-- | Perform the Extended operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +extendedAsync :: Ldap -> Oid -> Maybe ByteString -> IO (Async ()) +extendedAsync l oid mv = + atomically (extendedAsyncSTM l oid mv) + +-- | Perform the Extended operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +extendedAsyncSTM :: Ldap -> Oid -> Maybe ByteString -> STM (Async ()) +extendedAsyncSTM l oid mv = + let req = extendedRequest oid mv in sendRequest l (extendedResult req) req + +extendedRequest :: Oid -> Maybe ByteString -> Request +extendedRequest (Oid oid) = + Type.ExtendedRequest (Type.LdapOid oid) + +extendedResult :: Request -> Response -> Either ResponseError () +extendedResult req (Type.ExtendedResponse + (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString msg) _) _ _ :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +extendedResult req res = Left (ResponseInvalid req res) + + +-- | An example of @Extended Operation@, cf. 'extended'. +startTls :: Ldap -> IO () +startTls = + raise <=< startTlsEither + +-- | An example of @Extended Operation@, cf. 'extendedEither'. +startTlsEither :: Ldap -> IO (Either ResponseError ()) +startTlsEither = + wait <=< startTlsAsync + +-- | An example of @Extended Operation@, cf. 'extendedAsync'. +startTlsAsync :: Ldap -> IO (Async ()) +startTlsAsync = + atomically . startTlsAsyncSTM + +-- | An example of @Extended Operation@, cf. 'extendedAsyncSTM'. +startTlsAsyncSTM :: Ldap -> STM (Async ()) +startTlsAsyncSTM l = + extendedAsyncSTM l (Oid (fromString "1.3.6.1.4.1.1466.20037")) + Nothing diff --git a/src/Ldap-Client-Modify.html b/src/Ldap-Client-Modify.html index ee6a204..1c53f32 100644 --- a/src/Ldap-Client-Modify.html +++ b/src/Ldap-Client-Modify.html @@ -34,109 +34,112 @@ , modifyDnEither , modifyDnAsync , modifyDnAsyncSTM - ) where - -import Control.Monad.STM (STM, atomically) -import Data.List.NonEmpty (NonEmpty((:|))) -import Data.Text (Text) - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal + , Async + , wait + , waitSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.List.NonEmpty (NonEmpty((:|))) +import Data.Text (Text) - --- | Type of modification being performed. -data Operation = - Delete Attr [AttrValue] -- ^ Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed. - | Add Attr [AttrValue] -- ^ Add values to the attribute, creating it if necessary. - | Replace Attr [AttrValue] -- ^ Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty. - deriving (Show, Eq) - --- | Perform the Modify operation synchronously. Raises 'ResponseError' on failures. -modify :: Ldap -> Dn -> [Operation] -> IO () -modify l dn as = - raise =<< modifyEither l dn as - --- | Perform the Modify operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) -modifyEither l dn as = - wait =<< modifyAsync l dn as - --- | Perform the Modify operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) -modifyAsync l dn as = - atomically (modifyAsyncSTM l dn as) - --- | Perform the Modify operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) -modifyAsyncSTM l dn xs = - let req = modifyRequest dn xs in sendRequest l (modifyResult req) req - -modifyRequest :: Dn -> [Operation] -> Request -modifyRequest (Dn dn) xs = - Type.ModifyRequest (Type.LdapDn (Type.LdapString dn)) (map f xs) - where - f (Delete (Attr k) vs) = - (Type.Delete, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - f (Add (Attr k) vs) = - (Type.Add, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - f (Replace (Attr k) vs) = - (Type.Replace, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) - (map Type.AttributeValue vs)) - -modifyResult :: Request -> Response -> Either ResponseError () -modifyResult req (Type.ModifyResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -modifyResult req res = Left (ResponseInvalid req res) - - --- | A component of 'Dn'. -newtype RelativeDn = RelativeDn Text - deriving (Show, Eq) - --- | Perform the Modify DN operation synchronously. Raises 'ResponseError' on failures. -modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () -modifyDn l dn rdn del new = - raise =<< modifyDnEither l dn rdn del new - --- | Perform the Modify DN operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) -modifyDnEither l dn rdn del new = - wait =<< modifyDnAsync l dn rdn del new - --- | Perform the Modify DN operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) -modifyDnAsync l dn rdn del new = - atomically (modifyDnAsyncSTM l dn rdn del new) - --- | Perform the Modify DN operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) -modifyDnAsyncSTM l dn rdn del new = - let req = modifyDnRequest dn rdn del new in sendRequest l (modifyDnResult req) req - -modifyDnRequest :: Dn -> RelativeDn -> Bool -> Maybe Dn -> Request -modifyDnRequest (Dn dn) (RelativeDn rdn) del new = - Type.ModifyDnRequest (Type.LdapDn (Type.LdapString dn)) - (Type.RelativeLdapDn (Type.LdapString rdn)) - del - (fmap (\(Dn dn') -> Type.LdapDn (Type.LdapString dn')) new) - -modifyDnResult :: Request -> Response -> Either ResponseError () -modifyDnResult req (Type.ModifyDnResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) - | Type.Success <- code = Right () - | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) -modifyDnResult req res = Left (ResponseInvalid req res) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Type of modification being performed. +data Operation = + Delete Attr [AttrValue] -- ^ Delete values from the attribute. Deletes the attribute if the list is empty or all current values are listed. + | Add Attr [AttrValue] -- ^ Add values to the attribute, creating it if necessary. + | Replace Attr [AttrValue] -- ^ Replace all existing values of the attribute with the new list. Deletes the attribute if the list is empty. + deriving (Show, Eq) + +-- | Perform the Modify operation synchronously. Raises 'ResponseError' on failures. +modify :: Ldap -> Dn -> [Operation] -> IO () +modify l dn as = + raise =<< modifyEither l dn as + +-- | Perform the Modify operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +modifyEither :: Ldap -> Dn -> [Operation] -> IO (Either ResponseError ()) +modifyEither l dn as = + wait =<< modifyAsync l dn as + +-- | Perform the Modify operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +modifyAsync :: Ldap -> Dn -> [Operation] -> IO (Async ()) +modifyAsync l dn as = + atomically (modifyAsyncSTM l dn as) + +-- | Perform the Modify operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +modifyAsyncSTM :: Ldap -> Dn -> [Operation] -> STM (Async ()) +modifyAsyncSTM l dn xs = + let req = modifyRequest dn xs in sendRequest l (modifyResult req) req + +modifyRequest :: Dn -> [Operation] -> Request +modifyRequest (Dn dn) xs = + Type.ModifyRequest (Type.LdapDn (Type.LdapString dn)) (map f xs) + where + f (Delete (Attr k) vs) = + (Type.Delete, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + f (Add (Attr k) vs) = + (Type.Add, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + f (Replace (Attr k) vs) = + (Type.Replace, Type.PartialAttribute (Type.AttributeDescription (Type.LdapString k)) + (map Type.AttributeValue vs)) + +modifyResult :: Request -> Response -> Either ResponseError () +modifyResult req (Type.ModifyResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +modifyResult req res = Left (ResponseInvalid req res) + + +-- | A component of 'Dn'. +newtype RelativeDn = RelativeDn Text + deriving (Show, Eq) + +-- | Perform the Modify DN operation synchronously. Raises 'ResponseError' on failures. +modifyDn :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO () +modifyDn l dn rdn del new = + raise =<< modifyDnEither l dn rdn del new + +-- | Perform the Modify DN operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +modifyDnEither :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Either ResponseError ()) +modifyDnEither l dn rdn del new = + wait =<< modifyDnAsync l dn rdn del new + +-- | Perform the Modify DN operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +modifyDnAsync :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> IO (Async ()) +modifyDnAsync l dn rdn del new = + atomically (modifyDnAsyncSTM l dn rdn del new) + +-- | Perform the Modify DN operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +modifyDnAsyncSTM :: Ldap -> Dn -> RelativeDn -> Bool -> Maybe Dn -> STM (Async ()) +modifyDnAsyncSTM l dn rdn del new = + let req = modifyDnRequest dn rdn del new in sendRequest l (modifyDnResult req) req + +modifyDnRequest :: Dn -> RelativeDn -> Bool -> Maybe Dn -> Request +modifyDnRequest (Dn dn) (RelativeDn rdn) del new = + Type.ModifyDnRequest (Type.LdapDn (Type.LdapString dn)) + (Type.RelativeLdapDn (Type.LdapString rdn)) + del + (fmap (\(Dn dn') -> Type.LdapDn (Type.LdapString dn')) new) + +modifyDnResult :: Request -> Response -> Either ResponseError () +modifyDnResult req (Type.ModifyDnResponse (Type.LdapResult code (Type.LdapDn (Type.LdapString dn)) (Type.LdapString msg) _) :| []) + | Type.Success <- code = Right () + | otherwise = Left (ResponseErrorCode req code (Dn dn) msg) +modifyDnResult req res = Left (ResponseInvalid req res) diff --git a/src/Ldap-Client-Search.html b/src/Ldap-Client-Search.html index 65781ea..40813a0 100644 --- a/src/Ldap-Client-Search.html +++ b/src/Ldap-Client-Search.html @@ -25,207 +25,210 @@ module Ldap.Client.Search ( search , searchEither - , searchAsync - , searchAsyncSTM - , Search - , Mod - , Type.Scope(..) - , scope - , size - , time - , typesOnly - , Type.DerefAliases(..) - , derefAliases - , Filter(..) - , SearchEntry(..) - ) where - -import Control.Monad.STM (STM, atomically) -import Data.Int (Int32) -import Data.List.NonEmpty (NonEmpty((:|))) -import qualified Data.List.NonEmpty as NonEmpty -import Data.Maybe (mapMaybe) -#if __GLASGOW_HASKELL__ >= 710 -import Data.Semigroup (Semigroup(..)) -#else -import Data.Semigroup (Semigroup(..), Monoid(..)) -#endif - -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal + , Async + , searchAsync + , searchAsyncSTM + , Search + , Mod + , Type.Scope(..) + , scope + , size + , time + , typesOnly + , Type.DerefAliases(..) + , derefAliases + , Filter(..) + , SearchEntry(..) + , wait + , waitSTM + ) where + +import Control.Monad.STM (STM, atomically) +import Data.Int (Int32) +import Data.List.NonEmpty (NonEmpty((:|))) +import qualified Data.List.NonEmpty as NonEmpty +import Data.Maybe (mapMaybe) +#if __GLASGOW_HASKELL__ >= 710 +import Data.Semigroup (Semigroup(..)) +#else +import Data.Semigroup (Semigroup(..), Monoid(..)) +#endif - --- | Perform the Search operation synchronously. Raises 'ResponseError' on failures. -search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] -search l base opts flt attributes = - raise =<< searchEither l base opts flt attributes - --- | Perform the Search operation synchronously. Returns @Left e@ where --- @e@ is a 'ResponseError' on failures. -searchEither - :: Ldap - -> Dn - -> Mod Search - -> Filter - -> [Attr] - -> IO (Either ResponseError [SearchEntry]) -searchEither l base opts flt attributes = - wait =<< searchAsync l base opts flt attributes - --- | Perform the Search operation asynchronously. Call 'Ldap.Client.wait' to wait --- for its completion. -searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) -searchAsync l base opts flt attributes = - atomically (searchAsyncSTM l base opts flt attributes) - --- | Perform the Search operation asynchronously. --- --- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the --- same transaction you've performed it in. -searchAsyncSTM - :: Ldap - -> Dn - -> Mod Search - -> Filter - -> [Attr] - -> STM (Async [SearchEntry]) -searchAsyncSTM l base opts flt attributes = - let req = searchRequest base opts flt attributes in sendRequest l (searchResult req) req - -searchRequest :: Dn -> Mod Search -> Filter -> [Attr] -> Request -searchRequest (Dn base) (Mod m) flt attributes = - Type.SearchRequest (Type.LdapDn (Type.LdapString base)) - _scope - _derefAliases - _size - _time - _typesOnly - (fromFilter flt) - (Type.AttributeSelection (map (Type.LdapString . unAttr) attributes)) - where - Search { _scope, _derefAliases, _size, _time, _typesOnly } = - m defaultSearch - fromFilter (Not x) = Type.Not (fromFilter x) - fromFilter (And xs) = Type.And (fmap fromFilter xs) - fromFilter (Or xs) = Type.Or (fmap fromFilter xs) - fromFilter (Present (Attr x)) = - Type.Present (Type.AttributeDescription (Type.LdapString x)) - fromFilter (Attr x := y) = - Type.EqualityMatch - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :>= y) = - Type.GreaterOrEqual - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :<= y) = - Type.LessOrEqual - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :~= y) = - Type.ApproxMatch - (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) - (Type.AssertionValue y)) - fromFilter (Attr x :=* (mi, xs, mf)) = - Type.Substrings - (Type.SubstringFilter (Type.AttributeDescription (Type.LdapString x)) - (NonEmpty.fromList (concat - [ maybe [] (\i -> [Type.Initial (Type.AssertionValue i)]) mi - , fmap (Type.Any . Type.AssertionValue) xs - , maybe [] (\f -> [Type.Final (Type.AssertionValue f)]) mf - ]))) - fromFilter ((mx, mr, b) ::= y) = - Type.ExtensibleMatch - (Type.MatchingRuleAssertion (fmap (\(Attr r) -> Type.MatchingRuleId (Type.LdapString r)) mr) - (fmap (\(Attr x) -> Type.AttributeDescription (Type.LdapString x)) mx) - (Type.AssertionValue y) - b) - -searchResult :: Request -> Response -> Either ResponseError [SearchEntry] -searchResult req (Type.SearchResultDone (Type.LdapResult code (Type.LdapDn (Type.LdapString dn')) - (Type.LdapString msg) _) :| xs) - | Type.Success <- code = Right (mapMaybe g xs) - | Type.AdminLimitExceeded <- code = Right (mapMaybe g xs) - | Type.SizeLimitExceeded <- code = Right (mapMaybe g xs) - | otherwise = Left (ResponseErrorCode req code (Dn dn') msg) - where - g (Type.SearchResultEntry (Type.LdapDn (Type.LdapString dn)) - (Type.PartialAttributeList ys)) = - Just (SearchEntry (Dn dn) (map h ys)) - g _ = Nothing - h (Type.PartialAttribute (Type.AttributeDescription (Type.LdapString x)) - y) = (Attr x, fmap j y) - j (Type.AttributeValue x) = x -searchResult req res = Left (ResponseInvalid req res) - --- | Search options. Use 'Mod' to change some of those. -data Search = Search - { _scope :: !Type.Scope - , _derefAliases :: !Type.DerefAliases - , _size :: !Int32 - , _time :: !Int32 - , _typesOnly :: !Bool - } deriving (Show, Eq) - -defaultSearch :: Search -defaultSearch = Search - { _scope = Type.WholeSubtree - , _size = 0 - , _time = 0 - , _typesOnly = False - , _derefAliases = Type.NeverDerefAliases - } - --- | Scope of the search (default: 'WholeSubtree'). -scope :: Type.Scope -> Mod Search -scope x = Mod (\y -> y { _scope = x }) - --- | Maximum number of entries to be returned as a result of the Search. --- No limit if the value is @0@ (default: @0@). -size :: Int32 -> Mod Search -size x = Mod (\y -> y { _size = x }) - --- | Maximum time (in seconds) allowed for the Search. No limit if the value --- is @0@ (default: @0@). -time :: Int32 -> Mod Search -time x = Mod (\y -> y { _time = x }) - --- | Whether Search results are to contain just attribute descriptions, or --- both attribute descriptions and values (default: 'False'). -typesOnly :: Bool -> Mod Search -typesOnly x = Mod (\y -> y { _typesOnly = x }) - --- | Alias dereference policy (default: 'NeverDerefAliases'). -derefAliases :: Type.DerefAliases -> Mod Search -derefAliases x = Mod (\y -> y { _derefAliases = x }) - --- | Search modifier. Combine using 'Semigroup' and/or 'Monoid' instance. -newtype Mod a = Mod (a -> a) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal + + +-- | Perform the Search operation synchronously. Raises 'ResponseError' on failures. +search :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO [SearchEntry] +search l base opts flt attributes = + raise =<< searchEither l base opts flt attributes + +-- | Perform the Search operation synchronously. Returns @Left e@ where +-- @e@ is a 'ResponseError' on failures. +searchEither + :: Ldap + -> Dn + -> Mod Search + -> Filter + -> [Attr] + -> IO (Either ResponseError [SearchEntry]) +searchEither l base opts flt attributes = + wait =<< searchAsync l base opts flt attributes + +-- | Perform the Search operation asynchronously. Call 'Ldap.Client.wait' to wait +-- for its completion. +searchAsync :: Ldap -> Dn -> Mod Search -> Filter -> [Attr] -> IO (Async [SearchEntry]) +searchAsync l base opts flt attributes = + atomically (searchAsyncSTM l base opts flt attributes) + +-- | Perform the Search operation asynchronously. +-- +-- Don't wait for its completion (with 'Ldap.Client.waitSTM') in the +-- same transaction you've performed it in. +searchAsyncSTM + :: Ldap + -> Dn + -> Mod Search + -> Filter + -> [Attr] + -> STM (Async [SearchEntry]) +searchAsyncSTM l base opts flt attributes = + let req = searchRequest base opts flt attributes in sendRequest l (searchResult req) req + +searchRequest :: Dn -> Mod Search -> Filter -> [Attr] -> Request +searchRequest (Dn base) (Mod m) flt attributes = + Type.SearchRequest (Type.LdapDn (Type.LdapString base)) + _scope + _derefAliases + _size + _time + _typesOnly + (fromFilter flt) + (Type.AttributeSelection (map (Type.LdapString . unAttr) attributes)) + where + Search { _scope, _derefAliases, _size, _time, _typesOnly } = + m defaultSearch + fromFilter (Not x) = Type.Not (fromFilter x) + fromFilter (And xs) = Type.And (fmap fromFilter xs) + fromFilter (Or xs) = Type.Or (fmap fromFilter xs) + fromFilter (Present (Attr x)) = + Type.Present (Type.AttributeDescription (Type.LdapString x)) + fromFilter (Attr x := y) = + Type.EqualityMatch + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :>= y) = + Type.GreaterOrEqual + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :<= y) = + Type.LessOrEqual + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :~= y) = + Type.ApproxMatch + (Type.AttributeValueAssertion (Type.AttributeDescription (Type.LdapString x)) + (Type.AssertionValue y)) + fromFilter (Attr x :=* (mi, xs, mf)) = + Type.Substrings + (Type.SubstringFilter (Type.AttributeDescription (Type.LdapString x)) + (NonEmpty.fromList (concat + [ maybe [] (\i -> [Type.Initial (Type.AssertionValue i)]) mi + , fmap (Type.Any . Type.AssertionValue) xs + , maybe [] (\f -> [Type.Final (Type.AssertionValue f)]) mf + ]))) + fromFilter ((mx, mr, b) ::= y) = + Type.ExtensibleMatch + (Type.MatchingRuleAssertion (fmap (\(Attr r) -> Type.MatchingRuleId (Type.LdapString r)) mr) + (fmap (\(Attr x) -> Type.AttributeDescription (Type.LdapString x)) mx) + (Type.AssertionValue y) + b) + +searchResult :: Request -> Response -> Either ResponseError [SearchEntry] +searchResult req (Type.SearchResultDone (Type.LdapResult code (Type.LdapDn (Type.LdapString dn')) + (Type.LdapString msg) _) :| xs) + | Type.Success <- code = Right (mapMaybe g xs) + | Type.AdminLimitExceeded <- code = Right (mapMaybe g xs) + | Type.SizeLimitExceeded <- code = Right (mapMaybe g xs) + | otherwise = Left (ResponseErrorCode req code (Dn dn') msg) + where + g (Type.SearchResultEntry (Type.LdapDn (Type.LdapString dn)) + (Type.PartialAttributeList ys)) = + Just (SearchEntry (Dn dn) (map h ys)) + g _ = Nothing + h (Type.PartialAttribute (Type.AttributeDescription (Type.LdapString x)) + y) = (Attr x, fmap j y) + j (Type.AttributeValue x) = x +searchResult req res = Left (ResponseInvalid req res) + +-- | Search options. Use 'Mod' to change some of those. +data Search = Search + { _scope :: !Type.Scope + , _derefAliases :: !Type.DerefAliases + , _size :: !Int32 + , _time :: !Int32 + , _typesOnly :: !Bool + } deriving (Show, Eq) + +defaultSearch :: Search +defaultSearch = Search + { _scope = Type.WholeSubtree + , _size = 0 + , _time = 0 + , _typesOnly = False + , _derefAliases = Type.NeverDerefAliases + } + +-- | Scope of the search (default: 'WholeSubtree'). +scope :: Type.Scope -> Mod Search +scope x = Mod (\y -> y { _scope = x }) + +-- | Maximum number of entries to be returned as a result of the Search. +-- No limit if the value is @0@ (default: @0@). +size :: Int32 -> Mod Search +size x = Mod (\y -> y { _size = x }) + +-- | Maximum time (in seconds) allowed for the Search. No limit if the value +-- is @0@ (default: @0@). +time :: Int32 -> Mod Search +time x = Mod (\y -> y { _time = x }) + +-- | Whether Search results are to contain just attribute descriptions, or +-- both attribute descriptions and values (default: 'False'). +typesOnly :: Bool -> Mod Search +typesOnly x = Mod (\y -> y { _typesOnly = x }) + +-- | Alias dereference policy (default: 'NeverDerefAliases'). +derefAliases :: Type.DerefAliases -> Mod Search +derefAliases x = Mod (\y -> y { _derefAliases = x }) -instance Semigroup (Mod a) where - Mod f <> Mod g = Mod (g . f) +-- | Search modifier. Combine using 'Semigroup' and/or 'Monoid' instance. +newtype Mod a = Mod (a -> a) -instance Monoid (Mod a) where - mempty = Mod id - mappend = (<>) - --- | Conditions that must be fulfilled in order for the Search to match a given entry. -data Filter = - Not !Filter -- ^ Filter does not match the entry - | And !(NonEmpty Filter) -- ^ All filters match the entry - | Or !(NonEmpty Filter) -- ^ Any filter matches the entry - | Present !Attr -- ^ Attribute is present in the entry - | !Attr := !AttrValue -- ^ Attribute's value is equal to the assertion - | !Attr :>= !AttrValue -- ^ Attribute's value is equal to or greater than the assertion - | !Attr :<= !AttrValue -- ^ Attribute's value is equal to or less than the assertion - | !Attr :~= !AttrValue -- ^ Attribute's value approximately matches the assertion - | !Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue) - -- ^ Glob match - | (Maybe Attr, Maybe Attr, Bool) ::= AttrValue - -- ^ Extensible match - --- | Entry found during the Search. -data SearchEntry = SearchEntry !Dn !(AttrList []) - deriving (Show, Eq) +instance Semigroup (Mod a) where + Mod f <> Mod g = Mod (g . f) + +instance Monoid (Mod a) where + mempty = Mod id + mappend = (<>) + +-- | Conditions that must be fulfilled in order for the Search to match a given entry. +data Filter = + Not !Filter -- ^ Filter does not match the entry + | And !(NonEmpty Filter) -- ^ All filters match the entry + | Or !(NonEmpty Filter) -- ^ Any filter matches the entry + | Present !Attr -- ^ Attribute is present in the entry + | !Attr := !AttrValue -- ^ Attribute's value is equal to the assertion + | !Attr :>= !AttrValue -- ^ Attribute's value is equal to or greater than the assertion + | !Attr :<= !AttrValue -- ^ Attribute's value is equal to or less than the assertion + | !Attr :~= !AttrValue -- ^ Attribute's value approximately matches the assertion + | !Attr :=* !(Maybe AttrValue, [AttrValue], Maybe AttrValue) + -- ^ Glob match + | (Maybe Attr, Maybe Attr, Bool) ::= AttrValue + -- ^ Extensible match + +-- | Entry found during the Search. +data SearchEntry = SearchEntry !Dn !(AttrList []) + deriving (Show, Eq) diff --git a/src/Ldap-Client.html b/src/Ldap-Client.html index 58ecd01..29d7327 100644 --- a/src/Ldap-Client.html +++ b/src/Ldap-Client.html @@ -20,257 +20,254 @@ , LdapError(..) , ResponseError(..) , Type.ResultCode(..) - , Async - -- * Bind - , Password(..) - , bind - -- * Search - , search - , SearchEntry(..) - -- ** Search modifiers - , Search - , Mod - , Type.Scope(..) - , scope - , size - , time - , typesOnly - , Type.DerefAliases(..) - , derefAliases - , Filter(..) - -- * Modify - , modify - , Operation(..) - -- * Add - , add - -- * Delete - , delete - -- * ModifyDn - , RelativeDn(..) - , modifyDn - -- * Compare - , compare - -- * Extended - , Oid(..) - , extended - -- * Waiting for completion - , wait - -- * Miscellanous - , Dn(..) - , Attr(..) - , AttrValue - , AttrList - -- * Re-exports - , NonEmpty - ) where - -#if __GLASGOW_HASKELL__ < 710 -import Control.Applicative ((<$>)) -#endif -import qualified Control.Concurrent.Async as Async -import Control.Concurrent.STM (atomically, throwSTM) -import Control.Concurrent.STM.TMVar (putTMVar) -import Control.Concurrent.STM.TQueue (TQueue, newTQueueIO, writeTQueue, readTQueue) -import Control.Exception (Exception, Handler(..), bracket, throwIO, catch, catches) -import Control.Monad (forever) -import qualified Data.ASN1.BinaryEncoding as Asn1 -import qualified Data.ASN1.Encoding as Asn1 -import qualified Data.ASN1.Error as Asn1 -import qualified Data.ByteString as ByteString -import qualified Data.ByteString.Lazy as ByteString.Lazy -import Data.Foldable (asum) -import Data.Function (fix) -import Data.List.NonEmpty (NonEmpty((:|))) -import qualified Data.Map.Strict as Map -import Data.Monoid (Endo(appEndo)) -import Data.String (fromString) -import Data.Text (Text) -#if __GLASGOW_HASKELL__ < 710 -import Data.Traversable (traverse) -#endif -import Data.Typeable (Typeable) -import Network.Connection (Connection) -import qualified Network.Connection as Conn -import Prelude hiding (compare) -import qualified System.IO.Error as IO - -import Ldap.Asn1.ToAsn1 (ToAsn1(toAsn1)) -import Ldap.Asn1.FromAsn1 (FromAsn1, parseAsn1) -import qualified Ldap.Asn1.Type as Type -import Ldap.Client.Internal -import Ldap.Client.Bind (Password(..), bind) -import Ldap.Client.Search - ( search - , Search - , Mod - , scope - , size - , time - , typesOnly - , derefAliases - , Filter(..) - , SearchEntry(..) - ) -import Ldap.Client.Modify (Operation(..), modify, RelativeDn(..), modifyDn) -import Ldap.Client.Add (add) -import Ldap.Client.Delete (delete) -import Ldap.Client.Compare (compare) -import Ldap.Client.Extended (Oid(..), extended) + -- * Bind + , Password(..) + , bind + -- * Search + , search + , SearchEntry(..) + -- ** Search modifiers + , Search + , Mod + , Type.Scope(..) + , scope + , size + , time + , typesOnly + , Type.DerefAliases(..) + , derefAliases + , Filter(..) + -- * Modify + , modify + , Operation(..) + -- * Add + , add + -- * Delete + , delete + -- * ModifyDn + , RelativeDn(..) + , modifyDn + -- * Compare + , compare + -- * Extended + , Oid(..) + , extended + -- * Miscellanous + , Dn(..) + , Attr(..) + , AttrValue + , AttrList + -- * Re-exports + , NonEmpty + ) where + +#if __GLASGOW_HASKELL__ < 710 +import Control.Applicative ((<$>)) +#endif +import qualified Control.Concurrent.Async as Async +import Control.Concurrent.STM (atomically, throwSTM) +import Control.Concurrent.STM.TMVar (putTMVar) +import Control.Concurrent.STM.TQueue (TQueue, newTQueueIO, writeTQueue, readTQueue) +import Control.Exception (Exception, Handler(..), bracket, throwIO, catch, catches) +import Control.Monad (forever) +import qualified Data.ASN1.BinaryEncoding as Asn1 +import qualified Data.ASN1.Encoding as Asn1 +import qualified Data.ASN1.Error as Asn1 +import qualified Data.ByteString as ByteString +import qualified Data.ByteString.Lazy as ByteString.Lazy +import Data.Foldable (asum) +import Data.Function (fix) +import Data.List.NonEmpty (NonEmpty((:|))) +import qualified Data.Map.Strict as Map +import Data.Monoid (Endo(appEndo)) +import Data.String (fromString) +import Data.Text (Text) +#if __GLASGOW_HASKELL__ < 710 +import Data.Traversable (traverse) +#endif +import Data.Typeable (Typeable) +import Network.Connection (Connection) +import qualified Network.Connection as Conn +import Prelude hiding (compare) +import qualified System.IO.Error as IO + +import Ldap.Asn1.ToAsn1 (ToAsn1(toAsn1)) +import Ldap.Asn1.FromAsn1 (FromAsn1, parseAsn1) +import qualified Ldap.Asn1.Type as Type +import Ldap.Client.Internal +import Ldap.Client.Bind (Password(..), bind) +import Ldap.Client.Search + ( search + , Search + , Mod + , scope + , size + , time + , typesOnly + , derefAliases + , Filter(..) + , SearchEntry(..) + ) +import Ldap.Client.Modify (Operation(..), modify, RelativeDn(..), modifyDn) +import Ldap.Client.Add (add) +import Ldap.Client.Delete (delete) +import Ldap.Client.Compare (compare) +import Ldap.Client.Extended (Oid(..), extended) + +{-# ANN module "HLint: ignore Use first" #-} + -{-# ANN module "HLint: ignore Use first" #-} - - -newLdap :: IO Ldap -newLdap = Ldap - <$> newTQueueIO - --- | Various failures that can happen when working with LDAP. -data LdapError = - IOError IOError -- ^ Network failure. - | ParseError Asn1.ASN1Error -- ^ Invalid ASN.1 data received from the server. - | ResponseError ResponseError -- ^ An LDAP operation failed. - | DisconnectError Disconnect -- ^ Notice of Disconnection has been received. - deriving (Show, Eq) +newLdap :: IO Ldap +newLdap = Ldap + <$> newTQueueIO + +-- | Various failures that can happen when working with LDAP. +data LdapError = + IOError IOError -- ^ Network failure. + | ParseError Asn1.ASN1Error -- ^ Invalid ASN.1 data received from the server. + | ResponseError ResponseError -- ^ An LDAP operation failed. + | DisconnectError Disconnect -- ^ Notice of Disconnection has been received. + deriving (Show, Eq) + +newtype WrappedIOError = WrappedIOError IOError + deriving (Show, Eq, Typeable) -newtype WrappedIOError = WrappedIOError IOError - deriving (Show, Eq, Typeable) - -instance Exception WrappedIOError +instance Exception WrappedIOError + +data Disconnect = Disconnect Type.ResultCode Dn Text + deriving (Show, Eq, Typeable) -data Disconnect = Disconnect Type.ResultCode Dn Text - deriving (Show, Eq, Typeable) - -instance Exception Disconnect - --- | The entrypoint into LDAP. --- --- It catches all LDAP-related exceptions. -with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) -with host port f = do - context <- Conn.initConnectionContext - bracket (Conn.connectTo context params) Conn.connectionClose (\conn -> - bracket newLdap unbindAsync (\l -> do - inq <- newTQueueIO - outq <- newTQueueIO - as <- traverse Async.async - [ input inq conn - , output outq conn - , dispatch l inq outq - , f l - ] - fmap (Right . snd) (Async.waitAnyCancel as))) - `catches` - [ Handler (\(WrappedIOError e) -> return (Left (IOError e))) - , Handler (return . Left . ParseError) - , Handler (return . Left . ResponseError) - ] - where - params = Conn.ConnectionParams - { Conn.connectionHostname = - case host of - Plain h -> h - Secure h -> h - Insecure h -> h - , Conn.connectionPort = port - , Conn.connectionUseSecure = - case host of - Plain _ -> Nothing - Secure _ -> Just Conn.TLSSettingsSimple - { Conn.settingDisableCertificateValidation = False - , Conn.settingDisableSession = False - , Conn.settingUseServerName = False - } - Insecure _ -> Just Conn.TLSSettingsSimple - { Conn.settingDisableCertificateValidation = True - , Conn.settingDisableSession = False - , Conn.settingUseServerName = False - } - , Conn.connectionUseSocks = Nothing - } - -input :: FromAsn1 a => TQueue a -> Connection -> IO b -input inq conn = wrap . flip fix [] $ \loop chunks -> do - chunk <- Conn.connectionGet conn 8192 - case ByteString.length chunk of - 0 -> throwIO (IO.mkIOError IO.eofErrorType "Ldap.Client.input" Nothing Nothing) - _ -> do - let chunks' = chunk : chunks - case Asn1.decodeASN1 Asn1.DER (ByteString.Lazy.fromChunks (reverse chunks')) of - Left Asn1.ParsingPartial - -> loop chunks' - Left e -> throwIO e - Right asn1 -> do - flip fix asn1 $ \loop' asn1' -> - case parseAsn1 asn1' of - Nothing -> return () - Just (asn1'', a) -> do - atomically (writeTQueue inq a) - loop' asn1'' - loop [] - -output :: ToAsn1 a => TQueue a -> Connection -> IO b -output out conn = wrap . forever $ do - msg <- atomically (readTQueue out) - Conn.connectionPut conn (encode (toAsn1 msg)) - where - encode x = Asn1.encodeASN1' Asn1.DER (appEndo x []) - -dispatch - :: Ldap - -> TQueue (Type.LdapMessage Type.ProtocolServerOp) - -> TQueue (Type.LdapMessage Request) - -> IO a -dispatch Ldap { client } inq outq = - flip fix (Map.empty, 1) $ \loop (!req, !counter) -> - loop =<< atomically (asum - [ do New new var <- readTQueue client - writeTQueue outq (Type.LdapMessage (Type.Id counter) new Nothing) - return (Map.insert (Type.Id counter) ([], var) req, counter + 1) - , do Type.LdapMessage mid op _ - <- readTQueue inq - res <- case op of - Type.BindResponse {} -> done mid op req - Type.SearchResultEntry {} -> saveUp mid op req - Type.SearchResultReference {} -> return req - Type.SearchResultDone {} -> done mid op req - Type.ModifyResponse {} -> done mid op req - Type.AddResponse {} -> done mid op req - Type.DeleteResponse {} -> done mid op req - Type.ModifyDnResponse {} -> done mid op req - Type.CompareResponse {} -> done mid op req - Type.ExtendedResponse {} -> probablyDisconnect mid op req - Type.IntermediateResponse {} -> saveUp mid op req - return (res, counter) - ]) - where - saveUp mid op res = - return (Map.adjust (\(stack, var) -> (op : stack, var)) mid res) - - done mid op req = - case Map.lookup mid req of - Nothing -> return req - Just (stack, var) -> do - putTMVar var (op :| stack) - return (Map.delete mid req) - - probablyDisconnect (Type.Id 0) - (Type.ExtendedResponse - (Type.LdapResult code - (Type.LdapDn (Type.LdapString dn)) - (Type.LdapString reason) - _) - moid _) - req = - case moid of - Just (Type.LdapOid oid) - | oid == noticeOfDisconnection -> throwSTM (Disconnect code (Dn dn) reason) - _ -> return req - probablyDisconnect mid op req = done mid op req +instance Exception Disconnect + +-- | The entrypoint into LDAP. +-- +-- It catches all LDAP-related exceptions. +with :: Host -> PortNumber -> (Ldap -> IO a) -> IO (Either LdapError a) +with host port f = do + context <- Conn.initConnectionContext + bracket (Conn.connectTo context params) Conn.connectionClose (\conn -> + bracket newLdap unbindAsync (\l -> do + inq <- newTQueueIO + outq <- newTQueueIO + as <- traverse Async.async + [ input inq conn + , output outq conn + , dispatch l inq outq + , f l + ] + fmap (Right . snd) (Async.waitAnyCancel as))) + `catches` + [ Handler (\(WrappedIOError e) -> return (Left (IOError e))) + , Handler (return . Left . ParseError) + , Handler (return . Left . ResponseError) + ] + where + params = Conn.ConnectionParams + { Conn.connectionHostname = + case host of + Plain h -> h + Secure h -> h + Insecure h -> h + , Conn.connectionPort = port + , Conn.connectionUseSecure = + case host of + Plain _ -> Nothing + Secure _ -> Just Conn.TLSSettingsSimple + { Conn.settingDisableCertificateValidation = False + , Conn.settingDisableSession = False + , Conn.settingUseServerName = False + } + Insecure _ -> Just Conn.TLSSettingsSimple + { Conn.settingDisableCertificateValidation = True + , Conn.settingDisableSession = False + , Conn.settingUseServerName = False + } + , Conn.connectionUseSocks = Nothing + } + +input :: FromAsn1 a => TQueue a -> Connection -> IO b +input inq conn = wrap . flip fix [] $ \loop chunks -> do + chunk <- Conn.connectionGet conn 8192 + case ByteString.length chunk of + 0 -> throwIO (IO.mkIOError IO.eofErrorType "Ldap.Client.input" Nothing Nothing) + _ -> do + let chunks' = chunk : chunks + case Asn1.decodeASN1 Asn1.DER (ByteString.Lazy.fromChunks (reverse chunks')) of + Left Asn1.ParsingPartial + -> loop chunks' + Left e -> throwIO e + Right asn1 -> do + flip fix asn1 $ \loop' asn1' -> + case parseAsn1 asn1' of + Nothing -> return () + Just (asn1'', a) -> do + atomically (writeTQueue inq a) + loop' asn1'' + loop [] + +output :: ToAsn1 a => TQueue a -> Connection -> IO b +output out conn = wrap . forever $ do + msg <- atomically (readTQueue out) + Conn.connectionPut conn (encode (toAsn1 msg)) + where + encode x = Asn1.encodeASN1' Asn1.DER (appEndo x []) + +dispatch + :: Ldap + -> TQueue (Type.LdapMessage Type.ProtocolServerOp) + -> TQueue (Type.LdapMessage Request) + -> IO a +dispatch Ldap { client } inq outq = + flip fix (Map.empty, 1) $ \loop (!req, !counter) -> + loop =<< atomically (asum + [ do New new var <- readTQueue client + writeTQueue outq (Type.LdapMessage (Type.Id counter) new Nothing) + return (Map.insert (Type.Id counter) ([], var) req, counter + 1) + , do Type.LdapMessage mid op _ + <- readTQueue inq + res <- case op of + Type.BindResponse {} -> done mid op req + Type.SearchResultEntry {} -> saveUp mid op req + Type.SearchResultReference {} -> return req + Type.SearchResultDone {} -> done mid op req + Type.ModifyResponse {} -> done mid op req + Type.AddResponse {} -> done mid op req + Type.DeleteResponse {} -> done mid op req + Type.ModifyDnResponse {} -> done mid op req + Type.CompareResponse {} -> done mid op req + Type.ExtendedResponse {} -> probablyDisconnect mid op req + Type.IntermediateResponse {} -> saveUp mid op req + return (res, counter) + ]) + where + saveUp mid op res = + return (Map.adjust (\(stack, var) -> (op : stack, var)) mid res) + + done mid op req = + case Map.lookup mid req of + Nothing -> return req + Just (stack, var) -> do + putTMVar var (op :| stack) + return (Map.delete mid req) + + probablyDisconnect (Type.Id 0) + (Type.ExtendedResponse + (Type.LdapResult code + (Type.LdapDn (Type.LdapString dn)) + (Type.LdapString reason) + _) + moid _) + req = + case moid of + Just (Type.LdapOid oid) + | oid == noticeOfDisconnection -> throwSTM (Disconnect code (Dn dn) reason) + _ -> return req + probablyDisconnect mid op req = done mid op req + + noticeOfDisconnection :: Text + noticeOfDisconnection = fromString "1.3.6.1.4.1.1466.20036" - noticeOfDisconnection :: Text - noticeOfDisconnection = fromString "1.3.6.1.4.1.1466.20036" - -wrap :: IO a -> IO a -wrap m = m `catch` (throwIO . WrappedIOError) +wrap :: IO a -> IO a +wrap m = m `catch` (throwIO . WrappedIOError)