コード例 #1
0
ファイル: views.py プロジェクト: DanielSBrown/osf.io
def resend_confirmation(auth):
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    try:
        primary = data['email']['primary']
        confirmed = data['email']['confirmed']
        address = data['email']['address'].strip().lower()
    except KeyError:
        raise HTTPError(httplib.BAD_REQUEST)

    if primary or confirmed:
        raise HTTPError(httplib.BAD_REQUEST, data={'message_long': 'Cannnot resend confirmation for confirmed emails'})

    user.add_unconfirmed_email(address)

    # TODO: This setting is now named incorrectly.
    if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
        send_confirm_email(user, email=address)

    user.save()

    return _profile_view(user, is_profile=True)
コード例 #2
0
def resend_confirmation(auth):
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    try:
        primary = data['email']['primary']
        confirmed = data['email']['confirmed']
        address = data['email']['address'].strip().lower()
    except KeyError:
        raise HTTPError(httplib.BAD_REQUEST)

    if primary or confirmed:
        raise HTTPError(httplib.BAD_REQUEST,
                        data={
                            'message_long':
                            'Cannnot resend confirmation for confirmed emails'
                        })

    user.add_unconfirmed_email(address)

    # TODO: This setting is now named incorrectly.
    if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
        send_confirm_email(user, email=address)

    user.save()

    return _profile_view(user, is_profile=True)
コード例 #3
0
ファイル: views.py プロジェクト: cwisecarver/osf.io
def resend_confirmation(auth):
    user = auth.user
    data = request.get_json()

    validate_user(data, user)
    if not throttle_period_expired(user.email_last_sent, settings.SEND_EMAIL_THROTTLE):
        raise HTTPError(
            httplib.BAD_REQUEST,
            data={"message_long": "Too many requests. Please wait a while before sending another confirmation email."},
        )

    try:
        primary = data["email"]["primary"]
        confirmed = data["email"]["confirmed"]
        address = data["email"]["address"].strip().lower()
    except KeyError:
        raise HTTPError(httplib.BAD_REQUEST)

    if primary or confirmed:
        raise HTTPError(httplib.BAD_REQUEST, data={"message_long": "Cannnot resend confirmation for confirmed emails"})

    user.add_unconfirmed_email(address)

    # TODO: This setting is now named incorrectly.
    if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
        send_confirm_email(user, email=address)
        user.email_last_sent = datetime.datetime.utcnow()

    user.save()

    return _profile_view(user, is_profile=True)
コード例 #4
0
def resend_confirmation(auth):
    user = auth.user
    data = request.get_json()

    validate_user(data, user)
    if not throttle_period_expired(user.email_last_sent, settings.SEND_EMAIL_THROTTLE):
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST,
                        data={'message_long': 'Too many requests. Please wait a while before sending another confirmation email.'})

    try:
        primary = data['email']['primary']
        confirmed = data['email']['confirmed']
        address = data['email']['address'].strip().lower()
    except KeyError:
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST)

    if primary or confirmed:
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data={'message_long': 'Cannnot resend confirmation for confirmed emails'})

    user.add_unconfirmed_email(address)

    # TODO: This setting is now named incorrectly.
    if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
        send_confirm_email(user, email=address)
        user.email_last_sent = timezone.now()

    user.save()

    return _profile_view(user, is_profile=True)
コード例 #5
0
    def create(self, validated_data):
        user = self.context['request'].user
        address = validated_data['address']
        is_merge = Email.objects.filter(address=address).exists()
        if address in user.unconfirmed_emails or address in user.emails.all(
        ).values_list('address', flat=True):
            raise Conflict(
                'This user already has registered with the email address {}'.
                format(address))
        try:
            token = user.add_unconfirmed_email(address)
            user.save()
            if CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)
                user.email_last_sent = timezone.now()
                user.save()
        except ValidationError as e:
            raise exceptions.ValidationError(e.args[0])
        except BlacklistedEmailError:
            raise exceptions.ValidationError(
                'This email address domain is blacklisted.')

        return UserEmail(email_id=token,
                         address=address,
                         confirmed=False,
                         verified=False,
                         primary=False,
                         is_merge=is_merge)
