예제 #1
0
    def handle(self, *args, **options):

        members = User.objects.filter(memberid__isnull=False)
        pending_users = members.filter(is_pending=True)
        normal_users = members.filter(is_pending=False)

        # Check for pending users that recently got their Actor, and shouldn't be pending
        for u in pending_users.filter(is_expired=False):
            # This method automatically updates the user if not pending anymore
            u.verify_still_pending(ignore_cache=True)

        # Check for expired pending users that may have gotten their Actor or Enrollment object back
        # (doesn't make sense that this actually happens, but let's not make assumptions for Focus)
        for u in pending_users.filter(is_expired=True):
            if Actor.get_personal_members().filter(memberid=u.memberid).exists():
                u.is_expired = False
                u.is_pending = False
                u.save()
            elif Enrollment.objects.filter(memberid=u.memberid).exists():
                u.is_expired = False
                u.save()

        # Check for normal expired users that regained their Actor and shouldn't be expired anymore
        for u in normal_users.filter(is_expired=True):
            if Actor.get_personal_members().filter(memberid=u.memberid).exists():
                u.is_expired = False
                u.save()

        # Check for normal users that have lost their Actor and should be expired
        for u in normal_users.filter(is_expired=False):
            if not Actor.get_personal_members().filter(memberid=u.memberid).exists():
                u.is_expired = True
                u.save()
예제 #2
0
    def create_inactive_user(memberid):
        Actor.get_personal_members().get(memberid=memberid) # Verify that the Actor 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 existing_user.is_pending:
                # Well, we saw that they're not pending anymore since we checked the actor, so fix that and let them
                # pass.
                existing_user.is_pending = False
                existing_user.save()

            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()

            return existing_user
        except User.DoesNotExist:
            user = User(identifier=memberid, memberid=memberid, is_inactive=True)
            user.set_unusable_password()
            user.save()
            return user
예제 #3
0
파일: views.py 프로젝트: simensma/sherpa
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))
예제 #4
0
def check_memberid(request):
    if not request.user.can_modify_user_memberid():
        raise PermissionDenied

    user_to_change = User.objects.get(id=request.POST['user'])
    memberid_is_equal = str(user_to_change.memberid) == request.POST['memberid'].strip()

    try:
        existing_user = User.objects.get(memberid=request.POST['memberid'])
    except (User.DoesNotExist, ValueError):
        existing_user = None

    try:
        actor = Actor.get_personal_members().get(memberid=request.POST['memberid'])
    except (Actor.DoesNotExist, ValueError):
        actor = None

    context = {
        'user_to_change': user_to_change,
        'existing_user': existing_user,
        'actor': actor,
        'memberid': request.POST['memberid'],
        'memberid_is_equal': memberid_is_equal,
    }
    html = render_to_string('central/admin/users/check_memberid.html', context, request=request)
    return HttpResponse(json.dumps({
        'valid': actor is not None and not memberid_is_equal,
        'html': html,
    }))
