def test_is_contact_active_for_user(self): self.assertTrue(is_contact_active(self.domain, "CommCareUser", self.user.get_id)) self.user.is_active = False self.user.save() self.assertFalse(is_contact_active(self.domain, "CommCareUser", self.user.get_id)) self.user.is_active = True self.user.save() self.assertTrue(is_contact_active(self.domain, "CommCareUser", self.user.get_id))
def test_is_contact_active_for_user(self): self.assertTrue(is_contact_active(self.domain, 'CommCareUser', self.user.get_id)) self.user.is_active = False self.user.save() self.assertFalse(is_contact_active(self.domain, 'CommCareUser', self.user.get_id)) self.user.is_active = True self.user.save() self.assertTrue(is_contact_active(self.domain, 'CommCareUser', self.user.get_id))
def process_incoming(msg): v = PhoneNumber.by_phone(msg.phone_number, include_pending=True) if v: msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.location_id = get_location_id_by_verified_number(v) msg.save() elif msg.domain_scope: msg.domain = msg.domain_scope msg.save() can_receive_sms = PhoneBlacklist.can_receive_sms(msg.phone_number) opt_in_keywords, opt_out_keywords = get_opt_keywords(msg) domain = v.domain if v else None if is_opt_message(msg.text, opt_out_keywords) and can_receive_sms: if PhoneBlacklist.opt_out_sms(msg.phone_number, domain=domain): metadata = MessageMetadata(ignore_opt_out=True) text = get_message(MSG_OPTED_OUT, v, context=(opt_in_keywords[0],)) if v: send_sms_to_verified_number(v, text, metadata=metadata) else: send_sms(msg.domain, None, msg.phone_number, text, metadata=metadata) elif is_opt_message(msg.text, opt_in_keywords) and not can_receive_sms: if PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain): text = get_message(MSG_OPTED_IN, v, context=(opt_out_keywords[0],)) if v: send_sms_to_verified_number(v, text) else: send_sms(msg.domain, None, msg.phone_number, text) else: handled = False is_verified = v is not None and v.verified if msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS): handled = load_and_call(settings.CUSTOM_SMS_HANDLERS, v, msg.text, msg) if not handled and is_verified and is_contact_active(v.domain, v.owner_doc_type, v.owner_id): handled = load_and_call(settings.SMS_HANDLERS, v, msg.text, msg) if not handled and not is_verified: handled = process_pre_registration(msg) if not handled: handled = process_sms_registration(msg) if not handled: import verify verify.process_verification(v, msg) # If the sms queue is enabled, then the billable gets created in remove_from_queue() if ( not settings.SMS_QUEUE_ENABLED and msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS) ): create_billable_for_sms(msg)
def process_incoming(msg): v = PhoneNumber.by_phone(msg.phone_number, include_pending=True) if v is not None and v.verified: msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.location_id = get_location_id_by_verified_number(v) msg.save() if msg.domain_scope: # only process messages for phones known to be associated with this domain if v is None or v.domain != msg.domain_scope: raise DomainScopeValidationError( 'Attempted to simulate incoming sms from phone number not ' \ 'verified with this domain' ) can_receive_sms = PhoneBlacklist.can_receive_sms(msg.phone_number) opt_in_keywords, opt_out_keywords = get_opt_keywords(msg) domain = v.domain if v else None if is_opt_message(msg.text, opt_out_keywords) and can_receive_sms: if PhoneBlacklist.opt_out_sms(msg.phone_number, domain=domain): metadata = MessageMetadata(ignore_opt_out=True) text = get_message(MSG_OPTED_OUT, v, context=(opt_in_keywords[0],)) if v: send_sms_to_verified_number(v, text, metadata=metadata) else: send_sms(msg.domain, None, msg.phone_number, text, metadata=metadata) elif is_opt_message(msg.text, opt_in_keywords) and not can_receive_sms: if PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain): text = get_message(MSG_OPTED_IN, v, context=(opt_out_keywords[0],)) if v: send_sms_to_verified_number(v, text) else: send_sms(msg.domain, None, msg.phone_number, text) elif v is not None and v.verified: if ( domain_has_privilege(msg.domain, privileges.INBOUND_SMS) and is_contact_active(v.domain, v.owner_doc_type, v.owner_id) ): for h in settings.SMS_HANDLERS: try: handler = to_function(h) except: notify_exception(None, message=('error loading sms handler: %s' % h)) continue try: was_handled = handler(v, msg.text, msg=msg) except Exception, e: log_sms_exception(msg) was_handled = False if was_handled: break
def process_incoming(msg): sms_load_counter("inbound", msg.domain)() v, has_domain_two_way_scope = get_inbound_phone_entry(msg) if v: if any_migrations_in_progress(v.domain): raise DelayProcessing() msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.location_id = get_location_id_by_verified_number(v) msg.save() elif msg.domain_scope: if any_migrations_in_progress(msg.domain_scope): raise DelayProcessing() msg.domain = msg.domain_scope msg.save() opt_in_keywords, opt_out_keywords, pass_through_opt_in_keywords = get_opt_keywords( msg) domain = v.domain if v else None if is_opt_message(msg.text, opt_out_keywords): if PhoneBlacklist.opt_out_sms(msg.phone_number, domain=domain): metadata = MessageMetadata(ignore_opt_out=True) text = get_message(MSG_OPTED_OUT, v, context=(opt_in_keywords[0], )) if v: send_sms_to_verified_number(v, text, metadata=metadata) elif msg.backend_id: send_sms_with_backend(msg.domain, msg.phone_number, text, msg.backend_id, metadata=metadata) else: send_sms(msg.domain, None, msg.phone_number, text, metadata=metadata) elif is_opt_message(msg.text, opt_in_keywords): if PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain): text = get_message(MSG_OPTED_IN, v, context=(opt_out_keywords[0], )) if v: send_sms_to_verified_number(v, text) elif msg.backend_id: send_sms_with_backend(msg.domain, msg.phone_number, text, msg.backend_id) else: send_sms(msg.domain, None, msg.phone_number, text) else: if is_opt_message(msg.text, pass_through_opt_in_keywords): # Opt the phone number in, and then process the message normally PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain) handled = False is_two_way = v is not None and v.is_two_way if msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS): if v and v.pending_verification: from . import verify handled = verify.process_verification( v, msg, create_subevent_for_inbound=not has_domain_two_way_scope) if ((is_two_way or has_domain_two_way_scope) and is_contact_active( v.domain, v.owner_doc_type, v.owner_id)): handled = load_and_call(settings.SMS_HANDLERS, v, msg.text, msg) if not handled and not is_two_way: handled = process_pre_registration(msg) if not handled: handled = process_sms_registration(msg) # If the sms queue is enabled, then the billable gets created in remove_from_queue() if (not settings.SMS_QUEUE_ENABLED and msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS)): create_billable_for_sms(msg)
def process_sms(queued_sms_pk): """ queued_sms_pk - pk of a QueuedSMS entry """ utcnow = get_utcnow() # Prevent more than one task from processing this SMS, just in case # the message got enqueued twice. message_lock = get_lock("sms-queue-processing-%s" % queued_sms_pk) if message_lock.acquire(blocking=False): try: msg = QueuedSMS.objects.get(pk=queued_sms_pk) except QueuedSMS.DoesNotExist: # The message was already processed and removed from the queue release_lock(message_lock, True) return if message_is_stale(msg, utcnow): msg.set_system_error(SMS.ERROR_MESSAGE_IS_STALE) remove_from_queue(msg) release_lock(message_lock, True) return outbound_counter = None if msg.direction == OUTGOING: domain_object = Domain.get_by_name( msg.domain) if msg.domain else None if domain_object and handle_domain_specific_delays( msg, domain_object, utcnow): release_lock(message_lock, True) return outbound_counter = OutboundDailyCounter(domain_object) if not outbound_counter.can_send_outbound_sms(msg): release_lock(message_lock, True) return requeue = False # Process inbound SMS from a single contact one at a time recipient_block = msg.direction == INCOMING # We check datetime_to_process against utcnow plus a small amount # of time because timestamps can differ between machines which # can cause us to miss sending the message the first time and # result in an unnecessary delay. if (isinstance(msg.processed, bool) and not msg.processed and not msg.error and msg.datetime_to_process < (utcnow + timedelta(seconds=10))): if recipient_block: recipient_lock = get_lock("sms-queue-recipient-phone-%s" % msg.phone_number) recipient_lock.acquire(blocking=True) if msg.direction == OUTGOING: if (msg.domain and msg.couch_recipient_doc_type and msg.couch_recipient and not is_contact_active( msg.domain, msg.couch_recipient_doc_type, msg.couch_recipient)): msg.set_system_error(SMS.ERROR_CONTACT_IS_INACTIVE) remove_from_queue(msg) else: requeue = handle_outgoing(msg) elif msg.direction == INCOMING: try: handle_incoming(msg) except DelayProcessing: process_sms.apply_async([queued_sms_pk], countdown=60) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) else: msg.set_system_error(SMS.ERROR_INVALID_DIRECTION) remove_from_queue(msg) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) if requeue: if outbound_counter: outbound_counter.decrement() send_to_sms_queue(msg)
def process_sms(queued_sms_pk): """ queued_sms_pk - pk of a QueuedSMS entry """ client = get_redis_client() utcnow = get_utcnow() # Prevent more than one task from processing this SMS, just in case # the message got enqueued twice. message_lock = get_lock(client, "sms-queue-processing-%s" % queued_sms_pk) if message_lock.acquire(blocking=False): try: msg = QueuedSMS.objects.get(pk=queued_sms_pk) except QueuedSMS.DoesNotExist: # The message was already processed and removed from the queue release_lock(message_lock, True) return if message_is_stale(msg, utcnow): msg.set_system_error(SMS.ERROR_MESSAGE_IS_STALE) remove_from_queue(msg) release_lock(message_lock, True) return if msg.direction == OUTGOING: if msg.domain: domain_object = Domain.get_by_name(msg.domain) else: domain_object = None if domain_object and handle_domain_specific_delays( msg, domain_object, utcnow): release_lock(message_lock, True) return requeue = False # Process inbound SMS from a single contact one at a time recipient_block = msg.direction == INCOMING if (isinstance(msg.processed, bool) and not msg.processed and not msg.error and msg.datetime_to_process < utcnow): if recipient_block: recipient_lock = get_lock( client, "sms-queue-recipient-phone-%s" % msg.phone_number) recipient_lock.acquire(blocking=True) if msg.direction == OUTGOING: if (msg.domain and msg.couch_recipient_doc_type and msg.couch_recipient and not is_contact_active( msg.domain, msg.couch_recipient_doc_type, msg.couch_recipient)): msg.set_system_error(SMS.ERROR_CONTACT_IS_INACTIVE) remove_from_queue(msg) else: requeue = handle_outgoing(msg) elif msg.direction == INCOMING: handle_incoming(msg) else: msg.set_system_error(SMS.ERROR_INVALID_DIRECTION) remove_from_queue(msg) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) if requeue: process_sms.delay(queued_sms_pk)
def test_is_contact_active_for_case(self): with create_test_case(self.domain, "contact", "test-case") as case: self.assertTrue(is_contact_active(self.domain, "CommCareCase", case.case_id)) update_case(self.domain, case.case_id, close=True) self.assertFalse(is_contact_active(self.domain, "CommCareCase", case.case_id))
def process_incoming(msg): v = PhoneNumber.by_phone(msg.phone_number, include_pending=True) if v: msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.location_id = get_location_id_by_verified_number(v) msg.save() elif msg.domain_scope: msg.domain = msg.domain_scope msg.save() can_receive_sms = PhoneBlacklist.can_receive_sms(msg.phone_number) opt_in_keywords, opt_out_keywords = get_opt_keywords(msg) domain = v.domain if v else None if is_opt_message(msg.text, opt_out_keywords) and can_receive_sms: if PhoneBlacklist.opt_out_sms(msg.phone_number, domain=domain): metadata = MessageMetadata(ignore_opt_out=True) text = get_message(MSG_OPTED_OUT, v, context=(opt_in_keywords[0], )) if v: send_sms_to_verified_number(v, text, metadata=metadata) else: send_sms(msg.domain, None, msg.phone_number, text, metadata=metadata) elif is_opt_message(msg.text, opt_in_keywords) and not can_receive_sms: if PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain): text = get_message(MSG_OPTED_IN, v, context=(opt_out_keywords[0], )) if v: send_sms_to_verified_number(v, text) else: send_sms(msg.domain, None, msg.phone_number, text) else: handled = False is_verified = v is not None and v.verified if msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS): handled = load_and_call(settings.CUSTOM_SMS_HANDLERS, v, msg.text, msg) if not handled and is_verified and is_contact_active( v.domain, v.owner_doc_type, v.owner_id): handled = load_and_call(settings.SMS_HANDLERS, v, msg.text, msg) if not handled and not is_verified: handled = process_pre_registration(msg) if not handled: handled = process_sms_registration(msg) if not handled: import verify verify.process_verification(v, msg) # If the sms queue is enabled, then the billable gets created in remove_from_queue() if (not settings.SMS_QUEUE_ENABLED and msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS)): create_billable_for_sms(msg)
def process_sms(queued_sms_pk): """ queued_sms_pk - pk of a QueuedSMS entry """ client = get_redis_client() utcnow = get_utcnow() # Prevent more than one task from processing this SMS, just in case # the message got enqueued twice. message_lock = get_lock(client, "sms-queue-processing-%s" % queued_sms_pk) if message_lock.acquire(blocking=False): try: msg = QueuedSMS.objects.get(pk=queued_sms_pk) except QueuedSMS.DoesNotExist: # The message was already processed and removed from the queue release_lock(message_lock, True) return if message_is_stale(msg, utcnow): msg.set_system_error(SMS.ERROR_MESSAGE_IS_STALE) remove_from_queue(msg) release_lock(message_lock, True) return if msg.direction == OUTGOING: if msg.domain: domain_object = Domain.get_by_name(msg.domain) else: domain_object = None if domain_object and handle_domain_specific_delays(msg, domain_object, utcnow): release_lock(message_lock, True) return requeue = False # Process inbound SMS from a single contact one at a time recipient_block = msg.direction == INCOMING if (isinstance(msg.processed, bool) and not msg.processed and not msg.error and msg.datetime_to_process < utcnow): if recipient_block: recipient_lock = get_lock(client, "sms-queue-recipient-phone-%s" % msg.phone_number) recipient_lock.acquire(blocking=True) if msg.direction == OUTGOING: if ( msg.domain and msg.couch_recipient_doc_type and msg.couch_recipient and not is_contact_active(msg.domain, msg.couch_recipient_doc_type, msg.couch_recipient) ): msg.set_system_error(SMS.ERROR_CONTACT_IS_INACTIVE) remove_from_queue(msg) else: requeue = handle_outgoing(msg) elif msg.direction == INCOMING: handle_incoming(msg) else: msg.set_system_error(SMS.ERROR_INVALID_DIRECTION) remove_from_queue(msg) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) if requeue: process_sms.delay(queued_sms_pk)
def process_sms(queued_sms_pk): """ queued_sms_pk - pk of a QueuedSMS entry """ utcnow = get_utcnow() # Prevent more than one task from processing this SMS, just in case # the message got enqueued twice. message_lock = get_lock("sms-queue-processing-%s" % queued_sms_pk) if message_lock.acquire(blocking=False): try: msg = QueuedSMS.objects.get(pk=queued_sms_pk) except QueuedSMS.DoesNotExist: # The message was already processed and removed from the queue release_lock(message_lock, True) return if message_is_stale(msg, utcnow): msg.set_system_error(SMS.ERROR_MESSAGE_IS_STALE) remove_from_queue(msg) release_lock(message_lock, True) return outbound_counter = None if msg.direction == OUTGOING: domain_object = Domain.get_by_name(msg.domain) if msg.domain else None if domain_object and handle_domain_specific_delays(msg, domain_object, utcnow): release_lock(message_lock, True) return outbound_counter = OutboundDailyCounter(domain_object) if not outbound_counter.can_send_outbound_sms(msg): release_lock(message_lock, True) return requeue = False # Process inbound SMS from a single contact one at a time recipient_block = msg.direction == INCOMING # We check datetime_to_process against utcnow plus a small amount # of time because timestamps can differ between machines which # can cause us to miss sending the message the first time and # result in an unnecessary delay. if ( isinstance(msg.processed, bool) and not msg.processed and not msg.error and msg.datetime_to_process < (utcnow + timedelta(seconds=10)) ): if recipient_block: recipient_lock = get_lock( "sms-queue-recipient-phone-%s" % msg.phone_number) recipient_lock.acquire(blocking=True) if msg.direction == OUTGOING: if ( msg.domain and msg.couch_recipient_doc_type and msg.couch_recipient and not is_contact_active(msg.domain, msg.couch_recipient_doc_type, msg.couch_recipient) ): msg.set_system_error(SMS.ERROR_CONTACT_IS_INACTIVE) remove_from_queue(msg) else: requeue = handle_outgoing(msg) elif msg.direction == INCOMING: try: handle_incoming(msg) except DelayProcessing: process_sms.apply_async([queued_sms_pk], countdown=60) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) else: msg.set_system_error(SMS.ERROR_INVALID_DIRECTION) remove_from_queue(msg) if recipient_block: release_lock(recipient_lock, True) release_lock(message_lock, True) if requeue: if outbound_counter: outbound_counter.decrement() send_to_sms_queue(msg)
def process_incoming(msg): v, has_domain_two_way_scope = get_inbound_phone_entry(msg) if v: if any_migrations_in_progress(v.domain): raise DelayProcessing() msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.location_id = get_location_id_by_verified_number(v) msg.save() elif msg.domain_scope: if any_migrations_in_progress(msg.domain_scope): raise DelayProcessing() msg.domain = msg.domain_scope msg.save() opt_in_keywords, opt_out_keywords, pass_through_opt_in_keywords = get_opt_keywords(msg) domain = v.domain if v else None if is_opt_message(msg.text, opt_out_keywords): if PhoneBlacklist.opt_out_sms(msg.phone_number, domain=domain): metadata = MessageMetadata(ignore_opt_out=True) text = get_message(MSG_OPTED_OUT, v, context=(opt_in_keywords[0],)) if v: send_sms_to_verified_number(v, text, metadata=metadata) elif msg.backend_id: send_sms_with_backend(msg.domain, msg.phone_number, text, msg.backend_id, metadata=metadata) else: send_sms(msg.domain, None, msg.phone_number, text, metadata=metadata) elif is_opt_message(msg.text, opt_in_keywords): if PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain): text = get_message(MSG_OPTED_IN, v, context=(opt_out_keywords[0],)) if v: send_sms_to_verified_number(v, text) elif msg.backend_id: send_sms_with_backend(msg.domain, msg.phone_number, text, msg.backend_id) else: send_sms(msg.domain, None, msg.phone_number, text) else: if is_opt_message(msg.text, pass_through_opt_in_keywords): # Opt the phone number in, and then process the message normally PhoneBlacklist.opt_in_sms(msg.phone_number, domain=domain) handled = False is_two_way = v is not None and v.is_two_way if msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS): handled = load_and_call(settings.CUSTOM_SMS_HANDLERS, v, msg.text, msg) if not handled and v and v.pending_verification: from . import verify handled = verify.process_verification(v, msg, create_subevent_for_inbound=not has_domain_two_way_scope) if ( not handled and (is_two_way or has_domain_two_way_scope) and is_contact_active(v.domain, v.owner_doc_type, v.owner_id) ): handled = load_and_call(settings.SMS_HANDLERS, v, msg.text, msg) if not handled and not is_two_way: handled = process_pre_registration(msg) if not handled: handled = process_sms_registration(msg) # If the sms queue is enabled, then the billable gets created in remove_from_queue() if ( not settings.SMS_QUEUE_ENABLED and msg.domain and domain_has_privilege(msg.domain, privileges.INBOUND_SMS) ): create_billable_for_sms(msg)
def _allow_load_handlers(v, is_two_way, has_domain_two_way_scope): return ((is_two_way or has_domain_two_way_scope) and is_contact_active(v.domain, v.owner_doc_type, v.owner_id))