Access Control and Data Validation for Clojure(Script) written in Clojure Spec.
A covenant, is a solemn promise to engage in or refrain from a specified action. - Wikipedia
Covenant is developed and maintained by Degree9
Covenant is divided into a few namespaces:
covenant.core
ICovenant protocol and public api.covenant.schema
type/value based data comparison on top of clojure.spec.covenant.acl
provides covenants around Access Control List's (ACL).covenant.rbac
provides covenants around Role Based Access Control (RBAC).covenant.abac
provides covenants around Attribute Based Access Control (ABAC).
Covenant exposes a protocol that closely matches cljs native spec.
(defprotocol ICovenant
"Provides an abstraction for validating data using clojure.spec based on a covenant."
(assert [covenant data] "See clojure.spec/assert.")
(conform [covenant data] "See clojure.spec/conform.")
(explain [covenant data] "See clojure.spec/explain.")
(problems [covenant data] "See clojure.spec/explain-data.")
(validate [covenant data] "See clojure.spec/valid?.")
(spec [covenant] "Returns related spec for `covenant`."))
The spec
function will return a spec based on the passed data.
A simple example is that (covenant.core/spec nil)
will return
:covenant.core/nil
which is preregistered with spec as
(clojure.spec.alpha/def :covenant.core/nil nil?)
.
Scalar primitives simply return a spec/predicate based on their data type while collections also compare their contents.
covenant.rbac
provides validation fns that are "loose" for collections.
If some values in the passed collection (deep) matches the passed covenant then
covenant.core/validate
returns true
after covenant.rbac
has been required.
(require 'covenant.rbac)
(covenant.core/validate {:roles [:admin :editor]} {:roles [:admin]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles [:admin :editor]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles [:editor]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles []}) ; false
(covenant.core/validate {:roles [:admin :editor]} {:roles [:foo]}) ; false
(:require covenant.core :as covenant)
For more examples check out the test suite.
A vanilla spec + scalar primitive will pass covenant/explain
.
(covenant/explain :covenant.core/number 1)
; =>
;Success!
Support this and other open-source projects on Patreon!