Пример #1
0
 def already_have_locations(self, users):
     user_query = (UserES()
                   .domain(self.domain_object.name)
                   .mobile_users()
                   .doc_id(list(users))
                   .exists('location_id')
                   .fields(['username']))
     return [raw_username(u['username']) for u in user_query.run().hits]
Пример #2
0
def get_prime_restore_user_params(request_user_id, sync_user_id):
    """Return username param and as_user param for performing formpalyer sync"""
    request_user = CouchUser.get_by_user_id(request_user_id).username
    as_username = None
    if sync_user_id and sync_user_id != request_user_id:
        as_user = CouchUser.get_by_user_id(sync_user_id)
        as_username = raw_username(as_user.username) if as_user else None
    return request_user, as_username
Пример #3
0
 def get_all_user_stubs(self):
     return {
         row.user_id: UserActivityStub(
             user_id=row.user_id,
             username=raw_username(row.username),
             num_forms_submitted=row.num_of_forms,
             is_performing=row.num_of_forms > row.threshold,
             previous_stub=None,
         ) for row in self._base_queryset.distinct('user_id')
     }
Пример #4
0
 def obj_get_list(self, bundle, **kwargs):
     domain = kwargs['domain']
     user_ids_username_pairs = get_all_user_id_username_pairs_by_domain(
         domain)
     results = [
         UserInfo(user_id=user_pair[0],
                  user_name=raw_username(user_pair[1]))
         for user_pair in user_ids_username_pairs
     ]
     return results
Пример #5
0
 def _get_all_user_stubs(self):
     return {
         row['user_id']: UserActivityStub(
             user_id=row['user_id'],
             username=raw_username(row['username']),
             num_forms_submitted=row['total_num_forms'],
             is_performing=row['total_num_forms'] >= self.performance_threshold,
             previous_stub=None,
             next_stub=None,
         ) for row in self._user_stat_from_malt
     }
Пример #6
0
 def transfer_to_domain(self, domain, app_id):
     username = format_username(raw_username(self.username), domain)
     self.change_username(username)
     self.domain = domain
     for form in self.get_forms():
         form.domain = domain
         form.app_id = app_id
         form.save()
     for case in self.get_cases():
         case.domain = domain
         case.save()
     self.save()
Пример #7
0
def _cached_owner_id_to_display(owner_id):
    key = 'owner_id_to_display_cache_{id}'.format(id=owner_id)
    ret = cache.get(key)
    if ret:
        return ret
    owner = get_wrapped_owner(owner_id)
    if owner is None:
        return None
    else:
        ret = raw_username(owner.username) if isinstance(owner, CouchUser) else owner.name
        cache.set(key, ret)
        return ret
Пример #8
0
    def obj_get_list(self, bundle, **kwargs):
        domain = kwargs['domain']

        couch_user = CouchUser.from_django_user(bundle.request.user)
        if not domain_has_privilege(domain, privileges.ZAPIER_INTEGRATION) or not couch_user.is_member_of(domain):
            raise ImmediateHttpResponse(
                HttpForbidden('You are not allowed to get list of usernames for this domain')
            )
        user_ids_username_pairs = get_all_user_id_username_pairs_by_domain(domain)

        results = [UserInfo(user_id=user_pair[0], user_name=raw_username(user_pair[1]))
                   for user_pair in user_ids_username_pairs]
        return results
Пример #9
0
    def obj_get_list(self, bundle, **kwargs):
        domain = kwargs['domain']

        couch_user = CouchUser.from_django_user(bundle.request.user)
        if not domain_has_privilege(domain, privileges.ZAPIER_INTEGRATION) or not couch_user.is_member_of(domain):
            raise ImmediateHttpResponse(
                HttpForbidden('You are not allowed to get list of usernames for this domain')
            )
        user_ids_username_pairs = get_all_user_id_username_pairs_by_domain(domain)

        results = [UserInfo(user_id=user_pair[0], user_name=raw_username(user_pair[1]))
                   for user_pair in user_ids_username_pairs]
        return results
Пример #10
0
 def _get_all_user_stubs(self):
     return {
         row['user_id']: UserActivityStub(
             user_id=row['user_id'],
             username=raw_username(row['username']),
             num_forms_submitted=row['total_num_forms'],
             is_performing=row['total_num_forms'] >=
             self.performance_threshold,
             previous_stub=None,
             next_stub=None,
         )
         for row in self._user_stat_from_malt
     }
