Example #1
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
Example #2
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()
Example #3
0
    def confirm_membership(self):
        """Register that this member has confirmed their membership"""
        status = self.actor.get_membership_confirmation_status()
        if status.Bekreftet:
            return

        Actor.confirm_membership_by_token(status.Token)
Example #4
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin.users.views.index')

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

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

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

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

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

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

    context = RequestContext(request, {
        'users': users,
        'actors_without_user': actors_without_user,
        'expired_users': expired_users
    })
    return HttpResponse(render_to_string('common/admin/users/user_results.html', context))
Example #5
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,
    }))
Example #6
0
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'
    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'])
Example #8
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)
Example #9
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)
Example #10
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
Example #11
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)
Example #12
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
    }))
Example #13
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
Example #14
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
            )
Example #15
0
    def enroll_family_member(self, user_data):
        """Enroll the given user and add them to this users' family membership.
        user_data is a dict with the following keys:
        - first_name
        - last_name
        - dob
        - gender
        - phone
        - email"""
        try:
            focus_service = suds.client.Client(settings.FOCUS_WSDL_URL)

            # Use a kwargs dictionary to avoid SyntaxError with non-ascii unicode characters for parameter names
            params = {
                'Token': settings.FOCUS_WSDL_TOKEN,
                'Hovedmedlem': self.actor.memberid,
                'Husstandsnummer': 0,
                'Fornavn': user_data['first_name'],
                'Etternavn': user_data['last_name'],
                'Født': datetime(
                    year=user_data['dob'].year,
                    month=user_data['dob'].month,
                    day=user_data['dob'].day,
                ),
                'Kjonn': Actor.convert_gender(user_data['gender']),
                'Mobil': user_data['phone'],
                'Epost': user_data['email'],
                'Gjensidige': user_data['accepts_partneroffers'],
            }
            result = focus_service.service.EndreHusstand(**params)
            if result != 'OK':
                raise Exception("Unknown Focus Webservice result '%s'" % result)
        except:
            logger.warning(
                "Feil med Focus webtjeneste",
                exc_info=sys.exc_info(),
                extra={
                    'member': self,
                    'user_data': user_data,
                },
            )
            raise FocusServiceError
Example #16
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
Example #17
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
Example #18
0
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
    }))
Example #19
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
Example #20
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))
Example #21
0
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
    }))
Example #22
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin:users.index')

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

    SEARCH_MAX_HITS = 40

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

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

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

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

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

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

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

    context = {
        'users': users,
        'actors_without_user': actors_without_user,
        'expired_users': expired_users,
        'max_hits_exceeded': max_hits_exceeded,
    }
    return HttpResponse(render_to_string('central/admin/users/user_results.html', context, request=request))
Example #23
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
Example #24
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)
Example #25
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'}))
    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()
Example #27
0
    def get_queryset(self):
        # This method uses Focus and local users to compile a search result
        # containing users.

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

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

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

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

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

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

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

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

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

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

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

        self.lazy_queryset = users
        return users
Example #28
0
def index(request):
    total_membership_count = cache.get('admin.total_membership_count')
    local_membership_count = cache.get('admin.local_membership_count.%s' % request.active_forening.id)
    if total_membership_count is None or local_membership_count is None:
        if request.db_connections['focus']['is_available']:
            all_active_members = Actor.all_active_members()
            total_membership_count = all_active_members.count()
            local_membership_count = all_active_members.filter(
                main_forening_id__in=[f.focus_id for f in request.active_forening.get_main_foreninger()],
            ).count()
            cache.set('admin.total_membership_count', total_membership_count, 60 * 60 * 12)
            cache.set('admin.local_membership_count.%s' % request.active_forening.id, local_membership_count, 60 * 60 * 12)
        else:
            # Fallback if Focus is down
            total_membership_count = None
            local_membership_count = None

    turledere = cache.get('admin.turleder_count')
    if turledere is None:
        turledere = User.get_users().filter(turledere__isnull=False).distinct().count()
        cache.set('admin.turleder_count', turledere, 60 * 60 * 6)

    aktiviteter = cache.get('admin.aktivitet_count')
    if aktiviteter is None:
        aktiviteter = Aktivitet.objects.filter(
            Q(forening=request.active_forening) |
            Q(co_foreninger=request.active_forening),
            pub_date__lte=date.today(),
            published=True,
            private=False,
        ).count()
        cache.set('admin.aktivitet_count', aktiviteter, 60 * 60 * 6)

    dashboard_stats = {
        'members': {
            'total': "{:,}".format(total_membership_count) if total_membership_count is not None else '?',
            'local': "{:,}".format(local_membership_count) if local_membership_count is not None else '?',
        },
        'turledere': turledere,
        'aktiviteter': aktiviteter,
    }

    betablog = cache.get('admin.betablog')
    if betablog is None:
        try:
            betablog = []
            r = requests.get("http://beta.dnt.no/", params={'feed': 'rss2'})
            channel = etree.fromstring(r.content).find('channel')
            for item in channel.findall('item'):
                content = item.find('description').text
                image = None
                m = re.search('<img.*?src="(.*?)" ', content)
                if m is not None:
                    image = m.group(1)
                pub_date = datetime.strptime(item.find('pubDate').text[:-6], "%a, %d %b %Y %H:%M:%S")

                betablog.append({
                    'title': item.find('title').text,
                    'link': item.find('link').text,
                    'content': content,
                    'image': image,
                    'pub_date': pub_date,
                })
        except (requests.ConnectionError, AttributeError):
            pass

        cache.set('admin.betablog', betablog, 60 * 60 * 12)

    context = {
        'betablog': betablog,
        'dashboard_stats': dashboard_stats,
    }
    return render(request, 'common/admin/dashboard.html', context)
Example #29
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)
    }))
Example #30
0
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'}))