Nguyễn Gia Phong <[email protected]> writes:
> Hi Zacchae,
>
> On 2026-08-27 at 15:33-07:00, Zacchaeus wrote:
>> An access control in exim is a name, followed by a list of statements.
>> A statement is a verb followed by a list of clauses. I could define
>> some configs like
>>
>> (define-configuration acl
>> (name string "")
>> (body list ""))
>> (define-configuration acl-statement
>> (verb string "")
>> (body list "")
>> (define-condition acl-clause
>> ...)
>>
>> then I could translate the above to
>>
>> (acl (name "acl_check_data")
>> (body (list
>> (acl-statement
>> (verb "deny")
>> (body (list
>> (acl-clause (condition "..."))
>> (acl-clause (message "...")))))
>> ...)))
>
> I believe define-configuration could offer useful type checking here
> if you define and use list-of-acl-statements et al. That being said,
Yes, I've moved in that direction, type checking being a big reason why.
It makes for maybe-cleaner code in guix proper, but matching becomes
more verbose as an end user. Suppose I want to modify the default acls
to allow for longer max linelength. With lists it's as easy as
(map (match-lambda
(("acl_check_data"
(deny (condition "${if > {$max_received_linelength}{998}}")
rest-clause ...)
rest-statements ...)
`("acl_check_data"
(deny (condition "${if > {$max_received_linelength}{3500}}")
. ,rest-clause)
. ,rest-statements))
(acl acl))
%exim-default-acls)
Maybe that seems easy to me since I've been looking at exim docs for
enough hours, but I find the records solution harder to read
(map (match-lambda
(($ <acl> "acl_check_data"
(($ <acl-statment> 'deny
(($ <acl-clause> (= condition "${if >
{$max_received_linelength}{998}}"))
rest-clauses ...))
rest-statements ...))
(acl (name "acl_check_data")
(statments (cons (acl-statement
(verb 'deny)
(clauses (cons (acl-clause (condition "${if >
{$max_received_linelength}{3500}}"))
rest-clauses)))
rest-statements))))
(acl acl))
%exim-default-acls)
> On 2026-08-27 at 15:33-07:00, Zacchaeus wrote:
>> '("acl_check_data"
>> (deny (condition "...")
>> (message "..."))
>> ...)
>>
>> [feels] cleaner to me. Now, acl-clause above gives some benefit
>> as far as detecting typos and some syntax verification,
>> so maybe I need something in-between.
>
> https://www.exim.org/exim-html-current/doc/html/spec_html/ch-access_control_lists.html
> defines the exhaustive list of verbs and modifiers,
> so you can land in the middle with
>
> (acl (name "acl_check_data")
> (body (list (acl-deny
> (condition "...")
> (message "..."))
> ...)))
>
> Hoping that helps,
> Phong
Unfortunately, acl's are a bit more free-form. Not only can each acl
statment have multiple of the same modifiers or conditions, but the
order matters, as illustrated by the followin example from the docs you
link:
require message = Can't verify sender
verify = sender
message = Can't verify recipient
verify = recipient
message = This message cannot be used
Which would render in your code as
(acl (name "acl_check_data")
(body (list (acl-require
(message "Can't verify sender")
(verify "sender")
(message "Can't verify recipient)
(verify "recipient")
(message "This message cannot be used")))))
which doesn't make any sense.
Thanks for the feedback,
-Zacchae