示例#1
0
def employees(request):
    """Get a licenses employees from Metrc.
    Args:
        request (HTTPRequest): A `djangorestframework` request.
    """

    # Authenticate the user.
    claims = authenticate_request(request)
    if not claims:
        message = 'Authentication failed. Please use the console or provide a valid API key.'
        return Response({'error': True, 'message': message}, status=403)
    _, project_id = google.auth.default()
    license_number = request.query_params.get('name')

    # Optional: Figure out how to pre-initialize a Metrc client.

    # Get Vendor API key using secret manager.
    # FIXME: Determine where to store project_id, secret_id, and version_id.
    vendor_api_key = access_secret_version(project_id=project_id,
                                           secret_id='metrc_vendor_api_key',
                                           version_id='1')

    # TODO: Get user API key using secret manager.
    user_api_key = access_secret_version(project_id=project_id,
                                         secret_id=f'{license_number}_secret',
                                         version_id='1')

    # Create a Metrc client.
    track = authorize(vendor_api_key, user_api_key)

    # Make a request to the Metrc API.
    data = track.get_employees(license_number=license_number)

    # Return the requested data.
    return Response({'data': data}, content_type='application/json')
示例#2
0
def initialize_traceability(project_id, license_number, version_id):
    """Initialize a Metrc client.
    Optional: Figure out how to pre-initialize and save Metrc client.
    """

    # Get vendor version number.
    admin_data = get_document('admin/metrc')
    vendor_version_id = admin_data['vendor_api_key_secret']['version_id']

    # Get Vendor API key using secret manager.
    vendor_api_key = access_secret_version(
        project_id=project_id,
        secret_id='metrc_vendor_api_key',
        version_id=vendor_version_id
    )

    # Get user API key using secret manager.
    user_api_key = access_secret_version(
        project_id=project_id,
        secret_id=f'{license_number}_secret',
        version_id=version_id
    )

    track = initialize_metrc(vendor_api_key, user_api_key)
    return track
def test_secret_manager():
    """Test Secret Manager by creating a secret, updating the version
    of the secret, then deleting the secret."""

    # Initialize Firebase
    env = environ.Env()
    env.read_env('../../.env')
    credentials = env('GOOGLE_APPLICATION_CREDENTIALS')
    os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials
    firebase.initialize_firebase()

    # Mock license.
    license_data = {
        'license_number': 'test',
        'license_type': 'lab',
        'state': 'OK',
        'user_api_key': '123',
    }
    license_number = license_data['license_number']
    user_api_key = license_data['user_api_key']

    # Create a secret.
    project_id = 'cannlytics'
    secret_id = f'{license_number}-secret'
    try:
        version_id = firebase.create_secret(project_id, secret_id, user_api_key)
    except: # AlreadyExists error
        pass # Secret may already be created.

    # Add the secret's secret data.
    secret = firebase.add_secret_version(project_id, secret_id, user_api_key)
    version_id = secret.split('/')[-1]

    # Get the secret.
    # In production the secret ID and version ID are stored with the license data.
    user_api_key = firebase.access_secret_version(project_id, secret_id, version_id)
    assert user_api_key == license_data['user_api_key']
def unsubscribe(request):
    """Unsubscribe a user from a PayPal subscription."""

    # Authenticate the user.
    claims = authenticate_request(request)
    try:
        uid = claims['uid']
        user_email = claims['email']
    except KeyError:
        response = {'success': False, 'message': 'Unable to authenticate.'}
        return JsonResponse(response)

    # Get the subscription they wish to unsubscribe from.
    data = loads(request.body)
    plan_name = data['plan_name']

    # Unsubscribe the user with the PayPal SDK.
    try:
        project_id = os.environ['GOOGLE_CLOUD_PROJECT']
        payload = access_secret_version(project_id, 'paypal', 'latest')
        paypal_secrets = loads(payload)
        paypal_client_id = paypal_secrets['client_id']
        paypal_secret = paypal_secrets['secret']
        paypal_access_token = get_paypal_access_token(paypal_client_id,
                                                      paypal_secret)
        user_data = get_document(f'users/{uid}')
        subscription_id = user_data[f'{plan_name}_subscription_id']
        cancel_paypal_subscription(paypal_access_token, subscription_id)
        updated_user_data = {'support': False}
        updated_user_data[f'{plan_name}_subscription_id'] = ''
        update_document(f'users/{uid}', updated_user_data)
    except:
        subscription_id = 'Unidentified'

    # Notify the staff.
    staff_message = """Confirm that the following subscription has been canceled:
    User: {}
    Email: {}
    Plan: {}
    Subscription ID: {}
    """.format(uid, user_email, plan_name, subscription_id)
    send_mail(
        subject='User unsubscribed from a PayPal subscription.',
        message=staff_message,
        from_email=DEFAULT_FROM_EMAIL,
        recipient_list=[DEFAULT_FROM_EMAIL],
        fail_silently=False,
    )

    # Create an activity log.
    create_log(
        ref='logs/website/subscriptions',
        claims=claims,
        action=f'User ({user_email}) unsubscribed from {plan_name}.',
        log_type='subscription',
        key='subscribe',
        changes=data,
    )

    # Return a success message.
    message = 'Successfully unsubscribed from subscription.'
    response = {'success': True, 'message': message}
    return JsonResponse(response)
