示例#1
0
def redirect_with_aktivitet_id(request, aktivitet_date_id, slug,
                               date_implemented):
    """Requests to:

      /aktiviteter/123/foo/

    are interpreted as a request to the old URL structure where only
    aktivitet date id was included as a parameter, and will be rewritten to:

      /aktiviteter/12/123/foo/

    Assuming that the date exists, and its related aktivitet id is 12.

    Note that this redirect was implemented 2017-04-26. There are many
    references to the old URLs, in both online and printed forms, so this
    redirect will have to live on for a long time.
    """
    librato.increment(
        'sherpa.aktiviteter.show.old_url_redirect.%s' % date_implemented)
    try:
        aktivitet_date = AktivitetDate.objects.get(id=aktivitet_date_id)
        # Rebuild the path, inserting the aktivitet_id parameter
        if slug:
            postfix = '/%s/%s/' % (aktivitet_date_id, slug)
        else:
            postfix = '/%s/' % (aktivitet_date_id)
        prefix = request.path[: -(len(postfix) - 1)]
        destination = '%s%s%s' % (prefix, aktivitet_date.aktivitet.id, postfix)
        if request.META['QUERY_STRING']:
            destination = '%s?%s' % (destination, request.META['QUERY_STRING'])
        return redirect(destination, permanent=True)
    except AktivitetDate.DoesNotExist:
        raise Http404
示例#2
0
def process_invoice(request):
    if 'enrollment' not in request.session:
        return redirect('enrollment:registration')
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'registration':
        # Whoops, how did we get here without going through payment first? Redirect back.
        return redirect('enrollment:payment_method')
    elif enrollment.state == 'payment':
        # Cool, this is where we want to be.
        pass
    elif enrollment.state == 'complete':
        # Registration has already been completed, redirect forwards to results page
        return redirect('enrollment:result')

    for user in enrollment.users.all():
        user.pending_user = User.create_pending_user(user.memberid)
        user.save()
        librato.increment('sherpa.medlemmer.innmeldinger')

    if enrollment.relation_type == 'family':
        librato.increment('sherpa.familiemedlemskap.innmelding.faktura_valgt')

    prepare_and_send_email(request, enrollment)
    enrollment.save_prices()
    enrollment.state = 'complete'
    enrollment.result = 'success_invoice'
    enrollment.save()
    return redirect('enrollment:result')
示例#3
0
def membership_household_data(request):
    librato.increment('sherpa.api.oauth.membership_household.request')
    if not request.user.is_member():
        # Not a member
        user_data = {
            'hovedmedlem': get_member_data(request.user),
            'husstandsmedlemmer': [],
        }
    elif not request.user.is_related_member():
        # A main member
        user_data = {
            'hovedmedlem': get_member_data(request.user),
            'husstandsmedlemmer': [get_member_data(u) for u in request.user.get_children()],
        }
    else:
        # A household member
        if request.user.get_parent() is not None:
            user_data = {
                'hovedmedlem': get_member_data(request.user.get_parent()),
                'husstandsmedlemmer': [get_member_data(u) for u in request.user.get_parent().get_children()],
            }
        else:
            # A household member without a parent, send it as such
            user_data = {
                'hovedmedlem': None,
                'husstandsmedlemmer': [get_member_data(request.user)],
            }
    return HttpResponse(json.dumps(user_data))
示例#4
0
def confirm_membership_by_token(request):
    """
    Confirm the membership with only the given token as authentication. Note that the URL to this view is hardcoded in
    Focus which sends out emails/SMS with the URL and correct token.
    """
    try:
        token = request.GET['code']
        actor = Actor.objects.get(family_youth_member_accepted_token=token)
        youth_user = User.get_or_create_inactive(memberid=actor.memberid)
        context = {
            'token': token,
            'youth_user': youth_user,
        }
    except (KeyError, Actor.DoesNotExist):
        raise Http404

    if request.method == 'GET':
        return render(request, 'common/user/membership_confirmation.html', context)
    elif request.method == 'POST':
        try:
            User.confirm_membership_by_token(token)
            librato.increment('sherpa.medlemmer.familiemedlemskap.bekreft_ungdomsmedlem')
            return redirect('%s?code=%s' % (reverse('user:confirm_membership_by_token'), token))
        except:
            context['confirmation_error'] = True
            return render(request, 'common/user/membership_confirmation.html', context)
示例#5
0
def convert_to_family_membership(request):
    try:
        request.user.convert_to_family_membership()
        librato.increment('sherpa.medlemmer.familiemedlemskap.konverter_husstand')
    except FocusServiceError:
        messages.error(request, 'focus_service_error')
    finally:
        return redirect('user:family')
示例#6
0
文件: views.py 项目: simensma/sherpa
def show(request, id):
    try:
        annonse = Annonse.objects.get(id=id, hidden=False)
    except Annonse.DoesNotExist:
        return render(request, 'central/fjelltreffen/show_not_found.html')

    context = {}
    if request.method == 'POST':
        form = ReplyForm(request.POST) if request.user.is_authenticated() else ReplyAnonForm(request.POST)
        if form.is_valid():
            try:
                # Send the reply-email
                email_context = RequestContext(request, {
                    'annonse': annonse,
                    'reply': {
                        'name': form.cleaned_data['name'],
                        'email': form.cleaned_data['email'],
                        'text': form.cleaned_data['text']
                    }
                })
                content = render_to_string('central/fjelltreffen/reply_email.txt', email_context)
                parse_for_spam(request, form.cleaned_data['name'], form.cleaned_data['email'], form.cleaned_data['text'], annonse)
                send_mail('DNT Fjelltreffen - Svar fra %s' % form.cleaned_data['name'], content, settings.DEFAULT_FROM_EMAIL, [annonse.email], fail_silently=False)
                librato.increment('sherpa.fjelltreffen_svar')
                request.session['fjelltreffen.reply'] = {
                    'name': form.cleaned_data['name'],
                    'email': form.cleaned_data['email'],
                    'text': form.cleaned_data['text']
                }
                return redirect('fjelltreffen.views.show_reply_sent', annonse.id)
            except Exception:
                # Use both a message (for consistency with the report-failure)
                # and context to be able to manipulate the template based on message info
                messages.error(request, 'email_reply_failure')
                context.update({'email_reply_failure': True})
                logger.warning(u"Klarte ikke å sende Fjelltreffen-epost",
                    exc_info=sys.exc_info(),
                    extra={'request': request}
                )
    else:
        if request.user.is_authenticated():
            form = ReplyForm(initial={
                'name': request.user.get_full_name(),
                'email': request.user.get_email()
            })
        else:
            form = ReplyAnonForm()

    report = ''
    if 'fjelltreffen.report' in request.session:
        report = request.session['fjelltreffen.report']
        del request.session['fjelltreffen.report']

    context.update({
        'annonse': annonse,
        'form': form,
        'report': report})
    return render(request, 'central/fjelltreffen/show.html', context)