예제 #5
0
    def update_from_actors(self):
        t1 = time.time()
        if self.print_log:
            print("  update_from_actors()")

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

        actors = Actor.get_personal_members().order_by('id')
        if self.filter_from_date:
            actors = actors.filter(changed_date__gt=self.filter_from_date)

        bulk_count = 10000
        p = Paginator(actors, bulk_count)

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

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

        self.update(p, 'actor')

        self.main_stats['actor']['ended'] = str(datetime.now())
        self.main_stats['actor']['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['actor'], 4)
            print("  update_from_actors() done in %0.2fs"
                  % self.main_stats['actor']['duration'])
예제 #6
0
파일: util.py 프로젝트: simensma/sherpa
def attempt_login(request):
    matches = authenticate_users(request.POST['email'], request.POST['password'])

    if len(matches) == 1:
        # Exactly one match, cool, just authenticate the user
        user = authenticate(user=matches[0])
        log_user_in(request, user)
        return matches, None

    elif len(matches) > 1:
        # Multiple matches, let the caller handle this
        return matches, None

    elif len(matches) == 0:
        # Incorrect credentials. Check if this is a user from the old userpage system
        old_member = authenticate_sherpa2_user(request.POST['email'], request.POST['password'])
        if old_member is not None:
            # Actually, it is! Let's try to import them.
            if User.get_users().filter(memberid=old_member.memberid, is_inactive=False).exists():
                return matches, 'old_memberid_but_memberid_exists'

            # Check if a pending user exists. This shouldn't ever happen (a pending user is recently
            # enrolled, and an existing user will have been member for a long time).
            if User.objects.filter(memberid=old_member.memberid, is_pending=True).exists():
                # Give the same error ("user exists, you need to use your new password")
                return matches, 'old_memberid_but_memberid_exists'

            # Verify that they exist in the membersystem (this turned out to be an incorrect assumption)
            if not Actor.get_personal_members().filter(memberid=old_member.memberid).exists():
                # We're not quite sure why this can happen, so we'll just give them the invalid
                # credentials message - but this might be confusing for those who were able to log
                # in previously.
                return matches, 'invalid_credentials'

            # Create the new user
            try:
                # Check if the user's already created as inactive
                user = User.get_users().get(memberid=old_member.memberid, is_inactive=True)
                user.is_inactive = False
                user.set_password(request.POST['password'])
                user.save()
            except User.DoesNotExist:
                # New user
                user = User(identifier=old_member.memberid, memberid=old_member.memberid)
                user.set_password(request.POST['password'])
                user.save()

            # Update the email on this actor, in case it were to differ from the sherpa2 email
            user.update_personal_data({'email': request.POST['email']})

            # Import any fjelltreffen-annonser from the old system
            import_fjelltreffen_annonser(user)

            authenticate(user=user)
            log_user_in(request, user)
            return [user], None

        else:
            # No luck, just provide the error message
            return matches, 'invalid_credentials'
예제 #7
0
def change_memberid(request):
    if not request.user.can_modify_user_memberid():
        raise PermissionDenied

    # The Actor was already checked client-side, but verify here
    if not Actor.get_personal_members().filter(memberid=request.POST['new-memberid']).exists():
        raise PermissionDenied

    old_user = User.objects.get(id=request.POST['old-user'])
    try:
        new_user = User.objects.get(memberid=request.POST['new-memberid'])
        # Ah, the new memberid already has a user - merge them, but keep the password
        # of the new user
        new_user.merge_with(old_user) # This will delete the old user
        resulting_user = new_user
    except User.DoesNotExist:
        # Allright, just update the memberid to the new one
        old_user.identifier = request.POST['new-memberid']
        old_user.memberid = request.POST['new-memberid']
        old_user.is_expired = False
        old_user.is_pending = False
        old_user.save()
        resulting_user = old_user
    if 'purge-busticket' in request.POST:
        ticket = resulting_user.norway_bus_ticket
        ticket.delete()
    return redirect('admin:users.show', resulting_user.id)
예제 #8
0
 def __init__(self, memberid, actor=None):
     try:
         self.actor = actor if actor is not None else cache.get('actor.%s' % memberid)
         if self.actor is None:
             self.actor = Actor.get_personal_members().get(memberid=memberid)
             cache.set('actor.%s' % memberid, self.actor, settings.FOCUS_MEMBER_CACHE_PERIOD)
     except Actor.DoesNotExist:
         # The referenced memberid doesn't exist in the member system. This typically occurs when the member system
         # purges members who haven't been enrolled for 2 years or more.
         raise ExpiredMember("Actor with memberid '%s' does not exist" % memberid)
예제 #9
0
    def get_children(self):
        from user.models import User

        children = cache.get('actor.%s.children' % self.actor.memberid)
        if children is None:
            actor_children = Actor.get_personal_members().filter(parent=self.actor.memberid).exclude(id=self.actor.id)
            children = [
                User.get_or_create_inactive(memberid=actor_child.memberid)
                for actor_child in actor_children
            ]
            cache.set('actor.%s.children' % self.actor.memberid, children, settings.FOCUS_MEMBER_CACHE_PERIOD)
        return children
예제 #10
0
def contact_person_search(request, forening_id):
    current_forening = Forening.objects.get(id=forening_id)
    if current_forening not in request.user.all_foreninger():
        raise PermissionDenied

    MAX_HITS = 100

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

    local_nonmember_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['q'].split():
        local_nonmember_users = local_nonmember_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word)
        )
    local_nonmember_users = local_nonmember_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')

    # Get (or create) the user objects for the first MAX_HITS actor-hits
    users = [
        User.get_or_create_inactive(a.memberid)
        for a in actors[:MAX_HITS]]

    # Merge with non-members
    users = sorted(
        list(users) + list(local_nonmember_users),
        key=lambda u: u.get_full_name())

    context = {
        'current_forening': current_forening,
        'users': users[:MAX_HITS],
    }
    return HttpResponse(json.dumps({
        'results': render_to_string(
            'central/admin/foreninger/contact_person_search_results.html',
            context,
            request=request,
        ),
        'max_hits_exceeded': len(users) > MAX_HITS or len(actors) > MAX_HITS
    }))
예제 #11
0
    def verify_still_pending(self, ignore_cache=False):
        # If, for any reason, a non-member got is_pending set to True incorrectly, fix it
        if not self.is_member():
            self.is_pending = False
            self.save()
            return False

        # Cache the check for an hour
        if not ignore_cache and cache.get('user.%s.checked_for_pending' % self.id) is not None:
            return True
        cache.set('user.%s.checked_for_pending' % self.id, True, 60 * 60)

        if Actor.get_personal_members().filter(memberid=self.memberid).exists():
            self.is_pending = False
            self.save()
            return False
        else:
            return True
예제 #12
0
def cache_actors(memberids):
    # Run a search with several memberids towards Focus and recieve all
    # relevant actor data. Then cache the result.
    # This prevents multiple queries to Focus when for instance looping
    # through users to display their name

    # If we have more than 2100 parameters, MSSQL will cry, so split it
    # up in bulks
    for i in range(0, len(memberids), settings.MSSQL_MAX_PARAMETER_COUNT):
        memberid_chunk = memberids[i:i + settings.MSSQL_MAX_PARAMETER_COUNT]
        actors = Actor.get_personal_members().filter(
            memberid__in=memberid_chunk)

        for actor in actors:
            cache.set(
                'actor.%s' % actor.memberid,
                actor,
                settings.FOCUS_MEMBER_CACHE_PERIOD
            )
예제 #13
0
    def get_queryset(self):
        # This method uses Focus and local users to compile a search result
        # containing valid turledere.

        # 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()

        local_nonmember_users = User.get_users().filter(memberid__isnull=True)
        for word in search.split():
            local_nonmember_users = local_nonmember_users.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word)
            )
        local_nonmember_users = local_nonmember_users.order_by('first_name')

        actors = Actor.get_personal_members()
        for word in search.split():
            actors = actors.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word)
            )
        actors = actors.order_by('first_name')

        # Get (or create) the user objects for the first MAX_HITS actor-hits
        users = [
            User.get_or_create_inactive(a.memberid)
            for a in actors[:SEARCH_MAX_HITS]]

        # Merge with non-members
        users = sorted(
            list(users) + list(local_nonmember_users),
            key=lambda u: u.get_full_name())

        self.lazy_queryset = users
        return users
