Пример #1
0
def gdpr_consent(shop_url, referringpage):
    # Create a unique encrypted ID for this removal to write in Audit Log and address2 line
    removal_id_str = datetime.datetime.now().strftime('%B-%d-%Y %H:%M:%S') + 'consent'
    dataevent_id = encrypt_ids(removal_id_str)

    # #######################################################
    # Log Data Removal in Audit Table (All times are in UTC)
    # #######################################################
    current_datetime = datetime.datetime.now() 
    action = 'Data Consent'
    method = 'Consent Form "Accept Button"'
    comment = 'Data subject granted consent to data collection for the purpose of marketing.'
    status = 'Completed'
    legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
    purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
    customer_id= 'Unregistered Customer'

    # Create AuditLog Instance 
    AuditLogInst = DataEventLogger(shop_url)
    # Add Consent Granted Entry line
    AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                customer_id, purpose, status, legal_basis)
Пример #2
0
def gdpr_removal_send_email(removal_request_email, shop_url, referringpage, country):
    request_date = datetime.date.today().strftime('%B %d %Y')

    # Create and Activate session for API calls
    ShopDeatzInst = ShopDeatz.objects.get(shop_url=shop_url)
    session = shopify.Session(shop_url, ShopDeatzInst.auth_token)
    shopify.ShopifyResource.activate_session(session)

    # Gets an object that contains all the shop info eqvalent to GET endpoint /admin/shop.json
    shop_info = shopify.Shop.current()
    
    # Make customer instance to check if customer email exists customer deatails (returns a list so use the first one)
    search_query = 'email:' + str(removal_request_email)
    CustomerInst = shopify.Customer.search(q=search_query)

    if len(CustomerInst) <= 0:
        # ##############################################################
        # Log INVALID Data Removal in Audit Table (All times are in UTC)
        # ##############################################################
        current_datetime = datetime.datetime.now()
        action = 'Invalid Data Removal Request'
        method = 'Data Removal Form'
        comment = 'Email does not correspond to any record in the database. No data removed.' 
        customer_id = 'Unregistered Customer'
        marketing_consent = '-'
        status = 'Completed'
        legal_basis = '-'
        purpose = '-'

        # Create AuditLog Instance 
        AuditLogInst = DataEventLogger(shop_url)

        # Add Data Removal Entry line
        AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)
        return 0

    else:
        pass

    # Generate 101 character random string confirmation code
    confirmation_code = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(101))

    # Check if removal_email exists in RemovalConfirmationCodes in the database for this user 
    # (because user might have clciked multiple times on the delete link by mistake which would generate new entries in the DB)
    # if it exists then just change the confirmation code, otherwise write a new entry for the user email
    try:
        ConfirmationCodesInst = RemovalConfirmationCodes.objects.get(removal_request_email=removal_request_email)
        ConfirmationCodesInst.confirmation_code = confirmation_code
        ConfirmationCodesInst.save()
    except ObjectDoesNotExist: 
        ConfirmationCodesInst = RemovalConfirmationCodes()
        ConfirmationCodesInst.confirmation_code = confirmation_code
        ConfirmationCodesInst.removal_request_email = removal_request_email
        ConfirmationCodesInst.save()
   
    removal_link = "https://cdn1.gdprinsider.ovh/dataevent/?" + "requesttype=confirmremoval" + "&shopurl=" + shop_url \
                     + "&email=" + removal_request_email + "&country=" + country + "&confirm=" + confirmation_code

    SENDER = str(shop_info.name) +  "<*****@*****.**>"
    
    # Replace [email protected] with a "To" address. If your account 
    RECIPIENT = str(removal_request_email)

    # If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
    AWS_REGION = "eu-west-1" 

    # The email body for recipients with non-HTML email clients.
    BODY_TEXT = (
                 "Hi there,\r\n"
                 "In response to your subject data removal request received on %s, please click the following link to "
                 "complete your data removal process.\r\n"
                 "%s \r\n"
                 "Please note that your data will be purged from our store's system and that we will no longer have any trace of "
                 "your customer details and purchase history. As such, you will no longer be entitled to any refunds or product exchanges.\r\n"
                 "Thank you for your inquiry.\r\n"
                 "Regards,\r\n"
                 "%s"
                ) %(
                    request_date,
                    removal_link,
                    str(shop_info.name)
                   )

    # print BODY_TEXT

    ###############################################
    # The HTML body of the email.
    ###############################################
    # FRENCH EMAIL TEMPLATE
    if country == 'France':
        # The subject line for the email.
        SUBJECT = str(shop_info.name) + " - GDPR Demande de Suppression de Données"
        
        # Create French format request_date
        request_date = datetime.date.today().strftime('%d/%m/%Y')

        # Get  content of html template
        template_relative_location = 'templates/emailtemplates/data_del_FR.html'
        filelocation = os.path.join(settings.BASE_DIR, template_relative_location)
        BODY_HTML = ""
        for line in open(filelocation):
            new_line = unicode(line.decode("utf-8"))
            new_line = new_line.rstrip('\n')
            # print new_line
            BODY_HTML = BODY_HTML + new_line
    
    # ALL OTHER (ENGLISH EMAIL TEMPLATE)
    else:
        # The subject line for the email.
        SUBJECT = str(shop_info.name) + " - GDPR Data Removal Request"

        # Get content of html template
        template_relative_location = 'templates/emailtemplates/data_del.html' 
        filelocation = os.path.join(settings.BASE_DIR, template_relative_location)
        BODY_HTML = ""
        for line in open(filelocation):
            new_line = line.rstrip('\n')
            # print new_line
            BODY_HTML = BODY_HTML + new_line

    # Replace content
    BODY_HTML = BODY_HTML.replace('#STORENAME#', str(shop_info.name))
    BODY_HTML = BODY_HTML.replace('#REQUESTDATE#', request_date)
    BODY_HTML = BODY_HTML.replace('#DATAREMOVELINK#', removal_link)
    
    # print '\n'
    # print '#####################################################################'
    # print BODY_HTML

    # The character encoding for the email.
    CHARSET = "UTF-8"

    ###########################################################
    # EMAIL SENDING CODE BLOCK
    ###########################################################
    # Try to send the email.
    try:
        # Select the email sending service to use SendGrid or Amazon depending on value of settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE
        if settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE == 'AMAZON':
            # Create a new SES resource and specify a region.
            client = boto3.client(
                                  'ses',
                                  region_name=AWS_REGION,
                                  aws_access_key_id=settings.aws_id,
                                  aws_secret_access_key=settings.aws_secret
                                 )

            #Provide the contents of the email.
            response = client.send_email(
                Destination={
                    'ToAddresses': [
                        RECIPIENT,
                    ],
                },
                Message={
                    'Body': {
                        'Html': {
                            'Charset': CHARSET,
                            'Data': BODY_HTML,
                        },
                        'Text': {
                            'Charset': CHARSET,
                            'Data': BODY_TEXT,
                        },
                    },
                    'Subject': {
                        'Charset': CHARSET,
                        'Data': SUBJECT,
                    },
                },
                Source=SENDER,
                # If you are not using a configuration set, comment or delete the
                # following line
                #ConfigurationSetName=CONFIGURATION_SET,
            )

        elif settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE == 'SENDGRID':
            sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
            from_email = Email(email="*****@*****.**", name=str(shop_info.name))
            to_email = Email(RECIPIENT)
            subject = SUBJECT
            content = Content("text/html", BODY_HTML)
            mail = Mail(from_email, subject, to_email, content)
            response = sg.client.mail.send.post(request_body=mail.get())
            print(response.status_code)
            print(response.body)
            print(response.headers)

    # Display an error if something goes wrong. 
    except ClientError as e:
        print ("ERROR - Failed to send email to %s") %(RECIPIENT)
        print(e.response.status_code)
    else:
        print("Email sent! Message ID:")
        print(response.status_code)
    
        # #######################################################
        # Log Data Removal in Audit Table (All times are in UTC)
        # #######################################################
        current_datetime = datetime.datetime.now()
        action = 'Data Removal Request'
        method = 'Data Removal Form'
        comment = 'Confirmation link sent via email to the address on record.'
        customer_id = CustomerInst[0].id
        marketing_consent = CustomerInst[0].accepts_marketing
        status = 'Completed'
        if marketing_consent is True:
            legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
            purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
        else:
            legal_basis = 'Preparing or Performing a Contract (Product Sales)'
            purpose = 'Ecommerce - Processing Customer Purchases'

        # Create AuditLog Instance 
        AuditLogInst = DataEventLogger(shop_url)

        # Add Data Removal Entry line
        AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)

    return 0
