There's a design pattern of sorts that I've thought about but haven't seen implemented where every function / method passes around a permissions object. I'm wondering whether using it in a project is a good idea or not. The key ideas here are that 1) capabilities are only ever taken away, not added (unless you're in some kind of entry point) and 2) don't inspect the contents of the permissions object except to assert that you have whatever specific capability is needed before doing something.
Most mainstream languages besides Haskell have nothing resembling an effect system, which is really what I'm trying to emulate.
The goal is that the specific fields in the permissions type will be meaningful for the application. It seems likely that the permissions that are meaningful to track will change more slowly than the rest of the application.
For example,
struct permission {
bool can_write_db;
bool can_create_tempfile;
bool can_delete_tempfile;
};
typedef struct permission permission;
And then inside a function that writes to the database you might do the following
void commit_transaction(permission p, X x, Y y)
{
assert(p.can_write_db);
...
do_something_else(p, 47);
return;
}
with do_something_else
being another function that gets handed the permissions object.
As for (2), the following example would violate the rule against inspecting the contents of the permissions object.
// BAD
void possibly_commit_transaction(permission p)
{
if (p.can_write_db) {
// commit the transaction
} else {
// write a description of the transaction to a log file
}
}
The permissions object isn't intended to be used like the other parameters, being handed the wrong thing indicates that the program has a bug in it.
Would it be worth going to the trouble of using something like this? Would this thing be likely to carry its own weight?
P.S.
The goal of this is expressly not security or hardening the application.