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
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}
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})
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')
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
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.'))
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
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
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
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
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.'))
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)
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
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)
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)
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}
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)
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), })
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), } )
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))
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)
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
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)
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
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()
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)
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)
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))
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)
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.'))
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)
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)
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)
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
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))
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)
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)
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()
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
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
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')
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)
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
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
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
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)