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)
示例#2
0
    def render(self):

        sfconn = getUtility(ISalesforceUtility).get_connection()

        soql = "select Id, Email from Contact where Online_Fundraising_User__c = True"

        # FIXME: Handle paginated query in case the number of contacts is > 200
        res = sfconn.query(soql)

        num_person_updated = 0
        num_member_updated = 0
        num_skipped = 0

        mtool = getToolByName(self.context, 'portal_membership')

        for contact in res['records']:
            person_res = get_brains_for_email(self.context, contact['Email'])
            if not person_res:
                num_skipped += 1
                continue
            person = person_res[0].getObject()
            if person.sf_object_id != contact['Id']:
                num_person_updated += 1
                person.sf_object_id = contact['Id']
                person.reindexObject(idxs=['sf_object_id'])

            member = mtool.getMemberById(person.email)
            if not member:
                continue
            if member.getProperty('sf_object_id') != person.sf_object_id:
                num_member_updated = 0
                member.setMemberProperties(
                    {'sf_object_id': person.sf_object_id})

        return "Updated %s Person objects, %s Member objects, and skipped %s non-existing Contacts" % (num_person_updated, num_member_updated, num_skipped)
    def render(self):
        
        sfconn = getUtility(ISalesforceUtility).get_connection()
    
        soql = "select Id, Email from Contact where Online_Fundraising_User__c = True"
      
        # FIXME: Handle paginated query in case the number of contacts is > 200 
        res = sfconn.query(soql)

        num_person_updated = 0
        num_member_updated = 0
        num_skipped = 0

        mtool = getToolByName(self.context, 'portal_membership')

        for contact in res['records']:
            person_res = get_brains_for_email(self.context, contact['Email'])
            if not person_res:
                num_skipped += 1
                continue
            person = person_res[0].getObject()
            if person.sf_object_id != contact['Id']:
                num_person_updated += 1
                person.sf_object_id = contact['Id']
                person.reindexObject(idxs=['sf_object_id'])
           
            member = mtool.getMemberById(person.email)
            if not member:
                continue
            if member.getProperty('sf_object_id') != person.sf_object_id:
                num_member_updated = 0
                member.setMemberProperties({'sf_object_id': person.sf_object_id})

        return "Updated %s Person objects, %s Member objects, and skipped %s non-existing Contacts" % (num_person_updated, num_member_updated, num_skipped)