示例#7
0
    def process_request(self, request):
        ua_string = request.META.get('HTTP_USER_AGENT')
        if not ua_string:
            return

        if any([c.search(ua_string) for c in crawlers]):
            librato.increment('sherpa.backend.requests.crawler')
        else:
            librato.increment('sherpa.backend.requests.human')
示例#8
0
def temporary_redirect(request, aktivitet_date_id, date_implemented):
    """
    The URL path to the 'description' view was previously renamed. This view redirects requests to the old path to the
    new correct destination.
    """
    # The date the redirect was implemented is included in the metric key. Check out the relevant metrics to see if the
    # old URLs are still in use before removing the redirect.
    librato.increment("sherpa.aktiviteter.show.old_url_redirect.%s" % date_implemented)
    return redirect("aktiviteter:description", aktivitet_date_id, permanent=True)
示例#9
0
def confirm_membership(request):
    try:
        request.user.confirm_membership()
        librato.increment('sherpa.medlemmer.familiemedlemskap.bekreft_ungdomsmedlem')
        messages.info(request, 'membership_confirmed')
    except FocusServiceError:
        messages.error(request, 'focus_service_error')
    finally:
        return redirect('user:home')
示例#10
0
def add_family_member(request):
    if request.method != 'POST' \
            or 'memberid' not in request.POST \
            or 'country' not in request.POST \
            or (request.POST['country'] == 'NO' and 'zipcode' not in request.POST):
        return redirect('user:family')

    try:
        # Include pending users in order to give an explicit error message
        new_family_member = User.get_users(include_pending=True).get(memberid=request.POST['memberid'])
    except (User.DoesNotExist, ValueError):
        messages.error(request, 'user_does_not_exist')
        return redirect('user:family')

    if not new_family_member.is_member():
        messages.error(request, 'user_is_not_member')
        return redirect('user:family')

    if new_family_member.address.country.code != request.POST['country']:
        messages.error(request, 'invalid_address')
        return redirect('user:family')

    if new_family_member.address.country.code == 'NO' \
            and new_family_member.address.zipcode.zipcode != request.POST['zipcode']:
        messages.error(request, 'invalid_address')
        return redirect('user:family')

    if new_family_member.is_pending:
        messages.error(request, 'user_is_pending')
        return redirect('user:family')

    if new_family_member == request.user:
        messages.error(request, 'user_is_current_user')
        return redirect('user:family')

    if new_family_member.has_family():
        messages.error(request, 'user_has_family')
        return redirect('user:family')

    if new_family_member.is_lifelong_member():
        messages.error(request, 'user_is_lifelong_member')
        return redirect('user:family')

    if new_family_member.get_dnt_age() >= settings.MEMBERSHIP['AGES']['MAIN'] \
            and request.user.family.has_max_adult_members():
        messages.error(request, 'user_is_adult_and_max_adults_reached')
        return redirect('user:family')

    assert request.user.has_family(), "User without family (single or not) should not be able to add family members"
    try:
        request.user.family.add_family_member(new_family_member)
        librato.increment('sherpa.medlemmer.familiemedlemskap.legg_til.eksisterende')
    except FocusServiceError:
        messages.error(request, 'focus_service_error')
    finally:
        return redirect('user:family')
示例#11
0
def url_versioning(request, resource, version, require_authentication=True):
    try:
        if require_authentication and not authenticate(request):
            raise invalid_authentication_exception()
        format = requested_representation_from_url(request)
        librato.increment('sherpa.api.tailored.url_versioning')
        librato.increment('sherpa.api.tailored.version.v%s' % version)
        return call_api(request, resource, version, format)
    except BadRequest as e:
        return e.response()
示例#12
0
    def get(code):
        """Lookup and create the aktivitet with the given turkode in Montis' API"""
        librato.increment('sherpa.requests.montis')

        try:
            r = requests.get(
                "%s/%s/" % (settings.DNTOSLO_MONTIS_API_URL, code),
                params={
                    'client': 'dnt',
                    'autentisering': settings.DNTOSLO_MONTIS_API_KEY,
                },
            )
        except (requests.ConnectionError, requests.exceptions.SSLError):
            raise MontisDateUnretrievable

        if r.status_code == 404:
            raise MontisDateNotFound

        if r.status_code != 200:
            logger.warning(
                "Montis API didn't return a valid HTTP response",
                extra={
                    'code': code,
                    'response': r,
                    'body': r.text,
                    'http_status_code': r.status_code,
                }
            )
            raise MontisDateInvalid

        try:
            return Aktivitet(
                code=code,
                dates=[
                    AktivitetDate(**AktivitetDate.map_fields(json_date))
                    for json_date in r.json()
                ],
            )
        except KeyError:
            # May occur if the corresponding Montis date doesn't send all the expected fields
            logger.warning(
                "Montis API returned invalid data",
                exc_info=sys.exc_info(),
                extra={
                    'code': code,
                    'response': r,
                    'body': r.text,
                    'http_status_code': r.status_code,
                }
            )
            raise MontisDateInvalid