예제 #14
0
def validate_existing(enrollment):
    try:
        actor = Actor.get_personal_members().get(memberid=enrollment.existing_memberid)
    except (Actor.DoesNotExist, ValueError):
        return False

    if not actor.has_paid():
        return False

    if datetime.now().year - actor.birth_date.year < AGE_YOUTH:
        return False

    if actor.is_household_member():
        return False

    if actor.get_clean_address().country.code != enrollment.country:
        return False

    if enrollment.country == 'NO' and actor.get_clean_address().zipcode.zipcode != enrollment.zipcode:
        return False

    return True
예제 #15
0
파일: views.py 프로젝트: simensma/sherpa
def existing(request):
    if not request.is_ajax():
        return redirect('enrollment.views.household')

    # Note: This logic is duplicated in validate_existing()
    data = json.loads(request.POST['data'])
    if data['country'] == 'NO' and len(data['zipcode']) != 4:
        return HttpResponse(json.dumps({'error': 'bad_zipcode'}))
    try:
        actor = Actor.get_personal_members().get(memberid=data['id'])
    except Actor.DoesNotExist:
        return HttpResponse(json.dumps({'error': 'actor.does_not_exist'}))
    except ValueError:
        return HttpResponse(json.dumps({'error': 'invalid_id'}))

    try:
        if data['country'] == 'NO':
            # Include zipcode for norwegian members
            address = ActorAddress.objects.get(actor=actor.id, zipcode=data['zipcode'], country_code=data['country'])
        else:
            address = ActorAddress.objects.get(actor=actor.id, country_code=data['country'])
    except ActorAddress.DoesNotExist:
        return HttpResponse(json.dumps({'error': 'actoraddress.does_not_exist'}))

    if not actor.has_paid():
        return HttpResponse(json.dumps({'error': 'actor.has_not_paid'}))

    age = datetime.now().year - actor.birth_date.year
    if age < AGE_YOUTH:
        return HttpResponse(json.dumps({'error': 'actor.too_young', 'age': age}))

    if actor.is_household_member():
        return HttpResponse(json.dumps({'error': 'actor.is_household_member'}))

    return HttpResponse(json.dumps({
        'name': "%s %s" % (actor.first_name, actor.last_name),
        'address': address.a1
    }))
예제 #16
0
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)
예제 #17
0
    def get_children_pending(self):
        """Returns existing single members who are *due to become* family members in this users' family"""
        from user.models import User

        children_pending = cache.get('actor.%s.children_pending' % self.actor.memberid)
        if children_pending is None:
            actors = Actor.get_personal_members().filter(
                pending_family_parent=self.actor.memberid,
            ).exclude(
                memberid=self.actor.memberid,
            ).exclude(
                # Exclude any actual family members. This is necessary because Focus doesn't clear the appropriate
                # fields when converting pending family members to actual family members.
                Q(services__code=get_membership_type_by_codename('family_household')['code']) |
                Q(services__code=get_membership_type_by_codename('family_primary')['code'])
            ).order_by('first_name', 'last_name')
            children_pending = [User.get_or_create_inactive(memberid=actor.memberid) for actor in actors]
            cache.set(
                'actor.%s.children_pending' % self.actor.memberid,
                children_pending,
                settings.FOCUS_MEMBER_CACHE_PERIOD,
            )
        return children_pending
예제 #18
0
def member_search(request):
    if len(request.POST['query']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    local_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['query'].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['query'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')

    users = User.get_users().filter(memberid__in=[a.memberid for a in actors])
    memberids = [u.memberid for u in users]
    actors_without_user = [a for a in actors if a.memberid not in memberids]

    # To sort users by name, we need the Actor data - go through the already-fetched bulk and cache them
    for actor in actors:
        cache.set('actor.%s' % actor.memberid, actor, settings.FOCUS_MEMBER_CACHE_PERIOD)

    users = sorted(users, key=lambda u: u.get_full_name())

    context = {
        'users': users,
        'actors_without_user': actors_without_user,
        'local_users': local_users,
    }
    return HttpResponse(render_to_string('central/admin/turledere/member_search_results.html', context, request=request))
예제 #19
0
파일: views.py 프로젝트: simensma/sherpa
def turleder_search(request):
    MAX_HITS = 100

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

    local_nonmember_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['q'].split():
        local_nonmember_users = local_nonmember_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word)
        )
    local_nonmember_users = local_nonmember_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')

    # Get (or create) the user objects for the first MAX_HITS actor-hits
    users = [User.get_or_create_inactive(a.memberid) for a in actors[:MAX_HITS]]

    # Merge with non-members
    users = sorted(list(users) + list(local_nonmember_users), key=lambda u: u.get_full_name())

    context = RequestContext(request, {
        'users': users[:MAX_HITS]
    })
    return HttpResponse(json.dumps({
        'results': render_to_string('common/admin/aktiviteter/edit/turleder_search_results.html', context),
        'max_hits_exceeded': len(users) > MAX_HITS or len(actors) > MAX_HITS
    }))