示例#4
0
    def handleOk(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        email = data['email']

        site = getSite()
        membership = getToolByName(site, 'portal_membership')
        member = membership.getMemberById(email)

        # Like mailPassword() in CMFPlone.RegistrationTool, render
        # and send the message ourselves to avoid tripping over security.
        reset_tool = getToolByName(site, 'portal_password_reset')
        reset = reset_tool.requestReset(member.getId())
        encoding = site.getProperty('email_charset', 'utf-8')
        mail_text = site.mail_password_template(site,
                                                self.request,
                                                member=member,
                                                reset=reset,
                                                password=member.getPassword(),
                                                charset=encoding)
        # The mail headers are not properly encoded, so we need to extract
        # them and let MailHost manage the encoding.
        if isinstance(mail_text, unicode):
            mail_text = mail_text.encode(encoding)
        message_obj = message_from_string(mail_text.strip())
        subject = message_obj['Subject']
        m_to = message_obj['To']
        m_from = message_obj['From']
        host = getToolByName(site, 'MailHost')
        host.send(mail_text,
                  m_to,
                  m_from,
                  subject=subject,
                  charset=encoding,
                  immediate=False)

        brains = get_brains_for_email(site, email)
        if brains is not None:
            person = brains[0].getObject()
            # person.registered must be set in order for the user
            # to log in with a password.
            person.registered = True

        self.request.response.redirect(self.context.absolute_url() +
                                       '/mail_password_response')
    def person(self):
        """provide access to the logged-in user
        """
        if self._person and self._person is not _marker:
            return self._person

        mtool = getToolByName(self.context, 'portal_membership')
        if mtool.isAnonymousUser():
            self._person = None
            return self._person
        
        member = mtool.getAuthenticatedMember()
        res = get_brains_for_email(self.context, member.id)
        if not res:
            return self._person

        self._person = res[0].getObject()
        return self._person
示例#6
0
    def person(self):
        """provide access to the logged-in user
        """
        if self._person and self._person is not _marker:
            return self._person

        mtool = getToolByName(self.context, 'portal_membership')
        if mtool.isAnonymousUser():
            self._person = None
            return self._person

        member = mtool.getAuthenticatedMember()
        res = get_brains_for_email(self.context, member.id)
        if not res:
            return self._person

        self._person = res[0].getObject()
        return self._person
def validateEmail(value):
    site = getSite()

    res = get_brains_for_email(site, value)
    if not res:
        raise Invalid(_(u"No existing user account found to set password.  Please use the registration form to create an account."))

    # Auto log in the user
    # NOTE: This is to allow the current anon user access to the user profile.  If there is an error, you MUST log the user out before raising an exception
    mtool = getToolByName(site, 'portal_membership')
    acl = getToolByName(site, 'acl_users')
    newSecurityManager(None, acl.getUser(value))
    mtool.loginUser()

    person = res[0].getObject()

    if person.registered == True:
        mtool.logoutUser()
        raise Invalid(_(u"This account already has a password set.  If you have forgotten the password, please use the forgot password link to reset your password."))    
    def handleOk(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        email = data['email']

        site = getSite()
        membership = getToolByName(site, 'portal_membership')
        member = membership.getMemberById(email)

        # Like mailPassword() in CMFPlone.RegistrationTool, render
        # and send the message ourselves to avoid tripping over security.
        reset_tool = getToolByName(site, 'portal_password_reset')
        reset = reset_tool.requestReset(member.getId())
        encoding = site.getProperty('email_charset', 'utf-8')
        mail_text = site.mail_password_template(
            site, self.request, member=member, reset=reset,
            password=member.getPassword(), charset=encoding)
        # The mail headers are not properly encoded, so we need to extract
        # them and let MailHost manage the encoding.
        if isinstance(mail_text, unicode):
            mail_text = mail_text.encode(encoding)
        message_obj = message_from_string(mail_text.strip())
        subject = message_obj['Subject']
        m_to = message_obj['To']
        m_from = message_obj['From']
        host = getToolByName(site, 'MailHost')
        host.send(mail_text, m_to, m_from, subject=subject,
                  charset=encoding, immediate=False)

        brains = get_brains_for_email(site, email)
        if brains is not None:
            person = brains[0].getObject()
            # person.registered must be set in order for the user
            # to log in with a password.
            person.registered = True

        self.request.response.redirect(
            self.context.absolute_url() + '/mail_password_response')
def validateEmail(value):
    site = getSite()

    res = get_brains_for_email(site, value)
    if res:
        membership = getToolByName(site, 'portal_membership')
        member = membership.getMemberById(value)
    else:
        member = None

    if member is None:
        raise Invalid(_(u"No existing user account found to set password. "
                        " Please use the registration form to create an"
                        "account."))

    person = res[0].getObject()

    if person.registered:
        raise Invalid(_(u"This account already has a password set.  If you "
                        "have forgotten the password, please use the forgot "
                        "password link to reset your password."))
示例#10
0
def validateEmail(value):
    site = getSite()

    res = get_brains_for_email(site, value)
    if res:
        membership = getToolByName(site, 'portal_membership')
        member = membership.getMemberById(value)
    else:
        member = None

    if member is None:
        raise Invalid(
            _(u"No existing user account found to set password. "
              " Please use the registration form to create an"
              "account."))

    person = res[0].getObject()

    if person.registered:
        raise Invalid(
            _(u"This account already has a password set.  If you "
              "have forgotten the password, please use the forgot "
              "password link to reset your password."))
    def handleOk(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        # NOTE: The validator on email should have already checked if the password can be set and auto logged the user in
        res = get_brains_for_email(self.context, data['email'], self.request)
        person = res[0].getObject()
        person.password = pw_encrypt(data['password'])
        person.registered = True

        # See if came_from was passed
        # fix odd bug where came_from is a list of two values
        came_from = data.get('came_from', None)
        if came_from and isinstance(came_from, (list, tuple)):
            came_from = came_from[0]

        self.request.form['came_from'] = came_from

        # merge in with standard plone login process.  
        login_next = self.context.restrictedTraverse('login_next')
        login_next()
    def get_user_category(self, email):
        """ Returns either registered, social, donor_only, or None """
        res = get_brains_for_email(self.context, email)
        if not res:
            return None

        mtool = getToolByName(self.context, 'portal_membership')
        acl = getToolByName(self.context, 'acl_users')
        newSecurityManager(None, acl.getUser(email))
        mtool.loginUser()

        category = 'donor_only'

        person = res[0].getObject()

        if person.social_signin:
            category = 'social'

        if person.registered:
            category = 'registered'

        mtool.logoutUser()

        return category
示例#13
0
    def get_user_category(self, email):
        """ Returns either registered, social, donor_only, or None """
        res = get_brains_for_email(self.context, email)
        if not res:
            return None

        mtool = getToolByName(self.context, 'portal_membership')
        acl = getToolByName(self.context, 'acl_users')
        newSecurityManager(None, acl.getUser(email))
        mtool.loginUser()

        category = 'donor_only'

        person = res[0].getObject()

        if person.social_signin:
            category = 'social'

        if person.registered:
            category = 'registered'

        mtool.logoutUser()

        return category
示例#14
0
    def render(self):
        # Get the api key from registry
        settings = get_settings()

        # workaround for http://bugs.python.org/issue5285,
        # map unicode to strings
        janrain_api_key = str(settings.janrain_api_key)

        if not janrain_api_key:
            return 'No Janrain API key configured'

        # Get the token
        token = self.request.form.get('token', None)
        if not token:
            return 'No token passed in request'

        # Get the user profile from Janrain
        auth_info_url = '%s/auth_info?apiKey=%s&token=%s' % (
            JANRAIN_API_BASE_URL,
            janrain_api_key,
            token,
        )

        if settings.janrain_use_extended_profile:
            auth_info_url = auth_info_url + '&extended=true'

        resp = urllib2.urlopen(auth_info_url)
        auth_info = simplejson.loads(resp.read())

        # This is for Plone's built in member management instead of membrane
        # See if a user already exists for the profile's email
        # email = auth_info['profile']['email']
        # member = None
        # if email:
        #     member = mtool.getMemberById(email)

        # See if user already exists using dexterity.membrane
        profile = auth_info.get('profile', {})

        email = profile.get('verifiedEmail', None)

        # NB: Do NOT accept the 'email' attribute as an alternative
        # to 'verifiedEmail'.  The 'email' attribute can be entered by
        # users and therefore would be a security hole.

        if not email:
            raise AttributeError(
                'No email provided from social profile, unable to create '
                'account')

        email = email.lower()

        res = get_brains_for_email(self.context, email, self.request)
        if not res:
            # create new Person if no existing Person was found
            # with the same email
            name = profile.get('name', {})
            address = profile.get('address', {})
            if not address:
                addresses = profile.get('addresses', [])
                if addresses:
                    address = addresses[0]

            data = {
                'first_name': name.get('givenName', None),
                'last_name': name.get('familyName', None),
                'email': email,
                'street_address': address.get('streetAddress', None),
                'city': address.get('locality', None),
                'state': address.get('region', None),
                'zip': address.get('postalCode', None),
                'country': address.get('country', None),
                # 'gender': profile.get('gender', None),
                'social_signin': True,
            }

            # Create the user
            people_container = getattr(getSite(), 'people')
            person = createContentInContainer(
                people_container,
                'collective.salesforce.fundraising.person',
                checkConstraints=False,
                **data)

            # Authenticate the user
            mtool = getToolByName(self.context, 'portal_membership')
            acl = getToolByName(self.context, 'acl_users')
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

        # or use the existing Person if found
        else:
            # Authenticate the user
            mtool = getToolByName(self.context, 'portal_membership')
            acl = getToolByName(self.context, 'acl_users')
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

            person = res[0].getObject()

            if not person.social_signin:
                person.social_signin = True

        # Set the photo
        photo = profile.get('photo', None)
        if not photo:
            photos = profile.get('photos', [])
            if photos:
                photo = photos[0]
        if photo and (not person.portrait or not person.portrait.size):
            img_data = urllib2.urlopen(photo).read()
            person.portrait = NamedBlobImage(img_data)

        # See if came_from was passed
        came_from = self.request.form.get('came_from', None)
        # fix odd bug where came_from is a list of two values
        if came_from and isinstance(came_from, (list, tuple)):
            came_from = came_from[0]
        if came_from:
            return self.request.response.redirect(came_from)

        # merge in with standard plone login process.
        login_next = self.context.restrictedTraverse('login_next')
        login_next()
    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"
                )
示例#16
0
 def has_membrane(self):
     current_user = api.user.get_current()
     email = current_user.getProperty('email')
     membranes = get_brains_for_email(self.context, self.email)
     return len(membranes) > 0
    def render(self):
        # Get the api key from registry
        settings = get_settings()

        # workaround for http://bugs.python.org/issue5285,
        # map unicode to strings
        janrain_api_key = str(settings.janrain_api_key)

        if not janrain_api_key:
            return "No Janrain API key configured"

        # Get the token
        token = self.request.form.get("token", None)
        if not token:
            return "No token passed in request"

        # Get the user profile from Janrain
        auth_info_url = "%s/auth_info?apiKey=%s&token=%s" % (JANRAIN_API_BASE_URL, janrain_api_key, token)

        if settings.janrain_use_extended_profile:
            auth_info_url = auth_info_url + "&extended=true"

        resp = urllib2.urlopen(auth_info_url)
        auth_info = simplejson.loads(resp.read())

        # This is for Plone's built in member management instead of membrane
        # See if a user already exists for the profile's email
        # email = auth_info['profile']['email']
        # member = None
        # if email:
        #     member = mtool.getMemberById(email)

        # See if user already exists using dexterity.membrane
        profile = auth_info.get("profile", {})

        email = profile.get("verifiedEmail", None)

        # NB: Do NOT accept the 'email' attribute as an alternative
        # to 'verifiedEmail'.  The 'email' attribute can be entered by
        # users and therefore would be a security hole.

        if not email:
            raise AttributeError("No email provided from social profile, unable to create " "account")

        email = email.lower()

        res = get_brains_for_email(self.context, email, self.request)
        if not res:
            # create new Person if no existing Person was found
            # with the same email
            name = profile.get("name", {})
            address = profile.get("address", {})
            if not address:
                addresses = profile.get("addresses", [])
                if addresses:
                    address = addresses[0]

            data = {
                "first_name": name.get("givenName", None),
                "last_name": name.get("familyName", None),
                "email": email,
                "street_address": address.get("streetAddress", None),
                "city": address.get("locality", None),
                "state": address.get("region", None),
                "zip": address.get("postalCode", None),
                "country": address.get("country", None),
                # 'gender': profile.get('gender', None),
                "social_signin": True,
            }

            # Create the user
            people_container = getattr(getSite(), "people")
            person = createContentInContainer(
                people_container, "collective.salesforce.fundraising.person", checkConstraints=False, **data
            )

            # Authenticate the user
            mtool = getToolByName(self.context, "portal_membership")
            acl = getToolByName(self.context, "acl_users")
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

        # or use the existing Person if found
        else:
            # Authenticate the user
            mtool = getToolByName(self.context, "portal_membership")
            acl = getToolByName(self.context, "acl_users")
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

            person = res[0].getObject()

            if not person.social_signin:
                person.social_signin = True

        # Set the photo
        photo = profile.get("photo", None)
        if not photo:
            photos = profile.get("photos", [])
            if photos:
                photo = photos[0]
        if photo and (not person.portrait or not person.portrait.size):
            img_data = urllib2.urlopen(photo).read()
            person.portrait = NamedBlobImage(img_data)

        # See if came_from was passed
        came_from = self.request.form.get("came_from", None)
        # fix odd bug where came_from is a list of two values
        if came_from and isinstance(came_from, (list, tuple)):
            came_from = came_from[0]
        if came_from:
            return self.request.response.redirect(came_from)

        # merge in with standard plone login process.
        login_next = self.context.restrictedTraverse("login_next")
        login_next()
示例#18
0
    def handleOk(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        # Don't allow creation of a personal page if one already exists
        existing_personal_campaign = \
            self.context.get_personal_fundraising_campaign_url()
        if existing_personal_campaign:
            messages = IStatusMessage(self.request)
            messages.add("You can't create more than one "
                         "personal page per campaign.")
            self.request.response.redirect(self.context.absolute_url())
            return

        # Add a personal campaign within the current context,
        # using the data from the form.
        parent_campaign = self.context
        campaign = createContentInContainer(
            parent_campaign,
            'collective.salesforce.fundraising.personalcampaignpage',
            checkConstraints=False,
            **data)

        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        person_res = get_brains_for_email(self.context,
                                          member.getProperty('email'))
        person = None
        contact_id = None
        if person_res:
            person = person_res[0].getObject()
            contact_id = person.sf_object_id

        settings = get_settings()

        # Add the campaign in Salesforce
        sfconn = getUtility(ISalesforceUtility).get_connection()
        data = {
            'Type': 'Personal Fundraising',
            'ParentId': parent_campaign.sf_object_id,
            'Name': data['title'],
            'Description': data['description'],
            'Public_Name__c': data['title'],
            'ExpectedRevenue': data['goal'],
            'Personal_Campaign_Contact__c': contact_id,
            'IsActive': True,
            'Status': 'In Progress',
        }
        if settings.sf_campaign_record_type_personal:
            data['RecordTypeID'] = settings.sf_campaign_record_type_personal

        res = sfconn.Campaign.create(data)
        if not res['success']:
            raise Exception(res['errors'][0])

        # Save the Id of the new campaign so it can be updated later.
        campaign.parent_sf_id = parent_campaign.sf_object_id
        campaign.sf_object_id = res['id']
        campaign.contact_sf_id = contact_id
        campaign.reindexObject()

        # Send email confirmation and links.
        try:
            campaign.send_email_personal_page_created()
        except HTTPRequestException as e:
            failure = {
                'func_name': 'MemorialEmailView',
                'func': '',
                'args': '',
                'kwargs': '',
                'portal_path': '',
                'context_path': repr(self.context),
                'userfolder_path': '',
                'user_id': '',
                'tb': e,
            }
            email_failure_from_portal(self.context, failure)

        # Send the user to their new campaign.
        IStatusMessage(self.request).add(u'Welcome to your fundraising page!')
        self.request.response.redirect(campaign.absolute_url())
    def handleOk(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        # Don't allow creation of a personal page if one already exists
        existing_personal_campaign = \
            self.context.get_personal_fundraising_campaign_url()
        if existing_personal_campaign:
            messages = IStatusMessage(self.request)
            messages.add("You can't create more than one "
                         "personal page per campaign.")
            self.request.response.redirect(self.context.absolute_url())
            return

        # Add a personal campaign within the current context,
        # using the data from the form.
        parent_campaign = self.context
        campaign = createContentInContainer(
            parent_campaign,
            'collective.salesforce.fundraising.personalcampaignpage',
            checkConstraints=False, **data
        )

        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        person_res = get_brains_for_email(
            self.context,
            member.getProperty('email')
        )
        person = None
        contact_id = None
        if person_res:
            person = person_res[0].getObject()
            contact_id = person.sf_object_id

        settings = get_settings()

        # Add the campaign in Salesforce
        sfconn = getUtility(ISalesforceUtility).get_connection()
        data = {
            'Type': 'Personal Fundraising',
            'ParentId': parent_campaign.sf_object_id,
            'Name': data['title'],
            'Description': data['description'],
            'Public_Name__c': data['title'],
            'ExpectedRevenue': data['goal'],
            'Personal_Campaign_Contact__c': contact_id,
            'IsActive': True,
            'Status': 'In Progress',
            }
        if settings.sf_campaign_record_type_personal:
            data['RecordTypeID'] = settings.sf_campaign_record_type_personal

        res = sfconn.Campaign.create(data)
        if not res['success']:
            raise Exception(res['errors'][0])

        # Save the Id of the new campaign so it can be updated later.
        campaign.parent_sf_id = parent_campaign.sf_object_id
        campaign.sf_object_id = res['id']
        campaign.contact_sf_id = contact_id
        campaign.reindexObject()

        # Send email confirmation and links.
        try:
            campaign.send_email_personal_page_created()
        except HTTPRequestException as e:
            failure = {
                'func_name': 'MemorialEmailView',
                'func': '',
                'args': '',
                'kwargs': '',
                'portal_path': '',
                'context_path': repr(self.context),
                'userfolder_path': '',
                'user_id': '',
                'tb': e,
            }
            email_failure_from_portal(self.context, failure)

        # Send the user to their new campaign.
        IStatusMessage(self.request).add(u'Welcome to your fundraising page!')
        self.request.response.redirect(campaign.absolute_url())
    def render(self):
        # Get the api key from registry
        settings = get_settings()

        # workaround for http://bugs.python.org/issue5285, map unicode to strings
        janrain_api_key = str(settings.janrain_api_key)

        if not janrain_api_key:
            return 'No Janrain API key configured'

        # Get the token
        token = self.request.form.get('token', None)
        if not token:
            return 'No token passed in request'

        # Get the user profile from Janrain
        auth_info_url = '%s/auth_info?apiKey=%s&token=%s' % (
            JANRAIN_API_BASE_URL,
            janrain_api_key,
            token,
        )
        
        if settings.janrain_use_extended_profile:
            auth_info_url = auth_info_url + '&extended=true'
        
        resp = urllib2.urlopen(auth_info_url)
        auth_info = simplejson.loads(resp.read())

        # This is for Plone's built in member management instead of membrane 
        # See if a user already exists for the profile's email
        #email = auth_info['profile']['email']
        #member = None
        #if email:
            #member = mtool.getMemberById(email)

        # See if user already exists using dexterity.membrane
        profile = auth_info.get('profile',{})

        email = profile.get('verifiedEmail', None)
        if not email:
            email = profile.get('email', None)
        if not email:
            raise AttributeError('No email provided from social profile, unable to create account')

        email = email.lower()

        res = get_brains_for_email(self.context, email, self.request)
        if not res:
            # create new Person if no existing Person was found with the same email
            name = profile.get('name',{})
            address = profile.get('address',{})
            if not address:
                addresses = profile.get('addresses', [])
                if addresses:
                    address = addresses[0]
        
            data = {
                'first_name': name.get('givenName', None),
                'last_name': name.get('familyName', None),
                'email': email,
                'street_address': address.get('streetAddress', None),
                'city': address.get('locality', None),
                'state': address.get('region', None),
                'zip': address.get('postalCode', None),
                'country': address.get('country', None),
                #'gender': profile.get('gender', None),
                'social_signin': True,
            }

            # Create the user
            people_container = getattr(getSite(), 'people')
            person = createContentInContainer(
                people_container,
                'collective.salesforce.fundraising.person',
                checkConstraints=False,
                **data
            )

            # Authenticate the user
            mtool = getToolByName(self.context, 'portal_membership')
            acl = getToolByName(self.context, 'acl_users')
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

        # or use the existing Person if found
        else:
            # Authenticate the user
            mtool = getToolByName(self.context, 'portal_membership')
            acl = getToolByName(self.context, 'acl_users')
            newSecurityManager(None, acl.getUser(email))
            mtool.loginUser()

            person = res[0].getObject()

            if person.social_signin == False:
                person.social_signin = True
            
        # Set the photo
        photo = profile.get('photo', None)
        if not photo:
            photos = profile.get('photos',[])
            if photos:
                photo = photos[0]
        if photo and (not person.portrait or not person.portrait.size):
            img_data = urllib2.urlopen(photo).read()
            person.portrait = NamedBlobImage(img_data)

        # See if came_from was passed
        came_from = self.request.form.get('came_from', None)
        # fix odd bug where came_from is a list of two values
        if came_from and isinstance(came_from, (list, tuple)):
            came_from = came_from[0]
        if came_from:
            return self.request.response.redirect(came_from)

        # merge in with standard plone login process.  
        login_next = self.context.restrictedTraverse('login_next')
        login_next()