Esempio n. 1
0
    def create(self, validated_data):
        tenant = self.context.get('request').user.tenant
        contact_count = Contact.objects.filter(is_deleted=False).count()

        if tenant.billing.is_free_plan and contact_count >= settings.FREE_PLAN_ACCOUNT_CONTACT_LIMIT:
            raise serializers.ValidationError({
                'limit_reached': _('You\'ve reached the limit of contacts for the free plan.'),
            })

        instance = super(ContactSerializer, self).create(validated_data)

        credentials = get_credentials('moneybird')

        if has_required_tier(2) and credentials and credentials.integration_context.get('auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials)

        # Track newly ceated accounts in segment.
        if not settings.TESTING:
            analytics.track(
                self.context.get('request').user.id,
                'contact-created', {
                    'creation_type': 'automatic' if is_external_referer(self.context.get('request')) else 'manual',
                },
            )

        return instance
Esempio n. 2
0
    def create(self, validated_data):
        tenant = self.context.get('request').user.tenant
        contact_count = Contact.objects.filter(is_deleted=False).count()

        if tenant.billing.is_free_plan and contact_count >= settings.FREE_PLAN_ACCOUNT_CONTACT_LIMIT:
            raise serializers.ValidationError({
                'limit_reached':
                _('You\'ve reached the limit of contacts for the free plan.'),
            })

        instance = super(ContactSerializer, self).create(validated_data)

        credentials = get_credentials('moneybird')

        if has_required_tier(
                2) and credentials and credentials.integration_context.get(
                    'auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials)

        # Track newly ceated accounts in segment.
        if not settings.TESTING:
            analytics.track(
                self.context.get('request').user.id,
                'contact-created',
                {
                    'creation_type':
                    'automatic' if is_external_referer(
                        self.context.get('request')) else 'manual',
                },
            )

        return instance
    def create(self, validated_data):
        instance = super(ContactSerializer, self).create(validated_data)

        credentials = get_credentials('moneybird')

        if credentials and credentials.integration_context.get('auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials)

        return instance
    def handle(self, *args, **options):
        tenant = Tenant.objects.get(pk=options['tenant_id'])

        if tenant:
            credentials = get_credentials('pandadoc', tenant)

            if credentials:
                logger.info('Syncing documents for tenant %s' % tenant.id)
                # Get all current documents.
                tenant_documents = Document.objects.filter(tenant=tenant)

                url = 'https://api.pandadoc.com/public/v1/documents'
                # Get all documents from PandaDoc.
                response = send_get_request(url, credentials)

                if response.status_code == 200:
                    documents = response.json().get('results')

                    for document in documents:
                        document_id = document.get('id')

                        # Document doesn't exist (so something probably went wrong while creating the quote).
                        if not tenant_documents.filter(document_id=document_id):
                            details_url = url + '/%s/details' % document_id
                            response = send_get_request(details_url, credentials)

                            if response.status_code == 200:
                                deal_id = response.json().get('metadata').get('deal')

                                if deal_id:
                                    deal = Deal.objects.get(pk=deal_id)

                                    document = Document.objects.create(
                                        contact=deal.contact,
                                        deal=deal,
                                        document_id=document_id,
                                        tenant=tenant,
                                    )

                                    self.imported_documents_count += 1
                            else:
                                message = '[PandaDoc] Something went wrong while syncing document %s: ' % document_id
                                message = message + response.text
                                logger.warning(message)
                else:
                    message = '[PandaDoc] Something went while syncing documents: ' + response.json()
                    logger.warning(message)
            else:
                message = '[PandaDoc] Tenant %s doesn\'t have PandaDoc credentials' % options['tenant_id']
                logger.warning(message)

            logger.info('%s documents have been imported' % self.imported_documents_count)
        else:
            logger.error('Please enter a valid tenant')
Esempio n. 5
0
    def authenticate(self, request):
        data = request.data[0].get('data')
        metadata = data.get('metadata')
        deal = metadata.get('deal')

        if not deal:
            # No shared key set by the user so we have no way to verify the request.
            raise PermissionDenied({'detail': _('No deal found.')})

        # Use the deal to retrieve the tenant.
        deal = Deal.objects.get(pk=metadata.get('deal'))

        # Get the shared key which has been provided by PandaDoc.
        credentials = get_credentials('pandadoc', deal.tenant)

        shared_key = credentials.integration_context.get('shared_key')

        if not shared_key:
            # No shared key set by the user so we have no way to verify the request.
            raise PermissionDenied({
                'detail':
                _('No shared key found. Please go to your PandaDoc webhook settings and provide the key.'
                  )
            })

        # A shared key has been stored. So create HMAC based on given values and check if it's valid.
        signature = hmac.new(str(shared_key),
                             str(request.body),
                             digestmod=hashlib.sha256).hexdigest()

        if signature != request.GET.get('signature'):
            raise PermissionDenied({
                'detail':
                _('Invalid request. Either the provided shared key or signature is incorrect'
                  )
            })

        user = metadata.get('user')

        if user:
            user = LilyUser.objects.get(pk=user)
        else:
            user = deal.assigned_to

        set_current_user(user)

        return (user, None)
Esempio n. 6
0
    def authenticate(self, request):
        data = request.data[0].get('data')
        metadata = data.get('metadata')
        deal = metadata.get('deal')

        if not deal:
            # No shared key set by the user so we have no way to verify the request.
            raise PermissionDenied({
                'detail': _('No deal found.')
            })

        # Use the deal to retrieve the tenant.
        deal = Deal.objects.get(pk=metadata.get('deal'))

        # Get the shared key which has been provided by PandaDoc.
        credentials = get_credentials('pandadoc', deal.tenant)

        shared_key = credentials.integration_context.get('shared_key')

        if not shared_key:
            # No shared key set by the user so we have no way to verify the request.
            raise PermissionDenied({
                'detail': _('No shared key found. Please go to your PandaDoc webhook settings and provide the key.')
            })

        # A shared key has been stored. So create HMAC based on given values and check if it's valid.
        signature = hmac.new(str(shared_key), str(request.body), digestmod=hashlib.sha256).hexdigest()

        if signature != request.GET.get('signature'):
            raise PermissionDenied({
                'detail': _('Invalid request. Either the provided shared key or signature is incorrect')
            })

        user = metadata.get('user')

        if user:
            user = LilyUser.objects.get(pk=user)
        else:
            user = deal.assigned_to

        set_current_user(user)

        return (user, None)
Esempio n. 7
0
    def create(self, validated_data):
        tenant = self.context.get('request').user.tenant
        contact_count = Contact.objects.filter(is_deleted=False).count()

        if tenant.billing.is_free_plan and contact_count >= settings.FREE_PLAN_ACCOUNT_CONTACT_LIMIT:
            raise serializers.ValidationError({
                'limit_reached':
                _('You\'ve reached the limit of contacts for the free plan.'),
            })

        instance = super(ContactSerializer, self).create(validated_data)

        credentials = get_credentials('moneybird')

        if has_required_tier(
                2) and credentials and credentials.integration_context.get(
                    'auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials)

        return instance
Esempio n. 8
0
    def update(self, instance, validated_data):
        # Save the current data for later use.
        original_data = {
            'full_name': instance.full_name,
        }

        email_addresses = instance.email_addresses.all()

        if len(email_addresses) == 1:
            original_data.update({
                'original_email_address': email_addresses[0].email_address
            })

        instance = super(ContactSerializer, self).update(instance, validated_data)

        credentials = get_credentials('moneybird')

        if has_required_tier(2) and credentials and credentials.integration_context.get('auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials, original_data)

        return instance
    def update(self, instance, validated_data):
        # Save the current data for later use.
        original_data = {
            'full_name': instance.full_name,
        }

        email_addresses = instance.email_addresses.all()

        if len(email_addresses) == 1:
            original_data.update(
                {'original_email_address': email_addresses[0].email_address})

        instance = super(ContactSerializer,
                         self).update(instance, validated_data)

        credentials = get_credentials('moneybird')

        if credentials and credentials.integration_context.get('auto_sync'):
            self.send_moneybird_contact(validated_data, instance, credentials,
                                        original_data)

        return instance
Esempio n. 10
0
    def get(self, request, *args, **kwargs):
        template = EmailTemplate.objects.get(pk=kwargs.get('template_id'))
        lookup = {'user': self.request.user}

        if 'account_id' in self.request.GET:
            try:
                account = Account.objects.get(pk=self.request.GET.get('account_id'))
            except Account.DoesNotExist:
                pass
            else:
                lookup.update({'account': account})

        if 'contact_id' in self.request.GET:
            try:
                contact = Contact.objects.get(pk=self.request.GET.get('contact_id'))
            except Contact.DoesNotExist:
                pass
            else:
                lookup.update({'contact': contact})
                functions = contact.functions.all()
                if len(functions) == 1:
                    try:
                        account = Account.objects.get(pk=functions[0].account_id)
                    except Account.DoesNotExist:
                        pass
                    else:
                        lookup.update({'account': account})

        if 'document_id' in self.request.GET:
            credentials = get_credentials(IntegrationDetails.PANDADOC)

            document_id = self.request.GET.get('document_id')
            recipient = self.request.GET.get('recipient_email')

            # Set the status of the document to 'sent' so we can create a view session.
            send_url = 'https://api.pandadoc.com/public/v1/documents/%s/send' % document_id
            send_params = {'silent': True}

            response = send_post_request(send_url, credentials, send_params)

            session_url = 'https://api.pandadoc.com/public/v1/documents/%s/session' % document_id
            year = 60 * 60 * 24 * 365
            session_params = {'recipient': recipient, 'lifetime': year}

            response = send_post_request(session_url, credentials, session_params)

            if response.status_code == 201:
                sign_url = 'https://app.pandadoc.com/s/%s' % response.json().get('id')
                lookup.update({'document': {'sign_url': sign_url}})

        if 'emailaccount_id' in self.request.GET:
            try:
                emailaccount = EmailAccount.objects.get(pk=self.request.GET.get('emailaccount_id'))
            except EmailAccount.DoesNotExist:
                pass
            else:
                lookup.get('user').current_email_address = emailaccount.email_address

        # Setup regex to find custom variables
        search_regex = '\[\[ custom\.(.*?) \]\]'
        # Find all occurrences.
        search_result = re.findall(search_regex, template.body_html)

        if search_result:
            for custom_variable in search_result:
                public = None

                try:
                    # Try to split to see if it's a public variable
                    variable, public = custom_variable.split('.')
                except ValueError:
                    # Not a public variable, so .split raises an error
                    variable = custom_variable

                if public:
                    template_variable = TemplateVariable.objects.filter(
                        name__iexact=variable,
                        is_public=True
                    )
                else:
                    template_variable = TemplateVariable.objects.filter(
                        name__iexact=variable,
                        owner=get_current_user()
                    )

                if template_variable:
                    # find = '\[\[ custom.' + custom_variable + '(\s)?\]\]'
                    find = re.compile('\[\[ custom\.' + custom_variable + ' \]\]')
                    replace = template_variable.first().text

                    template.body_html = re.sub(find, replace, template.body_html, 1)

        # Ugly hack to make parsing of new template brackets style work
        parsed_template = Template(template.body_html.replace('[[', '{{').replace(']]', '}}')).render(Context(lookup))
        parsed_subject = Template(template.subject.replace('[[', '{{').replace(']]', '}}')).render(Context(lookup))

        # Make sure HTML entities are displayed correctly
        html_parser = HTMLParser.HTMLParser()
        parsed_subject = html_parser.unescape(parsed_subject)

        attachments = []

        for attachment in template.attachments.all():
            # Get attachment name
            name = get_attachment_filename_from_url(attachment.attachment.name)

            attachments.append({
                'id': attachment.id,
                'name': name,
            })

        return HttpResponse(anyjson.serialize({
            'template': parsed_template,
            'template_subject': parsed_subject,
            'attachments': attachments,
        }), content_type='application/json')
Esempio n. 11
0
    def get(self, request, *args, **kwargs):
        template = EmailTemplate.objects.get(pk=kwargs.get('template_id'))
        lookup = {'user': self.request.user}
        errors = {}

        if 'account_id' in self.request.GET:
            try:
                account = Account.objects.get(
                    pk=self.request.GET.get('account_id'))
            except Account.DoesNotExist:
                pass
            else:
                lookup.update({'account': account})

        if 'contact_id' in self.request.GET:
            try:
                contact = Contact.objects.get(
                    pk=self.request.GET.get('contact_id'))
            except Contact.DoesNotExist:
                pass
            else:
                lookup.update({'contact': contact})
                functions = contact.functions.all()
                if len(functions) == 1:
                    try:
                        account = Account.objects.get(
                            pk=functions[0].account_id)
                    except Account.DoesNotExist:
                        pass
                    else:
                        lookup.update({'account': account})

        if 'document_id' in self.request.GET:
            credentials = get_credentials('pandadoc')

            if credentials:
                error_message = None
                document_id = self.request.GET.get('document_id')
                recipient = self.request.GET.get('recipient_email')

                details_url = 'https://api.pandadoc.com/public/v1/documents/%s/details' % document_id

                response = send_get_request(details_url, credentials)

                if response.status_code == 200:
                    # Only documents with the 'draft' status can be set to sent.
                    if response.json().get('status') == 'document.draft':
                        # Set the status of the document to 'sent' so we can create a view session.
                        send_url = 'https://api.pandadoc.com/public/v1/documents/%s/send' % document_id
                        send_params = {'silent': True}
                        response = send_post_request(send_url, credentials,
                                                     send_params)

                        if response.status_code != 200:
                            error_message = 'Something went wrong while setting up the PandaDoc sign URL.'

                    metadata = response.json().get('metadata')

                    if metadata and metadata.get('account'):
                        account_id = metadata.get('account')

                        try:
                            account = Account.objects.get(pk=account_id)
                        except Account.DoesNotExist:
                            pass
                        else:
                            lookup.update({'account': account})

                    # Document has been 'sent' so create the session.
                    session_url = 'https://api.pandadoc.com/public/v1/documents/%s/session' % document_id
                    year = 60 * 60 * 24 * 365
                    session_params = {'recipient': recipient, 'lifetime': year}

                    response = send_post_request(session_url, credentials,
                                                 session_params)

                    if response.status_code == 201:
                        sign_url = 'https://app.pandadoc.com/s/%s' % response.json(
                        ).get('id')
                        lookup.update({'document': {'sign_url': sign_url}})
                    else:
                        error_message = (
                            'The PandaDoc sign URL could not be created \
                                          because the recipient isn\'t correct'
                        )
                else:
                    error_message = 'The document doesn\'t seem to be valid.'

                if error_message:
                    errors.update({'document': error_message})

        if 'emailaccount_id' in self.request.GET:
            try:
                emailaccount = EmailAccount.objects.get(
                    pk=self.request.GET.get('emailaccount_id'))
            except EmailAccount.DoesNotExist:
                pass
            else:
                lookup.get(
                    'user').current_email_address = emailaccount.email_address

        # Setup regex to find custom variables
        search_regex = '\[\[ custom\.(.*?) \]\]'
        # Find all occurrences.
        search_result = re.findall(search_regex, template.body_html)

        if search_result:
            for custom_variable in search_result:
                public = None

                try:
                    # Try to split to see if it's a public variable
                    variable, public = custom_variable.split('.')
                except ValueError:
                    # Not a public variable, so .split raises an error
                    variable = custom_variable

                if public:
                    template_variable = TemplateVariable.objects.filter(
                        name__iexact=variable, is_public=True)
                else:
                    template_variable = TemplateVariable.objects.filter(
                        name__iexact=variable, owner=get_current_user())

                if template_variable:
                    # find = '\[\[ custom.' + custom_variable + '(\s)?\]\]'
                    find = re.compile('\[\[ custom\.' + custom_variable +
                                      ' \]\]')
                    replace = template_variable.first().text

                    template.body_html = re.sub(find, replace,
                                                template.body_html, 1)

        # Ugly hack to make parsing of new template brackets style work
        parsed_template = Template(
            template.body_html.replace('[[', '{{').replace(']]', '}}')).render(
                Context(lookup))
        parsed_subject = Template(
            template.subject.replace('[[', '{{').replace(']]', '}}')).render(
                Context(lookup))

        # Make sure HTML entities are displayed correctly
        html_parser = HTMLParser.HTMLParser()
        parsed_subject = html_parser.unescape(parsed_subject)

        attachments = []

        for attachment in template.attachments.all():
            # Get attachment name
            name = get_attachment_filename_from_url(attachment.attachment.name)

            attachments.append({
                'id': attachment.id,
                'name': name,
            })

        return HttpResponse(anyjson.serialize({
            'template': parsed_template,
            'template_subject': parsed_subject,
            'attachments': attachments,
            'errors': errors,
        }),
                            content_type='application/json')