def update_from_enrollment(self):
        t1 = time.time()
        if self.print_log:
            print("  update_from_enrollment()")

        self.main_stats['enrollment']['started'] = str(datetime.now())

        actors = Enrollment.get_active().order_by('tempid')
        bulk_count = 10000
        p = Paginator(actors, bulk_count)

        self.main_stats['enrollment']['num_pages'] = p.num_pages
        self.main_stats['enrollment']['pages'] = {}

        if self.task_log:
            self.task_log.data = self.main_stats
            self.task_log.save()

        self.update(p, 'enrollment')

        self.main_stats['enrollment']['ended'] = str(datetime.now())
        self.main_stats['enrollment']['duration'] = time.time() - t1

        if self.task_log:
            self.task_log.data = self.main_stats
            self.task_log.save()

        if self.print_log:
            self.print_stats(self.main_stats['enrollment'], 4)
            print("  update_from_enrollment() done in %0.2fs"
                  % self.main_stats['enrollment']['duration'])
Example #2
0
 def get_children(self):
     # Assuming that there aren't members in the Actor table that could be connected to this member.
     children = cache.get('focus.enrollment.children.%s' % self.enrollment.memberid)
     if children is None:
         children = Enrollment.get_active().filter(linked_to=self.enrollment.memberid).exclude(pk=self.enrollment.pk)
         cache.set('focus.enrollment.children.%s' % self.enrollment.memberid, children, settings.FOCUS_MEMBER_CACHE_PERIOD)
     return children
 def __init__(self, memberid):
     try:
         self.enrollment = cache.get('focus.enrollment.%s' % memberid)
         if self.enrollment is None:
             self.enrollment = Enrollment.get_active().get(memberid=memberid)
             cache.set('focus.enrollment.%s' % memberid, self.enrollment, settings.FOCUS_MEMBER_CACHE_PERIOD)
     except Enrollment.DoesNotExist:
         # The referenced memberid doesn't exist among active pending members. This is expected if the pending member
         # was accepted and is now an Actor; let the User object handle that case.
         raise ExpiredMember("Enrollment with memberid '%s' does not exist" % memberid)
Example #4
0
def verify_memberid(ip_address, memberid, country_code, zipcode):
    """
    Returns a User object matching the given memberid, country code, and if
    Norwegian; also zipcode. Includes pending users by default. Raises a range
    of exceptions if the provided data is invalid or does not match any user:
    - MemberidLookupsExceeded: If the client IP address has performed more
      lookups than we allowed
    - CountryDoesNotExist: If the given country code is invalid
    - ActorIsNotPersonalMember: If the data matches an Actor in Focus who
      isn't a personal member
    - NoMatchingMemberid: If the data doesn't match any member
    """
    # Check that the memberid is correct (and retrieve the Actor-entry)
    if memberid_lookups_exceeded(ip_address):
        raise MemberidLookupsExceeded

    if not FocusCountry.objects.filter(code=country_code).exists():
        raise CountryDoesNotExist

    # Not filtering on Actor.get_personal_members() in order to raise explicit
    # exception for non-personal-membership matches; see below
    actor = Actor.objects.filter(
        memberid=memberid,
        address__country_code=country_code
    )

    # Require correct zipcode for domestic members
    if country_code == 'NO':
        actor = actor.filter(address__zipcode=zipcode)

    if actor.exists():
        actor = actor.get()

        # Check that it's a proper member object (note that we didn't filter
        # the query on Actor.get_personal_members())
        if not actor.is_personal_member():
            raise ActorIsNotPersonalMember

        return User.get_or_create_inactive(memberid=actor.memberid)

    # No matching actors, check for pending users
    enrollment = Enrollment.get_active().filter(memberid=memberid)

    # Require correct zipcode for domestic members
    if country_code == 'NO':
        enrollment = enrollment.filter(zipcode=zipcode)

    if enrollment.exists():
        return User.get_or_create_inactive(memberid=memberid)

    # No matches
    raise NoMatchingMemberid
    def get_children(self):
        from user.models import User

        # Only look for children among other pending users. There could theoretically be children that are proper
        # members, but in most such cases the current pending member would also have been accepted, so don't handle it.
        enrollment_children = Enrollment.get_active().filter(
            parent=self.enrollment.memberid,
        ).exclude(
            pk=self.enrollment.pk,
        )
        return [
            User.get_or_create_inactive(memberid=enrollment_child.memberid)
            for enrollment_child in enrollment_children
        ]
