class IProfileRegistration(form.Schema):
    membrane_role = schema.Choice(
        title=_(u'Role for dexterity.membrane Member'),
        description=_(
            u'help_memberane_role',
            default=_(
                u'Select the role, which a user must have to create '
                u'a profile on your site. Whenever a user logs in, who does '
                u'not have the selected role, they will be redirected to '
                u'${navigational_url}/profile-registration. '
                u'Please note, the Member role will be added to the membrane '
                u'user in addition to selected the selected role.')
        ),
        required=False,
        missing_value=u'',
        vocabulary='plone.app.vocabularies.Roles'
    )
    membrane_type = schema.Choice(
        title=_(u'Select the content type, which your '
                u'dexterity.membrane.Member objects are using '),
        required=False,
        missing_value=u'',
        vocabulary='plone.app.vocabularies.PortalTypes'
    )
    
    welcome_message = schema.Text(
        title=_(u'Welcome message after successfully logging in.'),
        description=_(
            u'help_welcome_message',
            default=_(
                u'The welcome message will display below the base message, '
                u'Hi <user fullname>')
        ),
        required=False,
        missing_value=u'',
    )
    
    custom_redirect_path = schema.TextLine(
        title=_(u'Redirect non-membrane users to the path given.'),
        description=_(
            u'help_custom_redirect_path',
            default=_(
                u'If left empty, the default profile registration will be used'
            )
        ),
        required=False,
        missing_value=u'',
    )
    def __call__(self, came_from=None, is_initial_login=False):
        user = api.user.get_current()
        fullname = safe_unicode(user.getProperty('fullname'))

        registry = getUtility(IRegistry)
        membrane_role = registry.get('pas.authomatic.membrane.membrane_role',
                                     'Member')
        welcome_message = registry.get(
            'pas.authomatic.membrane.welcome_message',
            _(u'Thank you for being interested in us. '
              u'Please complete your profile using the link below'))
        custom_redirect_path = registry.get(
            'pas.authomatic.membrane.custom_redirect_path',
            "profile-registration")
        if membrane_role not in api.user.get_roles():
            api.portal.show_message(
                u'Hi {}! {}'.format(fullname, welcome_message), self.request)
            came_from = "{}/{}".format(self.context.portal_url(),
                                       custom_redirect_path.lstrip("/"))
        else:
            api.portal.show_message(
                u'Nice to see you again, {0}!'.format(fullname), self.request)
        if not came_from:
            came_from = self.context.portal_url()
        return came_from
    def __call__(self, **kwargs):
        self.identity_current_user = api.user.get_current()
        self.email = self.identity_current_user.getProperty('email')
        self.came_from = self.request.cookies.get(
            "login_came_from",
            self.request.form.get('came_from', None)
        )
        if not self.came_from:
            self.came_from = self.context.absolute_url()

        self.membrane_type, self.membrane_role, self.use_uuid_as_userid = \
            self.membrane_settings

        try:
            self.userID = self.getUserId(True)
        except AttributeError:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Please note, only non-superusers are allowed to have "
                  u"a profile on this site"),
                "error"
            )
            self.request.response.redirect(self.came_from)
            return

        self.providers = utils.getProvidersForUser(self.identity_current_user)
        self.membranes = get_brains_for_email(self.context, self.email)

        logger.info("Redirecting to {}".format(self.came_from))
        if len(self.membranes) > 0:
            self.apply_identity_membrane()
            return
        return super(MemberRegistrationForm, self).__call__(**kwargs)
class IExternalLogin(form.Schema):

    disable_external_login_url = schema.Bool(
        title=_(u'Embed external login on the default login page'),
        description=_(u'If enabled, then all external login will be embed '
                      u'on the login form page.'),
        required=True,
        default=False,
    )

    external_login_urls = schema.List(
        title=_(u'List external login urls'),
        description=_(u'If external login is not disable then the first '
                      u'external login url will be used.'),
        required=False,
        default=[u'authomatic-handler'],
        missing_value=[],
        value_type=schema.ASCIILine())