コード例 #6
0
ファイル: test_institution_auth.py プロジェクト: jwalz/osf.io
    def test_user_external_unconfirmed(self, app, institution, url_auth_institution):

        # Create an unconfirmed user with pending external identity
        username, fullname = '*****@*****.**', 'Foo Bar'
        external_id_provider, external_id, status = 'ORCID', '1234-1234-1234-1234', 'CREATE'
        external_identity = {external_id_provider: {external_id: status}}
        accepted_terms_of_service = timezone.now()
        user = OSFUser.create_unconfirmed(
            username=username,
            password=None,
            fullname=fullname,
            external_identity=external_identity,
            campaign=None,
            accepted_terms_of_service=accepted_terms_of_service
        )
        user.save()
        assert not user.has_usable_password()
        assert user.external_identity

        # Send confirm email in order to add new email verifications
        send_confirm_email(
            user,
            user.username,
            external_id_provider=external_id_provider,
            external_id=external_id
        )
        user.save()
        assert user.email_verifications
        email_verifications = user.email_verifications

        with capture_signals() as mock_signals:
            res = app.post(
                url_auth_institution,
                make_payload(
                    institution,
                    username,
                    family_name='User',
                    given_name='Fake',
                    fullname='Fake User',
                    department='Fake User',
                ),
                expect_errors=True
            )
        assert res.status_code == 403
        assert not mock_signals.signals_sent()

        user = OSFUser.objects.filter(username=username).first()
        assert user
        # User remains untouched, including affiliation, external identity email verifcaitons
        assert user.fullname == fullname
        assert user.given_name == 'Foo'
        assert user.family_name == 'Bar'
        assert institution not in user.affiliated_institutions.all()
        assert external_identity == user.external_identity
        assert email_verifications == user.email_verifications
        assert accepted_terms_of_service == user.accepted_terms_of_service
        assert not user.has_usable_password()
コード例 #7
0
ファイル: serializers.py プロジェクト: rdm-dev12/RDM-osf.io
    def create(self, validated_data):
        user = self.context['request'].user
        address = validated_data['address']
        if address in user.unconfirmed_emails or address in user.emails.all().values_list('address', flat=True):
            raise Conflict('This user already has registered with the email address {}'.format(address))
        try:
            token = user.add_unconfirmed_email(address)
            user.save()
            if CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)
        except ValidationError as e:
            raise exceptions.ValidationError(e.args[0])

        return UserEmail(email_id=token, address=address, confirmed=False, primary=False)
コード例 #8
0
ファイル: views.py プロジェクト: futa-ikeda/osf.io
    def get_object(self):
        email_id = self.kwargs['email_id']
        user = self.get_user()
        email = None

        # check to see if it's a confirmed email with hashed id
        decoded_id = hashids.decode(email_id)
        if decoded_id:
            try:
                email = user.emails.get(id=decoded_id[0])
            except Email.DoesNotExist:
                email = None
            else:
                primary = email.address == user.username
                address = email.address
                confirmed = True
                verified = True
                is_merge = False

        # check to see if it's an unconfirmed email with a token
        elif user.unconfirmed_emails:
            try:
                email = user.email_verifications[email_id]
                address = email['email']
                confirmed = email['confirmed']
                verified = False
                primary = False
                is_merge = Email.objects.filter(address=address).exists()
            except KeyError:
                email = None

        if not email:
            raise NotFound

        # check for resend confirmation email query parameter in a GET request
        if self.request.method == 'GET' and is_truthy(
                self.request.query_params.get('resend_confirmation')):
            if not confirmed and settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                if throttle_period_expired(user.email_last_sent,
                                           settings.SEND_EMAIL_THROTTLE):
                    send_confirm_email(user, email=address, renew=True)
                    user.email_last_sent = timezone.now()
                    user.save()

        return UserEmail(email_id=email_id,
                         address=address,
                         confirmed=confirmed,
                         verified=verified,
                         primary=primary,
                         is_merge=is_merge)
