def assure_citizen_alias(db, phone_number): ''' create citizen alias if does not exist yet ''' from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id alias_res = get_one_citizen_alias_by_phone_number(db, phone_number) if alias_res[0]: if (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]): return (False, 'wrong loaded citizen alias structure') return (True, alias_res[1]) authority = get_conf('authority') phone_identifier_type = get_conf('phone_identifier_type') alias_new = { 'authority': authority, 'identifiers': [{'type':phone_identifier_type, 'value':phone_number}], 'verified': False, 'local': False } alias_id = citizen_holder.save_alias(alias_new) if not alias_id: return (False, 'can not save citizen alias info') alias_res = get_one_citizen_alias_by_id(db, alias_id) if (not alias_res[0]) or (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]): return (False, 'wrong reloaded citizen alias structure') return alias_res
def get_sms(phone_number): session_info = None phone_number_normalized = normalize_phone_number(phone_number) if not phone_number_normalized: return None feed_type = get_conf('feed_type') authority = get_conf('authority') channel_value_send = get_conf('channel_value_send') channel_value_receive = get_conf('channel_value_receive') sess_spec_sent = { 'feed_type': feed_type, 'channels': { '$elemMatch': { 'value': channel_value_send } }, 'recipients': { '$elemMatch': { 'authority': authority, 'identifiers.user_id_search': phone_number_normalized } } } res = holder.find_last_session(sess_spec_sent) if (type(res) is not dict) or ('produced' not in res): res = None if res: session_info = res sess_spec_received = { 'feed_type': feed_type, 'channels': { '$elemMatch': { 'value': channel_value_receive } }, 'authors': { '$elemMatch': { 'authority': authority, 'identifiers.user_id_search': phone_number_normalized } } } res = holder.find_last_session(sess_spec_received) if (type(res) is not dict) or ('produced' not in res): res = None if res: if not session_info: session_info = res else: if res['produced'] >= session_info['produced']: session_info = res return session_info
def prepare_sms_send_report(targets, recipients, message, user_id=None, language=None, sensitive=None, client_ip=None): ''' preparing an sms-based report when the sms is sent not as a reply, i.e. starting a new session for it ''' channel_type = get_conf('channel_type') channel_value = get_conf('channel_value_send') feed_type = get_conf('feed_type') channel = { 'type': channel_type, 'value': channel_value, 'filter': None, 'reasons': None, 'request': None } current_timestamp = datetime.datetime.now() doc = { 'report_id': gen_id(feed_type, channel_type, channel_value, current_timestamp), # to generate the report_id 'channels': [channel], 'recipients': recipients, 'authors': [], # no citizen here 'endorsers': [], # no citizen here 'publisher': get_conf('publisher'), 'feed_type': feed_type, 'parent_id': None, # not a reply here 'session': None, 'user_id': user_id, # who requested the sending, if not automatic 'pinned_id': None, 'coverage_id': None, 'language': language, 'produced': current_timestamp, 'created': current_timestamp, 'assignments': [], 'original_id': None, 'original': {'message': message}, 'texts': [{'original': message, 'transcript': None}], 'tags': [], # we shall extract possible #tags, alike at sms receiving 'is_published': False, 'sensitive': None, 'summary': False, 'local': True, 'targets': targets, # alias_ids and/or group_ids for replies, on sent reports 'proto': False, 'client_ip': client_ip # for logging } if sensitive is not None: doc['sensitive'] = _get_boolean(sensitive) doc['session'] = doc['report_id'] doc['tags'] = _extract_tags(message) return doc
def assure_citizen_alias(db, phone_number): ''' create citizen alias if does not exist yet ''' from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id alias_res = get_one_citizen_alias_by_phone_number(db, phone_number) if alias_res[0]: if (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]): return (False, 'wrong loaded citizen alias structure') return (True, alias_res[1]) authority = get_conf('authority') alias_new = { 'authority': authority, 'identifiers': _create_phone_number_identities(phone_number), 'verified': False, 'local': False } alias_id = citizen_holder.save_alias(alias_new) if not alias_id: return (False, 'can not save citizen alias info') alias_res = get_one_citizen_alias_by_id(db, alias_id) if (not alias_res[0]) or (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]): return (False, 'wrong reloaded citizen alias structure') return alias_res
def get_sms(phone_number): session_info = None phone_number_normalized = normalize_phone_number(phone_number) if not phone_number_normalized: return None feed_type = get_conf('feed_type') authority = get_conf('authority') channel_value_send = get_conf('channel_value_send') channel_value_receive = get_conf('channel_value_receive') sess_spec_sent = { 'feed_type': feed_type, 'channels': {'$elemMatch': {'value': channel_value_send}}, 'recipients': {'$elemMatch': {'authority': authority, 'identifiers.user_id_search': phone_number_normalized}} } res = holder.find_last_session(sess_spec_sent) if (type(res) is not dict) or ('produced' not in res): res = None if res: session_info = res sess_spec_received = { 'feed_type': feed_type, 'channels': {'$elemMatch': {'value': channel_value_receive}}, 'authors': {'$elemMatch': {'authority': authority, 'identifiers.user_id_search': phone_number_normalized}} } res = holder.find_last_session(sess_spec_received) if (type(res) is not dict) or ('produced' not in res): res = None if res: if not session_info: session_info = res else: if res['produced'] >= session_info['produced']: session_info = res return session_info
def get_one_by_phone_number(db, phone_number, active=True): ''' returns data of a single sms citizen alias with given phone number ''' if not db: return (False, 'inner application error') coll = db[collection] phone_identifier_type = get_conf('phone_identifier_type') spec = {'active': active, 'authority': AUTHORITY, 'identifiers': {'type':phone_identifier_type, 'value':phone_number}} doc = coll.find_one(spec) if not doc: return (False, 'citizen alias info not found') return (True, doc)
def prepare_sms_send_report(targets, recipients, message, user_id=None, language=None, sensitive=None, client_ip=None): ''' preparing an sms-based report when the sms is sent not as a reply, i.e. starting a new session for it ''' channel_type = get_conf('channel_type') channel_value = get_conf('channel_value_send') feed_type = get_conf('feed_type') if user_id: user_id = _get_id_value(user_id) channel = { 'type': channel_type, 'value': channel_value, 'filter': None, 'reasons': None, 'request': None } current_timestamp = datetime.datetime.utcnow() doc = { 'report_id': gen_id(feed_type, channel_type, channel_value, current_timestamp), # to generate the report_id 'channels': [channel], 'recipients': recipients, 'authors': [], # no citizen here 'endorsers': [], # no citizen here 'publisher': get_conf('publisher'), 'feed_type': feed_type, 'parent_id': None, # not a reply here 'session': None, 'user_id': user_id, # who requested the sending, if not automatic 'pinned_id': None, 'language': language, 'produced': current_timestamp, '_created': current_timestamp, '_updated': current_timestamp, 'assignments': [], 'original_id': None, 'original': { 'message': message }, 'texts': [{ 'original': message, 'transcript': None }], 'tags': [], # we shall extract possible #tags, alike at sms receiving 'sensitive': None, 'summary': False, 'local': True, 'targets': targets, # alias_ids and/or group_ids for replies, on sent reports 'proto': False, 'client_ip': client_ip # for logging } if sensitive is not None: doc['sensitive'] = _get_boolean(sensitive) doc['session'] = doc['report_id'] doc['tags'] = _extract_tags(message) return doc
def ask_sender(db, session_start, orig_report, alias_info, phone_number, common_config): # for now, general config in a config file, or 'cd_config' collection in 'sms' document # by phone_number: in citizen_alias structure use_config = { 'sms_reply_send': None, 'sms_reply_message': None, 'sms_confirm_send': None, 'sms_confirm_message': None, } for key in use_config: if key in common_config: use_config[key] = common_config[key] alias_config = {} if ('config' in alias_info) and (type(alias_info['config']) is dict): alias_config = alias_info['config'] for key in use_config: if (key in alias_config) and (alias_config[key] is not None): use_config[key] = alias_config[key] message = None if session_start: to_send = use_config['sms_reply_send'] if to_send: message = use_config['sms_reply_message'] else: to_send = use_config['sms_confirm_send'] if to_send: message = use_config['sms_confirm_message'] if not message: return (True, None) if not controller: return (False, 'no sms gateway controller available') conf_alias_doctype = get_conf('alias_doctype') conf_authority = get_conf('authority') conf_phone_identifier_type = get_conf('phone_identifier_type') use_targets = [{'type':conf_alias_doctype, 'value':alias_info['_id']}] use_recipients = [{'authority':conf_authority, 'identifiers':[{'type':conf_phone_identifier_type, 'value':phone_number}]}] use_phone_numbers = [phone_number] doc = _prepare_sms_reply_report(orig_report, use_targets, use_recipients, message) if not doc: return (False, 'automatic report could not be prepared') doc['automatic'] = True doc_id = report_holder.save_report(doc) if not doc_id: return (False, 'automatic report could not be saved') sms_gateway_url = common_config['sms_gateway_url'] sms_gateway_key = common_config['sms_gateway_key'] connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key) res = connector.send_sms(message, {'phone_numbers': use_phone_numbers}) if not res[0]: report_holder.delete_report(doc_id) return (False, 'automatic message could not be sent', res[1]) return (True, {'_id': doc_id})
def do_post(db, params, main_config, client_ip): ''' * assure citizen_alias exists (i.e. create/save if does not yet) * find if following a previous report (incl. taking its session) * create and save the report * if starting a new session and with auto-replies: * create a reply-report * send a reply message (via gateway) ''' logger = get_logger() # taking given params feed_type = get_conf('feed_type') publisher = get_conf('publisher') feed_name = params['feed'] phone_number = params['phone'] message = params['text'] received = params['time'] timestamp = datetime.datetime.now() # assuring the citizen alias_id = None alias_info = None alias_res = assure_citizen_alias(db, phone_number) if alias_res[0]: alias_info = alias_res[1] alias_id = alias_info['_id'] # finding the followed report last_report = get_sms(phone_number) if last_report: for key in ['produced', 'session', 'report_id']: if key not in last_report: last_report = None # creating the report authority = get_conf('authority') phone_identifier_type = get_conf('phone_identifier_type') channel_type = get_conf('channel_type') channel_value_receive = get_conf('channel_value_receive') sms_filter = None if feed_name: sms_filter = {'feed_name': feed_name} channels = [{'type': channel_type, 'value': channel_value_receive, 'filter': sms_filter, 'request': None, 'reasons': None}] authors = [{'authority': authority, 'identifiers': [{'type': phone_identifier_type, 'value': phone_number}]}] endorsers = [] original = {'message': message} texts = [{'original': message, 'transcript': None}] tags = [] if message: tags = _extract_tags(message) report_id = gen_id(feed_type, channel_type, channel_value_receive, timestamp) session = report_id parent_id = None new_session = True pinned_id = None assignments = [] if last_report: if is_within_session(last_report['produced'], received, main_config): session = last_report['session'] parent_id = last_report['report_id'] if 'pinned_id' in last_report: pinned_id = last_report['pinned_id'] if 'assignments' in last_report: assignments = last_report['assignments'] new_session = False report = {} report['report_id'] = report_id report['parent_id'] = parent_id report['client_ip'] = client_ip report['feed_type'] = feed_type report['produced'] = received report['session'] = session report['publisher'] = publisher report['channels'] = channels report['authors'] = authors report['original'] = original report['texts'] = texts report['tags'] = tags report['pinned_id'] = pinned_id report['assignments'] = assignments report['proto'] = False report_doc_id = report_holder.save_report(report) if not report_doc_id: return (False, 'can not save SMS report') report = report_holder.provide_report(feed_type, report_id) reply_res = ask_sender(db, new_session, report, alias_info, phone_number, main_config) if not reply_res[0]: reason = str(reply_res[1]) if 2 < len(reply_res): reason += ', ' + str(reply_res[2]) logger.warning('Issue during auto-reply SMS: ' + reason) return (True, str(report_doc_id))
def do_post_send(db, sms_gateway_api, sms_gateway_url, sms_gateway_key, message, targets, user_id, language, sensitive, client_ip): try: controller = importlib.import_module('citizendesk.feeds.sms.external.' + sms_gateway_api) except: controller = None if not controller: return (False, 'no sms gateway controller available') if not db: return (False, 'no database available') if not sms_gateway_url: return (False, 'no sms gateway url configured') if not sms_gateway_key: return (False, 'no sms gateway key configured') if not message: return (False, 'no message provided') if not targets: return (False, 'no targets provided') from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id use_targets = [] use_recipients = [] use_phone_numbers = [] authority = get_conf('authority') alias_doctype = get_conf('alias_doctype') if type(targets) not in [list, tuple]: return (False, '') for one_target in targets: if type(one_target) is not dict: continue if 'type' not in one_target: continue if one_target['type'] != alias_doctype: continue if 'value' not in one_target: continue one_target_id = _get_id_value(one_target['value']) alias_res = get_one_citizen_alias_by_id(db, one_target_id) if (not alias_res) or (not alias_res[0]): continue alias = alias_res[1] if (type(alias) is not dict) or (not alias): continue if ('identifiers' not in alias) or (not alias['identifiers']): continue one_phone_number = _get_phone_number(alias) if not one_phone_number: continue one_recipient = {'authority': authority, 'identifiers': alias['identifiers']} use_phone_numbers.append(one_phone_number) use_recipients.append(one_recipient) use_targets.append(one_target) if not use_targets: return (False, 'no valid recipient found') # putting all the recipients into a single report; and thus using its session for next communication with all the recipients try: report = _prepare_sms_send_report(use_targets, use_recipients, message, user_id, language, sensitive, client_ip) except: report = None if not report: return (False, 'report could not be prepared') # we either save the report before sms sending, and deleting it if sending fails, # or we first send sms, and if success on it, we save the report then; # thus either transiently having a false report, or a possibility of not having the report # on sent sms if the report saving fails at the end (should not hopefully though) doc_id = report_holder.save_report(report) if not doc_id: return (False, 'report could not be saved') connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key) res = connector.send_sms(message, {'phone_numbers': use_phone_numbers}) if not res[0]: report_holder.delete_report(doc_id) return (False, 'message could not be sent', res[1]) return (True, {'_id': doc_id})
def ask_sender(db, session_start, orig_report, alias_info, phone_number, common_config): # for now, general config in a config file, or 'core_config' collection in 'sms' document # by phone_number: in citizen_alias structure try: gateway_api = common_config['gateway_api'] except: gateway_api = 'frontlinesms' try: controller = importlib.import_module('citizendesk.feeds.sms.external.' + gateway_api) except: controller = None use_config = { 'sms_reply_send': None, 'sms_reply_message': None, 'sms_confirm_send': None, 'sms_confirm_message': None, } for key in use_config: if key in common_config: use_config[key] = common_config[key] alias_config = {} if ('config' in alias_info) and (type(alias_info['config']) is dict): alias_config = alias_info['config'] for key in use_config: if (key in alias_config) and (alias_config[key] is not None): use_config[key] = alias_config[key] message = None if session_start: to_send = use_config['sms_reply_send'] if to_send: message = use_config['sms_reply_message'] else: to_send = use_config['sms_confirm_send'] if to_send: message = use_config['sms_confirm_message'] if not message: return (True, None) if not controller: return (False, 'no sms gateway controller available') conf_alias_doctype = get_conf('alias_doctype') conf_authority = get_conf('authority') use_targets = [{'type':conf_alias_doctype, 'value':alias_info['_id']}] use_identifiers = _create_phone_number_identities(phone_number) use_recipients = [{'authority':conf_authority, 'identifiers':use_identifiers}] use_phone_numbers = [phone_number] doc = _prepare_sms_reply_report(orig_report, use_targets, use_recipients, message) if not doc: return (False, 'automatic report could not be prepared') doc['automatic'] = True doc_id = report_holder.save_report(doc) if not doc_id: return (False, 'automatic report could not be saved') sms_gateway_url = common_config['sms_gateway_url'] sms_gateway_key = common_config['sms_gateway_key'] connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key) res = connector.send_sms(message, {'phone_numbers': use_phone_numbers}) if not res[0]: report_holder.delete_report(doc_id) return (False, 'automatic message could not be sent', res[1]) return (True, {'_id': doc_id})
def do_post(db, params, main_config, client_ip): ''' * assure citizen_alias exists (i.e. create/save if does not yet) * find if following a previous report (incl. taking its session) * create and save the report * if starting a new session and with auto-replies: * create a reply-report * send a reply message (via gateway) ''' logger = get_logger() # taking given params feed_type = get_conf('feed_type') publisher = get_conf('publisher') feed_name = params['feed'] phone_number = params['phone'] message = params['text'] received = params['time'] timestamp = datetime.datetime.utcnow() # assuring the citizen alias_id = None alias_info = None alias_res = assure_citizen_alias(db, phone_number) if alias_res[0]: alias_info = alias_res[1] alias_id = alias_info['_id'] # finding the followed report last_report = get_sms(phone_number) if last_report: for key in ['produced', 'session', 'report_id']: if key not in last_report: last_report = None # creating the report authority = get_conf('authority') channel_type = get_conf('channel_type') channel_value_receive = get_conf('channel_value_receive') sms_filter = None if feed_name: sms_filter = {'feed_name': feed_name} use_identifiers = _create_phone_number_identities(phone_number) channels = [{'type': channel_type, 'value': channel_value_receive, 'filter': sms_filter, 'request': None, 'reasons': None}] authors = [{'authority': authority, 'identifiers': use_identifiers}] endorsers = [] original = {'message': message} texts = [{'original': message, 'transcript': None}] tags = [] if message: tags = _extract_tags(message) report_id = gen_id(feed_type, channel_type, channel_value_receive, timestamp) session = report_id parent_id = None new_session = True pinned_id = None assignments = [] if last_report: if is_within_session(last_report['produced'], received, main_config): session = last_report['session'] parent_id = last_report['report_id'] if 'pinned_id' in last_report: pinned_id = last_report['pinned_id'] if 'assignments' in last_report: assignments = last_report['assignments'] new_session = False report = {} report['report_id'] = report_id report['parent_id'] = parent_id report['client_ip'] = client_ip report['feed_type'] = feed_type report['produced'] = received report['session'] = session report['publisher'] = publisher report['channels'] = channels report['authors'] = authors report['original'] = original report['texts'] = texts report['tags'] = tags report['pinned_id'] = pinned_id report['assignments'] = assignments report['proto'] = False report_doc_id = report_holder.save_report(report) if not report_doc_id: return (False, 'can not save SMS report') report = report_holder.provide_report(feed_type, report_id) reply_res = ask_sender(db, new_session, report, alias_info, phone_number, main_config) if not reply_res[0]: reason = str(reply_res[1]) if 2 < len(reply_res): reason += ', ' + str(reply_res[2]) logger.warning('Issue during auto-reply SMS: ' + reason) return (True, str(report_doc_id))
def do_post_reply(db, sms_gateway_api, sms_gateway_url, sms_gateway_key, message, report_id, user_id, language, sensitive, client_ip): try: controller = importlib.import_module('citizendesk.feeds.sms.external.' + sms_gateway_api) except: controller = None if not controller: return (False, 'no sms gateway controller available') if not db: return (False, 'no database available') if not sms_gateway_url: return (False, 'no sms gateway url configured') if not sms_gateway_key: return (False, 'no sms gateway key configured') if not message: return (False, 'no message provided') if not report_id: return (False, 'report_id not provided') from citizendesk.feeds.sms.report.storage import do_get_one_by_id as get_one_report_by_id from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number report_id = _get_id_value(report_id) report_res = get_one_report_by_id(db, report_id) if not report_res[0]: return (False, 'report of given id not found') report_source = report_res[1] was_sent = False was_received = False channel_type = get_conf('channel_type') channel_value_send = get_conf('channel_value_send') channel_value_receive = get_conf('channel_value_receive') alias_doctype = get_conf('alias_doctype') authority = get_conf('authority') if type(report_source) is not dict: return (False, 'wrong structure of report') if ('channels' in report_source) and (type(report_source['channels']) in (list, tuple)): for one_channel in report_source['channels']: if (type(one_channel) is dict) and ('type' in one_channel) and ('value' in one_channel): if one_channel['type'] != channel_type: continue if one_channel['value'] == channel_value_send: was_sent = True if one_channel['value'] == channel_value_receive: was_received = True if (not was_sent) and (not was_received): return (False, 'unknown form of report') citizen_aliases = [] if was_sent and ('targets' in report_source) and (type(report_source['targets']) in (list, tuple)): for one_target in report_source['targets']: if (type(one_target) is dict) and ('type' in one_target) and ('value' in one_target): if one_target['type'] == alias_doctype: one_target_value = _get_id_value(one_target['value']) one_citizen_alias_res = get_one_citizen_alias_by_id(db, one_target_value) if one_citizen_alias_res[0]: citizen_aliases.append(one_citizen_alias_res[1]) if was_received and ('authors' in report_source) and (type(report_source['authors']) in (list, tuple)): for one_author in report_source['authors']: one_phone_number = _get_phone_number(one_author) if not one_phone_number: continue one_citizen_alias_res = get_one_citizen_alias_by_phone_number(db, one_phone_number) if one_citizen_alias_res[0]: citizen_aliases.append(one_citizen_alias_res[1]) if not citizen_aliases: return (False, 'not target suitable citizen alias found') use_targets = [] use_recipients = [] use_phone_numbers = [] for one_citizen_alias in citizen_aliases: if (type(one_citizen_alias) is not dict): continue if ('_id' not in one_citizen_alias) or (not one_citizen_alias['_id']): continue one_target = {'type': alias_doctype, 'value': one_citizen_alias['_id']} if ('identifiers' not in one_citizen_alias) or (not one_citizen_alias['identifiers']): continue one_recipient = {'authority': authority, 'identifiers': one_citizen_alias['identifiers']} one_phone_number = _get_phone_number(one_citizen_alias) if not one_phone_number: continue use_phone_numbers.append(one_phone_number) use_recipients.append(one_recipient) use_targets.append(one_target) if not use_targets: return (False, 'no valid recipient found') # putting all the recipients into a single report; and thus using its session for next communication with all the recipients try: report = _prepare_sms_reply_report(report_source, use_targets, use_recipients, message, user_id, language, sensitive, client_ip) except: report = None if not report: return (False, 'report could not be prepared') # we either save the report before sms sending, and deleting it if sending fails, # or we first send sms, and if success on it, we save the report then; # thus either transiently having a false report, or a possibility of not having the report # on sent sms if the report saving fails at the end (should not hopefully though) doc_id = report_holder.save_report(report) if not doc_id: return (False, 'report could not be saved') connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key) res = connector.send_sms(message, {'phone_numbers': use_phone_numbers}) if not res[0]: report_holder.delete_report(doc_id) return (False, 'message could not be sent', res[1]) return (True, {'_id': doc_id})
def do_post_one(db, alias_id, alias_spec, user_id): ''' sets a basic info on phone_number-based citizen alias ''' if not db: return (False, 'inner application error') if type(alias_spec) is not dict: return (False, 'citizen specification should be a dict') if 'phone_number' not in alias_spec: return (False, 'phone number specification not provided') use_phone_number = alias_spec['phone_number'] try: use_phone_number = str(use_phone_number) except: return (False, 'wrong specification of phone number') if not use_phone_number: return (False, 'empty phone number specification') user_id = _get_id_value(user_id) if not alias_id: search_res = get_one_by_phone_number(db, use_phone_number) if search_res[0]: return (False, 'active citizen alias with given phone number already exists', search_res[1]['_id']) alias_doc = None if alias_id: alias_id = _get_id_value(alias_id) alias_doc = get_one_by_id(db, alias_id) if not alias_doc: return (False, 'citizen alias of provided id not found') spec_keys = { 'description': [str, unicode], 'name_first': [str, unicode], 'name_last': [str, unicode], 'name_full': [str, unicode], 'languages': [list, tuple], 'places': [list, tuple], 'home_pages': [list, tuple], 'verified': [bool] } phone_identifier_type = get_conf('phone_identifier_type') if not alias_doc: alias_use = { 'authority': AUTHORITY, 'identifiers': [{'type':phone_identifier_type, 'value':use_phone_number}], 'verified': False, 'local': True, 'created_by': user_id } for key in spec_keys: if (key in alias_spec) and (type(alias_spec[key]) in spec_keys[key]): alias_use[key] = alias_spec[key] alias_id = citizen_holder.save_alias(alias_use) if not alias_id: return (False, 'can not save the citizen alias') else: alias_use = alias_doc alias_use['identifiers'] = [{'type':phone_identifier_type, 'value':use_phone_number}] alias_use['updated_by'] = user_id alias_use['local'] = True for key in spec_keys: if (key in alias_spec) and (type(alias_spec[key]) in spec_keys[key]): alias_use[key] = alias_spec[key] coll = db[collection] alias_id = coll.save(alias_use) if not alias_id: return (False, 'can not update the citizen alias') return (True, {'_id': alias_id})