Add domain and domain administration models

This commit is contained in:
Ethan Paul 2020-02-22 19:27:00 -05:00
parent 2b5eafa71a
commit 425d39cd48
2 changed files with 193 additions and 0 deletions

123
keyosk/database/domain.py Normal file
View File

@ -0,0 +1,123 @@
"""Authentication domain model definition"""
import datetime
from typing import List
import peewee
from keyosk.database._shared import KeyoskBaseModel
from keyosk.database.domain_admin import DomainAdmin
class Domain(KeyoskBaseModel):
"""Authentication domain storage model
:attribute created: Datetime indicating when the domain was first created
:attribute updated: Datetime indicating when the domain was last modified
:attribute name: Simple URL-friendly name for the domain
:attribute audience: Value to populate the ``audience`` claim of issued JWTs with
when authenticating against this domain
:attribute title: Human-friendly display name for the domain
:attribute description: Human-friendly longer description of the domain's usage or
purpose
:attribute contact: Contact link for the domain
:attribute enabled: Whether the domain is enabled for authentication
:attribute enable_password: Whether to allow accounts to authenticate using the
client-set authentication secret
:attribute enable_autopassword: Whether to allow accounts to authenticate using the
server-set authentication secret
:attribute lifespan_access: Number of seconds that an issued JWT access token should
be valid for
:attribute lifespan_refresh: Number of seconds an an issued JWT refresh token should
be valid for
:attribute administration: Container of additional settings related to the
administration of the domain itself
:property access_list_names: List of Access Control Lists under the domain that accounts
can have permission entries on
:property permission_names: List of permissions that can be assigned to an account's ACL
entry
"""
class Meta: # pylint: disable=too-few-public-methods,missing-docstring
table_name = "domain"
created = peewee.DateTimeField(null=False, default=datetime.datetime.utcnow)
updated = peewee.DateTimeField(null=False, default=datetime.datetime.utcnow)
name = peewee.CharField(null=False, unique=True)
audience = peewee.CharField(null=False, unique=True)
title = peewee.CharField(null=True)
description = peewee.CharField(null=True)
contact = peewee.CharField(null=True)
enabled = peewee.BooleanField(null=False)
enable_password = peewee.BooleanField(null=False)
enable_autopassword = peewee.BooleanField(null=False)
enable_refresh = peewee.BooleanField(null=False)
lifespan_access = peewee.IntegerField(null=False)
lifespan_refresh = peewee.IntegerField(null=False)
administration = peewee.ForeignKeyField(DomainAdmin, null=False, unique=True)
@property
def access_list_names(self) -> List[str]:
"""Return the list of ACL items from the backref"""
return [item.name for item in self._access_lists]
@property
def permission_names(self) -> List[str]:
"""Return the list of permission names from the backref"""
return [item.name for item in self._permissions]
@staticmethod
def dict_keys() -> List[str]:
return [
"uuid",
"created",
"updated",
"name",
"audience",
"title",
"description",
"contact",
"enabled",
"enable_password",
"enable_autopassword",
"enable_refresh",
"lifespan_access",
"lifespan_refresh",
"access_list_names",
"permission_names",
"administration",
]
@staticmethod
def foreign_ref() -> List[str]:
return ["administration"]
class DomainAccessList(KeyoskBaseModel):
"""Access list name model definition
:attribute name: Name of the access control list
:attribute domain: Authentication domain the ACL applies to
"""
class Meta: # pylint: disable=missing-docstring,too-few-public-methods
table_name = "domain_acl"
name = peewee.CharField(null=False)
domain = peewee.ForeignKeyField(Domain, backref="access_lists")
class DomainPermission(KeyoskBaseModel):
"""Permission name model definition
:attribute name: Name of the permission
:attribute bitindex: Index in the generated bitmask that indicates this permission;
zero-indexed
:attribute domain: Authentication domain the permission should apply to the ACLs of
"""
class Meta: # pylint: disable=missing-docstring,too-few-public-methods
table_name = "domain_permission"
name = peewee.CharField(null=False)
bitindex = peewee.IntegerField(null=False)
domain = peewee.ForeignKeyField(Domain, backref="permissions")

View File

@ -0,0 +1,70 @@
"""Authentication domain meta admin settings model definition
The domain administration settings allow access to be granted to accounts assigned to
the domain to manage the domain itself. This allows accounts to manage the parts of
Keyosk that they need to without granting permissions to every domain Keyosk knows
about.
However, to avoid circular foreign key references, the admin settings need their own
relation tabel. If these settings were part of the main :class:`Domain` model then there
would be circular references between it and the :class:`DomainAccessList` and
:class:`DomainPermission` models.
"""
from typing import Generator
from typing import Tuple
import peewee
from keyosk.database._shared import KeyoskBaseModel
from keyosk.database.mappings import DomainAccessList
from keyosk.database.mappings import DomainPermission
class DomainAdmin(KeyoskBaseModel):
"""Authentication domain meta administration storage model
:attribute access_list: The ACL that an account must have permissions for to manage
the domain settings
:attribute domain_read: Permission granted by the ACL entry that gives the assigned
account read access to the domain settings
:attribute domain_update: Permission granted by the ACL entry that gives the
assigned account update access to the domain settings
:attribute account_create: Permission granted by the ACL entry that gives the
assigned account access to create new accounts assigned
to the domain
:attribute account_read: Permission granted by the ACL entry that gives the
assigned account read access to the accounts assigned to
the domain
:attribute account_delete: Permission granted by the ACL entry that gives the
assigned account access to unassign an account from the
domain
There are two permissions not available via this model that may make sense to
implement in the future: ``account_update`` and ``domain_delete``. The first is not
implemented due to the potential conflicts it causes: an account can be assigned to
multiple domains, so granting permissions on one domain to modify an account may
implicitly grant that same permission on one or more accounts assigned to another
domain; this seemed ill advised. The second is not implemented for no real good
reason, other than it seemed out of the inteneded usage of "domain management".
.. note:: Both the permissions denoted above, as well as other permissions not
enumerated here, are available through the primary Keyosk authentication
domain.
"""
class Meta: # pylint: disable=missing-docstring,too-few-public-methods
table_name = "domain_admin"
access_list = peewee.ForeignKeyField(DomainAccessList, null=True)
domain_read = peewee.ForeignKeyField(DomainPermission, null=True)
domain_update = peewee.ForeignKeyField(DomainPermission, null=True)
account_create = peewee.ForeignKeyField(DomainPermission, null=True)
account_read = peewee.ForeignKeyField(DomainPermission, null=True)
account_delete = peewee.ForeignKeyField(DomainPermission, null=True)
def __iter__(self) -> Generator[Tuple[str, str], None, None]:
yield "access_list", self.access_list.name
yield "domain_read", self.domain_read.name
yield "account_create", self.account_create.name
yield "account_read", self.account_read.name
yield "account_delete", self.account_delete.name