Пример #3
0
def gdpr_copy(copy_request_email, shop_url, referringpage, country):

    request_date = datetime.date.today().strftime('%B %d %Y')

    # Create and Activate session for API calls
    ShopDeatzInst = ShopDeatz.objects.get(shop_url=shop_url)
    session = shopify.Session(shop_url, ShopDeatzInst.auth_token)
    shopify.ShopifyResource.activate_session(session)

    # Gets an object that contains all the shop info eqvalent to GET endpoint /admin/shop.json
    shop_info = shopify.Shop.current()

    # Make customer instance to extract customer deatails (returns a list so use the first one)
    # .find() will not work on Customers using params, Search queries are only available on the Customer resource as a separate .search() method
    # This is because to search, you need to access a different endpont not /admin/customers.json but rather /admin/customers/search.json
    search_query = 'email:' + str(copy_request_email)
    CustomerInst = shopify.Customer.search(q=search_query)

    if len(CustomerInst) <= 0:
        # ##############################################################
        # Log INVALID Data Access in Audit Table (All times are in UTC)
        # ##############################################################
        current_datetime = datetime.datetime.now()
        action = 'Invalid Data Access Request'
        method = 'Data Access Form'
        comment = 'Email does not correspond to any record in the database. No data transmitted.'
        customer_id = 'Unregistered Customer'
        marketing_consent = '-'
        status = 'Completed'
        legal_basis = '-'
        purpose = '-'

        # Create AuditLog Instance 
        AuditLogInst = DataEventLogger(shop_url)

        # Add Data Removal Entry line
        AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)
        return 0

    else:
        pass

    SENDER = str(shop_info.name) +  "<*****@*****.**>"

    # Replace [email protected] with a "To" address. If your account 
    RECIPIENT = str(copy_request_email)

    # If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
    AWS_REGION = "eu-west-1" 

    # The email body for recipients with non-HTML email clients.
    BODY_TEXT = ("Hi there,\r\n"
                 "In response to your subject data access request received on %s, "
                 "please find below the requested copy of your personal data.\r\n"
                 '---------------------------------------------\r\n'
                 'Email: %s\r\n'
                 'First Name: %s\r\n'
                 'Last Name: %s\r\n'
                 'Phone: %s\r\n'
                 'Company: %s\r\n'
                 'Address: %s\r\n'
                 'Address: %s\r\n'
                 'City: %s\r\n'
                 'Province: %s\r\n'
                 'Country: %s\r\n' 
                 '---------------------------------------------\r\n'
                 "As per European General Data Protection Regulation, you may rectify this data at any time by "
                 "loging in to your shop account. Alternatively, you can request data removal by clicking the data "
                 "icon at the bottom of the store's pages.\r\n"
                 "Thank you for your inquiry.\r\n"
                 "Regards,\r\n"
                 "%s"

                ) %(
                    request_date,
                    str(CustomerInst[0].email),
                    str(CustomerInst[0].first_name),
                    str(CustomerInst[0].last_name),
                    str(CustomerInst[0].phone),
                    str(CustomerInst[0].addresses[0].company),
                    str(CustomerInst[0].addresses[0].address1),
                    str(CustomerInst[0].addresses[0].address2),
                    str(CustomerInst[0].addresses[0].city),
                    str(CustomerInst[0].addresses[0].province),
                    str(CustomerInst[0].addresses[0].country),
                    str(shop_info.name)
                   )

    # print BODY_TEXT
    #############################################
    # The HTML body of the email.
    #############################################

    # FRENCH EMAIL TEMPLATE
    if country == 'France':
        # The subject line for the email.
        SUBJECT = str(shop_info.name) + " - GDPR Demande de Copie de Données"

        # Create French format request_date
        request_date = datetime.date.today().strftime('%d/%m/%Y')

        # Get  content of html template
        template_relative_location = 'templates/emailtemplates/data_copy_FR.html'
        filelocation = os.path.join(settings.BASE_DIR, template_relative_location)
        BODY_HTML = ""
        for line in open(filelocation):
            new_line = unicode(line.decode("utf-8"))
            new_line = new_line.rstrip('\n')
            # print unicodedata.normalize('NFKD', new_line).encode('utf-8','ignore')
            BODY_HTML = BODY_HTML + new_line

    # ALL OTHERS (ENGLISH EMAIL TEMPLATE)
    else:
        # The subject line for the email.
        SUBJECT = str(shop_info.name) + " - GDPR Data Access Request"

        template_relative_location = 'templates/emailtemplates/data_copy.html'
        filelocation = os.path.join(settings.BASE_DIR, template_relative_location)
        BODY_HTML = ""
        for line in open(filelocation):
            new_line = line.rstrip('\n')
            BODY_HTML = BODY_HTML + new_line

    # replace content of template
    BODY_HTML = BODY_HTML.replace('#STORENAME#', str(shop_info.name))
    BODY_HTML = BODY_HTML.replace('#REQUESTDATE#', request_date)
    BODY_HTML = BODY_HTML.replace('#EMAIL#', str(CustomerInst[0].email))
    BODY_HTML = BODY_HTML.replace('#FNAME#', str(CustomerInst[0].first_name))
    BODY_HTML = BODY_HTML.replace('#LNAME#', str(CustomerInst[0].last_name))
    BODY_HTML = BODY_HTML.replace('#PHONE#', str(CustomerInst[0].phone))
    BODY_HTML = BODY_HTML.replace('#COMPANY#', str(CustomerInst[0].addresses[0].company))
    BODY_HTML = BODY_HTML.replace('#ADDRESS1#', str(CustomerInst[0].addresses[0].address1))
    BODY_HTML = BODY_HTML.replace('#ADDRESS2#', str(CustomerInst[0].addresses[0].address2))
    BODY_HTML = BODY_HTML.replace('#CITY#', str(CustomerInst[0].addresses[0].city))
    BODY_HTML = BODY_HTML.replace('#PROVINCE#', str(CustomerInst[0].addresses[0].province))
    BODY_HTML = BODY_HTML.replace('#COUNTRY#', str(CustomerInst[0].addresses[0].country))
    BODY_HTML = BODY_HTML.replace('#ZIP#', str(CustomerInst[0].addresses[0].zip))

    # print '\n'
    # print '#####################################################################'
    # print BODY_HTML

    # The character encoding for the email.
    CHARSET = "UTF-8"


    ###########################################################
    # EMAIL SENDING CODE BLOCK
    ###########################################################
    # Try to send the email.
    try:
        # Select the email sending service to use SendGrid or Amazon depending on value of settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE
        if settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE == 'AMAZON':
            # Create a new SES resource and specify a region.
            client = boto3.client(
                                  'ses',
                                  region_name=AWS_REGION,
                                  aws_access_key_id=settings.aws_id,
                                  aws_secret_access_key=settings.aws_secret
                                 )

            #Provide the contents of the email.
            response = client.send_email(
                Destination={
                    'ToAddresses': [
                        RECIPIENT,
                    ],
                },
                Message={
                    'Body': {
                        'Html': {
                            'Charset': CHARSET,
                            'Data': BODY_HTML,
                        },
                        'Text': {
                            'Charset': CHARSET,
                            'Data': BODY_TEXT,
                        },
                    },
                    'Subject': {
                        'Charset': CHARSET,
                        'Data': SUBJECT,
                    },
                },
                Source=SENDER,
                # If you are not using a configuration set, comment or delete the
                # following line
                #ConfigurationSetName=CONFIGURATION_SET,
            )

        elif settings.ACTIVE_TRANSACTIONALEMAIL_SERVICE == 'SENDGRID':
            sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
            from_email = Email(email="*****@*****.**", name=str(shop_info.name))
            to_email = Email(RECIPIENT)
            subject = SUBJECT
            content = Content("text/html", BODY_HTML)
            mail = Mail(from_email, subject, to_email, content)
            response = sg.client.mail.send.post(request_body=mail.get())
            print(response.status_code)
            print(response.body)
            print(response.headers)
    
    # Display an error if something goes wrong. 
    except ClientError as e:
        print ("ERROR - Failed to send email to %s") %(RECIPIENT)
        print(e.response.status_code)
    else:
        print("Email sent! Message ID:"),
        print(response.status_code)

        # #######################################################
        # Log Data Access in Audit Table (All times are in UTC)
        # #######################################################
        current_datetime = datetime.datetime.now()
        action = 'Data Access Request'
        method = 'Data Access Form'
        comment = 'Requested data transmitted via email to the address on record.'
        customer_id = CustomerInst[0].id
        marketing_consent = CustomerInst[0].accepts_marketing
        status = 'Completed'
        if marketing_consent is True:
            legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
            purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
        else:
            legal_basis = 'Preparing or Performing a Contract (Product Sales)'
            purpose = 'Ecommerce - Processing Customer Purchases'

        # Create AuditLog Instance 
        AuditLogInst = DataEventLogger(shop_url)

        # Add Data Removal Entry line
        AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)
        return 0