예제 #20
0
def authenticate_users(email, password):
    """
    Yup, this is a 'util' method instead of a proper authentication backend.
    The reason for this is that as our membersystem allows duplicate email
    fields, a user can potentially authenticate herself for multiple accounts,
    and the Django auth backend system doesn't account for that (it returns
    exactly one user, or None).
    """
    email = email.strip()

    # Support this special case explicitly because it will hit a lot of Actors
    # and check for a matching User for each of them, which takes a long time
    if email == '':
        return []

    # Add matching local users that aren't members
    matches = [
        u
        for u in User.get_users().filter(
            memberid__isnull=True,
            email__iexact=email
        )
        if u.check_password(password)
    ]

    # Add matching members in Actor
    for actor in Actor.get_personal_members().filter(email__iexact=email):
        try:
            # Ok, look for any matching active user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=actor.memberid,
                is_inactive=False  # ignore inactive users
            )

            # Reset state if this user was previously pending but is now a
            # proper member
            if user.is_pending:
                user.is_pending = False
                user.save()

            # Reset state if this user was previously marked as expired for
            # some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            # Now perform the password check for authentication
            if user.check_password(password):
                matches.append(user)
        except User.DoesNotExist:
            pass

    # Add matching pending members
    for enrollment in Enrollment.filter_on_email(email):
        try:
            # Ok, look for any matching active AND pending user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=enrollment.memberid,
                is_pending=True,
                is_inactive=False  # ignore inactive users
            )

            # Reset state if this user was previously marked as expired for
            # some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            # Now perform the password check for authentication
            # Check that the user isn't already matched as an Actor since this
            # theoretically could be a duplicate
            if user.check_password(password) and user not in matches:
                matches.append(user)
        except User.DoesNotExist:
            pass

    # And just return these matches
    return matches
