Modules

This section contains a complete API reference of the kadi.modules Python module.

Accounts

kadi.modules.accounts.core.purge_user(user)[source]

Purge an existing user.

This will completely delete the user and all their resources from the database.

Note that this function issues one or more database commits.

Parameters

user – The user to purge.

kadi.modules.accounts.core.merge_users(first_user, second_user)[source]

Merge two users together.

This will migrate the ownership of all identities, resources and permissions from the second user to the first user. The first user is then also able to log in using both identities.

Parameters
  • first_user – The user to merge the second user into.

  • second_user – The user to merge into the first user.

kadi.modules.accounts.forms.get_login_form(provider)[source]

Get a login form based on a given authentication provider.

All fields and labels will have the given provider’s type appended to their IDs in the form of "<field_id>_<provider>", so rendering multiple forms on a single page does not lead to issues because of duplicate IDs.

Parameters

provider – An authentication provider as specificed in kadi.lib.constants.AUTH_PROVIDER_TYPES.

Returns

The login form.

class kadi.modules.accounts.forms.CredentialsLoginForm(*args, **kwargs)[source]

Bases: KadiForm

A general login form using a username and a password.

class kadi.modules.accounts.forms.ShibLoginForm(*args, **kwargs)[source]

Bases: KadiForm

A login form for use in Shibboleth.

The form uses a selection field which has to be populated with the entity IDs and display names of all valid identity providers.

class kadi.modules.accounts.forms.NewUserForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in creating new local users.

class kadi.modules.accounts.forms.RegistrationForm(*args, **kwargs)[source]

Bases: NewUserForm

A form for use in registering new local users.

class kadi.modules.accounts.forms.RequestPasswordResetForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in requesting a password reset for local users.

class kadi.modules.accounts.forms.ResetPasswordForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in changing a local user’s password.

class kadi.modules.accounts.forms.EmailConfirmationForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in mandatory email confirmation for local users.

Offers an optional email field to let a user change their current email address.

class kadi.modules.accounts.models.UserState[source]

Bases: StringEnum

String enum containing all possible state values for users.

class kadi.modules.accounts.models.User(**kwargs)[source]

Bases: SimpleReprMixin, SimpleTimestampMixin, UserMixin, Model

Model to represent users.

In general, every resource that a user “owns” should be linked to this model. Each user can also potentially have multiple identities associated with it, all pointing to the same user.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'new_user_id', 'latest_identity_id', 'is_sysadmin', 'state']

See SimpleReprMixin.

timestamp_exclude = ['identities', 'records', 'record_links', 'files', 'temporary_files', 'uploads', 'collections', 'templates', 'groups', 'favorites', 'workflows', 'revisions', 'tasks', 'notifications', 'access_tokens', 'oauth2_tokens', 'config_items', 'permissions', 'roles']

See SimpleTimestampMixin.

check_constraints = {'about': {'length': {'max': 10000}}, 'state': {'values': ['active', 'inactive', 'deleted']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the user, auto incremented.

about

Additional personal information.

Restricted to a maximum length of 10_000 characters.

image_name

The optional name/identifier of a user’s profile image.

This identifier is used to build the local file path where the actual image is stored.

email_is_private

Flag indicating whether a user’s email address is private.

A private email is only visible to the user themselves, while a public one is visible to every logged-in user.

new_user_id

Points to a new user ID when the user was merged with another one.

latest_identity_id

Points to the ID of the latest identity the user logged in with.

is_sysadmin

Flag indicating whether a user is a system administrator.

System administrators are allowed to perform certain administrative actions separately from any permissions.

legals_accepted

Flag indicating if and when a user accepted the legal notices, if configured.

state

The state of the user.

property is_merged

Check if a user was merged.

property email_confirmed

Check if a local user’s email is confirmed.

This is the case if the user’s current identity is not local or if their email address was confirmed explicitely.

property needs_email_confirmation

Check if a user needs email confirmation.

This is the case if the user’s email has not yet been confirmed and email confirmation is required by the local authentication provider.

property needs_legals_acceptance

Check if a user needs to accept the legal notices.

This is the case if accepting the legal notices is required and the user did not accept them (or changes to them) yet.

classmethod create(state='active')[source]

Create a new user and add it to the database session.

Parameters

state – (optional) The state of the user.

Returns

The new User object.

accept_legals()[source]

Accept the legal notices for this user.

Automatically sets the date of acceptance to the current date.

get_config(key, default=<kadi.lib.config.core.MISSING>, decrypt=False)[source]

Get the value of a user-specific config item from the database.

Convenience method that wraps kadi.lib.config.core.get_user_config() with the user set accordingly.

set_config(key, value, encrypt=False)[source]

Set the value of a user-specific config item in the database.

Convenience method that wraps kadi.lib.config.core.set_user_config() with the user set accordingly.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

class kadi.modules.accounts.models.Identity(**kwargs)[source]

Bases: SimpleReprMixin, SimpleTimestampMixin, Model

Model to represent base identities.

This model uses its type column to specify different types of identities. Each specific identity (i.e. each subclass of this model) needs at least a unique username, a displayname and an email column.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'type']

See SimpleReprMixin.

id

The ID of the identity, auto incremented.

user_id

The ID of the user the identity belongs to.

type

The identity type.

Used by SQLAlchemy to distinguish between different identity types and to automatically select from the correct identity table using joined table inheritance.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

class kadi.modules.accounts.models.LocalIdentity(**kwargs)[source]

Bases: Identity

Model to represent local identities.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'username', 'email']

See SimpleReprMixin.

identity_type = {'name': l'Local', 'type': 'local'}

The type and full name of the identity.

check_constraints = {'displayname': {'length': {'max': 150}}, 'email': {'length': {'max': 256}}, 'username': {'length': {'max': 50, 'min': 3}}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the local identity and of the associated identity.

username

Unique username.

Restricted to a minimum length of 3 and a maximum length of 50 characters.

email

Email address.

Restricted to a maximum length of 256 characters.

displayname

Display name.

Restricted to a maximum length of 150 characters.

password_hash

Hashed password using PBKDF2 with SHA256 and a salt value of 16 chars.

email_confirmed

Indicates whether the user’s email has been confirmed or not.

classmethod decode_email_confirmation_token(token)[source]

Decode the given JSON web token of type "email_confirmation".

See also get_email_confirmation_token().

Parameters

token – The token to decode.

Returns

The tokens decoded payload or None if the token is invalid or expired.

classmethod decode_password_reset_token(token)[source]

Decode the given JSON web token of type "password_reset".

See also get_password_reset_token().

Parameters

token – The token to decode.

Returns

The tokens decoded payload or None if the token is invalid or expired.

classmethod create(*, user, username, email, displayname, password)[source]

Create a new local identity and add it to the database session.

Parameters
  • user – The user the identity should belong to.

  • username – The identity’s unique username.

  • email – The identity’s email.

  • displayname – The identity’s display name.

  • password – The identity’s password, which will be hashed securely before persisting.

Returns

The new LocalIdentity object.

set_password(password)[source]

Set an identity’s password.

Parameters

password – The password, which will be hashed securely before persisting.

check_password(password)[source]

Check if an identity’s password matches the given password.

The given password will be hashed and checked against the stored password hash.

Parameters

password – The password to check.

Returns

True if the passwords match, False otherwise.

get_email_confirmation_token(email=None, expires_in=3600)[source]

Create a new JSON web token of type "email_confirmation".

Besides its type, the token includes the ID and email address of this identity.

Parameters
  • email – (optional) An email to include in the payload of the token, which can be used to change an identity’s email on confirmation. Defaults to the identity’s current email.

  • expires_in – (optional) The time in seconds the token will expire in.

Returns

The encoded token.

get_password_reset_token(expires_in=3600)[source]

Create a new JSON web token of type "password_reset".

Besides its type, the token includes the ID of this identity.

Parameters

expires_in – (optional) The time in seconds the token will expire in.

Returns

The encoded token.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

type

The identity type.

Used by SQLAlchemy to distinguish between different identity types and to automatically select from the correct identity table using joined table inheritance.

user_id

The ID of the user the identity belongs to.

class kadi.modules.accounts.models.LDAPIdentity(**kwargs)[source]

Bases: Identity

Model to represent LDAP identities.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'username', 'email']

See SimpleReprMixin.

identity_type = {'name': 'LDAP', 'type': 'ldap'}

The type and full name of the identity.

check_constraints = {'displayname': {'length': {'max': 150}}}

See kadi.lib.db.generate_check_constraints().

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

type

The identity type.

Used by SQLAlchemy to distinguish between different identity types and to automatically select from the correct identity table using joined table inheritance.

user_id

The ID of the user the identity belongs to.

id

The ID of the LDAP identity and of the associated identity.

username

Unique username.

email

Email address.

displayname

Display name.

Restricted to a maximum length of 150 characters.

classmethod create(*, user, username, email, displayname)[source]

Create a new LDAP identity and add it to the database session.

Parameters
  • user – The user the identity should belong to.

  • username – The identity’s unique username.

  • email – The identity’s email.

  • displayname – The identity’s display name.

Returns

The new LDAPIdentity object.

class kadi.modules.accounts.models.ShibIdentity(**kwargs)[source]

Bases: Identity

Model to represent Shibboleth identities.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

type

The identity type.

Used by SQLAlchemy to distinguish between different identity types and to automatically select from the correct identity table using joined table inheritance.

user_id

The ID of the user the identity belongs to.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'username', 'email']

See SimpleReprMixin.

identity_type = {'name': 'Shibboleth', 'type': 'shib'}

The type and full name of the identity.