class IMemberRegistrationForm(model.Schema):

    email = Email(
        # String with validation in place looking for @, required.
        # Note that a person's email address will be their username.
        title=_(u'E-mail Address'),
        required=True,
    )

    first_name = schema.TextLine(title=_(u"First Name"), required=True)
    last_name = schema.TextLine(title=_(u"Last Name"), required=True)
    password = schema.Password(title=_(u'Password'), required=True)
    confirm_password = schema.Password(title=_(u'Confirm Password'),
                                       required=True)

    @invariant
    def password_invariant(self):
        if self.confirm_password != self.password:
            raise Invalid(_(u'Password fields do not match'))
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        if not self.identity_current_user:
            IStatusMessage(self.request).addStatusMessage(
                    _(u"Please login before continuing"),
                    "error"
                )
            contextURL = "{}/login".format(self.context.absolute_url())
            self.request.response.redirect(contextURL)
            return "redirecting"

        password = data.get("password")

        success = True
        if not self.membranes:
            first_name = data.get("first_name")
            last_name = data.get("last_name")
            self.email = data.get('email', self.email)
            name = "{}-{}".format(
                first_name,
                last_name
            )

            if not first_name or not last_name:
                fullname = self.identity_current_user.getProperty('fullname')
                if not fullname:
                    first_name = self.email.split("@")[0]
                    last_name = ""
                    name = first_name
                else:
                    fullname = fullname.split(' ')
                    first_name = fullname[0]
                    last_name = fullname[-1]
                    name = "{}-{}".format(
                        first_name,
                        last_name
                    )

            with api.env.adopt_roles('Manager'):
                context = api.content.get(path='/profiles')
                base_path = 'profiles/'
                if not context:
                    context = self.context
                    base_path = ''
                if not self.use_uuid_as_userid:
                    name = self.userID
                try:
                    user_profile = api.content.create(
                        type=self.membrane_type,
                        container=context,
                        id=name,
                        first_name=first_name,
                        last_name=last_name,
                        email=self.email,
                        password=password,
                        safe_id=True,
                        **{
                            "_plone.uuid": self.getUserId()
                        }
                    )
                    api.content.transition(
                        user_profile, transition='approve'
                    )
                    api.user.grant_roles(
                        user=self.identity_current_user,
                        roles=tuple(set(('Member', self.membrane_role)))
                    )
                    self.membranes = \
                        get_brains_for_email(self.context, self.email)
                except:
                    success = False

        if success:
            self.apply_identity_membrane()
        else:
            IStatusMessage(self.request).addStatusMessage(
                    _(u"Something went wrong"),
                    "error"
                )