예제 #21
0
파일: views.py 프로젝트: simensma/sherpa
def index(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)]
    for actor in Actor.get_personal_members().filter(memberid__in=memberids):
        cache.set('actor.%s' % actor.memberid, actor, settings.FOCUS_MEMBER_CACHE_PERIOD)

    # 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())
    sherpa_admins = sorted(User.objects.filter(permissions__name='sherpa_admin'), key=lambda u: u.get_full_name())

    # The parent choices are tricky to define in the forms API, so do it here.
    # Note that we're intentionally letting users choose parents among only those they have permission to.
    all_sorted = request.user.all_foreninger_sorted()
    parents_choices = {
        'forening': all_sorted['forening'],
        'turlag': all_sorted['turlag'],
    }

    # If the parent of the current forening isn't in the user's permissions, we still need to include that one as an
    # available parent so that they're able to make changes.
    if current_forening.type != 'sentral':
        for current_parent in current_forening.get_main_foreninger():
            if current_parent not in parents_choices['forening'] and current_parent not in parents_choices['turlag']:
                parents_choices[current_parent.type].append(current_parent)

    context = {
        'current_forening': current_forening,
        'forening_users': forening_users,
        'forening_users_by_parent': forening_users_by_parent,
        'sherpa_admins': sherpa_admins,
        'parents_choices': parents_choices,
        'admin_user_search_char_length': settings.ADMIN_USER_SEARCH_CHAR_LENGTH
    }

    zipcode = current_forening.zipcode
    edit_form_zipcode_area = zipcode.area if zipcode is not None else ''

    if current_forening.contact_person is not None:
        choose_contact = 'person'
        contact_person = current_forening.contact_person.id
        contact_person_name = current_forening.contact_person.get_full_name()
        phone = current_forening.contact_person.get_phone_mobile()
        email = current_forening.contact_person.get_sherpa_email()
    elif current_forening.contact_person_name != '':
        choose_contact = 'person'
        contact_person = None
        contact_person_name = current_forening.contact_person_name
        phone = current_forening.phone
        email = current_forening.email
    else:
        choose_contact = 'forening'
        contact_person = None
        contact_person_name = ''
        phone = current_forening.phone
        email = current_forening.email

    edit_form = ExistingForeningDataForm(request.user, prefix='edit', initial={
        'forening': current_forening.id,
        'parents': current_forening.parents.all(),
        'name': current_forening.name,
        'type': current_forening.type,
        'group_type': current_forening.group_type,
        'post_address': current_forening.post_address,
        'visit_address': current_forening.visit_address,
        'zipcode': zipcode.zipcode if zipcode is not None else '',
        'counties': current_forening.counties.all(),
        'choose_contact': choose_contact,
        'contact_person': contact_person,
        'contact_person_name': contact_person_name,
        'phone': phone,
        'email': email,
        'organization_no': current_forening.organization_no,
        'gmap_url': current_forening.gmap_url,
        'facebook_url': current_forening.facebook_url,
    })

    create_form = ForeningDataForm(request.user, prefix='create', initial={
        'zipcode': '',
    })

    context.update({
        'edit_form': edit_form,
        'create_form': create_form,
        'edit_form_zipcode_area': edit_form_zipcode_area,
    })

    if request.method == 'GET':
        return render(request, 'common/admin/forening/index.html', context)

    elif request.method == 'POST':

        if request.POST.get('form') == 'edit':
            edit_form = ExistingForeningDataForm(request.user, request.POST, prefix='edit')
            if edit_form.is_valid():
                forening = edit_form.cleaned_data['forening']
                forening.parents = edit_form.cleaned_data['parents']
                forening.name = edit_form.cleaned_data['name']
                forening.type = edit_form.cleaned_data['type']
                if forening.type == 'turgruppe':
                    forening.group_type = edit_form.cleaned_data['group_type']
                else:
                    forening.group_type = ''
                forening.post_address = edit_form.cleaned_data['post_address']
                forening.visit_address = edit_form.cleaned_data['visit_address']
                forening.zipcode = edit_form.cleaned_data['zipcode']
                forening.counties = edit_form.cleaned_data['counties']

                if edit_form.cleaned_data['choose_contact'] == 'person':
                    if edit_form.cleaned_data['contact_person'] is not None:
                        forening.contact_person = edit_form.cleaned_data['contact_person']
                        forening.contact_person_name = ''
                    else:
                        forening.contact_person = None
                        forening.contact_person_name = edit_form.cleaned_data['contact_person_name']
                else:
                    forening.contact_person = None
                    forening.contact_person_name = ''

                forening.phone = edit_form.cleaned_data['phone']
                forening.email = edit_form.cleaned_data['email']

                forening.organization_no = edit_form.cleaned_data['organization_no']
                forening.gmap_url = edit_form.cleaned_data['gmap_url']
                forening.facebook_url = edit_form.cleaned_data['facebook_url']
                forening.save()
                messages.info(request, 'forening_save_success')
                cache.delete('foreninger.all.sorted_by_name')
                cache.delete('foreninger.all.sorted_by_name.with_active_url')
                cache.delete('foreninger.all.sorted_by_type')
                cache.delete('forening.%s' % forening.id)
                cache.delete('forening.main_foreninger.%s' % forening.id)
                return redirect('admin.forening.views.index', current_forening.id)
            else:
                context.update({'edit_form': edit_form})
                return render(request, 'common/admin/forening/index.html', context)

        elif request.POST.get('form') == 'create':
            create_form = ForeningDataForm(request.user, request.POST, prefix='create')
            if create_form.is_valid():
                forening = Forening()
                forening.name = create_form.cleaned_data['name']
                forening.type = create_form.cleaned_data['type']
                if forening.type == 'turgruppe':
                    forening.group_type = create_form.cleaned_data['group_type']
                else:
                    forening.group_type = ''
                forening.post_address = create_form.cleaned_data['post_address']
                forening.visit_address = create_form.cleaned_data['visit_address']
                forening.zipcode = create_form.cleaned_data['zipcode']

                if create_form.cleaned_data['choose_contact'] == 'person':
                    if create_form.cleaned_data['contact_person'] is not None:
                        forening.contact_person = create_form.cleaned_data['contact_person']
                        forening.contact_person_name = ''
                    else:
                        forening.contact_person = None
                        forening.contact_person_name = create_form.cleaned_data['contact_person_name']
                else:
                    forening.contact_person = None
                    forening.contact_person_name = ''

                forening.phone = create_form.cleaned_data['phone']
                forening.email = create_form.cleaned_data['email']

                forening.organization_no = create_form.cleaned_data['organization_no']
                forening.gmap_url = create_form.cleaned_data['gmap_url']
                forening.facebook_url = create_form.cleaned_data['facebook_url']
                forening.save()

                # Set M2M-fields after the initial db-save
                forening.parents = create_form.cleaned_data['parents']
                forening.counties = create_form.cleaned_data['counties']

                # Add the current user as admin on the new forening
                role = ForeningRole(
                    user=request.user,
                    forening=forening,
                    role='admin',
                )
                role.save()
                # FIXME: We can't delete the permission cache for all users, so some may find that they can't edit
                # the new forening even though they should be able, until the cache (which is currently 24h) expires.
                cache.delete('user.%s.all_foreninger' % request.user.id)

                messages.info(request, 'forening_create_success')
                request.session['active_forening'] = forening.id
                cache.delete('foreninger.all.sorted_by_name')
                cache.delete('foreninger.all.sorted_by_name.with_active_url')
                cache.delete('foreninger.all.sorted_by_type')
                cache.delete('forening.%s' % forening.id)
                cache.delete('forening.main_foreninger.%s' % forening.id)
                # Since GET url == POST url, we need to specifically set the tab hashtag we want, or the existing
                # one (create) will be kept
                return redirect('%s#metadata' % reverse('admin.forening.views.index', args=[current_forening.id]))
            else:
                context.update({'create_form': create_form})
                return render(request, 'common/admin/forening/index.html', context)

        else:
            return redirect('admin.forening.views.index', current_forening.id)
예제 #22
0
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)
예제 #23
0
def send_restore_password_email(request):
    if 'email' not in request.POST:
        raise PermissionDenied

    email = request.POST['email'].strip()

    if not validator.email(email):
        return HttpResponse(json.dumps({'status': 'invalid_email'}))

    # The address might match one non-member, check it:
    local_matches = list(User.objects.filter(memberid__isnull=True, email=email))

    # The address might match several members, registered or not
    focus_unregistered_matches = False

    # Search through matching Actors
    for actor in Actor.get_personal_members().filter(email=email):
        try:
            # Ok, look for any matching active user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=actor.memberid,
                is_inactive=False # ignore inactive users; these need to register first
            )

            # Reset state if this user was previously pending but is now a proper member
            if user.is_pending:
                user.is_pending = False
                user.save()

            # Reset state if this user was previously marked as expired for some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            local_matches.append(user)
        except User.DoesNotExist:
            # There is an actor but no corresponding user - inform the user that they need to register
            focus_unregistered_matches = True

    # Now search through matching active enrollments
    for enrollment in Enrollment.filter_on_email(email):
        try:
            # Ok, look for any matching active AND pending user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=enrollment.memberid,
                is_pending=True,
                is_inactive=False # ignore inactive users; these need to register first
            )

            # Reset state if this user was previously marked as expired for some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            # Check that the user isn't already matched as an Actor since this theoretically could be a duplicate
            if user not in local_matches:
                local_matches.append(user)
        except User.DoesNotExist:
            pass

    if len(local_matches) == 0:
        # No email-address matches.
        if focus_unregistered_matches:
            # Oh, the email address exists in Focus, but the user(s) aren't in our user-base. Let them know.
            return HttpResponse(json.dumps({'status': 'unregistered_email'}))
        else:
            return HttpResponse(json.dumps({'status': 'unknown_email'}))
    else:
        for user in local_matches:
            key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)
            while User.objects.filter(password_restore_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 password-restore-key som allerede finnes!",
                    extra={
                        'request': request,
                        'should_you_play_the_lottery': True,
                        'key': key
                    }
                )
                key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)

            user.password_restore_key = key
            user.password_restore_date = datetime.now()
            user.save()

        if len(local_matches) == 1:
            context = {
                'found_user': user,
                'validity_period': settings.RESTORE_PASSWORD_VALIDITY,
            }
            message = render_to_string('common/user/login/restore-password-email.txt', context, request=request)
        else:
            context = {
                'users': local_matches,
                'validity_period': settings.RESTORE_PASSWORD_VALIDITY,
            }
            message = render_to_string(
                'common/user/login/restore-password-email-multiple.txt',
                context,
                request=request,
            )
        send_mail("Nytt passord på Min side", message, settings.DEFAULT_FROM_EMAIL, [email])
    return HttpResponse(json.dumps({'status': 'success'}))
