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): 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')
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)
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)
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
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
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')
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')