Пример #1
0
def _update_group_membership(request, domain, group_id):
    group = Group.get(group_id)
    if group.domain != domain:
        return HttpResponseForbidden()

    selected_users = request.POST.getlist('selected_ids')

    # check to make sure no users were deleted at time of making group
    users = iter_docs(CouchUser.get_db(), selected_users)
    safe_users = [
        CouchUser.wrap_correctly(user) for user in users
        if user['doc_type'] == 'CommCareUser' and user.get('domain') == domain
    ]
    safe_ids = [user.user_id for user in safe_users]
    users_added_ids, users_removed_ids = group.set_user_ids(safe_ids)
    _ensure_case_sharing_privilege(request, group)

    group.save()

    # re-fetch users to get fresh groups
    for updated_user_doc in iter_docs(CouchUser.get_db(), set.union(users_added_ids, users_removed_ids)):
        updated_user = CouchUser.wrap_correctly(updated_user_doc)
        log_user_groups_change(domain, request, updated_user)

    messages.success(request, _("Group %s updated!") % group.name)
    return HttpResponseRedirect(reverse("group_members", args=[domain, group_id]))
Пример #2
0
    def rows_for_domain(self, domain_obj):

        rows = []
        for user in get_all_user_rows(domain_obj.name,
                                      include_web_users=True,
                                      include_mobile_users=False,
                                      include_inactive=False,
                                      include_docs=True):
            user = CouchUser.wrap_correctly(user['doc'])
            domain_membership = user.get_domain_membership(domain_obj.name)
            last_accessed_domain = None
            if domain_membership:
                last_accessed_domain = domain_membership.last_accessed
            rows.append([
                user.username, user.full_name,
                user.role_label(domain_obj.name),
                self.format_date(user.last_login), last_accessed_domain,
                _('Active User')
            ] + self.domain_properties(domain_obj))
        for invite in Invitation.by_domain(domain_obj.name):
            rows.append([
                invite.email, 'N/A',
                invite.get_role_name(), 'N/A', 'N/A',
                _('Invited')
            ] + self.domain_properties(domain_obj))
        return rows
Пример #3
0
def update_users_at_locations(domain, location_ids, supply_point_ids,
                              ancestor_ids):
    """
    Update location fixtures for users given locations
    """
    from corehq.apps.users.models import CouchUser, update_fixture_status_for_users
    from corehq.apps.locations.dbaccessors import mobile_user_ids_at_locations
    from corehq.apps.fixtures.models import UserLookupTableType
    from dimagi.utils.couch.database import iter_docs

    # close supply point cases
    for supply_point_id in supply_point_ids:
        close_supply_point_case(domain, supply_point_id)

    # unassign users from locations
    unassign_user_ids = mobile_user_ids_at_locations(location_ids)
    for doc in iter_docs(CouchUser.get_db(), unassign_user_ids):
        user = CouchUser.wrap_correctly(doc)
        for location_id in location_ids:
            if location_id not in user.get_location_ids(domain):
                continue
            if user.is_web_user():
                user.unset_location_by_id(domain,
                                          location_id,
                                          fall_back_to_next=True)
            elif user.is_commcare_user():
                user.unset_location_by_id(location_id, fall_back_to_next=True)

    # update fixtures for users at ancestor locations
    user_ids = mobile_user_ids_at_locations(ancestor_ids)
    update_fixture_status_for_users(user_ids, UserLookupTableType.LOCATION)
Пример #4
0
def update_users_at_locations(domain, location_ids, supply_point_ids, ancestor_ids):
    """
    Update location fixtures for users given locations
    """
    from corehq.apps.users.models import CouchUser, update_fixture_status_for_users
    from corehq.apps.locations.dbaccessors import user_ids_at_locations
    from corehq.apps.fixtures.models import UserFixtureType
    from dimagi.utils.couch.database import iter_docs

    # close supply point cases
    for supply_point_id in supply_point_ids:
        close_supply_point_case(domain, supply_point_id)

    # unassign users from locations
    unassign_user_ids = user_ids_at_locations(location_ids)
    for doc in iter_docs(CouchUser.get_db(), unassign_user_ids):
        user = CouchUser.wrap_correctly(doc)
        for location_id in location_ids:
            if location_id not in user.get_location_ids(domain):
                continue
            if user.is_web_user():
                user.unset_location_by_id(domain, location_id, fall_back_to_next=True)
            elif user.is_commcare_user():
                user.unset_location_by_id(location_id, fall_back_to_next=True)

    # update fixtures for users at ancestor locations
    user_ids = user_ids_at_locations(ancestor_ids)
    update_fixture_status_for_users(user_ids, UserFixtureType.LOCATION)