示例#13
0
def header_versioning(request, versions, require_authentication=True):
    try:
        if require_authentication and not authenticate(request):
            raise invalid_authentication_exception()
        version, format = requested_representation_from_header(request)
        try:
            resource = [v for v in versions if v['version'] == version][0]['resource']
        except IndexError:
            return invalid_version_response(version)
        librato.increment('sherpa.api.tailored.header_versioning')
        librato.increment('sherpa.api.tailored.version.%s' % version)
        return call_api(request, resource, version, format)
    except BadRequest as e:
        return e.response()
示例#14
0
def confirm_family_member_enrollment(request):
    if 'user.family.validated_user' not in request.session:
        return redirect('user:family')

    del request.session['user.family.enrollment_form']
    new_family_member = request.session.pop('user.family.validated_user')
    new_family_member['dob'] = datetime.strptime(new_family_member['dob'], "%Y-%m-%d").date()

    assert request.user.has_family(), "User without family (single or not) should not be able to enroll family members"
    try:
        request.user.family.enroll_family_member(new_family_member)
        librato.increment('sherpa.medlemmer.familiemedlemskap.legg_til.nytt_medlem')
    except FocusServiceError:
        messages.error(request, 'focus_service_error')
    finally:
        return redirect('user:family')
def forening(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.forening.request')

        if 'bruker_sherpa_id' in request.GET or 'bruker_medlemsnummer' in request.GET:
            try:
                # Lookup by specified members' access
                if 'bruker_sherpa_id' in request.GET and 'bruker_medlemsnummer' in request.GET:
                    user = User.get_users(include_pending=True).get(id=request.GET['bruker_sherpa_id'], memberid=request.GET['bruker_medlemsnummer'])
                elif 'bruker_sherpa_id' in request.GET:
                    user = User.get_users(include_pending=True).get(id=request.GET['bruker_sherpa_id'])
                elif 'bruker_medlemsnummer' in request.GET:
                    try:
                        user = User.get_or_create_inactive(memberid=request.GET['bruker_medlemsnummer'])
                    except (User.DoesNotExist, ValueError):
                        # No such member
                        raise User.DoesNotExist

                foreninger = [get_forening_data(f) for f in user.all_foreninger()]
                librato.increment('sherpa.api.tailored.forening.response.200')
                return HttpResponse(json.dumps(foreninger))

            except (User.DoesNotExist, ValueError):
                librato.increment('sherpa.api.tailored.forening.response.404')
                raise BadRequest(
                    "A member matching that 'sherpa_id', 'bruker_medlemsnummer', or both if both were provided, does not exist.",
                    code=error_codes.RESOURCE_NOT_FOUND,
                    http_code=404
                )
        else:
            librato.increment('sherpa.api.tailored.forening.response.400')
            raise BadRequest(
                "You must supply either a 'bruker_sherpa_id' or 'bruker_medlemsnummer' parameter for forening lookup by member. Only this form of forening-lookup is implemented in this version.",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )
    else:
        librato.increment('sherpa.api.tailored.forening.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
示例#16
0
def temporary_redirect(request, aktivitet_date_id, date_implemented):
    """
    The URL path to the 'description' view was previously renamed. This view
    redirects requests to the old path to the
    new correct destination.
    """
    # The date the redirect was implemented is included in the metric key.
    # Check out the relevant metrics to see if the old URLs are still in use
    # before removing the redirect.
    try:
        aktivitet_date = AktivitetDate.objects.select_related('aktivitet').get(
            id=aktivitet_date_id)
        librato.increment(
            'sherpa.aktiviteter.show.old_url_redirect.%s' % date_implemented)
        return redirect(
            'aktiviteter:description', aktivitet_date.aktivitet.id,
            aktivitet_date_id, permanent=True)
    except:
        raise Http404
示例#17
0
def send_sms(number, message, logging_extra={}):
    """
    Send an SMS message to the given number. Raises SMSGatewayDeliveryError if the SMS message couldn't be delivered
    through the SMS gateway for any reason. The logging_extra parameter may be filled with extra logging data on failure
    """
    logging_extra["number"] = number
    logging_extra["sms_message"] = message
    try:
        librato.increment("sherpa.requests.sms")
        r = requests.get(settings.SMS_URL % (quote_plus(number), quote_plus(message.encode("utf-8"))))
        if r.text.find("1 SMS messages added to queue") == -1:
            logging_extra["request_object"] = r
            logging_extra["response_text"] = r.text
            logger.error("Fikk ikke sendt SMS: Ukjent status-svar fra SMS-gateway", extra=logging_extra)
            raise SMSGatewayDeliveryError("Unknown response status")
    except requests.ConnectionError:
        logger.error(
            "Fikk ikke sendt SMS: Kan ikke koble til SMS-gateway", exc_info=sys.exc_info(), extra=logging_extra
        )
        raise SMSGatewayDeliveryError("Connection error")
def members(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.medlem.request')

        try:
            if 'sherpa_id' in request.GET and 'medlemsnummer' in request.GET:
                user = User.get_users(include_pending=True).get(id=request.GET['sherpa_id'], memberid=request.GET['medlemsnummer'])
            elif 'sherpa_id' in request.GET:
                user = User.get_users(include_pending=True).get(id=request.GET['sherpa_id'])
            elif 'medlemsnummer' in request.GET:
                try:
                    user = User.get_or_create_inactive(memberid=request.GET['medlemsnummer'])
                except (User.DoesNotExist, ValueError):
                    # No such member
                    raise User.DoesNotExist
            else:
                librato.increment('sherpa.api.tailored.medlem.response.400')
                raise BadRequest(
                    "You must supply either an 'sherpa_id' or 'medlemsnummer' parameter for member lookup",
                    code=error_codes.MISSING_REQUIRED_PARAMETER,
                    http_code=400
                )
            librato.increment('sherpa.api.tailored.medlem.response.200')
            return HttpResponse(json.dumps(get_member_data(user)))
        except (User.DoesNotExist, ValueError):
            librato.increment('sherpa.api.tailored.medlem.response.404')
            raise BadRequest(
                "A member matching that 'sherpa_id', 'medlemsnummer', or both if both were provided, does not exist.",
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )
    else:
        librato.increment('sherpa.api.tailored.medlem.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
示例#19
0
def membership_data(request):
    librato.increment('sherpa.api.oauth.membership.request')

    try:
        token = request.META['HTTP_AUTHORIZATION'].replace('Bearer ', '')
        at = AccessToken.objects.select_related('application').get(token=token)
        client_id = at.application.id
        client_name = at.application.name

        request.user.last_active_oauth_date = datetime.now()
        request.user.save()
        log, created = UserOauthActiveLog.objects.get_or_create(
            user=request.user,
            oauth_client_id=client_id,
            defaults={
                'last_data_date': request.user.last_active_oauth_date,
            })
        if not created:
            log.last_data_date = request.user.last_active_oauth_date
            log.save()
    except Exception as e:
        pass

    return HttpResponse(json.dumps(get_member_data(request.user)))
def membership_fee(request, memberid):
    librato.increment('sherpa.api.tailored.medlemskontingent.request')
    try:
        user = User.get_or_create_inactive(memberid)
        response = json.dumps({
            'id': user.id,
            'hasPaid': user.payment.status['is_paid'],
        })
        librato.increment('sherpa.api.tailored.medlemskontingent.response.200')
        return HttpResponse(response, content_type="application/json")
    except (User.DoesNotExist, ValueError):
        librato.increment('sherpa.api.tailored.medlemskontingent.response.404')
        raise Http404
示例#21
0
def membership_data(request):
    librato.increment('sherpa.api.oauth.membership.request')
    return HttpResponse(json.dumps(get_member_data(request.user)))
示例#22
0
def process_card(request):
    if 'enrollment' not in request.session:
        return redirect('enrollment:registration')
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'registration':
        # Whoops, how did we get here without going through payment first? Redirect back.
        # Note, *this* makes it impossible to use a previously verified transaction id
        # on a *second* registration by skipping the payment view and going straight to this check.
        return redirect('enrollment:payment_method')
    elif enrollment.state == 'payment':
        # Cool, this is where we want to be.
        pass
    elif enrollment.state == 'complete':
        # Registration has already been completed, redirect forwards to results page
        return redirect('enrollment:result')

    # The client's transaction id CAN differ from the one we think is active. Let them override it,
    # given that the transaction id is already registered. Note that the transaction id from the
    # GET parameter is obviously untrusted input.
    try:
        enrollment.transactions.update(active=False)
        active_transaction = enrollment.transactions.get(transaction_id=request.GET['transactionId'])
        active_transaction.active = True
        active_transaction.save()
    except Transaction.DoesNotExist:
        # They returned with a transaction id which we haven't registered on them - cannot see this happen
        # without them tampering with the GET parameter, we'll have to send them back with an error message.
        messages.error(request, 'invalid_transaction_id')
        enrollment.state = 'payment'
        enrollment.save()
        return redirect('enrollment:payment_method')

    if request.GET.get('responseCode') == 'OK':
        try:
            librato.increment('sherpa.requests.nets.process')
            r = requests.get(settings.NETS_PROCESS_URL, params={
                'merchantId': settings.NETS_MERCHANT_ID,
                'token': settings.NETS_TOKEN,
                'operation': 'SALE',
                'transactionId': active_transaction.transaction_id
            })
            response = r.text.encode('utf-8')

            dom = ET.fromstring(response)
            response_code = dom.find(".//ResponseCode")
            response_text = dom.find(".//ResponseText")
            payment_verified = False

            tx_already_processed_explicit = response_code.text == '98'
            tx_already_processed_general = (
                response_code.text == '99'
                and response_text is not None
                and response_text.text == 'Transaction already processed'
            )

            if response_code is None:
                # Crap, we didn't get the expected response from Nets.
                # This has happened a few times before. We'll have to handle it ourselves.
                logger.error(
                    "Mangler 'ResponseCode' element fra Nets",
                    extra={
                        'request': request,
                        'nets_response': response,
                        'enrollment': enrollment,
                        'transaction_id': active_transaction.transaction_id
                    }
                )
                enrollment.state = 'payment'
                enrollment.save()
                context = current_template_layout(request)
                return render(request, 'central/enrollment/payment-process-error.html', context)
            elif tx_already_processed_explicit or tx_already_processed_general:
                # The transaction might have already been processed if the user resends the process_card
                # request - recheck nets with a Query request and verify those details
                sale_response = response
                librato.increment('sherpa.requests.nets.query')
                r = requests.get(settings.NETS_QUERY_URL, params={
                    'merchantId': settings.NETS_MERCHANT_ID,
                    'token': settings.NETS_TOKEN,
                    'transactionId': active_transaction.transaction_id
                })
                response = r.text.encode('utf-8')
                dom = ET.fromstring(response)
                order_amount = int(dom.find(".//OrderInformation/Amount").text)
                captured_amount = int(dom.find(".//Summary/AmountCaptured").text)
                credited_amount = int(dom.find(".//Summary/AmountCredited").text)

                if order_amount == (captured_amount - credited_amount) == enrollment.total_price() * 100:
                    payment_verified = True
                else:
                    logger.warning(
                        "Nets: Prosessert transaksjon matcher ikke forventet beløp",
                        extra={
                            'request': request,
                            'enrollment': enrollment,
                            'nets_sale_response': sale_response,
                            'nets_query_response': response,
                            'transaction_id': active_transaction.transaction_id,
                            'payment_verified': payment_verified,
                            'order_amount': order_amount,
                            'captured_amount': captured_amount,
                            'credited_amount': credited_amount,
                            'total_price_100': enrollment.total_price() * 100
                        }
                    )

            elif response_code.text == 'OK':
                payment_verified = True

            if payment_verified:
                # Mark the transaction as successful
                active_transaction.state = 'success'
                active_transaction.save()

                # Register the payment in focus
                for user in enrollment.users.all():
                    focus_user = FocusEnrollment.objects.get(memberid=user.memberid)
                    focus_user.paid = True
                    focus_user.save()
                    user.pending_user = User.create_pending_user(user.memberid)
                    user.save()
                    librato.increment('sherpa.medlemmer.innmeldinger')

                if enrollment.relation_type == 'family':
                    librato.increment('sherpa.familiemedlemskap.innmelding.kort_betalt')

                prepare_and_send_email(request, enrollment)
                enrollment.save_prices()
                enrollment.state = 'complete'
                enrollment.result = 'success_card'
                enrollment.save()
            else:
                active_transaction.state = 'fail'
                active_transaction.save()

                enrollment.state = 'registration'
                enrollment.result = 'fail'
                enrollment.save()
        except requests.ConnectionError:
            logger.warning(
                "Nets `process` feil",
                exc_info=sys.exc_info(),
                extra={'request': request}
            )
            enrollment.state = 'payment'
            enrollment.save()
            context = current_template_layout(request)
            return render(request, 'central/enrollment/payment-process-error.html', context)

    else:
        active_transaction.state = 'cancel'
        active_transaction.save()

        enrollment.state = 'registration'
        enrollment.result = 'cancel'
        enrollment.save()
    return redirect('enrollment:result')
示例#23
0
def payment(request):
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'registration':
        # All right, enter payment state
        enrollment.state = 'payment'
        enrollment.save()
    elif enrollment.state == 'payment':
        # Already in payment state, redirect them forwards to processing
        if enrollment.payment_method == 'invoice':
            return redirect('enrollment:process_invoice')
        elif enrollment.payment_method == 'card':
            # Let's check for an existing transaction first
            try:
                active_transaction = enrollment.transactions.get(state='register', active=True)
                # Yeah, it's there. Skip payment and redirect forwards to processing
                return redirect("%s?merchantId=%s&transactionId=%s" % (
                    settings.NETS_TERMINAL_URL, settings.NETS_MERCHANT_ID, active_transaction.transaction_id
                ))
            except Transaction.DoesNotExist:
                # No active transactions - maybe a problem occured during payment.
                # Assume payment failed and just redo it - if something failed, we'll know
                # through logs and hopefully discover any double-payments
                pass
    elif enrollment.state == 'complete':
        # Registration has already been completed, redirect forwards to results page
        return redirect('enrollment:result')

    enrollment.payment_method = request.POST.get('payment_method', '')

    # Validate chosen payment method
    if enrollment.payment_method not in ['card', 'invoice']:
        messages.error(request, 'invalid_payment_method')
        return redirect('enrollment:payment_method')

    # Ensure card payment is accepted if chosen
    if enrollment.payment_method == 'card' and not Settings.get_cached().enrollment_accept_card:
        messages.error(request, 'invalid_payment_method')
        return redirect('enrollment:payment_method')

    # Ensure invoice is accepted if chosen
    if enrollment.payment_method == 'invoice' and not Settings.get_cached().enrollment_accept_invoice:
        messages.error(request, 'invalid_payment_method')
        return redirect('enrollment:payment_method')

    # Ensure user is not enrolling through aktivitet if invoice is chosen
    if enrollment.payment_method == 'invoice' and 'innmelding.aktivitet' in request.session:
        messages.error(request, 'invalid_payment_method')
        return redirect('enrollment:payment_method')

    # Ok, we're good to go. Save all users to Focus
    enrollment.save()
    enrollment.save_users_to_focus()

    # If we're paying by invoice, skip ahead to invoice processing
    if enrollment.payment_method == 'invoice':
        return redirect('enrollment:process_invoice')

    # Paying with card, move on.
    order_number = Transaction.generate_order_number()

    # Choose a user as the Nets customer; preferably the main member
    try:
        nets_customer = enrollment.get_chosen_main_member()
    except EnrollmentUser.DoesNotExist:
        # There's no main member, so they're either all children or related to an existing member. We still need a
        # 'main' user though, for the customer data. Try to find the oldest one that *has* contact information.
        nets_customer = enrollment.users.exclude(email='').order_by('dob')[0]
    first_name, last_name = nets_customer.name.rsplit(maxsplit=1)

    description = render_to_string('central/enrollment/payment-terminal.html', request=request)

    # Send the transaction registration to Nets
    try:
        librato.increment('sherpa.requests.nets.register')
        r = requests.get(settings.NETS_REGISTER_URL, params={
            'merchantId': settings.NETS_MERCHANT_ID,
            'token': settings.NETS_TOKEN,
            'orderNumber': order_number,
            'customerFirstName': first_name,
            'customerLastName': last_name,
            'customerEmail': nets_customer.email,
            'currencyCode': 'NOK',
            'amount': enrollment.total_price() * 100,
            'orderDescription': description,
            'redirectUrl': "http://%s%s" % (request.site.domain, reverse("enrollment:process_card"))
        })

        # Sweet, almost done, now just send the user to complete the transaction
        # Consider handling errors here (unexpected XML response or connection error)
        # We recieved a random "Unable to create setup string" message once, ignoring it for now
        response = r.text.encode('utf-8')
        enrollment.transactions.update(active=False)
        transaction = Transaction(
            enrollment=enrollment,
            transaction_id=ET.fromstring(response).find("TransactionId").text,
            order_number=order_number,
            state='register',
            active=True,
        )
        transaction.save()
    except Exception as e:
        # Handle any exception that might occur (requests.ConnectionError, invalid response from Nets, etc.)
        logger.warning(
            "Nets `register` feil",
            exc_info=sys.exc_info(),
            extra={'request': request}
        )
        messages.error(request, 'nets_register_connection_error')
        return redirect('enrollment:payment_method')

    return redirect("%s?merchantId=%s&transactionId=%s" % (
        settings.NETS_TERMINAL_URL, settings.NETS_MERCHANT_ID, transaction.transaction_id
    ))
示例#24
0
def set_main_member(request):
    enrollment = get_or_create_enrollment(request)

    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:registration")

    if request.method != 'POST':
        return redirect("enrollment:verification")

    # Assign the chosen relation type; default to 'household'
    relation_type = request.POST.get('relation-type', 'household')
    if relation_type not in ['family', 'household']:
        raise Exception("Invalid membership relation type '%s' POSTed" % relation_type)
    if relation_type == 'family' and not enrollment.eligible_for_family_membership():
        logger.warning(
            "Enrolling member was able to choose family membership even though not eligible",
            extra={
                'request': request,
                'enrollment': enrollment,
            }
        )
        messages.error(request, 'not_eligible_for_family_membership')
        return redirect('enrollment:verification')
    if relation_type == 'family' and not enrollment.forening.offers_family_membership:
        logger.warning(
            "Enrolling member was able to choose family membership even though their forening doesn't offer it",
            extra={
                'request': request,
                'enrollment': enrollment,
            }
        )
        return redirect('enrollment:verification')
    enrollment.relation_type = relation_type
    enrollment.save()

    # Assign the chosen main member
    enrollment.users.all().update(chosen_main_member=False)
    if request.POST.get('main', '') != '':
        user = enrollment.users.get(id=request.POST['main'])

        if not user.can_be_main_member():
            messages.error(request, 'invalid_main_member')
            return redirect('enrollment:verification')

        user.chosen_main_member = True
        user.save()
    else:
        # No choice for main member was made, which might be OK; check
        if enrollment.existing_memberid != '':
            # There's a relation to an existing member; all right, carry on
            pass
        elif not enrollment.has_potential_main_member():
            # There are only children in this enrollment, no one can be a main member; all right, carry on
            pass
        elif not enrollment.has_multiple_potential_main_members():
            # Okay, there's only one potential main member. We did expect their ID to be POSTed by a hidden input,
            # but no worries; we can deduce who it should be in hindsight. Delegate the logic to the model.
            enrollment.set_single_main_member()
        else:
            # No existing member AND there are multiple potential main members: This shouldn't have happened, might be
            # a UI bug
            logger.warning(
                "More than one available main members and no choice made. Fix the UI",
                extra={
                    'request': request,
                    'enrollment': enrollment,
                }
            )
            messages.error(request, 'no_main_member')
            return redirect('enrollment:verification')

    if enrollment.relation_type == 'family':
        librato.increment('sherpa.familiemedlemskap.innmelding.startet')

    # Successfully set main member; redirect forwards
    return redirect('enrollment:payment_method')
def membership(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.medlemskap.request')

        if not 'medlemsnummer' in request.GET or not 'født' in request.GET:
            librato.increment('sherpa.api.tailored.medlemskap.response.400')
            raise BadRequest(
                "Missing 'medlemsnummer' and/or 'født' parameters'",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            requested_date_of_birth = datetime.strptime(request.GET['født'], "%d.%m.%Y").date()
        except ValueError:
            librato.increment('sherpa.api.tailored.medlemskap.response.400')
            raise BadRequest(
                "Could not parse the 'født' parameter ('%s'), which should be in the following format: 'dd.mm.yyyy'" %
                    request.GET['født'],
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            try:
                user = User.get_or_create_inactive(memberid=request.GET['medlemsnummer'])
            except (User.DoesNotExist, ValueError):
                # No such member
                raise User.DoesNotExist

            # Make sure we have the most up-to-date information; users will often contact membership service and
            # they'll fix their birth date directly in Focus, and then retry some service using this API resource
            user.clear_cache()

            # Verify the requested date of birth
            if user.get_birth_date() != requested_date_of_birth:
                raise User.DoesNotExist

            if 'hele_husstanden' in request.GET:
                if not user.is_related_member():
                    user_data = {
                        'hovedmedlem': get_member_data(user),
                        'husstandsmedlemmer': [get_member_data(u) for u in user.get_children()],
                    }
                else:
                    if user.get_parent() is not None:
                        user_data = {
                            'hovedmedlem': get_member_data(user.get_parent()),
                            'husstandsmedlemmer': [get_member_data(u) for u in user.get_parent().get_children()],
                        }
                    else:
                        # A household member without a parent, send it as such
                        user_data = {
                            'hovedmedlem': None,
                            'husstandsmedlemmer': [get_member_data(user)],
                        }
            else:
                user_data = get_member_data(user)

            librato.increment('sherpa.api.tailored.medlemskap.response.200')
            return HttpResponse(json.dumps(user_data))
        except (User.DoesNotExist, ValueError):
            librato.increment('sherpa.api.tailored.medlemskap.response.404')
            raise BadRequest(
                "A membership with member ID '%s' and date of birth '%s' does not exist." %
                    (request.GET['medlemsnummer'], request.GET['født']),
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )

    else:
        librato.increment('sherpa.api.tailored.medlemskap.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
def prices(request, version, format):
    def format_prices(forening, lang):
        return {
            'overnatting': [{
                'id': lodging.id,
                'navn': lodging.name_eng if lang == 'en' else lodging.name,
                'pris_medlem': lodging.price_member,
                'pris_ikkemedlem': lodging.price_nonmember,
            } for lodging in forening.lodging_prices.all()],

            'proviant': [{
                supply_category.name_eng if lang == 'en' else supply_category.name: [{
                    'id': supply.id,
                    'navn': supply.name_eng if lang == 'en' else supply.name,
                    'pris_medlem': supply.price_member,
                    'pris_ikkemedlem': supply.price_nonmember,
                } for supply in supply_category.supplies.all()]
            } for supply_category in forening.supply_categories.all()]
        }

    librato.increment('sherpa.api.tailored.priser.request')

    if request.method != 'GET':
        librato.increment('sherpa.api.tailored.priser.response.400')
        raise BadRequest(
            "Unsupported HTTP verb '%s'" % request.method,
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400,
        )

    if request.GET.get('språk', 'nb').lower().startswith('en'):
        lang = 'en'
    else:
        lang = 'nb'

    if 'forening' in request.GET:
        try:
            forening = Forening.objects.get(turbasen_object_id=request.GET['forening'])
            return HttpResponse(json.dumps(format_prices(forening, lang)))
        except Forening.DoesNotExist:
            librato.increment('sherpa.api.tailored.priser.response.404')
            raise BadRequest(
                "A forening with object id '%s', does not exist." % request.GET['forening'],
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404,
            )
    elif 'hytte' in request.GET:
        try:
            sted = Sted.get(request.GET['hytte'])
            # @TODO: Use private fields to get the appropriate owner: first forening of privat.juridisk_eier,
            # privat.vedlikeholdes_av
            forening = Forening.objects.get(turbasen_object_id=sted['grupper'][0])
            librato.increment('sherpa.api.tailored.priser.response.200')
            return HttpResponse(json.dumps(format_prices(forening, lang)))
        except DocumentNotFound:
            librato.increment('sherpa.api.tailored.priser.response.404')
            raise BadRequest(
                "A cabin with object id '%s', does not exist." % request.GET['hytte'],
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404,
            )
    else:
        librato.increment('sherpa.api.tailored.priser.response.200')
        return HttpResponse(json.dumps([{
            'object_id': forening.turbasen_object_id,
            'navn': forening.name,
            'priser': format_prices(forening, lang),
        } for forening in Forening.objects.filter(type='forening')]))
def memberid(request, version, format):
    librato.increment('sherpa.api.tailored.medlemsnummer.request')

    if request.method != 'GET':
        librato.increment('sherpa.api.tailored.medlemsnummer.response.400')
        raise BadRequest(
            "Unsupported HTTP verb '%s'" % request.method,
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )

    require_focus(request)

    if 'mobilnummer' not in request.GET:
        librato.increment('sherpa.api.tailored.medlemsnummer.response.400')
        raise BadRequest(
            "Missing required 'mobilnummer' parameter",
            code=error_codes.MISSING_REQUIRED_PARAMETER,
            http_code=400
        )

    phone_number = request.GET['mobilnummer'].strip()
    users = lookup_users_by_phone(phone_number)

    # Send the recipient an SMS
    if len(users) == 0:
        librato.increment('sherpa.api.tailored.medlemsnummer.response.404')
        raise BadRequest(
            "A member with phone number '%s' wasn't found." % phone_number,
            code=error_codes.RESOURCE_NOT_FOUND,
            http_code=404
        )
    elif len(users) == 1:
        user = users[0]
    elif len(users) > 1:
        # Usually, this will be because household members have the same number as their parents.
        # Check if any of these are related, and in that case, use the parent.
        user = None
        for user_to_check in users:
            if user_to_check.is_related_member() and \
                    user_to_check.get_parent() is not None and \
                    user_to_check.get_parent() in users:
                # Ah, this parent is in the result set - probably the one we want, use it
                user = user_to_check.get_parent()
                break
        if user is None:
            # Multiple hits, and they are not related. What do? Pick a random hit for now.
            user = users[0]

    # Delete the user cache in case the number was recently updated; the cache may differ from our raw lookup above
    user.clear_cache()
    result = send_sms_receipt(request, user)
    if result['status'] == 'ok':
        librato.increment('sherpa.api.tailored.medlemsnummer.response.200')
        return HttpResponse(json.dumps({
            'status': 'ok',
            'message': 'An SMS was successfully sent to the member with the given phone number.',
        }))
    elif result['status'] == 'service_fail':
        librato.increment('sherpa.api.tailored.medlemsnummer.response.500')
        raise BadRequest(
            "There is a problem with our SMS gateway and we were unable to send the SMS.",
            code=error_codes.SMS_GATEWAY_ERROR,
            http_code=500
        )
    else:
        # Might happen if we add a new status code to the send_sms_receipt function and forget to account for it here
        logger.error(
            "Unknown SMS return status code '%s'" % result['status'],
            extra={'request': request}
        )
        librato.increment('sherpa.api.tailored.medlemsnummer.response.500')
        raise BadRequest(
            "An internal error occurred while trying to send the SMS. This error has been logged and we'll get it fixed asap.",
            code=error_codes.INTERNAL_ERROR,
            http_code=500
        )
示例#28
0
def index(request):
    turledere = cache.get('admin.turleder_count')
    if turledere is None:
        turledere = Turleder.objects.only(
            # Select only the related approved forening, and only the ID from that model
            'forening_approved',
            'forening_approved__id',
        ).select_related(
            # Join the related forening into this query as we'll traverse that later
            'forening_approved',
        ).distinct(
            # The Turleder model may have >1 references to a user, so select distinctly on user
            'user',
        )

        # Make sure the lazy queryset has been evaluated before caching it
        len(turledere)

        cache.set('admin.turleder_count', turledere, 60 * 60 * 24 * 14)

    turleder_stats = {
        'total': len(turledere),
        # Filter on the local forening in code - it's prefetched, so that's much faster, and it lets us cache the
        # entire query instead of having a seperate cache key per forening
        'local': len([t for t in turledere if t.forening_approved == request.active_forening]),
    }

    aktiviteter = cache.get('admin.aktivitet_count.%s' % request.active_forening.id)
    if aktiviteter is None:
        aktiviteter = AktivitetDate.get_searchable().filter(
            Q(aktivitet__organizer_forening=request.active_forening) |
            Q(aktivitet__co_organizers_forening=request.active_forening),
            start_date__gte=date.today(),
        ).count()
        cache.set('admin.aktivitet_count', aktiviteter, 60 * 60 * 6)

    dashboard_stats = {
        'turledere': turleder_stats,
        'aktiviteter': aktiviteter,
    }

    betablog = cache.get('admin.betablog')
    BETABLOG_ITEM_COUNT = 4
    if betablog is None:
        try:
            betablog = []
            librato.increment('sherpa.requests.betablog')
            r = requests.get("http://beta.dnt.no/", params={'feed': 'rss2'})
            channel = ET.fromstring(r.content).find('channel')
            for item in channel.findall('item')[:BETABLOG_ITEM_COUNT]:
                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,
                    'is_new': pub_date > datetime.now() - timedelta(days=7),
                })
        except:
            logger.warning(
                "Kunne ikke hente innhold fra betabloggen",
                exc_info=sys.exc_info(),
                extra={'request': request}
            )

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

    context = {
        'betablog': betablog,
        'dashboard_stats': dashboard_stats,
    }
    return render(request, 'central/admin/dashboard.html', context)
def membership_price(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.medlemskapspris.request')

        if not 'postnummer' in request.GET:
            librato.increment('sherpa.api.tailored.medlemskapspris.response.400')
            raise BadRequest(
                "Missing required 'postnummer' parameter",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            # Get focus zipcode-forening ID
            focus_forening_id = cache.get('focus.zipcode_forening.%s' % request.GET['postnummer'])
            if focus_forening_id is None:
                focus_forening_id = FocusZipcode.objects.get(zipcode=request.GET['postnummer']).main_forening_id
                cache.set('focus.zipcode_forening.%s' % request.GET['postnummer'], focus_forening_id, 60 * 60 * 24 * 7)

            # Get forening based on zipcode-ID
            forening = Forening.objects.get(focus_id=focus_forening_id)
            price = forening.get_focus_price()

            # Success, return the appropriate data
            librato.increment('sherpa.api.tailored.medlemskapspris.response.200')
            return HttpResponse(json.dumps({
                'forening': {'sherpa_id': forening.id, 'navn': forening.name},
                'pristabell': {
                    'main': {
                        'navn': str(get_membership_type_by_codename('main')['name']),
                        'pris': price.main,
                    },
                    'youth': {
                        'navn': str(get_membership_type_by_codename('youth')['name']),
                        'pris': price.youth,
                    },
                    'senior': {
                        'navn': str(get_membership_type_by_codename('senior')['name']),
                        'pris': price.senior,
                    },
                    'lifelong': {
                        'navn': str(get_membership_type_by_codename('lifelong')['name']),
                        'pris': price.lifelong,
                    },
                    'child': {
                        'navn': str(get_membership_type_by_codename('child')['name']),
                        'pris': price.child,
                    },
                    'school': {
                        'navn': str(get_membership_type_by_codename('school')['name']),
                        'pris': price.school,
                    },
                    'household': {
                        'navn': str(get_membership_type_by_codename('household')['name']),
                        'pris': price.household,
                    },
                }
            }))

        except FocusZipcode.DoesNotExist:
            # The Zipcode doesn't exist in Focus, but if it exists in our Zipcode model, Focus is just not updated
            if Zipcode.objects.filter(zipcode=request.GET['postnummer']).exists():
                logger.warning(
                    "Postnummer finnes i Zipcode, men ikke i Focus!",
                    exc_info=sys.exc_info(),
                    extra={
                        'request': request,
                        'postnummer': request.GET['postnummer']
                    }
                )
                librato.increment('sherpa.api.tailored.medlemskapspris.response.404')
                raise BadRequest(
                    "The postal code '%s' exists, but isn't connected to a Forening. It should be, and we've logged this occurrence." %
                        request.GET['postnummer'],
                    code=error_codes.RESOURCE_NOT_FOUND,
                    http_code=404
                )
            else:
                # This *could* be an entirely new Zipcode, or just an invalid one.
                librato.increment('sherpa.api.tailored.medlemskapspris.response.404')
                raise BadRequest(
                    "The postal code '%s' isn't registered in our database." %
                        request.GET['postnummer'],
                    code=error_codes.RESOURCE_NOT_FOUND,
                    http_code=404
                )

        except Forening.DoesNotExist:
            logger.warning(
                "Focus-postnummer mangler foreningstilknytning!",
                exc_info=sys.exc_info(),
                extra={'request': request}
            )
            librato.increment('sherpa.api.tailored.medlemskapspris.response.404')
            raise BadRequest(
                "The postal code '%s' exists, but isn't connected to a Forening. It should be, and we've logged this occurrence." %
                    request.GET['postnummer'],
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )

    else:
        librato.increment('sherpa.api.tailored.medlemskapspris.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
示例#30
0
def show(request, id):
    try:
        annonse = Annonse.objects.get(id=id, hidden=False)
    except Annonse.DoesNotExist:
        return render(request, 'central/fjelltreffen/show_not_found.html')

    context = {}
    if request.method == 'POST':
        form = ReplyForm(request.POST) if request.user.is_authenticated() else ReplyAnonForm(request.POST)
        if form.is_valid():
            parse_for_spam(
                request,
                form.cleaned_data['name'],
                form.cleaned_data['email'],
                form.cleaned_data['text'],
                annonse,
            )

            try:
                email_context = {
                    'annonse': annonse,
                    'sender': {
                        'name': form.cleaned_data['name'],
                        'email': form.cleaned_data['email'],
                        'text': form.cleaned_data['text']
                    }
                }

                # Send the reply email to the advertiser
                content = render_to_string('central/fjelltreffen/reply_email.txt', email_context, request=request)
                send_mail(
                    'DNT Fjelltreffen - Svar fra %s' % form.cleaned_data['name'],
                    content,
                    settings.DEFAULT_FROM_EMAIL,
                    [annonse.email],
                    fail_silently=False,
                )

                # At this point, the reply email was successful, so send a confirmation copy to the sender
                try:
                    content = render_to_string(
                        'central/fjelltreffen/reply_copy_email.txt',
                        email_context,
                        request=request,
                    )
                    send_mail(
                        'DNT Fjelltreffen - Kopi av ditt svar',
                        content,
                        settings.DEFAULT_FROM_EMAIL,
                        [form.cleaned_data['email']],
                        fail_silently=False,
                    )
                except:
                    request.session['fjelltreffen.reply.email_copy_failure'] = True

                librato.increment('sherpa.fjelltreffen_svar')
                request.session['fjelltreffen.reply'] = {
                    'name': form.cleaned_data['name'],
                    'email': form.cleaned_data['email'],
                    'text': form.cleaned_data['text']
                }
                return redirect('fjelltreffen:show_reply_sent', annonse.id)
            except:
                context['email_reply_failure'] = True
                logger.warning(
                    "Klarte ikke å sende Fjelltreffen-epost",
                    exc_info=sys.exc_info(),
                    extra={'request': request}
                )
    else:
        if request.user.is_authenticated():
            form = ReplyForm(initial={
                'name': request.user.get_full_name(),
                'email': request.user.get_email()
            })
        else:
            form = ReplyAnonForm()

    report = ''
    if 'fjelltreffen.report' in request.session:
        report = request.session['fjelltreffen.report']
        del request.session['fjelltreffen.report']

    context.update({
        'annonse': annonse,
        'form': form,
        'report': report})
    return render(request, 'central/fjelltreffen/show.html', context)