Esempio n. 1
0
class IUserRegistrationInfo(Interface):
    """User registration info"""

    login = TextLine(
        title=USER_LOGIN_TITLE,
        description=_(
            "If you don't provide a custom login, your login will be your "
            "email address..."),
        required=False)

    @invariant
    def check_login(self):
        """Set login as mail when missing"""
        if not self.login:
            self.login = self.email

    email = TextLine(
        title=_("E-mail address"),
        description=_(
            "An email will be sent to this address to validate account "
            "activation; it will be used as your future user login"),
        required=True)

    @invariant
    def check_email(self):
        """Check for valid email"""
        if not EMAIL_REGEX.match(self.email):
            raise Invalid(_("Your email address is not valid!"))

    firstname = TextLine(title=_("First name"), required=True)

    lastname = TextLine(title=_("Last name"), required=True)

    company_name = TextLine(title=_("Company name"), required=False)

    password = EncodedPasswordField(
        title=_("Password"),
        description=_("Password must be at least 8 characters long, "
                      "and contain at least three kinds of "
                      "characters between lowercase letters, "
                      "uppercase letters, numbers and special "
                      "characters"),
        min_length=8,
        required=True)

    confirmed_password = EncodedPasswordField(title=_("Confirmed password"),
                                              required=True)

    @invariant
    def check_password(self):
        """Check for password confirmation"""
        if self.password != self.confirmed_password:
            raise Invalid(_("You didn't confirmed your password correctly!"))
        check_password(self.password)
Esempio n. 2
0
class ISiteRootRoles(IContentRoles):
    """Site root roles"""

    managers = PrincipalsSetField(
        title=_("Site managers"),
        description=_("These principals are allowed to manage the "
                      "whole application environment"),
        role_id=SYSTEM_ADMIN_ROLE,
        required=False)

    viewers = PrincipalsSetField(
        title=_("Site viewers"),
        description=_("These principals are allowed to view some "
                      "application settings, without update"),
        role_id=SYSTEM_VIEWER_ROLE,
        required=False)
Esempio n. 3
0
def notify_user_activation(user, request=None):
    """Send mail for user activation"""
    security = query_utility(ISecurityManager)
    settings = INotificationSettings(security)
    if not settings.enable_notifications:  # pylint: disable=assignment-from-no-return
        LOGGER.info("Security notifications disabled, no message sent...")
        return
    mailer = settings.get_mailer()  # pylint: disable=assignment-from-no-return
    if mailer is None:
        LOGGER.warning("Can't find mailer utility, no notification message sent!")
        return
    if request is None:
        request = check_request()
    translate = request.localizer.translate
    i18n_settings = II18n(settings)
    message_text, template_name = None, None
    if user.self_registered:
        # pylint: disable=assignment-from-no-return
        message_text = i18n_settings.query_attribute('registration_template', request=request)
        if not message_text:
            template_name = 'templates/register-message.pt'
    elif user.wait_confirmation:
        # pylint: disable=assignment-from-no-return
        message_text = i18n_settings.query_attribute('confirmation_template', request=request)
        if not message_text:
            template_name = 'templates/register-info.pt'
    site = get_parent(request.context, ISite)
    if message_text is not None:
        message_text = message_text.format(**user.to_dict())
    elif template_name is not None:
        message_text = render(template_name, request=request, value={
            'user': user,
            'site': site,
            'settings': settings
        })
    html_body = render('templates/register-body.pt', request=request, value={
        'user': user,
        'site': site,
        'settings': settings,
        'message': message_text
    })
    message = Message(
        subject=translate(_("{prefix}Please confirm registration")).format(
            prefix="{prefix} ".format(prefix=settings.subject_prefix)
            if settings.subject_prefix else ''),
        sender='{name} <{email}>'.format(name=settings.sender_name,
                                         email=settings.sender_email),
        recipients=("{firstname} {lastname} <{email}>".format(firstname=user.firstname,
                                                              lastname=user.lastname,
                                                              email=user.email),),
        html=Attachment(data=html_body,
                        content_type='text/html; charset=utf-8',
                        disposition='inline',
                        transfer_encoding='quoted-printable'),
        body=Attachment(data=html_to_text(html_body),
                        content_type='text/plain; charset=utf-8',
                        disposition='inline',
                        transfer_encoding='quoted-printable'))
    mailer.send(message)
