packages feed

ldap-scim-bridge 0.3 → 0.4

raw patch · 4 files changed

+29/−8 lines, 4 filesdep +unordered-containersPVP ok

version bump matches the API change (PVP)

Dependencies added: unordered-containers

API changes (from Hackage documentation)

+ LdapScimBridge: [ldapSearchExtra] :: LdapSearch -> [LdapFilterAttr]
+ LdapScimBridge: instance GHC.Show.Show LdapScimBridge.BridgeConf
+ LdapScimBridge: ldapFilterAttrToFilter :: LdapFilterAttr -> Filter
- LdapScimBridge: LdapSearch :: Dn -> Text -> LdapSearch
+ LdapScimBridge: LdapSearch :: Dn -> Text -> [LdapFilterAttr] -> LdapSearch

Files

CHANGELOG.md view
@@ -3,6 +3,10 @@ `ldap-scim-bridge` uses [PVP][1]-compatible versioning. The changelog is available [on GitHub][2]. +## 0.4++- Filter for arbitrary LDAP attributes (#16)+ ## 0.3  - Better error logging. (#11)
examples/wire-server/conf1.yaml view
@@ -8,6 +8,8 @@   search:     base: "ou=People,dc=nodomain"     objectClass: "account"+    #memberOf: "team red"+    #hairColor: "yellow"   codec: "utf8" scimTarget:   tls: false
ldap-scim-bridge.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.4 name:                ldap-scim-bridge-version:             0.3+version:             0.4 synopsis:            See README for synopsis description:         See README for description homepage:            https://github.com/fisx/ldap-scim-bridge@@ -39,6 +39,7 @@                      , email-validate >=2.3.2.13 && <2.4                      , string-conversions >=0.4.0.1 && <0.5                      , servant-client >=0.18.3 && <0.19+                     , unordered-containers >= 0.2.14.0 && <0.3                      , servant-client-core >=0.18.3 && <0.19                      , servant >=0.18.3 && <0.19                      , http-types >=0.12.3 && <0.13
src/LdapScimBridge.hs view
@@ -8,6 +8,7 @@ import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.ByteString.Char8 as ByteString import qualified Data.Foldable as Foldable+import qualified Data.HashMap.Lazy as HM import qualified Data.List import qualified Data.Map as Map import Data.String.Conversions (cs)@@ -63,7 +64,9 @@   { -- | `$ slapcat | grep ^dn`, eg. @Dn "dc=nodomain"@.     ldapSearchBase :: Dn,     -- | eg. @"account"@-    ldapSearchObjectClass :: Text+    ldapSearchObjectClass :: Text,+    -- | eg. @[LdapFilterAttr "memberOf" "team red", LdapFilterAttr "hairColor" "yellow"]+    ldapSearchExtra :: [LdapFilterAttr]   }   deriving stock (Eq, Show) @@ -79,7 +82,7 @@     fpassword :: String <- obj Aeson..: "password"     fsearch :: LdapSearch <- obj Aeson..: "search"     fcodec :: Text <- obj Aeson..: "codec"-    fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute"+    fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute" -- TODO: this can go into 'fdeleteFromDirectory'.     fdeleteFromDirectory :: Maybe LdapSearch <- obj Aeson..:? "deleteFromDirectory"      let vhost :: Host@@ -117,8 +120,15 @@   parseJSON = Aeson.withObject "LdapSearch" $ \obj -> do     fbase :: Text <- obj Aeson..: "base"     fobjectClass :: Text <- obj Aeson..: "objectClass"-    pure $ LdapSearch (Dn fbase) fobjectClass +    extra :: [LdapFilterAttr] <- do+      let go :: (Text, Yaml.Value) -> Yaml.Parser LdapFilterAttr+          go (key, val) = do+            str <- Aeson.withText "val" pure val+            pure $ LdapFilterAttr key str+      go `mapM` HM.toList (HM.filterWithKey (\k _ -> k `notElem` ["base", "objectClass"]) obj)+    pure $ LdapSearch (Dn fbase) fobjectClass extra+ data ScimConf = ScimConf   { scimTls :: Bool,     scimHost :: String,@@ -143,7 +153,7 @@     mapping :: Mapping,     logLevel :: Level   }-  deriving stock (Generic)+  deriving stock (Show, Generic)  instance Aeson.FromJSON Level where   parseJSON "Trace" = pure Trace@@ -255,14 +265,18 @@  type LdapResult a = IO (Either LdapError a) -ldapObjectClassFilter :: Text -> Filter+ldapObjectClassFilter :: Text -> Filter -- TODO: inline? ldapObjectClassFilter = (Attr "objectClass" :=) . cs +ldapFilterAttrToFilter :: LdapFilterAttr -> Filter -- TODO: inline?  replace LdapFilterAttr with `Attr` and `:=`?+ldapFilterAttrToFilter (LdapFilterAttr key val) = Attr key := (cs val)+ listLdapUsers :: LdapConf -> LdapSearch -> LdapResult [SearchEntry] listLdapUsers conf searchConf = Ldap.with (ldapHost conf) (ldapPort conf) $ \l -> do   Ldap.bind l (ldapDn conf) (ldapPassword conf)-  let fltr = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf-  Ldap.search l (ldapSearchBase searchConf) mempty fltr mempty+  let fltr :: Filter = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf+      allfltr :: Filter = And (fltr :| (ldapFilterAttrToFilter <$> ldapSearchExtra searchConf))+  Ldap.search l (ldapSearchBase searchConf) mempty allfltr mempty  type User = Scim.User ScimTag