kanidm/designs/schema.rst
2019-02-14 12:49:45 +10:00

118 lines
4 KiB
ReStructuredText

Schema
------
Schema is one of the three foundational concepts of the server, along with filters and entries.
Schema defines how attribute values *must* be represented, sorted, indexed and more. It also
defines what attributes could exist on an entry.
Why Schema?
-----------
The way that the server is designed, you could extract the backend parts and just have "Entries"
with no schema. That's totally valid if you want!
However, usually in the world all data maintains some form of structure, even if loose. We want to
have ways to say a database entry represents a person, and what a person requires.
Attributes
----------
In the entry document, I discuss that avas have a single attribute, and 1 to infinite values that
are utf8 case sensitive strings. Which schema attribute types we can constrain these avas on an
entry.
For example, while the entry may be capable of holding 1 to infinite "name" values, the schema
defines that only one name is valid on the entry. Addition of a second name would be a violation. Of
course, schema also defines "multi-value", our usual 1 to infinite value storage concept.
Schema can also define that values of the attribute must conform to a syntax. For example, name
is a case *insensitive* string. So despite the fact that avas store case-sensitive data, all inputs
to name will be normalised to a lowercase form for faster matching. There are a number of syntax
types built into the server, and we'll add more later.
Finally, an attribute can be defined as indexed, and in which ways it can be indexed. We often will
want to search for "mail" on a person, so we can define in the schema that mail is indexed by the
backend indexing system. We don't define *how* the index is built - only that some index should exist
for when a query is made.
Classes
-------
So while we have attributes that define "what is valid in the avas", classes define "which attributes
can exist on the entry itself".
A class defines requirements that are "may", "must", "systemmay", "systemmust". The system- variants
exist so that we can ship what we believe are good definitions. The may and must exists so you can
edit and extend our classes with your extra attribute fields (but it may be better just to add
your own class types :) )
An attribute in a class marked as "may" is optional on the entry. It can be present as an ava, or
it may not be.
An attribute in a class marked as "must" is required on the entry. An ava that is valid to the
attribute syntax is required on this entry.
An attribute that is not "may" or "must" can not be present on this entry.
Lets imagine we have a class (pseudo example) of "person". We'll make it:
Class {
"name": "person",
"systemmust": ["name"],
"systemmay": ["mail"]
}
If we had an entry such as:
Entry {
"class": ["person"],
"uid": ["bob"],
"mail": ["bob@email"]
}
This would be invalid: We are missing the "systemmust" name attribute. It's also invalid because uid
is not present in systemmust or systemmay.
Entry {
"class": ["person"],
"name": ["claire"],
"mail": ["claire@email"]
}
This entry is now valid. We have met the must requirement of name, and we have the optional
mail ava populated. The following is also valid.
Entry {
"class": ["person"],
"name": ["claire"],
}
Classes are 'additive' - this means given two classes on an entry, the must/may are unioned, and the
strongest rule is applied to attribute presence.
Imagine we have also
Class {
"name": "person",
"systemmust": ["name"],
"systemmay": ["mail"]
}
Class {
"name": "emailperson",
"systemmust": ["mail"]
}
With our entry now, this turns the "may" from person, into a "must" because of the emailperson
class. On our entry Claire, that means this entry below is now invalid:
Entry {
"class": ["person", "emailperson"],
"name": ["claire"],
}
Simply adding an ava of mail back to the entry would make it valid once again.