Пример #5
0
def send_report(scheduled_report, user):
    if isinstance(user, dict):
        user = CouchUser.wrap_correctly(user)
    try:
        report = ScheduledReportFactory.get_report(scheduled_report.report_slug)
        body = report.get_response(user, scheduled_report.domain)
        email = user.get_email()
        if email:
            send_HTML_email("%s [%s]" % (report.title, scheduled_report.domain), email,
                        html2text(body), body)
        else:
            raise SMTPRecipientsRefused(None)
    except Http404:
        # Scenario: user has been removed from the domain that they have scheduled reports for.
        # Do a scheduled report cleanup
        user_id = unicode(user.get_id)
        domain = Domain.get_by_name(scheduled_report.domain)
        user_ids = [user.get_id for user in domain.all_users()]
        if user_id not in user_ids:
            # remove the offending user from the scheduled report
            scheduled_report.user_ids.remove(user_id)
            if len(scheduled_report.user_ids) == 0:
                # there are no users with appropriate permissions left in the scheduled report,
                # so remove it
                scheduled_report.delete()
            else:
                scheduled_report.save()
Пример #6
0
 def wrap_user(row):
     doc = row['doc']
     try:
         return CouchUser.wrap_correctly(doc)
     except Exception as e:
         logging.exception('trouble with user %s' % doc['_id'])
     return None
Пример #7
0
 def wrap_user(row):
     doc = row["doc"]
     try:
         return CouchUser.wrap_correctly(doc)
     except Exception as e:
         logging.exception("trouble with user %s" % doc["_id"])
     return None
Пример #8
0
def deactivate_users_at_location(location_id):
    from corehq.apps.locations.dbaccessors import mobile_user_ids_at_locations
    user_ids = mobile_user_ids_at_locations([location_id])
    for doc in iter_docs(CouchUser.get_db(), user_ids):
        user = CouchUser.wrap_correctly(doc)
        user.is_active = False
        user.save(spawn_task=True)
Пример #9
0
def refresh_es_for_profile_users(domain, profile_id):
    try:
        profile = CustomDataFieldsProfile.objects.get(
            id=profile_id, definition__domain=domain)
    except CustomDataFieldsProfile.DoesNotExist:
        return

    for user_doc in iter_docs(CouchUser.get_db(), profile.user_ids_assigned()):
        update_user_in_es(None, CouchUser.wrap_correctly(user_doc))
Пример #10
0
def get_all_users_by_location(domain, location_id):
    from corehq.apps.users.models import CouchUser
    results = CouchUser.get_db().view(
        'users_extra/users_by_location_id',
        startkey=[domain, location_id],
        endkey=[domain, location_id, {}],
        include_docs=True,
        reduce=False,
    )
    return (CouchUser.wrap_correctly(res['doc']) for res in results)
Пример #11
0
def get_all_users_by_location(domain, location_id):
    from corehq.apps.users.models import CouchUser
    results = CouchUser.get_db().view(
        'users_extra/users_by_location_id',
        startkey=[domain, location_id],
        endkey=[domain, location_id, {}],
        include_docs=True,
        reduce=False,
    )
    return (CouchUser.wrap_correctly(res['doc']) for res in results)
Пример #12
0
 def _format_user(self, user_json):
     user = CouchUser.wrap_correctly(user_json)
     return {
         'username': user.raw_username,
         'customFields': user.user_data,
         'first_name': user.first_name,
         'last_name': user.last_name,
         'phoneNumbers': user.phone_numbers,
         'user_id': user.user_id,
         'location': user.sql_location.to_json() if user.sql_location else None,
     }
Пример #13
0
        def wrap_user(row):
            try:
                doc = row['doc']
            except KeyError:
                logging.exception('trouble with user result %r' % row)
                return None

            try:
                return CouchUser.wrap_correctly(doc)
            except Exception:
                logging.exception('trouble with user %s' % doc['_id'])
                return None