Пример #4
0
def activateRecurringCharge(request):
    print '==> activateRecurringCharge()'
    # Use the charge id that is passed in the GET request to create an instance of your store's data
    charge_id = request.GET.get('charge_id')

    # Create and activate session
    # Add try / Except statement here for double return_url call
    # On the second call ShopDeatz object will have been deleted and will return ObjectNotFound at that point just return the decline_page.html
    
    try:
        ShopDeatzInst = ShopDeatz.objects.get(charge_id=charge_id)
        shop_url = ShopDeatzInst.shop_url
        auth_token = ShopDeatzInst.auth_token
    except ObjectDoesNotExist:
        print 'rendering from except'
        # Return App Charge Declined Page
        shop_url = request.GET.get('shop', False)
        #full_shop_url = 'https://' + shop_url
        context = {
                    'SHOPIFY_API_KEY': settings.SHOPIFY_API_KEY,
                    #'shop_url': full_shop_url,
                    #'apps_link': (full_shop_url + '/admin/apps/')
                  }
        print context
        return render(request, 'installer/decline_page.html', context)

    session = shopify.Session(shop_url, ShopDeatzInst.auth_token)
    shopify.ShopifyResource.activate_session(session)

    print 'Activationg charge for %s' %(shop_url)
    # use the charge_id to find the correct RecurringApplicationCharge within the store's charges
    charge = shopify.RecurringApplicationCharge.find(charge_id)

    # Check the status of the application charge
    # if it is declined then remove the store from our DB to restrict access
    print "Current charge status = %s" %(charge.status)
    if charge.status != 'accepted' and charge.status != 'active':
        print 'Declined Deleting Shop from DB'
        ShopDeatzInst.delete()

        # Return App Charge Declined Page
        full_shop_url = 'https://' + shop_url
        context = {
                    'SHOPIFY_API_KEY': settings.SHOPIFY_API_KEY,
                    'shop_url': full_shop_url,
                    'apps_link': (full_shop_url + '/admin/apps/')
                  }
        print context
        return render(request, 'installer/decline_page.html', context)

    elif charge.status == 'active':
        # redirect to dashboard
        return dashboard.views.index(request)

    # Otherwise if merchant accepted then, activate the charge and finalize the installation 
    else:
        # Activate the charge
        charge.activate()
        final_status = charge.status
        print 'Final charge status %s' %(final_status)
        print 'Finalizing Installation'

        # #############################
        # Finish installation
        # #############################

        # Install Script Tag
        scripttag_return = createScriptTag()
        print scripttag_return

        # Create uinstall webhook (removed during testing phase)
        webhook_return = createUninstallWebHook()
        print webhook_return

        # ###############################
        # CREATE REQUIRED MODELS
        # ###############################
        # Note: Wrap all model creations in try/except statements to make check that you are not adding an entry that already exists
        # double entries bug out the entire code when doing lookups. No need to wrap the ShopDeatz, there is already a try/except check above 

        # Save the same info in models.InstallTracker
        # if an entry for the store exists then update the info of the entry
        try: 
            InstallTrackerInst = InstallTracker.objects.get(shop_url=shop_url)
            install_datetime = datetime.datetime.now()
            InstallTrackerInst.auth_token = auth_token
            InstallTrackerInst.install_date = install_datetime
            InstallTrackerInst.db_purge = '-' 
            InstallTrackerInst.save()
        # otherwise if no entry exists then create one
        except ObjectDoesNotExist:
            InstallTrackerInst = InstallTracker()
            install_datetime = datetime.datetime.now()
            InstallTrackerInst.shop_url = shop_url
            InstallTrackerInst.auth_token = auth_token
            InstallTrackerInst.install_date = install_datetime
            InstallTrackerInst.db_purge = '-' 
            InstallTrackerInst.save()
            print 'Install written in models.InstallTracker'

        # Create Customization Model entry for shop
        try:
            ShopCustomInst =  ShopCustomizations.objects.get(shop_url=shop_url)

        except ObjectDoesNotExist:
            DefaultTemplateInst = TemplateDefaults.objects.get(template_name='retro')
            ShopCustInst = ShopCustomizations()
            ShopCustInst.shop_url = shop_url
            ShopCustInst.active_template = DefaultTemplateInst.template_name
            ShopCustInst.background_color = DefaultTemplateInst.background_color
            ShopCustInst.text_color = DefaultTemplateInst.text_color
            ShopCustInst.secondary_text_color = DefaultTemplateInst.secondary_text_color
            ShopCustInst.active_tab_text_color = DefaultTemplateInst.active_tab_text_color
            ShopCustInst.accept_color = DefaultTemplateInst.accept_color
            ShopCustInst.decline_color = DefaultTemplateInst.decline_color
            ShopCustInst.font_type = DefaultTemplateInst.font_type
            ShopCustInst.font_size = DefaultTemplateInst.font_size
            ShopCustInst.time_delay= DefaultTemplateInst.time_delay
            ShopCustInst.save()

        # Create Shop Settings Model entry for shop
        try:
            ShopSettingsInst = ShopSettings.objects.get(shop_url=shop_url)

        except ObjectDoesNotExist:
            ShopSettingsInst = ShopSettings()
            ShopSettingsInst.shop_url = shop_url
            ShopSettingsInst.save()

        # Create Shop Marketing Services entry for shop
        try:
            ShopMarketingServicesInst = ShopMarketingServices.objects.get(shop_url=shop_url) 

        except ObjectDoesNotExist:
            ShopMarketingServicesInst = ShopMarketingServices()
            ShopMarketingServicesInst.shop_url = shop_url
            ShopMarketingServicesInst.save()
        
        # Create Shop Advanced Settings entry for shop
        try:
            AdvancedSettingsInst = AdvancedSettings.objects.get(shop_url=shop_url) 

        except ObjectDoesNotExist:
            AdvancedSettingsInst = AdvancedSettings()
            AdvancedSettingsInst.shop_url = shop_url
            AdvancedSettingsInst.save()

        # Create Email Service Provider entry in DB for shop
        try:
            ESPInst = ESPCredentials.objects.get(shop_url=shop_url) 

        except ObjectDoesNotExist:
            ESPInst = ESPCredentials()
            ESPInst.shop_url = shop_url
            ESPInst.save()

        #####################################################################
        # MYSQL SETUP
        #####################################################################
        # Check if table already exists in case of re-installs and abandonned upgrades. In these cases a table will already exist and there
        # is no need to re-create one or to launch initial_data_import, doing so would re-write the customers data or append the same data again
        AuditLogInst = DataEventLogger(shop_url)
        table_exists = AuditLogInst.check_table_exists()
        if table_exists == False:
            #####################################################
            # Create MYSQL table Audit Log (Do NOT wrap in try)
            #################################################### 

            AuditLogInst.create_shop_audit_table()
 
            #####################################################
            # Queue Asynchronous Initial Data Import    
            ####################################################
            # This calls the code that we wish to run asynchronously.
            # Basically once the app finishes installing in finalize, we want to immediately let him continue on his way, 
            # while we process imports in the all in the background. The function called below will be sent to the rabbitmq queue and 
            # will wait there for a worker to pick it up and execute the code in the background asynchronously. That we this finalize() 
            # won't have to wait for this process to finish before rendering the finalize page. We can render the user backend and allow 
            # the impot function to finish in its own time. Without locking the flow control.
            initial_data_import.delay(shop_url, auth_token)

        else:
            ShopDeatzInst.initial_import = True
            ShopDeatzInst.last_import_datetime = datetime.datetime.now()
            ShopDeatzInst.save()
            print '%s SQL table exists, table creation and initial_data_import have been skipped' %(shop_url)
            pass

    # You must pass 2 arguements to the EASDK JS, your app's api_key and the FULL path to the store that is installing the app.
    full_shop_url = 'https://' + shop_url
    context = {
                'SHOPIFY_API_KEY': settings.SHOPIFY_API_KEY,
                'shop_url': full_shop_url
          }

    print 'APP INSTALLATION SUCCESSFULLY TERMINATED'
    # Now render the emmbeded home.html template using the context above
    return render(request, 'dashboard/home.html', context)