コード例 #9
0
ファイル: serializers.py プロジェクト: aaxelb/osf.io
    def create(self, validated_data):
        user = self.context['request'].user
        address = validated_data['address']
        if address in user.unconfirmed_emails or address in user.emails.all().values_list('address', flat=True):
            raise Conflict('This user already has registered with the email address {}'.format(address))
        try:
            token = user.add_unconfirmed_email(address)
            user.save()
            if CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)
        except ValidationError as e:
            raise exceptions.ValidationError(e.args[0])
        except BlacklistedEmailError:
            raise exceptions.ValidationError('This email address domain is blacklisted.')

        return UserEmail(email_id=token, address=address, confirmed=False, primary=False)
コード例 #10
0
ファイル: views.py プロジェクト: CenterForOpenScience/osf.io
    def get_object(self):
        email_id = self.kwargs['email_id']
        user = self.get_user()
        email = None

        # check to see if it's a confirmed email with hashed id
        decoded_id = hashids.decode(email_id)
        if decoded_id:
            try:
                email = user.emails.get(id=decoded_id[0])
            except Email.DoesNotExist:
                email = None
            else:
                primary = email.address == user.username
                address = email.address
                confirmed = True
                verified = True
                is_merge = False

        # check to see if it's an unconfirmed email with a token
        elif user.unconfirmed_emails:
            try:
                email = user.email_verifications[email_id]
                address = email['email']
                confirmed = email['confirmed']
                verified = False
                primary = False
                is_merge = Email.objects.filter(address=address).exists()
            except KeyError:
                email = None

        if not email:
            raise NotFound

        # check for resend confirmation email query parameter in a GET request
        if self.request.method == 'GET' and is_truthy(self.request.query_params.get('resend_confirmation')):
            if not confirmed and settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                if throttle_period_expired(user.email_last_sent, settings.SEND_EMAIL_THROTTLE):
                    send_confirm_email(user, email=address, renew=True)
                    user.email_last_sent = timezone.now()
                    user.save()

        return UserEmail(email_id=email_id, address=address, confirmed=confirmed, verified=verified, primary=primary, is_merge=is_merge)
コード例 #11
0
ファイル: serializers.py プロジェクト: scooley/osf.io
    def create(self, validated_data):
        username = validated_data.get('username', '').lower() or None
        full_name = validated_data.get('fullname')
        if not full_name:
            raise JSONAPIException('A `full_name` is required to create a user.')

        user = User.create_unregistered(full_name, email=username)
        user.registered_by = self.context['request'].user
        if username:
            user.add_unconfirmed_email(user.username)

        try:
            user.save()
        except ValidationValueError:
            raise Conflict('User with specified username already exists.')

        if self.context['request'].GET.get('send_email', False) and username:
            send_confirm_email(user, user.username)

        return user
コード例 #12
0
ファイル: serializers.py プロジェクト: baylee-d/osf.io
    def create(self, validated_data):
        username = validated_data.get('username', '').lower() or None
        full_name = validated_data.get('fullname')
        if not full_name:
            raise JSONAPIException('A `full_name` is required to create a user.')

        user = User.create_unregistered(full_name, email=username)
        user.registered_by = self.context['request'].user
        if username:
            user.add_unconfirmed_email(user.username)

        try:
            user.save()
        except ValidationValueError:
            raise Conflict('User with specified username already exists.')

        if self.context['request'].GET.get('send_email', False) and username:
            send_confirm_email(user, user.username)

        return user
