Пример #1
0
def get_kc_profile_data(user_id):
    '''
    Retrieve all fields from the user's KC profile and  return them in a
    dictionary
    '''
    try:
        profile_model = _models.UserProfile.objects.get(user_id=user_id)
        # Use a dict instead of the object in case we enter the next exception.
        # The response will return a json.
        # We want the variable to have the same type in both cases.
        profile = profile_model.__dict__
    except _models.UserProfile.DoesNotExist:
        try:
            response = _trigger_kc_profile_creation(
                User.objects.get(pk=user_id))
            profile = response.json()
        except _KoboCatProfileException:
            logging.exception('Failed to create KoBoCAT user profile')
            return {}

    fields = [
        # Use a (kc_name, new_name) tuple to rename a field
        'name',
        'organization',
        ('home_page', 'organization_website'),
        ('description', 'bio'),
        ('phonenumber', 'phone_number'),
        'address',
        'city',
        'country',
        'require_auth',
        'twitter',
        'metadata',
    ]

    result = {}

    for field in fields:

        if isinstance(field, tuple):
            kc_name, field = field
        else:
            kc_name = field

        value = profile.get(kc_name)
        # When a field contains JSON (e.g. `metadata`), it gets loaded as a
        # `dict`. Convert it back to a string representation
        if isinstance(value, dict):
            value = json.dumps(value)
        result[field] = value
    return result
Пример #2
0
    def handle(self, *args, **options):
        if not settings.KOBOCAT_URL or not settings.KOBOCAT_INTERNAL_URL:
            raise ImproperlyConfigured(
                'Both KOBOCAT_URL and KOBOCAT_INTERNAL_URL must be '
                'configured before using this command')
        self._quiet = options.get('quiet')
        users = User.objects.all()
        # Do a basic query just to make sure the ReadOnlyXForm model is loaded
        if not ReadOnlyXForm.objects.exists():
            return
        self._print_str('%d total users' % users.count())
        # A specific user or everyone?
        if options.get('username'):
            users = User.objects.filter(username=options.get('username'))
        self._print_str('%d users selected' % users.count())
        # Only users who prefer KPI or all users?
        if not options.get('all_users'):
            users = users.filter(
                models.Q(formbuilderpreference__preferred_builder=
                         FormBuilderPreference.KPI) |
                models.Q(formbuilderpreference=None)  # KPI is the default now
            )
            self._print_str('%d of selected users prefer KPI' % users.count())

        # We'll be copying the date fields from KC, so don't auto-update them
        _set_auto_field_update(Asset, "date_created", False)
        _set_auto_field_update(Asset, "date_modified", False)

        for user in users:
            # Make sure the user has a token for access to KC's API
            Token.objects.get_or_create(user=user)

            existing_surveys = user.assets.filter(asset_type='survey')

            # Each asset that the user has already deployed to KC should have a
            # form uuid stored in its deployment data
            xform_uuids_to_asset_pks = {}
            for existing_survey in existing_surveys:
                dd = existing_survey._deployment_data
                try:
                    backend_response = dd['backend_response']
                except KeyError:
                    continue
                xform_uuids_to_asset_pks[backend_response['uuid']] = \
                    existing_survey.pk

            xforms = user.xforms.all()
            for xform in xforms:
                try:
                    with transaction.atomic():
                        if xform.uuid not in xform_uuids_to_asset_pks:
                            # This is an orphaned KC form. Build a new asset to
                            # match
                            asset = Asset(asset_type='survey', owner=user)
                            asset.name = _make_name_for_asset(asset, xform)
                        else:
                            asset = Asset.objects.get(
                                pk=xform_uuids_to_asset_pks[xform.uuid])

                        changes = []
                        try:
                            content_changed = _sync_form_content(
                                asset, xform, changes)
                            metadata_changed = _sync_form_metadata(
                                asset, xform, changes)
                        except SyncKCXFormsWarning as e:
                            error_information = [
                                'WARN', user.username, xform.id_string,
                                e.message
                            ]
                            self._print_tabular(*error_information)
                            continue

                        if content_changed or metadata_changed:
                            # preserve the original "asset.content"
                            asset.save(adjust_content=False)
                            # save a new version with standardized content
                            asset.save()
                            if content_changed:
                                asset._mark_latest_version_as_deployed()
                            self._print_tabular(','.join(changes),
                                                user.username, xform.id_string,
                                                asset.uid)
                        else:
                            self._print_tabular('NOOP', user.username,
                                                xform.id_string, asset.uid)
                except Exception as e:
                    error_information = [
                        'FAIL', user.username, xform.id_string,
                        repr(e)
                    ]
                    self._print_tabular(*error_information)
                    logging.exception(u'sync_kobocat_xforms: {}'.format(
                        u', '.join(error_information)))

        _set_auto_field_update(Asset, "date_created", True)
        _set_auto_field_update(Asset, "date_modified", True)
