def users(request, forening_id): current_forening = Forening.objects.get(id=forening_id) if current_forening not in request.user.all_foreninger(): raise PermissionDenied forening_users = list(User.objects.filter(foreninger=current_forening)) forening_users_by_parent = [] parent_ids = [p.id for p in current_forening.get_parents_deep()] forening_users_by_parent_all = list(User.objects.filter(foreninger__in=parent_ids)) # Prefetch and cache the actors memberids = [u.memberid for u in (forening_users + forening_users_by_parent)] Actor.cache_all( Actor.get_personal_members().filter(memberid__in=memberids).prefetch_related('services') ) # Safe to iterate without having n+1 issues # Filter on admins forening_users_by_parent = [] for user in forening_users_by_parent_all: for forening in user.all_foreninger(): if forening == current_forening and forening.role == 'admin': forening_users_by_parent.append(user) forening_users = sorted(forening_users, key=lambda u: u.get_full_name()) forening_users_by_parent = sorted(forening_users_by_parent, key=lambda u: u.get_full_name()) context = { 'current_forening': current_forening, 'forening_users': forening_users, 'forening_users_by_parent': forening_users_by_parent, 'admin_user_search_char_length': settings.ADMIN_USER_SEARCH_CHAR_LENGTH, } return render(request, 'central/admin/foreninger/users.html', context)
def users(request, forening_id): current_forening = Forening.objects.get(id=forening_id) if current_forening not in request.user.all_foreninger(): raise PermissionDenied p_name = 'sherpa/association/user' prefetch_related = ( 'user_permission_grants', 'user_permission_grants__user_permission', # This is to avoid multiple extra queries from # user.get_permissions_cached() when we check for admin # permission below. 'user_permission_grants__user_permission__oauth_applications', ) forening_users = list( User.objects.filter( user_permission_grants__user_permission__name=p_name, user_permission_grants__association=current_forening ).prefetch_related(*prefetch_related) ) forening_users_by_parent = [] parent_ids = [p.id for p in current_forening.get_parents_deep()] forening_users_by_parent_all = list( User.objects.filter( user_permission_grants__user_permission__name=p_name, user_permission_grants__association__in=parent_ids ).prefetch_related(*prefetch_related) ) # Prefetch and cache the actors memberids = [ u.memberid for u in (forening_users + forening_users_by_parent)] actors = Actor.get_personal_members().filter( memberid__in=memberids, ).prefetch_related( 'services', ) Actor.cache_all(actors) # Safe to iterate without having n+1 issues # Filter on admins forening_users_by_parent = [] for user in forening_users_by_parent_all: for forening in user.all_foreninger(): if forening == current_forening and forening.role == 'admin': forening_users_by_parent.append(user) forening_users = sorted( forening_users, key=lambda u: u.get_full_name(True) ) forening_users_by_parent = sorted( forening_users_by_parent, key=lambda u: u.get_full_name(True) ) context = { 'is_admin_in_forening': request.user.is_admin_in_forening(current_forening), 'current_forening': current_forening, 'forening_users': forening_users, 'forening_users_by_parent': forening_users_by_parent, 'admin_user_search_char_length': ( settings.ADMIN_USER_SEARCH_CHAR_LENGTH ), } return render(request, 'central/admin/foreninger/users.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))