예제 #24
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))
예제 #25
0
    def handle(self, *args, **options):
        t1 = time.time()
        task_log = TaskLog.objects.create(
            thread=str(uuid4()),
            data={'started': str(datetime.now())},
            name='update-user-status',
        )

        members = User.objects.filter(memberid__isnull=False)
        pending_users = members.filter(is_pending=True)
        normal_users = members.filter(is_pending=False)

        task_log.data['pending_users'] = pending_users.count()
        task_log.data['normal_users'] = normal_users.count()
        task_log.data['update_pending_count'] = 0
        task_log.data['reclaim_for_pending_user_count'] = 0
        task_log.data['expire_users_count'] = 0
        task_log.save()

        # Check for pending users that recently got their Actor, and shouldn't
        # be pending
        i = 1
        for u in pending_users.filter(is_expired=False):
            i += 1
            # This method automatically updates the user if not pending anymore
            u.verify_still_pending(ignore_cache=True)

            if not (i % 1000):
                task_log.data['update_pending_count'] = i
                task_log.save()

        task_log.data['update_pending_count'] = i
        task_log.data['update_pending_done'] = str(datetime.now())
        task_log.save()

        # Check for expired pending users that may have gotten their Actor or
        # Enrollment object back (doesn't make sense that this actually
        # happens, but let's not make assumptions for Focus)
        i = 0
        for u in pending_users.filter(is_expired=True):
            i += 1
            if Actor.get_personal_members().filter(
                    memberid=u.memberid).exists():
                u.is_expired = False
                u.is_pending = False
                u.save()
            elif Enrollment.objects.filter(memberid=u.memberid).exists():
                u.is_expired = False
                u.save()

            if not (i % 1000):
                task_log.data['reclaim_for_pending_user_count'] = i
                task_log.save()

        task_log.data['reclaim_for_pending_user_count'] = i
        task_log.data['reclaim_for_pending_user_done'] = str(datetime.now())
        task_log.save()

        # Check for normal expired users that regained their Actor and
        # shouldn't be expired anymore
        for u in normal_users.filter(is_expired=True):
            if Actor.get_personal_members().filter(
                    memberid=u.memberid).exists():
                u.is_expired = False
                u.save()

        task_log.data['reclaim_for_normal_user_done'] = str(datetime.now())
        task_log.save()

        # Check for normal users that have lost their Actor and should be
        # expired
        i = 0
        for u in normal_users.filter(is_expired=False):
            i += 1
            if not Actor.get_personal_members().filter(
                    memberid=u.memberid).exists():
                u.is_expired = True
                u.save()

            if not (i % 1000):
                task_log.data['expire_users_count'] = i
                task_log.save()

        task_log.data['expire_users_count'] = i
        task_log.data['expire_users_done'] = str(datetime.now())
        task_log.data['ended'] = str(datetime.now())
        task_log.data['duration'] = time.time() - t1
        task_log.complete = True
        task_log.save()
