def get_user_by_email(email, create_pending=False):
    """finds a user based on his email address.

    :param email: The email address of the user.
    :param create_pending: If True, this function searches for external
                           users and creates a new pending User in case
                           no existing user was found.
    :return: A :class:`.User` instance or ``None`` if not exactly one
             user was found.
    """
    email = email.lower().strip()
    if not email:
        return None
    if not create_pending:
        res = User.find_all(~User.is_deleted, User.all_emails.contains(email))
    else:
        res = search_users(exact=True, include_pending=True, external=True, email=email)
    if len(res) != 1:
        return None
    user_or_identity = next(iter(res))
    if isinstance(user_or_identity, User):
        return user_or_identity
    elif not create_pending:
        return None
    # Create a new pending user
    data = user_or_identity.data
    user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=data['email'],
                address=data.get('address', ''), phone=data.get('phone', ''),
                affiliation=data.get('affiliation', ''), is_pending=True)
    db.session.add(user)
    db.session.flush()
    return user
Beispiel #2
0
def test_deletion_no_primary_email():
    # this tests setting the is_deleted property on a user with no primary email
    # very unlikely case but let's make sure we never try to set the deleted
    # flag on a None primary email.
    user = User()
    assert user.email is None
    user.is_deleted = True
Beispiel #3
0
 def _original_user(self):
     # A proper user, with an id that can be mapped directly to sqlalchemy
     if isinstance(self.id, int) or self.id.isdigit():
         return User.get(int(self.id))
     # A user who had no real fossir account but an ldap identifier/email.
     # In this case we try to find his real user and replace the ID of this object
     # with that user's ID.
     data = self.id.split(':')
     # TODO: Once everything is in SQLAlchemy this whole thing needs to go away!
     user = None
     if data[0] == 'LDAP':
         identifier = data[1]
         email = data[2]
         # You better have only one ldap provider or at least different identifiers ;)
         identity = Identity.find_first(Identity.provider != 'fossir',
                                        Identity.identifier == identifier)
         if identity:
             user = identity.user
     elif data[0] == 'Nice':
         email = data[1]
     else:
         return None
     if not user:
         user = User.find_first(User.all_emails.contains(email))
     if user:
         self._old_id = self.id
         self.id = str(user.id)
         logger.info("Updated legacy user id (%s => %s)", self._old_id,
                     self.id)
     return user
Beispiel #4
0
def test_title(db):
    user = User(first_name='Guinea', last_name='Pig')
    db.session.add(user)
    db.session.flush()
    assert user.title == ''
    user.title = UserTitle.prof
    assert user.title == UserTitle.prof.title
    assert is_lazy_string(user.title)
    assert User.find_one(title=UserTitle.prof) == user
Beispiel #5
0
def test_emails(db):
    user = User(first_name='Guinea', last_name='Pig')
    db.session.add(user)
    db.session.flush()
    assert user.email is None
    assert not user.secondary_emails
    user.email = '*****@*****.**'
    db.session.flush()
    assert user.all_emails == {'*****@*****.**'}
    user.secondary_emails.add('*****@*****.**')
    db.session.flush()
    assert user.all_emails == {'*****@*****.**', '*****@*****.**'}
Beispiel #6
0
def test_deletion(db):
    user = User(first_name='Guinea',
                last_name='Pig',
                email='*****@*****.**',
                secondary_emails=['[email protected]'])
    db.session.add(user)
    db.session.flush()
    assert not user.is_deleted
    assert all(not ue.is_user_deleted for ue in user._all_emails)
    user.is_deleted = True
    db.session.flush()
    assert all(ue.is_user_deleted for ue in user._all_emails)
Beispiel #7
0
def test_get_full_name_empty_names(first_name, last_name):
    user = User(first_name=first_name,
                last_name=last_name,
                title=UserTitle.none)
    for last_name_first, last_name_upper, abbrev_first_name in itertools.product(
        (True, False), repeat=3):
        # Just make sure it doesn't fail. We don't really care about the output.
        # It's only allowed for pending users so in most cases it only shows up
        # in the ``repr`` of such a user.
        user.get_full_name(last_name_first=last_name_first,
                           last_name_upper=last_name_upper,
                           abbrev_first_name=abbrev_first_name)