Esempio n. 4
0
class IPlugin(IContained, IAttributeAnnotatable):
    """Basic authentication plug-in interface"""

    containers('pyams_security.interfaces.IAuthentication')

    prefix = TextLine(
        title=_("Plug-in prefix"),
        description=_(
            "This prefix is mainly used by authentication plug-ins to "
            "mark principals"))

    title = TextLine(title=_("Plug-in title"), required=False)

    enabled = Bool(title=_("Enabled plug-in?"),
                   description=_("You can choose to disable any plug-in..."),
                   required=True,
                   default=True)
Esempio n. 5
0
class IUserRegistrationConfirmationInfo(Interface):
    """User registration confirmation info"""

    activation_hash = TextLine(title=_("Activation hash"), required=True)

    login = TextLine(title=USER_LOGIN_TITLE, required=True)

    password = EncodedPasswordField(title=_("Password"),
                                    min_length=8,
                                    required=True)

    confirmed_password = EncodedPasswordField(title=_("Confirmed password"),
                                              required=True)

    @invariant
    def check_password(self):
        """Check for password confirmation"""
        if self.password != self.confirmed_password:
            raise Invalid(_("You didn't confirmed your password correctly!"))
        check_password(self.password)
Esempio n. 6
0
 def check_activation(self, hash, login, password):  # pylint: disable=redefined-builtin
     """Check is given hash is matching stored one, and activate user"""
     if self.self_registered:
         # If principal was registered by it's own, we check activation hash
         # with given login and password
         manager = get_utility(IPasswordManager, name=self.password_manager)
         password = manager.encodePassword(password, salt=self._password_salt)
         secret = hmac.new(password, login.encode(), digestmod=hashlib.sha256)
         secret.update(self.activation_secret.encode())
         activation_hash = base64.b32encode(secret.digest()).decode()
         if hash != activation_hash:
             raise Invalid(_("Can't activate profile with given params!"))
     else:
         # If principal was registered by a site manager, just check that
         # hash is matching stored one and update user password...
         if hash != self.activation_hash:
             raise Invalid(_("Can't activate profile with given params!"))
         self.password = password
     self.wait_confirmation = False
     self.activation_date = datetime.utcnow()
     self.activated = True
Esempio n. 7
0
def check_password(password):
    """Check validity of a given password"""
    nbmaj = 0
    nbmin = 0
    nbn = 0
    nbo = 0
    for car in password:
        if ord(car) in MAJS:
            nbmaj += 1
        elif ord(car) in MINS:
            nbmin += 1
        elif ord(car) in NUMS:
            nbn += 1
        else:
            nbo += 1
    if [nbmin, nbmaj, nbn, nbo].count(0) > 1:
        raise Invalid(
            _("Your password must contain at least three of these kinds of characters: "
              "lowercase letters, uppercase letters, numbers and special characters"
              ))
Esempio n. 8
0
class ILocalGroup(Interface):
    """Local principals group interface"""

    containers(IGroupsFolderPlugin)

    group_id = TextLine(
        title=_("Group ID"),
        description=_("This ID should be unique between all groups"),
        required=True,
        readonly=True)

    title = TextLine(title=_("Title"),
                     description=_("Public label of this group"),
                     required=True)

    description = Text(title=_("Description"), required=False)

    principals = PrincipalsSetField(
        title=_("Group principals"),
        description=_("IDs of principals contained in this group"),
        required=False,
        default=set())
Esempio n. 9
0
class IAdminAuthenticationPlugin(IAuthenticationPlugin):
    """Admin authentication plug-in base interface"""

    login = TextLine(title=_("Admin. login"))

    password = EncodedPasswordField(title=_("Admin. password"), required=False)