Пример #5
0
def removal_queue_processing():

    print 'started task'

    current_datetime = datetime.datetime.now()

    # Create an instance of RemovalQueue and loop through all entries in the queue
    RemovalQueue_list = RemovalQueue.objects.all()

    for RemovalQueue_entry in RemovalQueue_list:
        print RemovalQueue_entry

        # Get the Shop's 0auth token, that was stored in installer.models.ShopDeatz during installation
        ShopDeatzInst = ShopDeatz.objects.get(
            shop_url=RemovalQueue_entry.shop_url)
        auth_token = ShopDeatzInst.auth_token

        # Create a session object using shop_url and 0auth_token
        session = shopify.Session(RemovalQueue_entry.shop_url, auth_token)

        # Activate the Session
        shopify.ShopifyResource.activate_session(session)

        # STEP1. Create an instance of the customer by looking him up using his ID
        customer = shopify.Customer.find(RemovalQueue_entry.customer_id)

        # STEP1. Check if last_order_id has not changed
        print customer.last_order_id
        print RemovalQueue_entry.last_order_id
        if str(customer.last_order_id) == RemovalQueue_entry.last_order_id:
            print "last order ids match"
            pass

        # In case the customer has initiated a new order in between his removal request date and now, then re-set his last_order_date to
        # account for the new chargeback period
        else:
            print "orders don't match"
            last_order = shopify.Order.find(customer.last_order_id)
            last_order_date = dateutil.parser.parse(last_order.created_at)

            # This will update all entries corresponding to the the customer_id and shop url. This is used in case the customer would have
            # submitted multiple removal queries
            RemovalQueue.objects.filter(
                customer_id=RemovalQueue_entry.customer_id,
                shop_url=RemovalQueue_entry.shop_url).update(
                    last_order_id=customer.last_order_id)
            RemovalQueue.objects.filter(
                customer_id=RemovalQueue_entry.customer_id,
                shop_url=RemovalQueue_entry.shop_url).update(
                    last_order_date=last_order_date)
            continue

        ################################################################################################
        # Shopify Removal Processing
        ###############################################################################################
        # The Rest of this code will not execute unless the if statement above is successfully passed

        # Charge Back Period (defined in number of days, should be set to 181 days)
        chargeback_period = 6

        # calculate how many days have passed since last order
        days_since_last_order = current_datetime - RemovalQueue_entry.last_order_date.replace(
            tzinfo=None)
        print 'days since last order'
        print days_since_last_order

        # if less than 181 days don't do anything move to the next removal entry in the queue
        if days_since_last_order < datetime.timedelta(chargeback_period):
            print "ChargeBack period hasn't been terminated for customer_id %s" % (
                str(RemovalQueue_entry.customer_id))
            continue

        elif days_since_last_order >= datetime.timedelta(chargeback_period):
            print "ChargeBack period terminated sending removal email to Shopify Privacy Team"

            # ##############################################################
            # Use Sendgrid to send removal request to [email protected]
            # ##############################################################

            # Get Shop Owner's email Address for CC'ing him in the email
            ShopInfo = shopify.Shop.current()
            owner_email = ShopInfo.email
            owner_name = ShopInfo.shop_owner
            shop_name = ShopInfo.name
            shop_id = ShopInfo.id

            template_relative_location = 'templates/emailtemplates/data_removal.html'
            filelocation = os.path.join(settings.BASE_DIR,
                                        template_relative_location)
            BODY_HTML = ""
            for line in open(filelocation):
                new_line = line.rstrip('\n')
                BODY_HTML = BODY_HTML + new_line

            # replace content of template
            BODY_HTML = BODY_HTML.replace('#SHOPNAME#', str(shop_name))
            BODY_HTML = BODY_HTML.replace('#SHOPID#', str(shop_id))
            BODY_HTML = BODY_HTML.replace('#CUSTOMERID#',
                                          str(RemovalQueue_entry.customer_id))
            BODY_HTML = BODY_HTML.replace(
                '#LASTORDERID#', str(RemovalQueue_entry.last_order_id))
            BODY_HTML = BODY_HTML.replace(
                '#DOLO#',
                RemovalQueue_entry.last_order_date.strftime("%d %B %Y"))
            BODY_HTML = BODY_HTML.replace(
                '#EOCBP#', ((RemovalQueue_entry.last_order_date +
                             datetime.timedelta(180)).strftime("%d %B %Y")))
            BODY_HTML = BODY_HTML.replace(
                '#DOGDPR#',
                RemovalQueue_entry.removal_request_date.strftime("%d %B %Y"))
            BODY_HTML = BODY_HTML.replace('#STOREOWNER#', str(owner_name))

            # The character encoding for the email.
            CHARSET = "UTF-8"

            # SendGrid Code Block
            RECIPIENT = '*****@*****.**'  # This should be changed to the email of the Shopify Privacy Team
            SUBJECT = str(shop_name) + " - GDPR Data Removal Request"

            #from_email = Email(email="*****@*****.**", name=shop_name)
            #subject = SUBJECT
            #to_email = Email(RECIPIENT)
            #content = Content("text/html", BODY_HTML)
            #mail = Mail(from_email, subject, to_email, content)
            #mail.personalizations[0].add_to(Email(RECIPIENT))  # This should be the Shopify Privacy team [email protected]
            #mail.personalizations[0].add_cc(Email(owner_email))  ## CC store owner

            print "owner email %s" % (owner_email)

            sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
            from_email = Email(
                email="*****@*****.**",
                name=str(shop_name))
            to_email = Email(RECIPIENT)
            subject = SUBJECT
            content = Content("text/html", BODY_HTML)
            mail = Mail(from_email, subject, to_email, content)
            mail.personalizations[0].add_cc(Email(owner_email))

            response = sg.client.mail.send.post(request_body=mail.get())
            print(response.status_code)
            print(response.body)
            print(response.headers)

            # ######################################################
            # Change Status of 'PENDING' Removal in Audit Table
            # ######################################################

            # Create AuditLog Instance
            AuditLogInst = DataEventLogger(RemovalQueue_entry.shop_url)

            # Update Status
            AuditLogInst.update_status(RemovalQueue_entry.customer_id)

            # #######################################################
            # Log Data Removal in Audit Table (All times are in UTC)
            # #######################################################

            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            action = 'Data Removal Request Processed'
            method = 'Removal Request Transmitted to Processor'
            comment = 'Charge-back period terminated, data removal request sent to the Data Processor (Shopfy) via email ([email protected]) for erasure.'
            referringpage = '-'
            status = 'Completed'
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            # Add Data Removal Entry line
            AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)

            # ##############################################################
            # Remove the customer's removal request from the removal queue
            # ###############################################################
            RemovalQueue.objects.filter(
                customer_id=RemovalQueue_entry.customer_id,
                shop_url=RemovalQueue_entry.shop_url).delete()

        else:
            print "Somethong went wrong in gdpr.tasks.removal_queue_processing"

    print "Removal Queue Processing Terminated SUCCESSFULLY"
    return 0