Example #6
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin.users.views.index')

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    local_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['q'].split():
        local_users = local_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word))
    local_users = local_users.order_by('first_name')

    actors = Actor.get_personal_members()
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word))
    actors = actors.order_by('first_name')

    # Match expired users only on memberid
    expired_users = User.objects.all()
    for word in request.POST['q'].split():
        expired_users = expired_users.filter(memberid__icontains=word)
    expired_users = [u for u in expired_users if not Actor.get_personal_members().filter(memberid=u.memberid).exists()]

    # Pending users
    pending_enrollment = Enrollment.get_active()
    for word in request.POST['q'].split():
        pending_enrollment = pending_enrollment.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word))
    pending_enrollment = pending_enrollment.order_by('first_name')

    members = User.get_users().filter(memberid__in=[a.memberid for a in actors])
    pending_users = User.get_users(include_pending=True).filter(memberid__in=[e.memberid for e in pending_enrollment])
    actors_without_user = [a for a in actors if a.memberid not in list(members.values_list('memberid', flat=True))]
    users = list(local_users) + list(members) + list(pending_users)

    context = RequestContext(request, {
        'users': users,
        'actors_without_user': actors_without_user,
        'expired_users': expired_users
    })
    return HttpResponse(render_to_string('common/admin/users/user_results.html', context))
Example #7
0
    def get_queryset(self):
        # This method uses Focus and local users to compile a search result
        # containing users.

        # See the comment on the class definition of the lazy_queryset variable
        if self.lazy_queryset:
            return self.lazy_queryset

        SEARCH_MAX_HITS = 100
        search = self.request.query_params.get('search', '').strip()

        if len(search) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
            raise PermissionDenied

        local_users = User.get_users().filter(memberid__isnull=True)
        for word in search.split():
            local_users = local_users.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(email__icontains=word))
        local_users = local_users.order_by('first_name')[:SEARCH_MAX_HITS]

        actors = Actor.get_personal_members().select_related(
            'address', 'address__zipcode')
        for word in search.split():
            actors = actors.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word) |
                Q(email__icontains=word))
        actors = actors.order_by('first_name')[:SEARCH_MAX_HITS]

        # Cache all the actor objects because we will be accessing them through
        # user objects later
        Actor.cache_all(actors)

        # Match expired users only on memberid
        expired_users = User.objects.all()
        for word in search.split():
            expired_users = expired_users.filter(memberid__icontains=word)
        expired_users = [
            u for u in expired_users
            if not Actor.get_personal_members().only('id').filter(
                memberid=u.memberid).exists() and not Enrollment.get_active()
            .only('id').filter(memberid=u.memberid).exists()
        ]

        # Pending users
        pending_enrollment = Enrollment.get_active()
        for word in search.split():
            pending_enrollment = pending_enrollment.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word))
        pending_enrollment = pending_enrollment.order_by(
            'first_name')[:SEARCH_MAX_HITS]

        members = User.get_users().filter(
            memberid__in=[a.memberid for a in actors])
        user_member_ids = list(members.values_list('memberid', flat=True))
        pending_users = User.get_users(include_pending=True).filter(
            memberid__in=[e.memberid for e in pending_enrollment])

        # Create inactive users for any actor hit without a corresponding user
        newly_created_members = [
            User.get_or_create_inactive(memberid=a.memberid) for a in actors
            if a.memberid not in user_member_ids
        ]

        users = sorted(
            list(local_users) + list(members) + list(pending_users) +
            list(newly_created_members),
            key=lambda u: u.get_full_name())

        self.lazy_queryset = users
        return users