Пример #11
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')

    assert doc.get('domain') == domain or domain in doc.get('domains', ())

    if cache and doc_id in cache:
        return cache[doc_id]

    if doc_type in ('Application', 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'corehq.apps.app_manager.views.download_index',
                    args=[domain, doc_id],
                ),
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'corehq.apps.app_manager.views.view_app',
                    args=[domain, doc_id],
                ),
            )
    elif doc_type in ('CommCareCase', ):
        doc_info = DocInfo(
            display=doc['name'],
            type_display=_('Case'),
            link=reverse(
                'case_details',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('XFormInstance', ):
        doc_info = DocInfo(
            type_display=_('Form'),
            link=reverse(
                'render_form_data',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('CommCareUser', ):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=reverse(
                'edit_commcare_user',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('WebUser', ):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=reverse(
                'user_account',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('Domain', ):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(urlname, kwargs={'domain': doc['name']}),
        )
    else:
        doc_info = DocInfo()

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #12
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return (doc_type == expected_doc_type or
            doc_type == ('%s%s' % (expected_doc_type, DELETED_SUFFIX)))

    if (
        domain_hint and
        not (
            doc.get('domain') == domain_hint or
            domain_hint in doc.get('domains', ())
        )
    ):
        raise DomainMismatchException("Doc '%s' does not match the domain_hint '%s'" % (doc_id, domain_hint))

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, 'Application') or has_doc_type(doc_type, 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display='%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'download_index',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'view_app',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, 'CommCareCaseGroup'):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView
        doc_info = DocInfo(
            type_display=_('Case Group'),
            display=doc['name'],
            link=reverse(
                CaseGroupCaseManagementView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'CommCareCase'):
        doc_info = case_docinfo(domain, doc_id, doc['name'], generic_delete)
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = form_docinfo(domain, doc_id, generic_delete)
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=get_commcareuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=get_webuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, 'Group'):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Domain'):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Location'):
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=_('Location'),
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(
            is_deleted=generic_delete,
        )

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #13
0
def create_or_update_users_and_groups(domain, user_specs, group_specs, location_specs, task=None):
    ret = {"errors": [], "rows": []}
    total = len(user_specs) + len(group_specs) + len(location_specs)
    def _set_progress(progress):
        if task is not None:
            DownloadBase.set_progress(task, progress, total)

    group_memoizer = create_or_update_groups(domain, group_specs, log=ret)
    current = len(group_specs)

    usernames = set()
    user_ids = set()
    allowed_groups = set(group_memoizer.groups)
    allowed_group_names = [group.name for group in allowed_groups]
    try:
        for row in user_specs:
            _set_progress(current)
            current += 1
            data, email, group_names, language, name, password, phone_number, user_id, username = (
                row.get(k) for k in sorted(allowed_headers)
            )
            if password:
                password = unicode(password)
            group_names = group_names or []
            try:
                username = normalize_username(str(username), domain)
            except TypeError:
                username = None
            except ValidationError:
                ret['rows'].append({
                    'username': username,
                    'row': row,
                    'flag': _('username cannot contain spaces or symbols'),
                })
                continue
            status_row = {
                'username': raw_username(username) if username else None,
                'row': row,
            }
            if username in usernames or user_id in user_ids:
                status_row['flag'] = 'repeat'
            elif not username and not user_id:
                status_row['flag'] = 'missing-data'
            else:
                try:
                    if username:
                        usernames.add(username)
                    if user_id:
                        user_ids.add(user_id)
                    if user_id:
                        user = CommCareUser.get_by_user_id(user_id, domain)
                    else:
                        user = CommCareUser.get_by_username(username)

                    def is_password(password):
                        if not password:
                            return False
                        for c in password:
                            if c != "*":
                                return True
                        return False

                    if user:
                        if user.domain != domain:
                            raise UserUploadError(_(
                                'User with username %(username)r is '
                                'somehow in domain %(domain)r'
                            ) % {'username': user.username, 'domain': user.domain})
                        if username and user.username != username:
                            user.change_username(username)
                        if is_password(password):
                            user.set_password(password)
                        status_row['flag'] = 'updated'
                    else:
                        if len(raw_username(username)) > CommCareAccountForm.max_len_username:
                            ret['rows'].append({
                                'username': username,
                                'row': row,
                                'flag': _("username cannot contain greater than %d characters" %
                                          CommCareAccountForm.max_len_username)
                            })
                            continue
                        if not is_password(password):
                            raise UserUploadError(_("Cannot create a new user with a blank password"))
                        user = CommCareUser.create(domain, username, password, uuid=user_id or '', commit=False)
                        status_row['flag'] = 'created'
                    if phone_number:
                        user.add_phone_number(_fmt_phone(phone_number), default=True)
                    if name:
                        user.set_full_name(name)
                    if data:
                        user.user_data.update(data)
                    if language:
                        user.language = language
                    if email:
                        user.email = email
                    user.save()
                    if is_password(password):
                        # Without this line, digest auth doesn't work.
                        # With this line, digest auth works.
                        # Other than that, I'm not sure what's going on
                        user.get_django_user().check_password(password)

                    for group_id in Group.by_user(user, wrap=False):
                        group = group_memoizer.get(group_id)
                        if group.name not in group_names:
                            group.remove_user(user, save=False)

                    for group_name in group_names:
                        if group_name not in allowed_group_names:
                            raise UserUploadError(_(
                                "Can't add to group '%s' "
                                "(try adding it to your spreadsheet)"
                            ) % group_name)
                        group_memoizer.by_name(group_name).add_user(user, save=False)

                except (UserUploadError, CouchUser.Inconsistent) as e:
                    status_row['flag'] = '%s' % e

            ret["rows"].append(status_row)
    finally:
        try:
            group_memoizer.save_all()
        except BulkSaveError as e:
            _error_message = (
                "Oops! We were not able to save some of your group changes. "
                "Please make sure no one else is editing your groups "
                "and try again."
            )
            logging.exception((
                'BulkSaveError saving groups. '
                'User saw error message "%s". Errors: %s'
            ) % (_error_message, e.errors))
            ret['errors'].append(_error_message)

    create_or_update_locations(domain, location_specs, log=ret)
    _set_progress(total)
    return ret
Пример #14
0
 def _user_section(username, data):
     return {
         'username': raw_username(username),
         'msgs': list(_messages(data)),
     }
Пример #15
0
 def get_headers(self):
     return [raw_username(u.username) for u in self.users]
Пример #16
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')

    assert doc.get('domain') == domain or domain in doc.get('domains', ())

    if cache and doc_id in cache:
        return cache[doc_id]

    if doc_type in ('Application', 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'corehq.apps.app_manager.views.download_index',
                    args=[domain, doc_id],
                ),
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'corehq.apps.app_manager.views.view_app',
                    args=[domain, doc_id],
                ),
            )
    elif doc_type in ('CommCareCase',):
        doc_info = DocInfo(
            display=doc['name'],
            type_display=_('Case'),
            link=reverse(
                'case_details',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in (couchforms_models.doc_types().keys()):
        doc_info = DocInfo(
            type_display=_('Form'),
            link=reverse(
                'render_form_data',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=reverse(
                'edit_commcare_user',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=reverse(
                'user_account',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('Group',):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('Domain',):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
        )
    elif doc_type == 'Location':
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=doc['location_type'],
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
        )
    else:
        doc_info = DocInfo()

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #17
0
 def _user_section(user):
     user_data = data_by_user.get(user._id, None)
     return {
         'username': raw_username(u.username),
         'msgs': list(_messages(user_data)),
     }
Пример #18
0
def create_or_update_users_and_groups(domain, user_specs, group_specs):
    ret = {"errors": [], "rows": []}
    group_memoizer = create_or_update_groups(domain, group_specs, log=ret)
    usernames = set()
    user_ids = set()

    allowed_groups = set(group_memoizer.groups)
    allowed_group_names = [group.name for group in allowed_groups]

    try:
        for row in user_specs:
            data, group_names, language, name, password, phone_number, user_id, username = (
                row.get(k) for k in sorted(allowed_headers)
            )
            password = unicode(password)
            group_names = group_names or []
            try:
                username = normalize_username(username, domain)
            except TypeError:
                username = None
            except ValidationError:
                ret['rows'].append({
                    'username': username,
                    'row': row,
                    'flag': _('username cannot contain spaces or symbols'),
                })
                continue
            status_row = {
                'username': raw_username(username) if username else None,
                'row': row,
            }
            if username in usernames or user_id in user_ids:
                status_row['flag'] = 'repeat'
            elif not username and not user_id:
                status_row['flag'] = 'missing-data'
            else:
                try:
                    if username:
                        usernames.add(username)
                    if user_id:
                        user_ids.add(user_id)
                    if user_id:
                        user = CommCareUser.get_by_user_id(user_id, domain)
                    else:
                        user = CommCareUser.get_by_username(username)
                    if user:
                        if user.domain != domain:
                            raise UserUploadError(_('User with username %(username)r is somehow in domain %(domain)r') %
                                            {'username': user.username, 'domain': user.domain})
                        if username and user.username != username:
                            user.change_username(username)
                        if password:
                            user.set_password(password)
                        status_row['flag'] = 'updated'
                    else:
                        if not password:
                            raise UserUploadError(_("Cannot create a new user with a blank password"))
                        user = CommCareUser.create(domain, username, password, uuid=user_id or '')
                        status_row['flag'] = 'created'
                    if phone_number:
                        user.add_phone_number(_fmt_phone(phone_number), default=True)
                    if name:
                        user.set_full_name(name)
                    if data:
                        user.user_data.update(data)
                    if language:
                        user.language = language
                    user.save()
                    if password:
                        # Without this line, digest auth doesn't work.
                        # With this line, digest auth works.
                        # Other than that, I'm not sure what's going on
                        user.get_django_user().check_password(password)

                    for group_id in Group.by_user(user, wrap=False):
                        group = group_memoizer.get(group_id)
                        if group.name not in group_names:
                            group.remove_user(user, save=False)

                    for group_name in group_names:
                        if group_name not in allowed_group_names:
                            raise UserUploadError(_(
                                "Can't add to group '%s' "
                                "(try adding it to your spreadsheet)"
                            ) % group_name)
                        group_memoizer.by_name(group_name).add_user(user, save=False)

                except UserUploadError as e:
                    status_row['flag'] = '%s' % e
                    
            ret["rows"].append(status_row)
    finally:
        group_memoizer.save_all()
    
    return ret
Пример #19
0
 def is_pending(cls, domain, username):
     """Is there a pending device log request matching these params?"""
     return (domain, raw_username(username)) in _all_device_log_requests()
Пример #20
0
 def validate_spec(self, spec):
     username = spec.get('username')
     if username:
         username = str(username)
     if len(raw_username(username)) > self.max_username_length:
         return self.error_message
Пример #21
0
 def user_choices(self):
     users = UserES().domain(self.domain).fields(['_id', 'username']).run().hits
     return [(user['_id'], raw_username(user['username'])) for user in users]
Пример #22
0
def get_doc_info_couch(doc, domain_hint=None, cache=None):
    """Return DocInfo objects for Couch doc dicts"""
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return (doc_type == expected_doc_type or
            doc_type == ('%s%s' % (expected_doc_type, DELETED_SUFFIX)))

    if cache and doc_id in cache:
        return cache[doc_id]

    if (
        has_doc_type(doc_type, 'Application')
        or has_doc_type(doc_type, 'LinkedApplication')
        or has_doc_type(doc_type, 'RemoteApp')
    ):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display='%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'download_index',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'view_app',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, 'CommCareCaseGroup'):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView
        doc_info = DocInfo(
            type_display=_('Case Group'),
            display=doc['name'],
            link=reverse(
                CaseGroupCaseManagementView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'CommCareCase'):
        doc_info = case_docinfo(domain, doc_id, doc['name'], generic_delete)
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = form_docinfo(domain, doc_id, generic_delete)
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=get_commcareuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=get_webuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, 'Group'):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Domain'):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Location'):
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=_('Location'),
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(
            is_deleted=generic_delete,
        )

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #23
0
 def already_have_locations(self, users):
     user_query = (UserES().domain(
         self.domain_object.name).mobile_users().doc_id(
             list(users)).exists('location_id').fields(['username']))
     return [raw_username(u['username']) for u in user_query.run().hits]
Пример #24
0
 def get_headers(self):
     return [raw_username(u.username) for u in self.users]
Пример #25
0
def create_or_update_users_and_groups(domain,
                                      user_specs,
                                      group_specs,
                                      location_specs,
                                      task=None):
    ret = {"errors": [], "rows": []}
    total = len(user_specs) + len(group_specs) + len(location_specs)

    def _set_progress(progress):
        if task is not None:
            DownloadBase.set_progress(task, progress, total)

    group_memoizer = create_or_update_groups(domain, group_specs, log=ret)
    current = len(group_specs)

    usernames = set()
    user_ids = set()
    allowed_groups = set(group_memoizer.groups)
    allowed_group_names = [group.name for group in allowed_groups]
    try:
        for row in user_specs:
            _set_progress(current)
            current += 1
            data, email, group_names, language, name, password, phone_number, user_id, username = (
                row.get(k) for k in sorted(allowed_headers))
            if password:
                password = unicode(password)
            group_names = group_names or []
            try:
                username = normalize_username(str(username), domain)
            except TypeError:
                username = None
            except ValidationError:
                ret['rows'].append({
                    'username':
                    username,
                    'row':
                    row,
                    'flag':
                    _('username cannot contain spaces or symbols'),
                })
                continue
            status_row = {
                'username': raw_username(username) if username else None,
                'row': row,
            }
            if username in usernames or user_id in user_ids:
                status_row['flag'] = 'repeat'
            elif not username and not user_id:
                status_row['flag'] = 'missing-data'
            else:
                try:
                    if username:
                        usernames.add(username)
                    if user_id:
                        user_ids.add(user_id)
                    if user_id:
                        user = CommCareUser.get_by_user_id(user_id, domain)
                    else:
                        user = CommCareUser.get_by_username(username)

                    def is_password(password):
                        if not password:
                            return False
                        for c in password:
                            if c != "*":
                                return True
                        return False

                    if user:
                        if user.domain != domain:
                            raise UserUploadError(
                                _('User with username %(username)r is '
                                  'somehow in domain %(domain)r') % {
                                      'username': user.username,
                                      'domain': user.domain
                                  })
                        if username and user.username != username:
                            user.change_username(username)
                        if is_password(password):
                            user.set_password(password)
                        status_row['flag'] = 'updated'
                    else:
                        if len(raw_username(username)
                               ) > CommCareAccountForm.max_len_username:
                            ret['rows'].append({
                                'username':
                                username,
                                'row':
                                row,
                                'flag':
                                _("username cannot contain greater than %d characters"
                                  % CommCareAccountForm.max_len_username)
                            })
                            continue
                        if not is_password(password):
                            raise UserUploadError(
                                _("Cannot create a new user with a blank password"
                                  ))
                        user = CommCareUser.create(domain,
                                                   username,
                                                   password,
                                                   uuid=user_id or '',
                                                   commit=False)
                        status_row['flag'] = 'created'
                    if phone_number:
                        user.add_phone_number(_fmt_phone(phone_number),
                                              default=True)
                    if name:
                        user.set_full_name(name)
                    if data:
                        user.user_data.update(data)
                    if language:
                        user.language = language
                    if email:
                        user.email = email
                    user.save()
                    if is_password(password):
                        # Without this line, digest auth doesn't work.
                        # With this line, digest auth works.
                        # Other than that, I'm not sure what's going on
                        user.get_django_user().check_password(password)

                    for group_id in Group.by_user(user, wrap=False):
                        group = group_memoizer.get(group_id)
                        if group.name not in group_names:
                            group.remove_user(user, save=False)

                    for group_name in group_names:
                        if group_name not in allowed_group_names:
                            raise UserUploadError(
                                _("Can't add to group '%s' "
                                  "(try adding it to your spreadsheet)") %
                                group_name)
                        group_memoizer.by_name(group_name).add_user(user,
                                                                    save=False)

                except (UserUploadError, CouchUser.Inconsistent) as e:
                    status_row['flag'] = unicode(e)

            ret["rows"].append(status_row)
    finally:
        try:
            group_memoizer.save_all()
        except BulkSaveError as e:
            _error_message = (
                "Oops! We were not able to save some of your group changes. "
                "Please make sure no one else is editing your groups "
                "and try again.")
            logging.exception(('BulkSaveError saving groups. '
                               'User saw error message "%s". Errors: %s') %
                              (_error_message, e.errors))
            ret['errors'].append(_error_message)

    create_or_update_locations(domain, location_specs, log=ret)
    _set_progress(total)
    return ret
Пример #26
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return (doc_type == expected_doc_type
                or doc_type == ('%s%s' % (expected_doc_type, DELETED_SUFFIX)))

    assert doc.get('domain') == domain or domain in doc.get('domains', ())

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, 'Application') or has_doc_type(
            doc_type, 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'corehq.apps.app_manager.views.download_index',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'corehq.apps.app_manager.views.view_app',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, 'CommCareCaseGroup'):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView
        doc_info = DocInfo(
            type_display=_('Case Group'),
            display=doc['name'],
            link=reverse(
                CaseGroupCaseManagementView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'CommCareCase'):
        doc_info = DocInfo(
            display=doc['name'],
            type_display=_('Case'),
            link=reverse(
                'case_details',
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif any([
            has_doc_type(doc_type, d)
            for d in couchforms_models.doc_types().keys()
    ]):
        doc_info = DocInfo(
            type_display=_('Form'),
            link=reverse(
                'render_form_data',
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif doc_type in ('CommCareUser', ):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=reverse(
                'edit_commcare_user',
                args=[domain, doc_id],
            ),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif doc_type in ('WebUser', ):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=reverse(
                'user_account',
                args=[domain, doc_id],
            ),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, 'Group'):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Domain'):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(urlname, kwargs={'domain': doc['name']}),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Location'):
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=_('Location'),
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(is_deleted=generic_delete, )

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #27
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get("domain") or domain_hint
    doc_type = doc.get("doc_type")
    doc_id = doc.get("_id")
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return doc_type == expected_doc_type or doc_type == ("%s%s" % (expected_doc_type, DELETED_SUFFIX))

    if domain_hint and not (doc.get("domain") == domain_hint or domain_hint in doc.get("domains", ())):
        raise DomainMismatchException("Doc '%s' does not match the domain_hint '%s'" % (doc_id, domain_hint))

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, "Application") or has_doc_type(doc_type, "RemoteApp"):
        if doc.get("copy_of"):
            doc_info = DocInfo(
                display=u"%s (#%s)" % (doc["name"], doc["version"]),
                type_display=_("Application Build"),
                link=reverse("corehq.apps.app_manager.views.download_index", args=[domain, doc_id]),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc["name"],
                type_display=_("Application"),
                link=reverse("corehq.apps.app_manager.views.view_app", args=[domain, doc_id]),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, "CommCareCaseGroup"):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView

        doc_info = DocInfo(
            type_display=_("Case Group"),
            display=doc["name"],
            link=reverse(CaseGroupCaseManagementView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "CommCareCase"):
        doc_info = DocInfo(
            display=doc["name"],
            type_display=_("Case"),
            link=reverse("case_details", args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = DocInfo(
            type_display=_("Form"), link=reverse("render_form_data", args=[domain, doc_id]), is_deleted=generic_delete
        )
    elif doc_type in ("CommCareUser",):
        doc_info = DocInfo(
            display=raw_username(doc["username"]),
            type_display=_("Mobile Worker"),
            link=reverse("edit_commcare_user", args=[domain, doc_id]),
            is_deleted=doc.get("base_doc", "").endswith(DELETED_SUFFIX),
        )
    elif doc_type in ("WebUser",):
        doc_info = DocInfo(
            type_display=_("Web User"),
            display=doc["username"],
            link=reverse("user_account", args=[domain, doc_id]),
            is_deleted=doc.get("base_doc", "").endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, "Group"):
        from corehq.apps.users.views.mobile import EditGroupMembersView

        doc_info = DocInfo(
            type_display=_("Group"),
            display=doc["name"],
            link=reverse(EditGroupMembersView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "Domain"):
        if doc["is_snapshot"] and doc["published"]:
            urlname = "project_info"
        else:
            urlname = "domain_basic_info"
        doc_info = DocInfo(
            type_display=_("Domain"),
            display=doc["name"],
            link=reverse(urlname, kwargs={"domain": doc["name"]}),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "Location"):
        from corehq.apps.locations.views import EditLocationView

        doc_info = DocInfo(
            type_display=_("Location"),
            display=doc["name"],
            link=reverse(EditLocationView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(is_deleted=generic_delete)

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #28
0
def create_or_update_users_and_groups(domain, user_specs, group_specs):
    ret = {"errors": [], "rows": []}
    group_memoizer = create_or_update_groups(domain, group_specs, log=ret)
    usernames = set()
    user_ids = set()

    allowed_groups = set(group_memoizer.groups)
    allowed_group_names = [group.name for group in allowed_groups]

    try:
        for row in user_specs:
            data, group_names, language, name, password, phone_number, user_id, username = (
                row.get(k) for k in sorted(allowed_headers))
            password = unicode(password)
            group_names = group_names or []
            try:
                username = normalize_username(username, domain)
            except TypeError:
                username = None
            except ValidationError:
                ret['rows'].append({
                    'username':
                    username,
                    'row':
                    row,
                    'flag':
                    _('username cannot contain spaces or symbols'),
                })
                continue
            status_row = {
                'username': raw_username(username) if username else None,
                'row': row,
            }
            if username in usernames or user_id in user_ids:
                status_row['flag'] = 'repeat'
            elif not username and not user_id:
                status_row['flag'] = 'missing-data'
            else:
                try:
                    if username:
                        usernames.add(username)
                    if user_id:
                        user_ids.add(user_id)
                    if user_id:
                        user = CommCareUser.get_by_user_id(user_id, domain)
                    else:
                        user = CommCareUser.get_by_username(username)
                    if user:
                        if user.domain != domain:
                            raise UserUploadError(
                                _('User with username %(username)r is somehow in domain %(domain)r'
                                  ) % {
                                      'username': user.username,
                                      'domain': user.domain
                                  })
                        if username and user.username != username:
                            user.change_username(username)
                        if password:
                            user.set_password(password)
                        status_row['flag'] = 'updated'
                    else:
                        if not password:
                            raise UserUploadError(
                                _("Cannot create a new user with a blank password"
                                  ))
                        user = CommCareUser.create(domain,
                                                   username,
                                                   password,
                                                   uuid=user_id or '')
                        status_row['flag'] = 'created'
                    if phone_number:
                        user.add_phone_number(_fmt_phone(phone_number),
                                              default=True)
                    if name:
                        user.set_full_name(name)
                    if data:
                        user.user_data.update(data)
                    if language:
                        user.language = language
                    user.save()
                    if password:
                        # Without this line, digest auth doesn't work.
                        # With this line, digest auth works.
                        # Other than that, I'm not sure what's going on
                        user.get_django_user().check_password(password)

                    for group_id in Group.by_user(user, wrap=False):
                        group = group_memoizer.get(group_id)
                        if group.name not in group_names:
                            group.remove_user(user, save=False)

                    for group_name in group_names:
                        if group_name not in allowed_group_names:
                            raise UserUploadError(
                                _("Can't add to group '%s' "
                                  "(try adding it to your spreadsheet)") %
                                group_name)
                        group_memoizer.by_name(group_name).add_user(user,
                                                                    save=False)

                except UserUploadError as e:
                    status_row['flag'] = '%s' % e

            ret["rows"].append(status_row)
    finally:
        group_memoizer.save_all()

    return ret
Пример #29
0
 def user_choices(self):
     users = UserES().domain(self.domain).fields(['_id',
                                                  'username']).run().hits
     return [(user['_id'], raw_username(user['username']))
             for user in users]
Пример #30
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get("domain") or domain_hint
    doc_type = doc.get("doc_type")
    doc_id = doc.get("_id")

    assert doc.get("domain") == domain or domain in doc.get("domains", ())

    if cache and doc_id in cache:
        return cache[doc_id]

    if doc_type in ("Application", "RemoteApp"):
        if doc.get("copy_of"):
            doc_info = DocInfo(
                display=u"%s (#%s)" % (doc["name"], doc["version"]),
                type_display=_("Application Build"),
                link=reverse("corehq.apps.app_manager.views.download_index", args=[domain, doc_id]),
            )
        else:
            doc_info = DocInfo(
                display=doc["name"],
                type_display=_("Application"),
                link=reverse("corehq.apps.app_manager.views.view_app", args=[domain, doc_id]),
            )
    elif doc_type in ("CommCareCase",):
        doc_info = DocInfo(
            display=doc["name"], type_display=_("Case"), link=reverse("case_details", args=[domain, doc_id])
        )
    elif doc_type in ("XFormInstance",):
        doc_info = DocInfo(type_display=_("Form"), link=reverse("render_form_data", args=[domain, doc_id]))
    elif doc_type in ("CommCareUser",):
        doc_info = DocInfo(
            display=raw_username(doc["username"]),
            type_display=_("Mobile Worker"),
            link=reverse("edit_commcare_user", args=[domain, doc_id]),
        )
    elif doc_type in ("WebUser",):
        doc_info = DocInfo(
            type_display=_("Web User"), display=doc["username"], link=reverse("user_account", args=[domain, doc_id])
        )
    elif doc_type in ("Domain",):
        if doc["is_snapshot"] and doc["published"]:
            urlname = "project_info"
        else:
            urlname = "domain_basic_info"
        doc_info = DocInfo(
            type_display=_("Domain"), display=doc["name"], link=reverse(urlname, kwargs={"domain": doc["name"]})
        )
    else:
        doc_info = DocInfo()

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Пример #31
0
 def _user_section(username, data):
     return {
         'username': raw_username(username),
         'msgs': list(_messages(data)),
     }
Пример #32
0
 def get_choices_from_es_query(user_es):
     return [
         Choice(user_id, raw_username(username))
         for user_id, username in user_es.values_list('_id', 'username')
     ]
Пример #33
0
def create_or_update_users_and_groups(domain, user_specs, group_specs):
    group_memoizer = GroupMemoizer(domain)
    ret = {"errors": [], "rows": []}
    for row in group_specs:
        group_name, case_sharing, reporting = row['name'], row['case-sharing'], row['reporting']
        try:
            group = group_memoizer.get_or_create_group(group_name)
        except MultipleResultsFound:
            ret["errors"].append("Multiple groups named: %s" % group_name)
        else:
            group.case_sharing = case_sharing
            group.reporting = reporting
    usernames = set()
    user_ids = set()

    try:
        for row in user_specs:
            data, group_names, name, password, phone_number, user_id, username = (
                row.get(k) for k in sorted(allowed_headers)
            )
            if isinstance(password, float):
                # almost certainly what was intended
                password = unicode(int(password))
            group_names = group_names or []
            try:
                username = normalize_username(username, domain)
            except TypeError:
                username = None
            status_row = {'username': raw_username(username) if username else None}
            status_row['row'] = row
            if username in usernames or user_id in user_ids:
                status_row['flag'] = 'repeat'
            elif not username and not user_id:
                status_row['flag'] = 'missing-data'
            else:
                try:
                    if username:
                        usernames.add(username)
                    if user_id:
                        user_ids.add(user_id)
                    if user_id:
                        user = CommCareUser.get_by_user_id(user_id, domain)
                    else:
                        user = CommCareUser.get_by_username(username)
                    if user:
                        if user.domain != domain:
                            raise Exception('User with username %r is somehow in domain %r' % (user.username, user.domain))
                        if username and user.username != username:
                            user.change_username(username)
                        if password:
                            user.set_password(password)
                        status_row['flag'] = 'updated'
                    else:
                        if not password:
                            raise Exception("Cannot create a new user with a blank password")
                        user = CommCareUser.create(domain, username, password, uuid=user_id or '')
                        status_row['flag'] = 'created'
                    if phone_number:
                        user.add_phone_number(_fmt_phone(phone_number), default=True)
                    if name:
                        user.set_full_name(name)
                    if data:
                        user.user_data.update(data)
                    user.save()
                    if password:
                        # Without this line, digest auth doesn't work.
                        # With this line, digest auth works.
                        # Other than that, I'm not sure what's going on
                        user.get_django_user().check_password(password)
                    for group in Group.by_user(user):
                        if group.name not in group_names:
                            group = group_memoizer.get_or_create_group(group.name)
                            group.remove_user(user)

                    for group_name in group_names:
                        try:
                            group_memoizer.get_group(group_name).add_user(user)
                        except Exception:
                            raise Exception("Can't add to group '%s' (try adding it to your spreadsheet)" % group_name)
                except Exception, e:
                    if isinstance(e, DatabaseError):
                        transaction.rollback()
                    status_row['flag'] = 'error: %s' % e
                    
            ret["rows"].append(status_row)
    finally:
        group_memoizer.save_all()
    
    return ret
    
Пример #34
0
 def format(data):
     if col_name == 'user_name':
         return raw_username(data)
     else:
         return data
Пример #35
0
 def _user_section(user):
     user_data = data_by_user.get(user._id, None)
     return {
         'username': raw_username(u.username),
         'msgs': list(_messages(user_data)),
     }
Пример #36
0
 def format(data):
     if col_name == 'user_name':
         return raw_username(data)
     else:
         return data
Пример #37
0
def get_doc_info(doc, domain_hint=None):
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')

    assert doc.get('domain') == domain or domain in doc.get('domains', ())

    if doc_type in ('Application', 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'corehq.apps.app_manager.views.download_index',
                    args=[domain, doc_id],
                ),
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'corehq.apps.app_manager.views.view_app',
                    args=[domain, doc_id],
                ),
            )
    elif doc_type in ('CommCareCase',):
        doc_info = DocInfo(
            display=doc['name'],
            type_display=_('Case'),
            link=reverse(
                'case_details',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('XFormInstance',):
        doc_info = DocInfo(
            type_display=_('Form'),
            link=reverse(
                'render_form_data',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=reverse(
                'edit_commcare_user',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=reverse(
                'user_account',
                args=[domain, doc_id],
            ),
        )
    else:
        doc_info = DocInfo()

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    return doc_info
Пример #38
0
 def get_choices_from_es_query(user_es):
     return [Choice(user_id, raw_username(username))
             for user_id, username in user_es.values_list('_id', 'username')]
Пример #39
0
 def _user_section(user):
     user_data = data_by_user.get(user._id, None)
     return {"username": raw_username(u.username), "msgs": list(_messages(user_data))}