示例#5
0
def buy_data(request):
    """Facilitate the purchase of a dataset on the data market."""

    # Ensure that the user has a valid email.
    data = loads(request.body)
    try:
        user_email = data['email']
        validate_email(user_email)
    except ValidationError:
        response = {
            'success': False,
            'message': 'Invalid email in request body.'
        }
        return JsonResponse(response)

    # Check if the payment ID is valid.
    # FIXME: Make this required.
    try:
        payment_id = data['payment_id']
        print('Checking payment ID:', payment_id)
        project_id = os.environ['GOOGLE_CLOUD_PROJECT']
        payload = access_secret_version(project_id, 'paypal', 'latest')
        paypal_secrets = loads(payload)
        paypal_client_id = paypal_secrets['client_id']
        paypal_secret = paypal_secrets['secret']
        paypal_access_token = get_paypal_access_token(paypal_client_id,
                                                      paypal_secret)
        payment = get_paypal_payment(paypal_access_token, payment_id)
        assert payment['id'] == payment_id
        print('Payment ID matched captured payment ID.')
    except:
        pass

    # Future work: Ensure that the user has a .edu email for student discount?

    # Get the dataset zipped folder.
    dataset = data['dataset']
    file_name = dataset['file_name']
    file_ref = dataset['file_ref']
    download_url = get_file_url(file_ref)
    # Optional: Allow for specifying suffix options.
    short_url = create_short_url(FIREBASE_API_KEY, download_url,
                                 FIREBASE_PROJECT_ID)
    data['download_url'] = download_url
    data['short_url'] = short_url

    # Keep track of a user's downloaded data if the user is signed in.
    now = datetime.now()
    iso_time = now.isoformat()
    data['created_at'] = iso_time
    data['updated_at'] = iso_time
    try:
        claims = authenticate_request(request)
        uid = claims['uid']
        update_document(f'users/{uid}/datasets', {**data, **{'uid': uid}})
    except KeyError:
        pass

    # Optional: Read the email template from storage?
    # Optional: Use HTML template.
    # Optional: Load messages from state?
    # # template_url = 'website/emails/newsletter_subscription_thank_you.html'
    # Optional: Actually attach the datafile (too large a file problem?)

    # Email the data to the user.
    message = f'Congratulations on your new dataset,\n\nYou can access your data with the following link:\n\n{short_url}\n\nYou can monitor the market for new datasets.\n\nAlways here to help,\nThe Cannlytics Team'  #pylint: disable=line-too-long
    subject = 'Dataset Purchased - Your Dataset is Attached'
    send_mail(
        subject=subject,
        message=message,
        from_email=DEFAULT_FROM_EMAIL,
        recipient_list=[user_email, DEFAULT_FROM_EMAIL],
        fail_silently=False,
        # html_message = render_to_string(template_url, {'context': 'values'})
    )

    # Create an activity log.
    create_log(
        ref='logs/website/payments',
        claims=claims,
        action=f'User ({user_email}) bought a dataset.',
        log_type='market',
        key='buy_data',
        changes=data,
    )

    # Return the file to download.
    return FileResponse(open(download_url, 'rb'), filename=file_name)
示例#6
0
env_file = os.path.join(BASE_DIR, '.env')

# Attempt to load the Project ID into the environment, safely failing on error.
try:
    _, os.environ['GOOGLE_CLOUD_PROJECT'] = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
    pass

# Use a local secret file, if provided.
# Otherwise retrieve the secrets from Secret Manager.
if os.path.isfile(env_file):
    env.read_env(env_file)
else:
    try:
        project_id = os.environ['GOOGLE_CLOUD_PROJECT']
        payload = access_secret_version(project_id, SECRET_SETTINGS_NAME, 'latest')
        env.read_env(io.StringIO(payload))
    except KeyError:
        raise Exception('No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.')

# Access the secret key.
SECRET_KEY = env('SECRET_KEY')

# Get production status. When publishing, ensure PRODUCTION in .env is `True`.
try:
    PRODUCTION = env('PRODUCTION')
except:
    PRODUCTION = 'True'

# Toggle Django debug mode if not in production.
if PRODUCTION == 'True':