I have uploaded the latest code, which simplifies filters, projections and accommodates multiple results. In this version: - Users can search by specifying search keys, OR writing more advanced filters. If search_keys are specified, value of 'filter' will be ignored if specified. - Users can specify a return_key for a simplified projection. It would default to "result" if not specified. - Users can set more complex projections. If a projection is set, value of return_key will become irrelevant (the code handles that automatically). - If there are multiple results, a comma-separated list of strings will be returned.
Please let me know if any other adjustments are necessary. > You should also support the "domain" attribute to limit the keys sent to the database to just email addresses with a domain part matching one of the elements of that list. I copied what was in dict_ldap, so this should now be supported. but I can not see where if actually gets the 'domain' attribute from the configuration! Am I missing something? Regards Hamid Maadani June 15, 2022 5:34 PM, "Hamid Maadani" <ha...@dexo.tech> wrote: > (As a side question, Why is "_id" part of the "projection"???) > > Oh, and mongo returns '_id' by default, so you turn that off using projection > if you > want the result to have only one key-pair value. > > Regards > Hamid Maadani > > June 15, 2022 5:30 PM, "Hamid Maadani" <ha...@dexo.tech> wrote: > >> Understood. This is great, appreciate the guidance. >> I'll work on implementing it this way and update this thread once the code >> is pushed. >> >> Regards >> Hamid Maadani >> >> June 15, 2022 3:40 PM, "Viktor Dukhovni" <postfix-us...@dukhovni.org> wrote: > > On Wed, Jun 15, 2022 at 10:12:57PM +0000, Hamid Maadani wrote: >> Let's say I have a database called 'mail' in my MongoDB cluster, and there >> is a collection (table) named 'mailbox' inside of it. >> Each object in this collection holds a mailbox, and also includes it's >> aliases (real world example from my mail server): >> >> { >> "_id" : ObjectId(REDACTED), >> "username" : "ha...@dexo.tech", >> "password" : "REDACTED", >> "name" : "Hamid Maadani", >> "maildir" : "ha...@dexo.tech/", >> "quota" : REDACTED, >> "local_part" : "hamid", >> "domain" : "dexo.tech", >> "created" : ISODate("2016-11-07T21:07:21.000Z"), >> "modified" : ISODate("2017-05-02T22:10:00.000Z"), >> "active" : 1, >> "alias" : [ >> { >> "address" : "ab...@dexo.tech", >> "created" : ISODate("2016-11-07T21:04:16.000Z"), >> "modified" : ISODate("2016-11-07T21:04:16.000Z"), >> "active" : 1 >> }, >> { >> "address" : "hostmas...@dexo.tech", >> "created" : ISODate("2016-11-07T21:04:16.000Z"), >> "modified" : ISODate("2016-11-07T21:04:16.000Z"), >> "active" : 1 >> } >> ] >> }, >> >> { >> "_id" : ObjectId(REDACTED), >> "username" : "ad...@dexo.tech", >> "password" : "REDACTED", >> "name" : "Site Admin", >> "maildir" : "ad...@dexo.tech/", >> "quota" : REDACTED, >> "local_part" : "admin", >> "domain" : "dexo.tech", >> "created" : ISODate("2017-04-12T22:24:17.000Z"), >> "modified" : ISODate("2021-06-03T02:54:35.000Z"), >> "active" : 1 >> } > > See LDAP_README which talks about structurally similar use-cases. >> Now, if I want to query for 'ha...@dexo.tech', or any of it's aliases, I >> would use >> this filter: >> filter = {"$$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1} >> >> of course, this will return an entire JSON document. > > JSON documents will be fairly useless in Postfix, so there should always > be a projection, and its syntax should be more user-friendly by default, > so similar to "result_attribute" in LDAP, i.e. just a key to extract > from the JSON document, which should be either a string-valued scalar, > or a list of string values (which you would internally combine with > commas). >> So I would use Mongo projections to >> limit it to just one key-value pair, in which case, the driver will only >> return the value: >> options = {"projection": {"_id": 0, "username": 1}} > > Using explicit "projections" should be an advanced feature, far better > to ask users to write: > > result_attribute = username > > (As a side question, Why is "_id" part of the "projection"???) >> If I change the query to: >> filter = {"active": 1} >> >> and keep the same projection, it will return: >> {"username":"ha...@dexo.tech"} >> {"username":"ad...@dexo.tech"} >> >> from what you just described, the result should be returned as: >> ha...@dexo.tech,ad...@dexo.tech > > Yes. >> That's the easy part. Question is, should I allow users to use the >> filter/options combination >> to search however they need? The reason I ask is, if someone uses this >> projection: >> {"projection": {"_id": 0, "username": 1, "name" : 1}} >> >> The results would be: >> {"username":"ha...@dexo.tech", "name":"hamid"} >> {"username":"ad...@dexo.tech", "name":"admin"} >> >> and I am unsure how to handle that. Limit it by requiring a key? > > Returning compound JSON objects should be an error. Only string and > list of string values should be supported. The result is obtained > by flattening all lists to a comma-separated string, and then combining > these (again comma-separated) across the returned JSON "documents". >> Or just return the string representation of the JSON documents for the >> user to parse by 'jq' or similar utilities? > > No, because Postfix dictionaries are not for use in MongoDB query CLIs, > they are for the MTA to resolve email lists, transports, ... where > only scalar results and sometimes comma-separated lists are supported. >> Would there be a use case for that (postmap -q ... | jq)? > > No. >> I assume I should limit it by key, but want to run it by you guys first.. > > Read LDAP_README, virtual(5), aliases(5), transport(5), ... > > Note also that with e.g. LDAP there's also a way to specify an expansion > limit (e.g. 1), so that queries returning more than the expected number > of rows fail instead of returning garbage. > > So, also see ldap_table(5) for any additional table attributes (like > the previously mentioned "domain") that may apply. > > -- > Viktor.