Example #8
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin:users.index')

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    SEARCH_MAX_HITS = 40

    local_users = User.get_users().filter(
        memberid__isnull=True,
    ).prefetch_related(
        'permissions',
    )
    for word in request.POST['q'].split():
        local_users = local_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word)
        )
    local_users = local_users.order_by('first_name')[:SEARCH_MAX_HITS]

    actors = Actor.get_personal_members().select_related('address', 'address__zipcode')
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')[:SEARCH_MAX_HITS]

    # Cache all the actor objects because we will be accessing them through user objects later
    Actor.cache_all(actors)

    # Match expired users only on memberid
    expired_users = User.objects.all()
    for word in request.POST['q'].split():
        expired_users = expired_users.filter(memberid__icontains=word)
    expired_users = [
        u for u in expired_users
        if not Actor.get_personal_members().only('id').filter(memberid=u.memberid).exists()
        and not Enrollment.get_active().only('id').filter(memberid=u.memberid).exists()
    ]

    # Pending users
    pending_enrollment = Enrollment.get_active()
    for word in request.POST['q'].split():
        pending_enrollment = pending_enrollment.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    pending_enrollment = pending_enrollment.order_by('first_name')[:SEARCH_MAX_HITS]

    max_hits_exceeded = len(local_users) >= SEARCH_MAX_HITS or \
        len(actors) >= SEARCH_MAX_HITS or \
        len(pending_enrollment) >= SEARCH_MAX_HITS

    members = User.get_users().filter(
        memberid__in=[a.memberid for a in actors],
    ).prefetch_related(
        'permissions',
    )
    user_member_ids = list(members.values_list('memberid', flat=True))
    pending_users = User.get_users(include_pending=True).filter(memberid__in=[e.memberid for e in pending_enrollment])
    actors_without_user = [a for a in actors if a.memberid not in user_member_ids]
    users = list(local_users) + list(members) + list(pending_users)

    context = {
        'users': users,
        'actors_without_user': actors_without_user,
        'expired_users': expired_users,
        'max_hits_exceeded': max_hits_exceeded,
    }
    return HttpResponse(render_to_string('central/admin/users/user_results.html', context, request=request))
Example #9
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin:users.index')

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    SEARCH_MAX_HITS = 40

    # Look up non-members in the local user database
    nonmembers = User.get_users().filter(
        memberid__isnull=True,
    ).prefetch_related(
        'user_permission_grants',
        'user_permission_grants__user_permission',
        'user_permission_grants__user_permission__oauth_applications',
    )
    for word in request.POST['q'].split():
        nonmembers = nonmembers.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word)
        )
    nonmembers = nonmembers.order_by('first_name')[:SEARCH_MAX_HITS]

    # Look up members directly in Actors
    actors = Actor.get_personal_members().select_related(
        'address', 'address__zipcode')
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')[:SEARCH_MAX_HITS]

    # Cache all the actor objects because we will be accessing them through
    # user objects later
    Actor.cache_all(actors)

    # Look up pending members directly in Enrollment
    enrollments = Enrollment.get_active()
    for word in request.POST['q'].split():
        enrollments = enrollments.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    enrollments = enrollments.order_by('first_name')[:SEARCH_MAX_HITS]

    # Create a list of all memberids
    focus_memberids = (
        [a.memberid for a in actors]
        + [e.memberid for e in enrollments])

    # Select user objects based on the known memberids
    members = User.get_users(
        include_pending=True,
    ).filter(
        memberid__in=focus_memberids,
    )

    # Create users for any members who don't have a User object
    memberids_existing = [u.memberid for u in members]
    memberids_missing = [
        m for m in focus_memberids
        if m not in memberids_existing]
    created_members = [
        User.get_or_create_inactive(memberid=memberid)
        for memberid in memberids_missing]

    users = list(nonmembers) + list(members) + list(created_members)

    max_hits_exceeded = len(nonmembers) >= SEARCH_MAX_HITS or \
        len(actors) >= SEARCH_MAX_HITS or \
        len(enrollments) >= SEARCH_MAX_HITS

    # Match expired users only on memberid
    expired_users = User.objects.all()
    for word in request.POST['q'].split():
        expired_users = expired_users.filter(memberid__icontains=word)
    expired_users = [
        u for u in expired_users
        if not Actor.get_personal_members().only('id').filter(
            memberid=u.memberid).exists()
        and not Enrollment.get_active().only('id').filter(
            memberid=u.memberid).exists()
    ]

    context = {
        'users': users,
        'expired_users': expired_users,
        'max_hits_exceeded': max_hits_exceeded,
    }
    return HttpResponse(render_to_string('central/admin/users/user_results.html', context, request=request))
