Beispiel #1
0
def claim_user_post(node, **kwargs):
    """View for claiming a user from the X-editable form on a project page.
    """
    reqdata = request.json
    # Unreg user
    user = User.load(reqdata['pk'])
    unclaimed_data = user.get_unclaimed_record(node._primary_key)
    # Submitted through X-editable
    if 'value' in reqdata:  # Submitted email address
        email = reqdata['value'].lower().strip()
        claimer = get_user(email=email)
        if claimer and claimer.is_registered:
            send_claim_registered_email(claimer=claimer, unreg_user=user,
                node=node)
        else:
            send_claim_email(email, user, node, notify=True)
    # TODO(sloria): Too many assumptions about the request data. Just use
    elif 'claimerId' in reqdata:  # User is logged in and confirmed identity
        claimer_id = reqdata['claimerId']
        claimer = User.load(claimer_id)
        send_claim_registered_email(claimer=claimer, unreg_user=user, node=node)
        email = claimer.username
    else:
        raise HTTPError(http.BAD_REQUEST)
    return {
        'status': 'success',
        'email': email,
        'fullname': unclaimed_data['name']
    }
Beispiel #2
0
def claim_user_post(node, **kwargs):
    """
    View for claiming a user from the X-editable form on a project page.

    :param node: the project node
    :return:
    """

    request_data = request.json

    # The unclaimed user
    unclaimed_user = User.load(request_data["pk"])
    unclaimed_data = unclaimed_user.get_unclaimed_record(node._primary_key)

    # Claimer is not logged in and submit her/his email through X-editable, stored in `request_data['value']`
    if "value" in request_data:
        email = request_data["value"].lower().strip()
        claimer = get_user(email=email)
        # registered user
        if claimer and claimer.is_registered:
            send_claim_registered_email(claimer, unclaimed_user, node)
        # unregistered user
        else:
            send_claim_email(email, unclaimed_user, node, notify=True)
    # Claimer is logged in with confirmed identity stored in `request_data['claimerId']`
    elif "claimerId" in request_data:
        claimer_id = request_data["claimerId"]
        claimer = User.load(claimer_id)
        send_claim_registered_email(claimer, unclaimed_user, node)
        email = claimer.username
    else:
        raise HTTPError(http.BAD_REQUEST)

    return {"status": "success", "email": email, "fullname": unclaimed_data["name"]}
Beispiel #3
0
def get_most_in_common_contributors(auth, node, **kwargs):
    node_contrib_ids = set(node.contributors._to_primary_keys())
    try:
        n_contribs = int(request.args.get('max', None))
    except (TypeError, ValueError):
        n_contribs = settings.MAX_MOST_IN_COMMON_LENGTH

    contrib_counts = Counter(contrib_id
        for node in auth.user.node__contributed
        for contrib_id in node.contributors._to_primary_keys()
        if contrib_id not in node_contrib_ids)

    active_contribs = itertools.ifilter(
        lambda c: User.load(c[0]).is_active,
        contrib_counts.most_common()
    )

    limited = itertools.islice(active_contribs, n_contribs)

    contrib_objs = [(User.load(_id), count) for _id, count in limited]

    contribs = [
        utils.add_contributor_json(most_contrib, auth.user)
        for most_contrib, count in sorted(contrib_objs, key=lambda t: (-t[1], t[0].fullname))
    ]
    return {'contributors': contribs}
Beispiel #4
0
def claim_user_post(node, **kwargs):
    """View for claiming a user from the X-editable form on a project page.
    """
    reqdata = request.json
    # Unreg user
    user = User.load(reqdata['pk'])
    unclaimed_data = user.get_unclaimed_record(node._primary_key)
    # Submitted through X-editable
    if 'value' in reqdata:  # Submitted email address
        email = reqdata['value'].lower().strip()
        claimer = get_user(email=email)
        if claimer and claimer.is_registered:
            send_claim_registered_email(claimer=claimer,
                                        unreg_user=user,
                                        node=node)
        else:
            send_claim_email(email, user, node, notify=True)
    # TODO(sloria): Too many assumptions about the request data. Just use
    elif 'claimerId' in reqdata:  # User is logged in and confirmed identity
        claimer_id = reqdata['claimerId']
        claimer = User.load(claimer_id)
        send_claim_registered_email(claimer=claimer,
                                    unreg_user=user,
                                    node=node)
        email = claimer.username
    else:
        raise HTTPError(http.BAD_REQUEST)
    return {
        'status': 'success',
        'email': email,
        'fullname': unclaimed_data['name']
    }
Beispiel #5
0
def do_registrar():
    """
    """
    _auth = Auth()
    if not _auth.is_login:
        errors = [] #errores 
        #validacion de campos vacios
        _username = request.forms.get('username')
        if _username == "":
            errors.append("El campo Usuario esta vacio")

        #validacion de contrasenias
        _password = request.forms.get('password')
        repassword = request.forms.get('repassword')
        if len(_password) < 8 or len(_password) >= 16:
            errors.append("la contrasenia debe tener entre 8 y 16 caracteres")
        if _password != repassword:
            errors.append("Las contrasenias no coinciden")

        _name = request.forms.get('name')
        if _name == "":
            errors.append("El campo Nombre esta vacio")
        
        _email = request.forms.get('email')
        if _email == "":
            errors.append("El campo Email esta vacio")

        if len(errors) == 0:
            #validacion de que no exista el usuario
            query = db.GqlQuery("SELECT * FROM User WHERE username = :1", _username)        
            if query.count() != 0:
                errors.append("El nombre de usuarios \"%s\" ya existe" %_username)
                form_error = True

            else:            
                user = User(
                    username = _username,
                    password = _password,
                    name = _name,
                    email = _email,
                )
                user.put()
                return template("auth/registrar-ok.html")

        else:
            form_error = True
        #si llego hasta aqui hay algun tipo de errors        
        data = {
            "errors" : errors,
            "form_error": form_error,
            "username": _username,
            "name": _name,
            "email": _email,
        }
        return template("auth/registrar.html", data)

    else:
        message = "Error ya has iniciado Session con la cuenta \"%s\" " %_auth.is_login()
        message += "en caso de querer proceder por fabor cierra la session actual."
        return template("message.html", {'message': message} )
Beispiel #6
0
def get_most_in_common_contributors(auth, node, **kwargs):
    node_contrib_ids = set(node.contributors._to_primary_keys())
    try:
        n_contribs = int(request.args.get('max', None))
    except (TypeError, ValueError):
        n_contribs = settings.MAX_MOST_IN_COMMON_LENGTH

    contrib_counts = Counter(
        contrib_id for node in auth.user.node__contributed
        for contrib_id in node.contributors._to_primary_keys()
        if contrib_id not in node_contrib_ids)

    active_contribs = itertools.ifilter(lambda c: User.load(c[0]).is_active,
                                        contrib_counts.most_common())

    limited = itertools.islice(active_contribs, n_contribs)

    contrib_objs = [(User.load(_id), count) for _id, count in limited]

    contribs = [
        profile_utils.add_contributor_json(most_contrib, auth.user)
        for most_contrib, count in sorted(contrib_objs,
                                          key=lambda t: (-t[1], t[0].fullname))
    ]
    return {'contributors': contribs}