Esempio n. 10
0
def include_package(config):
    """Pyramid package include"""

    # add translations
    config.add_translation_dirs('pyams_security:locales')

    config.registry.registerUtility(factory=PlainTextPasswordManager,
                                    provided=IPasswordManager,
                                    name='Plain Text')
    config.registry.registerUtility(factory=MD5PasswordManager,
                                    provided=IPasswordManager,
                                    name='MD5')
    config.registry.registerUtility(factory=SHA1PasswordManager,
                                    provided=IPasswordManager,
                                    name='SHA1')
    config.registry.registerUtility(factory=SSHAPasswordManager,
                                    provided=IPasswordManager,
                                    name='SSHA')

    # add configuration directives
    config.add_directive('register_permission', register_permission)
    config.add_directive('register_role', register_role)
    config.add_directive('upgrade_role', upgrade_role)

    # add request methods
    config.add_request_method(get_principal, 'principal', reify=True)

    # add subscribers predicate
    config.add_subscriber_predicate('role_selector', RoleSelector)
    config.add_subscriber_predicate('plugin_selector', PluginSelector)

    # register standard permissions
    config.register_permission({
        'id': PUBLIC_PERMISSION,
        'title': _("View public contents")
    })
    config.register_permission({
        'id': VIEW_PERMISSION,
        'title': _("View protected contents")
    })
    config.register_permission({
        'id': MANAGE_PERMISSION,
        'title': _("Manage contents properties")
    })
    config.register_permission({
        'id': VIEW_SYSTEM_PERMISSION,
        'title': _("View management screens")
    })
    config.register_permission({
        'id': MANAGE_SYSTEM_PERMISSION,
        'title': _("Manage system properties")
    })
    config.register_permission({
        'id': MANAGE_SECURITY_PERMISSION,
        'title': _("Manage security")
    })
    config.register_permission({
        'id': MANAGE_ROLES_PERMISSION,
        'title': _("Manage roles")
    })

    # register standard roles
    config.register_role({
        'id': SYSTEM_ADMIN_ROLE,
        'title': _("System manager (role)"),
        'permissions': {
            PUBLIC_PERMISSION, VIEW_PERMISSION, MANAGE_PERMISSION,
            MANAGE_SYSTEM_PERMISSION, VIEW_SYSTEM_PERMISSION,
            MANAGE_SECURITY_PERMISSION, MANAGE_ROLES_PERMISSION
        },
        'managers': {ADMIN_USER_ID,
                     ROLE_ID.format(SYSTEM_ADMIN_ROLE)}
    })
    config.register_role({
        'id': SYSTEM_VIEWER_ROLE,
        'title': _("System viewer (role)"),
        'permissions':
        {PUBLIC_PERMISSION, VIEW_PERMISSION, VIEW_SYSTEM_PERMISSION},
        'managers': {ADMIN_USER_ID,
                     ROLE_ID.format(SYSTEM_ADMIN_ROLE)}
    })

    # custom classes implementations
    if not asbool(
            config.registry.settings.get(
                'pyams.security.disable-default-policy', False)):
        classImplements(BaseSiteRoot, IDefaultProtectionPolicy)
        BaseSiteRoot.__acl__ = ProtectedObjectMixin.__acl__

    config.scan()
Esempio n. 11
0
 def check_mailer(self):
     """Check mailer to enable notifications"""
     if self.enable_notifications and not self.mailer:
         raise Invalid(
             _("Notifications can't be enabled without mailer utility"))
Esempio n. 12
0
class INotificationSettings(IAttributeAnnotatable):
    """Mailer notification settings interface"""

    enable_notifications = Bool(
        title=_("Enable notifications?"),
        description=_("If 'no', mail notifications will be disabled"),
        required=True,
        default=False)

    mailer = Choice(
        title=_("Mailer utility"),
        description=_("Mail delivery utility used to send notifications"),
        required=False,
        vocabulary=MAILERS_VOCABULARY_NAME)

    @invariant
    def check_mailer(self):
        """Check mailer to enable notifications"""
        if self.enable_notifications and not self.mailer:
            raise Invalid(
                _("Notifications can't be enabled without mailer utility"))

    def get_mailer(self):
        """Return mailer utility"""

    service_name = TextLine(
        title=_("Service name"),
        description=_("Name of service as defined in registration mail "
                      "subject"),
        required=True)

    service_owner = TextLine(
        title=_("Service owner"),
        description=_("Name of the entity providing this service, which "
                      "will be visible in notifications messages"),
        required=True)

    sender_name = TextLine(
        title=_("Sender name"),
        description=_("Visible name of registration mail sender"),
        required=True)

    sender_email = TextLine(
        title=_("Sender email"),
        description=_("Email address of registration mail sender"),
        required=True)

    subject_prefix = TextLine(
        title=_("Subject prefix"),
        description=_("This prefix will be inserted into subject prefix of "
                      "each notification message"),
        required=False)

    confirmation_template = I18nHTMLField(
        title=_("Confirmation template"),
        description=
        _("This template will be used instead of default template to send "
          "notification when a user is registered by a system administrator; you can "
          "use some user properties into the message body, like: {login}, {email}, "
          "{firstname}, {lastname}, {title} or {company_name}; message activation "
          "link and footer are added automatically"),
        required=False)

    registration_template = I18nHTMLField(
        title=_("Registration template"),
        description=
        _("This template will be used instead of default template to send "
          "notificaiton when a user is auto-registered; you can use some user "
          "properties into the message body, like: {login}, {email}, {firstname}, "
          "{lastname}, {title} or {company_name}; message activation link and footer "
          "are added automatically"),
        required=False)

    signature = Text(title=_("Email signature"),
                     description=_("Text displayed in email footer"),
                     required=False)