check_constraints = {'displayname': {'length': {'max': 150}}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the Shibboleth identity and of the associated identity.

username

Unique username.

email

Email address.

displayname

Display name.

Restricted to a maximum length of 150 characters.

classmethod create(*, user, username, email, displayname)[source]

Create a new Shibboleth identity and add it to the database session.

Parameters
  • user – The user the identity should belong to.

  • username – The identity’s unique username.

  • email – The identity’s email.

  • displayname – The identity’s display name.

Returns

The new ShibIdentity object.

class kadi.modules.accounts.providers.core.BaseProvider[source]

Bases: ABC

Base class for authentication providers.

Each provider should override register() and authenticate() and specify its meta attributes in Meta. Those methods should return an identity object subclassing Identity or a UserInfo object respectively. If passwords are allowed to be changed by users, allow_password_change() and change_password() need to be overridden as well, returning a boolean value indicating whether passwords can be changed and whether the change was successful repectively.

The function init_auth_providers() needs to be called beforehand to initialize the application’s configuration for use with the registered authentication providers.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = None

The type of a provider.

defaults = {}

The default configuration values of a provider.

Each provider should at least specify a title alongside all other provider-specific configuration.

class UserInfo(is_authenticated, data=None)[source]

Bases: object

Wrapper class to store user information.

Should be returned by authenticate().

Parameters
  • is_authenticated – Flag to indicate if the represented user is authenticated or not.

  • data – (optional) The wrapped user data. This should generally be an object-like type representing the user information or the actual user.

classmethod create_identity(*, system_role, identity_model, apply_role_rules=True, **kwargs)[source]

Create a new user and a corresponding identity.

The latest identity of the user will be set to the newly created one automatically. Additionally, all existing role rules will be applied to the newly created user in a background task.

Note that this function issues a database commit or rollback.

Parameters
  • system_role – The system role of the user.

  • identity_model – The identity model to use for creating the user’s identity.

  • apply_role_rules – (optional) Flag indicating whether to apply all existing role rules to the newly registered user.

  • **kwargs – Additional keyword arguments to pass to the identity model’s create method.

Returns

The newly created identity or None if it could not be created.

classmethod is_registered()[source]

Check if a provider is registered in the application.

Returns

True if the provider is registered, False otherwise.

classmethod get_config()[source]

Get a provider’s config from the current application object.

Returns

The provider’s configuration dictionary.

classmethod allow_password_change()[source]

Check whether a provider supports changing passwords.

Returns

Flag indicating whether the provider supports changing passwords.

abstract classmethod register(**kwargs)[source]

Register a virtual subclass of an ABC.

Returns the subclass, to allow usage as a class decorator.

abstract classmethod change_password(username, old_password, new_password)[source]

Change a password of an existing user if supported by a provider.

Parameters
  • username – The unique username of the user.

  • old_password – The current password of the user.

  • new_password – The new password of the user.

Returns

A boolean value indicating whether the password change was successful.

Raises

NotImplementedError – If changing a user’s password is not supported by the provider.

kadi.modules.accounts.providers.core.init_auth_providers(app)[source]

Initialize all authentication providers for use in the application.

Makes use of the AUTH_PROVIDERS specified in the application’s configuration. During initialization, the AUTH_PROVIDERS configuration will be modified to use an ordered dictionary instead and will also include the following additional keys:

  • "provider_class": A reference to the provider class.

  • "identity_class": A reference to the identity class.

  • "form_class": A reference to the form class.

Parameters

app – The application object.

class kadi.modules.accounts.providers.ldap.LDAPProvider[source]

Bases: BaseProvider

LDAP authentication provider.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = 'ldap'

The type of the provider.

defaults = {'active_directory': False, 'allow_password_change': False, 'bind_pw': None, 'bind_user': None, 'default_system_role': 'member', 'displayname_attr': 'displayName', 'email_attr': 'mail', 'encryption': None, 'firstname_attr': None, 'host': '', 'lastname_attr': None, 'port': 389, 'send_old_password': False, 'title': l'Login with LDAP', 'username_attr': 'uid', 'users_dn': '', 'validate_cert': True}

The default configuration values of the provider.

classmethod allow_password_change()[source]

Check whether a provider supports changing passwords.

Returns

Flag indicating whether the provider supports changing passwords.

classmethod register(*, username, email, displayname, system_role=None, apply_role_rules=True, **kwargs)[source]

Register a new LDAP user.

If an identity with the given username already exists, that identity will be updated with the given email.

Note that this function may issue a database commit or rollback.

Parameters
  • username – The user’s unique name.

  • email – The user’s email address.

  • displayname – The user’s display name.

  • system_role – (optional) The user’s system role. Defaults to "member".

  • apply_role_rules – (optional) Flag indicating whether to apply all existing role rules to the newly registered user.

Returns

A new LDAPIdentity object linked with a new user or an existing, updated LDAPIdentity. Returns None if the identity could not be created or if this provider is not registered in the application.

classmethod authenticate(*, username, password, **kwargs)[source]

Authenticate an LDAP user.

Parameters
  • username – The user’s unique name to use for binding to the LDAP server and for searching their entry in the database.

  • password – The user’s password to use for binding to the LDAP server.

Returns

An instance of UserInfo or None if this provider is not registered in the application. In case the authentication is successful, the contained data is an object containing the username, email and display name of the user as attributes username, email and displayname respectively.

classmethod change_password(username, old_password, new_password)[source]

Change a password of an existing user if supported by a provider.

Parameters
  • username – The unique username of the user.

  • old_password – The current password of the user.

  • new_password – The new password of the user.

Returns

A boolean value indicating whether the password change was successful.

Raises

NotImplementedError – If changing a user’s password is not supported by the provider.

class kadi.modules.accounts.providers.local.LocalProvider[source]

Bases: BaseProvider

Local authentication provider.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = 'local'

The type of the provider.

defaults = {'allow_registration': False, 'default_system_role': 'member', 'email_confirmation_required': False, 'title': l'Login with credentials'}

The default configuration values of the provider.

classmethod registration_allowed()[source]

Check if this provider allows registration of new users.

Returns

True if registration is allowed, False if not or if this provider is not registered in the application.

classmethod email_confirmation_required()[source]

Check if this provider requires email confirmation.

Returns

True if email confirmation is required, False if not or if this provider is not registered in the application.

classmethod allow_password_change()[source]

Check whether a provider supports changing passwords.

Returns

Flag indicating whether the provider supports changing passwords.

classmethod register(*, username, email, displayname, password, system_role=None, apply_role_rules=True, **kwargs)[source]

Register a new local user.

Note that this function may issue a database commit or rollback.

Parameters
  • username – The user’s unique name.

  • email – The user’s email address.

  • displayname – The user’s display name.

  • password – The user’s password.

  • system_role – (optional) The user’s system role. Defaults to "member".

  • apply_role_rules – (optional) Flag indicating whether to apply all existing role rules to the newly registered user.

Returns

A new LocalIdentity object linked with a new user or None if the identity could not be created or if this provider is not registered in the application.

classmethod authenticate(*, username, password, **kwargs)[source]

Authenticate a local user.

Parameters
  • username – The user’s unique name to search in the local database.

  • password – The user’s password to call LocalIdentity.check_password() with.

Returns

An instance of UserInfo or None if this provider is not registered in the application. In case the authentication is successful, the contained data is the user’s existing LocalIdentity.

classmethod change_password(username, old_password, new_password)[source]

Change a password of an existing user if supported by a provider.

Parameters
  • username – The unique username of the user.

  • old_password – The current password of the user.

  • new_password – The new password of the user.

Returns

A boolean value indicating whether the password change was successful.

Raises

NotImplementedError – If changing a user’s password is not supported by the provider.

class kadi.modules.accounts.providers.shib.ShibProvider[source]

Bases: BaseProvider

Shibboleth authentication provider.

Currently tested with the official “Shibboleth Service Provider 3” in combination with the Apache web server using “mod_shib”.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = 'shib'

The type of the provider.

defaults = {'default_system_role': 'member', 'displayname_attr': 'displayName', 'email_attr': 'mail', 'env_encoding': 'latin-1', 'firstname_attr': 'givenName', 'idp_displayname_attr': 'Meta-displayName', 'idp_entity_id_attr': 'Shib-Identity-Provider', 'idp_support_contact_attr': 'Meta-supportContact', 'idps': [], 'lastname_attr': 'sn', 'multivalue_separator': ';', 'sp_entity_id': '/shibboleth', 'sp_logout_initiator': '/Shibboleth.sso/Logout', 'sp_session_initiator': '/Shibboleth.sso/Login', 'title': l'Login with Shibboleth', 'username_attr': 'eppn'}

The default configuration values of the provider.

The configured identity providers ("idps") must be specified as a list of dictionaries, each dictionary containing the entity ID ("entity_id") and display name ("name") of the provider.

classmethod get_choices()[source]

Get all configured identity providers for use in a selection.

Returns

A list of tuples, each tuple containing the entity ID and display name of the identity provider, sorted by display name. The first entry in the list represents the empty default choice in a selection where both values are set to an empty string. If this provider is not registered in the application, the returned list will only contain the default choice.

classmethod get_session_initiator(entity_id, target)[source]

Get the configured Shibboleth session initiator.

The session initiator is simply an URL consisting of the configured login endpoint of the service provider and containing the given arguments, the entity_id and target URL, as query parameters.

Parameters
  • entity_id – The entity ID of the identity provider to use for login.

  • target – The URL to redirect to after logging in successfully.

Returns

The generated session initiator URL. If this provider is not registered in the application, an empty string will be returned.

classmethod get_logout_initiator(target)[source]

Get the configured Shibboleth local logout initiator.

The local logout initiator is simply an URL consisting of the configured logout endpoint of the service provider and containing the given argument, the target URL, as query parameter.

Parameters

target – The URL to redirect to after logging out successfully.

Returns

The generated local logout initiator URL. If this provider is not registered in the application, an empty string will be returned.

classmethod contains_valid_idp()[source]

Check if the Shibboleth session contains a valid identity provider.

In this case, valid means that the entity ID of an identity provider is contained in the configured list of identity providers. This requires the entity ID to check to be available as an environment variable, so a valid Shibboleth session is required.

Returns

True if the identity provider is valid, False if it is not or if there is no valid Shibboleth session or if this provider is not registered in the application.

classmethod get_metadata()[source]

Get the metadata of the Shibboleth session.

Returns

An object containing the entity ID of the service provider, the entity ID of the identity provider, its displayname and its support contact email address as attributes sp_entity_id, idp_entity_id, idp_displayname and idp_support_contact respectively. This requires those attributes to be available as an environment variables, so a valid Shibboleth session is required. If this provider is not registered in the application, None will be returned.

classmethod get_required_attributes()[source]

Get all attributes required for successful authentication.

Currently, the only required attributes are the user’s unique username and email address.

Returns

A dictionary containing the required keys to get as environment variables and their respective values. If the identity provider did not provide an attribute, the value will be None for the respective key or for all of them if no valid Shibboleth session exists. If this provider is not registered in the application, None will be returned.

classmethod register(*, username, email, displayname, system_role=None, apply_role_rules=True, **kwargs)[source]

Register a new Shibboleth user.

If an identity with the given username already exists, that identity will be updated with the given email.

Note that this function may issue a database commit or rollback.

Parameters
  • username – The user’s unique name.

  • email – The user’s email address.

  • displayname – The user’s display name.

  • system_role – (optional) The user’s system role. Defaults to "member".

  • apply_role_rules – (optional) Flag indicating whether to apply all existing role rules to the newly registered user.

Returns

A new ShibIdentity object linked with a new user or an existing, updated ShibIdentity. Returns None if the identity could not be created or if this provider is not registered in the application.

classmethod authenticate(**kwargs)[source]

Authenticate a Shibboleth user.

No arguments need to be given, as the necessary user attributes need to be available as environment variables if a valid Shibboleth session exists.

Returns

An instance of UserInfo or None if this provider is not registered in the application. In case the authentication is successful, the contained data is an object containing the username, email and display name of the user as attributes username, email and displayname respectively.

classmethod change_password(username, old_password, new_password)[source]

Change a password of an existing user if supported by a provider.

Parameters
  • username – The unique username of the user.

  • old_password – The current password of the user.

  • new_password – The new password of the user.

Returns

A boolean value indicating whether the password change was successful.

Raises

NotImplementedError – If changing a user’s password is not supported by the provider.

class kadi.modules.accounts.schemas.IdentitySchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent identities.

See Identity.

class kadi.modules.accounts.schemas.UserSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent users.

See User.

kadi.modules.accounts.utils.login_user(identity, **kwargs)[source]

Login a user by their identity.

Wraps Flask-Login’s login_user function but also makes sure to update the user’s current identity.

Parameters

identity – The identity to log in with.

Returns

True if the login was successful, False otherwise.

kadi.modules.accounts.utils.save_user_image(user, file_object)[source]

Set an image file as a user’s profile image.

Uses kadi.lib.storage.local.save_as_thumbnail() to create and save a thumbnail of the given image. Any previous image will be deleted beforehand using delete_user_image(), which will also be called if the image cannot be saved.

Parameters
  • user – The user to set the new profile image for.

  • file_object – The image file object.

kadi.modules.accounts.utils.delete_user_image(user)[source]

Delete a user’s profile image if one exists.

Uses kadi.lib.storage.local.delete_thumbnail() to delete the actual thumbnail file.

Parameters

user – The user whose profile image should be deleted.

kadi.modules.accounts.utils.json_user(user)[source]

Convert a user into a JSON representation.

Parameters

user – The user to convert.

Returns

The converted user.

kadi.modules.accounts.utils.get_filtered_user_ids(filter_term)[source]

Get all IDs of users filtered by the given term.

Convenience function to filter users based on their identities. Note that users with multiple identities are only returned once and merged users are always excluded, as they do not have any identities anymore.

Parameters

filter_term – A (case insensitive) term to filter the users by their username or display name.

Returns

The filtered user IDs as query.

kadi.modules.accounts.utils.clean_users(inside_task=False)[source]

Clean all deleted users.

Note that this function may issue one or more database commits.

Parameters

inside_task – (optional) A flag indicating whether the function is executed in a task. In that case, additional information will be logged.

Collections

kadi.modules.collections.core.create_collection(*, identifier, title, creator=None, description='', visibility='private', state='active', tags=None)[source]

Create a new collection.

Uses kadi.lib.resources.core.create_resource().

Parameters
Returns

See kadi.lib.resources.core.create_resource().

kadi.modules.collections.core.update_collection(collection, tags=None, user=None, **kwargs)[source]

Update an existing collection.

Uses kadi.lib.resources.core.update_resource().

Parameters
  • collection – The collection to update.

  • tags – (optional) A list of tag names to tag the collection with. See also Tag.

  • user – (optional) The user who triggered the update. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.resources.core.update_resource().

Returns

See kadi.lib.resources.core.update_resource().

kadi.modules.collections.core.delete_collection(collection, user=None)[source]

Delete an existing collection.

Uses kadi.lib.resources.core.delete_resource().

Parameters
  • collection – The collection to delete.

  • user – (optional) The user who triggered the deletion. Defaults to the current user.

kadi.modules.collections.core.restore_collection(collection, user=None)[source]

Restore a deleted collection.

Uses kadi.lib.resources.core.restore_resource().

Parameters
  • collection – The collection to restore.

  • user – (optional) The user who triggered the restoration. Defaults to the current user.

kadi.modules.collections.core.purge_collection(collection)[source]

Purge an existing collection.

Uses kadi.lib.resources.core.purge_resource().

Parameters

collection – The collection to purge.

Link two collections together.

Note that this function acquires a lock on the given collections.

Parameters
  • parent_collection – The parent collection.

  • child_collection – The child collection.

  • user – (optional) The user performing the link operation. Defaults to the current user.

Returns

True if the collections were linked successfully, False if both given collections refer to the same object, if the given child collection already has a parent or if the given child collection is already a parent of the parent collection.

Raises

KadiPermissionError – If the user performing the operation does not have the necessary permissions.

kadi.modules.collections.export.get_json_data(collection, export_filter, user)[source]

Export a collection as a JSON file.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.collections.export.get_qr_data(collection)[source]

Export a collection as a QR code in PNG format.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.collections.export.get_ro_crate_data(collection, export_filter, user)[source]

Export a collection as a RO-Crate.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.collections.export.get_export_data(collection, export_type, export_filter=None, user=None)[source]

Export a collection in a given format.

Parameters
  • collection – The collection to export.

  • export_type – The export type, one of "json", "qr" or "ro-crate".

  • export_filter

    (optional) A dictionary specifying various filters to exclude certain information from the returned export data, depending on the export type. Only usable in combination with the "json" and "ro-crate" export types.

    Example:

    {
        # Whether user information about the creator of the collection or any
        # linked resource should be excluded.
        "user": False,
        # Whether to exclude information about records that are part of the
        # collection.
        "records": False,
        # When record information is not excluded, whether to exclude all
        # (True), outgoing ("out") or incoming ("in") links of records with
        # other records.
        "links": False,
        # Whether to return only the metadata file of an exported RO-Crate.
        "metadata_only": False,
    }
    

  • user – (optional) The user to check for various access permissions when generating the export data. Defaults to the current user.

Returns

The exported collection data as an in-memory byte stream or None if an unknown export type was given. Note that for the ro-crate export type, the returned data is an iterable producing the actual data on the fly instead, unless only the metadata file is exported by specifying the corresponding export filter.

class kadi.modules.collections.forms.BaseCollectionForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating or updating collections.

Parameters

collection – (optional) A collection used for prefilling the form.

class kadi.modules.collections.forms.NewCollectionForm(*args, **kwargs)[source]

Bases: BaseCollectionForm

A form for use in creating new collections.

Parameters
  • collection – (optional) See BaseCollectionForm.

  • user – (optional) A user that will be used for checking various access permissions when prefilling the form. Defaults to the current user.

class kadi.modules.collections.forms.EditCollectionForm(*args, **kwargs)[source]

Bases: BaseCollectionForm

A form for use in editing existing collections.

Parameters

collection – The collection to edit, used for prefilling the form.

class kadi.modules.collections.forms.LinkRecordsForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in linking collections with records.

class kadi.modules.collections.forms.LinkCollectionsForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in linking collections with other collections.

class kadi.modules.collections.forms.BaseRolesForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in managing user or group roles of collections.

validate(extra_validators=None)[source]

Validate the form by calling validate on each field. Returns True if validation passes.

If the form defines a validate_<fieldname> method, it is appended as an extra validator for the field’s validate.

Parameters

extra_validators – A dict mapping field names to lists of extra validator methods to run. Extra validators run after validators passed when creating the field. If the form has validate_<fieldname>, it is the last extra validator.

class kadi.modules.collections.forms.AddCollectionRolesForm(*args, **kwargs)[source]

Bases: BaseRolesForm

A form for use in adding user or group roles to a collection.

class kadi.modules.collections.forms.UpdateRecordsRolesForm(*args, **kwargs)[source]

Bases: BaseRolesForm

A form for use in updating user or group roles of linked records.

class kadi.modules.collections.mappings.CollectionMapping(meta=None, **kwargs)[source]

Bases: Document, MappingMixin

Search mapping for collections.

See Collection.

class kadi.modules.collections.models.CollectionVisibility[source]

Bases: StringEnum

String enum containing all possible visibility values for collections.

class kadi.modules.collections.models.CollectionState[source]

Bases: StringEnum

String enum containing all possible state values for collections.

class kadi.modules.collections.models.Collection(**kwargs)[source]

Bases: SimpleReprMixin, SearchableMixin, StateTimestampMixin, FavoriteMixin, TaggingMixin, Model

Model to represent collections.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'parent_id', 'identifier', 'visibility', 'state']