Beispiel #7
0
def set_node_many_to_many_on_users(page_size=5000):
    print 'Starting {}...'.format(sys._getframe().f_code.co_name)
    user_count = 0
    m2m_count = 0
    start = datetime.now()
    total = MODMUser.find(build_query(m2m_node_fields, MODMUser)).count()
    print '{} Users'.format(total)
    while user_count < total:
        with transaction.atomic():
            for modm_user in MODMUser.find(
                    build_query(m2m_node_fields, MODMUser)).sort(
                        '-date_registered')[user_count:page_size + user_count]:
                django_user = User.objects.get(
                    pk=modm_to_django[modm_user._id])
                for m2m_node_field in m2m_node_fields:
                    try:
                        attr = getattr(django_user, m2m_node_field)
                    except AttributeError as ex:
                        # node field doesn't exist on user
                        pass
                    else:
                        # node field exists, do the stuff
                        django_pks = []
                        for modm_m2m_value in getattr(modm_user,
                                                      m2m_node_field, []):
                            if isinstance(modm_m2m_value, MODMNode):
                                django_pks.append(
                                    modm_to_django[modm_m2m_value._id])
                            elif isinstance(modm_m2m_value, basestring):
                                django_pks.append(
                                    modm_to_django[modm_m2m_value])
                            elif isinstance(modm_m2m_value, Pointer):
                                django_pks.append(
                                    modm_to_django[modm_m2m_value.node._id])
                            else:
                                # wth
                                print '\a'  # bells!
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                import bpdb
                                bpdb.set_trace()

                        if len(django_pks) > 0:
                            attr.add(*django_pks)
                        m2m_count += len(django_pks)
                user_count += 1
                if user_count % page_size == 0 or user_count == total:
                    print 'Through {} users and {} m2m'.format(
                        user_count, m2m_count)
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #8
0
def set_node_many_to_many_on_users(page_size=5000):
    print 'Starting {}...'.format(sys._getframe().f_code.co_name)
    user_count = 0
    m2m_count = 0
    start = datetime.now()
    total = MODMUser.find(build_query(m2m_node_fields, MODMUser)).count()
    print '{} Users'.format(total)
    while user_count < total:
        with transaction.atomic():
            for modm_user in MODMUser.find(build_query(
                    m2m_node_fields, MODMUser)).sort('-date_registered')[
                        user_count:page_size + user_count]:
                django_user = User.objects.get(
                    pk=modm_to_django[modm_user._id])
                for m2m_node_field in m2m_node_fields:
                    try:
                        attr = getattr(django_user, m2m_node_field)
                    except AttributeError as ex:
                        # node field doesn't exist on user
                        pass
                    else:
                        # node field exists, do the stuff
                        django_pks = []
                        for modm_m2m_value in getattr(modm_user,
                                                      m2m_node_field, []):
                            if isinstance(modm_m2m_value, MODMNode):
                                django_pks.append(modm_to_django[
                                    modm_m2m_value._id])
                            elif isinstance(modm_m2m_value, basestring):
                                django_pks.append(modm_to_django[
                                    modm_m2m_value])
                            elif isinstance(modm_m2m_value, Pointer):
                                django_pks.append(modm_to_django[
                                    modm_m2m_value.node._id])
                            else:
                                # wth
                                print '\a'  # bells!
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                print '\a'
                                import bpdb
                                bpdb.set_trace()

                        if len(django_pks) > 0:
                            attr.add(*django_pks)
                        m2m_count += len(django_pks)
                user_count += 1
                if user_count % page_size == 0 or user_count == total:
                    print 'Through {} users and {} m2m'.format(user_count,
                                                               m2m_count)
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #9
0
def deserialize_contributors(node, user_dicts, auth):
    """View helper that returns a list of User objects from a list of
    serialized users (dicts). The users in the list may be registered or
    unregistered users.

    e.g. ``[{'id': 'abc123', 'registered': True, 'fullname': ..},
            {'id': None, 'registered': False, 'fullname'...},
            {'id': '123ab', 'registered': False, 'fullname': ...}]

    If a dict represents an unregistered user without an ID, creates a new
    unregistered User record.

    :param Node node: The node to add contributors to
    :param list(dict) user_dicts: List of serialized users in the format above.
    :param Auth auth:
    """

    # Add the registered contributors
    contribs = []
    for contrib_dict in user_dicts:
        fullname = contrib_dict['fullname']
        visible = contrib_dict['visible']
        email = contrib_dict.get('email')

        if contrib_dict['id']:
            contributor = User.load(contrib_dict['id'])
        else:
            try:
                contributor = User.create_unregistered(fullname=fullname,
                                                       email=email)
                contributor.save()
            except ValidationValueError:
                contributor = get_user(username=email)

        # Add unclaimed record if necessary
        if (not contributor.is_registered
                and node._primary_key not in contributor.unclaimed_records):
            contributor.add_unclaimed_record(node=node,
                                             referrer=auth.user,
                                             given_name=fullname,
                                             email=email)
            contributor.save()
            unreg_contributor_added.send(node,
                                         contributor=contributor,
                                         auth=auth)

        contribs.append({
            'user':
            contributor,
            'visible':
            visible,
            'permissions':
            expand_permissions(contrib_dict.get('permission'))
        })
    return contribs
Beispiel #10
0
def main():
    total = MODMUser.find().count()
    count = 0
    page_size = 1000

    while count < total:
        modm_users = MODMUser.find()[count:count + page_size]
        for modm_user in modm_users:
            django_user = get_or_create_user(modm_user)
            count += 1
        print 'Count: {}'.format(count)
Beispiel #11
0
def deserialize_contributors(node, user_dicts, auth, validate=False):
    """View helper that returns a list of User objects from a list of
    serialized users (dicts). The users in the list may be registered or
    unregistered users.

    e.g. ``[{'id': 'abc123', 'registered': True, 'fullname': ..},
            {'id': None, 'registered': False, 'fullname'...},
            {'id': '123ab', 'registered': False, 'fullname': ...}]

    If a dict represents an unregistered user without an ID, creates a new
    unregistered User record.

    :param Node node: The node to add contributors to
    :param list(dict) user_dicts: List of serialized users in the format above.
    :param Auth auth:
    :param bool validate: Whether to validate and sanitize fields (if necessary)
    """

    # Add the registered contributors
    contribs = []
    for contrib_dict in user_dicts:
        fullname = contrib_dict["fullname"]
        visible = contrib_dict["visible"]
        email = contrib_dict.get("email")

        if validate is True:
            # Validate and sanitize inputs as needed. Email will raise error if invalid.
            # TODO Edge case bug: validation and saving are performed in same loop, so all in list
            # up to the invalid entry will be saved. (communicate to the user what needs to be retried)
            fullname = sanitize.strip_html(fullname)
            if not fullname:
                raise ValidationValueError("Full name field cannot be empty")
            if email:
                validate_email(email)  # Will raise a ValidationError if email invalid

        if contrib_dict["id"]:
            contributor = User.load(contrib_dict["id"])
        else:
            try:
                contributor = User.create_unregistered(fullname=fullname, email=email)
                contributor.save()
            except ValidationValueError:
                ## FIXME: This suppresses an exception if ID not found & new validation fails; get_user will return None
                contributor = get_user(email=email)

        # Add unclaimed record if necessary
        if not contributor.is_registered and node._primary_key not in contributor.unclaimed_records:
            contributor.add_unclaimed_record(node=node, referrer=auth.user, given_name=fullname, email=email)
            contributor.save()

        contribs.append(
            {"user": contributor, "visible": visible, "permissions": expand_permissions(contrib_dict.get("permission"))}
        )
    return contribs
