use corium_query::edn::Edn;
pub const DEFAULT_AUTHZ_DB: &str = "corium_authz";
pub const PRINCIPAL_ID: &str = "authz.principal/id";
pub const PRINCIPAL_PROVIDER: &str = "authz.principal/provider";
pub const PRINCIPAL_ROLE: &str = "authz.principal/role";
pub const OBJECT_TYPE: &str = "authz.object/type";
pub const OBJECT_ID: &str = "authz.object/id";
pub const OBJECT_DATABASE: &str = "authz.object/database";
pub const TUPLE_SUBJECT: &str = "authz.tuple/subject";
pub const TUPLE_RELATION: &str = "authz.tuple/relation";
pub const TUPLE_OBJECT: &str = "authz.tuple/object";
pub const PERMISSION_OBJECT_TYPE: &str = "authz.permission/object-type";
pub const PERMISSION_ACTION: &str = "authz.permission/action";
pub const PERMISSION_RELATION: &str = "authz.permission/relation";
pub const REWRITE_RELATION: &str = "authz.rewrite/relation";
pub const REWRITE_VIA_RELATION: &str = "authz.rewrite/via-relation";
pub const REWRITE_ON_RELATION: &str = "authz.rewrite/on-relation";
pub const REWRITE_OBJECT_TYPE: &str = "authz.rewrite/object-type";
pub const VIEW_NAME: &str = "authz.view/name";
pub const VIEW_FILTER_TYPE: &str = "authz.view/filter-type";
pub const VIEW_ATTRIBUTE: &str = "authz.view/attribute";
pub const BINDING_RELATION: &str = "authz.binding/relation";
pub const BINDING_OBJECT: &str = "authz.binding/object";
pub const BINDING_VIEW: &str = "authz.binding/view";
pub const BINDING_UNFILTERED: &str = "authz.binding/unfiltered";
pub const ATTRIBUTES: &[&str] = &[
PRINCIPAL_ID,
PRINCIPAL_PROVIDER,
PRINCIPAL_ROLE,
OBJECT_TYPE,
OBJECT_ID,
OBJECT_DATABASE,
TUPLE_SUBJECT,
TUPLE_RELATION,
TUPLE_OBJECT,
PERMISSION_OBJECT_TYPE,
PERMISSION_ACTION,
PERMISSION_RELATION,
REWRITE_RELATION,
REWRITE_VIA_RELATION,
REWRITE_ON_RELATION,
REWRITE_OBJECT_TYPE,
VIEW_NAME,
VIEW_FILTER_TYPE,
VIEW_ATTRIBUTE,
BINDING_RELATION,
BINDING_OBJECT,
BINDING_VIEW,
BINDING_UNFILTERED,
];
pub const SCHEMA_EDN: &str = r"
[{:db/ident :authz.principal/id :db/valueType :db.type/string :db/unique :db.unique/identity}
{:db/ident :authz.principal/provider :db/valueType :db.type/string}
{:db/ident :authz.principal/role :db/valueType :db.type/string :db/cardinality :db.cardinality/many}
{:db/ident :authz.object/type :db/valueType :db.type/string :db/index true}
{:db/ident :authz.object/id :db/valueType :db.type/string :db/index true}
{:db/ident :authz.object/database :db/valueType :db.type/string :db/index true}
{:db/ident :authz.tuple/subject :db/valueType :db.type/string :db/index true}
{:db/ident :authz.tuple/relation :db/valueType :db.type/string :db/index true}
{:db/ident :authz.tuple/object :db/valueType :db.type/string :db/index true}
{:db/ident :authz.permission/object-type :db/valueType :db.type/string :db/index true}
{:db/ident :authz.permission/action :db/valueType :db.type/string :db/index true}
{:db/ident :authz.permission/relation :db/valueType :db.type/string :db/cardinality :db.cardinality/many}
{:db/ident :authz.rewrite/relation :db/valueType :db.type/string :db/index true}
{:db/ident :authz.rewrite/via-relation :db/valueType :db.type/string}
{:db/ident :authz.rewrite/on-relation :db/valueType :db.type/string}
{:db/ident :authz.rewrite/object-type :db/valueType :db.type/string}
{:db/ident :authz.view/name :db/valueType :db.type/string :db/unique :db.unique/identity}
{:db/ident :authz.view/filter-type :db/valueType :db.type/string}
{:db/ident :authz.view/attribute :db/valueType :db.type/string :db/cardinality :db.cardinality/many}
{:db/ident :authz.binding/relation :db/valueType :db.type/string :db/index true}
{:db/ident :authz.binding/object :db/valueType :db.type/string :db/index true}
{:db/ident :authz.binding/view :db/valueType :db.type/string}
{:db/ident :authz.binding/unfiltered :db/valueType :db.type/boolean}]
";
pub const DEFAULT_PERMISSIONS_EDN: &str = r#"
[{:db/id "p-db-read" :authz.permission/object-type "database" :authz.permission/action "read" :authz.permission/relation ["viewer" "writer" "owner"]}
{:db/id "p-db-write" :authz.permission/object-type "database" :authz.permission/action "write" :authz.permission/relation ["writer" "owner"]}
{:db/id "p-db-admin" :authz.permission/object-type "database" :authz.permission/action "admin" :authz.permission/relation ["owner"]}
{:db/id "p-cat-read" :authz.permission/object-type "catalog" :authz.permission/action "read" :authz.permission/relation ["viewer" "owner"]}
{:db/id "p-cat-write" :authz.permission/object-type "catalog" :authz.permission/action "write" :authz.permission/relation ["owner"]}
{:db/id "p-cat-admin" :authz.permission/object-type "catalog" :authz.permission/action "admin" :authz.permission/relation ["owner"]}]
"#;
#[must_use]
pub fn schema_forms() -> Vec<Edn> {
forms_of(SCHEMA_EDN)
}
#[must_use]
pub fn default_permission_forms() -> Vec<Edn> {
forms_of(DEFAULT_PERMISSIONS_EDN)
}
fn forms_of(text: &str) -> Vec<Edn> {
match corium_query::edn::read_all(text)
.expect("reserved authz EDN parses")
.pop()
{
Some(Edn::Vector(items) | Edn::List(items)) => items,
other => panic!("reserved authz EDN must be one vector, got {other:?}"),
}
}
#[cfg(test)]
mod tests {
use super::*;
use corium_forms::schemaform::schema_from_edn;
#[test]
fn reserved_schema_installs() {
let forms = schema_forms();
assert_eq!(forms.len(), ATTRIBUTES.len());
let (schema, idents) = schema_from_edn(&forms).expect("reserved schema is well formed");
for attribute in ATTRIBUTES {
let keyword = corium_core::Keyword::parse(attribute);
let id = idents
.entid(&keyword)
.unwrap_or_else(|| panic!("{attribute} is installed"));
assert!(schema.get(id).is_some(), "{attribute} has schema metadata");
}
}
#[test]
fn default_permissions_parse() {
assert_eq!(default_permission_forms().len(), 6);
}
}