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'])
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)
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 ]
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))
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
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))
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))
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
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