Beispiel #12
0
def save_bare_users(page_size=20000):
    print 'Starting {}...'.format(sys._getframe().f_code.co_name)
    count = 0
    start = datetime.now()
    total = MODMUser.find().count()

    while count < total:
        with transaction.atomic():
            users = []
            for modm_user in MODMUser.find().sort(
                    '-date_registered')[count:count + page_size]:
                guid = Guid.objects.get(guid=modm_user._id)
                user_fields = dict(_guid_id=guid.pk, **modm_user.to_storage())

                cleaned_user_fields = {
                    key: user_fields[key]
                    for key in user_fields if key not in user_key_blacklist
                }

                for k, v in cleaned_user_fields.iteritems():
                    if isinstance(v, datetime):
                        cleaned_user_fields[k] = pytz.utc.localize(v)

                cleaned_user_fields = {
                    k: v
                    for k, v in cleaned_user_fields.iteritems()
                    if v is not None
                }
                users.append(User(**cleaned_user_fields))
                count += 1
                if count % page_size == 0 or count == total:
                    then = datetime.now()
                    print 'Saving users {} through {}...'.format(
                        count - page_size, count)
                    woot = User.objects.bulk_create(users)
                    for wit in woot:
                        modm_to_django[wit._guid.guid] = wit.pk
                    now = datetime.now()
                    print 'Done with {} users in {} seconds...'.format(
                        len(woot), (now - then).total_seconds())
                    users = None
                    woot = None
                    guid = None
                    user_fields = None
                    cleaned_user_fields = None
                    trash = gc.collect()
                    print 'Took out {} trashes'.format(trash)

    print 'Modm Users: {}'.format(total)
    print 'django Users: {}'.format(User.objects.all().count())
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #13
0
def find_inactive_users_with_no_inactivity_email_sent_or_queued():
    inactive_users = User.find(
        (Q('date_last_login', 'lt', datetime.utcnow() - settings.NO_LOGIN_WAIT_TIME) & Q('osf4m', 'ne', 'system_tags')) |
        (Q('date_last_login', 'lt', datetime.utcnow() - settings.NO_LOGIN_OSF4M_WAIT_TIME) & Q('osf4m', 'eq', 'system_tags'))
    )
    inactive_emails = mails.QueuedMail.find(Q('email_type', 'eq', mails.NO_LOGIN_TYPE))

    #This is done to prevent User query returns comparison to User, as equality fails
    #on datetime fields due to pymongo rounding. Instead here _id is compared.
    users_sent_id = [email.user._id for email in inactive_emails]
    inactive_ids = [user._id for user in inactive_users if user.is_active]
    users_to_send = [User.load(id) for id in (set(inactive_ids) - set(users_sent_id))]
    return users_to_send
Beispiel #14
0
def find_inactive_users_with_no_inactivity_email_sent_or_queued():
    inactive_users = User.find(
        (Q('date_last_login', 'lt', timezone.now() - settings.NO_LOGIN_WAIT_TIME) & Q('tags__name', 'ne', 'osf4m')) |
        (Q('date_last_login', 'lt', timezone.now() - settings.NO_LOGIN_OSF4M_WAIT_TIME) & Q('tags__name', 'eq', 'osf4m'))
    )
    inactive_emails = mails.QueuedMail.find(Q('email_type', 'eq', mails.NO_LOGIN_TYPE))

    #This is done to prevent User query returns comparison to User, as equality fails
    #on datetime fields due to pymongo rounding. Instead here _id is compared.
    users_sent_id = [email.user._id for email in inactive_emails]
    inactive_ids = [user._id for user in inactive_users if user.is_active]
    users_to_send = [User.load(id) for id in (set(inactive_ids) - set(users_sent_id))]
    return users_to_send
Beispiel #15
0
def save_bare_users(page_size=20000):
    print 'Starting {}...'.format(sys._getframe().f_code.co_name)
    count = 0
    start = datetime.now()
    total = MODMUser.find().count()

    while count < total:
        with transaction.atomic():
            users = []
            for modm_user in MODMUser.find().sort('-date_registered')[
                    count:count + page_size]:
                guid = Guid.objects.get(guid=modm_user._id)
                user_fields = dict(_guid_id=guid.pk, **modm_user.to_storage())

                cleaned_user_fields = {key: user_fields[key]
                                       for key in user_fields
                                       if key not in user_key_blacklist}

                for k, v in cleaned_user_fields.iteritems():
                    if isinstance(v, datetime):
                        cleaned_user_fields[k] = pytz.utc.localize(v)

                cleaned_user_fields = {k: v
                                       for k, v in
                                       cleaned_user_fields.iteritems()
                                       if v is not None}
                users.append(User(**cleaned_user_fields))
                count += 1
                if count % page_size == 0 or count == total:
                    then = datetime.now()
                    print 'Saving users {} through {}...'.format(
                        count - page_size, count)
                    woot = User.objects.bulk_create(users)
                    for wit in woot:
                        modm_to_django[wit._guid.guid] = wit.pk
                    now = datetime.now()
                    print 'Done with {} users in {} seconds...'.format(
                        len(woot), (now - then).total_seconds())
                    users = None
                    woot = None
                    guid = None
                    user_fields = None
                    cleaned_user_fields = None
                    trash = gc.collect()
                    print 'Took out {} trashes'.format(trash)

    print 'Modm Users: {}'.format(total)
    print 'django Users: {}'.format(User.objects.all().count())
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #16
0
def deserialize_contributors(node, user_dicts, auth):
    """View helper that returns a list of User objects from a list of
    serialized users (dicts). The users in the list may be registered or
    unregistered users.

    e.g. ``[{'id': 'abc123', 'registered': True, 'fullname': ..},
            {'id': None, 'registered': False, 'fullname'...},
            {'id': '123ab', 'registered': False, 'fullname': ...}]

    If a dict represents an unregistered user without an ID, creates a new
    unregistered User record.

    :param Node node: The node to add contributors to
    :param list(dict) user_dicts: List of serialized users in the format above.
    :param Auth auth:
    """

    # Add the registered contributors
    contribs = []
    for contrib_dict in user_dicts:
        fullname = contrib_dict['fullname']
        visible = contrib_dict['visible']
        email = contrib_dict.get('email')

        if contrib_dict['id']:
            contributor = User.load(contrib_dict['id'])
        else:
            try:
                contributor = User.create_unregistered(
                    fullname=fullname,
                    email=email)
                contributor.save()
            except ValidationValueError:
                contributor = get_user(email=email)

        # Add unclaimed record if necessary
        if (not contributor.is_registered
                and node._primary_key not in contributor.unclaimed_records):
            contributor.add_unclaimed_record(node=node, referrer=auth.user,
                given_name=fullname,
                email=email)
            contributor.save()
            unreg_contributor_added.send(node, contributor=contributor,
                auth=auth)

        contribs.append({
            'user': contributor,
            'visible': visible,
            'permissions': expand_permissions(contrib_dict.get('permission'))
        })
    return contribs
Beispiel #17
0
def get_user_from_cas_resp(cas_resp):
    """
    Given a CAS service validation response, attempt to retrieve user information and next action.

    :param cas_resp: the cas service validation response
    :return: the user, the external_credential, and the next action
    """

    if cas_resp.user:
        user = User.load(cas_resp.user)
        # cas returns a valid OSF user id
        if user:
            return user, None, 'authenticate'
        # cas does not return a valid OSF user id
        else:
            external_credential = validate_external_credential(cas_resp.user)
            # invalid cas response
            if not external_credential:
                return None, None, None
            # cas returns a valid external credential
            user = get_user(
                external_id_provider=external_credential['provider'],
                external_id=external_credential['id'])
            # existing user found
            if user:
                return user, external_credential, 'authenticate'
            # user first time login through external identity provider
            else:
                return None, external_credential, 'external_first_login'
Beispiel #18
0
def send_claim_registered_email(claimer, unreg_user, node, throttle=24 * 3600):
    unclaimed_record = unreg_user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = web_url_for(
        'claim_user_registered',
        uid=unreg_user._primary_key,
        pid=node._primary_key,
        token=unclaimed_record['token'],
        _external=True,
    )
    timestamp = unclaimed_record.get('last_sent')
    if throttle_period_expired(timestamp, throttle):
        # Send mail to referrer, telling them to forward verification link to claimer
        mails.send_mail(
            referrer.username,
            mails.FORWARD_INVITE_REGiSTERED,
            user=unreg_user,
            referrer=referrer,
            node=node,
            claim_url=claim_url,
            fullname=unclaimed_record['name'],
        )
        unclaimed_record['last_sent'] = get_timestamp()
        unreg_user.save()
    # Send mail to claimer, telling them to wait for referrer
    mails.send_mail(
        claimer.username,
        mails.PENDING_VERIFICATION_REGISTERED,
        fullname=claimer.fullname,
        referrer=referrer,
        node=node,
    )