def create_user(email,
                data,
                identity=None,
                settings=None,
                other_emails=None,
                from_moderation=True):
    """Create a new user.

    This may also convert a pending user to a proper user in case the
    email address matches such a user.

    :param email: The primary email address of the user.
    :param data: The data used to populate the user.
    :param identity: An `Identity` to associate with the user.
    :param settings: A dict containing user settings.
    :param other_emails: A set of email addresses that are also used
                         to check for a pending user. They will also
                         be added as secondary emails to the user.
    :param from_moderation: Whether the user was created through the
                            moderation process or manually by an admin.
    """
    if other_emails is None:
        other_emails = set()
    if settings is None:
        settings = {}
    settings.setdefault('timezone', config.DEFAULT_TIMEZONE)
    settings.setdefault('lang', config.DEFAULT_LOCALE)
    settings.setdefault('suggest_categories', False)
    # Get a pending user if there is one
    user = User.find_first(
        ~User.is_deleted, User.is_pending,
        User.all_emails.contains(db.func.any(list({email}
                                                  | set(other_emails)))))
    if not user:
        user = User()

    if email in user.secondary_emails:
        # This can happen if there's a pending user who has a secondary email
        # for some weird reason which should now become the primary email...
        user.make_email_primary(email)
    else:
        user.email = email
    user.populate_from_dict(data)
    user.is_pending = False
    user.secondary_emails |= other_emails
    user.favorite_users.add(user)
    if identity is not None:
        user.identities.add(identity)
    db.session.add(user)
    user.settings.set_multi(settings)
    db.session.flush()
    signals.users.registered.send(user,
                                  from_moderation=from_moderation,
                                  identity=identity)
    db.session.flush()
    return user
Beispiel #9
0
 def _process_args(self):
     if not session.user:
         return
     self.user = session.user
     if 'user_id' in request.view_args:
         self.user = User.get(request.view_args['user_id'])
         if self.user is None:
             raise NotFound('This user does not exist')
         elif request.method == 'GET' and not request.is_xhr and self.flash_user_status:
             # Show messages about the user's status if it's a simple GET request
             if self.user.is_deleted:
                 if self.user.merged_into_id is not None:
                     msg = _(
                         'This user has been merged into <a href="{url}">another user</a>.'
                     )
                     flash(
                         Markup(msg).format(url=url_for(
                             request.endpoint, self.user.merged_into_user)),
                         'warning')
                 else:
                     flash(_('This user is marked as deleted.'), 'warning')
             if self.user.is_pending:
                 flash(
                     _('This user is marked as pending, i.e. it has been attached to something but never '
                       'logged in.'), 'warning')
     if not self.allow_system_user and self.user.is_system:
         return redirect(url_for('users.user_profile'))
Beispiel #10
0
 def _process(self):
     users = [User.get(int(id_)) for id_ in request.form.getlist('user_id')]
     self.user.favorite_users |= set(filter(None, users))
     tpl = get_template_module('users/_favorites.html')
     return jsonify(success=True,
                    users=[serialize_user(user) for user in users],
                    html=tpl.favorite_users_list(self.user))
def category_cleanup():
    from fossir.modules.events import Event
    janitor_user = User.get_system_user()

    logger.debug("Checking whether any categories should be cleaned up")
    for categ_id, days in config.CATEGORY_CLEANUP.iteritems():
        try:
            category = Category.get(int(categ_id), is_deleted=False)
        except KeyError:
            logger.warning("Category %s does not exist!", categ_id)
            continue

        now = now_utc()
        to_delete = Event.query.with_parent(category).filter(
            Event.created_dt < (now - timedelta(days=days))).all()
        if not to_delete:
            continue

        logger.info(
            "Category %s: %s events were created more than %s days ago and will be deleted",
            categ_id, len(to_delete), days)
        for i, event in enumerate(to_delete, 1):
            logger.info("Deleting %s", event)
            event.delete('Cleaning up category', janitor_user)
            if i % 100 == 0:
                db.session.commit()
        db.session.commit()
 def _get_breadcrumbs(self):
     if 'user_id' in request.view_args:
         user = User.get(request.view_args['user_id'])
         profile_breadcrumb = _('Profile of {name}').format(
             name=user.full_name)
     else:
         profile_breadcrumb = _('My Profile')
     return render_breadcrumbs(profile_breadcrumb)
Beispiel #13
0
 def _process(self):
     user = User.get(int(request.view_args['fav_user_id']))
     self.user.favorite_users.discard(user)
     try:
         db.session.flush()
     except StaleDataError:
         # Deleted in another transaction
         db.session.rollback()
     return jsonify(success=True)
