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(primary_user, secondary_user)[source]

Merge two users together.

This will migrate the ownership of all identities, resources and permissions from the secondary user to the primary user. The primary user will then be able to log in using both identities.

Parameters:
  • primary_user – The primary user to merge the secondary user into.

  • secondary_user – The secondary user to merge into the primary 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 appended to their IDs in the form of "<field_id>_<provider>". Additionally, the provider will be saved in the form as _provider.

Parameters:

provider – The name of 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.OIDCLoginForm(*args, **kwargs)[source]

Bases: KadiForm

A login form for use in OpenID Connect (OIDC).

Note that the actual provider validation needs to happen outside this form, as the form is simply a container to pass along a selected OIDC provider.

property oidc_providers

Get a list of all configured OIDC providers.

See also OIDCProvider.get_providers().

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.BaseUserForm(*args, **kwargs)[source]

Bases: KadiForm

Base form class for use in creating new users.

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

Bases: BaseUserForm

A form for use in creating new local users.

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

Bases: CreateLocalUserForm

A form for use in registering new local users.

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

Bases: BaseUserForm

A form for use in registering new OIDC users.

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

Bases: KadiForm

A form for use in mandatory email confirmation.

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.PasswordResetForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in changing the password of local users.

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

Bases: KadiForm

A form for use in mandatory acceptance of legal notices.

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', 'displayname', 'latest_identity_id', 'is_sysadmin', 'new_user_id', 'state']

See SimpleReprMixin.

timestamp_exclude = ['identities', 'records', 'record_links', 'files', 'temporary_files', 'uploads', 'collections', 'templates', 'groups', 'workflows', 'revisions', 'favorites', 'saved_searches', 'config_items', 'tasks', 'notifications', 'personal_tokens', 'oauth2_client_tokens', 'oauth2_server_clients', 'oauth2_server_tokens', 'oauth2_server_auth_codes', 'permissions', 'roles']

See BaseTimestampMixin.

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

See kadi.lib.db.generate_check_constraints().

id

The ID of the user, auto incremented.

displayname

The display name of the user.

Restricted to a maximum length of 150 characters.

orcid

The optional ORCID iD of the user.

Restricted to a maximum length of 19 characters.

about

Additional user information.

Restricted to a maximum length of 10_000 characters.

image_name

The optional identifier of a user’s profile image.

email_is_private

Flag indicating whether a user’s email addresses are private for other users.

latest_identity_id

The ID of the latest Identity the user logged in with.

is_sysadmin

Flag indicating whether a user is a sysadmin.

legals_accepted

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

new_user_id

The ID of a User the current user was merged with.

state

The state of the user.

One of "active", "inactive" or "deleted".

property is_merged

Check if a user was merged.

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(*, displayname, state='active')[source]

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

Parameters:
  • displayname – The display name of the user.

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

Returns:

The new User object.

get_user_id()[source]

Get the ID of this user.

Required for the implementation of the OAuth2 server.

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 and an email column.

class Meta[source]

Bases: object

Container to store meta class attributes.

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

See SimpleReprMixin.

common_constraints = {'email': {'length': {'max': 256}}, 'username': {'length': {'max': 50, 'min': 3}}}

Common check constraints for the minimum required identity attributes.

These are useful for identities where the underlying accounts are user-supplied via a corresponding registration form.

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.

property email_confirmed

Check if an identity’s email address is confirmed.

By default, this is assumed to be the case for all concrete identity types.

property needs_email_confirmation

Check if an identity’s email address needs to be confirmed.

By default, this is assumed to not be the case for all concrete identity types.

get_email_confirmation_token(expires_in, email=None)[source]

Create a new JSON web token used for email confirmation.

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

  • 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.

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.

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 = {'email': {'length': {'max': 256}}, 'username': {'length': {'max': 50, 'min': 3}}}

See kadi.lib.db.generate_check_constraints().

id

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

username

The unique username of the identity.

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

email

The email address of the identity.

Restricted to a maximum length of 256 characters.

password_hash

Hashed password using scrypt and a salt value of 16 chars.

email_confirmed

Indicates whether the user’s email has been confirmed.

property needs_email_confirmation

Check if an identity’s email address needs to be confirmed.

By default, this is assumed to not be the case for all concrete identity types.