Пример #14
0
 def rows_for_domain(self, domain_obj):
     rows = []
     for user in get_all_user_rows(domain_obj.name, include_web_users=True, include_mobile_users=False,
                                   include_inactive=False, include_docs=True):
         user = CouchUser.wrap_correctly(user['doc'])
         rows.append([
             user.full_name,
             user.username,
             user.role_label(domain_obj.name),
             self.format_date(user.last_login),
         ] + self.domain_properties(domain_obj))
     return rows
Пример #15
0
 def _format_user(self, user_json):
     user = CouchUser.wrap_correctly(user_json)
     formatted_user = {
         'username': user.raw_username,
         'customFields': user.user_data,
         'first_name': user.first_name,
         'last_name': user.last_name,
         'phoneNumbers': user.phone_numbers,
         'user_id': user.user_id,
         'location': user.sql_location.to_json() if user.sql_location else None,
     }
     return formatted_user
Пример #16
0
        def wrap_user(row):
            try:
                doc = row['doc']
            except KeyError:
                logging.exception('trouble with user result %r' % row)
                return None

            try:
                return CouchUser.wrap_correctly(doc)
            except Exception:
                logging.exception('trouble with user %s' % doc['_id'])
                return None
Пример #17
0
 def rows_for_domain(self, domain_obj):
     rows = []
     for user in get_all_user_rows(domain_obj.name, include_web_users=False, include_mobile_users=True,
                                   include_inactive=False, include_docs=True):
         user = CouchUser.wrap_correctly(user['doc'])
         rows.append([
             re.sub(r'@.*', '', user.username),
             user.full_name,
             self.format_date(user.created_on),
             self.format_date(user.reporting_metadata.last_sync_for_user.sync_date),
             self.format_date(user.reporting_metadata.last_submission_for_user.submission_date),
             user.reporting_metadata.last_submission_for_user.commcare_version or '',
         ] + self.domain_properties(domain_obj))
     return rows
Пример #18
0
 def handle(self, *args, **options):
     db = CouchUser.get_db()
     # This view includes users with base_doc == CouchUser-Deleted
     for res in db.view("users/by_default_phone", include_docs=True, reduce=False):
         doc = res['doc']
         # if this condition is met, the doc can't be wrapped
         if doc['email'] and not doc['email'].islower():
             print doc['email']
             doc['email'] = doc['email'].lower()
             try:
                 user = CouchUser.wrap_correctly(doc)
                 user.save()
             except:
                 print doc['_id'], "failed to save"
Пример #19
0
    def process_view(self, request, view_func, view_args, view_kwargs):
        if 'domain' in view_kwargs:
            request.domain = view_kwargs['domain']
        if 'org' in view_kwargs:
            request.org = view_kwargs['org']
        if request.user and hasattr(request.user, 'get_profile'):
            sessionid = request.COOKIES.get('sessionid', None)
            if sessionid:
                # roundabout way to keep doc_id based caching consistent.
                # get user doc_id from session_id
                MISSING = object()
                INTERRUPTED = object()
                try:
                    cached_user_doc_id = rcache.get(
                        SESSION_USER_KEY_PREFIX % sessionid, MISSING)
                except ConnectionInterrumped:
                    cached_user_doc_id = INTERRUPTED

                # disable session based couch user caching - to be enabled later.
                if cached_user_doc_id not in (MISSING, INTERRUPTED):
                    # cache hit
                    couch_user = CouchUser.wrap_correctly(
                        cache_core.cached_open_doc(CouchUser.get_db(),
                                                   cached_user_doc_id))
                else:
                    # cache miss, write to cache
                    couch_user = CouchUser.from_django_user(request.user)
                    if couch_user:
                        cache_core.do_cache_doc(couch_user.to_json())
                        if cached_user_doc_id is not INTERRUPTED:
                            rcache.set(SESSION_USER_KEY_PREFIX % sessionid,
                                       couch_user.get_id)
                request.couch_user = couch_user

            if 'domain' in view_kwargs:
                domain = request.domain
                if not request.couch_user:
                    couch_domain = Domain.view(
                        "domain/domains",
                        key=domain,
                        reduce=False,
                        include_docs=True,
                    ).one()
                    if couch_domain and couch_domain.is_public:
                        request.couch_user = PublicUser(domain)
                    else:
                        request.couch_user = InvalidUser()
                if request.couch_user:
                    request.couch_user.current_domain = domain
        return None