Beispiel #19
0
def save_bare_system_tags(page_size=10000):
    print 'Starting save_bare_system_tags...'
    start = datetime.now()

    things = list(MODMNode.find(MQ('system_tags', 'ne', [])).sort(
        '-_id')) + list(MODMUser.find(MQ('system_tags', 'ne', [])).sort(
            '-_id'))

    system_tag_ids = []
    for thing in things:
        for system_tag in thing.system_tags:
            system_tag_ids.append(system_tag)

    unique_system_tag_ids = set(system_tag_ids)

    total = len(unique_system_tag_ids)

    system_tags = []
    for system_tag_id in unique_system_tag_ids:
        system_tags.append(Tag(_id=system_tag_id,
                               lower=system_tag_id.lower(),
                               system=True))

    woot = Tag.objects.bulk_create(system_tags)

    print 'MODM System Tags: {}'.format(total)
    print 'django system tags: {}'.format(Tag.objects.filter(system=
                                                             True).count())
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #20
0
    def setUpClass(cls):
        super(TestVarnish, cls).setUpClass()
        username = uuid.uuid4()
        cls.user = User.create_confirmed(username='******'.format(
            str(username)),
                                         password='******',
                                         fullname='Mocha Test User')
        cls.user.save()
        cls.authorization = HTTPBasicAuth(cls.user.username, 'password')

        small = 5
        large = 10

        components = [[[
            range(small, random.randint(small, large))
            for x in range(small, random.randint(small, large))
        ] for y in range(small, random.randint(small, large))]
                      for z in range(small, random.randint(small, large))]

        number_of_projects = random.randint(1, 11)
        number_of_tags = random.randint(1, 11)
        number_of_users = random.randint(1, 11)

        for i in range(number_of_projects):
            name = ''
            create_fake_project(cls.user, number_of_users,
                                random.choice(['public', 'private']),
                                components, name, number_of_tags, None, False)
Beispiel #21
0
    def setUpClass(cls):
        super(TestVarnish, cls).setUpClass()
        username = uuid.uuid4()
        cls.user = User.create_confirmed(
            username='******'.format(str(username)),
            password='******',
            fullname='Mocha Test User')
        cls.user.save()
        cls.authorization = HTTPBasicAuth(cls.user.username, 'password')

        small = 5
        large = 10

        components = [[[range(small, random.randint(small, large))
                        for x in range(small, random.randint(small, large))]
                       for y in range(small, random.randint(small, large))]
                      for z in range(small, random.randint(small, large))]

        number_of_projects = random.randint(1, 11)
        number_of_tags = random.randint(1, 11)
        number_of_users = random.randint(1, 11)

        for i in range(number_of_projects):
            name = ''
            create_fake_project(cls.user, number_of_users,
                                random.choice(['public', 'private']),
                                components, name, number_of_tags, None, False)
Beispiel #22
0
def get_node_contributors_abbrev(auth, node, **kwargs):
    anonymous = has_anonymous_link(node, auth)
    formatter = "surname"
    max_count = kwargs.get("max_count", 3)
    if "user_ids" in kwargs:
        users = [User.load(user_id) for user_id in kwargs["user_ids"] if user_id in node.visible_contributor_ids]
    else:
        users = node.visible_contributors

    if anonymous or not node.can_view(auth):
        raise HTTPError(http.FORBIDDEN)

    contributors = []

    n_contributors = len(users)
    others_count = ""

    for index, user in enumerate(users[:max_count]):

        if index == max_count - 1 and len(users) > max_count:
            separator = " &"
            others_count = str(n_contributors - 3)
        elif index == len(users) - 1:
            separator = ""
        elif index == len(users) - 2:
            separator = " &"
        else:
            separator = ","
        contributor = user.get_summary(formatter)
        contributor["user_id"] = user._primary_key
        contributor["separator"] = separator

        contributors.append(contributor)

    return {"contributors": contributors, "others_count": others_count}
Beispiel #23
0
def send_claim_registered_email(claimer, unreg_user, node, throttle=24 * 3600):
    unclaimed_record = unreg_user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = web_url_for(
        'claim_user_registered',
        uid=unreg_user._primary_key,
        pid=node._primary_key,
        token=unclaimed_record['token'],
        _external=True,
    )
    timestamp = unclaimed_record.get('last_sent')
    if throttle_period_expired(timestamp, throttle):
        # Send mail to referrer, telling them to forward verification link to claimer
        mails.send_mail(
            referrer.username,
            mails.FORWARD_INVITE_REGiSTERED,
            user=unreg_user,
            referrer=referrer,
            node=node,
            claim_url=claim_url,
            fullname=unclaimed_record['name'],
        )
        unclaimed_record['last_sent'] = get_timestamp()
        unreg_user.save()
    # Send mail to claimer, telling them to wait for referrer
    mails.send_mail(
        claimer.username,
        mails.PENDING_VERIFICATION_REGISTERED,
        fullname=claimer.fullname,
        referrer=referrer,
        node=node,
    )
Beispiel #24
0
def project_removecontributor(auth, node, **kwargs):

    contributor = User.load(request.json['id'])
    if contributor is None:
        raise HTTPError(http.BAD_REQUEST)

    # Forbidden unless user is removing herself
    if not node.has_permission(auth.user, 'admin'):
        if auth.user != contributor:
            raise HTTPError(http.FORBIDDEN)

    outcome = node.remove_contributor(
        contributor=contributor, auth=auth,
    )

    if outcome:
        if auth.user == contributor:
            status.push_status_message('Removed self from project', 'info')
            return {'redirectUrl': web_url_for('dashboard')}
        status.push_status_message('Contributor removed', 'info')
        return {}

    raise HTTPError(
        http.BAD_REQUEST,
        data={
            'message_long': (
                '{0} must have at least one contributor with admin '
                'rights'.format(
                    node.project_or_component.capitalize()
                )
            )
        }
    )
Beispiel #25
0
def project_before_remove_contributor(auth, node, **kwargs):

    contributor = User.load(request.json.get('id'))

    # Forbidden unless user is removing herself
    if not node.has_permission(auth.user, 'admin'):
        if auth.user != contributor:
            raise HTTPError(http.FORBIDDEN)

    if len(node.visible_contributor_ids) == 1 \
            and node.visible_contributor_ids[0] == contributor._id:
        raise HTTPError(http.FORBIDDEN, data={
            'message_long': 'Must have at least one bibliographic contributor'
        })

    prompts = node.callback(
        'before_remove_contributor', removed=contributor,
    )

    if auth.user == contributor:
        prompts.insert(
            0,
            'Are you sure you want to remove yourself from this project?'
        )

    return {'prompts': prompts}
Beispiel #26
0
def get_user_from_cas_resp(cas_resp):
    """
    Given a CAS service validation response, attempt to retrieve user information and next action.

    :param cas_resp: the cas service validation response
    :return: the user, the external_credential, and the next action
    """

    if cas_resp.user:
        user = User.load(cas_resp.user)
        # cas returns a valid OSF user id
        if user:
            return user, None, 'authenticate'
        # cas does not return a valid OSF user id
        else:
            external_credential = validate_external_credential(cas_resp.user)
            # invalid cas response
            if not external_credential:
                return None, None, None
            # cas returns a valid external credential
            user = get_user(external_id_provider=external_credential['provider'],
                            external_id=external_credential['id'])
            # existing user found
            if user:
                return user, external_credential, 'authenticate'
            # user first time login through external identity provider
            else:
                return None, external_credential, 'external_first_login'
Beispiel #27
0
def project_before_remove_contributor(auth, node, **kwargs):

    contributor = User.load(request.json.get('id'))

    # Forbidden unless user is removing herself
    if not node.has_permission(auth.user, 'admin'):
        if auth.user != contributor:
            raise HTTPError(http.FORBIDDEN)

    if len(node.visible_contributor_ids) == 1 \
            and node.visible_contributor_ids[0] == contributor._id:
        raise HTTPError(http.FORBIDDEN,
                        data={
                            'message_long':
                            'Must have at least one bibliographic contributor'
                        })

    prompts = node.callback(
        'before_remove_contributor',
        removed=contributor,
    )

    if auth.user == contributor:
        prompts.insert(
            0, 'Are you sure you want to remove yourself from this project?')

    return {'prompts': prompts}