class MemberRegistrationForm(AutoExtensibleForm, form.Form):
    schema = IMemberRegistrationForm
    form_name = 'registration_form'
    membranes = []

    label = _(u"Registering your profile")
    description = _(u"At the moment, you do not have a profile page. "
                    u"Please fill out the form below to create one.")

    def update(self):
        # disable Plone's editable border
        self.request.set('disable_border', True)
        # call the base class version - this is very important!
        super(MemberRegistrationForm, self).update()

    @property
    def membrane_settings(self):
        registry = getUtility(IRegistry)
        return registry.get(
            'pas.authomatic.membrane.membrane_type', 'Member'
        ), registry.get(
            'pas.authomatic.membrane.membrane_role', 'Member'
        ), registry.get(
            ('dexterity.membrane.behavior.settings.'
             'IDexterityMembraneSettings.use_uuid_as_userid'), True
        )

    @button.buttonAndHandler(_(u'Register'), name='save')
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        if not self.identity_current_user:
            IStatusMessage(self.request).addStatusMessage(
                    _(u"Please login before continuing"),
                    "error"
                )
            contextURL = "{}/login".format(self.context.absolute_url())
            self.request.response.redirect(contextURL)
            return "redirecting"

        password = data.get("password")

        success = True
        if not self.membranes:
            first_name = data.get("first_name")
            last_name = data.get("last_name")
            self.email = data.get('email', self.email)
            name = "{}-{}".format(
                first_name,
                last_name
            )

            if not first_name or not last_name:
                fullname = self.identity_current_user.getProperty('fullname')
                if not fullname:
                    first_name = self.email.split("@")[0]
                    last_name = ""
                    name = first_name
                else:
                    fullname = fullname.split(' ')
                    first_name = fullname[0]
                    last_name = fullname[-1]
                    name = "{}-{}".format(
                        first_name,
                        last_name
                    )

            with api.env.adopt_roles('Manager'):
                context = api.content.get(path='/profiles')
                base_path = 'profiles/'
                if not context:
                    context = self.context
                    base_path = ''
                if not self.use_uuid_as_userid:
                    name = self.userID
                try:
                    user_profile = api.content.create(
                        type=self.membrane_type,
                        container=context,
                        id=name,
                        first_name=first_name,
                        last_name=last_name,
                        email=self.email,
                        password=password,
                        safe_id=True,
                        **{
                            "_plone.uuid": self.getUserId()
                        }
                    )
                    api.content.transition(
                        user_profile, transition='approve'
                    )
                    api.user.grant_roles(
                        user=self.identity_current_user,
                        roles=tuple(set(('Member', self.membrane_role)))
                    )
                    self.membranes = \
                        get_brains_for_email(self.context, self.email)
                except:
                    success = False

        if success:
            self.apply_identity_membrane()
        else:
            IStatusMessage(self.request).addStatusMessage(
                    _(u"Something went wrong"),
                    "error"
                )

    @button.buttonAndHandler(_(u'Continue Browsing'), name='cancel')
    def skipRegistration(self, action):
        self.request.response.redirect(self.came_from)

    def updateActions(self):
        super(MemberRegistrationForm, self).updateActions()
        self.actions['save'].addClass("context")
        self.actions['cancel'].addClass("standalone")

    def apply_identity_membrane(self):
        user_url = ""
        base_membrane = None
        user_id = None
        for membrane in self.membranes:
            membrane_obj = membrane.getObject()
            if not base_membrane:
                user_id = membrane.getUserId
                base_membrane = membrane
                user_url = "{}/edit".format(membrane_obj.absolute_url())
            if membrane.getUserId in (self.userID, self.email):
                self.request.response.redirect(self.came_from)
                return
            annotations = IAnnotations(membrane_obj)
            stored_providers = annotations.get(ANNOTATION_KEYS["authomatic"], {})
            if self.providers is not None:
                stored_providers.update(self.providers)
                annotations[ANNOTATION_KEYS["authomatic"]] = stored_providers

        mt = api.portal.get_tool('portal_membership')
        userid = base_membrane.getUserId
        if userid in (self.userID, self.email):
            self.request.response.redirect(self.came_from)
        else:
            transaction_note('Switching ACL Identity')
            self.context.acl_users.session._setupSession(
                userid, self.context.REQUEST.RESPONSE)
            self.request.response.redirect(self.came_from)

    def secret_login(self, login_name=None):
        if login_name is not None:
            if "@" not in login_name:
                return login_name
            root, domain = login_name.split("@")
        else:
            root, domain = self.email.split("@")
        len_root = len(root)
        num_hide_root = len_root - 3
        return "{}{}@{}".format(
            root[:(3 if len_root > 2 else (len_root - 1))],
            "*" * num_hide_root,
            domain
        )

    def getUserId(self, use_uuid=False):
        if self.use_uuid_as_userid or use_uuid:
            return self.identity_current_user.getUserId()
        else:
            return self.email


    def __call__(self, **kwargs):
        self.identity_current_user = api.user.get_current()
        self.email = self.identity_current_user.getProperty('email')
        self.came_from = self.request.cookies.get(
            "login_came_from",
            self.request.form.get('came_from', None)
        )
        if not self.came_from:
            self.came_from = self.context.absolute_url()

        self.membrane_type, self.membrane_role, self.use_uuid_as_userid = \
            self.membrane_settings

        try:
            self.userID = self.getUserId(True)
        except AttributeError:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Please note, only non-superusers are allowed to have "
                  u"a profile on this site"),
                "error"
            )
            self.request.response.redirect(self.came_from)
            return

        self.providers = utils.getProvidersForUser(self.identity_current_user)
        self.membranes = get_brains_for_email(self.context, self.email)

        logger.info("Redirecting to {}".format(self.came_from))
        if len(self.membranes) > 0:
            self.apply_identity_membrane()
            return
        return super(MemberRegistrationForm, self).__call__(**kwargs)
 def password_invariant(self):
     if self.confirm_password != self.password:
         raise Invalid(_(u'Password fields do not match'))