Пример #20
0
    def process_view(self, request, view_func, view_args, view_kwargs):
        if 'domain' in view_kwargs:
            request.domain = view_kwargs['domain']
        if 'org' in view_kwargs:
            request.org = view_kwargs['org']
        if request.user and hasattr(request.user, 'get_profile'):
            sessionid = request.COOKIES.get('sessionid', None)
            if sessionid:
                # roundabout way to keep doc_id based caching consistent.
                # get user doc_id from session_id
                MISSING = object()
                INTERRUPTED = object()
                try:
                    cached_user_doc_id = rcache.get(SESSION_USER_KEY_PREFIX % sessionid, MISSING)
                except ConnectionInterrumped:
                    cached_user_doc_id = INTERRUPTED

                # disable session based couch user caching - to be enabled later.
                if cached_user_doc_id not in (MISSING, INTERRUPTED):
                    # cache hit
                    couch_user = CouchUser.wrap_correctly(
                        cache_core.cached_open_doc(
                            CouchUser.get_db(), cached_user_doc_id
                        )
                    )
                else:
                    # cache miss, write to cache
                    couch_user = CouchUser.from_django_user(request.user)
                    if couch_user:
                        cache_core.do_cache_doc(couch_user.to_json())
                        if cached_user_doc_id is not INTERRUPTED:
                            rcache.set(SESSION_USER_KEY_PREFIX % sessionid, couch_user.get_id)
                request.couch_user = couch_user

            if 'domain' in view_kwargs:
                domain = request.domain
                if not request.couch_user:
                    couch_domain = Domain.view("domain/domains",
                        key=domain,
                        reduce=False,
                        include_docs=True,
                    ).one()
                    if couch_domain and couch_domain.is_public:
                        request.couch_user = PublicUser(domain)
                    else:
                        request.couch_user = InvalidUser()
                if request.couch_user:
                    request.couch_user.current_domain = domain
        return None
Пример #21
0
 def rows_for_domain(self, domain_obj):
     rows = []
     for user in get_all_user_rows(domain_obj.name,
                                   include_web_users=True,
                                   include_mobile_users=False,
                                   include_inactive=False,
                                   include_docs=True):
         user = CouchUser.wrap_correctly(user['doc'])
         rows.append([
             user.full_name,
             user.username,
             user.role_label(domain_obj.name),
             self.format_date(user.last_login),
         ] + self.domain_properties(domain_obj))
     return rows
Пример #22
0
def _unassign_users_from_location(domain, location_id):
    """
    Unset location for all users assigned to that location.
    """
    from corehq.apps.locations.dbaccessors import user_ids_at_locations
    from corehq.apps.users.models import CouchUser
    from dimagi.utils.couch.database import iter_docs

    user_ids = user_ids_at_locations([location_id])
    for doc in iter_docs(CouchUser.get_db(), user_ids):
        user = CouchUser.wrap_correctly(doc)
        if user.is_web_user():
            user.unset_location_by_id(domain, location_id, fall_back_to_next=True)
        elif user.is_commcare_user():
            user.unset_location_by_id(location_id, fall_back_to_next=True)
Пример #23
0
def make_web_user_dict(user, domain):
    user = CouchUser.wrap_correctly(user['doc'])
    domain_membership = user.get_domain_membership(domain)
    role_name = get_user_role_name(domain_membership)
    return {
        'username': user.username,
        'first_name': user.first_name,
        'last_name': user.last_name,
        'email': user.email,
        'role': role_name,
        'status': ugettext('Active User'),
        'last_access_date (read only)': domain_membership.last_accessed,
        'last_login (read only)': user.last_login,
        'remove': '',
    }
Пример #24
0
def _unassign_users_from_location(domain, location_id):
    """
    Unset location for all users assigned to that location.
    """
    from corehq.apps.locations.dbaccessors import user_ids_at_locations
    from corehq.apps.users.models import CouchUser
    from dimagi.utils.couch.database import iter_docs

    user_ids = user_ids_at_locations([location_id])
    for doc in iter_docs(CouchUser.get_db(), user_ids):
        user = CouchUser.wrap_correctly(doc)
        if user.is_web_user():
            user.unset_location_by_id(domain, location_id, fall_back_to_next=True)
        elif user.is_commcare_user():
            user.unset_location_by_id(location_id, fall_back_to_next=True)