Пример #6
0
def newly_regestered_data():
    #####################################################
    # New Data Collected (insert multiple rows @ once)
    ####################################################
    # Get a list of all shops
    ShopDeatzInst = ShopDeatz.objects.all()

    # Extract individual objects from object list, to get their urls and create a store session to send API calls
    for Store in ShopDeatzInst:
        shop_url = Store.shop_url
        auth_token = Store.auth_token

        # Create and activate store session to retrieve cutomer list
        session = shopify.Session(shop_url, auth_token)
        shopify.ShopifyResource.activate_session(session)

        current_datetime = datetime.datetime.now()

        # This cron runs at 1am and gets a list of customers who's details were updated between last_import_datetime and current_datetime
        start_datetime = Store.last_import_datetime.strftime(
            "%Y-%m-%dT%H:%M:%S") + '-00:00'
        end_datetime = current_datetime.strftime(
            "%Y-%m-%dT%H:%M:%S"
        ) + '-00:00'  # format: 2014-04-25T16:15:47-04:00

        print start_datetime
        print end_datetime

        # Get Customer list
        # .find() works here because the updated_at_min param access the top-level endoint /admin/customers.json NOT /admin/customers/search.json
        customer_list = shopify.Customer.find(
            updated_at_min=start_datetime, updated_at_max=end_datetime
        )  # Find with no params gets all (Returns a list)

        # Create AuditLog instance to insert customers
        AuditLogInst = DataEventLogger(shop_url)

        # Concatenate customers into multiple VALUE clauses to minimize insertion time and cpu load
        sql_query_values = ''
        total_counter = 0
        set_counter = 0
        for customer in customer_list:
            total_counter += 1
            set_counter += 1
            if (customer.id != '') and (customer.id != None):
                customer_id = customer.id
            else:
                customer_id = str(customer.id)

            # In Case this is an intial data creation
            if customer.created_at == customer.updated_at:

                # Convert ISO 8601 string date and time to python datetime object
                creation_datetime = dateutil.parser.parse(customer.created_at)

                # Convert datetime object back to UTC time (in case there is a timezon offset)
                date = creation_datetime.astimezone(pytz.utc)

                action = 'Data Collection'
                method = 'Data Collection Form'
                referringpage = ''
                comment = 'Personal details provided by data subject were collected and stored in the customer database.'

                customer_id = customer.id
                marketing_consent = customer.accepts_marketing
                status = 'Completed'
                if marketing_consent is True:
                    legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                    purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
                else:
                    legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                    purpose = 'Ecommerce - Processing Customer Purchases'

                sql_query_value_line = "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'),"\
                            % (
                                 date,
                                 action,
                                 method,
                                 referringpage,
                                 comment,
                                 customer_id,
                                 purpose,
                                 status,
                                 legal_basis
                               )

            # Otherwise its a data update
            else:

                # Convert ISO 8601 string date and time to python datetime object
                creation_datetime = dateutil.parser.parse(customer.updated_at)

                # Convert datetime object back to UTC time (in case there is a timezon offset)
                date = creation_datetime.astimezone(pytz.utc)

                action = 'Data Rectification'
                method = 'Rectified via user account.'
                referringpage = ''
                comment = 'Data updated.'
                customer_id = customer.id
                marketing_consent = customer.accepts_marketing
                status = 'Completed'
                if marketing_consent is True:
                    legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                    purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
                else:
                    legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                    purpose = 'Ecommerce - Processing Customer Purchases'

                sql_query_value_line = "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'),"\
                            % (
                                 date,
                                 action,
                                 method,
                                 referringpage,
                                 comment,
                                 customer_id,
                                 purpose,
                                 status,
                                 legal_basis
                               )

            sql_query_values = sql_query_values + sql_query_value_line

            # for every set of 150 values (customer inserts) call the insert_multiple_data_events() to process these sql inserts
            # or if we have reached the end of the customer list then just dump all the values you have left in sql_query_values
            if set_counter == 150 or total_counter >= len(customer_list):

                # Pop the last comma off the end of the insert string
                sql_query_values = sql_query_values[:-1]

                # Call insert_multiple_data_events() to insert the current set of values
                AuditLogInst.insert_multiple_data_events(sql_query_values)

                # reset set_counter and sql_query_values
                set_counter = 0
                sql_query_values = ''

        # Update last_import_datetime for this store
        Store.last_import_datetime = current_datetime
        Store.save()

    return 0