Esempio n. 13
0
class UnknownPrincipal:
    """Unknown principal info"""

    id = '__none__'  # pylint: disable=invalid-name
    title = _("< unknown principal >")
Esempio n. 14
0
class IProtectedObject(IAttributeAnnotatable):
    """Protected object interface

    This is the only interface used by authorization policy.
    So you are free to implement custom protection mechanisms.
    """

    inherit_parent_security = Bool(
        title=_("Inherit parent security?"),
        description=_("Get access control entries (ACE) inherited "
                      "from parent levels"),
        required=True,
        default=True)

    everyone_denied = PermissionsSetField(
        title=_("Public denied permissions"),
        description=_("These permissions will be denied to all "
                      "users. Denied permissions take "
                      "precedence over granted ones."),
        required=False)

    everyone_granted = PermissionsSetField(
        title=_("Public granted permissions"),
        description=_("These permissions will be granted to "
                      "all users"),
        required=False)

    authenticated_denied = PermissionsSetField(
        title=_("Authenticated denied permissions"),
        description=_("These permissions will be denied "
                      "to authenticated users. Denied "
                      "permissions take precedence over "
                      "granted ones."),
        required=False)

    authenticated_granted = PermissionsSetField(
        title=_("Authenticated granted permissions"),
        description=_("These permissions will be granted "
                      "to authenticated users"),
        required=False)

    inherit_parent_roles = Bool(
        title=_("Inherit parent roles?"),
        description=_("Get roles granted on parent levels"),
        required=True,
        default=True)

    def __acl__(self):
        """Object ACL"""

    def get_principals(self, role_id):
        """Get ID of principals who were granted given role

        May return an empty set when empty
        """

    def get_roles(self, principal_id):
        """Get ID of roles granted to given principal

        May return an empty set when empty
        """

    def get_roles_ids(self, principal_id):
        """Get ID of roles granted to given principal"""

    def get_permissions(self, principal_id):
        """Get ID of permissions granted to given principal"""

    def get_everyone_denied(self):
        """Get denied permissions for everyone, including inherited ones"""

    def get_everyone_granted(self):
        """Get granted permissions for everyone, including inherited ones"""

    def get_authenticated_denied(self):
        """Get denied permissions for authenticated, including inherited ones"""

    def get_authenticated_granted(self):
        """Get granted permissions for authenticated, including inherited ones"""

    def get_granted_roles(self):
        """Get all roles, including inherited ones"""
Esempio n. 15
0
class ISecurityManager(IContainer, IDirectoryPluginInfo,
                       IAttributeAnnotatable):
    """Authentication and principals management utility"""

    contains(IPlugin)

    open_registration = Bool(
        title=_("Enable free registration?"),
        description=_("If 'Yes', any use will be able to create a new user "
                      "account"),
        required=False,
        default=False)

    users_folder = Choice(
        title=_("Users folder"),
        description=_(
            "Name of users folder used to store registered principals"),
        required=False,
        vocabulary=USERS_FOLDERS_VOCABULARY_NAME)

    @invariant
    def check_users_folder(self):
        """Check for open registration"""
        if self.open_registration and not self.users_folder:
            raise Invalid(
                _("You can't activate open registration without selecting a users "
                  "folder"))

    credentials_plugins_names = Tuple(
        title=_("Credentials plug-ins"),
        description=_("These plug-ins are used to extract "
                      "credentials from an incoming request (the "
                      "Pyramid session plug-in is built-in!). "
                      "They can rely on authentication plug-ins "
                      "to ensure that provided credentials are "
                      "valid..."),
        value_type=TextLine(),
        readonly=True)

    authentication_plugins_names = Tuple(
        title=_("Authentication plug-ins"),
        description=_("The plug-ins can be used to check "
                      "extracted credentials against a local or "
                      "remote users database"),
        value_type=TextLine(),
        default=())

    directory_plugins_names = Tuple(
        title=_("Directory plug-ins"),
        description=_("The plug-in can be used to extract principals "
                      "information"),
        value_type=TextLine(),
        default=())

    def get_plugin(self, name):
        """Get plug-in matching given name"""

    credentials_plugins = Attribute(
        "Iterator on registered credentials plug-ins")

    authentication_plugins = Attribute(
        "Iterator on registered and local authentication plug-ins")

    directory_plugins = Attribute(
        "Iterator on registered and local directory plug-ins")

    groups_directory_plugins = Attribute(
        "Iterator on registered and local groups plug-ins")

    def effective_principals(self, principal_id, request=None, context=None):
        """Get effective principals of provided principal ID"""

    def get_principal(self, principal_id, info=True):
        """Principal lookup for provided principal ID"""

    def get_all_principals(self, principal_id):
        """Get all principals of given principal ID"""