예제 #26
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
예제 #27
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))
예제 #28
0
파일: views.py 프로젝트: simensma/sherpa
def send_restore_password_email(request):
    if not 'email' in request.POST:
        raise PermissionDenied

    if not validator.email(request.POST['email']):
        return HttpResponse(json.dumps({'status': 'invalid_email'}))

    # The address might match one non-member, check it:
    local_matches = list(User.objects.filter(memberid__isnull=True, email=request.POST['email']))

    # The address might match several members, registered or not
    focus_unregistered_matches = False

    # Search through matching Actors
    for actor in Actor.get_personal_members().filter(email=request.POST['email']):
        try:
            # Ok, look for any matching active user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=actor.memberid,
                is_inactive=False # ignore inactive users; these need to register first
            )

            # Reset state if this user was previously pending but is now a proper member
            if user.is_pending:
                user.is_pending = False
                user.save()

            # Reset state if this user was previously marked as expired for some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            local_matches.append(user)
        except User.DoesNotExist:
            # There is an actor but no corresponding user - inform the user that they need to register
            focus_unregistered_matches = True

    # Now search through matching active enrollments
    for enrollment in get_enrollment_email_matches(request.POST['email']):
        try:
            # Ok, look for any matching active AND pending user
            user = User.get_users(
                include_pending=True,
                include_expired=True
            ).get(
                memberid=enrollment.memberid,
                is_pending=True,
                is_inactive=False # ignore inactive users; these need to register first
            )

            # Reset state if this user was previously marked as expired for some reason
            if user.is_expired:
                user.is_expired = False
                user.save()

            # Check that the user isn't already matched as an Actor since this theoretically could be a duplicate
            if user not in local_matches:
                local_matches.append(user)
        except User.DoesNotExist:
            pass

    # Check for matching old user system members - we'll generate a password so that they can login and be imported
    all_sherpa2_matches = Member.objects.filter(email=request.POST['email'])
    # Include expired users when excluding sherpa2 matches - if their current user object is expired,
    # it's irrelevant whether or not the old user account matches
    sherpa2_matches = [m for m in all_sherpa2_matches if not User.objects.filter(memberid=m.memberid, is_inactive=False).exists()]

    if len(local_matches) == 0 and len(sherpa2_matches) == 0:
        # No email-address matches.
        if focus_unregistered_matches:
            # Oh, the email address exists in Focus, but the user(s) aren't in our user-base. Let them know.
            return HttpResponse(json.dumps({'status': 'unregistered_email'}))
        else:
            return HttpResponse(json.dumps({'status': 'unknown_email'}))

    if len(sherpa2_matches) > 0:
        for member in sherpa2_matches:
            sha1 = hashlib.sha1()
            new_password = crypto.get_random_string(length=10)
            sha1.update(new_password)
            member.password = sha1.hexdigest()
            member.save()

        t = loader.get_template('common/user/login/restore-password-email-sherpa25.txt')
        c = RequestContext(request, {
            'member': member,
            'new_password': new_password
        })
        send_mail("Nytt passord på Min side", t.render(c), settings.DEFAULT_FROM_EMAIL, [request.POST['email']])

    if len(local_matches) > 0:
        for user in local_matches:
            key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)
            while User.objects.filter(password_restore_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(u"Noen fikk en random-generert password-restore-key som allerede finnes!",
                    extra={
                        'request': request,
                        'should_you_play_the_lottery': True,
                        'key': key
                    }
                )
                key = crypto.get_random_string(length=settings.RESTORE_PASSWORD_KEY_LENGTH)

            user.password_restore_key = key
            user.password_restore_date = datetime.now()
            user.save()

        if len(local_matches) == 1:
            t = loader.get_template('common/user/login/restore-password-email.txt')
            c = RequestContext(request, {
                'found_user': user,
                'validity_period': settings.RESTORE_PASSWORD_VALIDITY
            })
        else:
            t = loader.get_template('common/user/login/restore-password-email-multiple.txt')
            c = RequestContext(request, {
                'users': local_matches,
                'validity_period': settings.RESTORE_PASSWORD_VALIDITY
            })
        send_mail("Nytt passord på Min side", t.render(c), settings.DEFAULT_FROM_EMAIL, [request.POST['email']])
    return HttpResponse(json.dumps({'status': 'success'}))
예제 #29
0
파일: views.py 프로젝트: simensma/sherpa
def verification(request):
    enrollment = get_or_create_enrollment(request)

    validation = validate(enrollment, require_location=True, require_existing=True)
    if not validation['valid']:
        if 'message' in validation:
            messages.error(request, validation['message'])
        return redirect(*validation['redirect'])

    if enrollment.state == 'payment':
        # Payment has been initiated but the user goes back here - why?
        # Reset the state and let them reinitiate payment when they're ready.
        enrollment.state = 'registration'
        enrollment.save()
    elif enrollment.state == 'complete':
        # A previous registration has been completed, so why would the user come directly here?
        # Just redirect them back to registration which will restart a new registration.
        return redirect("enrollment.views.registration")

    # If existing member is specified, save details and change to that address
    existing_name = ''
    if enrollment.existing_memberid != '':
        actor = Actor.get_personal_members().get(memberid=enrollment.existing_memberid)
        existing_name = "%s %s" % (actor.first_name, actor.last_name)
        enrollment.country = actor.get_clean_address().country.code
        if actor.get_clean_address().country.code == 'NO':
            enrollment.address1 = actor.get_clean_address().field1
        elif actor.get_clean_address().country.code == 'DK' or actor.get_clean_address().country.code == 'SE':
            # Don't change the user-provided address.
            # The user might potentially provide a different address than the existing
            # member, which isn't allowed, but this is preferable to trying to parse the
            # existing address into zipcode, area etc.
            # In order to enforce the same address, the address logic for DK and SE in
            # add_focus_user would have to be rewritten.
            pass
        else:
            # Uppercase the country code as Focus doesn't use consistent casing
            enrollment.country = actor.get_clean_address().country.code
            enrollment.address1 = actor.get_clean_address().field1
            enrollment.address2 = actor.get_clean_address().field2
            enrollment.address3 = actor.get_clean_address().field3

    # Get the area name for this zipcode
    if enrollment.country == 'NO':
        enrollment.area = Zipcode.objects.get(zipcode=enrollment.zipcode).area

    # Figure out which forening this member/these members will belong to
    if enrollment.existing_memberid != '':
        # Use main members' forening if applicable
        focus_forening_id = Actor.get_personal_members().get(memberid=enrollment.existing_memberid).main_forening_id
        forening = cache.get('forening.focus.%s' % focus_forening_id)
        if forening is None:
            forening = Forening.objects.get(focus_id=focus_forening_id)
            cache.set('forening.focus.%s' % focus_forening_id, forening, 60 * 60 * 24 * 7)
    else:
        if enrollment.country == 'NO':
            focus_forening_id = cache.get('focus.zipcode_forening.%s' % enrollment.zipcode)
            if focus_forening_id is None:
                focus_forening_id = FocusZipcode.objects.get(zipcode=enrollment.zipcode).main_forening_id
                cache.set('focus.zipcode_forening.%s' % enrollment.zipcode, focus_forening_id, 60 * 60 * 24 * 7)
            forening = cache.get('forening.focus.%s' % focus_forening_id)
            if forening is None:
                forening = Forening.objects.get(focus_id=focus_forening_id)
                cache.set('forening.focus.%s' % focus_forening_id, forening, 60 * 60 * 24 * 7)
        else:
            # Foreign members are registered with DNT Oslo og Omegn
            forening = cache.get('forening.%s' % Forening.DNT_OSLO_ID)
            if forening is None:
                forening = Forening.objects.get(id=Forening.DNT_OSLO_ID)
                cache.set('forening.%s' % Forening.DNT_OSLO_ID, forening, 60 * 60 * 24 * 7)
    enrollment.forening = forening
    enrollment.save()

    keycount = 0
    youth_or_older_count = 0
    main = None
    for user in enrollment.users.all():
        if main is None or (user.get_age() < main.get_age() and user.get_age() >= AGE_YOUTH):
            # The cheapest option will be to set the youngest member, 19 or older, as main member
            main = user
        if user.get_age() >= AGE_YOUTH:
            youth_or_older_count += 1
        if user.key:
            keycount += 1
    keyprice = keycount * KEY_PRICE
    multiple_main = youth_or_older_count > 1
    context = {
        'enrollment': enrollment,
        'existing_name': existing_name,
        'keycount': keycount,
        'keyprice': keyprice,
        'multiple_main': multiple_main,
        'main': main,
        'age_senior': AGE_SENIOR,
        'age_main': AGE_MAIN,
        'age_youth': AGE_YOUTH,
        'age_school': AGE_SCHOOL,
        'membership_type_names': {
            'senior': get_membership_type_by_codename('senior')['name'],
            'main': get_membership_type_by_codename('main')['name'],
            'youth': get_membership_type_by_codename('youth')['name'],
            'school': get_membership_type_by_codename('school')['name'],
            'child': get_membership_type_by_codename('child')['name'],
            'household': get_membership_type_by_codename('household')['name'],
        },
        'foreign_shipment_price': FOREIGN_SHIPMENT_PRICE,
    }
    context.update(current_template_layout(request))
    return render(request, 'central/enrollment/verification.html', context)
예제 #30
0
def turleder_search(request):
    turledere = User.get_users().filter(turledere__isnull=False)

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

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

        turledere = turledere.filter(memberid__in=[a.memberid for a in actors])

    # Filter on foreninger where the turleder is active
    active_foreninger = json.loads(request.POST['turleder_foreninger_active'])
    if len(active_foreninger) > 0:
        turledere = turledere.filter(turleder_active_foreninger__in=active_foreninger)

    turleder_role = request.POST['turleder_role']
    if turleder_role != '':
        if json.loads(request.POST['turleder_role_include']):
            roles = []
            found = False
            for i in reversed(range(0, len(Turleder.TURLEDER_CHOICES))):
                if Turleder.TURLEDER_CHOICES[i][0] == turleder_role:
                    found = True
                if found:
                    roles.append(Turleder.TURLEDER_CHOICES[i][0])
        else:
            roles = [request.POST['turleder_role']]
        turledere = turledere.filter(turledere__role__in=roles)

    for role in json.loads(request.POST['instruktor_roles']):
        turledere = turledere.filter(instruktor__role=role)

    if json.loads(request.POST['only_kursledere']):
        turledere = turledere.filter(kursleder__isnull=False)

    # Filter on certificates approved by some forening
    forening_approved = None
    if request.POST['turleder_forening_approved'] != '':
        forening_approved = Forening.objects.get(id=request.POST['turleder_forening_approved'])
        turledere = turledere.filter(turledere__forening_approved=forening_approved)

    # Eliminates duplicate rows from the query results
    turledere = turledere.distinct()

    # Store the toal count for current query
    total_count = turledere.count()

    # Limit result set to only 40 elements
    BULK_COUNT = 40
    start = int(request.POST['bulk']) * BULK_COUNT
    end = start + BULK_COUNT
    turledere = turledere[start:end]

    # Prefetch result set in one query and cache them to for future use
    turledere = turledere.prefetch_related('turledere', 'turledere__forening_approved')
    memberids = [t.memberid for t in turledere if cache.get('actor.%s' % t.memberid) is None]

    # If we have more than 2100 parameters, MSSQL will cry, so split it up in bulks
    for i in range(0, len(memberids), settings.MSSQL_MAX_PARAMETER_COUNT):
        memberid_chunk = memberids[i:i + settings.MSSQL_MAX_PARAMETER_COUNT]
        for actor in Actor.get_personal_members().filter(memberid__in=memberid_chunk):
            cache.set('actor.%s' % actor.memberid, actor, settings.FOCUS_MEMBER_CACHE_PERIOD)

    context = {
        'users': turledere,
        'first_bulk': request.POST['bulk'] == '0',
        'total_count': total_count,
        'forening_count': Forening.objects.filter(type='forening').count(),
    }
    return HttpResponse(json.dumps({
        'complete': len(turledere) == 0,
        'html': render_to_string('central/admin/turledere/turleder_search_results.html', context, request=request)
    }))