classmethod create(*, user, username, email, 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.

  • 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. Note that if the current password hash does not match the hash method used by set_password(), the password hash will be updated accordingly.

Parameters:

password – The password to check.

Returns:

True if the passwords match, False otherwise.

get_password_reset_token(expires_in)[source]

Create a new JSON web token used for password resets.

Parameters:

expires_in – 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.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

id

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

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.

username

The unique username of the identity.

email

The email address of the identity.

classmethod create(*, user, username, email)[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.

Returns:

The new LDAPIdentity object.

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

Bases: Identity

Model to represent OpenID Connect (OIDC) 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', 'issuer']

See SimpleReprMixin.

identity_type = {'name': 'OpenID Connect', 'type': 'oidc'}

The type and full name of the identity.

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

See kadi.lib.db.generate_check_constraints().

id

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

username

The unique username of the identity.

email

The email address of the identity.

Restricted to a maximum length of 256 characters.

email_confirmed

Indicates whether the user’s email has been confirmed.

issuer

The OIDC issuer.

subject

The OIDC subject.

property needs_email_confirmation

Check if an identity’s email address needs to be confirmed.

By default, this is assumed to not be the case for all concrete identity types.

classmethod create(*, user, username, email, email_confirmed, issuer, subject)[source]

Create a new OIDC 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.

  • email_confirmed – Flag indicating whether the user’s email address should be marked as confirmed.

  • issuer – The OIDC issuer.

  • subject – The OIDC subject.

Returns:

The new OIDCIdentity 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.

id

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

username

The unique username of the identity.

email

The email address of the identity.

classmethod create(*, user, username, email)[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.

Returns:

The new ShibIdentity object.

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

Bases: object

Base class for authentication providers.

Note that the function init_auth_providers() needs to be called beforehand to initialize the application for use with the configured 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 authentication information.

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 information about the authenticated user.

classmethod create_identity(identity_model, *, displayname, system_role, activate_user=True, 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:
  • identity_model – The identity model to use for creating the user’s identity.

  • displayname – The display name of the user. May be truncated if it exceeds the maximum allowed length.

  • system_role – The system role of the user.

  • activate_user – (optional) Flag indicating whether the newly registered user should be activated automatically.

  • 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 as dictionary.

classmethod email_confirmation_required()[source]

Check if a provider requires email confirmation.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider requires email confirmation, False otherwise.

classmethod allow_email_change()[source]

Check if a provider supports changing emails.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

classmethod allow_password_change()[source]

Check if a provider supports changing passwords.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

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:

True if the password change was successful, False otherwise.

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

Initialize all authentication providers for use in the application.

Rebuilds the AUTH_PROVIDERS specified in the application’s configuration to use a dictionary, which will be updated with the default values for each provider, wherever applicable, and also includes the following additional class references for convenience:

  • "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.

kadi.modules.accounts.providers.core.get_auth_provider(name)[source]

Get the provider class of an authentication provider by its name.

Parameters:

name – The name of the authentication provider.

Returns:

The authentication provider class or None if no provider with the given name exists.

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 = {'activate_users': True, 'active_directory': False, 'allow_password_change': False, 'bind_pw': None, 'bind_user': None, 'ciphers': 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 if a provider supports changing passwords.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

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:

True if the password change was successful, False otherwise.

classmethod authenticate(*, username, password)[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. If the authentication was successful, the contained data is a named tuple containing the username (username), email (email) and display name (displayname) of the user.

classmethod register(*, displayname, username, email, system_role=None, apply_role_rules=True)[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:
  • displayname – The user’s display name.

  • username – The user’s unique name.

  • email – The user’s email address.

  • system_role – (optional) The user’s system role. Defaults to the configured default system role.

  • 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.

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 = {'activate_users': True, 'allow_registration': False, 'default_system_role': 'member', 'email_confirmation_required': False, 'title': l'Login with credentials'}

The default configuration values of the provider.

classmethod email_confirmation_required()[source]

Check if a provider requires email confirmation.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider requires email confirmation, False otherwise.

classmethod allow_email_change()[source]

Check if a provider supports changing emails.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

classmethod allow_password_change()[source]

Check if a provider supports changing passwords.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

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

Change a password of an existing local user.

Note that this function may issue a database commit.

See also BaseProvider.change_password().

classmethod allow_registration()[source]

Check if this provider allows registration of new users.

Returns:

True if registration is allowed, False otherwise.

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

Authenticate a local user.

Note that this function may issue a database commit.

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. If the authentication was successful, the contained data is the user’s existing LocalIdentity.

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

Register a new local user.

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

Parameters:
  • displayname – The user’s display name.

  • username – The user’s unique name.

  • email – The user’s email address.

  • password – The user’s password.

  • system_role – (optional) The user’s system role. Defaults to the configured default system role.

  • 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.

class kadi.modules.accounts.providers.oidc.OIDCProvider[source]

Bases: BaseProvider

OpenID Connect (OIDC) authentication provider.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = 'oidc'

The type of the provider.

defaults = {'activate_users': True, 'default_system_role': 'member', 'email_confirmation_required': False, 'providers': [], 'title': l'Login with OpenID Connect'}

The default configuration values of the provider.

classmethod email_confirmation_required()[source]

Check if a provider requires email confirmation.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider requires email confirmation, False otherwise.

classmethod allow_email_change()[source]

Check if a provider supports changing emails.

By default, this is assumed to not be the case for all identity providers.

Returns:

True if the provider supports changing passwords, False otherwise.

classmethod get_providers()[source]

Get all configured OIDC providers for use in a suitable selection.

Returns:

A list of dictionaries, each dictionary containing the name ("name") and title ("title") of the provider.

classmethod get_identity(*, issuer, subject)[source]

Get an existing OIDC identity based on the provided issuer and subject.

Parameters:
  • issuer – The OIDC issuer.

  • subject – The OIDC subject.

Returns:

A OIDCIdentity or None if no suitable identity exists.

classmethod initiate_login(provider)[source]

Initiate the OIDC authentication flow.

Parameters:

provider – The name of the OIDC provider.

Returns:

A response object with a corresponding redirect.

classmethod authenticate(*, provider)[source]

Authenticate an OIDC user.

Note that this requires an authorization code sent via the current request as part of the OIDC authentication flow initiated via OIDCProvider.initiate_login().

Parameters:

provider – The name of the OIDC provider.

Returns:

An instance of UserInfo. If the authentication was successful, the contained data is a named tuple containing the issuer (issuer), subject (subject), username (username), email (email), email confirmation flag (email_confirmed) and display name (displayname) of the user.

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

Register a new OIDC user.

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

Parameters:
  • displayname – The user’s display name.

  • username – The user’s unique name.

  • email – The user’s email address.

  • email_confirmed – Flag indicating whether the user’s email address should be marked as confirmed.

  • issuer – The OIDC issuer.

  • subject – The OIDC subject.

  • system_role – (optional) The user’s system role. Defaults to the configured default system role.

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

Returns:

A new OIDCIdentity object linked with a new user or None if the identity could not be created.

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

Bases: BaseProvider

Shibboleth authentication provider.

class Meta[source]

Bases: object

Container to store meta class attributes.

provider_type = 'shib'

The type of the provider.

defaults = {'activate_users': True, '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': None, '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.

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.

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 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.

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 target URL as query parameter.

Parameters:

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

Returns:

The generated local logout initiator URL.

classmethod contains_valid_idp()[source]

Check if the current 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.

Returns:

True if the identity provider is valid, False otherwise.

classmethod get_metadata()[source]

Get the metadata of the current Shibboleth session.

Returns:

An dictionary containing the entity ID of the service provider (sp_entity_id), the entity ID of the identity provider (idp_entity_id), its display name (idp_displayname) and its support contact email address (idp_support_contact).

classmethod get_required_attributes()[source]

Get all required authentication attributes of the current Shibboleth session.

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.

classmethod authenticate()[source]

Authenticate a Shibboleth user.

A successful authentication requires all necessary user attributes to be available as environment variables via a valid Shibboleth session.

Returns:

An instance of UserInfo. If the authentication was successful, the contained data is a named tuple containing the username (username), email (email) and display name (displayname) of the user.

classmethod register(*, displayname, username, email, system_role=None, apply_role_rules=True)[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:
  • displayname – The user’s display name.

  • username – The user’s unique name.

  • email – The user’s email address.

  • system_role – (optional) The user’s system role. Defaults to the configured default system role.

  • 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.

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.tasks.start_merge_users_task(primary_user, secondary_user)[source]

Merge two users together in a background task.

Uses kadi.modules.accounts.core.merge_users().

Parameters:
  • primary_user – The primary user to merge the second user into.

  • secondary_user – The secondary user to merge into the first user.

Returns:

True if the task was started successfully, False otherwise.

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

Log in a user by their identity.

Wraps Flask-Login’s login_user function but also ensures that the user’s latest identity is updated. Note that this function requires an active request context.

Parameters:

identity – The identity to log in with.

Returns:

True if the login was successful, False otherwise.

kadi.modules.accounts.utils.logout_user()[source]

Log out the current user.

Wraps Flask-Login’s logout_user function. Note that this function requires an active request context.

Returns:

The URL to redirect the user to after logging out, depending on their latest identity.

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

Save image data as a user’s profile image.

Uses kadi.lib.storage.misc.save_as_thumbnail() to store the actual image data. Note that any previous profile image will be deleted beforehand using delete_user_image(), which will also be called if the image could not be saved.

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

  • stream – The image data as a readable binary stream.

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

Delete a user’s profile image.

This is the inverse operation of save_user_image().

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 for use in HTML templates.

Parameters:

user – The user to convert.

Returns:

The converted user.

kadi.modules.accounts.utils.decode_email_confirmation_token(token)[source]

Decode the given JSON web token used for email confirmation.

Parameters:

token – The token to decode.

Returns:

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

kadi.modules.accounts.utils.decode_password_reset_token(token)[source]

Decode the given JSON web token used for password resets.

Parameters:

token – The token to decode.

Returns:

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

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 displayname and username of their latest identity.

Parameters:

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

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, record_template=None, tags=None, description='', visibility='private', state='active')[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(). See also create_collection().

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 may acquire 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_dict_data(collection, export_filter, user)[source]

Export a collection as a dictionary.

See get_export_data() for an explanation of the parameters.

Returns:

The exported collection as a dictionary.

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 an RO-Crate.

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

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

Export a collection as an RDF graph in Turtle format.

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", "rdf", "qr" or "ro-crate".

  • export_filter

    (optional) A dictionary specifying various filters to adjust the returned export data, depending on the export type. Only usable in combination with the "json", "rdf" and "ro-crate" export types. Note that the values in the example below represent the respective default values.

    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,
        # Whether to exclude all (True), outgoing ("out") or incoming ("in")
        # links of records with other records when record information is not
        # excluded.
        "links": False,
        # To specify which kind of export data of records should be included in
        # an exported RO-Crate when using the "ro-crate" export type and record
        # information is not excluded. All other filters also apply to this
        # export data, as far as applicable.
        "export_data": ["json", "rdf"],
        # Whether to return only the metadata file of an exported RO-Crate when
        # using the "ro-crate" export type.
        "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 using io.BytesIO 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 binary 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: BaseResourceForm

Base form class for use in creating or updating collections.

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

  • 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.NewCollectionForm(*args, **kwargs)[source]

Bases: BaseCollectionForm

A form for use in creating new collections.

Parameters:
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.AddCollectionRolesForm(*args, **kwargs)[source]

Bases: KadiForm

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

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

Bases: KadiForm

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]', 'record_template[id]']

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': 50000}}, '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.

title

The title of the collection.

Restricted to a maximum length of 150 characters.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

description

The description of the collection.

Restricted to a maximum length of 50_000 characters.

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.

plain_description

The plain description of the collection.

Equal to the normal description with the difference that most markdown is stripped out and whitespaces are normalized.

visibility

The default visibility of the collection.

One of "private" or "public".

record_template_id

The optional ID of a record Template associated with the collection.

If specified, the template will be used as a default when adding new records to the collection.

state

The state of the collection.

One of "active" or "deleted".

classmethod create(*, creator, identifier, title, description='', plain_description='', visibility='private', record_template=None, 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.

  • record_template – (optional) The record template 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: BaseResourceSchema

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.

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

Bases: CollectionSchema

Schema to represent collection revisions.

Additionally includes the serialization of the default record template with a limited subset of attributes.

kadi.modules.collections.utils.search_collections(search_query=None, page=1, per_page=10, sort='_score', visibility=None, explicit_permissions=False, 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:
Returns:

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

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

Recursively 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) A list of further actions to check as part of the access permissions of records.

  • 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.

Get the links of a collection for visualizing them in a graph.

Used in conjunction with D3.js to visualize the collection links in a graph.

Parameters:
  • collection – The collection to get the links of.

  • records – (optional) Whether to include the records (and their links) of the given collection.

  • children – (optional) Whether to include the children of the given collection.

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

Returns:

A dictionary containing the metadata of the given collection, optionally including its records ("records"), record links ("record_links") and its children ("children").

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(). See also create_group().

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: BaseResourceForm

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.

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 BaseTimestampMixin.

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': 50000}}, '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 50_000 characters.

plain_description

The plain description of the group.

Equal to the normal description with the difference that most markdown is stripped out and whitespaces are normalized.

image_name

The optional identifier of a group’s profile image.

visibility

The default visibility of the group.

One of "private" or "public".

state

The state of the group.

One of "active" or "deleted".

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: BaseResourceSchema

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, member_only=False, user_ids=None, user=None)[source]

Search and filter for groups.

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

Parameters:
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, specifically, as long as a user has any role inside a group, they are a member of it and should be able to at least read it. 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, stream)[source]

Save image data as a group’s profile image.

Uses kadi.lib.storage.misc.save_as_thumbnail() to store the actual image data. Note that any previous profile image will be deleted beforehand using delete_group_image(), which will also be called if the image could not be saved.

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

  • stream – The image data as a readable binary stream.

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

Delete a group’s profile image.

This is the inverse operation of save_group_image().

Parameters:

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

Main

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

Bases: KadiForm

A form for use in authorizing an OAuth2 application.

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

Bases: KadiSchema

Schema to represent the basic attributes of resources.

These resources may refer to instances of Record, Collection, Template or Group.

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

Bases: BasicResourceSchema

Schema to represent the basic attributes of deleted resources.

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_resource_searches(user=None)[source]

Get a list of serialized saved resource searches of the given user.

Parameters:

user – (optional) The user the saved searches belong to. Defaults to the current user.

Returns:

The serialized searches as a list of dictionaries, each search additionally containing its corresponding resource 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").

Records

kadi.modules.records.core.create_record(*, identifier, title, creator=None, license=None, tags=None, type=None, description='', extras=None, visibility='private', state='active')[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(). See also create_record().

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_record_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.RecordRDFGraph(record_or_records, export_filter=None, user=None)[source]

Bases: RDFGraph

Record RDF graph export class.

add_record_metadata(record)[source]

Add the metadata of a record to the RDF graph.

class kadi.modules.records.export.RecordROCrate(record_or_records, root_dir, export_filter=None, user=None)[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 name of the root directory of the RO-Crate.

  • export_filter – (optional) See get_record_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, record_export_data)[source]

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

add_record_data(record, record_export_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_record_export_data().

Returns:

A copy of the filtered extras.

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

Export a record as a dictionary.

See get_record_export_data() for an explanation of the parameters.

Returns:

The exported record as a dictionary.

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

Export a record as a JSON file.

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

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

Export a record as a PDF file.

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

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

Export a record as a QR code in PNG format.

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

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

Export a record as an RDF graph in Turtle format.

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

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

Export a record as an RO-Crate.

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

kadi.modules.records.export.get_record_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", "rdf", "pdf", "qr" or "ro-crate".

  • export_filter

    (optional) A dictionary specifying various filters to adjust the returned export data, depending on the export type. Currently only usable in combination with the "json", "rdf", "pdf" and "ro-crate" export types. Note that the values in the example below represent the respective default values.

    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, e.g. {"sample_key": {}, "sample_list": {"0": {}}}. The value
        # of each key can either be an empty dictionary, to exclude the whole
        # extra, 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": {},
        # Whether to apply the extras filter mask to any linked records as well.
        "propagate_extras": False,
        # To specify which kind of export data of records should be included in
        # an exported RO-Crate when using the "ro-crate" export type. All other
        # filters also apply to this export data, as far as applicable.
        "export_data": ["json", "rdf"],
        # Whether to return only the metadata file of an exported RO-Crate when
        # using the "ro-crate" export type.
        "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 using io.BytesIO 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 binary data on the fly instead, unless only the metadata file is exported by specifying the corresponding export filter.

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

Export the extras of a record as a JSON file.

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

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

Export the extras of a record in a given format.

Parameters:
  • record – The record whose extras should be exported.

  • export_type – The export type, currently only "json".

  • export_filter

    (optional) A dictionary specifying various filters to adjust the returned export data. Note that the values in the example below represent the respective default values.

    Example:

    {
        # A dictionary specifying a filter mask of extra metadata keys to
        # exclude, e.g. {"sample_key": {}, "sample_list": {"0": {}}}. The value
        # of each key can either be an empty dictionary, to exclude the whole
        # extra, 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": {},
        # The format of an exported JSON file when using the "json" export type.
        # This can either be the regular format used by Kadi4Mat ("standard") or
        # a simplified format, mapping keys directly to their respective values
        # ("plain").
        "format": "standard",
    }
    

Returns:

The exported extras data as an in-memory byte stream using io.BytesIO or None if an unknown export type was given.

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.

kadi.modules.records.extras.remove_extra_values(extras)[source]

Remove all values of the the given extra metadata.

Parameters:

extras – The extras for which the values are to be removed.

Returns:

A copy of the extras without values.

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

Bases: TypeDecorator

Custom JSON type for values (potentially) containing extra 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 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 metadata.

Uses ExtraSchema for its validation.

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.stream_files(record)[source]

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

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='', record_id=None, 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.

  • record_id – (optional) A record ID by which to filter the files.

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

Returns:

The permitted file objects as query.

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

Bases: JSONField

Custom field to process and validate record links.

Uses RecordLinkDataSchema for its validation.

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.

to_dict()[source]

Convert this field into a dictionary representation.

set_initial_data(data=None, record=None, user=None)[source]

Set the initial data of this field.

Parameters:
  • data – (optional) The form data to use for prefilling. Defaults to the submitted data of the current field instance.

  • record – (optional) An existing record, which can be used to set the initial data instead of the given form data.

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

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

Bases: BaseResourceForm

Base form class for use in creating or updating records.

Parameters:
  • import_data – (optional) A dictionary containing data imported from a file used for prefilling the form.

  • 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:
  • import_data – (optional) See BaseRecordForm.

  • 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.AddRecordLinksForm(*args, **kwargs)[source]

Bases: KadiForm

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: KadiForm

A form for use in editing existing record links.

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

  • record – The record in whose context the given record link is edited.

  • 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.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.

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

Bases: KadiForm

A form for use in uploading data for direct uploads.

Currently only used within the API with data sent via custom headers.

class Meta[source]

Bases: object

Container to store meta class attributes.

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

Bases: KadiForm

A form for use in uploading data for chunked uploads.

Currently only used within the API with data sent via custom headers.

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 and size.

class Meta[source]

Bases: object

Container to store meta class attributes.

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.

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

Bases: UploadChunkForm

A form for use in uploading chunks.

Currently only kept for backwards compatibility.

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

Bases: KadiForm

A form for use in directly uploading files.

Currently only kept for backwards compatibility.

class Meta[source]

Bases: object

Container to store meta class attributes.

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.

Convenience function to create multiple new record links at once.

For ease of use in view functions, as errors are silently ignored. Furthermore, only a single revision is created for each updated record, even if multiple links from/to a single record are involved.

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

Parameters:
  • record – The record the new links should be linked with.

  • record_link_data – A list of dictionaries containing record link data corresponding to the structure of RecordLinkDataSchema.

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

Returns:

The number of record links that were created successfully.

Update an existing record link.

Note that this function may issue a database commit.

Parameters:
  • record_link – The record link to update.

  • 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.

kadi.modules.records.links.get_linked_record(record_link, record)[source]

Get the record another record is linked to based on a given record link.

Record_link:

The record link.

Record:

One of the records linked via the given record link.

Returns:

A record linked to the given record via the given record link or None if the given record is not part of the given record link.

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. Note that record links containing inactive records will be filtered out.

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.

  • actions – (optional) A list of further actions to check as part of the access permissions of records.

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

Returns:

The permitted record link objects as query.

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

The collected changes are based on the record and file revisions of the two linked records that were created since the record link was last updated.

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 created immediately after updating the record link will also be included, if there has been at least one further change since then. The changes are returned as a dictionary in the following form:

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

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

Used in conjunction with D3.js to visualize the record links in a 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 ("record_links") as well as all records ("records") involved in the links.

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 = ['uploads', 'temporary_files']

See BaseTimestampMixin.

revision = ['identifier', 'title', 'type', 'description', 'extras', 'visibility', 'state', 'license[name]', 'tags[name]', 'links_to[id, record_to_id, name, term]', 'linked_from[id, 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': 50000}}, '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 50_000 characters.

plain_description

The plain description of the record.

Equal to the normal description with the difference that most markdown is stripped out and whitespaces are normalized.

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 corresponding to an enhanced key/value-pair representing the metadatum. Each object contains some or all of the following properties:

  • type: The type of the extra, which is always present and must be one of "str", "int", "float", "bool", "date", "dict" or "list". Dictionaries ("dict") and lists ("list") contain nested values of the same structure as the top level extra metadata values (i.e. an array of objects), the only difference being that "list" values have no keys. All other types contain literal values of the corresponding type:

    • "str": A (non-empty) string value.

    • "int": An integer value. Limited to values between -(2^53 - 1) and 2^53 - 1.

    • "float": A float value using double-precision (64 Bit) floating point format.

    • "bool": A (binary) boolean value, either true or false.

    • "date": A date and time string value according to ISO 8601 format.

  • key: The key of the extra as string, which needs to be unique within 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 literal values and an empty array for nested types.

  • unit: A unit the value corresponds to as string. Only usable in combination with the "int" or "float" type. Defaults to null.

  • description: An optional description of the extra as string.

  • 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, also optional, 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 (distinct) possible values that the extra can have, which all need to match the type of the extra. Only usable in combination with the "str", "int" or "float" type.

    • range: An object containing a maximum ("max") and minimum ("min") value to restrict the range of the value an extra can have. Each range value may also be null, in which case the values are only limited in one direction. Note that the range is always inclusive. Only usable in combination with the "int" or "float" type.

visibility

The default visibility of the record.

One of "private" or "public".

state

The state of the record.

One of "active", "deleted" or "purged".

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 = ['storage_type', 'uploads']

See BaseTimestampMixin.

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

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

check_constraints = {'checksum': {'length': {'max': 256}}, 'description': {'length': {'max': 50000}}, '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 50_000 characters.

size

The size of the file in bytes.

Must be a value greater than or equal to 0.

checksum

The checksum of the file.

The actual value depends on how a file was uploaded. For direct uploads, the value is an MD5 hash of the file’s content. For chunked uploads, the value is an MD5 hash created by first concatenating the MD5 hashes of all uploaded chunks (in chunk index order) and then calculating an MD5 hash of the result. The amount of chunks is then appended to the resulting value in the form of "<hash>-<chunk_count>".

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 provider type of the file.

state

The state of the file.

One of "active", "inactive" or "deleted".

property identifier

The identifier of the file.

Mainly used in correspondence with the file’s storage provider.

property storage

Get the storage provider of this file.

property has_md5_checksum

Check if the checksum of this file is an MD5 hash of it’s content.

classmethod create(*, creator, record, name, size, description='', checksum=None, mimetype='application/octet-stream', magic_mimetype=None, storage_type=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.

  • 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.

  • storage_type – (optional) The storage provider type of the file. Defaults to the STORAGE_PROVIDER specified in the application’s configuration.

  • 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', 'size', 'storage_type', 'upload_type', 'state']

See SimpleReprMixin.

timestamp_exclude = ['storage_type']

See BaseTimestampMixin.

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

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 by the upload.

name

The name of the upload.

Restricted to a maximum length of 256 characters.

size

The size of the upload in bytes.

Must be a value greater than or equal to 0.

checksum

The checksum of the upload.

Calculated automatically during the upload process. The actual value depends on the upload type and is copied to the resulting file, see File.checksum.

Restricted to a maximum length of 256 characters.

created_at

The date and time an object has been created at.

Always uses the current UTC time.

description

The optional description of the upload.

Restricted to a maximum length of 50_000 characters.

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.

mimetype

The optional MIME type of the upload.

Restricted to a maximum length of 256 characters.

chunk_count

Number of chunks an upload is split into.

For direct uploads, the chunk count is always 1.

Must be a value greater than or equal to 1.

storage_type

The storage provider type of the upload.

upload_type

The type of the upload.

One of "direct" or "chunked".

state

The state of the upload.

One of "active", "inactive" or "processing".

property identifier

The identifier of the upload.

Mainly used in correspondence with the upload’s storage provider.

property storage

Get the storage provider of this upload.

property active_chunks

Get all active chunks of this upload as query.

classmethod create(*, creator, record, name, size, description=None, mimetype=None, chunk_count=None, storage_type=None, upload_type=None, file=None, 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 size of the upload in bytes.

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

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

  • chunk_count – (optional) The chunk count of the upload. Defaults to an automatically calculated value based on kadi.lib.constants.UPLOAD_CHUNK_SIZE for chunked uploads, and to 1 for direct uploads.

  • storage_type – (optional) The storage provider type of the upload. Defaults to the STORAGE_PROVIDER specified in the application’s configuration.

  • upload_type – (optional) The upload type. Defaults to a type based on the provided size and kadi.lib.constants.UPLOAD_CHUNKED_BOUNDARY.

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

  • 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 = {'checksum': {'length': {'max': 256}}, '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 greater than or equal to 0.

size

The size of the chunk in bytes.

Must be a value greater than or equal to 0.

checksum

The checksum of the chunk.

Always corresponds to an MD5 hash of the chunk’s content, which is calculated automatically during the chunk upload process.

Restricted to a maximum length of 256 characters.

state

The state of the chunk.

One of "active" or "inactive".

property identifier

The identifier of the chunk.

Mainly used in correspondence with the storage provider of the chunk’s upload.

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, but may still be repurposed in the future.

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 greater than or equal to 0.

mimetype

MIME type of the temporary file.

Restricted to a maximum length of 256 characters.

state

The state of the temporary file.

One of "active" or "inactive".

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_BINARY 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.

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

Bases: BaseResourceSchema

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.

  • 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.RecordRevisionSchema(previous_record=None, linked_collection=None, 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.RecordImportSchema(previous_record=None, linked_collection=None, is_template=False, **kwargs)[source]

Bases: RecordSchema

Schema to represent imported record data.

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

Bases: KadiSchema

Base schema class to represent record links.

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

Bases: BaseRecordLinkSchema

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.RecordLinkDataSchema(*args, _internal=None, **kwargs)[source]

Bases: BaseRecordLinkSchema

Schema to represent the data of a generic record link in a certain direction.

Mainly useful in combination with kadi.modules.records.links.create_record_links() and within templates.

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.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.UploadSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent uploads.

See Upload.

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

Bases: KadiSchema

Schema to represent chunks.

See Chunk.

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.uploads.merge_chunk_data(). 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_data(upload, stream, *, index, size, checksum=None)[source]

Save the uploaded chunk data of a chunked upload.

Note that this function issues one or more database commits.

Parameters:
  • upload – The upload.

  • stream – The chunk data as a readable binary stream.

  • index – The index of the chunk.

  • size – The size of the chunk in bytes.

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

Returns:

The created or updated Chunk object.

Raises:
kadi.modules.records.uploads.merge_chunk_data(upload)[source]

Merge the chunk data of a chunked upload.

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

Parameters:

upload – The upload.

Returns:

The newly created or updated file or None if a conflict occured while completing the upload.

Raises:

KadiFilesizeMismatchError – If the actual final size of the upload data does not match the size provided when the upload was created.

kadi.modules.records.uploads.save_upload_data(upload, stream, checksum=None)[source]

Save the uploaded data of a direct upload.

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

Parameters:
  • upload – The upload.

  • stream – The upload data as a readable binary stream.

  • checksum – (optional) The checksum of the upload. If provided, it will be used to verify the calculated checksum after saving the upload.

Returns:

The newly created or updated file or None if a conflict occured while completing the upload.

Raises:
kadi.modules.records.utils.search_records(search_query=None, page=1, per_page=10, sort='_score', visibility=None, explicit_permissions=False, user_ids=None, collection_ids=None, child_collections=False, record_types=None, tags=None, tag_operator='or', mimetypes=None, extras=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 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 kadi.lib.resources.utils.get_filtered_resources().

  • explicit_permissions – (optional) See kadi.lib.resources.utils.get_filtered_resources().

  • user_ids – (optional) See 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

  • extras

    (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 value restrictions 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 can also be left out.
            "link": "and",
            # The key of the metadatum. Supports exact matches when surrounded
            # by double quotes.
            "key": "sample key",
            # The type of the metadatum, one of "str", "numeric" (for integer
            # and float values), "bool" or "date".
            "type": "str",
            # The string value of the metadatum if the type is "str". Supports
            # exact matches when surrounded by double quotes.
            "str": "string",
            # Restrictions about the numeric value of the metadatum if the type
            # is "numeric". Either a minimum value ("min"), a maximum value
            # ("max") or both can be specified. Note that the range is always
            # inclusive. Units ("unit") can optionally be specified as well and
            # are always matched exactly.
            "numeric": {"min": 0, "max": 1, "unit": "cm"},
            # The boolean value of the metadatum if the type is "bool", one of
            # True, "true", False or "false".
            "bool": True,
            # Restrictions about the date value of the metadatum if the type is
            # "date". Either a minimum value ("min"), a maximum value ("max") or
            # both can be specified as a formatted date string. Note that the
            # range is always inclusive.
            "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.get_user_quota(user=None)[source]

Get the total size (quota) of a user’s files and uploads.

All active files as well as active and processing uploads are taken into account. Uploads that replace files are only considered if their size is larger than the file they are replacing, in which case the size difference between the upload and the replaced file is added to the total. Note that if multiple uploads replace the same file, their combined size is taken instead.

Parameters:

user – (optional) The user to calculate the quota for. Defaults to the current user.

Returns:

The user’s quota.

kadi.modules.records.utils.parse_import_data(stream, import_type)[source]

Parse imported record data of a given format.

Parameters:
  • stream – The import data as a readable binary stream.

  • import_type – The import type, currently only "json".

Returns:

The imported record data as a dictionary. Note that none of the record attributes are guaranteed to be present.

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

Clean all expired/inactive files and uploads.

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.OrcidField(*args, **kwargs)[source]

Bases: StringField

Custom field to process and validate ORCID iDs.

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.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.ScopesField(*args, **kwargs)[source]

Bases: StringField

Custom field to process and validate access token scopes.

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.RedirectURIsField(*args, **kwargs)[source]

Bases: LFTextAreaField

Custom field to process and validate OAuth2 redirect URIs.

Parameters:

max_len – (optional) The maximum length of each invidiual URI.

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.

to_dict()[source]

Convert this field into a dictionary representation.

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.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.NewPersonalTokenForm(*args, **kwargs)[source]

Bases: KadiForm

A form for use in creating new personal tokens.

clear()[source]

Reset all relevant field data of this form to their default values.

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

Bases: KadiForm

Base form class for use in creating or updating OAuth2 applications.

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

Bases: BaseApplicationForm

A form for use in creating new OAuth2 applications.

clear()[source]

Reset all relevant field data of this form to their default values.

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

Bases: BaseApplicationForm

A form for use in editing existing OAuth2 application.

Parameters:

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

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:

A dictionary of plugin preferences configurations, mapping the name of each plugin (as specificed in the plugin forms) to a dictionary in the form 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.

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

Bases: KadiForm

A form for use in merging users.

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(stream)[source]

Save image data as the global index image config item.

Uses kadi.lib.storage.misc.save_as_thumbnail() to store the actual image data and kadi.lib.constants.SYS_CONFIG_INDEX_IMAGE as the key for the config item. Note that any previous index image will be deleted beforehand using delete_index_image(), which will also be called if the image could not be saved.

Parameters:

stream – The image data as a readable binary stream.

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

Delete the global index image config item.

This is the inverse operation of save_index_image().

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(). See also create_template().

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.

Returns:

The exported template as a dictionary.

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 template 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 to adjust the returned export data, depending on the export and template type. Only usable in combination with the "json" export type. Note that the values in the example below represent the respective default values.

    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, e.g. {"sample_key": {}, "sample_list": {"0": {}}}. The value
        # of each key can either be an empty dictionary, to exclude the whole
        # extra, 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": {},
    }
    

  • 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 using io.BytesIO or None if an unknown export type was given.

class kadi.modules.templates.forms.BaseTemplateForm(*args, **kwargs)[source]

Bases: BaseResourceForm

Base form class for use in creating or updating templates.

Parameters:
  • import_data – (optional) A dictionary containing data imported from a file used for prefilling the form.

  • template – (optional) A template used for prefilling the form, which must be of the correct type corresponding to each form class.

property template_data

Get the collected template data.

The data may optionally be validated again. If it is invalid, None should be returned instead.

class kadi.modules.templates.forms.BaseRecordTemplateForm(*args, **kwargs)[source]

Bases: BaseTemplateForm

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

Parameters:
  • import_data – (optional) See BaseTemplateForm.

  • 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.

property template_data

Get the collected template data.

The data may optionally be validated again. If it is invalid, None should be returned instead.

class kadi.modules.templates.forms.BaseExtrasTemplateForm(*args, **kwargs)[source]

Bases: BaseTemplateForm

Base form class for use in creating or updating extras templates.

Parameters:
  • import_data – (optional) See BaseTemplateForm.

  • template – (optional) See BaseTemplateForm.

  • record – (optional) A record used for prefilling the template data.

property template_data

Get the collected template data.

The data may optionally be validated again. If it is invalid, None should be returned instead.

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.

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.

timestamp_exclude = ['collections']

See BaseTimestampMixin.

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': 50000}}, '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 50_000 characters.

plain_description

The plain description of the template.

Equal to the normal description with the difference that most markdown is stripped out and whitespaces are normalized.

visibility

The default visibility of the template.

One of "private" or "public".

type

The type of the template.

One of "record" or "extras".

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. Furthermore, some additional settings can be specified:

    • "collections": An array of collection IDs that a record may directly be linked with, assuming the required permissions are met.

    • "record_links": An array of objects specifying predefined record links that a record may directly be linked with, assuming the required permissions are met. Each object must contain the link direction ("direction"), one of "out" or "in", the record ID to link with ("record"), the name of the link ("name") and optionally its term IRI ("term").

    • "roles": An array of objects specifying predefined roles that may directly be granted to users and/or groups (also referred to as subjects), assuming the required permissions are met. Each object must contain the type of subject ("subject_type"), one of "user" or "group", the ID of the subject ("subject_id") and the corresponding role name ("role").

  • "extras": An array of objects containing the extra metadata of a record. See also Record.extras.

state

The state of the template.

One of "active" or "deleted".

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.RecordTemplateDataSchema(*args, _internal=None, **kwargs)[source]

Bases: KadiSchema

Schema to represent the data of record templates.

See Template.data.

class kadi.modules.templates.schemas.TemplateSchema(previous_template=None, template_type=None, **kwargs)[source]

Bases: BaseResourceSchema

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.

class kadi.modules.templates.schemas.TemplateImportSchema(previous_template=None, template_type=None, **kwargs)[source]

Bases: TemplateSchema

Schema to represent imported template data.

kadi.modules.templates.utils.search_templates(search_query=None, page=1, per_page=10, sort='_score', visibility=None, explicit_permissions=False, 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:
Returns:

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

kadi.modules.templates.utils.parse_import_data(stream, import_type, template_type)[source]

Parse imported template data of a given format.

Parameters:
  • stream – The import data as a readable binary stream.

  • import_type – The import type, currently only "json".

  • template_type – The expected template type corresponding to the import data.

Returns:

The imported template data as a dictionary. Note that none of the template attributes are guaranteed to be present.