コード例 #13
0
ファイル: views.py プロジェクト: GageGaskins/osf.io
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if 'emails' in data:

        emails_list = [x['address'].strip().lower() for x in data['emails']]

        if user.username not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        # removals
        removed_emails = [
            each
            for each in user.emails + user.unconfirmed_emails
            if each not in emails_list
        ]

        if user.username in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if address in user.emails:
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, e.message)
            user.remove_unconfirmed_email(address)

        # additions
        added_emails = [
            each['address'].strip().lower()
            for each in data['emails']
            if each['address'].strip().lower() not in user.emails
            and each['address'].strip().lower() not in user.unconfirmed_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                continue

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next(
            (
                each for each in data['emails']
                # email is primary
                if each.get('primary') and each.get('confirmed')
                # an address is specified (can't trust those sneaky users!)
                and each.get('address')
            )
        )

        if primary_email:
            primary_email_address = primary_email['address'].strip().lower()
            if primary_email_address not in user.emails:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username in user.emails and username != user.username:
            mails.send_mail(user.username,
                            mails.PRIMARY_EMAIL_CHANGED,
                            user=user,
                            new_address=username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if 'locale' in data:
        if data['locale']:
            locale = data['locale'].replace('-', '_')
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if 'timezone' in data:
        if data['timezone']:
            user.timezone = data['timezone']

    user.save()

    return _profile_view(user)
コード例 #14
0
ファイル: views.py プロジェクト: cwisecarver/osf.io
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if "emails" in data:

        emails_list = [x["address"].strip().lower() for x in data["emails"]]

        if user.username.strip().lower() not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        available_emails = [each.strip().lower() for each in user.emails + user.unconfirmed_emails]
        # removals
        removed_emails = [each.strip().lower() for each in available_emails if each not in emails_list]

        if user.username.strip().lower() in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if address in user.emails:
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, e.message)
            user.remove_unconfirmed_email(address)

        # additions
        added_emails = [
            each["address"].strip().lower()
            for each in data["emails"]
            if each["address"].strip().lower() not in available_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                raise HTTPError(http.BAD_REQUEST, data=dict(message_long="Invalid Email"))

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next(
            (
                each
                for each in data["emails"]
                # email is primary
                if each.get("primary") and each.get("confirmed")
                # an address is specified (can't trust those sneaky users!)
                and each.get("address")
            )
        )

        if primary_email:
            primary_email_address = primary_email["address"].strip().lower()
            if primary_email_address not in [each.strip().lower() for each in user.emails]:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username in user.emails and username != user.username:
            mails.send_mail(user.username, mails.PRIMARY_EMAIL_CHANGED, user=user, new_address=username)

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.iteritems():
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(list_name, user._id, username=user.username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if "locale" in data:
        if data["locale"]:
            locale = data["locale"].replace("-", "_")
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if "timezone" in data:
        if data["timezone"]:
            user.timezone = data["timezone"]

    user.save()

    # Update subscribed mailing lists with new primary email
    # TODO: move to user.save()
    for list_name, subscription in user.mailchimp_mailing_lists.iteritems():
        if subscription:
            mailchimp_utils.subscribe_mailchimp(list_name, user._id)

    return _profile_view(user, is_profile=True)
コード例 #15
0
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if 'emails' in data:

        emails_list = [x['address'].strip().lower() for x in data['emails']]

        if user.username.strip().lower() not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        available_emails = [
            each.strip().lower() for each in
            list(user.emails.values_list('address', flat=True)) + user.unconfirmed_emails
        ]
        # removals
        removed_emails = [
            each.strip().lower()
            for each in available_emails
            if each not in emails_list
        ]

        if user.username.strip().lower() in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if user.emails.filter(address=address):
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, e.message)
            user.remove_unconfirmed_email(address)

        # additions
        added_emails = [
            each['address'].strip().lower()
            for each in data['emails']
            if each['address'].strip().lower() not in available_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                raise HTTPError(http.BAD_REQUEST, data=dict(
                    message_long='Invalid Email')
                )
            except BlacklistedEmailError:
                raise HTTPError(http.BAD_REQUEST, data=dict(
                    message_long=language.BLACKLISTED_EMAIL)
                )

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next(
            (
                each for each in data['emails']
                # email is primary
                if each.get('primary') and each.get('confirmed')
                # an address is specified (can't trust those sneaky users!)
                and each.get('address')
            )
        )

        if primary_email:
            primary_email_address = primary_email['address'].strip().lower()
            if primary_email_address not in [each.strip().lower() for each in user.emails.values_list('address', flat=True)]:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username != user.username and user.emails.filter(address=username).exists():

            mails.send_mail(
                user.username,
                mails.PRIMARY_EMAIL_CHANGED,
                user=user,
                new_address=username,
                can_change_preferences=False,
                osf_contact_email=settings.OSF_CONTACT_EMAIL
            )

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.iteritems():
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(list_name, user._id, username=user.username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if 'locale' in data:
        if data['locale']:
            locale = data['locale'].replace('-', '_')
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if 'timezone' in data:
        if data['timezone']:
            user.timezone = data['timezone']

    user.save()

    # Update subscribed mailing lists with new primary email
    # TODO: move to user.save()
    for list_name, subscription in user.mailchimp_mailing_lists.iteritems():
        if subscription:
            mailchimp_utils.subscribe_mailchimp(list_name, user._id)

    return _profile_view(user, is_profile=True)
コード例 #16
0
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if 'emails' in data:

        emails_list = [x['address'].strip().lower() for x in data['emails']]

        if user.username.strip().lower() not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        available_emails = [
            each.strip().lower()
            for each in user.emails + user.unconfirmed_emails
        ]
        # removals
        removed_emails = [
            each.strip().lower() for each in available_emails
            if each not in emails_list
        ]

        if user.username.strip().lower() in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if address in user.emails:
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, e.message)
            user.remove_unconfirmed_email(address)

        # additions
        added_emails = [
            each['address'].strip().lower() for each in data['emails']
            if each['address'].strip().lower() not in available_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                raise HTTPError(http.BAD_REQUEST,
                                data=dict(message_long="Invalid Email"))

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next((
            each for each in data['emails']
            # email is primary
            if each.get('primary') and each.get('confirmed')
            # an address is specified (can't trust those sneaky users!)
            and each.get('address')))

        if primary_email:
            primary_email_address = primary_email['address'].strip().lower()
            if primary_email_address not in [
                    each.strip().lower() for each in user.emails
            ]:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username in user.emails and username != user.username:
            mails.send_mail(user.username,
                            mails.PRIMARY_EMAIL_CHANGED,
                            user=user,
                            new_address=username)

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.iteritems(
            ):
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(
                        list_name, user._id, username=user.username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if 'locale' in data:
        if data['locale']:
            locale = data['locale'].replace('-', '_')
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if 'timezone' in data:
        if data['timezone']:
            user.timezone = data['timezone']

    user.save()

    # Update subscribed mailing lists with new primary email
    # TODO: move to user.save()
    for list_name, subscription in user.mailchimp_mailing_lists.iteritems():
        if subscription:
            mailchimp_utils.subscribe_mailchimp(list_name, user._id)

    return _profile_view(user, is_profile=True)
コード例 #17
0
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user
    data = request.get_json()

    validate_user(data, user)

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if 'emails' in data:

        emails_list = [x['address'].strip().lower() for x in data['emails']]

        if user.username.strip().lower() not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        available_emails = [
            each.strip().lower()
            for each in list(user.emails.values_list('address', flat=True)) +
            user.unconfirmed_emails
        ]
        # removals
        removed_emails = [
            each.strip().lower() for each in available_emails
            if each not in emails_list
        ]

        if user.username.strip().lower() in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if user.emails.filter(address=address):
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, str(e))
            user.remove_unconfirmed_email(address)

        # additions
        added_emails = [
            each['address'].strip().lower() for each in data['emails']
            if each['address'].strip().lower() not in available_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                raise HTTPError(http.BAD_REQUEST,
                                data=dict(message_long='Invalid Email'))
            except BlacklistedEmailError:
                sentry.log_message('User attempted to add a blacklisted email',
                                   extra_data={
                                       'user_id': user.id,
                                       'address': address,
                                   })
                raise HTTPError(
                    http.BAD_REQUEST,
                    data=dict(message_long=language.BLACKLISTED_EMAIL))

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                if not throttle_period_expired(user.email_last_sent,
                                               settings.SEND_EMAIL_THROTTLE):
                    raise HTTPError(
                        httplib.BAD_REQUEST,
                        data={
                            'message_long':
                            'Too many requests. Please wait a while before adding an email to your account.'
                        })
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next((
            each for each in data['emails']
            # email is primary
            if each.get('primary') and each.get('confirmed')
            # an address is specified (can't trust those sneaky users!)
            and each.get('address')))

        if primary_email:
            primary_email_address = primary_email['address'].strip().lower()
            if primary_email_address not in [
                    each.strip().lower()
                    for each in user.emails.values_list('address', flat=True)
            ]:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username != user.username and user.emails.filter(
                address=username).exists():

            mails.send_mail(user.username,
                            mails.PRIMARY_EMAIL_CHANGED,
                            user=user,
                            new_address=username,
                            can_change_preferences=False,
                            osf_contact_email=settings.OSF_CONTACT_EMAIL)

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.items(
            ):
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(
                        list_name, user._id, username=user.username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if 'locale' in data:
        if data['locale']:
            locale = data['locale'].replace('-', '_')
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if 'timezone' in data:
        if data['timezone']:
            user.timezone = data['timezone']

    user.save()

    # Update subscribed mailing lists with new primary email
    # TODO: move to user.save()
    for list_name, subscription in user.mailchimp_mailing_lists.items():
        if subscription:
            mailchimp_utils.subscribe_mailchimp(list_name, user._id)

    return _profile_view(user, is_profile=True)
コード例 #18
0
def update_user(auth):
    """Update the logged-in user's profile."""

    # trust the decorator to handle auth
    user = auth.user

    data = request.get_json()

    # check if the user in request is the user who log in
    if 'id' in data:
        if data['id'] != user._id:
            raise HTTPError(httplib.FORBIDDEN)
    else:
        # raise an error if request doesn't have user id
        raise HTTPError(httplib.BAD_REQUEST, data={'message_long': '"id" is required'})

    # TODO: Expand this to support other user attributes

    ##########
    # Emails #
    ##########

    if 'emails' in data:

        emails_list = [x['address'].strip().lower() for x in data['emails']]

        if user.username not in emails_list:
            raise HTTPError(httplib.FORBIDDEN)

        # removals
        removed_emails = [
            each
            for each in user.emails + user.unconfirmed_emails
            if each not in emails_list
        ]

        if user.username in removed_emails:
            raise HTTPError(httplib.FORBIDDEN)

        for address in removed_emails:
            if address in user.emails:
                try:
                    user.remove_email(address)
                except PermissionsError as e:
                    raise HTTPError(httplib.FORBIDDEN, e.message)
            try:
                user.remove_unconfirmed_email(address)
            except PermissionsError as e:
                raise HTTPError(httplib.FORBIDDEN, e.message)

        # additions
        added_emails = [
            each['address'].strip().lower()
            for each in data['emails']
            if each['address'].strip().lower() not in user.emails
            and each['address'].strip().lower() not in user.unconfirmed_emails
        ]

        for address in added_emails:
            try:
                user.add_unconfirmed_email(address)
            except (ValidationError, ValueError):
                continue

            # TODO: This setting is now named incorrectly.
            if settings.CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)

        ############
        # Username #
        ############

        # get the first email that is set to primary and has an address
        primary_email = next(
            (
                each for each in data['emails']
                # email is primary
                if each.get('primary') and each.get('confirmed')
                # an address is specified (can't trust those sneaky users!)
                and each.get('address')
            )
        )

        if primary_email:
            primary_email_address = primary_email['address'].strip().lower()
            if primary_email_address not in user.emails:
                raise HTTPError(httplib.FORBIDDEN)
            username = primary_email_address

        # make sure the new username has already been confirmed
        if username and username in user.emails and username != user.username:
            mails.send_mail(user.username,
                            mails.PRIMARY_EMAIL_CHANGED,
                            user=user,
                            new_address=username)
            user.username = username

    ###################
    # Timezone/Locale #
    ###################

    if 'locale' in data:
        if data['locale']:
            locale = data['locale'].replace('-', '_')
            user.locale = locale
    # TODO: Refactor to something like:
    #   user.timezone = data.get('timezone', user.timezone)
    if 'timezone' in data:
        if data['timezone']:
            user.timezone = data['timezone']

    user.save()

    return _profile_view(user)