Example #1
0
    def _denial_responder(self, logger, request):
        from time import time
        import random
        context = get_context(request)
        issue_code = ['ACD', str(int(time()) % 10000000)]
        if (request.user.is_authenticated()):
            issue_code.insert(1, str(request.user.pk))
            msg = '%s/%s: ACCESS DENIED to user %s %s (pk=%s) from %s. request.    META is \'%s\'' % \
             (request.session.session_key, '-'.join(issue_code), request.user.first_name,
              request.user.last_name, request.user.pk, request.META['REMOTE_ADDR'], request.META)
            logger.error(msg)
        else:
            issue_code.insert(1, 'NA')
            msg = '%s/%s: ACCESS DENIED to anonymous user from %s. request.META is \'%s\'' % \
             (request.session.session_key, '-'.join(issue_code),
              request.META['REMOTE_ADDR'], request.META)
            logger.error(msg)
        issue_code.append(str(random.randrange(100, 999)))

        context['issue_code'] = '-'.join(issue_code)

        subj = _('ACL Denial %(issue_code)s: %(path)s') % \
         {'issue_code': '-'.join(issue_code), 'path': request.path}

        mail_admins(subj, msg, fail_silently=False)

        response = render_to_response('ACL/access_denied.html', context)
        response.status_code = 403
        return response
Example #2
0
	def _denial_responder(self, logger, request):
		from time import time
		import random
		context = get_context(request)
		issue_code = ['ACD', str(int(time()) % 10000000)]
		if (request.user.is_authenticated()):
			issue_code.insert(1, str(request.user.pk))
			msg = '%s/%s: ACCESS DENIED to user %s %s (pk=%s) from %s. request.    META is \'%s\'' % \
				(request.session.session_key, '-'.join(issue_code), request.user.first_name, 
					request.user.last_name, request.user.pk, request.META['REMOTE_ADDR'], request.META)
			logger.error(msg)
		else:
			issue_code.insert(1, 'NA')
			msg = '%s/%s: ACCESS DENIED to anonymous user from %s. request.META is \'%s\'' % \
				(request.session.session_key, '-'.join(issue_code), 
					request.META['REMOTE_ADDR'], request.META)
			logger.error(msg)
		issue_code.append(str(random.randrange(100, 999)))

		context['issue_code'] = '-'.join(issue_code)

		subj = _('ACL Denial %(issue_code)s: %(path)s') % \
			{'issue_code': '-'.join(issue_code), 'path': request.path}

		mail_admins(subj, msg, fail_silently=False)

		response = render_to_response('ACL/access_denied.html', context)
		response.status_code = 403
		return response
Example #3
0
def geocode2(addr,
             city,
             state,
             zipcode,
             geocoder=geocoders.Yahoo,
             appid=settings.YAHOO_APP_ID):
    """ 
	This is the new geocode lookup, it will by default use the yahoo
	geocoder, however a specific geocoder can be passed in in the geocoder field.  Note 
	some geocoders require an app id such as Yahoo, Google does not.
	see http://code.google.com/p/geopy/wiki/GettingStarted for supported geocoders.

	.. code-block:: python

		# TODO: pass in an ordered list of supported geocoders:
		geocoders = [(geocoder.Yahoo, appid), (geocoder.Google, None)]  # , etc..
		for geo in geocoders:  # something like this, some work without app_id like GoogleV3
			try:
				geo = geo[0](geo[1]) 
				msg, (lat, lng) = geo.geocode("%s, %s, %s, %s" % (addr, city, state, zipcode))
				break
			except Exception as err:
				msg = msg + str(err)
				lat = lng = 0.0

	:returns: dictionary lat, lng, msg.  msg will contain the location lookup and
		any error messages along the way.  lat,lng will be 0.0 if lookup fails
	"""
    # normalize
    msg = ""
    lat = lng = 0.0
    addr, city, state, zipcode = addr or "", city or "", state or "", zipcode or ""

    if addr or city or state or zipcode:
        try:
            geo = geocoder(appid)
            msg, (lat, lng) = geo.geocode("%s, %s, %s, %s" %
                                          (addr, city, state, zipcode))
        except Exception as err:
            msg = msg + str(err)
            # fall back on Google but check if original geocoder was not google
            if geocoder != geocoders.GoogleV3:
                try:  # try google
                    gg = geocoders.GoogleV3()
                    results = gg.geocode("%s, %s, %s, %s" %
                                         (addr, city, state, zipcode))
                    msg = msg + ", " + results[
                        0]  # keep first geocoder error in msg
                    lat, lng = results[1]
                except Exception as err:
                    msg = msg + ", " + str(err)
                    lat = lng = 0.0

        if (lat == 0.0 and lng == 0.0):
            msg = "Unable to determine address for %s, %s, %s, %s, description: %s" % \
             (addr, city, state, zipcode, msg)
            mail_admins('Geocode Error!', msg)
            logger.warn(msg)

    return {'lat': lat, 'lng': lng, 'msg': msg}
Example #4
0
def err403_denied(request):
	""" Helper to send access denied message to client and report incident to admin(s)

	:returns: HttpResonse with specified error template
	"""
	issue_code = ['ACD', str(int(time()) % 10000000)]
	if (request.user.is_authenticated()):
		issue_code.insert(1, str(request.user.pk))
		msg = '%s/%s: ACCESS DENIED to user %s %s (pk=%s) from %s. request.    "\
			"META is \'%s\'' % (request.session.session_key, '-'.join(issue_code), 
							request.user.first_name, request.user.last_name,
							request.user.pk, request.META['REMOTE_ADDR'], request.META)
	else:
		issue_code.insert(1, 'NA')
		msg = '%s/%s: ACCESS DENIED to anonymous user from %s. request.META is \'%s\'' % \
			(request.session.session_key, '-'.join(issue_code), 
				request.META['REMOTE_ADDR'], request.META)
	issue_code.append(str(random.randrange(100, 999)))

	issue_msg = '-'.join(issue_code)
	subj = _('ACL Denial %(issue_code)s: %(path)s') % \
		{'issue_code': issue_msg, 'path': request.path}
	mail_admins(subj, msg, fail_silently=False)

	return errxxx(request, 'ACL/access_denied.html', 403, None, {'issue_code': issue_msg})
Example #5
0
def delete_message(request, message_id):
	msgs = list(MessageBodyUserStatus.objects.filter(user=request.user,
						delete_flag=False, msg_body__message__uuid=message_id))
	# Integrity check.
	if (len(msgs) > 1):
		# shouldn't be possible!
		mail_admins('Duplicate message ID', ' '.join(['server: ',
				settings.SERVER_ADDRESS, '\n',
				'The message id with uuid', message_id, 'has returned with',
				'more than one Message!\nAt: ',
				str(inspect.getfile(inspect.currentframe())), ':',
					str(inspect.currentframe().f_back.f_lineno)
			]))
	elif (len(msgs) == 0):
		return err_IN003()

	status = msgs[0]
	status.delete_flag = True
	if (not status.delete_timestamp):
		status.delete_timestamp = int(time.time())
	status.save()

	response = {
		'data': {},
		'warnings': {},
	}
	return HttpResponse(content=json.dumps(response), mimetype='application/json')
Example #6
0
def sendToDicomServer(dicom_info):
	dicom_name = dicom_info["name"]
	dicom_token = str(dicom_info["token"])
	dicom_content = dicom_info["content"]

	opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(),
									MultipartPostHandler)
	params = { 
				DICOM_PARAM_NAME_REVOKE_URL : settings.DICOM_REVOKE_URL, 
				DICOM_PARAM_NAME_TOKEN : dicom_token,
				DICOM_PARAM_NAME_DICOM_FILE : FileInfo(dicom_name, dicom_content)
			}

	try:
		response = opener.open(settings.DICOM_SERVER_URL, params).read()
		return response
	except Exception as e:
		msg = 'Sending dicom to server failed -- attachment id: %s!' % (dicom_token)
		err_email_body = '\n'.join([
				msg,
				''.join(['Server: ', settings.SERVER_ADDRESS]),
				''.join(['Exception: ', str(e)]),
			])
		mail_admins(msg, err_email_body)
		raise e
Example #7
0
def download_pdf(request, refer_id):
	"""
	download_pdf

	:param request: Request info
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:param refer_id: referall id
	:type refer_id: int  
	:returns: django.http.HttpResponse -- the result in an HttpResonse object 
	"""
	refer = get_object_or_404(MessageRefer, uuid=refer_id)

	if (request.user != refer.message.sender and not
			(request.user in refer.message.recipients.all())):
		return err403(request, err_msg="You don't seem to be a valid recipient for this file.")

	try:
		response = refer.get_file(request)
		return response
	except Exception as e: 
		err_email_body = '\n'.join([
		('PDF file not exist!'),
		''.join(['Server: ', settings.SERVER_ADDRESS]),
		''.join(['Session: ', str(request.session.session_key)]),
		''.join(['Message: ', (u'PDF file not exist in media/refer/pdf')]),
		''.join(['Exception: ', str(e)]),
		''.join(['Exception data: ', str(e.args)]),
		])
		mail_admins(_('PDF folder not exist'), err_email_body)
		raise Exception(_('A seemingly invalid URL has been stored for Refer Pdf.'))
Example #8
0
def save_voice_attachment(request, msg):
    wav_data, metadata = _download_recording(request)
    metadata = json.dumps(metadata)
    if (not wav_data):
        admin_email_body = ''.join([
            ('Answering service recording download failed on call SID '),
            request.REQUEST['CallSid'], ('. Since the automatic '),
            ('downloader hasn\'t been implemented yet, please go and'),
            ('manually deal with the message.\n\n'), settings.SERVER_ADDRESS
        ])
        admin_email_subject = _('Answering Service Message Download Failed')
        mail_admins(admin_email_subject, admin_email_body)
        return None
    attachment = encrypt_object(
        MessageAttachment, {
            'message': msg,
            'size': len(wav_data),
            'encrypted': True,
            'metadata': metadata
        })
    attachment.encrypt_url(request, ''.join(['file://', attachment.uuid]))
    attachment.encrypt_filename(
        request, ''.join([
            'call_from_', request.session['ivr_makeRecording_callbacknumber'],
            '.mp3'
        ]))
    try:
        attachment.encrypt_file(request, [wav_data])
    except Exception as e:
        log = AnsSvcDLFailure(
            practice_id=request.session.get('practice_id', 0),
            error_message_uuid=msg.uuid,
            recording_url=request.session['ivr_makeRecording_recording'],
            callback_number=request.
            session['ivr_makeRecording_callbacknumber'],
            failure_type='UL',
        )
        log.init_from_post_data(request.REQUEST)
        log.save()
        admin_email_body = ''.join([
            ('Answering service recording upload failed on call SID '),
            request.REQUEST['CallSid'], ('. Since the automatic '),
            ('downloader hasn\'t been implemented yet, please go and'),
            ('manually deal with the message.\n\n'), settings.SERVER_ADDRESS,
            ('\n\nException: '),
            repr(e)
        ])
        admin_email_subject = _('Answering Service Message Upload Failed')
        mail_admins(admin_email_subject, admin_email_body)
        return None

    if (not USE_MP3):
        attachment.suffix = 'wav'
        attachment.content_type = 'audio/wav'
    else:
        attachment.suffix = 'mp3'
        attachment.content_type = 'audio/mp3'

    attachment.save()
    return attachment