Beispiel #28
0
def save_bare_system_tags(page_size=10000):
    print 'Starting save_bare_system_tags...'
    start = datetime.now()

    things = list(MODMNode.find(MQ(
        'system_tags', 'ne', [])).sort('-_id')) + list(
            MODMUser.find(MQ('system_tags', 'ne', [])).sort('-_id'))

    system_tag_ids = []
    for thing in things:
        for system_tag in thing.system_tags:
            system_tag_ids.append(system_tag)

    unique_system_tag_ids = set(system_tag_ids)

    total = len(unique_system_tag_ids)

    system_tags = []
    for system_tag_id in unique_system_tag_ids:
        system_tags.append(
            Tag(_id=system_tag_id, lower=system_tag_id.lower(), system=True))

    woot = Tag.objects.bulk_create(system_tags)

    print 'MODM System Tags: {}'.format(total)
    print 'django system tags: {}'.format(
        Tag.objects.filter(system=True).count())
    print 'Done with {} in {} seconds...'.format(
        sys._getframe().f_code.co_name,
        (datetime.now() - start).total_seconds())
Beispiel #29
0
def send_claim_registered_email(claimer, unclaimed_user, node, throttle=24 * 3600):
    """
    A registered user claiming the unclaimed user account as an contributor to a project.
    Send an email for claiming the account to the referrer and notify the claimer.

    :param claimer: the claimer
    :param unclaimed_user: the user account to claim
    :param node: the project node where the user account is claimed
    :param throttle: the time period in seconds before another claim for the account can be made
    :return:
    :raise: http.BAD_REQUEST
    """

    unclaimed_record = unclaimed_user.get_unclaimed_record(node._primary_key)

    # check throttle
    timestamp = unclaimed_record.get('last_sent')
    if not throttle_period_expired(timestamp, throttle):
        raise HTTPError(http.BAD_REQUEST, data=dict(
            message_long='User account can only be claimed with an existing user once every 24 hours'
        ))

    # roll the valid token for each email, thus user cannot change email and approve a different email address
    verification_key = generate_verification_key(verification_type='claim')
    unclaimed_record['token'] = verification_key['token']
    unclaimed_record['expires'] = verification_key['expires']
    unclaimed_record['claimer_email'] = claimer.username
    unclaimed_user.save()

    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = web_url_for(
        'claim_user_registered',
        uid=unclaimed_user._primary_key,
        pid=node._primary_key,
        token=unclaimed_record['token'],
        _external=True,
    )

    # Send mail to referrer, telling them to forward verification link to claimer
    mails.send_mail(
        referrer.username,
        mails.FORWARD_INVITE_REGISTERED,
        user=unclaimed_user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        fullname=unclaimed_record['name'],
    )
    unclaimed_record['last_sent'] = get_timestamp()
    unclaimed_user.save()

    # Send mail to claimer, telling them to wait for referrer
    mails.send_mail(
        claimer.username,
        mails.PENDING_VERIFICATION_REGISTERED,
        fullname=claimer.fullname,
        referrer=referrer,
        node=node,
    )
Beispiel #30
0
def send_claim_email(email, user, node, notify=True, throttle=24 * 3600):
    """Send an email for claiming a user account. Either sends to the given email
    or the referrer's email, depending on the email address provided.

    :param str email: The address given in the claim user form
    :param User user: The User record to claim.
    :param Node node: The node where the user claimed their account.
    :param bool notify: If True and an email is sent to the referrer, an email
        will also be sent to the invited user about their pending verification.
    :param int throttle: Time period (in seconds) after the referrer is
        emailed during which the referrer will not be emailed again.

    """
    claimer_email = email.lower().strip()

    unclaimed_record = user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = user.get_claim_url(node._primary_key, external=True)
    # If given email is the same provided by user, just send to that email
    if unclaimed_record.get('email') == claimer_email:
        mail_tpl = mails.INVITE
        to_addr = claimer_email
        unclaimed_record['claimer_email'] = claimer_email
        user.save()
    else:  # Otherwise have the referrer forward the email to the user
        # roll the valid token for each email, thus user cannot change email and approve a different email address
        timestamp = unclaimed_record.get('last_sent')
        if not throttle_period_expired(timestamp, throttle):
            raise HTTPError(400, data=dict(
                message_long='User account can only be claimed with an existing user once every 24 hours'
            ))
        unclaimed_record['last_sent'] = get_timestamp()
        unclaimed_record['token'] = generate_confirm_token()
        unclaimed_record['claimer_email'] = claimer_email
        user.save()
        claim_url = user.get_claim_url(node._primary_key, external=True)
        if notify:
            pending_mail = mails.PENDING_VERIFICATION
            mails.send_mail(
                claimer_email,
                pending_mail,
                user=user,
                referrer=referrer,
                fullname=unclaimed_record['name'],
                node=node
            )
        mail_tpl = mails.FORWARD_INVITE
        to_addr = referrer.username
    mails.send_mail(
        to_addr,
        mail_tpl,
        user=user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        email=claimer_email,
        fullname=unclaimed_record['name']
    )
    return to_addr
Beispiel #31
0
def send_claim_email(email, user, node, notify=True, throttle=24 * 3600):
    """Send an email for claiming a user account. Either sends to the given email
    or the referrer's email, depending on the email address provided.

    :param str email: The address given in the claim user form
    :param User user: The User record to claim.
    :param Node node: The node where the user claimed their account.
    :param bool notify: If True and an email is sent to the referrer, an email
        will also be sent to the invited user about their pending verification.
    :param int throttle: Time period (in seconds) after the referrer is
        emailed during which the referrer will not be emailed again.

    """
    claimer_email = email.lower().strip()

    unclaimed_record = user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = user.get_claim_url(node._primary_key, external=True)
    # If given email is the same provided by user, just send to that email
    if unclaimed_record.get('email') == claimer_email:
        mail_tpl = mails.INVITE
        to_addr = claimer_email
        unclaimed_record['claimer_email'] = claimer_email
        user.save()
    else:  # Otherwise have the referrer forward the email to the user
        # roll the valid token for each email, thus user cannot change email and approve a different email address
        timestamp = unclaimed_record.get('last_sent')
        if not throttle_period_expired(timestamp, throttle):
            raise HTTPError(400, data=dict(
                message_long='User account can only be claimed with an existing user once every 24 hours'
            ))
        unclaimed_record['last_sent'] = get_timestamp()
        unclaimed_record['token'] = generate_confirm_token()
        unclaimed_record['claimer_email'] = claimer_email
        user.save()
        claim_url = user.get_claim_url(node._primary_key, external=True)
        if notify:
            pending_mail = mails.PENDING_VERIFICATION
            mails.send_mail(
                claimer_email,
                pending_mail,
                user=user,
                referrer=referrer,
                fullname=unclaimed_record['name'],
                node=node
            )
        mail_tpl = mails.FORWARD_INVITE
        to_addr = referrer.username
    mails.send_mail(
        to_addr,
        mail_tpl,
        user=user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        email=claimer_email,
        fullname=unclaimed_record['name']
    )
    return to_addr