Пример #25
0
    def build_table(self):

        for domain in Domain.get_all():
            logger.info("Building MALT for {}".format(domain.name))

            for monthspan in self.monthspan_list:
                all_users = get_all_user_rows(domain.name, include_inactive=False, include_docs=True)
                for users in chunked(all_users, 1000):
                    users_by_id = {user['id']: CouchUser.wrap_correctly(user['doc']) for user in users}
                    try:
                        malt_rows_to_save = self._get_malt_row_dicts(domain.name, monthspan, users_by_id)
                    except Exception as ex:
                        logger.error("Failed to get rows for domain {name}. Exception is {ex}".format
                                    (name=domain.name, ex=str(ex)), exc_info=True)
                    if malt_rows_to_save:
                        self._save_to_db(malt_rows_to_save, domain._id)
Пример #26
0
 def _format_user(self, user_json):
     user = CouchUser.wrap_correctly(user_json)
     formatted_user = {
         'username': user.raw_username,
         'customFields': user.user_data,
         'first_name': user.first_name,
         'last_name': user.last_name,
         'phoneNumbers': user.phone_numbers,
         'user_id': user.user_id,
         'location':
         user.sql_location.to_json() if user.sql_location else None,
     }
     if toggles.ENIKSHAY.enabled(self.domain):
         formatted_user.update(
             {'enikshay': get_enikshay_login_as_context(user)})
     return formatted_user
Пример #27
0
    def build_table(self):

        for domain in Domain.get_all():
            logger.info("Building MALT for {}".format(domain.name))

            for monthspan in self.monthspan_list:
                all_users = get_all_user_rows(domain.name, include_inactive=False, include_docs=True)
                for users in chunked(all_users, 1000):
                    users_by_id = {user['id']: CouchUser.wrap_correctly(user['doc']) for user in users}
                    try:
                        malt_rows_to_save = self._get_malt_row_dicts(domain.name, monthspan, users_by_id)
                    except Exception as ex:
                        logger.error("Failed to get rows for domain {name}. Exception is {ex}".format
                                    (name=domain.name, ex=str(ex)), exc_info=True)
                    if malt_rows_to_save:
                        self._save_to_db(malt_rows_to_save, domain._id)
Пример #28
0
    def get_users_without_permission(self, start_date, end_date):
        usernames = self.get_usernames(start_date, end_date)

        print(f'Filter {len(usernames)} users according to permission')
        permission_name = get_permission_name(Permissions.view_report)
        users_without_permission = []
        for chunk in with_progress_bar(chunked(usernames, 100),
                                       prefix='\tProcessing'):
            users = [
                CouchUser.wrap_correctly(doc)
                for doc in get_user_docs_by_username(chunk)
            ]
            for user in users:
                if not user.has_permission(
                        DASHBOARD_DOMAIN, permission_name, data=PERMISSION):
                    users_without_permission.append(user.username)

        return users_without_permission
Пример #29
0
 def rows_for_domain(self, domain_obj):
     rows = []
     for user in get_all_user_rows(domain_obj.name,
                                   include_web_users=False,
                                   include_mobile_users=True,
                                   include_inactive=False,
                                   include_docs=True):
         user = CouchUser.wrap_correctly(user['doc'])
         rows.append([
             re.sub(r'@.*', '', user.username), user.full_name, user.email,
             self.format_date(user.created_on),
             self.format_date(
                 user.reporting_metadata.last_sync_for_user.sync_date),
             self.format_date(user.reporting_metadata.
                              last_submission_for_user.submission_date),
             user.reporting_metadata.last_submission_for_user.
             commcare_version or '', user.user_id
         ] + self.domain_properties(domain_obj))
     return rows
Пример #30
0
def transform_user_for_elasticsearch(doc_dict):
    doc = copy.deepcopy(doc_dict)
    if doc['doc_type'] == 'CommCareUser' and '@' in doc['username']:
        doc['base_username'] = doc['username'].split("@")[0]
    else:
        doc['base_username'] = doc['username']

    results = get_group_id_name_map_by_user(doc['_id'])
    doc['__group_ids'] = [res.id for res in results]
    doc['__group_names'] = [res.name for res in results]
    doc['user_data_es'] = []
    if 'user_data' in doc:
        from corehq.apps.users.models import CouchUser
        user = CouchUser.wrap_correctly(doc)
        for key, value in user.metadata.items():
            doc['user_data_es'].append({
                'key': key,
                'value': value,
            })
    return doc