Example #9
0
def notify_iphones(associations, notification):
    """Common function: send notification to iPhone client.
		:param associations: list of SmartPhoneAssn.
		:param notification: notification data, dict object.
	"""
    try:
        if (not OPTIONS['CONFIGURED']):
            configure(None)
    except Exception as e:
        err_email_body = '\n'.join([
            ('APNS configuration has errors!'),
            ''.join(['Server: ', settings.SERVER_ADDRESS]),
            ''.join(['Message: ', ('Notify mobile has errors.')]),
            ''.join(['Exception: ', str(e)]),
            ''.join(['Exception data: ', str(e.args)]),
        ])
        mail_admins('notify mobile has errors', err_email_body)
        return

    tokens = [assn.push_token for assn in associations]
    try:
        notify(settings.APS_APPID, tokens, [notification] * len(tokens))
        logger.debug("Notify users(ios): %s for %s" %
                     (str(tokens), str(notification)))
    except Exception:
        pass
Example #10
0
	def clean(self):
		cleaned_data = self.cleaned_data
		street = cleaned_data['practice_address1']
		city = cleaned_data['practice_city']
		state = cleaned_data['practice_state']
		zip = cleaned_data['practice_zip']

		if(self.instance):

			def compare(form, model, field):
				return form.cleaned_data[field] == model.__getattribute__(field)
			if(all(compare(self, self.instance, field) for field in ('practice_address1', 
					'practice_city', 'practice_state', 'practice_zip'))):
				self.cleaned_data['practice_lat'] = self.instance.practice_lat
				self.cleaned_data['practice_longit'] = self.instance.practice_longit
				return cleaned_data
		if ((street and city and state)) or ((street and zip)):
			results = geocode2(street, city, state, zip)
			if results['lat'] == 0.0 and results['lng'] == 0.0:
				from MHLogin.utils.admin_utils import mail_admins
				self.non_field_warnings = _('Warning: Your form has been saved but '
					'determining coordinates from the entered address was not successful.  '
					'Please verify correctness, if this persists our staff will be notified.  '
					'Our apologies, thanks for your patience - DoctorCom staff.')
				mail_admins('Geocode error in Practice form save', 'Geocode lookup '
					'problems saving PracticeLocation: %s.\n\nGeocode message:\n%s' % 
					(self.instance.practice_name, results['msg']))
			else:
				self.non_field_warnings = None
			cleaned_data['practice_lat'] = results['lat']
			cleaned_data['practice_longit'] = results['lng']
		else:
			raise ValidationError(_('At a minimum, please enter in either '
				'street, city and state or street and zip'))
		return cleaned_data
Example #11
0
	def clean(self):
		cleaned_data = super(BrokerUserForm, self).clean()
		street = cleaned_data['address1']
		city = cleaned_data['city']
		state = cleaned_data['state']
		zip = cleaned_data['zip']

		if(self.instance):
			def compare(form, model, field):
				return form.cleaned_data[field] == model.__getattribute__(field)
			if(all(compare(self, self.instance, field) for field in 
					('address1', 'city', 'state', 'zip'))):
				self.cleaned_data['lat'] = self.instance.lat
				self.cleaned_data['longit'] = self.instance.longit
				return cleaned_data
		if ((street and city and state)) or ((street and zip)):
			results = geocode2(street, city, state, zip)
			if results['lat'] == 0.0 and results['lng'] == 0.0:
				from MHLogin.utils.admin_utils import mail_admins
				self.non_field_warnings = MSG_GEO_ADDRESS_INVALID
				mail_admins('Geocode error in Broker form save', 'Geocode lookup '
					'problems saving Broker: %s.\n\nGeocode message:\n%s' % 
					(self.instance.username, results['msg']))
			else:
				self.non_field_warnings = None
			cleaned_data['lat'] = results['lat']
			cleaned_data['longit'] = results['lng']
		else:
			raise forms.ValidationError(MSG_GEO_EMPTY)

		return cleaned_data
Example #12
0
def download_pdf(request, refer_id):
    """
	download_pdf

	:param request: Request info
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:param refer_id: referall id
	:type refer_id: int  
	:returns: django.http.HttpResponse -- the result in an HttpResonse object 
	"""
    refer = get_object_or_404(MessageRefer, uuid=refer_id)

    if (request.user != refer.message.sender
            and not (request.user in refer.message.recipients.all())):
        return err403(
            request,
            err_msg="You don't seem to be a valid recipient for this file.")

    try:
        response = refer.get_file(request)
        return response
    except Exception as e:
        err_email_body = '\n'.join([
            ('PDF file not exist!'),
            ''.join(['Server: ', settings.SERVER_ADDRESS]),
            ''.join(['Session: ',
                     str(request.session.session_key)]),
            ''.join(['Message: ', (u'PDF file not exist in media/refer/pdf')]),
            ''.join(['Exception: ', str(e)]),
            ''.join(['Exception data: ', str(e.args)]),
        ])
        mail_admins(_('PDF folder not exist'), err_email_body)
        raise Exception(
            _('A seemingly invalid URL has been stored for Refer Pdf.'))
Example #13
0
	def exception_email(self, request, exc_info):
		subject = _('Error (%(ip)s IP): %(path)s') % \
			{'ip': (request.META.get('REMOTE_ADDR') in 
				settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), 'path': request.path}
		try:
			request_repr = repr(request)
		except:
			request_repr = "Request repr() unavailable"
		message = "%s\n\n%s" % (_get_traceback(exc_info), request_repr)
		mail_admins(subject, message, include_stack=False)
Example #14
0
 def exception_email(self, request, exc_info):
     subject = _('Error (%(ip)s IP): %(path)s') % \
      {'ip': (request.META.get('REMOTE_ADDR') in
       settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), 'path': request.path}
     try:
         request_repr = repr(request)
     except:
         request_repr = "Request repr() unavailable"
     message = "%s\n\n%s" % (_get_traceback(exc_info), request_repr)
     mail_admins(subject, message, include_stack=False)
Example #15
0
def alternativeCallerID(sender, recipient):
	"""
	Creates a mapping between an SMS sender and recipient, should the sender
	NOT have a DoctorCom number.

	To create a mapping, just pass in the sender and recipient normally.

	To look up a mapping, pass the recipient and sender in reverse. That is, with the
	inbound sender as the function argument /recipient/, and the inbound recipient as
	the function argument /sender/.

	Arguments:
		sender - An MHLUser object; the sender of the SMS message
		recipient - An MHLUser object; the recipient of the SMS message
	Returns:
		A caller ID to send the user.
	"""

	# First, see if this mapping already exists.
	mapping = SenderLookup.objects.filter(user=sender).filter(mapped_user=recipient)
	if (mapping.count() == 1):
		mapping = mapping.get()
		mapping.save()  # update the timestamp
		return mapping.number
	if (mapping.count() > 1):
		import cPickle
		mail_admins('Django Error: Multiple SenderLookup Objects Found',
			cPickle.dumps(list(mapping.all())))
		return mapping[0].number

	# Okay, the mapping doesn't exist. Create it.

	# If the user hasn't exhausted the number pool....
	mapping_count = SenderLookup.objects.filter(mapped_user=recipient).count()
	if (mapping_count < len(settings.TWILIO_SMS_NUMBER_POOL)):
		# number pool hasn't been exhausted yet.
		lookup = SenderLookup(
				user=sender,
				mapped_user=recipient,
				number=settings.TWILIO_SMS_NUMBER_POOL[mapping_count],
			)
		lookup.save()
		return lookup.number
	else:
		oldest = SenderLookup.objects.filter(mapped_user=recipient).order_by('timestamp', 'pk')[0]

		sms_number = oldest.number
		oldest.delete()
		lookup = SenderLookup(
				user=sender,
				mapped_user=recipient,
				number=sms_number,
			)
		lookup.save()
		return lookup.number