Пример #7
0
def gdpr_removal(removal_request_email, confirmation_code, shop_url,
                 referringpage):

    # Check that email corresponds to confirmation code
    try:
        RemovalConfirmInst = RemovalConfirmationCodes.objects.get(
            removal_request_email=removal_request_email)
        if RemovalConfirmInst.confirmation_code == confirmation_code:
            print 'Removal confirmation codes match'
            # Remove the consumed confirmation code o avoid clashes in future deletions
            RemovalConfirmInst.delete()
            pass
        else:
            print 'Removal confirmation codes do NOT match'
            return 0
    # in case email cant be found in RemovalConfirmationCodes model, then don't return anything just end function execution
    except ObjectDoesNotExist:
        print 'No removal confirmation code entry for email %s' % (
            removal_request_email)
        return 0

    # ##################################################
    # Activate your session with shopify store
    # ##################################################
    # Get the Shop's 0auth token, that was stored in installer.models.ShopDeatz during installation
    ShopDeatzInst = ShopDeatz.objects.get(shop_url=shop_url)
    auth_token = ShopDeatzInst.auth_token

    # Create a session object using shop_url and 0auth_token
    session = shopify.Session(shop_url, auth_token)

    # Activate the Session
    shopify.ShopifyResource.activate_session(session)

    # ##################################################
    # Check for customers added between last customer
    # check and removal request
    # ##################################################
    # Check for new customers that were added between yesterday and request time (now) in the shop where the removal_request_email is registered
    current_datetime = datetime.datetime.now()

    # Get a list of customers who's details were updated between last_import_datetime and current_datetime
    start_datetime = ShopDeatzInst.last_import_datetime.strftime(
        "%Y-%m-%dT%H:%M:%S") + '-00:00'
    end_datetime = current_datetime.strftime(
        "%Y-%m-%dT%H:%M:%S") + '-00:00'  # format: 2014-04-25T16:15:47-04:00

    # Get Customer list
    # .find() works here because the updated_at_min param access the top-level endoint /admin/customers.json NOT /admin/customers/search.json
    customer_list = shopify.Customer.find(
        updated_at_min=start_datetime, updated_at_max=end_datetime
    )  # Find with no params gets all (Returns a list)

    # Create AuditLog instance to insert customers
    AuditLogInst = DataEventLogger(shop_url)

    # Concatenate customers into multiple VALUE clauses to minimize insertion time and cpu load
    sql_query_values = ''
    total_counter = 0
    set_counter = 0
    for customer in customer_list:
        total_counter += 1
        set_counter += 1
        if (customer.id != '') and (customer.id != None):
            customer_id = customer.id
        else:
            customer_id = str(customer.id)

        # In Case this is an intial data creation
        if customer.created_at == customer.updated_at:

            # Convert ISO 8601 string date and time to python datetime object
            creation_datetime = dateutil.parser.parse(customer.created_at)

            # Convert datetime object back to UTC time (in case there is a timezon offset)
            date = creation_datetime.astimezone(pytz.utc)

            action = 'Data Collection'
            method = 'Data Collection Form'
            referringpage = ''
            comment = 'Personal details provided by data subject were collected and stored in the customer database.'

            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            status = 'Completed'
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            sql_query_value_line = "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'),"\
                            % (
                                 date,
                                 action,
                                 method,
                                 referringpage,
                                 comment,
                                 customer_id,
                                 purpose,
                                 status,
                                 legal_basis
                               )

        # Otherwise its a data update
        else:
            # Convert ISO 8601 string date and time to python datetime object
            creation_datetime = dateutil.parser.parse(customer.updated_at)

            # Convert datetime object back to UTC time (in case there is a timezon offset)
            date = creation_datetime.astimezone(pytz.utc)

            action = 'Data Rectification'
            method = 'User Account'
            referringpage = ''
            comment = 'Data subject rectified personal details, subject records were updated to reflect changes.'

            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            status = 'Completed'
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            sql_query_value_line = "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'),"\
                            % (
                                 date,
                                 action,
                                 method,
                                 referringpage,
                                 comment,
                                 customer_id,
                                 purpose,
                                 status,
                                 legal_basis
                               )

        sql_query_values = sql_query_values + sql_query_value_line

        # for every set of 150 values (customer inserts) call the insert_multiple_data_events() to process these sql inserts
        # or if we have reached the end of the customer list then just dump all the values you have left in sql_query_values
        if set_counter == 150 or total_counter >= len(customer_list):

            # Pop the last comma off the end of the insert string
            sql_query_values = sql_query_values[:-1]

            # Call insert_multiple_data_events() to insert the current set of values
            AuditLogInst.insert_multiple_data_events(sql_query_values)

            # reset set_counter and sql_query_values
            set_counter = 0
            sql_query_values = ''

    # Update last_import_datetime
    ShopDeatzInst.last_import_datetime = current_datetime
    ShopDeatzInst.save()

    # #####################################################
    # Make your API CALLS to remove data from shopify store
    # #####################################################
    # First use email to locate the correct customer to remove (get his customer id from shopify store DB)
    # Note : .find() will not work on Customers for SEARCHING using params,
    # Search queries are only available on the Customer resource as a separate .search() method
    # This is because to search, you need to access a different endpont not /admin/customers.json but rather /admin/customers/search.json
    search_query = 'email:' + str(removal_request_email)
    customer_list = shopify.Customer.search(
        q=search_query)  # This should return a list of customers

    # Now verify that the list of customers is greater than 0, meaning we found the customer
    # then update the attributes of the customer and save
    if len(customer_list) > 0:
        pass
    else:
        print 'No matiching customers found in DB'
        return 0

    # Go through the list of customers and check if they have an order history
    for customer in customer_list:
        if (customer.last_order_id == None) and (customer.orders_count == 0):
            # If no history then delete the customer from the using the API
            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            customer.destroy()  #destroy replaces the REST-ful DELETE request

            # #######################################################
            # Log Data Removal in Audit Table (All times are in UTC)
            # #######################################################
            action = 'Data Removal Request Processed'
            method = 'Data Removed via Shopify API'
            comment = 'Data removal confirmed via email removal link. Data subject personal data removed from store database via Shopify API.'
            status = 'Completed'
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            # Create AuditLog Instance
            AuditLogInst = DataEventLogger(shop_url)
            # Add Data Removal Entry line
            AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)
            # Update Data Copy and Data Registration lines to remove email and replace with Removal_Dataevent_ID
            # AuditLogInst.update_event_id(dataevent_id, removal_request_email)

        else:
            # Queue the order in gdpr.models.RemovalQueue for processing by celery task below
            last_order = shopify.Order.find(customer.last_order_id)
            last_order_date = dateutil.parser.parse(last_order.created_at)

            RemovalQueueInst = RemovalQueue()
            RemovalQueueInst.shop_url = shop_url
            RemovalQueueInst.customer_id = customer.id
            RemovalQueueInst.last_order_id = customer.last_order_id
            RemovalQueueInst.last_order_date = last_order_date
            RemovalQueueInst.removal_request_date = current_datetime
            RemovalQueueInst.removal_request_email = removal_request_email
            RemovalQueueInst.save()

            # ########################################################
            # Log Queued Removal in Audit Table (All times are in UTC)
            # ########################################################
            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            action = 'Data Removal Request Queued'
            method = 'Removal Request Pending'
            comment = 'Data removal confirmed via email removal link. Subject data removal request is pending end of charge-back period.'
            status = 'Pending'
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            # Create AuditLog Instance
            AuditLogInst = DataEventLogger(shop_url)
            # Add Data Removal Entry line
            AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)

        print "FINISHED SHOPIFY ERASURE QUEUEING"

        # NOW START CUSTOMER REMOVAL FROM ESP

        # #########################################################
        # Make your API CALLS to remove data from ESPs
        # #########################################################
        # Check if they are using an ESP if yes get the emailing_service, esp_username, esp_API_key, esp_list_id

        # Make an object of the MarketingServices() details, by looking up the corresponding ShopDeatz.consent_form_id (foreign key)
        # Basically get the row corresponding to ShopDeatz.consent_form_id (foreign key), make it into an objects with 'row fields' as attributes
        ESPInst = ESPCredentials.objects.get(shop_url=shop_url)

        if ESPInst.configured_ESP == '-':
            pass  # If its blank this means that no service was set in admin dashboard, then dont do anything

        elif ESPInst.configured_ESP == 'mailchimp':
            #
            #Step1: Get API Login Credentials
            #
            api_key = ESPInst.esp_API_key
            list_endpoint = ESPInst.esp_api_endpoint_url + '/3.0/lists'
            search_endpoint = ESPInst.esp_api_endpoint_url + '/3.0/search-members'

            #
            # Step2: Make API call to get list of subscriber lists
            #
            # Pass the the 'data' dict to access_token_uri using a POST request
            response = requests.get(
                list_endpoint,
                auth=('MyAPP', api_key))  #USe any arbitrary username

            # Grab the JSON dictionary that is returned and extract access_token
            response_dict = response.json(
            )  # Use the .json method to convert the {data:data} JSON dictionary returned into a Python dictionary

            # Get the list of lists, and loop through all lists extracting id numbers
            list_ids = []
            if len(response_dict['lists']) > 0:
                for email_list in response_dict['lists']:
                    list_ids.append(email_list['id'])

            # Means that there are no lists available on this account
            else:
                return 0

            #
            #Step3: Loop through all the lists looking fo user-email
            #
            lists_to_erase = []
            for id_num in list_ids:
                params = (('query', removal_request_email), ('list_id',
                                                             id_num))
                response = requests.get(search_endpoint,
                                        params=params,
                                        auth=('MYAPP', api_key))
                response_dict = response.json(
                )  # Use the .json method to convert the {data:data} JSON dictionary returned into a Python dictionary

                # if it finds exact matches in this list, then add this list id to lists_to_erase[]
                if (len(response_dict["exact_matches"]["members"]) > 0):
                    lists_to_erase.append(id_num)

            #
            #Step4: Remove useremail from all lists where it was located
            #
            for id_num in lists_to_erase:
                lowercase_email = removal_request_email.lower()
                email_bytes = lowercase_email.encode(
                    'utf-8'
                )  # must convert string to bytes first before hashing
                email_hash_object = hashlib.md5(
                    email_bytes)  # create hash object from byte string
                email_hash = email_hash_object.hexdigest()

                # Construct Removal Endpoint URL
                removal_endpoint = ESPInst.esp_api_endpoint_url + '/3.0/lists/' + id_num + '/members/' + email_hash

                # Send the Delete request
                response = requests.delete(removal_endpoint,
                                           auth=('MYAPP', api_key))

            print "FINISHED MAILCHIMP ERASURE"

            # #######################################################
            # Log MAIL LIST Removal in Audit Table (All times are in UTC)
            # #######################################################
            action = 'Data Removal Request Processed'
            method = 'Data Removed via MailChimp API'
            comment = 'Data removal confirmed via email removal link. Subject personal data removed from mailing list via MailChimp API.'
            status = 'Completed'
            customer_id = customer.id
            marketing_consent = customer.accepts_marketing
            if marketing_consent is True:
                legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
                purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
            else:
                legal_basis = 'Preparing or Performing a Contract (Product Sales)'
                purpose = 'Ecommerce - Processing Customer Purchases'

            # Create AuditLog Instance
            AuditLogInst = DataEventLogger(shop_url)
            # Add Data Removal Entry line
            AuditLogInst.insert_data_processing_event(current_datetime, action, method, referringpage, comment,\
                                                      customer_id, purpose, status, legal_basis)

        elif ESPInst.configured_ESP == 'omnisend':
            # Not possible even updtating data leaves traces of old data
            # Need to wait for omnisend to open up their DELETE portion of the API (coming soon)
            pass

        # #######################################################
        # Send Email to Partners to request customer data removal
        # #######################################################

    return 0