Beispiel #14
0
 def export_user(self, user):
     if not user:
         raise HTTPAPIError('You need to be logged in', 403)
     user = User.get(self._user_id, is_deleted=False)
     if not user:
         raise HTTPAPIError('Requested user not found', 404)
     if not user.can_be_modified(user):
         raise HTTPAPIError('You do not have access to that info', 403)
     return [user.as_avatar.fossilize()]
Beispiel #15
0
def test_can_be_modified():
    user = User()
    # user can modify himself
    assert user.can_be_modified(user)
    # admin can modify anyone
    assert user.can_be_modified(User(is_admin=True))
    # normal users can't
    assert not user.can_be_modified(User())
def test_acls_invalid():
    user = User()
    proxy = SettingsProxy('foo', {'reg': None}, acls={'acl'})
    pytest.raises(ValueError, proxy.get, 'acl')
    pytest.raises(ValueError, proxy.set, 'acl', 'foo')
    pytest.raises(ValueError, proxy.acls.get, 'reg')
    pytest.raises(ValueError, proxy.acls.set, 'reg', {user})
    pytest.raises(ValueError, proxy.acls.contains_user, 'reg', user)
    pytest.raises(ValueError, proxy.acls.add_principal, 'reg', user)
    pytest.raises(ValueError, proxy.acls.remove_principal, 'reg', user)
Beispiel #17
0
    def _process(self):
        form = SearchForm(obj=FormDefaults(exact=True))
        form_data = form.data
        search_results = None
        num_of_users = User.query.count()
        num_deleted_users = User.find(is_deleted=True).count()

        if form.validate_on_submit():
            search_results = []
            exact = form_data.pop('exact')
            include_deleted = form_data.pop('include_deleted')
            include_pending = form_data.pop('include_pending')
            external = form_data.pop('external')
            form_data = {
                k: v
                for (k, v) in form_data.iteritems() if v and v.strip()
            }
            matches = search_users(exact=exact,
                                   include_deleted=include_deleted,
                                   include_pending=include_pending,
                                   external=external,
                                   allow_system_user=True,
                                   **form_data)
            for entry in matches:
                if isinstance(entry, User):
                    search_results.append(
                        UserEntry(profile_url=url_for('.user_profile', entry),
                                  user=entry,
                                  **{
                                      k: getattr(entry, k)
                                      for k in IDENTITY_ATTRIBUTES
                                  }))
                else:
                    search_results.append(
                        UserEntry(profile_url=None,
                                  user=None,
                                  full_name="{first_name} {last_name}".format(
                                      **entry.data.to_dict()),
                                  **{
                                      k: entry.data.get(k)
                                      for k in (IDENTITY_ATTRIBUTES -
                                                {'full_name'})
                                  }))
            search_results.sort(key=attrgetter('first_name', 'last_name'))

        num_reg_requests = RegistrationRequest.query.count()
        return WPUsersAdmin.render_template(
            'users_admin.html',
            'users',
            form=form,
            search_results=search_results,
            num_of_users=num_of_users,
            num_deleted_users=num_deleted_users,
            num_reg_requests=num_reg_requests)
 def _process_args(self):
     self.identity_info = load_identity_info()
     if not self.identity_info or self.identity_info['fossir_user_id'] is None:
         # Just redirect to the front page or whereever we wanted to go.
         # Probably someone simply used his browser's back button.
         flash('There is no pending login.', 'warning')
         return multipass.redirect_success()
     self.user = User.get(self.identity_info['fossir_user_id'])
     self.emails = sorted(self.user.all_emails & set(self.identity_info['data'].getlist('email')))
     self.verification_email_sent = self.identity_info.get('verification_email_sent', False)
     self.email_verified = self.identity_info['email_verified']
     self.must_choose_email = len(self.emails) != 1 and not self.email_verified
    def get_form_defaults(self):
        email = session.get('register_verified_email')
        existing_user_id = session.get('register_pending_user')
        existing_user = User.get(existing_user_id) if existing_user_id else None
        data = {'email': email}

        if existing_user:
            data.update(first_name=existing_user.first_name,
                        last_name=existing_user.last_name,
                        affiliation=existing_user.affiliation)

        return FormDefaults(**data)
Beispiel #20
0
def test_make_email_primary(db):
    user = User(first_name='Guinea', last_name='Pig', email='*****@*****.**')
    db.session.add(user)
    db.session.flush()
    with pytest.raises(ValueError):
        user.make_email_primary('*****@*****.**')
    user.secondary_emails = {'*****@*****.**', '*****@*****.**'}
    db.session.flush()
    user.make_email_primary('*****@*****.**')
    db.session.expire(user)
    assert user.email == '*****@*****.**'
    assert user.secondary_emails == {'*****@*****.**', '*****@*****.**'}
