示例#1
0
def send_stall_approved_email(stall):
    if stall.election.polling_places_loaded is False:
        location_info = stall.location_info
        stall_name = location_info["name"]
    else:
        location_info = model_to_dict(stall.polling_place)
        stall_name = location_info["premises"]

    token = str(getrandbits(128))
    signature = make_confirmation_hash(stall.id, token)

    html = get_mail_template(
        "stall_approved_with_mail_optout", {
            "POLLING_PLACE_NAME":
            location_info["name"],
            "POLLING_PLACE_ADDRESS":
            location_info["address"],
            "STALL_NAME":
            stall.name,
            "STALL_DESCRIPTION":
            stall.description,
            "STALL_OPENING_HOURS":
            stall.opening_hours,
            "STALL_WEBSITE":
            stall.website,
            "DELICIOUSNESS":
            getFoodDescription(stall),
            "STALL_PERMALINK":
            "{site_url}/{election_name}/stalls/{stall_id}".format(
                site_url=get_env("PUBLIC_SITE_URL"),
                stall_id=stall.id,
                election_name=get_url_safe_election_name(stall.election)),
            "STALL_EDIT_URL":
            "{site_url}/edit-stall?stall_id={stall_id}&token={token}&signature={signature}"
            .format(site_url=get_env("PUBLIC_SITE_URL"),
                    stall_id=stall.id,
                    token=token,
                    signature=signature),
            "CONFIRM_OPTOUT_URL":
            "{api_url}/0.1/mail/opt_out/?format=json&stall_id={stall_id}&token={token}&signature={signature}"
            .format(api_url=get_env("PUBLIC_API_BASE_URL"),
                    stall_id=stall.id,
                    token=token,
                    signature=signature),
        })

    return send({
        "to":
        stall.email,
        "subject":
        "Your Democracy Sausage stall for {} has been approved!".format(
            stall_name),
        "html":
        html,
    })
示例#2
0
    def __init__(self, election, file, dry_run, config):
        def _get_config_or_none(param_name, config):
            return config[param_name] if self.has_config is True and param_name in config else None

        def check_config_is_valid(config):
            if config is not None:
                for field in config.keys():
                    if field not in allowed_fields:
                        self.logger.error("Config: Invalid field '{}' in config".format(field))

                if "address_fields" in config and "address_format" not in config:
                    self.logger.error("Config: address_format required if address_fields provided")
                if "address_fields" not in config and "address_format" in config:
                    self.logger.error("Config: address_fields required if address_format provided")

                return True

        self.election = election
        self.dry_run = dry_run
        self.logger = self.make_logger()

        allowed_fields = ["filters", "exclude_columns", "rename_columns", "extras", "cleaning_regexes", "address_fields", "address_format", "division_fields", "fix_data_issues", "geocoding", "bbox_validation", "multiple_division_handling"]
        self.has_config = True if config is not None and check_config_is_valid(config) else False
        self.raise_exception_if_errors()
        for field_name in allowed_fields:
            setattr(self, field_name, _get_config_or_none(field_name, config))

        if self.geocoding is not None and self.geocoding["enabled"] is True:
            self.gmaps = googlemaps.Client(key=get_env("GOOGLE_GEOCODING_API_KEY"))

        self.file = file
        file_body = self.file.read()
        encoding = chardet.detect(file_body)["encoding"]
        self.reader = csv.DictReader(StringIO(file_body.decode(encoding)))
        self.polling_places = list(self.reader)
示例#3
0
def verify_webhook(token, timestamp, signature):
    # Check if the timestamp is fresh
    if abs(time.time() - timestamp) > 30:  # seconds
        return False

    return generate_signature(get_env("MAILGUN_API_KEY"),
                              "{}{}".format(timestamp, token)) == signature
示例#4
0
def send(body):
    r = requests.post(
        get_env("MAILGUN_API_BASE_URL") + "/messages",
        auth=("api", get_env("MAILGUN_API_KEY")),
        data={
            **{
                "from": get_env("MAILGUN_FROM_ADDRESS"),
                "h:Reply-To": get_env("MAILGUN_REPLY_TO_ADDRESS"),
            },
            **body
        })

    if r.status_code != 200:
        raise MailgunException("Mailgun Error ({}): {}".format(
            r.status_code, r.text))
    return True
示例#5
0
def send_stall_submitted_email(stall):
    if stall.election.polling_places_loaded is False:
        location_info = stall.location_info
        stall_name = location_info["name"]
    else:
        location_info = model_to_dict(stall.polling_place)
        stall_name = location_info["premises"]

    token = str(getrandbits(128))
    signature = make_confirmation_hash(stall.id, token)

    html = get_mail_template(
        "stall_submitted", {
            "POLLING_PLACE_NAME":
            location_info["name"],
            "POLLING_PLACE_ADDRESS":
            location_info["address"],
            "STALL_NAME":
            stall.name,
            "STALL_DESCRIPTION":
            stall.description,
            "STALL_OPENING_HOURS":
            stall.opening_hours,
            "STALL_WEBSITE":
            stall.website,
            "DELICIOUSNESS":
            getFoodDescription(stall),
            "STALL_EDIT_URL":
            "{site_url}/edit-stall?stall_id={stall_id}&token={token}&signature={signature}"
            .format(site_url=get_env("PUBLIC_SITE_URL"),
                    stall_id=stall.id,
                    token=token,
                    signature=signature),
        })

    return send({
        "to":
        stall.email,
        "subject":
        "Your Democracy Sausage stall for {} has been received!".format(
            stall_name),
        "html":
        html,
    })
示例#6
0
import os

import sentry_sdk
from corsheaders.defaults import default_headers
from sentry_sdk.integrations.django import DjangoIntegration

from demsausage.util import get_env

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = get_env("SECRET_KEY")

# Security
SECURE_SSL_REDIRECT = True
# https://stackoverflow.com/a/22284717
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
X_FRAME_OPTIONS = "DENY"
CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = list(get_env("ALLOWED_HOSTS_AND_WHITELIST").split(","))
CSRF_TRUSTED_ORIGINS = get_env("ALLOWED_HOSTS_AND_WHITELIST").replace(
    "https://", "").split(",")
示例#7
0
def is_development():
    return get_env("ENVIRONMENT") == "DEVELOPMENT"
示例#8
0
def make_confirmation_hash(stall_id, token):
    return generate_signature(get_env("SECRET_KEY"),
                              "{}{}".format(stall_id, token))