Пример #8
0
def initial_data_import(shop_url, auth_token):
    ########################################################
    # Initial Customer Import (insert multiple rows @ once)
    #########################################################

    # Create and activate store session to retrieve cutomer list
    session = shopify.Session(shop_url, auth_token)
    shopify.ShopifyResource.activate_session(session)

    # Get Customer list
    customer_list = shopify.Customer.find(
    )  # Find with no params gets all (Returns a list)

    # Create AuditLog instance to insert customers
    AuditLogInst = DataEventLogger(shop_url)

    print AuditLogInst.__dict__

    # Concatenate customers into multiple VALUE clauses to minimize insertion time and cpu load
    sql_query_values = ''
    total_counter = 0
    set_counter = 0
    for customer in customer_list:
        total_counter += 1
        set_counter += 1
        if (customer.id != '') and (customer.id != None):
            customer_id = customer.id
        else:
            customer_id = str(customer.id)

        # Convert ISO 8601 string date and time to python datetime object
        creation_datetime = dateutil.parser.parse(customer.created_at)

        # Convert datetime object back to UTC time (in case there is a timezon offset)
        date = creation_datetime.astimezone(pytz.utc)

        action = 'Data Collection'
        method = 'Initial Data Import'
        referringpage = 'Data imported on GDPR App install'
        comment = 'Personal details provided by data subject were collected and stored in the customer database.'

        customer_id = customer.id
        marketing_consent = customer.accepts_marketing
        status = 'Completed'
        if marketing_consent is True:
            legal_basis = 'Preparing or Performing a Contract (Product Sales) and Consent (Granted for Marketing)'
            purpose = 'Ecommerce - Processing Customer Purchases and Marketing'
        else:
            legal_basis = 'Preparing or Performing a Contract (Product Sales)'
            purpose = 'Ecommerce - Processing Customer Purchases'

        sql_query_value_line = "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'),"\
                            % (
                                 date,
                                 action,
                                 method,
                                 referringpage,
                                 comment,
                                 customer_id,
                                 purpose,
                                 status,
                                 legal_basis
                               )

        sql_query_values = sql_query_values + sql_query_value_line

        # for every set of 150 values (customer inserts) call the insert_multiple_data_events() to process these sql inserts
        # or if we have reached the end of the customer list then just dump all the values you have left in sql_query_values
        if set_counter == 150 or total_counter >= len(customer_list):

            # Pop the last comma off the end of the insert string
            sql_query_values = sql_query_values[:-1]

            # Call insert_multiple_data_events() to insert the current set of values
            AuditLogInst.insert_multiple_data_events(sql_query_values)

            # reset set_counter and sql_query_values
            set_counter = 0
            sql_query_values = ''

    # Change initial_import flag in ShopDeatz to true and change time for last_import_datetime
    Store = ShopDeatz.objects.get(shop_url=shop_url)
    Store.initial_import = True
    Store.last_import_datetime = datetime.datetime.now()
    Store.save()

    print "Inserted Initial Import Data to SQL for %s" % (shop_url)
    return 0