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.

Reply via email to