Hmm.. understood.

What I was trying to do, is leave the implementation as generic as possible.
I need to understand if I should limit the search capabilities granted to
users, or keep it as general as it is.

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
}

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. 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}}

The result of this filter-options combo, will be 'ha...@dexo.tech' whether you 
search for
'ha...@dexo.tech' or 'hostmas...@dexo.tech'

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

Correct?

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?
Or just return the string representation of the JSON documents for the user to 
parse by
'jq' or similar utilities? Would there be a use case for that (postmap -q ... | 
jq)?
I assume I should limit it by key, but want to run it by you guys first..

Regards
Hamid Maadani


June 15, 2022 2:43 PM, "Viktor Dukhovni" <postfix-us...@dukhovni.org> wrote:

> On Wed, Jun 15, 2022 at 09:22:37PM +0000, Hamid Maadani wrote:
> 
>> This is good, was unaware of the multi-row result standard.
>> How does this work with other DBs? for example, if you have two result sets:
>> { "name": "hamid", "value": "test" }
>> { "name": "viktor", "value": "test2" }
> 
> Well, Postfix dictionaries cannot meaningfully consume structured data,
> you can return a single value, or a comma-separated list. If it is a
> list of email addresses, they should be stored in "external form"
> (RFC-5322 quoted) allowing robust parsing as a comma-separated list of
> such quoted forms).
> 
> Thus "name" might be the key, and "value" the desired value column,
> so that a query for "hamid" would return "test", and a query for
> "viktor" would return "test2".
> 
> But if the database also held:
> 
> { "name": "devs", "value": "wietse" }
> { "name": "devs", "value": "viktor" }
> { "name": "devs", "value": "hamid" }
> 
> then a query for "devs" would return:
> 
> wietse,viktor,hamid
> 
>> should it return as below?
>> hamid,test,viktor,test2
> 
> So definitely not this, it makes no sense.
> 
>> Regarding the 'db_common_expand' line, I used the same function used for the 
>> SQL dict,
>> to support expansions like %s , %u and such for mongodb search filter, if 
>> that makes sense.
> 
> Yes, "%s", "%u" and "%d" are reasonably expected.
> 
> 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.
> 
> --
> Viktor.

Reply via email to