Example #10
0
 def __init__(self, memberid):
     enrollment = cache.get('focus.enrollment.%s' % memberid)
     if enrollment is None:
         enrollment = Enrollment.get_active().get(memberid=memberid)
         cache.set('focus.enrollment.%s' % memberid, enrollment, settings.FOCUS_MEMBER_CACHE_PERIOD)
     self.enrollment = enrollment
Example #11
0
    def create_pending_user(memberid):
        """Create an inactive pending user. Note that the caller must verify that the memberid does not exist in Actor
        first. Read the implementation for more details."""
        # Note that a known bug will result in an exception here.
        # This occurs during enrollment. When saving an enrollment in Focus, the payment_method field should be set to
        # one of two sentinel values for card or invoice; see focus.util.PAYMENT_METHOD_CODES. However, for some
        # reason, some of these entries are saved with payment_method=0 (which is NOT one of the sentinel values). This
        # will occur in an exception where, because Enrollment.get_active() will filter on valid payment codes, not
        # find the given memberid, and raise an exception which isn't handled in the enrollment view (because it
        # shouldn't need to be).
        Enrollment.get_active().get(memberid=memberid) # Ensure that the enrollment exists
        try:
            # Check if the user object already exists first.
            existing_user = User.objects.get(memberid=memberid)

            # Note that we don't check if this user is inactive or not.
            # If they are, maybe someone double-clicked some link or something.
            # It doesn't matter, let this user pass as the created one.

            if not existing_user.verify_still_pending():
                # Should never happen - this method should only be called:
                # - When creating new members, in which case the database should return a memberid which is
                #   *guaranteed* to be new, unique and NOT used in Actor
                # - If the caller has verified that the memberid isn't in use in Actor, and needs to create a new
                #   inactive pending user.
                # We could ignore this and just return the user, but since the caller expects this to be a pending
                # user, there's no telling what craziness might happen, so it is (probably) better to raise an
                # exception here. I don't expect this to happen unless there's been made a code logic mistake
                # somewhere.
                raise Exception("Tried to create a pending user with a memberid which exists in the Actor table.")

            if existing_user.is_expired:
                # Oh, what happened here? Well, they're not expired anymore since the actor exists, so fix that and
                # let them pass.
                existing_user.is_expired = False
                existing_user.save()

            if not existing_user.is_pending:
                # Oh, what happened here? Since our context is that a corresponding actor doesn't exist (see method
                # comment), this user should be pending, so fix it and let them pass
                existing_user.is_pending = True
                existing_user.save()

            return existing_user
        except User.DoesNotExist:
            user = User(
                identifier='%s' % memberid,
                memberid=memberid,
                is_inactive=True,
                is_pending=True
            )
            user.set_unusable_password()
            key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)
            while User.objects.filter(pending_registration_key=key).exists():
                # Ensure that the key isn't already in use. With the current key length of 40, we'll have
                # ~238 bits of entropy which means that this will never ever happen, ever.
                # You will win the lottery before this happens. And I want to know if it does, so log it.
                logger.warning(
                    "Noen fikk en random-generert pending-registration-key som allerede finnes!",
                    extra={
                        'should_you_play_the_lottery': True,
                        'key': key
                    }
                )
                key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)
            user.pending_registration_key = key
            user.save()
            return user