Beispiel #21
0
def undo_impersonate_user():
    """Undo an admin impersonation login and revert to the old user"""
    from fossir.modules.auth import logger
    from fossir.modules.users import User

    try:
        entry = session.pop('login_as_orig_user')
    except KeyError:
        # The user probably already switched back from another tab
        return
    user = User.get_one(entry['user_id'])
    logger.info('Admin %r stopped impersonating user %r', user, session.user)
    session.user = user
    session.update(entry['session_data'])
    def _make_idref(self, column, value, incoming=False, target_column=None):
        """Generate a ID reference.

        When generating an incoming ID reference, `column` must be a PK
        and point to the column that is referenced by FKs.  In this case
        the `value` is ignored since it will be auto-generated by the db
        when the new row is isnerted.

        Otherwise, exactly one of `column` or `target_column` must be set.
        `column` is the column in the current table that has a FK referencing
        some other column.
        `target_column` is already the column that is referenced by a FK
        in the current table.
        """
        assert (column is None) != (target_column is None)

        if value is None:
            return None

        if incoming:
            assert column.primary_key
            assert target_column is None
            fullname = '{}.{}'.format(column.table.fullname, column.name)
            type_ = 'idref_set'
        else:
            if target_column is not None:
                fullname = '{}.{}'.format(target_column.table.fullname,
                                          target_column.name)
            else:
                fk = _get_single_fk(column)
                fullname = fk.target_fullname
                target_column = fk.column
            if target_column is User.__table__.c.id and value is not None:
                type_ = 'userref'
            else:
                type_ = 'idref'
        uuid = self.id_map[fullname].setdefault(value, self._get_uuid())
        if type_ == 'userref' and uuid not in self.users:
            user = User.get(value)
            self.users[uuid] = None if user.is_system else {
                'first_name': user.first_name,
                'last_name': user.last_name,
                'title': user._title,
                'affiliation': user.affiliation,
                'phone': user.phone,
                'address': user.address,
                'email': user.email,
                'all_emails': list(user.all_emails)
            }
        return type_, uuid
 def _get_user_data(self):
     user_id = request.args.get('user')
     if user_id is None:
         return {}
     elif user_id.isdigit():
         # existing fossir user
         user = User.find_first(id=user_id, is_deleted=False)
         user_data = {t.name: getattr(user, t.name, None) if user else '' for t in PersonalDataType}
     else:
         # non-fossir user
         data = GenericCache('pending_identities').get(user_id, {})
         user_data = {t.name: data.get(t.name) for t in PersonalDataType}
     user_data['title'] = get_title_uuid(self.regform, user_data['title'])
     return user_data
Beispiel #24
0
def grant_admin(user_id):
    """Grants administration rights to a given user"""
    user = User.get(user_id)
    if user is None:
        print(cformat("%{red}This user does not exist"))
        return
    _print_user_info(user)
    if user.is_admin:
        print(cformat("%{yellow}This user already has administration rights"))
        return
    if click.confirm(
            cformat("%{yellow}Grant administration rights to this user?")):
        user.is_admin = True
        db.session.commit()
        print(cformat("%{green}Administration rights granted successfully"))
Beispiel #25
0
def revoke_admin(user_id):
    """Revokes administration rights from a given user"""
    user = User.get(user_id)
    if user is None:
        print(cformat("%{red}This user does not exist"))
        return
    _print_user_info(user)
    if not user.is_admin:
        print(
            cformat("%{yellow}This user does not have administration rights"))
        return
    if click.confirm(
            cformat("%{yellow}Revoke administration rights from this user?")):
        user.is_admin = False
        db.session.commit()
        print(cformat("%{green}Administration rights revoked successfully"))
Beispiel #26
0
def test_iter_acl():
    user = User()
    user_p = MagicMock(principal=user, spec=['principal'])
    ipn = IPNetworkGroup()
    ipn_p = MagicMock(principal=ipn, spec=['principal'])
    local_group = GroupProxy(123, _group=MagicMock())
    local_group_p = MagicMock(principal=local_group, spec=['principal'])
    remote_group = GroupProxy('foo', 'bar')
    remote_group_p = MagicMock(principal=remote_group, spec=['principal'])
    acl = [
        ipn, user_p, remote_group, local_group_p, user, local_group,
        remote_group_p, ipn_p
    ]
    assert list(iter_acl(iter(acl))) == [
        user_p, user, ipn, ipn_p, local_group_p, local_group, remote_group,
        remote_group_p
    ]