See SimpleReprMixin.

search_mapping = 'kadi.modules.collections.mappings.CollectionMapping'

See SearchableMixin.

revision = ['identifier', 'title', 'description', 'visibility', 'state', 'tags[name]']

See kadi.lib.revisions.core.setup_revisions().

permissions = {'actions': [('read', l'View this collection.'), ('link', l'Manage links of this collection with other resources.'), ('update', l'Edit this collection.'), ('permissions', l'Manage permissions of this collection.'), ('delete', l'Delete this collection.')], 'default_permissions': {'read': {'visibility': 'public'}}, 'global_actions': [('create', 'Create collections.'), ('read', 'View any collection.'), ('link', 'Manage links of any collection with other resources.'), ('update', 'Edit any collection.'), ('permissions', 'Manage permissions of any collection.'), ('delete', 'Delete any collection.')], 'roles': [('member', ['read']), ('collaborator', ['read', 'link']), ('editor', ['read', 'link', 'update']), ('admin', ['read', 'link', 'update', 'permissions', 'delete'])]}

Possible permissions and roles for collections.

See kadi.lib.permissions.

check_constraints = {'description': {'length': {'max': 10000}}, 'identifier': {'length': {'max': 50}}, 'state': {'values': ['active', 'deleted']}, 'title': {'length': {'max': 150}}, 'visibility': {'values': ['private', 'public']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the collection, auto incremented.

user_id

The ID of the user who created the collection.

parent_id

The optional ID of the parent collection.

identifier

The unique identifier of the collection.

Restricted to a maximum length of 50 characters.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

title

The title of the collection.

Restricted to a maximum length of 150 characters.

description

The description of the collection.

Restricted to a maximum length of 10_000 characters.

plain_description

The plain description of the collection.

Equal to the normal description with the difference that most markdown is stripped out.

visibility

The default visibility of the collection.

state

The state of the collection.

classmethod create(*, creator, identifier, title, description='', plain_description='', visibility='private', state='active')[source]

Create a new collection and add it to the database session.

Parameters
  • creator – The creator of the collection.

  • identifier – The unique identifier of the collection.

  • title – The title of the collection.

  • description – (optional) The description of the collection.

  • plain_description – (optional) The plain description of the collection.

  • visibility – (optional) The default visibility of the collection.

  • state – (optional) The state of the collection.

Returns

The new Collection object.

class kadi.modules.collections.schemas.CollectionSchema(previous_collection=None, linked_record=None, parent_collection=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent collections.

See Collection.

Parameters
  • previous_collection – (optional) A collection whose identifier should be excluded when checking for duplicates while deserializing.

  • linked_record – (optional) A record that is linked to each collection that should be serialized. Will be used to build endpoints for corresponding actions.

  • parent_collection – (optional) A collection that is the parent of each collection that should be serialized. Will be used to build endpoints for corresponding actions.

kadi.modules.collections.utils.search_collections(search_query=None, page=1, per_page=10, sort='_score', visibility=None, user_ids=None, tags=None, tag_operator='or', user=None)[source]

Search and filter for collections.

Uses kadi.lib.resources.utils.get_filtered_resources() and kadi.lib.resources.utils.search_resources().

Parameters
  • search_query – (optional) See func:kadi.lib.resources.utils.search_resources.

  • page – (optional) See kadi.lib.resources.utils.search_resources().

  • per_page – (optional) See kadi.lib.resources.utils.search_resources().

  • sort – (optional) See kadi.lib.resources.utils.search_resources().

  • visibility – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • user_ids – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • tags – (optional) A list of tag names to filter the collections with.

  • tag_operator – (optional) The operator to filter the tags with. One of "or" or "and".

  • user – (optional) The user to check for any permissions regarding the searched collections. Defaults to the current user.

Returns

The search results as returned by kadi.lib.resources.utils.search_resources().

kadi.modules.collections.utils.get_parent_collections(collection, user=None)[source]

Get all parents of a collection that a user can access.

In this context having access to a collection means having read permission for it. Note that as soon as a parent collection is not accessible or inactive, no further potential parents are collected.

Parameters
  • collection – The collection to get the parents of.

  • user – (optional) The user to check for access permissions when retrieving the collections. Defaults to the current user.

Returns

A list of parent collections starting with the immediate parent of the given collection.

kadi.modules.collections.utils.get_child_collections(collection, user=None)[source]

Recursively get all children of a collection that a user can access.

In this context having access to a collection means having read permission for it. Note that if a collection is not accessible or inactive, no further potential children of this collection are collected.

Parameters
  • collection – The collection to get the children of.

  • user – (optional) The user to check for access permissions when retrieving the collections. Defaults to the current user.

Returns

A list of child collections in unspecified order.

kadi.modules.collections.utils.get_child_collection_records(collection, actions=None, user=None)[source]

Recursively get all records of a collection hierarchy that a user can access.

In this context, the collection hierarchy refers to the given collection and all its direct or indirect children. Having access to a child collection or record means having read permission for it.

Uses get_child_collections() to determine the children of the given collection.

Parameters
  • collection – The collection to get the children and records of.

  • actions – (optional) Further actions to check the access permissions of the records for.

  • user – (optional) The user to check for access permissions when retrieving the collections and records. Defaults to the current user.

Returns

The records as query. Note that duplicate records are already filtered out.

Groups

kadi.modules.groups.core.create_group(*, identifier, title, creator=None, description='', visibility='private', state='active')[source]

Create a new group.

Uses kadi.lib.resources.core.create_resource().

Parameters
Returns

See kadi.lib.resources.core.create_resource().

kadi.modules.groups.core.update_group(group, user=None, **kwargs)[source]

Update an existing group.

Uses kadi.lib.resources.core.update_resource().

Parameters
  • group – The group to update.

  • user – (optional) The user who triggered the update. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.resources.update_resource().

Returns

See kadi.lib.resources.core.update_resource().

kadi.modules.groups.core.delete_group(group, user=None)[source]

Delete an existing group.

Uses kadi.lib.resources.core.delete_resource().

Parameters
  • group – The group to delete.

  • user – (optional) The user who triggered the deletion. Defaults to the current user.

kadi.modules.groups.core.restore_group(group, user=None)[source]

Restore a deleted group.

Uses kadi.lib.resources.core.restore_resource().

Parameters
  • group – The group to restore.

  • user – (optional) The user who triggered the restoration. Defaults to the current user.

kadi.modules.groups.core.purge_group(group)[source]

Purge an existing group.

Uses kadi.lib.resources.core.purge_resource().

Parameters

group – The group to purge.

class kadi.modules.groups.forms.BaseGroupForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating or updating groups.

class kadi.modules.groups.forms.NewGroupForm(*args, **kwargs)[source]

Bases: BaseGroupForm

A form for use in creating new groups.

class kadi.modules.groups.forms.EditGroupForm(*args, **kwargs)[source]

Bases: BaseGroupForm

A form for use in editing existing groups.

Parameters

group – The group to edit, used for prefilling the form.

class kadi.modules.groups.forms.AddMembersForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in adding members (i.e. user roles) to a group.

validate(extra_validators=None)[source]

Validate the form by calling validate on each field. Returns True if validation passes.

If the form defines a validate_<fieldname> method, it is appended as an extra validator for the field’s validate.

Parameters

extra_validators – A dict mapping field names to lists of extra validator methods to run. Extra validators run after validators passed when creating the field. If the form has validate_<fieldname>, it is the last extra validator.

class kadi.modules.groups.forms.AddRulesForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in adding new username role rules for groups.

class kadi.modules.groups.mappings.GroupMapping(meta=None, **kwargs)[source]

Bases: Document, MappingMixin

Search mapping for groups.

See Group.

class kadi.modules.groups.models.GroupVisibility[source]

Bases: StringEnum

String enum containing all possible visibility values for groups.

class kadi.modules.groups.models.GroupState[source]

Bases: StringEnum

String enum containing all possible state values for groups.

class kadi.modules.groups.models.Group(**kwargs)[source]

Bases: SimpleReprMixin, SearchableMixin, StateTimestampMixin, FavoriteMixin, Model

Model to represent groups.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'identifier', 'visibility', 'state']

See SimpleReprMixin.

search_mapping = 'kadi.modules.groups.mappings.GroupMapping'

See SearchableMixin.

timestamp_exclude = ['permissions', 'roles']

See StateTimestampMixin.

revision = ['identifier', 'title', 'description', 'visibility', 'state']

See kadi.lib.revisions.core.setup_revisions().

permissions = {'actions': [('read', l'View this group.'), ('update', l'Edit this group.'), ('members', l'Manage members of this group.'), ('delete', l'Delete this group.')], 'default_permissions': {'read': {'visibility': 'public'}}, 'global_actions': [('create', 'Create groups.'), ('read', 'View any group.'), ('update', 'Edit any group.'), ('members', 'Manage members of any group.'), ('delete', 'Delete any group.')], 'roles': [('member', ['read']), ('editor', ['read', 'update']), ('admin', ['read', 'update', 'members', 'delete'])]}

Possible permissions and roles for groups.

See kadi.lib.permissions.

check_constraints = {'description': {'length': {'max': 10000}}, 'identifier': {'length': {'max': 50}}, 'state': {'values': ['active', 'deleted']}, 'title': {'length': {'max': 150}}, 'visibility': {'values': ['private', 'public']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the group, auto incremented.

user_id

The ID of the user who created the group.

identifier

The unique identifier of the group.

Restricted to a maximum length of 50 characters.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

title

The title of the group.

Restricted to a maximum length of 150 characters.

description

The description of the group.

Restricted to a maximum length of 10_000 characters.

plain_description

The plain description of the group.

Equal to the normal description with the difference that most markdown is stripped out.

image_name

The optional name/identifier of a group’s profile image.

This identifier is used to build the local file path where the actual image is stored.

visibility

The default visibility of the group.

state

The state of the group.

classmethod create(*, creator, identifier, title, description='', plain_description='', visibility='private', state='active')[source]

Create a new group and add it to the database session.

Parameters
  • creator – The creator of the group.

  • identifier – The unique identifier of the group.

  • title – The title of the group.

  • description – (optional) The description of the group.

  • plain_description – (optional) The plain description of the group.

  • visibility – (optional) The default visibility of the group.

  • state – (optional) The state of the group.

Returns

The new Group object.

class kadi.modules.groups.schemas.GroupSchema(previous_group=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent groups.

See Group.

Parameters

previous_group – (optional) A group whose identifier should be excluded when checking for duplicates while deserializing.

kadi.modules.groups.utils.search_groups(search_query=None, page=1, per_page=10, sort='_score', visibility=None, user_ids=None, member_only=False, user=None)[source]

Search and filter for groups.

Uses kadi.lib.resources.utils.get_filtered_resources() and kadi.lib.resources.utils.search_resources().

Parameters
  • search_query – (optional) See func:kadi.lib.resources.utils.search_resources.

  • page – (optional) See kadi.lib.resources.utils.search_resources().

  • per_page – (optional) See kadi.lib.resources.utils.search_resources().

  • sort – (optional) See kadi.lib.resources.utils.search_resources().

  • visibility – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • user_ids – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • member_only – (optional) Flag indicating whether to exclude groups without membership.

  • user – (optional) The user to check for any permissions regarding the searched groups. Defaults to the current user.

Returns

The search results as returned by kadi.lib.resources.utils.search_resources().

kadi.modules.groups.utils.get_user_groups(user=None)[source]

Get all groups a user is a member of.

Group membership currently works through roles. As long as a user has any role inside a group, they are a member of it. Therefore, it is currently safe to assume that the given user has at least read permission for such groups. Note that inactive groups will be filtered out.

Parameters

user – (optional) The user to get the groups for. Defaults to the current user.

Returns

The groups of the given user as query.

kadi.modules.groups.utils.save_group_image(group, file_object)[source]

Set an image file as a group’s profile image.

Uses kadi.lib.storage.local.save_as_thumbnail() to create and save a thumbnail of the given image. Any previous image will be deleted beforehand using delete_group_image(), which will also be called if the image cannot be saved.

Parameters
  • group – The group to set the new profile image for.

  • file_object – The image file object.

kadi.modules.groups.utils.delete_group_image(group)[source]

Delete a group’s profile image if one exists.

Uses kadi.lib.storage.local.delete_thumbnail() to delete the actual thumbnail file.

Parameters

group – The group of which the profile image should be deleted.

Main

class kadi.modules.main.forms.LegalsAcceptanceForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in mandatory acceptance of legal notices.

kadi.modules.main.utils.get_tags(filter_term='', resource_type=None, user=None)[source]

Get all distinct tags of resources a user can access.

Parameters
  • filter_term – (optional) A (case insensitive) term to filter the tags by their name.

  • resource_type – (optional) A resource type to limit the tags to. One of "record" or "collection".

  • user – (optional) The user who will be checked for access permissions. Defaults to the current user.

Returns

The tags as query, ordered by their name in ascending order.

kadi.modules.main.utils.get_licenses(filter_term='')[source]

Get all licenses.

Parameters

filter_term – (optional) A (case insensitive) term to filter the licenses by their title or name.

Returns

The licenses as query, ordered by their title in ascending order.

kadi.modules.main.utils.get_favorite_resources(max_items=6, user=None)[source]

Get a list of serialized resources favorited by the given user.

Parameters
  • max_items – (optional) The maximum number of resource to return.

  • user – (optional) The user the favorite resources belong to. Defaults to the current user.

Returns

The serialized resources as a list of dictionaries, each resource additionally containing its type in a human-readable manner as pretty_type.

kadi.modules.main.utils.get_latest_resources(user=None)[source]

Get a list of serialized resources according to their modification date.

Uses the home page layout as configured via the user-specific "HOME_LAYOUT" config item to determine how many resources of each type to collect.

Parameters

user – (optional) The user the layout belongs to. Defaults to the current user.

Returns

The serialized resources as a list of dictionaries per resource type, each containing the localized resource title ("title"), the resource search url ("url") and the serialized resources themselves ("items").

Notifications

kadi.modules.notifications.core.create_notification_data(notification)[source]

Create a notification suitable for presenting it to a client.

Parameters

notification – A Notification object.

Returns

A tuple containing the title and the HTML body of the notification.

kadi.modules.notifications.core.dismiss_notification(notification)[source]

Dismiss a notification.

If the notification is of type "task_status", the referenced task will be revoked as well.

Parameters

notification – The Notification to dismiss.

kadi.modules.notifications.mails.send_email_confirmation_mail(email, displayname, token, expires_in)[source]

Send an email confirmation mail in a background task.

Uses kadi.modules.notifications.tasks.start_send_mail_task() to send the mail.

Parameters
  • email – The recipient address.

  • displayname – The display name of the addressed user.

  • token – A JSON web token as returned by LocalIdentity.get_email_confirmation_token() corresponding to the identity of the addressed user.

  • expires_in – The time in seconds the token will expire in.

Returns

True if the task was started successfully, False otherwise.

kadi.modules.notifications.mails.send_password_reset_mail(email, displayname, token, expires_in)[source]

Send a password reset mail in a background task.

Uses kadi.modules.notifications.tasks.start_send_mail_task() to send the mail.

Parameters
  • email – The recipient address.

  • displayname – The display name of the addressed user.

  • token – A JSON web token as returned by LocalIdentity.get_password_reset_token() corresponding to the identity of the addressed user.

  • expires_in – The time in seconds the token will expire in.

Returns

True if the task was started successfully, False otherwise.

kadi.modules.notifications.mails.send_test_mail(email, displayname)[source]

Send a test mail in a background task.

Uses kadi.modules.notifications.tasks.start_send_mail_task() to send the mail.

Parameters
  • email – The recipient address.

  • displayname – The display name of the addressed user.

Returns

True if the task was started successfully, False otherwise.

class kadi.modules.notifications.models.Notification(**kwargs)[source]

Bases: SimpleReprMixin, Model

Model to represent notifications.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'name']

See SimpleReprMixin.

id

The ID of the notification, auto incremented.

user_id

The ID of the user who should receive the notification.

name

The name or type of the notification.

data

The optional data of the notification, depending on its type.

created_at

The date and time the notification was created at.

classmethod create(*, user, name, data=None)[source]

Create a new notification and add it to the database session.

Parameters
  • user – The user who should receive the notification.

  • name – The name or type of the notification.

  • data – (optional) The data of the notification.

Returns

The new Notification object.

class kadi.modules.notifications.schemas.NotificationSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent notifications.

See Notification.

kadi.modules.notifications.tasks.start_send_mail_task(*, subject, message, to_addresses, from_address=None, cc=None, bcc=None, attachments=None, reply_to=None, html_message=None, headers=None)[source]

Send a mail in a background task.

See kadi.lib.mails.send_mail() for the possible parameters.

In case the connection to the mail server fails, the task will be retried every 60 seconds until a maximum defined in CELERY_ANNOTATIONS in the application’s configuration is reached. Other errors will cause the task to fail, however.

Returns

True if the task was started successfully, False otherwise. Note that the task being started successfully does not necessarily mean that the email will be sent successfully as well.

Records

kadi.modules.records.core.create_record(*, identifier, title, creator=None, type=None, description='', license=None, extras=None, visibility='private', state='active', tags=None)[source]

Create a new record.

Uses kadi.lib.resources.core.create_resource().

Parameters
Returns

See kadi.lib.resources.core.create_resource().

kadi.modules.records.core.update_record(record, tags=None, user=None, **kwargs)[source]

Update an existing record.

Uses kadi.lib.resources.core.update_resource().

Parameters
  • record – The record to update.

  • tags – (optional) A list of tag names to tag the record with. See also Tag.

  • user – (optional) The user who triggered the update. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.resources.update_resource().

Returns

See kadi.lib.resources.core.update_resource().

kadi.modules.records.core.delete_record(record, user=None)[source]

Delete an existing record.

Uses kadi.lib.resources.core.delete_resource().

Parameters
  • record – The record to delete.

  • user – (optional) The user who triggered the deletion. Defaults to the current user.

kadi.modules.records.core.restore_record(record, user=None)[source]

Restore a deleted record.

Uses kadi.lib.resources.core.restore_resource().

Parameters
  • record – The record to restore.

  • user – (optional) The user who triggered the restoration. Defaults to the current user.

kadi.modules.records.core.purge_record(record)[source]

Purge an existing record.

This will also remove all files and uploads of the record.

Uses kadi.lib.resources.core.purge_resource().

Parameters

record – The record to purge.

class kadi.modules.records.export.RecordPDF(record, export_filter=None, user=None)[source]

Bases: PDF

Record PDF export class.

Parameters
  • record – The record to generate the PDF from.

  • export_filter – (optional) See get_export_data().

  • user – (optional) The user to check for various access permissions when generating the PDF. Defaults to the current user.

print_overview()[source]

Print the record overview, i.e. the basic metadata of the record.

print_extras()[source]

Print the extra metadata of the record.

print_files()[source]

Print the files of the record.

Print the links of the record with other records.

class kadi.modules.records.export.RecordROCrate(record_or_records, root_dir, export_filter=None, user=False)[source]

Bases: ROCrate

Record RO-Crate export class.

Parameters
  • record_or_records – A single record or iterable of records to include in the RO-Crate.

  • root_dir – The root directory of the RO-Crate.

  • export_filter – (optional) See get_export_data().

  • user – (optional) The user to check for various access permissions when generating the RO-Crate. Defaults to the current user.

add_record_metadata(record, json_data)[source]

Add the metadata of a record to the RO-Crate.

add_record_data(record, json_data)[source]

Add the data of a record to the RO-Crate.

kadi.modules.records.export.filter_extras(extras, excluded_extras)[source]

Filter the given extra metadata.

Parameters
  • extras – The extras to filter

  • excluded_extras – A filter mask of extra metadata keys to exclude. See get_export_data().

Returns

A copy of the filtered extras.

kadi.modules.records.export.get_dict_data(record, export_filter, user)[source]

Export a record as a dictionary.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.records.export.get_json_data(record, export_filter, user)[source]

Export a record as a JSON file.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.records.export.get_pdf_data(record, export_filter, user)[source]

Export a record as a PDF file.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.records.export.get_qr_data(record)[source]

Export a record as a QR code in PNG format.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.records.export.get_ro_crate_data(record, export_filter, user)[source]

Export a record as a RO-Crate.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.records.export.get_export_data(record, export_type, export_filter=None, user=None)[source]

Export a record in a given format.

Parameters
  • record – The record to export.

  • export_type – The export type, one of "json", "pdf", "qr" or "ro-crate".

  • export_filter

    (optional) A dictionary specifying various filters to exclude certain information from the returned export data, depending on the export type. Only usable in combination with the "json", "pdf" and "ro-crate" export types.

    Example:

    {
        # Whether user information about the creator of the record or any linked
        # resource should be excluded.
        "user": False,
        # Whether to exclude all (True), outgoing ("out") or incoming ("in")
        # links of the record with other records.
        "links": False,
        # A dictionary specifying a filter mask of extra metadata keys to
        # exclude. The value of each key can either be an empty dictionary, to
        # exclude the whole extra including all of its potentially nested
        # values, or another dictionary with the same possibilities as in the
        # parent dictionary. For list entries, indices need to be specified as
        # strings, starting at 0.
        "extras": {"sample_key": {}, "sample_list": {"0": {}}},
        # Whether to apply the extras filter mask to any linked records as well.
        "propagate_extras": False,
        # Whether to return only the metadata file of an exported RO-Crate.
        "metadata_only": False,
    }
    

  • user – (optional) The user to check for various access permissions when generating the export data. Defaults to the current user.

Returns

The exported record data as an in-memory byte stream or None if an unknown export type was given. Note that for the ro-crate export type, the returned data is an iterable producing the actual data on the fly instead, unless only the metadata file is exported by specifying the corresponding export filter.

kadi.modules.records.extras.is_nested_type(value_type)[source]

Check if the type of an extra metadata entry is nested.

Parameters

value_type – The type of the extra metadata entry.

Returns

True if the given type is nested, False otherwise.

class kadi.modules.records.extras.ExtrasJSONB(*args, **kwargs)[source]

Bases: TypeDecorator

Custom JSON type for values (potentially) containing extra record metadata.

Converts float values to float explicitly, as larger float values might otherwise be interpreted as integers. This also works with dictionaries that do not contain extras directly, but as any nested dictionary value instead. See also Record.extras.

impl

alias of JSONB

process_result_value(value, dialect)[source]

Convert float values of any extras recursively.

class kadi.modules.records.extras.ExtraSchema(is_template=False, **kwargs)[source]

Bases: KadiSchema

Schema to represent extra record metadata.

Also does all necessary conversion and validation when deserializing. See also Record.extras.

Parameters

is_template – (optional) Flag indicating whether the schema is used within a template, in which case slightly different validation rules apply.

class kadi.modules.records.extras.ExtrasField(*args, **kwargs)[source]

Bases: JSONField

Custom convenience field to process and validate extra record metadata.

Uses ExtraSchema for the validation of the metadata.

Parameters

is_template – (optional) See ExtraSchema.

process_formdata(valuelist)[source]

Process data received over the wire from a form.

This will be called during form construction with data supplied through the formdata argument.

Parameters

valuelist – A list of strings to process.

kadi.modules.records.files.update_file(file, user=None, **kwargs)[source]

Update an existing file.

Note that this function issues a database commit or rollback.

Parameters
  • file – The file to update.

  • user – (optional) The user who triggered the update. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.db.update_object().

Returns

True if the file was updated successfully, False otherwise.

kadi.modules.records.files.delete_file(file, create_revision=True, user=None)[source]

Delete an existing file.

This will mark the file for deletion, i.e. only the file’s state will be changed. Note that this function issues one or more database commits.

Parameters
  • file – The file to delete.

  • create_revision – (optional) Flag indicating whether a revision should be created for the deletion.

  • user – (optional) The user who triggered the deletion. Defaults to the current user.

kadi.modules.records.files.remove_file(file, delete_from_db=True)[source]

Remove a file from storage and optionally from the database.

Note that this function issues one or more database commits.

Parameters
  • file – The file to remove.

  • delete_from_db – (optional) A flag indicating whether the file should be deleted from the database as well, instead of just doing a soft deletion.

kadi.modules.records.files.open_file(file, mode='rb', encoding=None)[source]

Context manager that yields an open file.

Example:

with open_file(file) as file_object:
    pass
Parameters
  • file – The file to open.

  • mode – (optional) The mode to open the file with.

  • encoding – (optional) The encoding of the file if opening it in text mode.

kadi.modules.records.files.download_file(file)[source]

Send a file to a client for downloading.

Parameters

file – The file to download.

Returns

The response object.

kadi.modules.records.files.stream_files(record)[source]

Stream all files of a record to a client as ZIP archive for downloading.

Parameters

record – The record the files belong to.

Returns

The response object.

kadi.modules.records.files.get_custom_mimetype(file, base_mimetype=None)[source]

Get a custom MIME type of a file based on its content.

Uses the kadi.plugins.spec.kadi_get_custom_mimetype() plugin hook for custom MIME types based on the file’s content.

Parameters
  • file – The file to get the MIME type of.

  • base_mimetype – (optional) The base MIME type of the file on which to base the custom MIME type.

Returns

The custom MIME type or None if no valid custom MIME type was found.

kadi.modules.records.files.get_direct_upload_type(file)[source]

Get the direct upload type of a file.

This type can be used to determine whether a file can be directly edited via a corresponding editor in the frontend. Such files must have a certain format and must not exceed a size of 10 MB.

Parameters

file – The file to get the direct upload type of.

Returns

The direct upload type or None if no suitable type can be determined.

kadi.modules.records.files.get_permitted_files(filter_term='', user=None)[source]

Convenience function to get all active record files that a user can access.

In this context having access to a file means having read permission for the record the file belongs to.

Parameters
  • filter_term – (optional) A (case insensitive) term to filter the files by their name or record identifier.

  • user – (optional) The user to check for access permissions. Defaults to the current user.

Returns

The permitted file objects as query.

kadi.modules.records.files.download_temporary_file(temporary_file)[source]

Send a temporary file to a client as attachment for download.

Parameters

temporary_file – The TemporaryFile to download.

Returns

The response object.

kadi.modules.records.files.remove_temporary_file(temporary_file)[source]

Remove a temporary file from storage and from the database.

Note that this function may issue one or more database commits.

Parameters

temporary_file – The TemporaryFile to remove.

class kadi.modules.records.forms.BaseRecordForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating or updating records.

Parameters
  • record – (optional) A record used for prefilling the form.

  • template – (optional) A record or extras template used for prefilling the form.

class kadi.modules.records.forms.NewRecordForm(*args, **kwargs)[source]

Bases: BaseRecordForm

A form for use in creating new records.

Parameters
  • record – (optional) See BaseRecordForm.

  • template – (optional) See BaseRecordForm.

  • collection – (optional) A collection used for prefilling the linked collections.

  • user – (optional) A user that will be used for checking various access permissions when prefilling the form. Defaults to the current user.

class kadi.modules.records.forms.EditRecordForm(*args, **kwargs)[source]

Bases: BaseRecordForm

A form for use in editing existing records.

Parameters

record – The record to edit, used for prefilling the form.

class kadi.modules.records.forms.BaseRecordLinkForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating or updating record links.

Parameters

record_link – (optional) A record link used for prefilling the form.

class kadi.modules.records.forms.NewRecordLinkForm(*args, **kwargs)[source]

Bases: BaseRecordLinkForm

A form for use in creating new record links.

Parameters

user – (optional) A user that will be used for checking various access permissions when prefilling the form. Defaults to the current user.

class kadi.modules.records.forms.EditRecordLinkForm(*args, **kwargs)[source]

Bases: BaseRecordLinkForm

A form for use in editing existing record links.

Parameters

record_link – The record link to edit, used for prefilling the form.

class kadi.modules.records.forms.LinkCollectionsForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in linking records with collections.

class kadi.modules.records.forms.AddRolesForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in adding user or group roles to a record.

validate(extra_validators=None)[source]

Validate the form by calling validate on each field. Returns True if validation passes.

If the form defines a validate_<fieldname> method, it is appended as an extra validator for the field’s validate.

Parameters

extra_validators – A dict mapping field names to lists of extra validator methods to run. Extra validators run after validators passed when creating the field. If the form has validate_<fieldname>, it is the last extra validator.

class kadi.modules.records.forms.ChunkForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in uploading file chunks.

Currently only used within the API.

Parameters
  • chunk_count – The total amount of chunks that the upload this chunk is part of has. Will be used to validate the chunk’s index.

  • chunk_size – The configured chunk size.

class kadi.modules.records.forms.EditFileForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in editing file metadata.

Parameters

file – A file used for prefilling the form and checking for duplicate file names.

Create a new record link.

Note that this function may issue a database commit.

Parameters
  • name – See RecordLink.name.

  • record_from – The record that is being linked from.

  • record_to – The record that is being linked to.

  • creator – (optional) The creator of the record link. Defaults to the current user.

  • term – (optional) See RecordLink.term.

Returns

The created record link.

Raises
  • KadiPermissionError – If the creator does not have the necessary permissions.

  • ValueError – When trying to link a record with itself or the link already exists.

Update an existing record link.

Note that this function may issue a database commit.

Parameters
  • record_link – The record link to upate.

  • user – (optional) The user performing the update operation. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.db.update_object().

Raises
  • KadiPermissionError – If the user performing the operation does not have the necessary permissions.

  • ValueError – When the link already exists.

Remove an existing record link.

Note that this function may issue a database commit.

Parameters
  • record_link – The record link to remove.

  • user – (optional) The user performing the remove operation. Defaults to the current user.

Raises

KadiPermissionError – If the user performing the operation does not have the necessary permissions.

Convenience function to get all links of a record that a user can access.

In this context having access to a record link means having read permission for each record the given record links to or is linked from.

Parameters
  • record_or_id – The record or ID of a record whose links should be obtained.

  • direction – (optional) A direction to limit the returned record links to. One of "out" for outgoing links from the given record, or "in" for incoming links to the given record.

  • user – (optional) The user to check for access permissions. Defaults to the current user.

Returns

The permitted record link objects as query.

kadi.modules.records.links.get_record_changes(record_link)[source]

Get all changes of linked records since the given record link was created.

The changes are based on the record and file revisions of the two linked records that were triggered after the record link was initially created.

Parameters

record_link – The record link representing the two linked records whose changes should be collected.

Returns

The changes of the linked records, consisting of the amount of new record and file revisions for each record. For the record revisions, the revision at the point of creation of the record link will also be included. The changes are returned as a dictionary in the following form:

{
    <record_from_id>: {
        "record": {
            "count": 0,
            "revision": <revision>,
        },
        "files": {
            "count": 0,
        },
    },
    <record_to_id>: {
        "record": {
            "count": 1,
            "revision": <revision>,
        },
        "files": {
            "count": 2,
        },
    },
}

Get all links of a record for visualizing them in a graph.

Used in conjunction with “D3.js” to visualize all returned nodes and links in a force directed graph.

Parameters
  • record – The record to start with.

  • depth – (optional) The link depth.

  • direction – (optional) A direction to limit the returned record links to. One of "out" for outgoing links from the start record, or "in" for incoming links to the start record.

  • user – (optional) The user to check for access permissions regarding the linked records. Defaults to the current user.

Returns

A dictionary containing the record links ("links") as well as all records involved in the links ("nodes").

class kadi.modules.records.mappings.BaseExtraMapping(meta=None, **kwargs)[source]

Bases: InnerDoc

Base search mapping for extra metadata entries of records.

class kadi.modules.records.mappings.ExtraMappingString(meta=None, **kwargs)[source]

Bases: BaseExtraMapping

Search mapping for extra string values.

class kadi.modules.records.mappings.ExtraMappingInteger(meta=None, **kwargs)[source]

Bases: BaseExtraMapping

Search mapping for extra integer values.

Uses long values for the internal representation.

class kadi.modules.records.mappings.ExtraMappingFloat(meta=None, **kwargs)[source]

Bases: BaseExtraMapping

Search mapping for extra float values.

Uses double values for the internal representation.

class kadi.modules.records.mappings.ExtraMappingBoolean(meta=None, **kwargs)[source]

Bases: BaseExtraMapping

Search mapping for extra boolean values.

class kadi.modules.records.mappings.ExtraMappingDate(meta=None, **kwargs)[source]

Bases: BaseExtraMapping

Search mapping for extra date values.

class kadi.modules.records.mappings.RecordMapping(meta=None, **kwargs)[source]

Bases: Document, MappingMixin

Search mapping for records.

See Record.

classmethod create_document(obj)[source]

Create a new document to be indexed in ElasticSearch

Parameters

obj – The object to be indexed.

Returns

The created document.

class kadi.modules.records.models.RecordVisibility[source]

Bases: StringEnum

String enum containing all possible visibility values for records.

class kadi.modules.records.models.RecordState[source]

Bases: StringEnum

String enum containing all possible state values for records.

class kadi.modules.records.models.Record(**kwargs)[source]

Bases: SimpleReprMixin, SearchableMixin, StateTimestampMixin, FavoriteMixin, TaggingMixin, Model

Model to represent records.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'identifier', 'visibility', 'state']

See SimpleReprMixin.

search_mapping = 'kadi.modules.records.mappings.RecordMapping'

See SearchableMixin.

timestamp_exclude = ['temporary_files', 'uploads']

See StateTimestampMixin.

revision = ['identifier', 'title', 'type', 'description', 'extras', 'visibility', 'state', 'license[name]', 'tags[name]', 'links_to[record_to_id, name, term]', 'linked_from[record_from_id, name, term]']

See kadi.lib.revisions.core.setup_revisions().

permissions = {'actions': [('read', l'View this record and its files.'), ('link', l'Manage links of this record with other resources.'), ('update', l'Edit this record and its files.'), ('permissions', l'Manage permissions of this record.'), ('delete', l'Delete this record.')], 'default_permissions': {'read': {'visibility': 'public'}}, 'global_actions': [('create', 'Create records.'), ('read', 'View any record and its files.'), ('link', 'Manage links of any record with other resources.'), ('update', 'Edit any record and its files.'), ('permissions', 'Manage permissions of any record.'), ('delete', 'Delete any record.')], 'roles': [('member', ['read']), ('collaborator', ['read', 'link']), ('editor', ['read', 'link', 'update']), ('admin', ['read', 'link', 'update', 'permissions', 'delete'])]}

Possible permissions and roles for records.

See kadi.lib.permissions.

check_constraints = {'description': {'length': {'max': 10000}}, 'identifier': {'length': {'max': 50}}, 'state': {'values': ['active', 'deleted', 'purged']}, 'title': {'length': {'max': 150}}, 'type': {'length': {'max': 50}}, 'visibility': {'values': ['private', 'public']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the record, auto incremented.

user_id

The ID of the user who created the record.

identifier

The unique identifier of the record.

Restricted to a maximum length of 50 characters.

title

The title of the record.

Restricted to a maximum length of 150 characters.

type

The optional type of the record.

Restricted to a maximum length of 50 characters.

description

The description of the record.

Restricted to a maximum length of 10_000 characters.

plain_description

The plain description of the record.

Equal to the normal description with the difference that most markdown is stripped out.

license_id

The optional ID of the license of the record.

extras

The extra metadata of the record.

The extras are stored in JSON format as an array of objects. Each object contains some or all of the following properties:

  • type: The type of the extra, which is always present and is one of "str", "int", "float", "bool", "date", "dict" or "list". Dictionaries and lists contain nested values, the only difference between these types is that list values have no keys.

  • key: The key of the extra as string, which needs to be unique inside each array. Except for list values, it always needs to be present.

  • value: The value of the extra depending on its type. Defaults to null for simple values and an empty array for nested types.

  • unit: A unit the value corresponds to, which is only present when the type is one of "int" or "float". Defaults to null.

  • term: An optional IRI (Internationalized Resource Identifier) as string, which can be used to specify an existing term that the extra should represent.

  • validation: An optional object containing additional validation instructions for the values of non-nested types. The following instructions are currently supported:

    • required: A boolean value indicating whether the value of the extra should be required, i.e. not null.

    • options: An array containing an enumeration of possible values that the extra can have, which all need to match the type of the extra.

visibility

The default visibility of the record.

state

The state of the record.

property active_files

Get all active files of a record as a query.

classmethod create(*, creator, identifier, title, type=None, description='', plain_description='', license=None, extras=None, visibility='private', state='active')[source]

Create a new record and add it to the database session.

Parameters
  • creator – The creator of the record.

  • identifier – The unique identifier of the record.

  • title – The title of the record.

  • type – (optional) The type of the record.

  • description – (optional) The description of the record.

  • plain_description – (optional) The plain description of the record.

  • license – (optional) The license of the record.

  • extras – (optional) The extra metadata of the record.

  • visibility – (optional) The default visibility of the record.

  • state – (optional) The state of the record.

Returns

The new Record object.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

Bases: SimpleReprMixin, SimpleTimestampMixin, Model

Model to represent directional links between records.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'name', 'record_from_id', 'record_to_id']

See SimpleReprMixin.

check_constraints = {'name': {'length': {'max': 150}}, 'term': {'length': {'max': 2048}}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the link, auto incremented.

user_id

The ID of the user who created the record link.

name

The name of the link.

Restricted to a maximum length of 150 characters.

term

An optional IRI of an existing term that the link should represent.

Restricted to a maximum length of 2_048 characters.

record_from_id

The ID of the record the link points from.

record_to_id

The ID of the record the link points to.

classmethod create(*, creator, name, record_from, record_to, term=None)[source]

Create a new record link and add it to the database session.

Parameters
  • creator – The creator of the record link.

  • name – The name of the link.

  • record_from – The record the link points from.

  • record_to – The record the link points to.

  • term – (optional) The term the record link should represent.

Returns

The new RecordLink object.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

class kadi.modules.records.models.FileState[source]

Bases: StringEnum

String enum containing all possible state values for files.

class kadi.modules.records.models.File(**kwargs)[source]

Bases: SimpleReprMixin, StateTimestampMixin, Model

Model to represent files.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'record_id', 'name', 'size', 'mimetype', 'storage_type', 'state']

See SimpleReprMixin.

timestamp_exclude = ['uploads']

See StateTimestampMixin.

revision = ['name', 'description', 'size', 'mimetype', 'checksum', 'state']

See kadi.lib.revisions.core.setup_revisions().

check_constraints = {'checksum': {'length': {'max': 256}}, 'description': {'length': {'max': 10000}}, 'mimetype': {'length': {'max': 256}}, 'name': {'length': {'max': 256}}, 'size': {'range': {'min': 0}}, 'state': {'values': ['active', 'inactive', 'deleted']}}

See kadi.lib.db.generate_check_constraints().

id

The UUID of the file.

user_id

The ID of the user who created the file.

record_id

The ID of the record the file belongs to.

name

The name of the file.

Restricted to a maximum length of 256 characters.

description

The description of the file.

Restricted to a maximum length of 10_000 characters.

size

The size of the file in bytes.

Must be a value >= 0.

checksum

MD5 checksum to verify the integrity of the file’s content.

Restricted to a maximum length of 256 characters.

mimetype

Regular MIME type of the file, possibly user-provided.

Restricted to a maximum length of 256 characters.

magic_mimetype

MIME type based on magic numbers in the file’s content.

storage_type

The storage type of the file.

state

The state of the file.

property storage

Get the storage of this file.

Setter

Set the storage of this file by passing either an instance of BaseStorage or a corresponding dictionary containing at least the "storage_type".

classmethod create(*, creator, record, name, size, description='', storage=None, checksum=None, mimetype='application/octet-stream', magic_mimetype=None, state='inactive')[source]

Create a new file and add it to the database session.

Parameters
  • creator – The creator of the file.

  • record – The record the file belongs to.

  • name – The name of the file.

  • size – The size of the file in bytes.

  • description – (optional) The description of the file.

  • (optional) (storage) – The storage of the file, see storage. If not given, defaults to the local storage.

  • checksum – (optional) The checksum of the file.

  • mimetype – (optional) The regular MIME type of the file.

  • magic_mimetype – (optional) The MIME type of the file based on its content.

  • state – (optional) The state of the file.

Returns

The new File object.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

class kadi.modules.records.models.UploadType[source]

Bases: StringEnum

String enum containing all currently used upload type values for uploads.

class kadi.modules.records.models.UploadState[source]

Bases: StringEnum

String enum containing all possible state values for uploads.

class kadi.modules.records.models.Upload(**kwargs)[source]

Bases: SimpleReprMixin, StateTimestampMixin, Model

Model to represent uploads.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'record_id', 'file_id', 'name', 'chunk_count', 'size', 'mimetype', 'storage_type', 'upload_type', 'state']

See SimpleReprMixin.

check_constraints = {'calculated_checksum': {'length': {'max': 256}}, 'checksum': {'length': {'max': 256}}, 'chunk_count': {'range': {'min': 1}}, 'description': {'length': {'max': 10000}}, 'mimetype': {'length': {'max': 256}}, 'name': {'length': {'max': 256}}, 'size': {'range': {'min': 0}}, 'state': {'values': ['active', 'inactive', 'processing']}}

See kadi.lib.db.generate_check_constraints().

id

The UUID of the upload.

user_id

The ID of the user who initiated the upload.

record_id

The ID of the record the upload belongs to.

file_id

The optional ID of a file to be overwritten the upload belongs to.

name

The name of the upload.

Restricted to a maximum length of 256 characters.

description

The description of the upload.

Restricted to a maximum length of 10_000 characters.

chunk_count

Number of chunks an upload is split into, if applicable.

Must be a value >= 1.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

size

The total size of the upload in bytes.

Must be a value >= 0.

checksum

Optional MD5 checksum that can be provided to verify the integrity of the upload.

Restricted to a maximum length of 256 characters.

calculated_checksum

Actual MD5 checksum that may be automatically calculated during the upload.

Restricted to a maximum length of 256 characters.

mimetype

MIME type of the upload, possibly user-provided.

Restricted to a maximum length of 256 characters.

state

The state of the upload.

storage_type

The storage type of the upload.

upload_type

The type of the upload.

property active_chunks

Get all active chunks of this upload as query.

property storage

Get the storage of this upload.

Setter

Set the storage of this upload by passing either an instance of BaseStorage or a corresponding dictionary containing at least the "storage_type".

classmethod create(*, creator, record, name, size, upload_type, description='', storage=None, file=None, chunk_count=None, checksum=None, calculated_checksum=None, mimetype='application/octet-stream', state='active')[source]

Create a new upload and add it to the database session.

Parameters
  • creator – The user who is initiating the upload.

  • record – The record the upload belongs to.

  • name – The name of the upload.

  • size – The total size of the upload in bytes.

  • upload_type – The upload type.

  • description – (optional) The description of the upload.

  • (optional) (storage) – The storage of the upload, see storage. If not given, defaults to the local storage.

  • file – (optional) A file the upload should replace.

  • chunk_count – (optional) The number of chunks of the upload, if applicable. If not provided explicitly it will be calculated based on the upload’s size and the chunk size configured in the application’s configuration.

  • checksum – (optional) The checksum of the upload.

  • calculated_checksum – (optional) The checksum calculated during the upload.

  • mimetype – (optional) The MIME type of the upload.

  • state – The state of the upload.

Returns

The new Upload object.

class kadi.modules.records.models.ChunkState[source]

Bases: StringEnum

String enum containing all possible state values for chunks.

class kadi.modules.records.models.Chunk(**kwargs)[source]

Bases: SimpleReprMixin, Model

Model to represent file chunks.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'upload_id', 'index', 'size', 'state']

See SimpleReprMixin.

check_constraints = {'index': {'range': {'min': 0}}, 'size': {'range': {'min': 0}}, 'state': {'values': ['active', 'inactive']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the chunk, auto incremented.

upload_id

The ID of the upload the chunk belongs to.

index

The index of the chunk inside its upload.

Must be a value >= 0.

size

The size of the chunk in bytes.

Must be a value >= 0.

state

The state of the chunk.

classmethod create(*, upload, index, size, state='inactive')[source]

Create a new chunk and add it to the database session.

Parameters
  • upload – The upload the chunk belongs to.

  • index – The index of the chunk.

  • size – The size of the chunk in bytes.

  • state – (optional) The state of the chunk.

Returns

The new Chunk object.

classmethod update_or_create(*, upload, index, size, state='inactive')[source]

Update an existing chunk or create one if it does not exist yet.

See create() for an explanation of the parameters.

Returns

The new or updated Chunk object.

class kadi.modules.records.models.TemporaryFileState[source]

Bases: StringEnum

String enum containing all possible state values for temporary files.

class kadi.modules.records.models.TemporaryFile(**kwargs)[source]

Bases: SimpleReprMixin, StateTimestampMixin, Model

Model to represent temporary files.

Currently not used anymore, as the only previous usage, packaging multiple record files for downloading them, has been replaced with zipping the files on the fly and streaming the resulting archive to the client. Will probably be removed or repurposed in the future, including related functionality.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'record_id', 'type', 'name', 'size', 'mimetype', 'state']

See SimpleReprMixin.

check_constraints = {'mimetype': {'length': {'max': 256}}, 'name': {'length': {'max': 256}}, 'size': {'range': {'min': 0}}, 'state': {'values': ['active', 'inactive']}}

See kadi.lib.db.generate_check_constraints().

id

The UUID of the temporary file.

user_id

The ID of the user who created the temporary file.

record_id

The ID of the record the temporary file belongs to.

type

The optional type of the temporary file.

Can be used to distinguish different types of temporary files for different use cases.

name

The name of the temporary file.

Restricted to a maximum length of 256 characters.

size

The size of the temporary file in bytes.

Must be a value >= 0.

mimetype

MIME type of the temporary file.

Restricted to a maximum length of 256 characters.

state

The state of the temporary file.

classmethod create(*, creator, record, name, size, type=None, mimetype=None, state='inactive')[source]

Create a new temporary file and add it to the database session.

Parameters
  • creator – The creator of the temporary file.

  • record – The record the temporary file belongs to.

  • name – The name of the temporary file.

  • size – The size of the temporary file in bytes.

  • type – (optional) The type of the temporary file.

  • mimetype – (optional) The MIME type of the temporary file. Defaults to a MIME type based on the filename or the default MIME type as defined in kadi.lib.constants.MIMETYPE_DEFAULT if it cannot be guessed.

  • state – (optional) The state of the temporary file.

Returns

The new TemporaryFile object.

kadi.modules.records.previews.get_builtin_preview_data(file)[source]

Get the preview data of a file based on all built-in preview types.

Parameters

file – The File to get the preview data of.

Returns

The preview type and preview data as tuple or None` if none of the built-in preview types are suitable.

kadi.modules.records.previews.get_preview_data(file, use_fallback=True)[source]

Get the preview data of a file.

Uses the kadi.plugins.spec.kadi_get_preview_data() plugin hook for custom preview data.

Parameters
  • file – The File to get the preview data of.

  • use_fallback – (optional) Flag indicating whether the file should be checked for textual data as fallback.

Returns

The preview type and preview data as tuple, which are always guaranteed to be JSON serializable. If either the preview type or data could not be determined, None is returned.

kadi.modules.records.previews.preview_file(file)[source]

Send a file to a client for previewing in a browser.

Note that this can potentially pose a security risk, so this should only be used for files that are safe for displaying. Uses the content-based MIME type of the file to set the content type of the response (see File.magic_mimetype).

Parameters

file – The File to send to the client.

Returns

The response object.

class kadi.modules.records.schemas.RecordSchema(previous_record=None, linked_collection=None, check_identifier=True, is_template=False, **kwargs)[source]

Bases: KadiSchema

Schema to represent records.

See Record.

Parameters
  • previous_record – (optional) A record whose identifier should be excluded when checking for duplicates while deserializing.

  • linked_collection – (optional) A collection that is linked to each record that should be serialized. Will be used to build endpoints for corresponding actions.

  • check_identifier – (optional) Flag indicating whether the identifier should be checked for duplicates.

  • is_template – (optional) Flag indicating whether the schema is used inside a template. Currently, this is only relevant for the extra metadata.

class kadi.modules.records.schemas.RecordLinkSchema(current_record=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent record links.

See RecordLink.

Parameters

current_record – (optional) The current record in whose context the record links are being serialized, in order to generate corresponding URLs to view or edit each record link. Only relevant for internal use.

class kadi.modules.records.schemas.RecordLinkRevisionSchema(current_record=None, **kwargs)[source]

Bases: RecordLinkSchema

Schema to represent record link revisions.

Additionally includes the direct serialization of the IDs of the linked records.

class kadi.modules.records.schemas.RecordRevisionSchema(previous_record=None, linked_collection=None, check_identifier=True, is_template=False, **kwargs)[source]

Bases: RecordSchema

Schema to represent record revisions.

Additionally includes the direct serialization of record links with a limited subset of attributes.

class kadi.modules.records.schemas.FileSchema(record=None, previous_file=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent files.

See File.

Parameters
  • record – (optional) A record the file to be deserialized belongs to. Will be used to check for duplicate filenames while deserializing.

  • previous_file – (optional) A file that will be excluded when checking for duplicate filenames while deserializing.

class kadi.modules.records.schemas.ChunkSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent chunks.

See Chunk.

class kadi.modules.records.schemas.UploadSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent uploads.

See Upload.

class kadi.modules.records.streaming_uploads.KadiValueTarget(*args, on_finish=None, **kwargs)[source]

Bases: ValueTarget

Extended ValueTarget for use in streaming form data parsers.

Parameters
  • *args – Additional arguments to pass to the ValueTarget.

  • on_finish – (optional) A callback that will be invoked with the parsed value once the parser is done processing the respective input.

  • **kwargs – Additional keyword arguments to pass to the ValueTarget.

to_string()[source]

Converts a value from a ValueTarget to string.

Returns

The value as string.

to_int()[source]

Converts a value from a ValueTarget to int.

Returns

The value as int.

class kadi.modules.records.streaming_uploads.StorageTarget(file_factory, *args, on_data_received=None, on_upload_finished=None, **kwargs)[source]

Bases: BaseTarget

Extended BaseTarget for use in streaming form data parsers.

For use in file uploads to directly store received file data in a storage.

Parameters
  • file_factory – A factory function that needs to return a tuple containing a storage and an open file handle.

  • *args – Additional arguments to pass to the BaseTarget.

  • on_data_received – (optional) A callback that will be invoked with each received chunk of the uploaded file.

  • on_upload_finished – (optional) A callback that will be invoked with the final size of the uploaded file.

  • **kwargs – Additional keyword arguments to pass to the BaseTarget.

class kadi.modules.records.streaming_uploads.StreamingContext(record)[source]

Bases: object

Container class used to pass information between individual parsing stages.

Parameters

record – The record the streamed upload belongs to.

kadi.modules.records.streaming_uploads.validate_via_schema(schema_cls, field, streaming_context)[source]

Validate a streamed form field via a given schema.

Parameters
  • streaming_context – The StreamingContext.

  • schema_cls – The schema class to use for validation.

  • field – The name of the field, which is used as the corresponding field in the schema and for storing the validated field value in the form held by the streaming context.

kadi.modules.records.streaming_uploads.validate_filename(streaming_context)[source]

Validate the file name sent via a form field.

Parameters

streaming_context – The StreamingContext.

kadi.modules.records.streaming_uploads.validate_filesize(streaming_context)[source]

Validate the file size sent via a form field.

Also checks if any quotas for locally stored file uploads are exceeded.

Parameters

streaming_context – The StreamingContext.

kadi.modules.records.streaming_uploads.file_factory(streaming_context)[source]

Factory to create a storage and corresponding file.

Parameters

streaming_context – The StreamingContext.

kadi.modules.records.streaming_uploads.finish_upload(streaming_context)[source]

Updates the remaining information of the file after the upload finished.

Uses complete_file_upload() to complete the file upload process.

Parameters

streaming_context – The StreamingContext.

kadi.modules.records.streaming_uploads.check_field(on_field_received, streaming_context)[source]

Check if all form fields that are required so far have been received.

If not, the request is aborted with a status code of 400.

Parameters
  • on_field_received – Function that is be called when the field is checked successfully.

  • streaming_context – The StreamingContext.

kadi.modules.records.streaming_uploads.check_required_fields_received(streaming_context)[source]

Check if all required fields are received.

Parameters

streaming_context – The StreamingContext.

Returns

An error response or None if all required fields are received.

kadi.modules.records.streaming_uploads.create_streaming_parser(headers, streaming_context)[source]

Creates a StreamingFormDataParser suitable to handle direct file uploads.

Note that during the file streaming one or more database commits are issued.

Parameters
  • headers – The HTTP-headers of the request the parser is used in.

  • streaming_context – The StreamingContext.

kadi.modules.records.tasks.start_merge_chunks_task(upload, user=None)[source]

Merge the chunks of a local file upload in a background task.

Uses kadi.modules.records.files.merge_chunks(). The created task will be kept in the database.

Note that this function issues one or more database commits.

Parameters
  • upload – The upload that the chunks belong to.

  • user – (optional) The user who started the task. Defaults to the current user.

Returns

The new task object if the task was started successfully, None otherwise.

kadi.modules.records.tasks.start_purge_record_task(record)[source]

Purge an existing record in a background task.

Uses kadi.modules.records.core.purge_record().

Parameters

record – The record to purge.

kadi.modules.records.uploads.delete_upload(upload)[source]

Delete an existing upload.

This will mark the upload for deletion, i.e. only the upload’s state will be changed.

Parameters

upload – The upload to delete.

kadi.modules.records.uploads.remove_upload(upload)[source]

Remove an upload from storage and from the database.

Note that this function issues one or more database commits.

Parameters

upload – The upload to remove.

kadi.modules.records.uploads.save_chunk(*, upload, file_object, index, size, checksum=None)[source]

Save a chunk of an upload.

Each chunk uses the UUID of the given upload (see Upload.id) combined with its index as base name in the form of "<uuid>-<index>". The complete path of the file will then be generated by prepending "STORAGE_PATH" as configured in the application’s configuration.

Note that this function issues one or more database commits.

Parameters
  • upload – The upload the chunk belongs to.

  • file_object – A file-like object representing the actual uploaded file.

  • index – The index of the chunk.

  • size – The size of the chunk in bytes.

  • checksum – (optional) The MD5 checksum of the chunk. If given it will be used to verify the checksum after saving the chunk.

Raises
kadi.modules.records.uploads.merge_chunks(upload, task=None)[source]

Merge the chunks of an upload.

Uses complete_file_upload() to complete the file upload process.

Parameters
  • upload – The upload whose chunks should be merged.

  • task – (optional) A Task object that can be provided if this function is executed in a task. In that case, the progress of the given task will be updated.

Returns

See complete_file_upload().

kadi.modules.records.uploads.complete_file_upload(upload)[source]

Performs necessary steps to complete a file upload.

Validates the upload in regards to its stored data and creates or updates the corresponding file.

Note that this function issues one or more database commits or rollbacks.

Parameters

upload – The upload to complete.

Returns

The newly created or updated file or None if it could not be created due to a file name conflict or updated due to a replaced file already being deleted.

Raises
kadi.modules.records.utils.search_records(search_query=None, page=1, per_page=10, sort='_score', visibility=None, user_ids=None, collection_ids=None, child_collections=False, record_types=None, tags=None, tag_operator='or', mimetypes=None, extra_queries=None, user=None)[source]

Search for and filter records.

Uses kadi.lib.resources.utils.get_filtered_resources() and kadi.lib.resources.utils.search_resources().

Parameters
  • search_query – (optional) See func:kadi.lib.resources.utils.search_resources.

  • page – (optional) See kadi.lib.resources.utils.search_resources().

  • per_page – (optional) See kadi.lib.resources.utils.search_resources().

  • sort – (optional) See kadi.lib.resources.utils.search_resources().

  • visibility – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • user_ids – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • collection_ids – (optional) A list of collection IDs the searched records need to belong to.

  • child_collections – (optional) Flag indicating whether the records of the children of the given collection IDs should be included.

  • record_types – (optional) A list of record types to filter the records with.

  • tags – (optional) A list of tag names to filter the records with.

  • tag_operator – (optional) The operator to filter the tags with. One of "or" or "and".

  • mimetypes – (optional) A list of MIME types to filter the records with based on their files

  • extra_queries

    (optional) A list of dictionaries to specifiy search queries within the extra metadata of records. Each query can contain a link type, a key, a type and one or multiple values depending on the type. See also Record.extras.

    Example:

    [
        {
            # The link type, one of "and" or "or". Note that the link type of
            # the first query does not actually matter and can also be left out.
            "link": "and",
            # The key of the metadata entry. Supports exact matches when
            # surrounded by double quotes.
            "key": "sample key",
            # The type of the metadata entry, one of "str", "numeric", "bool" or
            # "date". Note that there are no separate types for integer and
            # float values.
            "type": "str",
            # The string value of the metadata entry if the type is "str".
            # Supports exact matches when surrounded by double quotes.
            "str": "string",
            # The numeric value of the metadata entry if the type is "numeric".
            # Either a minimum value, a maximum value or both can be specified.
            # Specifying a unit is optional.
            "numeric": {"min": 0, "max": 1, "unit": "cm"},
            # The boolean value of the metadata entry if the type is "bool", one
            # of True, "true", False or "false".
            "bool": True,
            # The formatted date value of the metadata entry if the type is
            # "date". Either a minimum value, a maximum value or both can be
            # specified.
            "date": {
                "min": "2020-07-01T00:00:00.000Z",
                "max": "2020-07-02T00:00:00.000Z",
            },
        },
    ]
    

  • user – (optional) The user to check for any permissions regarding the searched records. Defaults to the current user.

Returns

The search results as returned by kadi.lib.resources.utils.search_resources().

kadi.modules.records.utils.clean_files(inside_task=False)[source]

Clean all expired and/or inactive files, uploads and temporary files.

Note that this function may issue one or more database commits.

Parameters

inside_task – (optional) A flag indicating whether the function is executed in a task. In that case, additional information will be logged.

Settings

class kadi.modules.settings.forms.EditProfileForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in editing a user’s profile information.

Parameters

user – The user to prepopulate the fields with.

class kadi.modules.settings.forms.ChangePasswordForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in changing a local user’s password.

class kadi.modules.settings.forms.HomeLayoutField(*args, **kwargs)[source]

Bases: JSONField

Custom field to process and validate preferences for the home page layout.

process_formdata(valuelist)[source]

Process data received over the wire from a form.

This will be called during form construction with data supplied through the formdata argument.

Parameters

valuelist – A list of strings to process.

class kadi.modules.settings.forms.CustomizationPreferencesForm(*args, **kwargs)[source]

Bases: BaseConfigForm

A form for use in setting user-specific config items related to customization.

Parameters

user – (optional) The user to pass to BaseConfigForm. Defaults to the current user.

class kadi.modules.settings.forms.NewAccessTokenForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in creating new access tokens.

kadi.modules.settings.utils.get_plugin_preferences_configs()[source]

Get all plugin preferences configurations.

Uses the kadi.plugins.spec.kadi_get_preferences_config() plugin hook to collect all potential configurations.

Returns

An ordered (by title) dictionary of plugin preferences configurations, mapping the name of each plugin (as specificed in the plugin forms) to a dictionary in the form as expected by kadi.plugins.spec.kadi_get_preferences_config().

Sysadmin

class kadi.modules.sysadmin.forms.NavFooterField(*args, **kwargs)[source]

Bases: JSONField

Custom field to process and validate navigation footer items.

Only performs some basic validation to make sure the overall structure of the items is valid.

process_formdata(valuelist)[source]

Process data received over the wire from a form.

This will be called during form construction with data supplied through the formdata argument.

Parameters

valuelist – A list of strings to process.

class kadi.modules.sysadmin.forms.CustomizationConfigForm(*args, **kwargs)[source]

Bases: BaseConfigForm

A form for use in setting global config items related to customization.

class kadi.modules.sysadmin.forms.LegalsConfigForm(*args, **kwargs)[source]

Bases: BaseConfigForm

A form for use in setting global config items related to legal notices.

class kadi.modules.sysadmin.forms.MiscConfigForm(*args, **kwargs)[source]

Bases: BaseConfigForm

A form for use in setting miscellaneous global config items.

kadi.modules.sysadmin.utils.sysadmin_required(func)[source]

Decorator to add access restrictions based on sysadmin status to an endpoint.

If the current user is not authenticated, the decorator will behave the same as Flask-Login’s login_required decorator.

kadi.modules.sysadmin.utils.save_index_image(file_object)[source]

Set an image file used on the index page as a global config item.

Uses "INDEX_IMAGE" as the key for the config item and kadi.lib.storage.local.save_as_thumbnail() to create and save a thumbnail of the given image. Any previous image will be deleted beforehand using delete_index_image(), which will also be called if the image cannot be saved.

Parameters

file_object – The image file object.

kadi.modules.sysadmin.utils.delete_index_image()[source]

Delete the image file used on the index page, including the global config item.

Uses "INDEX_IMAGE" as the key for the config item and kadi.lib.storage.local.delete_thumbnail() to delete the actual thumbnail file.

kadi.modules.sysadmin.utils.legals_acceptance_required()[source]

Check whether users need to accept the configured legal notices.

Returns

True if any of the relevant legal notices are configured and accepting them is enforced, False otherwise.

kadi.modules.sysadmin.utils.get_legals_modification_date()[source]

Get the latest modification date of the configured legal notices.

Note that only config items in the database are considered, as only these track their modification date.

Returns

The latest modification date as a datetime object as specified in Python’s datetime module or None if none of the relevant legal notices is configured in the database.

Templates

kadi.modules.templates.core.create_template(*, identifier, title, type, data, creator=None, description='', visibility='private', state='active')[source]

Create a new template.

Uses kadi.lib.resources.core.create_resource().

Parameters
Returns

See kadi.lib.resources.core.create_resource().

kadi.modules.templates.core.update_template(template, data=None, user=None, **kwargs)[source]

Update an existing template.

Uses kadi.lib.resources.core.update_resource().

Parameters
  • template – The template to update.

  • data – (optional) See Template.data.

  • user – (optional) The user who triggered the update. Defaults to the current user.

  • **kwargs – Keyword arguments that will be passed to kadi.lib.resources.update_resource().

Returns

See kadi.lib.resources.core.update_resource().

kadi.modules.templates.core.delete_template(template, user=None)[source]

Delete an existing template.

Uses kadi.lib.resources.core.delete_resource().

Parameters
  • template – The template to delete.

  • user – (optional) The user who triggered the deletion. Defaults to the current user.

kadi.modules.templates.core.restore_template(template, user=None)[source]

Restore a deleted template.

Uses kadi.lib.resources.core.restore_resource().

Parameters
  • template – The template to restore.

  • user – (optional) The user who triggered the restoration. Defaults to the current user.

kadi.modules.templates.core.purge_template(template)[source]

Purge an existing template.

Uses kadi.lib.resources.core.purge_resource().

Parameters

template – The template to purge.

kadi.modules.templates.export.get_dict_data(template, export_filter, user)[source]

Export a template as a dictionary.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.templates.export.get_json_data(template, export_filter, user)[source]

Export a template as a JSON file.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.templates.export.get_json_schema_data(template, user)[source]

Export a collection as a JSON Schema file in JSON format.

See get_export_data() for an explanation of the parameters and return value.

kadi.modules.templates.export.get_export_data(template, export_type, export_filter=None, user=None)[source]

Export a template in a given format.

Parameters
  • template – The template to export.

  • export_type – The export type, one of "json" or "json-schema".

  • export_filter

    (optional) A dictionary specifying various filters in order to exclude certain information from the returned export data, depending on the export and template type. Only usable in combination with the "json" export type.

    Example:

    {
        # Whether user information about the creator of the template should be
        # excluded.
        "user": False,
        # A dictionary specifying a filter mask of extra metadata keys to
        # exclude. The value of each key can either be an empty dictionary, to
        # exclude the whole extra including all of its potentially nested
        # values, or another dictionary with the same possibilities as in the
        # parent dictionary. For list entries, indices need to be specified as
        # strings, starting at 0.
        "extras": {"sample_key": {}, "sample_list": {"0": {}}},
    }
    

  • user – (optional) The user to check for various access permissions when generating the export data. Defaults to the current user.

Returns

The exported template data as an in-memory byte stream or None if an unknown export type was given.

class kadi.modules.templates.forms.BaseTemplateForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating or updating templates.

Parameters

template – (optional) A template used for prefilling the form, which must be of the correct type corresponding to each form class.

class kadi.modules.templates.forms.BaseRecordTemplateForm(*args, **kwargs)[source]

Bases: BaseTemplateForm

Base form class for use in creating or updating record templates.

Parameters
  • template – (optional) See BaseTemplateForm.

  • record – (optional) A record used for prefilling the template data.

  • user – (optional) A user that will be used for checking various access permissions when prefilling the form. Defaults to the current user.

class kadi.modules.templates.forms.BaseExtrasTemplateForm(*args, **kwargs)[source]

Bases: BaseTemplateForm

Base form class for use in creating or updating extras templates.

Parameters
  • template – (optional) See BaseTemplateForm.

  • record – (optional) A record used for prefilling the template data.

class kadi.modules.templates.forms.NewTemplateFormMixin(*args, template=None, user=None, **kwargs)[source]

Bases: object

Mixin class for forms used in creating new templates.

Parameters
  • template – (optional) See BaseTemplateForm.

  • user – (optional) A user that will be used for checking various access permissions when prefilling the form. Defaults to the current user.

class kadi.modules.templates.forms.NewRecordTemplateForm(*args, **kwargs)[source]

Bases: NewTemplateFormMixin, BaseRecordTemplateForm

A form for use in creating new record templates.

class kadi.modules.templates.forms.NewExtrasTemplateForm(*args, **kwargs)[source]

Bases: NewTemplateFormMixin, BaseExtrasTemplateForm

A form for use in creating new extras templates.

class kadi.modules.templates.forms.EditTemplateFormMixin(template, *args, **kwargs)[source]

Bases: object

Mixin class for forms used in editing existing templates.

Parameters

template – The template to edit, used for prefilling the form.

class kadi.modules.templates.forms.EditRecordTemplateForm(*args, **kwargs)[source]

Bases: EditTemplateFormMixin, BaseRecordTemplateForm

A form for use in updating record templates.

class kadi.modules.templates.forms.EditExtrasTemplateForm(*args, **kwargs)[source]

Bases: EditTemplateFormMixin, BaseExtrasTemplateForm

A form for use in updating extras templates.

class kadi.modules.templates.forms.AddRolesForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in adding user or group roles to a template.

validate(extra_validators=None)[source]

Validate the form by calling validate on each field. Returns True if validation passes.

If the form defines a validate_<fieldname> method, it is appended as an extra validator for the field’s validate.

Parameters

extra_validators – A dict mapping field names to lists of extra validator methods to run. Extra validators run after validators passed when creating the field. If the form has validate_<fieldname>, it is the last extra validator.

class kadi.modules.templates.mappings.TemplateMapping(meta=None, **kwargs)[source]

Bases: Document, MappingMixin

Search mapping for templates.

See Template.

class kadi.modules.templates.models.TemplateVisibility[source]

Bases: StringEnum

String enum containing all possible visibility values for templates.

class kadi.modules.templates.models.TemplateType[source]

Bases: StringEnum

String enum containing all possible type values for templates.

class kadi.modules.templates.models.TemplateState[source]

Bases: StringEnum

String enum containing all possible state values for templates.

class kadi.modules.templates.models.Template(**kwargs)[source]

Bases: SimpleReprMixin, SearchableMixin, StateTimestampMixin, FavoriteMixin, Model

Model to represent templates.

class Meta[source]

Bases: object

Container to store meta class attributes.

representation = ['id', 'user_id', 'identifier', 'visibility', 'type', 'state']

See SimpleReprMixin.

search_mapping = 'kadi.modules.templates.mappings.TemplateMapping'

See SearchableMixin.

revision = ['identifier', 'title', 'description', 'visibility', 'data', 'state']

See kadi.lib.revisions.core.setup_revisions().

permissions = {'actions': [('read', l'View this template.'), ('update', l'Edit this template.'), ('permissions', l'Manage permissions of this template.'), ('delete', l'Delete this template.')], 'default_permissions': {'read': {'visibility': 'public'}}, 'global_actions': [('create', 'Create templates.'), ('read', 'View any template.'), ('update', 'Edit any template.'), ('permissions', 'Manage permissions of any template.'), ('delete', 'Delete any template.')], 'roles': [('member', ['read']), ('editor', ['read', 'update']), ('admin', ['read', 'update', 'permissions', 'delete'])]}

Possible permissions and roles for templates.

See kadi.lib.permissions.

check_constraints = {'description': {'length': {'max': 10000}}, 'identifier': {'length': {'max': 50}}, 'state': {'values': ['active', 'deleted']}, 'title': {'length': {'max': 150}}, 'type': {'values': ['record', 'extras']}, 'visibility': {'values': ['private', 'public']}}

See kadi.lib.db.generate_check_constraints().

id

The ID of the template, auto incremented.

user_id

The ID of the user who created the template.

identifier

The unique identifier of the template.

Restricted to a maximum length of 50 characters.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

last_modified

The date and time an object was last modified.

Always uses the current UTC time as initial value. After calling register_timestamp_listener() for an inheriting mixin class, this timestamp can automatically get updated by implementing “_before_flush_timestamp” as a class method.

title

The title of the template.

Restricted to a maximum length of 150 characters.

description

The description of the template.

Restricted to a maximum length of 10_000 characters.

plain_description

The plain description of the template.

Equal to the normal description with the difference that most markdown is stripped out.

visibility

The default visibility of the template.

type

The type of the template.

data

The data of the template depending on its type.

The data is stored in JSON format. For each of the template types, it consists of:

  • "record": An object containing all relevant record properties as keys with corresponding values. See also Record.

  • "extras": An array of objects containing the extra metadata of a record. See also Record.extras.

state

The state of the template.

classmethod create(*, creator, identifier, title, type, data, description='', plain_description='', visibility='private', state='active')[source]

Create a new template and add it to the database session.

Parameters
  • creator – The creator of the template.

  • identifier – The identifier of the template.

  • title – The title of the template.

  • type – The type of the template.

  • data – The data of the template.

  • description – (optional) The description of the template.

  • plain_description – (optional) The plain description of the template.

  • visibility – (optional) The default visibility of the template.

  • state – (optional) The state of the template.

Returns

The new Template object.

class kadi.modules.templates.schemas.TemplateSchema(previous_template=None, template_type=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent generic templates.

See Template.

Parameters
  • previous_template – (optional) A template whose identifier should be excluded when checking for duplicates while deserializing.

  • template_type – (optional) The type of the template. Used when deserializing the data and it contains no type value.

kadi.modules.templates.utils.search_templates(search_query=None, page=1, per_page=10, sort='_score', visibility=None, user_ids=None, template_type=None, user=None)[source]

Search and filter for templates.

Uses kadi.lib.resources.utils.get_filtered_resources() and kadi.lib.resources.utils.search_resources().

Parameters
  • search_query – (optional) See func:kadi.lib.resources.utils.search_resources.

  • page – (optional) See kadi.lib.resources.utils.search_resources().

  • per_page – (optional) See kadi.lib.resources.utils.search_resources().

  • sort – (optional) See kadi.lib.resources.utils.search_resources().

  • visibility – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • user_ids – (optional) See func:kadi.lib.resources.utils.get_filtered_resources.

  • template_type – (optional) A type value to filter the templates with.

  • user – (optional) The user to check for any permissions regarding the searched templates. Defaults to the current user.

Returns

The search results as returned by kadi.lib.resources.utils.search_resources().