Beispiel #32
0
def send_claim_registered_email(claimer, unclaimed_user, node, throttle=24 * 3600):
    """
    A registered user claiming the unclaimed user account as an contributor to a project.
    Send an email for claiming the account to the referrer and notify the claimer.

    :param claimer: the claimer
    :param unclaimed_user: the user account to claim
    :param node: the project node where the user account is claimed
    :param throttle: the time period in seconds before another claim for the account can be made
    :return:
    :raise: http.BAD_REQUEST
    """

    unclaimed_record = unclaimed_user.get_unclaimed_record(node._primary_key)

    # check throttle
    timestamp = unclaimed_record.get('last_sent')
    if not throttle_period_expired(timestamp, throttle):
        raise HTTPError(http.BAD_REQUEST, data=dict(
            message_long='User account can only be claimed with an existing user once every 24 hours'
        ))

    # roll the valid token for each email, thus user cannot change email and approve a different email address
    verification_key = generate_verification_key(verification_type='claim')
    unclaimed_record['token'] = verification_key['token']
    unclaimed_record['expires'] = verification_key['expires']
    unclaimed_record['claimer_email'] = claimer.username
    unclaimed_user.save()

    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = web_url_for(
        'claim_user_registered',
        uid=unclaimed_user._primary_key,
        pid=node._primary_key,
        token=unclaimed_record['token'],
        _external=True,
    )

    # Send mail to referrer, telling them to forward verification link to claimer
    mails.send_mail(
        referrer.username,
        mails.FORWARD_INVITE_REGISTERED,
        user=unclaimed_user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        fullname=unclaimed_record['name'],
    )
    unclaimed_record['last_sent'] = get_timestamp()
    unclaimed_user.save()

    # Send mail to claimer, telling them to wait for referrer
    mails.send_mail(
        claimer.username,
        mails.PENDING_VERIFICATION_REGISTERED,
        fullname=claimer.fullname,
        referrer=referrer,
        node=node,
    )
Beispiel #33
0
 def test_register(self):
     auth.register('*****@*****.**', 'gattaca', fullname="Rosie Franklin")
     user = User.find_one(Q('username', 'eq', '*****@*****.**'))
     # The password should be set
     assert_true(user.check_password('gattaca'))
     assert_equal(user.fullname, "Rosie Franklin")
     assert_equal(user.username, '*****@*****.**')
     assert_in("*****@*****.**", user.emails)
