:py:mod:`core.modules.user` =========================== .. py:module:: core.modules.user Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: core.modules.user.Status core.modules.user.UserSkel core.modules.user.UserAuthentication core.modules.user.UserPrimaryAuthentication core.modules.user.UserPassword core.modules.user.GoogleAccount core.modules.user.UserSecondFactorAuthentication core.modules.user.TimeBasedOTP core.modules.user.AuthenticatorOTP core.modules.user.User Functions ~~~~~~~~~ .. autoapisummary:: core.modules.user.createNewUserIfNotExists core.modules.user.__getattr__ .. py:class:: Status Bases: :py:obj:`enum.Enum` Status enum for a user Has backwards compatibility to be comparable with non-enum values. Will be removed with viur-core 4.0.0 .. py:attribute:: UNSET :value: 0 .. py:attribute:: WAITING_FOR_EMAIL_VERIFICATION :value: 1 .. py:attribute:: WAITING_FOR_ADMIN_VERIFICATION :value: 2 .. py:attribute:: DISABLED :value: 5 .. py:attribute:: ACTIVE :value: 10 .. py:method:: __eq__(other) Return self==value. .. py:method:: __lt__(other) Return self 0, it returns the index for which the OTP value obtained by pyotp.at(for_time=time.time(), counter_offset=index) equals the current value shown on the hardware token generator. This can be used to store the time drift of a given token generator. :param otp: the OTP token to check against :param secret: The OTP secret :param algorithm: digest function to use in the HMAC (expected to be sha1 or sha256) :param interval: the time interval in seconds for OTP. This defaults to 60 (old OTP c200 Generators). In pyotp, default is 30! :param timedrift: The known timedrift (old index) of the hardware OTP generator :param for_time: Time to check OTP at (defaults to now) :param valid_window: extends the validity to this many counter ticks before and after the current one :returns: The index where verification succeeded, None otherwise .. py:method:: updateTimeDrift(user_key, idx) Updates the clock-drift value. The value is only changed in 1/10 steps, so that a late submit by an user doesn't skew it out of bounds. Maximum change per call is 0.3 minutes. :param user_key: For which user should the update occour :param idx: How many steps before/behind was that token :return: .. py:class:: AuthenticatorOTP(moduleName, modulePath, _user_module) Bases: :py:obj:`UserSecondFactorAuthentication` This class handles the second factor for apps like authy and so on .. py:attribute:: METHOD_NAME :value: 'X-VIUR-2FACTOR-AuthenticatorOTP' .. py:attribute:: second_factor_add_template :value: 'user_secondfactor_add' Template to configure (add) a new TOPT .. py:attribute:: ACTION_NAME :value: 'authenticator_otp' Action name provided for *otp_template* on login .. py:attribute:: NAME :value: 'Authenticator App' .. py:method:: add(otp=None) We try to read the otp_app_secret form the current session. When this fails we generate a new one and store it in the session. If an otp and a skey are provided we are validate the skey and the otp. If both is successfully we store the otp_app_secret from the session in the user entry. .. py:method:: can_handle(skel) We can only handle the second factor if we have stored an otp_app_secret before. .. py:method:: patch_user_skel(skel_cls) :classmethod: Modifies the UserSkel to be equipped by bones required by Authenticator App .. py:method:: set_otp_app_secret(otp_app_secret=None) :classmethod: Write a new OTP Token in the current user entry. .. py:method:: generate_otp_app_secret_uri(otp_app_secret) :classmethod: :return an otp uri like otpauth://totp/Example:alice@google.com?secret=ABCDEFGH1234&issuer=Example .. py:method:: generate_otp_app_secret() :classmethod: Generate a new OTP Secret :return an otp .. py:method:: verify_otp(otp, secret) :classmethod: .. py:method:: start() .. py:method:: authenticator_otp(**kwargs) We verify the otp here with the secret we stored before. .. py:class:: User(moduleName, modulePath) Bases: :py:obj:`viur.core.prototypes.list.List` List module prototype. The list module prototype handles datasets in a flat list. It can be extended to filters and views to provide various use-cases. It is undoubtedly the most frequently used prototype in any ViUR project. .. py:attribute:: kindName :value: 'user' .. py:attribute:: addTemplate :value: 'user_add' .. py:attribute:: addSuccessTemplate :value: 'user_add_success' .. py:attribute:: lostPasswordTemplate :value: 'user_lostpassword' .. py:attribute:: verifyEmailAddressMail :value: 'user_verify_address' .. py:attribute:: passwordRecoveryMail :value: 'user_password_recovery' .. py:attribute:: authenticationProviders :type: viur.core.decorators.t.Iterable[UserPrimaryAuthentication] Specifies primary authentication providers that are made available as sub-modules under `user/auth_`. They might require customization or configuration. .. py:attribute:: secondFactorProviders :type: viur.core.decorators.t.Iterable[UserSecondFactorAuthentication] :value: () Specifies secondary authentication providers that are made available as sub-modules under `user/f2_`. They might require customization or configuration, which is determined during the login-process depending on the user that wants to login. .. py:attribute:: validAuthenticationMethods Specifies the possible combinations of primary- and secondary factor login methos. GoogleLogin defaults to no second factor, as the Google Account can be secured by a secondary factor. AuthenticatorOTP and TimeBasedOTP are only handled when there is a user-dependent configuration available. .. py:attribute:: msg_missing_second_factor :value: 'Second factor required but not configured for this user.' .. py:attribute:: secondFactorTimeWindow .. py:attribute:: default_order :value: 'name.idx' .. py:attribute:: adminInfo .. py:attribute:: roles .. py:method:: get_role_defaults(role) Returns a set of default access rights for a given role. .. py:method:: addSkel() Retrieve a new instance of a :class:`viur.core.skeleton.Skeleton` that is used by the application for adding an entry to the list. The default is a Skeleton instance returned by :func:`~baseSkel`. Like in :func:`viewSkel`, the skeleton can be post-processed. Bones that are being removed aren't visible and cannot be set, but it's also possible to just set a bone to readOnly (revealing it's value to the user, but preventing any modification. It's possible to pre-set values on that skeleton (and if that bone is readOnly, enforcing these values). .. seealso:: :func:`viewSkel`, :func:`editSkel`, :func:`~baseSkel` :return: Returns a Skeleton instance for adding an entry. .. py:method:: editSkel(*args, **kwargs) Retrieve a new instance of a :class:`viur.core.skeleton.Skeleton` that is used by the application for editing an existing entry from the list. The default is a Skeleton instance returned by :func:`~baseSkel`. Like in :func:`viewSkel`, the skeleton can be post-processed. Bones that are being removed aren't visible and cannot be set, but it's also possible to just set a bone to readOnly (revealing it's value to the user, but preventing any modification. .. seealso:: :func:`viewSkel`, :func:`editSkel`, :func:`~baseSkel` :return: Returns a Skeleton instance for editing an entry. .. py:method:: secondFactorProviderByClass(cls) .. py:method:: getCurrentUser() .. py:method:: continueAuthenticationFlow(provider, user_key) Continue authentication flow when primary authentication succeeded. .. py:method:: secondFactorSucceeded(provider, user_key) Continue authentication flow when secondary authentication succeeded. .. py:method:: authenticateUser(key, **kwargs) Performs Log-In for the current session and the given user key. This resets the current session: All fields not explicitly marked as persistent by conf.user.session_persistent_fields_on_login are gone afterwards. :param key: The (DB-)Key of the user we shall authenticate .. py:method:: logout(*args, **kwargs) Implements the logout action. It also terminates the current session (all keys not listed in viur.session_persistent_fields_on_logout will be lost). .. py:method:: login(*args, **kwargs) .. py:method:: onLogin(skel) Hook to be called on user login. .. py:method:: onLogout(skel) Hook to be called on user logout. .. py:method:: view(key = 'self', *args, **kwargs) Allow a special key "self" to reference the current user. By default, any authenticated user can view its own user entry, to obtain access rights and any specific user information. This behavior is defined in the customized `canView` function, which is overwritten by the User-module. The rendered skeleton can be modified or restriced by specifying a customized view-skeleton. .. py:method:: canView(skel) Checks if the current user can view the given entry. Should be identical to what's allowed by listFilter. By default, `meth:listFilter` is used to determine what's allowed and whats not; but this method can be overridden for performance improvements (to eliminate that additional database access). :param skel: The entry we check for :return: True if the current session is authorized to view that entry, False otherwise .. py:method:: edit(key = 'self', *args, **kwargs) Allow a special key "self" to reference the current user. This modification will only allow to use "self" as a key; The specific access right to let the user edit itself must still be customized. The rendered and editable skeleton can be modified or restriced by specifying a customized edit-skeleton. .. py:method:: getAuthMethods(*args, **kwargs) Inform tools like Viur-Admin which authentication to use .. py:method:: trigger(action, key) .. py:method:: onEdited(skel) Hook function that is called after modifying an entry. It should be overridden for a module-specific behavior. The default is writing a log entry. :param skel: The Skeleton that has been modified. .. seealso:: :func:`edit`, :func:`onEdit` .. py:method:: onDeleted(skel) Hook function that is called after deleting an entry. It should be overridden for a module-specific behavior. The default is writing a log entry. :param skel: The Skeleton that has been deleted. .. seealso:: :func:`delete`, :func:`onDelete` .. py:function:: createNewUserIfNotExists() Create a new Admin user, if the userDB is empty .. py:function:: __getattr__(attr)