Example #16
0
def twilioSMS_incoming(request):

	logger.debug('%s: into twilioSMS_incoming' % (request.session.session_key,))

	# TODO: Data sanitation is necessary on the following request.POST values.
	# For the time being, we're just going to trust Twilio.
	status = request.POST['SmsStatus']
	sid = request.POST['SmsSid']
	from_no = request.POST['From']
	to_no = request.POST['To']
	body = request.POST['Body']

	# First, check to ensure that the sender is a DoctorCom user.
	fromQuerySet = MHLUser.objects.filter(mobile_phone=from_no)
	if (not fromQuerySet.count()):
		# TODO: Reply back with an error.
		pass
	if (fromQuerySet.count() > 1):
		# More than one user has this mobile phone number!
		raise Exception('More than one user has the sender\'s mobile phone number')
		# TODO: mail_admins, then iterate over all recipients with messages.
	fromUser = fromQuerySet.get()

	toQuerySet = Provider.objects.filter(mdcom_phone=to_no)
	if (not toQuerySet.count()):
		# this is either an unassigned number, or this is from the generic SMS
		# number pool.
		if (to_no in settings.TWILIO_SMS_NUMBER_POOL):
			lookupEntry = SenderLookup.objects.filter(number=to_no).filter(mapped_user=fromUser).get()
			lookupEntry.save()  # update the timestamp
			toUser = lookupEntry.user
		else:
			mail_admins('Django Error: Incoming SMS message to unassigned number',
				repr(request.POST))
			return HttpResponse(str(twilio.Response()), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
	else:
		toUser = toQuerySet.get().user

	#build dashboard message to send along with sms
	from ..Messaging.models import Message, MessageRecipient
	message = Message(sender=fromUser, sender_site=None,
			message_type='SMS', subject="DoctorCom msg from %s %s" %
				(fromUser.first_name, fromUser.last_name))
	message.save()

	#formatted_body = ''.join(['DoctorCom msg from ', fromUser.first_name, ' ',
	#   fromUser.last_name, ': ', body])
	message_body = message.save_body(body)
	MessageRecipient(message=message, user=toUser).save()
	#message Send() also takes care of SMS, comment out sendSMS_Twilio(request, message, message_body)
	message.send(request, message_body)

	#sendSMS_Twilio(request, message, message_body)
	return HttpResponse(str(twilio.Response()), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
Example #17
0
	def handle(self, *args, **options):
		#table_name = 'Scheduler_evententry'
		#cursor = connection.cursor()

		#cursor.execute(' '.join(['SELECT * from', table_name]))
		#raw_dump = cursor.fetchall()

		qs = EventEntry.objects.all().order_by('id')
		body = '\n'.join([repr(e) for e in qs])

		mail_admins(''.join(['Events Dump (', datetime.now().strftime('%Y.%m.%d@%H:%M'), ')']), body)
Example #18
0
def geocode2(addr, city, state, zipcode, geocoder=geocoders.Yahoo, appid=settings.YAHOO_APP_ID):
	""" 
	This is the new geocode lookup, it will by default use the yahoo
	geocoder, however a specific geocoder can be passed in in the geocoder field.  Note 
	some geocoders require an app id such as Yahoo, Google does not.
	see http://code.google.com/p/geopy/wiki/GettingStarted for supported geocoders.

	.. code-block:: python

		# TODO: pass in an ordered list of supported geocoders:
		geocoders = [(geocoder.Yahoo, appid), (geocoder.Google, None)]  # , etc..
		for geo in geocoders:  # something like this, some work without app_id like GoogleV3
			try:
				geo = geo[0](geo[1]) 
				msg, (lat, lng) = geo.geocode("%s, %s, %s, %s" % (addr, city, state, zipcode))
				break
			except Exception as err:
				msg = msg + str(err)
				lat = lng = 0.0

	:returns: dictionary lat, lng, msg.  msg will contain the location lookup and
		any error messages along the way.  lat,lng will be 0.0 if lookup fails
	"""
	# normalize
	msg = ""
	lat = lng = 0.0
	addr, city, state, zipcode = addr or "", city or "", state or "", zipcode or ""

	if addr or city or state or zipcode:
		try:
			geo = geocoder(appid) 
			msg, (lat, lng) = geo.geocode("%s, %s, %s, %s" % (addr, city, state, zipcode))
		except Exception as err:
			msg = msg + str(err)
			# fall back on Google but check if original geocoder was not google
			if geocoder != geocoders.GoogleV3:
				try:  # try google
					gg = geocoders.GoogleV3()
					results = gg.geocode("%s, %s, %s, %s" % (addr, city, state, zipcode))
					msg = msg + ", " + results[0]  # keep first geocoder error in msg
					lat, lng = results[1]
				except Exception as err:
					msg = msg + ", " + str(err)
					lat = lng = 0.0

		if (lat == 0.0 and lng == 0.0):
			msg = "Unable to determine address for %s, %s, %s, %s, description: %s" % \
				(addr, city, state, zipcode, msg)
			mail_admins('Geocode Error!', msg) 
			logger.warn(msg)

	return {'lat': lat, 'lng': lng, 'msg': msg}
Example #19
0
def Twilio_record_initiate(request):
	abs_uri = '://'.join([settings.SERVER_PROTOCOL, settings.SERVER_ADDRESS])
	url = reverse('MHLogin.tests.views.Twilio_record')
	sid = Twilio_call_initiate(request, 2, urljoin(abs_uri, url))

	mail_admins('Test harness: New keypress recording', ''.join([
						'A new recording has been created with callSID ',
						sid
					]))

	context = get_context(request)
	context['sid'] = sid
	return render_to_response("tests/confirm_recording.html", context)
Example #20
0
    def handle(self, *args, **kwargs):
        msgs = AnsSvcDLFailure.objects.filter(resolved=False)
        if (len(msgs)):
            successes = []
            failures = []
            for msg in msgs:
                try:
                    resolution_success = resolve_download_failure(msg)
                except Exception:
                    failures.append(msg.call_sid)
                    mail_admins(_("Failed to retry Ans. Svc. DL Failure"),
                                traceback.format_exc())
                    transaction.rollback()
                else:
                    if (resolution_success):
                        successes.append(msg.call_sid)
                        mail_admins(_("Ans. Svc. DL Failure Retry Success"),
                                    msg.call_sid)
                        transaction.commit()
                    else:
                        failures.append(msg.call_sid)
                        mail_admins(_("Failed to retry Ans. Svc. DL Failure"),
                                    traceback.format_exc())
                        transaction.rollback()

            mail_admins(
                _('IVR Message Automatic Retry Status'),
                _('Successes: %(successes)s\nFailures: %(failures)s') % {
                    'successes': ', '.join(successes),
                    'failures': ', '.join(failures),
                })
Example #21
0
	def handle(self, *args, **kwargs):
		msgs = AnsSvcDLFailure.objects.filter(resolved=False)
		if (len(msgs)):
			successes = []
			failures = []
			for msg in msgs:
				try:
					resolution_success = resolve_download_failure(msg)
				except Exception:
					failures.append(msg.call_sid)
					mail_admins(_("Failed to retry Ans. Svc. DL Failure"),
							traceback.format_exc())
					transaction.rollback()
				else:
					if (resolution_success):
						successes.append(msg.call_sid)
						mail_admins(_("Ans. Svc. DL Failure Retry Success"),
								msg.call_sid)
						transaction.commit()
					else:
						failures.append(msg.call_sid)
						mail_admins(_("Failed to retry Ans. Svc. DL Failure"),
								traceback.format_exc())
						transaction.rollback()

			mail_admins(_('IVR Message Automatic Retry Status'),
					_('Successes: %(successes)s\nFailures: %(failures)s') %
					{'successes': ', '.join(successes), 'failures': ', '.join(failures), }
				)
Example #22
0
def run_purge_expired_sessions():
	"""
	Entry point used by kronos to run_purge_expired_sessions, checks daily.  For django 
	kronos installtasks command to work decorated function must be in python module 
	loaded at startup such as: models, __init__, admin, .cron, etc..
	"""
	try:
		recs = purge_expired_sessions()
		logger.info("kronos purge_expired_sessions: %d purged, DONE." % recs)
	except Exception as e:
		# enclose in try/catch Exception for now, run_purge_expired_sessions()
		# is run daily, code was not active on production until 1.64.00.
		mail_admins("Problems in run_purge_expired_sessions()", str(e))
		logger.error("Problems in run_purge_expired_sessions() %s" % str(e))
Example #23
0
    def handle(self, *args, **options):
        #table_name = 'Scheduler_evententry'
        #cursor = connection.cursor()

        #cursor.execute(' '.join(['SELECT * from', table_name]))
        #raw_dump = cursor.fetchall()

        qs = EventEntry.objects.all().order_by('id')
        body = '\n'.join([repr(e) for e in qs])

        mail_admins(
            ''.join([
                'Events Dump (',
                datetime.now().strftime('%Y.%m.%d@%H:%M'), ')'
            ]), body)
Example #24
0
	def clean(self):
		cleaned_data = self.cleaned_data
		street = cleaned_data['address1']
		city = cleaned_data['city']
		state = cleaned_data['state']
		zip = cleaned_data['zip']

		#clean mobile phone - required for providers	
		if(not 'mobile_phone' in cleaned_data or not cleaned_data['mobile_phone']):
			raise forms.ValidationError(MSG_MOBILE_PHONE_REQUIRED)

		email_confirmed = cleaned_data['email_confirmed']
		mobile_confirmed = cleaned_data['mobile_confirmed']
		pager_confirmed = cleaned_data['pager_confirmed']

		if not email_confirmed:
			cleaned_data['email'] = cleaned_data['old_email']
			cleaned_data['email_confirmed'] = cleaned_data['old_email_confirmed']
		if settings.CALL_ENABLE and not mobile_confirmed:
			cleaned_data['mobile_phone'] = cleaned_data['old_mobile_phone']
			cleaned_data['mobile_confirmed'] = cleaned_data['old_mobile_confirmed']
		if settings.CALL_ENABLE and not pager_confirmed and cleaned_data['pager']:
			cleaned_data['pager'] = cleaned_data['old_pager']
			cleaned_data['pager_confirmed'] = cleaned_data['old_pager_confirmed']

		if(self.instance):
			def compare(form, model, field):
				return form.cleaned_data[field] == model.__getattribute__(field)
			if(all(compare(self, self.instance, field) for field in 
					('address1', 'city', 'state', 'zip'))):
				self.cleaned_data['lat'] = self.instance.lat
				self.cleaned_data['longit'] = self.instance.longit
				return cleaned_data
		if ((street and city and state)) or ((street and zip)):
			results = geocode2(street, city, state, zip)
			if results['lat'] == 0.0 and results['lng'] == 0.0:
				from MHLogin.utils.admin_utils import mail_admins
				self.non_field_warnings = MSG_GEO_ADDRESS_INVALID
				mail_admins('Geocode error in Provider form save', 'Geocode lookup '
					'problems saving Provider: %s.\n\nGeocode message:\n%s' % 
					(self.instance.username, results['msg']))
			else:
				self.non_field_warnings = None
			cleaned_data['lat'] = results['lat']
			cleaned_data['longit'] = results['lng']
		else:
			raise forms.ValidationError(MSG_GEO_EMPTY)
		return cleaned_data
Example #25
0
	def delete(self):
		"""
		Disallow direct deletion of this object. Also, report all calls to delete 
		on this object as a DEBUG step.
		"""
		self.eventStatus = 0
		self.save()

		# DEBUG
		context = {
			'call_stack': ''.join(traceback.format_stack()),
			'event': self,
			'server_addr': settings.SERVER_ADDRESS,
		}
		body = render_to_string('MHLCallGroups/Scheduler/email_delete_event.txt', context)
		mail_admins(_('Event Deletion Attempt!'), body)
Example #26
0
def validate_user(token, tempcode):
	""" Validate token and verify internal log and user exist """
	tup = None, None
	try:
		expire = 3600 * 4  # four hours
		user_pk, date = signing.loads(token, max_age=expire, salt=SOME_SALT)
		date = json.loads(date)
		# our first stab at signing... if trusted we don't need LogEntry or tempcode
		log = LogEntry.objects.filter(user__pk=user_pk, object_repr=LOG_ACTION_ID,
			action_flag=ADDITION, change_message=tempcode, action_time=date)
		user = MHLUser.objects.filter(pk=user_pk)
		tup = (user.get(), log) if user.exists() and log.exists() else tup
	except (signing.BadSignature, ValueError) as e:
		msg = "token: %s, tempcode: %s, exception: %s" % (token, tempcode, str(e))
		mail_admins("Expired token or invalid code", msg)
	return tup
Example #27
0
def fetchRecording(request, uuid):
	"""
	:returns: recording to twilio
	"""
	attachment = MessageAttachment.objects.filter(uuid=uuid)
	if attachment:
		attachment = attachment[0]
		response = HttpResponse(content_type=attachment.content_type)
		try:
			attachment.get_file(request, response, ivr=True)
		except:
			body = "Unable to fetch recording, filename in storage: %s" % attachment.uuid
			mail_admins("Error fetching recording", body)
			with open(FETCH_ERROR, "rb") as f:
				return HttpResponse(f.read(), mimetype='audio/wav')
		return response
	return err404()
Example #28
0
    def delete(self):
        """
		Disallow direct deletion of this object. Also, report all calls to delete 
		on this object as a DEBUG step.
		"""
        self.eventStatus = 0
        self.save()

        # DEBUG
        context = {
            'call_stack': ''.join(traceback.format_stack()),
            'event': self,
            'server_addr': settings.SERVER_ADDRESS,
        }
        body = render_to_string(
            'MHLCallGroups/Scheduler/email_delete_event.txt', context)
        mail_admins(_('Event Deletion Attempt!'), body)
Example #29
0
def generate_new_user_keys(user, password):
	""" 
	Legacy helper to generate new rsa keys for user, keeping existing.  This will
	no longer be needed when #2115 in, but may be kept for prosperity.  Note: This 
	function will deny a user access to his/her *old* messages until the Administrator 
	logs in and enters the Administrator key.

	:param user: Base class MHLUser type.
	:param password: The user's new password.
	"""
	mail_admins('Password Force Change Notice (%s)' % settings.SERVER_ADDRESS,
		'%s %s (%s) force changed their password. Please go and reset their old keys.' %
			(user.first_name, user.last_name, user.username,))
	ipubs = OwnerPublicKey.objects.filter_pubkey(owner=user)
	UserPrivateKey.objects.filter(opub__in=ipubs).delete()
	ipubs.update(active=False)
	create_default_keys(user, password)
Example #30
0
def resolve_anssvc_dl_failures():
	"""
	Entry point used by kronos to resolve anssvc dl failures, checks every minute.  For 
	django kronos installtasks command to work decorated function must be in python 
	module loaded at startup such as: models, __init__, admin, .cron, etc..
	"""
	try:
		from MHLogin.DoctorCom.IVR.utils import resolve_download_failure
		msgs = AnsSvcDLFailure.objects.filter(resolved=False)
		for msg in msgs:
			resolve_download_failure(msg)
		logger.info("resolve_anssvc_dl_failures, DONE.")
	except Exception as e:
		# enclose in try/catch Exception for now, resolve_download_failure()
		# is run every minute, code was not active on production until 1.64.00.
		mail_admins("Problems in resolve_anssvc_dl_failures()", str(e))
		logger.error("Problems in resolve_anssvc_dl_failures() %s" % str(e))
Example #31
0
def generate_pdf(refer, request, context):
    """
	generate_pdf

	:param refer: Refer info
	:type refer: TODO 
	:param request: The request info 
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:param context: context
	:type context: TODO
	:returns: None -- Creates PDF file in refer/pdf directory
	"""
    try:
        from weasyprint import HTML
        # path contains leading / so use string join instead of path join
        img = ''.join(
            [settings.INSTALLATION_PATH, context['current_practice_photo']])
        html = render_to_string('DoctorCom/Messaging/PreviewDialog.html', {
            'pdf': True,
            'practice_photo_path': img
        }, context)

        htmlobj = HTML(string=html)
        pdf = htmlobj.write_pdf()

        encrypted_data = refer.encrypt_file(request, pdf)

        refer_pdf = '%s/refer/pdf' % (settings.MEDIA_ROOT, )
        if not os.path.exists(refer_pdf):
            os.makedirs(refer_pdf)

        f = create_file('refer/pdf/%s' % refer.uuid)
        f.set_contents(encrypted_data)
        f.close()
    except IOError as e:
        err_email_body = '\n'.join([
            ('PDF folder not exist!'),
            ''.join(['Server: ', settings.SERVER_ADDRESS]),
            ''.join(['Session: ',
                     str(request.session.session_key)]),
            ''.join(['Message: ', (u'PDF folder not exist: media/refer/pdf')]),
            ''.join(['Exception: ', str(e)]),
            ''.join(['Exception data: ', str(e.args)]),
        ])
        mail_admins('PDF folder not exist', err_email_body)
Example #32
0
def get_refer_pdf(request, refer_id):
	"""
	get_refer_pdf

	:param request: Request info
	:type request: django.core.handlers.wsgi.WSGIRequest
	:param refer_id: referall id
	:type refer_id: uuid
	:returns: django.http.HttpResponse -- the result in an HttpResonse object
	"""
	if (request.method != 'POST'):
		return err_GE002()
	form = MsgGetForm(request.POST)
	if (not form.is_valid()):
		return err_GE031(form)

	refer = get_object_or_404(MessageRefer, uuid=refer_id)

	message = refer.message
	if ((message.sender and request.user.pk != message.sender.pk) and
		not ((request.user.pk,) in message.recipients.values_list('id') or
			(request.user.pk,) in message.ccs.values_list('id'))):
		return err403(request, err_msg=_("You don't seem to be a valid recipient for this file."))

	# Get/set up data for KMS.
	request.session['key'] = request.device_assn.secret
	try:
		clearkey = decrypt_cipherkey(request, refer, ss=form.cleaned_data['secret'])
	except KeyInvalidException:
		return err_GE021()

	try:
		response = refer.get_file(request, clearkey)
		return response
	except Exception as e:
		err_email_body = '\n'.join([
				('PDF file not exist!'),
				''.join(['Server: ', settings.SERVER_ADDRESS]),
				''.join(['Session: ', str(request.session.session_key)]),
				''.join(['Message: ', (u'PDF file not exist in media/refer/pdf')]),
				''.join(['Exception: ', str(e)]),
				''.join(['Exception data: ', str(e.args)]),
			])
		mail_admins(_('PDF folder not exist'), err_email_body)
		raise Exception(_('A seemingly invalid URL has been stored for Refer Pdf.'))
Example #33
0
def notify_androids(associations, notification):
    """Common function: send notification to Android client.
		:param associations: list of SmartPhoneAssn.
		:param notification: notification data, dict object.
	"""
    gcm = GCM(settings.GCM_API_KEY)
    tokens = []
    for assn in associations:
        if assn.push_token not in tokens:
            tokens.append(assn.push_token)
            try:
                gcm.plaintext_request(registration_id=assn.push_token,
                                      data=notification)
                logger.debug("Notify users(android): %s for %s" %
                             (str(assn.push_token), str(notification)))
            except Exception as e:
                logger.error(e)
                mail_admins("GCM error", e)
Example #34
0
def confirm_test(request):
	context = get_context(request)
	success = 0

	if (request.POST['test_result'] == '1'):
		context['result'] = 'Success'
		context['success'] = 1
		success = 1
	else:
		context['result'] = 'Failure'
		context['success'] = 0

		# email admins
		mail_admins('Failed Test', ''.join([
						'Test harness failure ',
						test_types[request.POST['test_type']],
						', with ID ', request.POST['test_id']
					]))

	import re
	log_id = re.match('\d+', request.POST['test_id'])
	if (log_id == None):
		raise Exception("The log ID failed the regex check.")
	log_id = log_id.group(0)

	log = None

	# this isn't too efficient, but it works.
	if (request.POST['test_type'] == '1'):
		log = DoctorComC2CTest.objects.filter(id=log_id).get()
	elif (request.POST['test_type'] == '2'):
		log = DoctorComPagerTest.objects.filter(id=log_id).get()
	elif (request.POST['test_type'] == '10'):
		log = TwilioCallGatherTest.objects.filter(id=log_id).get()

	if (log == None):
		raise Exception("Failed to retrieve the log.")

	log.success = success
	log.save()

	context['admins'] = settings.ADMINS
	return render_to_response("tests/confirm_finish.html", context)
Example #35
0
def validate_user(token, tempcode):
    """ Validate token and verify internal log and user exist """
    tup = None, None
    try:
        expire = 3600 * 4  # four hours
        user_pk, date = signing.loads(token, max_age=expire, salt=SOME_SALT)
        date = json.loads(date)
        # our first stab at signing... if trusted we don't need LogEntry or tempcode
        log = LogEntry.objects.filter(user__pk=user_pk,
                                      object_repr=LOG_ACTION_ID,
                                      action_flag=ADDITION,
                                      change_message=tempcode,
                                      action_time=date)
        user = MHLUser.objects.filter(pk=user_pk)
        tup = (user.get(), log) if user.exists() and log.exists() else tup
    except (signing.BadSignature, ValueError) as e:
        msg = "token: %s, tempcode: %s, exception: %s" % (token, tempcode,
                                                          str(e))
        mail_admins("Expired token or invalid code", msg)
    return tup
Example #36
0
def generate_pdf(refer, request, context):
	"""
	generate_pdf

	:param refer: Refer info
	:type refer: TODO 
	:param request: The request info 
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:param context: context
	:type context: TODO
	:returns: None -- Creates PDF file in refer/pdf directory
	"""
	try:
		from weasyprint import HTML
		# path contains leading / so use string join instead of path join
		img = ''.join([settings.INSTALLATION_PATH, context['current_practice_photo']]) 
		html = render_to_string('DoctorCom/Messaging/PreviewDialog.html', 
			{'pdf': True, 'practice_photo_path': img}, context)

		htmlobj = HTML(string=html)
		pdf = htmlobj.write_pdf() 

		encrypted_data = refer.encrypt_file(request, pdf)

		refer_pdf = '%s/refer/pdf' % (settings.MEDIA_ROOT,)
		if not os.path.exists(refer_pdf):
			os.makedirs(refer_pdf)		

		f = create_file('refer/pdf/%s' % refer.uuid)
		f.set_contents(encrypted_data)
		f.close()
	except IOError as e:
		err_email_body = '\n'.join([
				('PDF folder not exist!'),
				''.join(['Server: ', settings.SERVER_ADDRESS]),
				''.join(['Session: ', str(request.session.session_key)]),
				''.join(['Message: ', (u'PDF folder not exist: media/refer/pdf')]),
				''.join(['Exception: ', str(e)]),
				''.join(['Exception data: ', str(e.args)]),
			])
		mail_admins('PDF folder not exist', err_email_body)
Example #37
0
		def inner_impl(request, *args, **kwargs):
			if not settings.DEBUG:
				ip_hash = str(hash(request.META['REMOTE_ADDR']))
				hashkey = ip_hash + '_ratelimview_' + func.func_name
				# TODO: profile --> hash the whole string instead of just ip?
				hit = cache.get(hashkey)
				if hit:
					hit = int(hit)
					if hit >= limit:
						mail_admins("Telling my mom! Rate limit exceeded", repr(request))
						resp = HttpResponseForbidden("Too many requests!")
					else:
						hit += 1
						cache.set(hashkey, hit, length)
						resp = func(request, *args, **kwargs)
				else:
					cache.add(hashkey, 1, length)
					resp = func(request, *args, **kwargs)
			else:
				resp = func(request, *args, **kwargs)
			return resp
Example #38
0
def check_feedback():
    """
	Entry point used by kronos to check_feedback, checks daily.  For django kronos 
	installtasks command to work decorated function must be in python module loaded at
	startup such as: models, __init__, admin, .cron, etc..
	"""
    import socket
    try:
        if not OPTIONS['CONFIGURED']:
            configure(None)

        tokens = feedback(settings.APS_APPID)
        for expire_time, token in tokens:
            associations = SmartPhoneAssn.objects.filter(push_token=token,
                                                         platform='iPhone')
            if associations:
                associations.update(push_token=None)
        logger.info("APNS check_feedback() DONE.")
    except socket.error as e:
        logger.error(str(e))
        mail_admins("APNS check_feedback() error", str(e))
Example #39
0
def generate_new_user_keys(user, password):
    """ 
	Legacy helper to generate new rsa keys for user, keeping existing.  This will
	no longer be needed when #2115 in, but may be kept for prosperity.  Note: This 
	function will deny a user access to his/her *old* messages until the Administrator 
	logs in and enters the Administrator key.

	:param user: Base class MHLUser type.
	:param password: The user's new password.
	"""
    mail_admins(
        'Password Force Change Notice (%s)' % settings.SERVER_ADDRESS,
        '%s %s (%s) force changed their password. Please go and reset their old keys.'
        % (
            user.first_name,
            user.last_name,
            user.username,
        ))
    ipubs = OwnerPublicKey.objects.filter_pubkey(owner=user)
    UserPrivateKey.objects.filter(opub__in=ipubs).delete()
    ipubs.update(active=False)
    create_default_keys(user, password)
Example #40
0
		def decorator_impl(request, *args, **kwargs):
			valid = False
			twilio_msg = _("Twilio signature invalid or missing.")
			if request.method == 'POST' or allow_get:
				if 'HTTP_X_TWILIO_SIGNATURE' not in request.META:
					mail_admins('HTTP_X_TWILIO_SIGNATURE missing', repr(request))
				else:			
					valid = validator.validate(uri=request.build_absolute_uri(), 
						signature=request.META['HTTP_X_TWILIO_SIGNATURE'],
							params=request.POST)
					if not valid:
						mail_admins("Twilio request didn't validate", repr(request))
			else:
				admin_msg = 'We received an unexpected request from Twilio to this URL:' \
					'\n\n%s\n\nIt is possible the configured url did not end with a "/", ' \
					'the configuration uses GET\ninstead of POST, or the view function ' \
					'should allow GET.  Please check the Twilio\nconfig for this user ' \
					'or practice, or check the view function.\n\n\n%s' % \
					(request.path, str(request))
				twilio_msg = _('Received unexpected request type from Twilio')
				mail_admins(twilio_msg, admin_msg)

			return func(request, *args, **kwargs) if valid else \
				err4xx(request, FORBIDDEN, twilio_msg)
Example #41
0
	def send(self, request, body_obj, attachment_objs=[], refer_objs=[]):
		"""
		Send this message. Note that this also saves the message automatically! Do NOT call 
		save on this object afterward!

		Requirements:
			1. You have to have run the save_body method to create a MessageBody object for the sender.

		Arguments:
			request: The standard Django HttpRequest object. This is required for decryption 
			of the body, if the optional body argument is omitted.
		"""
		# Disallow send of messages that have already been sent
		if (not self.draft):
			raise Exception(_('Trying to send a message that\'s already been sent.'))		
		# Generate a list of recipients, merging CCs and whatnot.
		all_recipients = list(self.recipients.all())
		all_recipients.extend(list(self.ccs.all()))
		recipients = list(self.recipients.all())
		if(not recipients):
			raise InvalidRecipientException(_("At least one recipient is required"))
		non_sender_recipients = [user for user in all_recipients if user.pk != 
								(self.sender.pk if self.sender else None)] 
		# remove the sender from the list of recipients to generate keys for

		# First, generate copies of the private key for the body of this message, except for the sender.
		ivr = self.message_type in ('VM', 'ANS')
		gen_keys_for_users(body_obj, non_sender_recipients, body_obj._key, request, ivr)

#		smartphones = SmartPhoneAssn.objects.filter(user__in=all_recipients)
		smartphones = SmartPhoneAssn.objects.filter(user__in=all_recipients, is_active=True).\
			exclude(push_token=None).exclude(push_token='')
		# Secondly, for each recipient, generate a new message user status object so that 
		# the message status (read, deleted, etc.) can be stored for that user.
		for recipient in non_sender_recipients:
			s = MessageBodyUserStatus(msg_body=body_obj, user=recipient)
			s.save()
#		notified_recipients = non_sender_recipients
#		
#		#sender is messeging himself, send a notification
#		if(not notified_recipients):
#			notified_recipients = [self.sender]
#		notified_recipients = MHLUser.objects.filter(id__in=[u.id for u in notified_recipients])
		notified_recipients = MHLUser.objects.filter(id__in=[u.id for u in all_recipients])
		for recipient in notified_recipients:
			if (self.message_type in ('ANS', 'VM', 'NM', 'SMS')):
				qs = smartphones.filter(user=recipient)
				if(qs):
					from utils import get_message_count
					if(self.sender):
						text = _("You have a new DoctorCom message from %(sender)s: %(subject)s") \
								% {'sender': self.sender, 'subject': self.subject}
					else:
						text = _("You have a new DoctorCom message: %s") % (self.subject,)
					try:
						notify(qs,
							text=text,
							additional_data={"message_id": self.uuid},
							count=get_message_count(recipient, None,
									read_flag=False, direction='received'))
					except Exception as e:
						err_email_body = '\n'.join([
								('notify mobile has errors!'),
								''.join(['Server: ', settings.SERVER_ADDRESS]),
								''.join(['Session: ', str(request.session.session_key)]),
								''.join(['Message: ', ('Notify mobile has errors.')]),
								''.join(['Exception: ', str(e)]),
								''.join(['Exception data: ', str(e.args)]),
							])
						mail_admins('notify mobile has errors', err_email_body)
				if(settings.CALL_ENABLE):
					config_type = ContentType.objects.get(app_label="MHLUsers", model="provider")
					config = VMBox_Config.objects.filter(
								owner_type__pk=config_type.id, owner_id=recipient.id)
					#always send a notification to providers (the query above only matches providers)
					#send a notification if we didn't send a push notification (not qs) or if the
					#user has explicitly asked for sms notifications
					if(config and (not qs or config[0].notification_sms)):
						sendSMS_Twilio_newMessage(request, body_obj.clear_data, 
										attachment_objs, self, recipient)

					if not config:
						config_type = ContentType.objects.get(app_label="MHLUsers", model="officestaff")
						staff = OfficeStaff.objects.filter(user=recipient)
						if staff and staff[0].id:
							config = VMBox_Config.objects.filter(
								owner_type__pk=config_type.id, owner_id=staff[0].id)
					if (config and config[0].notification_email):
						try:
							subject = "New DoctorCom System Message"
							body = "You've received a DoctorCom system message."
							if (self.sender):
								#sender_name = ' '.join(['New DoctorCom Message from', 
								#	self.sender.first_name, self.sender.last_name,])
								body = ' '.join(['You received a DoctorCom message from', 
									self.sender.first_name, self.sender.last_name])
							send_mail(
									subject,
									body,
									settings.SERVER_EMAIL,
									[user.email],
									fail_silently=False
								)
						except SMTPException as e:
							import inspect
							mail_admins('Mail Send Error', '%s\n%s' % (e, inspect.trace(),))

			if (self.message_type == 'ANS' and self.urgent and settings.CALL_ENABLE):

				config_type = ContentType.objects.get(app_label="MHLUsers", model="Provider")
				config = VMBox_Config.objects.filter(owner_id=recipient.id, owner_type=config_type)

				if(config and config[0].notification_page):
					paged = Provider.objects.get(user=recipient)
					if (paged.pager):
						send_page(self.sender, paged, self.callback_number)

		# Thirdly, generate keys for all attachments.
		for attach in attachment_objs:
			gen_keys_for_users(attach, non_sender_recipients, attach._key, request, ivr)

		for refer in refer_objs:
			gen_keys_for_users(refer, non_sender_recipients, refer._key, request, ivr)

		# Book keeping
		self.draft = False
		self.send_timestamp = time.time()
		# DEBUG: Temporarily disabled the following lines.
		#if ('Provider' in request.session['MHL_Users']):
		#	self.sender_site = request.session['MHL_Users']['Provider'].current_site

		# Save book keeping changes. Note that we don't use self.save since that
		# will choke on self.draft == False.
		super(Message, self).save()

		# Site Analytics
		from ..models import SiteAnalytics
		try:
			siteStat = SiteAnalytics.objects.get(dateoflog=datetime.date.today(), 
						site=self.sender_site)
		except SiteAnalytics.DoesNotExist:
			siteStat = SiteAnalytics(dateoflog=datetime.date.today(), 
				site=self.sender_site, countPage=0, countMessage=0, countClick2Call=0)
			siteStat.save()
		siteStat.countMessage = models.F('countMessage') + 1
		siteStat.save()
Example #42
0
def ProviderIVR_Init(request):
    request.session['answering_service'] = 'no'

    # First, make sure that the call stack is initialized:
    if (not 'ivr_call_stack' in request.session):
        request.session['ivr_call_stack'] = []

    #  Next, check for and store caller and called.
    if (not 'caller' in request.session or not 'called' in request.session):
        # Note: Twilio's international caller ID is just the full international
        # number all run together. For example, an international call from England
        # would be passed to us as 44XXXXXXXXXX, where 44 is the international
        # country code.
        # TODO: This sanitation could be much more sophisticated, albeit at the
        # risk of making future maintenance more difficult. I think that at the
        # moment, we're going to have to just accept that the caller ID we get from
        # Twilio is a trusted value.
        caller = request.POST['Caller']
        called = request.POST['Called']
        p = re.compile('\d+$')
        if (not p.match(caller)):
            if (caller != '' and caller != None):
                subject = 'ProviderIVR_Main Incoming CallerID Sanitation Fail'
                message = 'ProviderIVR_Main incoming CallerID failed on input %s.' % (
                    caller, )
                mail_admins(subject=subject,
                            message=message,
                            fail_silently=False)
            caller = ''
        if (not p.match(called)):
            # The number being called doesn't seem to be valid. Since we can't find
            # out which provider is being called, just raise an Exception and let
            # Django and Twilio deal with it.
            raise Exception('Invalid called value: %s' % (called, ))

        request.session['Caller'] = caller
        request.session['Called'] = called

    # Now, get the Provider being called
    provider = Provider.objects.filter(mdcom_phone=called)
    if provider.count() != 1:
        # If we don't allow multiple providers having same mdcom_phone it should
        # be unique in model, this code just logs more information than previously.
        if provider.count() > 1:
            msg = 'Multiple providers have mdcom_phone: %s, providers: %s' % \
              (called, ', '.join("%s" % p for p in provider))
            logger.error(msg)
            raise Exception(msg)
        else:
            msg = 'No providers have mdcom_phone %s' % (called, )
            logger.error(msg)
            raise Exception(msg)

    provider = provider[0]
    request.session['provider_id'] = provider.id

    # TODO: Flesh out the logging here so that we pull appropriate objects.
    log_qs = callLog.objects.filter(callSID=request.POST['CallSid'])
    if (log_qs.count()):
        # FIXME: This condition shouldn't be hit! This init function is getting
        # run multiple times per call, and I don't know why. --BK
        log = log_qs.get()
    else:
        log = callLog(
            caller_number=request.session['Caller'],
            called_number=request.session['Called'],
            mdcom_called=provider,
            callSID=request.POST['CallSid'],
            call_source='OC',
        )

    # Is the caller an existing user with a DoctorCom number? If so, mask the
    # caller's number with the DoctorCom number.
    mhlusers_mobile_phone = MHLUser.objects.filter(
        mobile_phone=request.session['Caller'])
    mhlusers_phone = MHLUser.objects.filter(phone=request.session['Caller'])
    total_users = mhlusers_mobile_phone.count() + mhlusers_phone.count()
    if (total_users == 1):
        # First, get the MHLUser involved.
        if (mhlusers_mobile_phone.count()):
            user = mhlusers_mobile_phone.get()
        else:
            user = mhlusers_phone.get()

        caller_provider = Provider.objects.filter(user=user)
        if caller_provider.exists():
            log.mdcom_caller = caller_provider[0]
            if log.mdcom_caller.mdcom_phone:
                # Mask the caller's caller ID since they have a doctorcom number
                request.session['Caller'] = log.mdcom_caller.mdcom_phone
        else:
            log.mdcom_caller = user

    log.save()

    return provider, log
Example #43
0
def ProviderIVR_Init(request):
	request.session['answering_service'] = 'no'

	# First, make sure that the call stack is initialized:
	if (not 'ivr_call_stack' in request.session):
		request.session['ivr_call_stack'] = []

	#  Next, check for and store caller and called.
	if (not 'caller' in request.session or not 'called' in request.session):
		# Note: Twilio's international caller ID is just the full international
		# number all run together. For example, an international call from England
		# would be passed to us as 44XXXXXXXXXX, where 44 is the international
		# country code.
		# TODO: This sanitation could be much more sophisticated, albeit at the
		# risk of making future maintenance more difficult. I think that at the
		# moment, we're going to have to just accept that the caller ID we get from
		# Twilio is a trusted value.
		caller = request.POST['Caller']
		called = request.POST['Called']
		p = re.compile('\d+$')
		if (not p.match(caller)):
			if (caller != '' and caller != None):
				subject = 'ProviderIVR_Main Incoming CallerID Sanitation Fail'
				message = 'ProviderIVR_Main incoming CallerID failed on input %s.' % (caller,)
				mail_admins(subject=subject, message=message, fail_silently=False)
			caller = ''
		if (not p.match(called)):
			# The number being called doesn't seem to be valid. Since we can't find
			# out which provider is being called, just raise an Exception and let
			# Django and Twilio deal with it.
			raise Exception('Invalid called value: %s' % (called,))

		request.session['Caller'] = caller
		request.session['Called'] = called

	# Now, get the Provider being called
	provider = Provider.objects.filter(mdcom_phone=called)
	if provider.count() != 1:
		# If we don't allow multiple providers having same mdcom_phone it should
		# be unique in model, this code just logs more information than previously.
		if provider.count() > 1:
			msg = 'Multiple providers have mdcom_phone: %s, providers: %s' % \
					(called, ', '.join("%s" % p for p in provider))
			logger.error(msg)
			raise Exception(msg)
		else:
			msg = 'No providers have mdcom_phone %s' % (called,)
			logger.error(msg)
			raise Exception(msg)

	provider = provider[0]
	request.session['provider_id'] = provider.id

	# TODO: Flesh out the logging here so that we pull appropriate objects.
	log_qs = callLog.objects.filter(callSID=request.POST['CallSid'])
	if (log_qs.count()):
		# FIXME: This condition shouldn't be hit! This init function is getting
		# run multiple times per call, and I don't know why. --BK
		log = log_qs.get()
	else:
		log = callLog(
				caller_number=request.session['Caller'],
				called_number=request.session['Called'],
				mdcom_called=provider,
				callSID=request.POST['CallSid'],
				call_source='OC',
			)

	# Is the caller an existing user with a DoctorCom number? If so, mask the
	# caller's number with the DoctorCom number.
	mhlusers_mobile_phone = MHLUser.objects.filter(mobile_phone=request.session['Caller'])
	mhlusers_phone = MHLUser.objects.filter(phone=request.session['Caller'])
	total_users = mhlusers_mobile_phone.count() + mhlusers_phone.count()
	if (total_users == 1):
		# First, get the MHLUser involved.
		if (mhlusers_mobile_phone.count()):
			user = mhlusers_mobile_phone.get()
		else:
			user = mhlusers_phone.get()

		caller_provider = Provider.objects.filter(user=user)
		if caller_provider.exists():
			log.mdcom_caller = caller_provider[0]
			if log.mdcom_caller.mdcom_phone:
				# Mask the caller's caller ID since they have a doctorcom number
				request.session['Caller'] = log.mdcom_caller.mdcom_phone
		else:
			log.mdcom_caller = user

	log.save()

	return provider, log
Example #44
0
def get_message(request, message_id):
	if (request.method != 'POST'):
		return err_GE002()
	form = MsgGetForm(request.POST)
	if (not form.is_valid()):
		return err_GE031(form)

	msgs = list(MessageBodyUserStatus.objects.filter(user=request.user,
					delete_flag=False, msg_body__message__uuid=message_id)
			.extra(select={'sender_title':"SELECT MHLUsers_mhluser.title \
				FROM MHLUsers_mhluser INNER JOIN Messaging_message ON \
				MHLUsers_mhluser.user_ptr_id = Messaging_message.sender_id \
				INNER JOIN  Messaging_messagebody ON \
				Messaging_message.id = Messaging_messagebody.message_id \
				WHERE Messaging_messagebody.id = Messaging_messagebodyuserstatus.msg_body_id"}).
			order_by('-msg_body__message__send_timestamp').select_related(
				'msg_body', 'msg_body__message', 'msg_body__message__sender'))\

	# Integrity check.
	if (len(msgs) > 1):
		# shouldn't be possible!
		mail_admins('Duplicate message ID', ' '.join(['server: ',
				settings.SERVER_ADDRESS, '\n',
				'The message id with uuid', message_id, 'has returned with',
				'more than one Message!\nAt: ',
				str(inspect.getfile(inspect.currentframe())), ':',
						str(inspect.currentframe().f_back.f_lineno)
			]))
	if (len(msgs) == 0):
		raise Http404

	status_obj = msgs[0]

	# Get/set up data for KMS.
	request.session['key'] = request.device_assn.secret
	ss = form.cleaned_data['secret']

	current_user = request.role_user
	current_user_mobile = current_user.user.mobile_phone
	try:
		read_message(request, status_obj.msg_body, ss=ss)
	except KeyInvalidException:
		return err_GE021()
	msg = status_obj.msg_body.message
	recipients = MessageRecipient.objects.filter(message__uuid=message_id).\
		select_related('user').extra(select={'title':'SELECT title FROM MHLUsers_mhluser \
			WHERE MHLUsers_mhluser.user_ptr_id = Messaging_message_recipients.user_id'}).\
		only('user__first_name', 'user__last_name')

	attachments = MessageAttachment.objects.filter(message=msg)

	ccs = MessageCC.objects.filter(message__uuid=message_id).select_related('user').\
		extra(select={'title':'SELECT title FROM MHLUsers_mhluser \
			WHERE MHLUsers_mhluser.user_ptr_id = Messaging_message_ccs.user_id'}).\
		only('user__first_name', 'user__last_name', 'message')

	use_time_setting = False
	if 'use_time_setting' in request.POST and request.POST['use_time_setting'] == 'true':
		use_time_setting = True
	user = request.user
	local_tz = getCurrentTimeZoneForUser(user)
	action_history = get_message_action_history(status_obj.msg_body.message.id)
	response = {
		'data': {
				'body': status_obj.msg_body.clear_data,
				'timestamp': formatTimeSetting(user, msg.send_timestamp, 
										local_tz, use_time_setting),
				'send_timestamp': msg.send_timestamp,
				'sender': {
							'name': get_fullname_bystr(msg.sender.last_name,msg.sender.first_name,status_obj.sender_title)\
										if msg.sender else "System Message",
							'id': msg.sender.id if msg.sender else 0,
						},
				'recipients': [{
							'name': get_fullname_bystr(u.user.last_name,u.user.first_name,u.title),
							'id': u.user.id,
							} for u in recipients],
				'ccs': [{
							'name': get_fullname_bystr(u.user.last_name,u.user.first_name,u.title),
							'id': u.user.id,
							} for u in ccs],
				'attachments': [
						{
							'id': att.uuid,
							'filename': get_attachment_filename(request, att, ss),
							'filesize': att.size,
							'suffix':att.suffix,
						} for att in attachments],
				'message_type': msg.message_type if msg.message_type else 'NM',
				'callback_number': msg.callback_number,
				'callback_available': settings.CALL_ENABLE and bool(msg.callback_number)
					and bool(current_user_mobile),
				'urgent': bool(msg.urgent),
				'resolution_flag': bool(msg._resolved_by_id),
				'refer': _get_refer_from_mbus(status_obj, logo_size="Large"),
				'thread_uuid': msg.thread_uuid,
				'action_history': action_history,
				'action_history_count': len(action_history)
			},
		'warnings': {},
	}

	return HttpResponse(content=json.dumps(response), mimetype='application/json')
Example #45
0
    def _generate_key(self, key):
        url = ''.join([
            'https://files.mdcom.com/KMS/Key/New/', settings.SERVER_PLATFORM,
            '/'
        ])
        try:
            # make sure this is defined for the default/catch-all Exception handler
            keypair_response_raw = ''
            keypair_response = urllib2.urlopen(url, timeout=5)
            keypair_response_raw = keypair_response.read()
            if (keypair_response.getcode() == 200):
                keypair = base64.b64decode(keypair_response_raw)
                keypair = cPickle.loads(keypair)
            else:
                keypair = self._generate_keypair_manually()
        except (urllib2.HTTPError, urllib2.URLError, ssl.SSLError) as e:
            # The fetch failed
            #print "The fetch failed!"
            mail_admins(
                _('KMS KeyGen Error: Failed Fetch'), """
KMS.models.%s._generate_key exception: %s
Host: %s
URL: %s
""" % (self.__class__.__name__, repr(e), settings.SERVER_ADDRESS, url))
            keypair = self._generate_keypair_manually()
        except (ValueError, ) as e:
            # The base64 decode failed
            #print "The base64 decode failed!"
            mail_admins(
                _('KMS KeyGen Error: base64 Decode Failed'), """
KMS.models.%s._generate_key exception: %s
Host: %s
URL: %s
Value: %s
""" % (self.__class__.__name__, repr(e), settings.SERVER_ADDRESS, url,
            keypair_response_raw))
            keypair = self._generate_keypair_manually()
        except (cPickle.PickleError, AttributeError, EOFError, ImportError,
                IndexError) as e:
            # The unpickle failed
            #print "The unpickle failed!"
            mail_admins(
                _('KMS KeyGen Error: Unpickle Failed'), """
KMS.models.%s._generate_key exception: %s
Host: %s
Value: %s
URL: %s
""" % (self.__class__.__name__, repr(e), settings.SERVER_ADDRESS, url,
            keypair_response_raw))
            keypair = self._generate_keypair_manually()
        except Exception as e:
            # Generic error handler! An unknown exception was raised.
            mail_admins(
                _('KMS KeyGen Error: UNKNOWN EXCEPTION'), """
KMS.models.%s._generate_key exception: %s
Host: %s
Value: %s
URL: %s
""" % (self.__class__.__name__, repr(e), settings.SERVER_ADDRESS, url,
            keypair_response_raw))
            keypair = self._generate_keypair_manually()

        self._public_key = keypair.publickey()

        # Prepare the keypair for storage, then assign it.
        keypair = cPickle.dumps(keypair)
        padding = [' ' for i in range(16 - (len(keypair) % 16))]
        padding.insert(0, keypair)
        keypair = ''.join(padding)
        aes = AES.new(key)
        keypair = aes.encrypt(keypair)
        self.keypair = base64.b64encode(keypair)
Example #46
0
def _getRecentOncallProviderId(request):
	"""
	clone from V1 replacing Caller with From: gets current oncall provider returning provider ID
	"""
	if 'ivr2_provider_onCall' in request.session:
		return request.session['ivr2_provider_onCall']

	call_time = request.session['calltime_local']
	call_time_string = request.session['calltime_local_string']
	callGroupId = request.session['callgroup_id']
	#which provider is on call right now?
	oncall_qs = getPrimaryOnCall(callGroupId, call_time_string)
	oncall_count = len(oncall_qs)
	callback = ''
	provider = None
	if (oncall_count == 0):
		provider_qs = getLastPrimaryOnCall(callGroupId, call_time_string)
		if (not provider_qs):
			logger.debug('%s: _getRecentOncallProviderId none on call. No previous.' % (
				request.session.session_key))
			message_managers(request, request.session['practice_id'],
						'DoctorCom Error: No On-Call User Defined',
						render_to_string("DoctorCom/IVR/no_oncall_error.txt", {
							'timestamp': call_time,
							'callsid': request.POST['CallSid'],
							'callback': callback,
							'callerid': request.POST['From'],
						})
					)
			mail_admins('DoctorCom Error: No On-Call User Defined',
					render_to_string('DoctorCom/IVR/no_oncall_error_admins.txt', {
					'practice': request.session['practice_id'],
					'timestamp': call_time,
					'callsid': request.POST['CallSid'],
					'callback': callback,
					'callerid': request.POST['From'],
				}))

			return None
		else:
			provider = provider_qs[0]
			logger.debug('%s: _getRecentOncallProviderId none on call. Previous %s' % (
				request.session.session_key, provider))
			message_managers(request, request.session['practice_id'],
						_('DoctorCom Error: No On-Call User Defined'),
						_("""Dear Manager,

An urgent call was received on {{timestamp|date:'l, F d, Y'}} at 
{{timestamp|date:'h:i A'}}, at which time nobody was defined as being on-call.

Because this is an urgent call, we automatically routed the message to the last 
on-call user: {{chosen_provider.first_name}} {{chosen_provider.last_name}}.

If you have any questions, please feel free to email us at [email protected] 
with the following data
    {{callsid}}
    {{timestamp}}
and we will be happy to assist you in any way we can.

Best,
DoctorCom Staff
"""),
						timestamp=call_time,
						callsid=request.POST['CallSid'],
						chosen_provider=User.objects.filter(
							pk=provider.user_id).values('first_name', 'last_name')[0]
					)
	elif (oncall_count > 1):
		# Multiple providers are defined as being on-call for this call.
		# We've already picked one, and let the practice manager know how
		# we're handling it.
		provider = oncall_qs[0]
		logger.debug('%s: _getRecentOncallProviderId multiple on call. Assigning %s' % (
			request.session.session_key, provider))
		message_managers(request, request.session['practice_id'],
					_('DoctorCom Warning: Multiple On-Call Users Defined'),
					_("""Dear Manager,

An urgent call was received on {{timestamp|date:'l, F d, Y'}} at {{timestamp|date:'h:i A'}}, 
at which time the following users were listed as being on-call:
{% for provider in providers %}
     {{provider.first_name}} {{provider.last_name}}{% endfor %}

Because we could not determine which user should have received the call, 
{{chosen_provider.first_name}} {{chosen_provider.last_name}} was chosen.

If you have any questions, please feel free to email us at [email protected] with 
the following data
    {{callsid}}
    {{timestamp}}
and we will be happy to assist you in any way we can.

Best,
DoctorCom Staff
"""),
					timestamp=call_time,
					callsid=request.POST['CallSid'],
					providers=User.objects.filter(pk__in=[p.pk for p in oncall_qs]),
					chosen_provider=provider
				)
	else:
		# This handles the nominal one provider on-call situation, and also
		# randomly picks one provider if multiple are defined. The warning for
		# the latter situation is sent later.
		provider = oncall_qs[0]
		logger.debug('%s: _getRecentOncallProviderId on call prov %s' % (
			request.session.session_key, provider))

	request.session['ivr2_provider_onCall'] = provider.id
	return provider.id
Example #47
0
def saveSingleAttachment(request, msg, file_data):
    """
	Save a single attachment

	:param request: request
	:param msg: message object which contain this attachment
	:param file_data: attachment information
		Example::
		file_data : {
		'name': file's name,
		'file_chunks': file's chunk data,
		'size': file's size,
		'suffix': file's extension name,
		'charset': file's charset
		}
	:returns: MessageAttachment
	"""
    name = file_data['name']
    file_chunks = file_data['file_chunks']
    size = file_data['size']
    suffix = None
    if 'suffix' in file_data:
        suffix = file_data['suffix']
    charset = file_data['charset']

    attachment = encrypt_object(
        MessageAttachment, {
            'message': msg,
            'size': size,
            'encrypted': True,
        },
        opub=OwnerPublicKey.objects.get_pubkey(owner=request.user))

    attachment.encrypt_url(request, ''.join(['file://', attachment.uuid]))
    if not suffix:
        suffix = os.path.splitext(name)[1][1:]

    if (suffix):
        attachment.suffix = suffix.lower()
        (attachment.content_type,
         attachment.encoding) = mimetypes.guess_type(name)
        attachment.charset = charset
    else:
        try:
            m = magic.Magic(mime=True)
            attachment.content_type = m.from_buffer(file_chunks)
            if (attachment.content_type == 'application/dicom'):
                attachment.suffix = "dcm"
                name += ".dcm"
            m = magic.Magic(mime_encoding=True)
            attachment.encoding = m.from_buffer(file_chunks)
        except magic.MagicException as e:
            err_email_body = '\n'.join([
                ('magic.MagicException!'),
                ''.join(['Server: ', settings.SERVER_ADDRESS]),
                ''.join(['Session: ',
                         str(request.session.session_key)]),
                ''.join(['Exception: ', str(e)]),
                ''.join(['Exception data: ', str(e.args)]),
            ])
            mail_admins('magic.MagicException', err_email_body)

    attachment.encrypt_filename(request, name)
    attachment.encrypt_file(request, file_chunks)

    attachment.save()
    if "dcm" == attachment.suffix:
        if not isinstance(file_chunks, str):
            file_chunks = ''.join(file_chunks)
        thread.start_new_thread(sendToDicomServer, ({
            "name": name,
            "token": attachment.uuid,
            "content": file_chunks
        }, ))
    return attachment
Example #48
0
def saveSingleAttachment(request, msg, file_data):
	"""
	Save a single attachment

	:param request: request
	:param msg: message object which contain this attachment
	:param file_data: attachment information
		Example::
		file_data : {
		'name': file's name,
		'file_chunks': file's chunk data,
		'size': file's size,
		'suffix': file's extension name,
		'charset': file's charset
		}
	:returns: MessageAttachment
	"""
	name = file_data['name']
	file_chunks = file_data['file_chunks']
	size = file_data['size']
	suffix = None
	if 'suffix' in file_data:
		suffix = file_data['suffix']
	charset = file_data['charset']

	attachment = encrypt_object(
		MessageAttachment,
		{
			'message': msg,
			'size': size,
			'encrypted': True,
		},
		opub=OwnerPublicKey.objects.get_pubkey(owner=request.user))

	attachment.encrypt_url(request, ''.join(['file://', attachment.uuid]))
	if not suffix:
		suffix = os.path.splitext(name)[1][1:]

	if (suffix):
		attachment.suffix = suffix.lower()
		(attachment.content_type, attachment.encoding) = mimetypes.guess_type(name)
		attachment.charset = charset
	else:
		try:
			m = magic.Magic(mime=True)
			attachment.content_type = m.from_buffer(file_chunks)
			if(attachment.content_type == 'application/dicom'):
				attachment.suffix = "dcm"
				name += ".dcm"
			m = magic.Magic(mime_encoding=True)
			attachment.encoding = m.from_buffer(file_chunks)
		except magic.MagicException as e:
			err_email_body = '\n'.join([
					('magic.MagicException!'),
					''.join(['Server: ', settings.SERVER_ADDRESS]),
					''.join(['Session: ', str(request.session.session_key)]),
					''.join(['Exception: ', str(e)]),
					''.join(['Exception data: ', str(e.args)]),
				])
			mail_admins('magic.MagicException', err_email_body)

	attachment.encrypt_filename(request, name)
	attachment.encrypt_file(request, file_chunks)

	attachment.save()
	if "dcm" == attachment.suffix:
		if not isinstance(file_chunks, str):
			file_chunks = ''.join(file_chunks)
		thread.start_new_thread(sendToDicomServer, ({
			"name": name, "token": attachment.uuid, "content": file_chunks},))
	return attachment
Example #49
0
def ProviderIVR_ForwardCall(request):
	"""Forward the call to the dialed user, as per the user's preferences.

	Uses the following session variables:
		ProviderIVR_ForwardCall_state: The most recent "state" of execution. May
			have the following values:
				- None/Undefined/Empty String: First execution of this function.
				- Getting_Name: Getting the caller's name, if one hasn't been
						defined.
				- Dialing: Phone(s) have been dialed, and waiting for a response Caller
	"""
	r = twilio.Response()
	request.session.modified = True
	provider = Provider.objects.get(id=request.session['provider_id'])

	if('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'):
		if('Duration' in request.POST):
			callSID = request.POST['CallSid']
			log = callLog.objects.get(callSID=callSID)
			log.call_duration = request.POST['Duration']
			log.save()

	if(not 'ProviderIVR_ForwardCall_forward' in request.session):
		request.session['ProviderIVR_ForwardCall_forward'] = provider.forward_voicemail
	forward = provider.forward_voicemail
	if (forward == 'VM'):
		return ProviderIVR_LeaveMsg(request)

	if (not 'ProviderIVR_ForwardCall_state' in request.session or
			not request.session['ProviderIVR_ForwardCall_state']):
		# New call. First, check to see if we should go straight to voicemail

		# Okay, the call isn't going to voicemail directly. Now, set state.
		request.session['ProviderIVR_ForwardCall_state'] = 'Getting_Name'

		# Now, get the caller's name

		# Is the user a DoctorCom user with a recorded name?
		callSID = request.POST['CallSid']
		log = callLog.objects.get(callSID=callSID)

		if (log.mdcom_caller and isinstance(log.mdcom_caller, Provider)):
			if (log.mdcom_caller.vm_config.count()):
				prov_vmconfig = log.mdcom_caller.vm_config.get()
				if (prov_vmconfig.config_complete):
					logger.debug('%s/%s: Found the caller\'s name!' % (
							request.session.session_key,
							request.session['ProviderIVR_ForwardCall_state'],
						))
					log.caller_spoken_name = prov_vmconfig.name
					log.save()
					return ProviderIVR_ForwardCall(request)  # restart execution of this function
				else:
					logger.debug('%s/%s: Caller\'s vm_config incomplete!' % (
							request.session.session_key,
							request.session['ProviderIVR_ForwardCall_state'],
						))
			else:
				logger.debug('%s/%s: An unsuitable number of vm_config objects found: %i' % 
					(request.session.session_key,
						request.session['ProviderIVR_ForwardCall_state'],
						log.mdcom_caller.vm_config.count(),
					))
		else:
			logger.debug('%s/%s: mdcom_caller %s either isn\'t defined or doesn\'t '
						'seem to be a Provider' % (request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
					str(log.mdcom_caller),
				))

		# Okay, it's not a user with a name recording. Get one.
		request.session['ivr_call_stack'].append('ProviderIVR_ForwardCall')
		request.session['ivr_makeRecording_prompt'] = \
			tts('Please say your name after the tone.')
		request.session['ivr_makeRecording_maxLength'] = 4
		request.session['ivr_makeRecording_timeout'] = 2
		request.session['ivr_makeRecording_leadSilence'] = 1
		return getQuickRecording(request)

	if (request.session['ProviderIVR_ForwardCall_state'] == 'Getting_Name'):
		request.session['ProviderIVR_ForwardCall_state'] = 'Dialed'

		logger.debug('%s/%s: Set session to %s' % (
				request.session.session_key,
				request.session['ProviderIVR_ForwardCall_state'],
				request.session['ProviderIVR_ForwardCall_state'],
			))

		callSID = request.POST['CallSid']
		log = callLog.objects.get(callSID=callSID)
		if (not log.caller_spoken_name):
			log.caller_spoken_name = request.session.pop('ivr_makeRecording_recording')
			log.save()

		logger.debug('%s/%s: got provider \'%s\' \'%s\' with id %s' % (
				request.session.session_key,
				request.session['ProviderIVR_ForwardCall_state'],
				provider.first_name,
				provider.last_name,
				provider.pk,
			))
		logger.debug('%s/%s: Provider phone is \'%s\' and forward_other is \'%s\'' % (
				request.session.session_key,
				request.session['ProviderIVR_ForwardCall_state'],
				provider.user.phone,
				str(provider.forward_other),
			))

		# Okay, let's dial!
		user_number = None
		if (forward == 'MO'):
			logger.debug('%s/%s: provider.forward_mobile True' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
				))
			user_number = provider.user.mobile_phone
			logger.debug('%s/%s: Setting user_number to \'%s\'' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
					provider.user.mobile_phone,
				))
		elif (forward == 'OF'):
			logger.debug('%s/%s: provider.forward_office True' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
				))
			user_number = provider.office_phone
			logger.debug('%s/%s: Setting user_number to \'%s\'' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
					provider.office_phone,
				))
		elif (forward == 'OT'):
			logger.debug('%s/%s: provider.forward_other True' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
				))
			user_number = provider.user.phone
			logger.debug('%s/%s: Setting user_number to \'%s\'' % (
					request.session.session_key,
					request.session['ProviderIVR_ForwardCall_state'],
					provider.user.phone,
				))

		logger.debug('%s/%s: Tried to get called\'s number. Got \'%s\'' % (
				request.session.session_key,
				request.session['ProviderIVR_ForwardCall_state'],
				user_number,
			))
		logger.debug('%s/%s: Provider phone is \'%s\' and forward_other is \'%s\'' % (
				request.session.session_key,
				request.session['ProviderIVR_ForwardCall_state'],
				provider.user.phone,
				str(provider.forward_other),
			))

		if (not user_number):
			# no flags were set.
			if (provider.user.mobile_phone):
				user_number = provider.user.mobile_phone
			else:
				return ProviderIVR_LeaveMsg(request)

		dial = twilio.Dial(
				action=reverse('ProviderIVR_ForwardCall'),
				timeout=22,
				timeLimit=14400,  # 4 hours
				callerId=request.session['Caller']
			)
		dial.append(twilio.Number(user_number,
				url=reverse('ProviderIVR_ForwardCall_VetAnswer')
			))
		r.append(dial)
		r.append(twilio.Redirect(reverse('ProviderIVR_LeaveMsg')))
		return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)

	if (request.session['ProviderIVR_ForwardCall_state'] == 'Dialed'):
		callSID = request.POST['CallSid']
		log = callLog.objects.get(callSID=callSID)

		if (log.call_connected):
			r.append(twilio.Hangup())
			return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)

		return ProviderIVR_LeaveMsg(request)

	r = twilio.Response()
	if (request.POST['DialStatus'] != 'answered'):
		if (request.POST['DialStatus'] == 'failed'):
			# TODO: Figure out how to deal with connection problems. Most
			# likely, send an email to the user and administrators.
			subject = 'ProviderIVR_ForwardCall Call Forward DialStatus Fail'
			message = 'ProviderIVR_ForwardCall got DialStatus failed. Post data: %s' % \
				(str(request.POST),)
			mail_admins(subject=subject, message=message, fail_silently=False)
		# else request.POST['DialStatus'] == 'busy' or request.POST['DialStatus'] == 'no-answer'
		return ProviderIVR_LeaveMsg(request)
	# else: Do nothing so that the call continues un-interrupted
	return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)