Esempio n. 16
0
 def check_users_folder(self):
     """Check for open registration"""
     if self.open_registration and not self.users_folder:
         raise Invalid(
             _("You can't activate open registration without selecting a users "
               "folder"))
Esempio n. 17
0
#

SYSTEM_PREFIX = 'system'

ADMIN_USER_NAME = '__system__'
ADMIN_USER_LOGIN = '******'
ADMIN_USER_ID = '{0}:{1}'.format(SYSTEM_PREFIX, ADMIN_USER_LOGIN)

INTERNAL_USER_NAME = '__internal__'
INTERNAL_USER_LOGIN = '******'
INTERNAL_USER_ID = '{0}:{1}'.format(SYSTEM_PREFIX, INTERNAL_USER_LOGIN)

SYSTEM_ADMIN_ROLE = 'system.Manager'
SYSTEM_VIEWER_ROLE = 'system.Viewer'

USER_LOGIN_TITLE = _("User login")

#
# Roles events interfaces
#


class IRoleEvent(IObjectEvent):
    """Base role event interface"""

    role_id = Attribute("Modified role ID")

    principal_id = Attribute("Modified principal ID")


@implementer(IRoleEvent)
Esempio n. 18
0
 def check_activated_user(self):
     """Check for missing password of activated user"""
     if not self.password and not self.wait_confirmation:
         raise Invalid(
             _("You can't activate an account without setting a password!"))
Esempio n. 19
0
 def check_email(self):
     """Check for invalid email address"""
     if not EMAIL_REGEX.match(self.email):
         raise Invalid(_("Given email address is not valid!"))
Esempio n. 20
0
class ILocalUser(IAttributeAnnotatable):
    """Local user interface"""

    containers(IUsersFolderPlugin)

    login = TextLine(title=USER_LOGIN_TITLE, required=True, readonly=True)

    @invariant
    def check_login(self):
        """Set login as mail when missing"""
        if not self.login:
            self.login = self.email

    email = TextLine(title=_("User email address"), required=True)

    @invariant
    def check_email(self):
        """Check for invalid email address"""
        if not EMAIL_REGEX.match(self.email):
            raise Invalid(_("Given email address is not valid!"))

    firstname = TextLine(title=_("First name"), required=True)

    lastname = TextLine(title=_("Last name"), required=True)

    title = Attribute("User full name")

    company_name = TextLine(title=_("Company name"), required=False)

    password_manager = Choice(
        title=_("Password manager name"),
        description=_("Utility used to encrypt user password"),
        required=True,
        vocabulary=PASSWORD_MANAGERS_VOCABULARY_NAME,
        default='PBKDF2')

    password = EncodedPasswordField(title=_("Password"),
                                    min_length=8,
                                    required=False)

    confirmed_password = EncodedPasswordField(title=_("Confirmed password"),
                                              min_length=8,
                                              required=False)

    wait_confirmation = Bool(
        title=_("Wait confirmation?"),
        description=_("If 'no', user will be activated immediately without "
                      "waiting email confirmation"),
        required=True,
        default=True)

    @invariant
    def check_activated_user(self):
        """Check for missing password of activated user"""
        if not self.password and not self.wait_confirmation:
            raise Invalid(
                _("You can't activate an account without setting a password!"))

    self_registered = Bool(title=_("Self-registered profile?"),
                           required=True,
                           default=True,
                           readonly=True)

    activation_secret = TextLine(
        title=_("Activation secret key"),
        description=_("This private secret is used to create and check "
                      "activation hash"))

    activation_hash = TextLine(
        title=_("Activation hash"),
        description=_("This hash is provided into activation message URL. "
                      "Activation hash is missing for local users which "
                      "were registered without waiting their "
                      "confirmation."))

    activated = Bool(title=_("Activated"), required=True, default=False)

    activation_date = Datetime(title=_("Activation date"), required=False)

    def check_password(self, password):
        """Check user password against provided one"""

    def generate_secret(self, notify=True, request=None):
        """Generate secret key of this profile"""

    def refresh_secret(self, notify=True, request=None):
        """Refresh secret key of this profile"""

    def check_activation(self, hash, login, password):  # pylint: disable=redefined-builtin
        """Check activation for given settings"""

    def to_dict(self):
        """Get main user properties as mapping"""
Esempio n. 21
0
 def check_password(self):
     """Check for password confirmation"""
     if self.password != self.confirmed_password:
         raise Invalid(_("You didn't confirmed your password correctly!"))
     check_password(self.password)