Пример #31
0
 def _format_user(self, user_json, include_location=False):
     user = CouchUser.wrap_correctly(user_json)
     user_data = {}
     for field in self.custom_data.fields:
         user_data[field.slug] = user.user_data.get(field.slug, '')
     return {
         'username': user.raw_username,
         'customFields': user_data,
         'first_name': user.first_name,
         'last_name': user.last_name,
         'phoneNumbers': user.phone_numbers,
         'user_id': user.user_id,
         'location': user.sql_location.to_json() if include_location and user.sql_location else None,
         'mark_activated': False,
         'mark_deactivated': False,
         'dateRegistered': user.created_on.strftime(USER_DATE_FORMAT) if user.created_on else '',
         'editUrl': reverse(EditCommCareUserView.urlname, args=[self.domain, user.user_id]),
         'deactivateUrl': "#",
         'actionText': _("Deactivate") if user.is_active else _("Activate"),
         'action': 'deactivate' if user.is_active else 'activate',
     }
Пример #32
0
    def rows_for_domain(self, domain_obj):
        def _get_role_name(role):
            if role:
                if role == 'admin':
                    return role
                else:
                    role_id = role[len('user-role:'):]
                    try:
                        return UserRole.get(role_id).name
                    except ResourceNotFound:
                        return _('Unknown Role')
            else:
                return 'N/A'

        rows = []
        for user in get_all_user_rows(domain_obj.name,
                                      include_web_users=True,
                                      include_mobile_users=False,
                                      include_inactive=False,
                                      include_docs=True):
            user = CouchUser.wrap_correctly(user['doc'])
            domain_membership = user.get_domain_membership(domain_obj.name)
            last_accessed_domain = None
            if domain_membership:
                last_accessed_domain = domain_membership.last_accessed
            rows.append([
                user.username, user.full_name,
                user.role_label(domain_obj.name),
                self.format_date(user.last_login), last_accessed_domain,
                _('Active User')
            ] + self.domain_properties(domain_obj))
        for invite in Invitation.by_domain(domain_obj.name):
            rows.append([
                invite.email, 'N/A',
                _get_role_name(invite.role), 'N/A', 'N/A',
                _('Invited')
            ] + self.domain_properties(domain_obj))
        return rows
Пример #33
0
def generate_malt(monthspans, domains=None):
    """
    Populates MALTRow SQL table with app submission data for a given list of months
    :param monthspans: list of DateSpan objects
    :param domains: list of domain names
    """
    domain_names = domains or Domain.get_all_names()
    for domain_name in domain_names:
        last_submission_date = get_last_form_submission_received(domain_name)
        last_malt_run_dates_by_month = _get_last_run_date_for_malt_by_month(domain_name, monthspans)
        for monthspan in monthspans:
            # if the MALTRow last_run_date is none, use the start date of the month
            last_malt_run_date = last_malt_run_dates_by_month.get(monthspan.startdate.date(), monthspan.startdate)
            if last_submission_date and last_submission_date >= last_malt_run_date:
                # use this date to populate last_run_date for all MALTRows with this domain and month
                run_date = datetime.datetime.utcnow()
                logger.info(f"Building MALT for {domain_name} for {monthspan} up to {run_date}")
                all_users = get_all_user_rows(domain_name, include_inactive=False, include_docs=True)
                for users in chunked(all_users, 1000):
                    users_by_id = {user['id']: CouchUser.wrap_correctly(user['doc']) for user in users}
                    malt_row_dicts = _get_malt_row_dicts(domain_name, monthspan, users_by_id, run_date)
                    if malt_row_dicts:
                        _save_malt_row_dicts_to_db(malt_row_dicts)
Пример #34
0
 def _clear_cache(doc):
     user = CouchUser.wrap_correctly(doc, allow_deleted_doc_types=True)
     user.clear_quickcache_for_user()
Пример #35
0
 def _clear_cache(doc):
     user = CouchUser.wrap_correctly(doc, allow_deleted_doc_types=True)
     user.clear_quickcache_for_user()