Пример #3
0
    def handle(self, *args, **options):
        if not settings.KOBOCAT_URL or not settings.KOBOCAT_INTERNAL_URL:
            raise ImproperlyConfigured(
                'Both KOBOCAT_URL and KOBOCAT_INTERNAL_URL must be '
                'configured before using this command')
        self._quiet = options.get('quiet')
        username = options.get('username')
        populate_xform_kpi_asset_uid = options.get(
            'populate_xform_kpi_asset_uid')
        sync_kobocat_form_media = options.get('sync_kobocat_form_media')
        verbosity = options.get('verbosity')
        users = User.objects.all()
        # Do a basic query just to make sure the KobocatXForm model is
        # loaded
        if not KobocatXForm.objects.exists():
            return
        self._print_str('%d total users' % users.count())
        # A specific user or everyone?
        if username:
            users = User.objects.filter(username=username)
        self._print_str('%d users selected' % users.count())

        # We'll be copying the date fields from KC, so don't auto-update them
        _set_auto_field_update(Asset, "date_created", False)
        _set_auto_field_update(Asset, "date_modified", False)

        for user in users:
            # Make sure the user has a token for access to KC's API
            Token.objects.get_or_create(user=user)

            existing_surveys = user.assets.filter(asset_type='survey')

            # Each asset that the user has already deployed to KC should have a
            # form uuid stored in its deployment data
            xform_uuids_to_asset_pks = {}
            for existing_survey in existing_surveys:
                if not existing_survey.has_deployment:
                    continue
                backend_response = existing_survey.deployment.backend_response
                xform_uuids_to_asset_pks[backend_response['uuid']] = \
                    existing_survey.pk

            # KobocatXForm has a foreign key on KobocatUser, not on User
            xforms = KobocatXForm.objects.filter(user_id=user.pk).all()
            for xform in xforms:
                try:
                    with transaction.atomic():
                        if xform.uuid not in xform_uuids_to_asset_pks:
                            # This is an orphaned KC form. Build a new asset to
                            # match
                            asset = Asset(asset_type='survey', owner=user)
                            asset.name = _make_name_for_asset(asset, xform)
                        else:
                            asset = Asset.objects.get(
                                pk=xform_uuids_to_asset_pks[xform.uuid])

                        changes = []
                        try:
                            content_changed = _sync_form_content(
                                asset, xform, changes)
                            metadata_changed = _sync_form_metadata(
                                asset, xform, changes)
                        except SyncKCXFormsWarning as e:
                            error_information = [
                                'WARN', user.username, xform.id_string,
                                e.message
                            ]
                            self._print_tabular(*error_information)
                            continue

                        if content_changed or metadata_changed:
                            # preserve the original "asset.content"
                            asset.save(adjust_content=False)
                            # save a new version with standardized content
                            asset.save()
                            if content_changed:
                                asset._mark_latest_version_as_deployed()
                            self._print_tabular(','.join(changes),
                                                user.username, xform.id_string,
                                                asset.uid)
                        else:
                            self._print_tabular('NOOP', user.username,
                                                xform.id_string, asset.uid)
                except Exception as e:
                    error_information = [
                        'FAIL', user.username, xform.id_string,
                        repr(e)
                    ]
                    self._print_tabular(*error_information)
                    logging.exception('sync_kobocat_xforms: {}'.format(
                        ', '.join(error_information)))

        _set_auto_field_update(Asset, "date_created", True)
        _set_auto_field_update(Asset, "date_modified", True)

        if populate_xform_kpi_asset_uid:
            call_command(
                'populate_kc_xform_kpi_asset_uid',
                username=username,
                verbosity=verbosity,
            )

        if sync_kobocat_form_media:
            call_command(
                'sync_kobocat_form_media',
                username=username,
                quiet=self._quiet,
                verbosity=verbosity,
            )