Beispiel #27
0
def create(grant_admin):
    """Creates a new user"""
    user_type = 'user' if not grant_admin else 'admin'
    while True:
        email = prompt_email()
        if email is None:
            return
        email = email.lower()
        if not User.find(User.all_emails.contains(email), ~User.is_deleted,
                         ~User.is_pending).count():
            break
        print(cformat('%{red}Email already exists'))
    first_name = click.prompt("First name").strip()
    last_name = click.prompt("Last name").strip()
    affiliation = click.prompt("Affiliation", '').strip()
    print()
    while True:
        username = click.prompt("Enter username").lower().strip()
        if not Identity.find(provider='fossir', identifier=username).count():
            break
        print(cformat('%{red}Username already exists'))
    password = prompt_pass()
    if password is None:
        return

    identity = Identity(provider='fossir',
                        identifier=username,
                        password=password)
    user = create_user(
        email, {
            'first_name': to_unicode(first_name),
            'last_name': to_unicode(last_name),
            'affiliation': to_unicode(affiliation)
        }, identity)
    user.is_admin = grant_admin
    _print_user_info(user)

    if click.confirm(cformat("%{yellow}Create the new {}?").format(user_type),
                     default=True):
        db.session.add(user)
        db.session.commit()
        print(
            cformat("%{green}New {} created successfully with ID: %{green!}{}"
                    ).format(user_type, user.id))
Beispiel #28
0
 def _create_user(id_,
                  first_name=u'Guinea',
                  last_name=u'Pig',
                  rb_admin=False,
                  admin=False,
                  email=None,
                  groups=None,
                  legacy=False):
     user = User.get(id_)
     if user:
         return user.as_avatar if legacy else user
     user = User()
     user.id = id_
     user.first_name = first_name
     user.last_name = last_name
     user.email = email or u'{}@example.com'.format(id_)
     user.is_admin = admin
     user.local_groups = {g.group for g in (groups or ())}
     db.session.add(user)
     db.session.flush()
     if rb_admin:
         rb_settings.acls.add_principal('admin_principals', user)
     db.session.flush()
     return user.as_avatar if legacy else user
    def _process(self):
        if session.user:
            return redirect(url_for_index())

        handler = MultipassRegistrationHandler(self) if self.identity_info else LocalRegistrationHandler(self)
        verified_email, prevalidated = self._get_verified_email()
        if verified_email is not None:
            handler.email_verified(verified_email)
            if prevalidated:
                flash(_("You may change your email address after finishing the registration process."), 'info')
            else:
                flash(_('You have successfully validated your email address and can now proceeed with the '
                        'registration.'), 'success')
            return redirect(url_for('.register', provider=self.provider_name))

        form = handler.create_form()
        if not handler.moderate_registrations and not handler.must_verify_email:
            del form.comment
        # Check for pending users if we have verified emails
        pending = None
        if not handler.must_verify_email:
            pending = User.find_first(~User.is_deleted, User.is_pending,
                                      User.all_emails.contains(db.func.any(list(handler.get_all_emails(form)))))
        if form.validate_on_submit():
            if handler.must_verify_email:
                return self._send_confirmation(form.email.data)
            elif handler.moderate_registrations:
                return self._create_registration_request(form, handler)
            else:
                return self._create_user(form, handler)
        elif not form.is_submitted() and pending:
            # If we have a pending user, populate empty fields with data from that user
            for field in form:
                value = getattr(pending, field.short_name, '')
                if value and not field.data:
                    field.data = value
        if pending:
            flash(_("There is already some information in fossir that concerns you. "
                    "We are going to link it automatically."), 'info')
        return WPAuth.render_template('register.html', form=form, local=(not self.identity_info),
                                      must_verify_email=handler.must_verify_email, widget_attrs=handler.widget_attrs,
                                      email_sent=session.pop('register_verification_email_sent', False),
                                      moderate_accounts=handler.moderate_registrations)
 def __init__(self,
              source_file,
              category_id=0,
              create_users=None,
              verbose=False,
              force=False):
     self.source_file = source_file
     self.category_id = category_id
     self.create_users = create_users
     self.verbose = verbose
     self.force = force
     self.archive = tarfile.open(fileobj=source_file)
     self.data = yaml.load(self.archive.extractfile('data.yaml'))
     self.id_map = {}
     self.user_map = {}
     self.event_id = None
     self.system_user_id = User.get_system_user().id
     self.spec = self._load_spec()
     self.deferred_idrefs = defaultdict(set)