Beispiel #34
0
def claim_user_registered(auth, node, **kwargs):
    """View that prompts user to enter their password in order to claim
    contributorship on a project.

    A user must be logged in.
    """
    current_user = auth.user

    sign_out_url = web_url_for('auth_login', logout=True, next=request.url)
    if not current_user:
        return redirect(sign_out_url)
    # Logged in user should not be a contributor the project
    if node.is_contributor(current_user):
        logout_url = web_url_for('auth_logout', redirect_url=request.url)
        data = {
            'message_short': 'Already a contributor',
            'message_long': ('The logged-in user is already a contributor to this '
                'project. Would you like to <a href="{}">log out</a>?').format(logout_url)
        }
        raise HTTPError(http.BAD_REQUEST, data=data)
    uid, pid, token = kwargs['uid'], kwargs['pid'], kwargs['token']
    unreg_user = User.load(uid)
    if not verify_claim_token(unreg_user, token, pid=node._primary_key):
        raise HTTPError(http.BAD_REQUEST)

    # Store the unreg_user data on the session in case the user registers
    # a new account
    session.data['unreg_user'] = {
        'uid': uid, 'pid': pid, 'token': token
    }

    form = PasswordForm(request.form)
    if request.method == 'POST':
        if form.validate():
            if current_user.check_password(form.password.data):
                node.replace_contributor(old=unreg_user, new=current_user)
                node.save()
                status.push_status_message(
                    'You are now a contributor to this project.',
                    kind='success',
                    trust=False
                )
                return redirect(node.url)
            else:
                status.push_status_message(language.LOGIN_FAILED, kind='warning', trust=False)
        else:
            forms.push_errors_to_status(form.errors)
    if is_json_request():
        form_ret = forms.utils.jsonify(form)
        user_ret = profile_utils.serialize_user(current_user, full=False)
    else:
        form_ret = form
        user_ret = current_user
    return {
        'form': form_ret,
        'user': user_ret,
        'signOutUrl': sign_out_url
    }
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = User.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if not form.validate():
            forms.push_errors_to_status(form.errors)
        elif settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(request.form.get('g-recaptcha-response'), remote_ip=request.remote_addr):
            status.push_status_message('Invalid captcha supplied.', kind='error')
        else:
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind='success', trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('view_project', pid=pid, _absolute=True),
                username=user.username,
                verification_key=user.verification_key
            ))

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #36
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect(web_url_for('auth_login'))
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get(
        'claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = security.random_string(20)
            user.save()
            # Authenticate user and redirect to project page
            node = Node.load(pid)
            status.push_status_message(
                language.CLAIMED_CONTRIBUTOR.format(node=node),
                kind='success',
                trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(
                cas.get_login_url(web_url_for('user_profile', _absolute=True),
                                  auto=True,
                                  username=user.username,
                                  verification_key=user.verification_key))
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #37
0
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = User.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)

    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind='success', trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('view_project', pid=pid, _absolute=True),
                username=user.username,
                verification_key=user.verification_key
            ))
        else:
            forms.push_errors_to_status(form.errors)

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #38
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect(web_url_for('auth_login'))
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = security.random_string(20)
            user.save()
            # Authenticate user and redirect to project page
            node = Node.load(pid)
            status.push_status_message(language.CLAIMED_CONTRIBUTOR.format(node=node),
                                       kind='success',
                                       trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('user_profile', _absolute=True),
                auto=True,
                username=user.username,
                verification_key=user.verification_key
            ))
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #39
0
def claim_user_registered(auth, node, **kwargs):
    """
    View that prompts user to enter their password in order to claim being a contributor on a project.
    A user must be logged in.
    """

    current_user = auth.user

    sign_out_url = web_url_for("auth_register", logout=True, next=request.url)
    if not current_user:
        return redirect(sign_out_url)

    # Logged in user should not be a contributor the project
    if node.is_contributor(current_user):
        logout_url = web_url_for("auth_logout", redirect_url=request.url)
        data = {
            "message_short": "Already a contributor",
            "message_long": (
                "The logged-in user is already a contributor to this "
                'project. Would you like to <a href="{}">log out</a>?'
            ).format(logout_url),
        }
        raise HTTPError(http.BAD_REQUEST, data=data)

    uid, pid, token = kwargs["uid"], kwargs["pid"], kwargs["token"]
    unreg_user = User.load(uid)
    if not verify_claim_token(unreg_user, token, pid=node._primary_key):
        error_data = {
            "message_short": "Invalid url.",
            "message_long": "The token in the URL is invalid or has expired.",
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # Store the unreg_user data on the session in case the user registers
    # a new account
    session.data["unreg_user"] = {"uid": uid, "pid": pid, "token": token}

    form = PasswordForm(request.form)
    if request.method == "POST":
        if form.validate():
            if current_user.check_password(form.password.data):
                node.replace_contributor(old=unreg_user, new=current_user)
                node.save()
                status.push_status_message("You are now a contributor to this project.", kind="success", trust=False)
                return redirect(node.url)
            else:
                status.push_status_message(language.LOGIN_FAILED, kind="warning", trust=False)
        else:
            forms.push_errors_to_status(form.errors)
    if is_json_request():
        form_ret = forms.utils.jsonify(form)
        user_ret = profile_utils.serialize_user(current_user, full=False)
    else:
        form_ret = form
        user_ret = current_user
    return {"form": form_ret, "user": user_ret, "signOutUrl": sign_out_url}
Beispiel #40
0
 def test_register(self):
     auth.register('*****@*****.**',
                   'gattaca',
                   fullname="Rosie Franklin")
     user = User.find_one(Q('username', 'eq', '*****@*****.**'))
     # The password should be set
     assert_true(user.check_password('gattaca'))
     assert_equal(user.fullname, "Rosie Franklin")
     assert_equal(user.username, '*****@*****.**')
     assert_in("*****@*****.**", user.emails)
Beispiel #41
0
def project_remove_contributor(auth, **kwargs):
    """Remove a contributor from a list of nodes.

    :param Auth auth: Consolidated authorization
    :raises: HTTPError(400) if contributors to be removed are not in list
        or if no admin users would remain after changes were applied

    """
    contributor_id = request.get_json()['contributorID']
    node_ids = request.get_json()['nodeIDs']
    contributor = User.load(contributor_id)
    if contributor is None:
        raise HTTPError(http.BAD_REQUEST,
                        data={'message_long': 'Contributor not found.'})
    redirect_url = {}
    parent_id = node_ids[0]
    for node_id in node_ids:
        # Update permissions and order
        node = Node.load(node_id)

        # Forbidden unless user is removing herself
        if not node.has_permission(auth.user, 'admin'):
            if auth.user != contributor:
                raise HTTPError(http.FORBIDDEN)

        if len(node.visible_contributor_ids) == 1 \
                and node.visible_contributor_ids[0] == contributor._id:
            raise HTTPError(
                http.FORBIDDEN,
                data={
                    'message_long':
                    'Must have at least one bibliographic contributor'
                })

        nodes_removed = node.remove_contributor(contributor, auth=auth)
        # remove_contributor returns false if there is not one admin or visible contributor left after the move.
        if not nodes_removed:
            raise HTTPError(
                http.BAD_REQUEST,
                data={'message_long': 'Could not remove contributor.'})

        # On parent node, if user has removed herself from project, alert; redirect to user
        # dashboard if node is private, else node dashboard
        if not node.is_contributor(auth.user) and node_id == parent_id:
            status.push_status_message(
                'You have removed yourself as a contributor from this project',
                kind='success',
                trust=False)
            if node.is_public:
                redirect_url = {'redirectUrl': node.url}
            # Else stay on current page
            else:
                redirect_url = {'redirectUrl': web_url_for('dashboard')}
    return redirect_url
Beispiel #42
0
def migrate_users(index):
    logger.info("Migrating users to index: {}".format(index))
    n_migr = 0
    n_iter = 0
    for user in User.find():
        if user.is_active:
            search.update_user(user, index=index)
            n_migr += 1
        n_iter += 1

    logger.info('Users iterated: {0}\nUsers migrated: {1}'.format(n_iter, n_migr))
Beispiel #43
0
def migrate_users(index):
    logger.info("Migrating users to index: {}".format(index))
    n_migr = 0
    n_iter = 0
    for user in User.find():
        if user.is_active:
            search.update_user(user, index=index)
            n_migr += 1
        n_iter += 1

    logger.info('Users iterated: {0}\nUsers migrated: {1}'.format(
        n_iter, n_migr))
Beispiel #44
0
def send_claim_email(email, user, node, notify=True, throttle=24 * 3600):
    """Send an email for claiming a user account. Either sends to the given email
    or the referrer's email, depending on the email address provided.

    :param str email: The address given in the claim user form
    :param User user: The User record to claim.
    :param Node node: The node where the user claimed their account.
    :param bool notify: If True and an email is sent to the referrer, an email
        will also be sent to the invited user about their pending verification.
    :param int throttle: Time period (in seconds) after the referrer is
        emailed during which the referrer will not be emailed again.

    """
    invited_email = email.lower().strip()

    unclaimed_record = user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = user.get_claim_url(node._primary_key, external=True)
    # If given email is the same provided by user, just send to that email
    if unclaimed_record.get('email', None) == invited_email:
        mail_tpl = mails.INVITE
        to_addr = invited_email
    else:  # Otherwise have the referrer forward the email to the user
        if notify:
            pending_mail = mails.PENDING_VERIFICATION
            mails.send_mail(
                invited_email,
                pending_mail,
                user=user,
                referrer=referrer,
                fullname=unclaimed_record['name'],
                node=node
            )
        timestamp = unclaimed_record.get('last_sent')
        if throttle_period_expired(timestamp, throttle):
            unclaimed_record['last_sent'] = get_timestamp()
            user.save()
        else:  # Don't send the email to the referrer
            return
        mail_tpl = mails.FORWARD_INVITE
        to_addr = referrer.username
    mails.send_mail(
        to_addr,
        mail_tpl,
        user=user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        email=invited_email,
        fullname=unclaimed_record['name']
    )
    return to_addr
Beispiel #45
0
def send_claim_email(email, user, node, notify=True, throttle=24 * 3600):
    """Send an email for claiming a user account. Either sends to the given email
    or the referrer's email, depending on the email address provided.

    :param str email: The address given in the claim user form
    :param User user: The User record to claim.
    :param Node node: The node where the user claimed their account.
    :param bool notify: If True and an email is sent to the referrer, an email
        will also be sent to the invited user about their pending verification.
    :param int throttle: Time period (in seconds) after the referrer is
        emailed during which the referrer will not be emailed again.

    """
    invited_email = email.lower().strip()

    unclaimed_record = user.get_unclaimed_record(node._primary_key)
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = user.get_claim_url(node._primary_key, external=True)
    # If given email is the same provided by user, just send to that email
    if unclaimed_record.get('email', None) == invited_email:
        mail_tpl = mails.INVITE
        to_addr = invited_email
    else:  # Otherwise have the referrer forward the email to the user
        if notify:
            pending_mail = mails.PENDING_VERIFICATION
            mails.send_mail(
                invited_email,
                pending_mail,
                user=user,
                referrer=referrer,
                fullname=unclaimed_record['name'],
                node=node
            )
        timestamp = unclaimed_record.get('last_sent')
        if throttle_period_expired(timestamp, throttle):
            unclaimed_record['last_sent'] = get_timestamp()
            user.save()
        else:  # Don't send the email to the referrer
            return
        mail_tpl = mails.FORWARD_INVITE
        to_addr = referrer.username
    mails.send_mail(
        to_addr,
        mail_tpl,
        user=user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        email=invited_email,
        fullname=unclaimed_record['name']
    )
    return to_addr
Beispiel #46
0
def claim_user_post(node, **kwargs):
    """
    View for claiming a user from the X-editable form on a project page.

    :param node: the project node
    :return:
    """

    request_data = request.json

    # The unclaimed user
    unclaimed_user = User.load(request_data['pk'])
    unclaimed_data = unclaimed_user.get_unclaimed_record(node._primary_key)

    # Claimer is not logged in and submit her/his email through X-editable, stored in `request_data['value']`
    if 'value' in request_data:
        email = request_data['value'].lower().strip()
        claimer = get_user(email=email)
        # registered user
        if claimer and claimer.is_registered:
            send_claim_registered_email(claimer, unclaimed_user, node)
        # unregistered user
        else:
            send_claim_email(email, unclaimed_user, node, notify=True)
    # Claimer is logged in with confirmed identity stored in `request_data['claimerId']`
    elif 'claimerId' in request_data:
        claimer_id = request_data['claimerId']
        claimer = User.load(claimer_id)
        send_claim_registered_email(claimer, unclaimed_user, node)
        email = claimer.username
    else:
        raise HTTPError(http.BAD_REQUEST)

    return {
        'status': 'success',
        'email': email,
        'fullname': unclaimed_data['name']
    }
Beispiel #47
0
def project_remove_contributor(auth, **kwargs):
    """Remove a contributor from a list of nodes.

    :param Auth auth: Consolidated authorization
    :raises: HTTPError(400) if contributors to be removed are not in list
        or if no admin users would remain after changes were applied

    """
    contributor_id = request.get_json()['contributorID']
    node_ids = request.get_json()['nodeIDs']
    contributor = User.load(contributor_id)
    if contributor is None:
        raise HTTPError(http.BAD_REQUEST, data={'message_long': 'Contributor not found.'})
    redirect_url = {}
    parent_id = node_ids[0]
    for node_id in node_ids:
        # Update permissions and order
        node = Node.load(node_id)

        # Forbidden unless user is removing herself
        if not node.has_permission(auth.user, 'admin'):
            if auth.user != contributor:
                raise HTTPError(http.FORBIDDEN)

        if len(node.visible_contributor_ids) == 1 \
                and node.visible_contributor_ids[0] == contributor._id:
            raise HTTPError(http.FORBIDDEN, data={
                'message_long': 'Must have at least one bibliographic contributor'
            })

        nodes_removed = node.remove_contributor(contributor, auth=auth)
        # remove_contributor returns false if there is not one admin or visible contributor left after the move.
        if not nodes_removed:
            raise HTTPError(http.BAD_REQUEST, data={
                'message_long': 'Could not remove contributor.'})

        # On parent node, if user has removed herself from project, alert; redirect to user
        # dashboard if node is private, else node dashboard
        if not node.is_contributor(auth.user) and node_id == parent_id:
            status.push_status_message(
                'You have removed yourself as a contributor from this project',
                kind='success',
                trust=False
            )
            if node.is_public:
                redirect_url = {'redirectUrl': node.url}
            # Else stay on current page
            else:
                redirect_url = {'redirectUrl': web_url_for('dashboard')}
    return redirect_url
Beispiel #48
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect('/account/')
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    email = unclaimed_record['email']
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = form.username.data, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.save()
            # Authenticate user and redirect to project page
            response = redirect('/settings/')
            node = Node.load(pid)
            status.push_status_message(
                language.CLAIMED_CONTRIBUTOR.format(node=node), 'success')
            return authenticate(user, response)
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': email if email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #49
0
def replace_unclaimed_user_with_registered(user):
    """Listens for the user_registered signal. If unreg_user is stored in the
    session, then the current user is trying to claim themselves as a contributor.
    Replaces the old, unregistered contributor with the newly registered
    account.

    """
    unreg_user_info = session.data.get("unreg_user")
    if unreg_user_info:
        unreg_user = User.load(unreg_user_info["uid"])
        pid = unreg_user_info["pid"]
        node = Node.load(pid)
        node.replace_contributor(old=unreg_user, new=user)
        node.save()
        status.push_status_message("Successfully claimed contributor.", kind="success", trust=False)
Beispiel #50
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect('/account/')
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    email = unclaimed_record['email']
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.save()
            # Authenticate user and redirect to project page
            response = redirect('/settings/')
            node = Node.load(pid)
            status.push_status_message(language.CLAIMED_CONTRIBUTOR.format(node=node),
                'success')
            return authenticate(user, response)
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': email if email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
Beispiel #51
0
def replace_unclaimed_user_with_registered(user):
    """Listens for the user_registered signal. If unreg_user is stored in the
    session, then the current user is trying to claim themselves as a contributor.
    Replaces the old, unregistered contributor with the newly registered
    account.

    """
    unreg_user_info = session.data.get('unreg_user')
    if unreg_user_info:
        unreg_user = User.load(unreg_user_info['uid'])
        pid = unreg_user_info['pid']
        node = Node.load(pid)
        node.replace_contributor(old=unreg_user, new=user)
        node.save()
        status.push_status_message(
            'Successfully claimed contributor.', kind='success', trust=False)
Beispiel #52
0
def make_response_from_ticket(ticket, service_url):
    """Given a CAS ticket and service URL, attempt to the user and return a proper
    redirect response.
    """
    service_furl = furl.furl(service_url)
    if 'ticket' in service_furl.args:
        service_furl.args.pop('ticket')
    client = get_client()
    cas_resp = client.service_validate(ticket, service_furl.url)
    if cas_resp.authenticated:
        user = User.load(cas_resp.user)
        # if we successfully authenticate and a verification key is present, invalidate it
        if user.verification_key:
            user.verification_key = None
            user.save()
        return authenticate(user, access_token=cas_resp.attributes['accessToken'], response=redirect(service_furl.url))
    # Ticket could not be validated, unauthorized.
    return redirect(service_furl.url)
Beispiel #53
0
def project_before_remove_contributor(auth, node, **kwargs):

    contributor = User.load(request.json.get('id'))

    # Forbidden unless user is removing herself
    if not node.has_permission(auth.user, 'admin'):
        if auth.user != contributor:
            raise HTTPError(http.FORBIDDEN)

    prompts = node.callback(
        'before_remove_contributor',
        removed=contributor,
    )

    if auth.user == contributor:
        prompts.insert(
            0, 'Are you sure you want to remove yourself from this project?')

    return {'prompts': prompts}
Beispiel #54
0
def get_node_contributors_abbrev(auth, **kwargs):
    node = kwargs['node'] or kwargs['project']

    anonymous = has_anonymous_link(node, auth)

    max_count = kwargs.get('max_count', 3)
    if 'user_ids' in kwargs:
        users = [
            User.load(user_id) for user_id in kwargs['user_ids']
            if user_id in node.visible_contributor_ids
        ]
    else:
        users = node.visible_contributors

    if anonymous or not node.can_view(auth):
        raise HTTPError(http.FORBIDDEN)

    contributors = []

    n_contributors = len(users)
    others_count = ''

    for index, user in enumerate(users[:max_count]):

        if index == max_count - 1 and len(users) > max_count:
            separator = '&nbsp;&'
            others_count = str(n_contributors - 3)
        elif index == len(users) - 1:
            separator = ''
        elif index == len(users) - 2:
            separator = '&nbsp&'
        else:
            separator = ','

        contributors.append({
            'user_id': user._primary_key,
            'separator': separator,
        })

    return {
        'contributors': contributors,
        'others_count': others_count,
    }
Beispiel #55
0
def send_claim_registered_email(claimer, unreg_user, node, throttle=24 * 3600):
    unclaimed_record = unreg_user.get_unclaimed_record(node._primary_key)
    # roll the valid token for each email, thus user cannot change email and approve a different email address
    timestamp = unclaimed_record.get('last_sent')
    if not throttle_period_expired(timestamp, throttle):
        raise HTTPError(
            400,
            data=dict(
                message_long=
                'User account can only be claimed with an existing user once every 24 hours'
            ))
    unclaimed_record['token'] = generate_confirm_token()
    unclaimed_record['claimer_email'] = claimer.username
    unreg_user.save()
    referrer = User.load(unclaimed_record['referrer_id'])
    claim_url = web_url_for(
        'claim_user_registered',
        uid=unreg_user._primary_key,
        pid=node._primary_key,
        token=unclaimed_record['token'],
        _external=True,
    )
    # Send mail to referrer, telling them to forward verification link to claimer
    mails.send_mail(
        referrer.username,
        mails.FORWARD_INVITE_REGiSTERED,
        user=unreg_user,
        referrer=referrer,
        node=node,
        claim_url=claim_url,
        fullname=unclaimed_record['name'],
    )
    unclaimed_record['last_sent'] = get_timestamp()
    unreg_user.save()
    # Send mail to claimer, telling them to wait for referrer
    mails.send_mail(
        claimer.username,
        mails.PENDING_VERIFICATION_REGISTERED,
        fullname=claimer.fullname,
        referrer=referrer,
        node=node,
    )
Beispiel #56
0
def get_node_contributors_abbrev(auth, node, **kwargs):
    anonymous = has_anonymous_link(node, auth)
    formatter = 'surname'
    max_count = kwargs.get('max_count', 3)
    if 'user_ids' in kwargs:
        users = [
            User.load(user_id) for user_id in kwargs['user_ids']
            if user_id in node.visible_contributor_ids
        ]
    else:
        users = node.visible_contributors

    if anonymous or not node.can_view(auth):
        raise HTTPError(http.FORBIDDEN)

    contributors = []

    n_contributors = len(users)
    others_count = ''

    for index, user in enumerate(users[:max_count]):

        if index == max_count - 1 and len(users) > max_count:
            separator = ' &'
            others_count = str(n_contributors - 3)
        elif index == len(users) - 1:
            separator = ''
        elif index == len(users) - 2:
            separator = ' &'
        else:
            separator = ','
        contributor = user.get_summary(formatter)
        contributor['user_id'] = user._primary_key
        contributor['separator'] = separator

        contributors.append(contributor)

    return {
        'contributors': contributors,
        'others_count': others_count,
    }