class ActivityResource(ModelResource):

    iati_identifier = fields.CharField('id')
    reporting_organisation = fields.ForeignKey(
        ActivityViewOrganisationResource,
        'reporting_organisation',
        full=True,
        null=True)
    participating_organisations = fields.ToManyField(
        ActivityViewOrganisationResource,
        'participating_organisation',
        full=True,
        null=True)
    activity_status = fields.ForeignKey(ActivityViewActivityStatusResource,
                                        'activity_status',
                                        full=True,
                                        null=True)
    recipient_country = fields.ToManyField(OnlyCountryResource,
                                           'recipient_country',
                                           full=True,
                                           null=True)
    recipient_region = fields.ToManyField(OnlyRegionResource,
                                          'recipient_region',
                                          full=True,
                                          null=True)
    sectors = fields.ToManyField(ActivityViewSectorsResource,
                                 'sector',
                                 full=True,
                                 null=True)
    titles = fields.ToManyField(TitleResource,
                                'title_set',
                                full=True,
                                null=True)
    descriptions = fields.ToManyField(DescriptionResource,
                                      'description_set',
                                      full=True,
                                      null=True)
    collaboration_type = fields.ForeignKey(
        ActivityViewCollaborationTypeResource,
        attribute='collaboration_type',
        full=True,
        null=True)
    default_flow_type = fields.ForeignKey(ActivityViewFlowTypeResource,
                                          attribute='default_flow_type',
                                          full=True,
                                          null=True)
    default_finance_type = fields.ForeignKey(FinanceTypeResource,
                                             attribute='default_finance_type',
                                             full=True,
                                             null=True)
    default_aid_type = fields.ForeignKey(ActivityViewAidTypeResource,
                                         attribute='default_aid_type',
                                         full=True,
                                         null=True)
    default_tied_status_type = fields.ForeignKey(
        ActivityViewTiedStatusResource,
        attribute='default_tied_status',
        full=True,
        null=True)
    activity_budgets = fields.ToManyField(ActivityBudgetResource,
                                          'budget_set',
                                          full=True,
                                          null=True)
    activity_transactions = fields.ToManyField(ActivityViewTransactionResource,
                                               'transaction_set',
                                               full=True,
                                               null=True)
    documents = fields.ToManyField(DocumentResource,
                                   'document_link_set',
                                   full=True,
                                   null=True)
    date_updated = fields.DateTimeField('last_updated_datetime', null=True)

    class Meta:
        queryset = Activity.objects.all()
        resource_name = 'activities'
        max_limit = 100
        serializer = Serializer(formats=['xml', 'json'])
        excludes = ['date_created', 'id']
        ordering = [
            'start_actual', 'start_planned', 'end_actual', 'end_planned',
            'activity_sectors', 'statistics', 'last_updated_datetime'
        ]
        filtering = {'iati_identifier': ALL}
        cache = NoTransformCache()

    def apply_filters(self, request, applicable_filters):
        base_object_list = super(ActivityResource,
                                 self).apply_filters(request,
                                                     applicable_filters)
        query = request.GET.get('query', None)
        sectors = request.GET.get('sectors', None)
        regions = request.GET.get('regions', None)
        countries = request.GET.get('countries', None)
        organisations = request.GET.get('organisations', None)
        filters = {}
        if sectors:
            sectors = sectors.replace('|', ',').split(',')
            filters.update(dict(activity_sector__sector__code__in=sectors))
        if regions:
            regions = regions.replace('|', ',').split(',')
            filters.update(
                dict(activity_recipient_region__region__code__in=regions))
        if countries:
            countries = countries.replace('|', ',').split(',')
            filters.update(
                dict(activity_recipient_country__country__code__in=countries))
        if organisations:
            organisations = organisations.replace('|', ',').split(',')
            filters.update(
                dict(reporting_organisation__code__in=organisations))
        if query:

            qset = (Q(activity_recipient_country__country__name__in=query,
                      **filters) | Q(title__title__icontains=query, **filters)
                    | Q(description__text__icontains=query, **filters))

            return base_object_list.filter(qset).distinct()
        return base_object_list.filter(**filters).distinct()
Esempio n. 2
0
class ConfigurableReportDataResource(HqBaseResource, DomainSpecificResourceMixin):
    """
    A resource that replicates the behavior of the ajax part of the
    ConfigurableReportView view.
    """
    data = fields.ListField(attribute="data", readonly=True)
    columns = fields.ListField(attribute="columns", readonly=True)
    total_records = fields.IntegerField(attribute="total_records", readonly=True)
    next_page = fields.CharField(attribute="next_page", readonly=True)

    LIMIT_DEFAULT = 50
    LIMIT_MAX = 50

    def _get_start_param(self, bundle):
        try:
            start = int(bundle.request.GET.get('offset', 0))
            if start < 0:
                raise ValueError
        except (ValueError, TypeError):
            raise BadRequest("start must be a positive integer.")
        return start

    def _get_limit_param(self, bundle):
        try:
            limit = int(bundle.request.GET.get('limit', self.LIMIT_DEFAULT))
            if limit < 0:
                raise ValueError
        except (ValueError, TypeError):
            raise BadRequest("limit must be a positive integer.")

        if limit > self.LIMIT_MAX:
            raise BadRequest("Limit may not exceed {}.".format(self.LIMIT_MAX))
        return limit

    def _get_next_page(self, domain, id_, start, limit, total_records, get_query_dict):
        if total_records > start + limit:
            start += limit
            new_get_params = get_query_dict.copy()
            new_get_params["offset"] = start
            # limit has not changed, but it may not have been present in get params before.
            new_get_params["limit"] = limit
            return reverse('api_dispatch_detail', kwargs=dict(
                api_name=self._meta.api_name,
                resource_name=self._meta.resource_name,
                domain=domain,
                pk=id_,
            )) + "?" + new_get_params.urlencode()
        else:
            return ""

    def _get_report_data(self, report_config, domain, start, limit, get_params):
        report = ConfigurableReportDataSource.from_spec(report_config, include_prefilters=True)

        string_type_params = [
            filter.name
            for filter in report_config.ui_filters
            if getattr(filter, 'datatype', 'string') == "string"
        ]
        filter_values = get_filter_values(
            report_config.ui_filters,
            query_dict_to_dict(get_params, domain, string_type_params)
        )
        report.set_filter_values(filter_values)

        page = list(report.get_data(start=start, limit=limit))

        columns = []
        for column in report.columns:
            simple_column = {
                "header": column.header,
                "slug": column.slug,
            }
            if isinstance(column, UCRExpandDatabaseSubcolumn):
                simple_column['expand_column_value'] = column.expand_value
            columns.append(simple_column)

        total_records = report.get_total_records()
        return page, columns, total_records

    def obj_get(self, bundle, **kwargs):
        domain = kwargs['domain']
        pk = kwargs['pk']
        start = self._get_start_param(bundle)
        limit = self._get_limit_param(bundle)

        report_config = self._get_report_configuration(pk, domain)
        page, columns, total_records = self._get_report_data(
            report_config, domain, start, limit, bundle.request.GET)

        return ConfigurableReportData(
            data=page,
            columns=columns,
            total_records=total_records,
            id=report_config._id,
            domain=domain,
            get_params=bundle.request.GET,
            next_page=self._get_next_page(
                domain,
                report_config._id,
                start,
                limit,
                total_records,
                bundle.request.GET,
            )
        )

    def _get_report_configuration(self, id_, domain):
        """
        Fetch the required ReportConfiguration object
        :param id_: The id of the ReportConfiguration
        :param domain: The domain of the ReportConfiguration
        :return: A ReportConfiguration
        """
        try:
            if report_config_id_is_static(id_):
                return StaticReportConfiguration.by_id(id_, domain=domain)
            else:
                return get_document_or_not_found(ReportConfiguration, domain, id_)
        except DocumentNotFound:
            raise NotFound

    def detail_uri_kwargs(self, bundle_or_obj):
        return {
            'domain': get_obj(bundle_or_obj).domain,
            'pk': get_obj(bundle_or_obj).id,
        }

    def get_resource_uri(self, bundle_or_obj=None, url_name='api_dispatch_list'):
        uri = super(ConfigurableReportDataResource, self).get_resource_uri(bundle_or_obj, url_name)
        if bundle_or_obj is not None and uri:
            get_params = get_obj(bundle_or_obj).get_params.copy()
            if "offset" not in get_params:
                get_params["offset"] = 0
            if "limit" not in get_params:
                get_params["limit"] = self.LIMIT_DEFAULT
            uri += "?{}".format(get_params.urlencode())
        return uri

    class Meta(CustomResourceMeta):
        authentication = RequirePermissionAuthentication(Permissions.view_reports, allow_session_auth=True)
        list_allowed_methods = []
        detail_allowed_methods = ["get"]
Esempio n. 3
0
class TemporaryFileResource(ModelResource):
    uuid = fields.CharField(attribute='uuid', readonly=True)

    class Meta:
        queryset = TemporaryFile.objects.all()
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get', 'delete']
        resource_name = 'temporary-files'
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        authorization = DjangoAuthorization()
        fields = ['uuid', 'date', 'filename']
        detail_uri_name = 'uuid'
        serializer = Serializer(formats=['json', 'jsonp'])

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/(?P<%s>.*?)/describe%s$" %
                (self._meta.resource_name, self._meta.detail_uri_name,
                 trailing_slash()),
                self.wrap_view('describe'),
                name='temporary_file_describe'),
            url(r"^(?P<resource_name>%s)/(?P<%s>.*?)/(?P<dataset_id>[\w\-@\._]+)/deploy%s$"
                % (self._meta.resource_name, self._meta.detail_uri_name,
                   trailing_slash()),
                self.wrap_view('deploy'),
                name='temporary_file_deploy'),
            url(r"^(?P<resource_name>%s)/(?P<%s>.*?)/(?P<dataset_id>[\w\-@\._]+)/append%s$"
                % (self._meta.resource_name, self._meta.detail_uri_name,
                   trailing_slash()),
                self.wrap_view('append'),
                name='temporary_file_append')
        ]

    def populate_point_data(self, dataset_id, csv_info):
        srid = csv_info['srid']
        x_column = csv_info['xColumn']
        y_column = csv_info['yColumn']
        populate_point_data(dataset_id, srid, x_column, y_column)

    def describe(self, request, **kwargs):
        """
        Describe, located at the ``{tablo-server}/api/v1/temporary-files/{uuid}/describe`` endpoint, will describe
        the uploaded CSV file. This allows you to know the column names and data types that were found within the
        file.

        :return:
            A JSON object in the following format:

            .. code-block:: json

                {
                    "fieldNames": ["field one", "field two", "latitude", "longitude"],
                    "dataTypes": ["String", "Integer", "Decimal", "Decimal"],
                    "optionalFields": ["field one"],
                    "xColumn": "longitude",
                    "yColumn": "latitude",
                    "filename": "uploaded.csv"
                }

            **fieldNames**
                A list of field (column) names within the CSV

            **dataTypes**
                A list of data types for each of the columns. The index of this list will match the index of the
                fieldNames list.

            **optionalFields**
                A list of fields that had empty values, and are taken to be optional.

            **xColumn**
                The best guess at which column contains X spatial coordinates.

            **yColumn**
                The best guess at which column contains Y spatial coordinates.

            **filename**
                The name of the file being described

        """
        self.is_authenticated(request)

        bundle = self.build_bundle(request=request)
        obj = self.obj_get(bundle, **self.remove_api_resource_names(kwargs))

        try:
            if obj.extension == 'csv':
                csv_file_name = obj.file.name
            else:
                raise InvalidFileError('Unsupported file format',
                                       extension=obj.extension)

        except InvalidFileError as e:
            raise ImmediateHttpResponse(
                HttpBadRequest(content=json.dumps(
                    derive_error_response_data(e, code=BAD_DATA)),
                               content_type='application/json'))

        csv_info = json.loads(request.POST.get('csv_info') or '{}') or None

        prepared_csv = prepare_csv_rows(obj.file, csv_info)
        row_set = prepared_csv['row_set']

        if not len(row_set):
            raise ImmediateHttpResponse(
                HttpBadRequest(content=json.dumps(
                    derive_error_response_data(InvalidFileError(
                        'File is empty', lines=0),
                                               code=BAD_DATA)),
                               content_type='application/json'))

        bundle.data['fieldNames'] = row_set.columns.to_list()
        bundle.data['dataTypes'] = prepared_csv['data_types']
        bundle.data['optionalFields'] = prepared_csv['optional_fields']

        x_field, y_field = prepared_csv['coord_fields']
        if x_field and y_field:
            bundle.data['xColumn'] = x_field
            bundle.data['yColumn'] = y_field

        bundle.data.update({'file_name': csv_file_name})

        return self.create_response(request, bundle)

    def deploy(self, request, **kwargs):
        """
            The deploy endpoint, at ``{tablo_server}/api/v1/temporary-files/{uuid}/{dataset_id}/deploy/`` deploys
            the file specified by {uuid} into a database table named after the {dataset_id}. The {dataset_id} must
            be unique for the instance of Tablo.

            With the deploy endpoint, this is the start of what Tablo considers an import. The data will be
            temporarily stored in an import table until the finalize endpoint for the dataset_id is called.

            POST messages to the deploy endpoint should include the following data:

            **csv_info**
                Information about the CSV file. This is generally that information obtained through the
                describe endpoint, but can be modified to send additional information or modify it.
            **fields**
                A list of field JSON objects in the following format:

                .. code-block:: json

                    {
                        "name": "field_name",
                        "type": "text",
                        "required": true
                    }

                The value can be specified if the field is a constant value throughout the table. This can
                be use for adding audit information.

            :return:
                An empty HTTP 200 response if the deploy was successful. An error response if otherwise.
        """
        self.is_authenticated(request)

        try:
            dataset_id = kwargs.pop('dataset_id', None)

            bundle = self.build_bundle(request=request)
            obj = self.obj_get(bundle,
                               **self.remove_api_resource_names(kwargs))

            csv_info = json.loads(request.POST.get('csv_info'))
            additional_fields = json.loads(request.POST.get('fields'))

            prepared_csv = prepare_csv_rows(obj.file, csv_info)

            table_name = create_database_table(
                prepared_csv['row_set'],
                csv_info,
                dataset_id,
                additional_fields=additional_fields)
            add_geometry_column(dataset_id)
            self.populate_point_data(dataset_id, csv_info)

            bundle.data['table_name'] = table_name

            obj.delete(
            )  # Temporary file has been moved to database, safe to delete

        except Exception as e:
            logger.exception(e)

            raise ImmediateHttpResponse(
                HttpBadRequest(content=json.dumps(
                    derive_error_response_data(e)),
                               content_type='application/json'))

        return self.create_response(request, bundle)

    def append(self, request, **kwargs):
        self.is_authenticated(request)

        try:
            dataset_id = kwargs.pop('dataset_id', None)

            bundle = self.build_bundle(request=request)
            obj = self.obj_get(bundle,
                               **self.remove_api_resource_names(kwargs))

            csv_info = json.loads(request.POST.get('csv_info'))
            additional_fields = json.loads(request.POST.get('fields'))

            prepared_csv = prepare_csv_rows(obj.file, csv_info)
            table_name = create_database_table(
                prepared_csv['row_set'],
                csv_info,
                dataset_id,
                append=True,
                additional_fields=additional_fields)
            self.populate_point_data(dataset_id, csv_info)

            bundle.data['table_name'] = table_name

            obj.delete(
            )  # Temporary file has been moved to database, safe to delete

        except Exception as e:
            logger.exception(e)

            raise ImmediateHttpResponse(
                HttpBadRequest(content=json.dumps(
                    derive_error_response_data(e)),
                               content_type='application/json'))

        return self.create_response(request, bundle)
Esempio n. 4
0
class DocumentResource(DeprecatedModelResourceWithFieldsFilter):
    citation = fields.ForeignKey(CitationResource, 'citation', full=True)
    court = fields.ForeignKey(JurisdictionResource, 'docket__court')
    html = fields.CharField(
        attribute='html',
        use_in='detail',
        null=True,
        help_text='HTML of the document, if available in the original')
    html_lawbox = fields.CharField(attribute='html_lawbox',
                                   use_in='detail',
                                   null=True,
                                   help_text='HTML of lawbox documents')
    html_with_citations = fields.CharField(
        attribute='html_with_citations',
        use_in='detail',
        null=True,
        help_text="HTML of the document with citation links and other "
        "post-processed markup added",
    )
    plain_text = fields.CharField(
        attribute='plain_text',
        use_in='detail',
        null=True,
        help_text="Plain text of the document after extraction using "
        "pdftotext, wpd2txt, etc.",
    )
    date_modified = fields.DateTimeField(
        attribute='date_modified',
        null=True,
        default='1750-01-01T00:00:00Z',
        help_text='The last moment when the item was modified. A value  in '
        'year 1750 indicates the value is unknown')

    class Meta:
        authentication = authentication.MultiAuthentication(
            BasicAuthenticationWithUser(realm="courtlistener.com"),
            authentication.SessionAuthentication())
        throttle = PerUserCacheThrottle(throttle_at=1000)
        resource_name = 'opinion'
        queryset = Document.objects.all().select_related(
            'docket__court__pk', 'citation')
        max_limit = 20
        allowed_methods = ['get']
        include_absolute_url = True
        excludes = [
            'is_stub_document',
            'cases_cited',
            'supreme_court_db_id',
        ]
        filtering = {
            'id': ('exact', ),
            'time_retrieved': good_time_filters,
            'date_modified': good_time_filters,
            'date_filed': good_date_filters,
            'sha1': ('exact', ),
            'court': ('exact', ),
            'citation': ALL,
            'citation_count': numerical_filters,
            'precedential_status': ('exact', 'in'),
            'date_blocked': good_date_filters,
            'blocked': ALL,
            'extracted_by_ocr': ALL,
        }
        ordering = [
            'time_retrieved', 'date_modified', 'date_filed', 'date_blocked'
        ]
Esempio n. 5
0
class SummaryFeedByCountryCodeResource(Resource):
    id = fields.CharField(attribute='id')
    freq = fields.IntegerField(attribute='freq')
    city = fields.CharField(attribute='city', default=None)
    longlat = fields.ListField(attribute='longlat')

    class Meta:
        resource_name = 'summary-country'
        object_class = SummaryFeed

    # adapted this from ModelResource
    # def get_resource_uri(self, bundle_or_obj=None):
    #     kwargs = {
    #         'resource_name': self._meta.resource_name,
    #     }
    #     if isinstance(bundle_or_obj, Bundle):
    #         kwargs['pk'] = bundle_or_obj.obj.id # pk is referenced in ModelResource
    #     else:
    #         kwargs['pk'] = bundle_or_obj.id
    #     if self._meta.api_name is not None:
    #         kwargs['api_name'] = self._meta.api_name
    #     return self._build_reverse_url('api_dispatch_detail', kwargs = kwargs)

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/(?P<countrycode>[\w\d_.-]+)/$" %
                self._meta.resource_name,
                self.wrap_view('dispatch_detail'),
                name="api_dispatch_detail"),
        ]

    def get_object_list(self, request):
        return []

    def obj_get_list(self, request=None, **kwargs):
        # outer get of object list... this calls get_object_list and
        # could be a point at which additional filtering may be applied
        return self.get_object_list(request)

    def obj_get(self, request=None, **kwargs):
        global resultsByCountry

        countryCode = kwargs['countrycode'].upper()
        resultsByCountry.clear()

        #countryCode = request.GET.get('countryCode', '')
        #print 'countryCode: ' + countryCode

        cursor = connection.cursor()
        print 'test - 1'
        cursor.execute(
            'SELECT COUNT(*) as freq, longitude, latitude, city FROM web_feed WHERE country = %s GROUP BY longitude, latitude ORDER BY freq DESC',
            [countryCode])
        print 'test - 2'
        rows = cursor.fetchall()
        print 'test - 3'
        for r in rows:
            print 'test - 4'
            #print 'args: ',r[0], [r[1], r[2]], r[3]
            s = SummaryFeed()
            s.freq = r[0]
            s.longlat = [r[1], r[2]]
            if r[3]:
                s.city = r[3]
            else:
                s.city = '<Unknown>'
            s.id = '%f_%f' % (r[1], r[2])
            resultsByCountry[s.id] = s

        print 'test - 5'
        return resultsByCountry.values()
class FilesystemResource(MetricResource, ConfParamResource):
    """
    A Lustre file system, associated with exactly one MGT and consisting of
    one or mode MDTs and one or more OSTs.

    When using POST to create a file system, specify volumes to use like this:
    ::

        {osts: [{volume_id: 22}],
        mdt: {volume_id: 23},
        mgt: {volume_id: 24}}

    To create a file system using an existing MGT instead of creating a new
    MGT, set the `id` attribute instead of the `volume_id` attribute for
    that target (i.e. `mgt: {id: 123}`).

    Note: A Lustre file system is owned by an MGT, and the ``name`` of the file system
    is unique within that MGT.  Do not use ``name`` as a globally unique identifier
    for a file system in your application.
    """

    bytes_free = fields.IntegerField()
    bytes_total = fields.IntegerField()
    files_free = fields.IntegerField()
    files_total = fields.IntegerField()
    client_count = fields.IntegerField(
        help_text=
        "Number of Lustre clients which are connected to this file system")

    mount_command = fields.CharField(
        null=True,
        help_text='Example command for\
            mounting this file system on a Lustre client, e.g. "mount -t lustre 192.168.0.1:/testfs /mnt/testfs"',
    )

    mount_path = fields.CharField(
        null=True,
        help_text='Path for mounting the file system\
            on a Lustre client, e.g. "192.168.0.1:/testfs"',
    )

    osts = fields.ToManyField(
        "chroma_api.target.TargetResource",
        null=True,
        attribute=lambda bundle: ManagedOst.objects.filter(filesystem=bundle.
                                                           obj),
        help_text="List of OSTs which belong to this file system",
    )
    mdts = fields.ToManyField(
        "chroma_api.target.TargetResource",
        null=True,
        full=True,
        attribute=lambda bundle: ManagedMdt.objects.filter(filesystem=bundle.
                                                           obj),
        help_text=
        "List of MDTs in this file system, should be at least 1 unless the "
        "file system is in the process of being deleted",
    )
    mgt = fields.ToOneField(
        "chroma_api.target.TargetResource",
        attribute="mgs",
        full=True,
        help_text="The MGT on which this file system is registered",
    )

    def _get_stat_simple(self, bundle, klass, stat_name, factor=1.0):
        try:
            return bundle.obj.metrics.fetch_last(
                klass, fetch_metrics=[stat_name])[1][stat_name] * factor
        except (KeyError, IndexError, TypeError):
            return None

    def dehydrate_mount_path(self, bundle):
        return bundle.obj.mount_path()

    def dehydrate_mount_command(self, bundle):
        path = self.dehydrate_mount_path(bundle)
        if path:
            return "mount -t lustre %s /mnt/%s" % (path, bundle.obj.name)
        else:
            return None

    def dehydrate_bytes_free(self, bundle):
        return self._get_stat_simple(bundle, ManagedOst, "kbytesfree", 1024)

    def dehydrate_bytes_total(self, bundle):
        return self._get_stat_simple(bundle, ManagedOst, "kbytestotal", 1024)

    def dehydrate_files_free(self, bundle):
        return self._get_stat_simple(bundle, ManagedMdt, "filesfree")

    def dehydrate_files_total(self, bundle):
        return self._get_stat_simple(bundle, ManagedMdt, "filestotal")

    def get_hsm_control_params(self, mdt, bundle):
        all_params = set(HSM_CONTROL_PARAMS.keys())
        available_params = all_params - set([bundle.data["cdt_status"]])
        bundle_params = []

        # Strip the mdt down for brevity of transport and also to
        # avoid problems with the PUT.
        (resource, id) = mdt.data["resource_uri"].split("/")[-3:-1]
        safe_mdt = dict(kind=mdt.data["kind"],
                        resource=resource,
                        id=id,
                        conf_params=mdt.data["conf_params"])

        for param in available_params:
            bundle_params.append(
                dict(
                    mdt=safe_mdt,
                    param_key=HSM_CONTROL_KEY,
                    param_value=param,
                    verb=HSM_CONTROL_PARAMS[param]["verb"],
                    long_description=HSM_CONTROL_PARAMS[param]
                    ["long_description"],
                ))

        return bundle_params

    def dehydrate(self, bundle):
        # Have to do this here because we can't guarantee ordering during
        # full_dehydrate to ensure that the mdt bundles are available.
        try:
            mdt = next(m for m in bundle.data["mdts"]
                       if "mdt.hsm_control" in m.data["conf_params"])
            bundle.data["cdt_status"] = mdt.data["conf_params"][
                "mdt.hsm_control"]
            bundle.data["cdt_mdt"] = mdt.data["resource_uri"]
            bundle.data["hsm_control_params"] = self.get_hsm_control_params(
                mdt, bundle)
        except StopIteration:
            pass

        # Now the number of MDT's is known calculate the client count. The client count is calculated by the number of connections
        # divided by the number of MDT's. In the case, that is possible durring creation and deletion of filesystems, where the mdt
        # count is 0 then the connected clients must be zero.
        if len(bundle.data["mdts"]) == 0:
            bundle.data["client_count"] = 0
        else:
            bundle.data["client_count"] = self._get_stat_simple(
                bundle,
                ManagedMdt,
                "client_count",
                factor=1.0 / len(bundle.data["mdts"]))

        return bundle

    class Meta:
        queryset = ManagedFilesystem.objects.all()
        resource_name = "filesystem"
        authorization = DjangoAuthorization()
        authentication = AnonymousAuthentication()
        excludes = ["not_deleted", "ost_next_index", "mdt_next_index"]
        ordering = ["name"]
        filtering = {"id": ["exact", "in"], "name": ["exact"]}
        list_allowed_methods = ["get", "post"]
        detail_allowed_methods = ["get", "delete", "put"]
        readonly = [
            "bytes_free",
            "bytes_total",
            "files_free",
            "files_total",
            "client_count",
            "mount_command",
            "mount_path",
        ]
        validation = FilesystemValidation()
        always_return_data = True

    @validate
    def obj_create(self, bundle, **kwargs):
        request = bundle.request

        filesystem_id, command_id = JobSchedulerClient.create_filesystem(
            bundle.data)
        filesystem = ManagedFilesystem.objects.get(pk=filesystem_id)
        command = Command.objects.get(pk=command_id)
        fs_bundle = self.full_dehydrate(self.build_bundle(obj=filesystem))
        filesystem_data = self.alter_detail_data_to_serialize(
            request, fs_bundle).data

        raise custom_response(self, request, http.HttpAccepted, {
            "command": dehydrate_command(command),
            "filesystem": filesystem_data
        })
Esempio n. 7
0
class ProfileResource(ModelResource):
    """Profile api"""
    user = fields.ToOneField(UserResource, 'user')
    avatar_100 = fields.CharField(null=True)
    profile_detail_url = fields.CharField()
    email = fields.CharField(default='')
    layers_count = fields.IntegerField(default=0)
    maps_count = fields.IntegerField(default=0)
    documents_count = fields.IntegerField(default=0)
    current_user = fields.BooleanField(default=False)
    activity_stream_url = fields.CharField(null=True)

    def build_filters(self, filters={}):
        """adds filtering by group functionality"""

        orm_filters = super(ProfileResource, self).build_filters(filters)
        
        if 'group' in filters:
            orm_filters['group'] = filters['group']

        return orm_filters

    def apply_filters(self, request, applicable_filters):
        """filter by group if applicable by group functionality"""

        group = applicable_filters.pop('group', None)

        semi_filtered = super(ProfileResource, self).apply_filters(request, applicable_filters)

        if group is not None:
            semi_filtered = semi_filtered.filter(user__groupmember__group__slug=group)
            
        return semi_filtered

    def dehydrate_email(self, bundle):
        email = ''
        if bundle.request.user.is_authenticated():
            email = bundle.obj.email
        return email

    def dehydrate_layers_count(self, bundle):
        return bundle.obj.user.resourcebase_set.instance_of(Layer).count()

    def dehydrate_maps_count(self, bundle):
        return bundle.obj.user.resourcebase_set.instance_of(Map).count()

    def dehydrate_documents_count(self, bundle):
        return bundle.obj.user.resourcebase_set.instance_of(Document).count()

    def dehydrate_avatar_100(self, bundle):
        return avatar_url(bundle.obj.user, 100)

    def dehydrate_profile_detail_url(self, bundle):
        return bundle.obj.get_absolute_url()

    def dehydrate_current_user(self, bundle):
        return bundle.request.user.username == bundle.obj.user.username

    def dehydrate_activity_stream_url(self, bundle):
        return reverse('actstream_actor', kwargs={
            'content_type_id': ContentType.objects.get_for_model(bundle.obj.user).pk, 
            'object_id': bundle.obj.user.pk})

    class Meta:
        queryset = Profile.objects.all()
        resource_name = 'profiles'
        allowed_methods = ['get',]
        ordering = ['user','name']
        
Esempio n. 8
0
class ConfigResource(Resource):
    """
    The resource for configuration data to be sent to the front end
    so that site config only need be set in 1 location (the django app).
    """

    uuid = fields.CharField(attribute='uuid')
    application_name = fields.CharField(attribute='application_name')
    application_tag_line = fields.CharField(attribute='application_tag_line')
    front_end_url = fields.CharField(attribute='front_end_url')
    login_url = fields.CharField(attribute='login_url')
    login_redirect_url = fields.CharField(attribute='login_redirect_url')
    show_latest_idea_count = fields.CharField(
        attribute='show_latest_idea_count')
    show_latest_project_count = fields.CharField(
        attribute='show_latest_project_count')
    admin_name = fields.CharField(attribute='admin_name')
    admin_email = fields.CharField(attribute='admin_email')
    admin_phone = fields.CharField(attribute='admin_phone')

    class Meta:
        """
        The basics for a tastypie resource
        """
        resource_name = 'config'
        object_class = ConfigObject
        serializer = CustomSerializer()
        allowed_methods = ('get')

        authentication = Authentication()
        authorization = Authorization()

        #filtering
        #ordering

    # ------------------------------------------------------------------------------------------------------------

    def determine_format(self, request):
        """ Override the default format, so that format=json is not required """

        content_types = {
            'json': 'application/json',
            'jsonp': 'text/javascript',
            'xml': 'application/xml',
            'yaml': 'text/yaml'
        }

        format = request.GET.get('format', None)
        if format == None:
            return 'application/json'
        else:
            return content_types[format]

    # ------------------------------------------------------------------------------------------------------------

    def detail_uri_kwargs(self, bundle_or_obj):
        """ Grab the id of the specific resource """
        kwargs = {}

        if isinstance(bundle_or_obj, Bundle):
            kwargs['pk'] = bundle_or_obj.obj.uuid
        else:
            kwargs['pk'] = bundle_or_obj.uuid

        return kwargs

    # ------------------------------------------------------------------------------------------------------------

    def get_object_list(self, request):
        """ Returns a list of results"""

        # This setting should be globally available from the settings import
        try:
            api_settings = settings.API_SETTINGS
        except:

            error_text = 'Failed to access settings to be used in config API. \n'
            error_text += 'Local config file needs a setting named CONFIG_API_INCLUDE which contains a list '
            error_text += 'of the settings to be shared via the API.'
            logging.error(error_text)
            raise NotFound(
                "Settings for config API not available. Administrator required to check settings."
            )

        new_obj = ConfigObject(initial=api_settings)
        new_obj.uuid = 'api_settings'
        results = [new_obj]

        return results

    # ------------------------------------------------------------------------------------------------------------

    def obj_get_list(self, bundle, **kwargs):
        """ Get the list """
        # Filtering disabled for brevity...
        return self.get_object_list(bundle.request)
Esempio n. 9
0
class QGISStyleResource(ModelResource):
    """Styles API for QGIS Server backend."""

    body = fields.CharField(attribute='body', use_in='detail')
    name = fields.CharField(attribute='name')
    title = fields.CharField(attribute='title')
    layer = fields.ForeignKey('geonode.api.resourcebase_api.LayerResource',
                              attribute='layer',
                              null=True)
    style_url = fields.CharField(attribute='style_url')
    type = fields.CharField(attribute='type')

    class Meta:
        paginator_class = CrossSiteXHRPaginator
        queryset = QGISServerStyle.objects.all()
        resource_name = 'styles'
        detail_uri_name = 'id'
        allowed_methods = ['get', 'post', 'delete']
        authorization = GeoNodeStyleAuthorization()
        filtering = {
            'id': ALL,
            'title': ALL,
            'name': ALL,
            'layer': ALL_WITH_RELATIONS
        }

    def populate_object(self, style):
        """Populate results with necessary fields

        :param style: Style objects
        :type style: QGISServerStyle
        :return:
        """
        try:
            qgis_layer = style.layer_styles.first()
            """:type: geonode.qgis_server.QGISServerLayer"""
            style.layer = qgis_layer.layer
            style.type = 'qml'
        except BaseException:
            pass
        return style

    def build_filters(self, filters=None, **kwargs):
        """Apply custom filters for layer."""
        filters = super(QGISStyleResource,
                        self).build_filters(filters, **kwargs)
        # Convert layer__ filters into layer_styles__layer__
        updated_filters = {}
        for key, value in filters.iteritems():
            key = key.replace('layer__', 'layer_styles__layer__')
            updated_filters[key] = value
        return updated_filters

    def build_bundle(self, obj=None, data=None, request=None, **kwargs):
        """Override build_bundle method to add additional info."""

        if obj is None and self._meta.object_class:
            obj = self._meta.object_class()

        elif obj:
            obj = self.populate_object(obj)

        return Bundle(obj=obj, data=data, request=request, **kwargs)

    def post_list(self, request, **kwargs):
        """Attempt to redirect to QGIS Server Style management.

        A post method should have the following field:

        name: Slug name of style
        title: Title of style
        style: the style file uploaded

        Also, should have kwargs:

        layername or layer__name: The layer name associated with the style

        or

        layer__id: The layer id associated with the style

        """
        from geonode.qgis_server.views import qml_style

        # Extract layer name information
        POST = request.POST
        FILES = request.FILES
        layername = POST.get('layername') or POST.get('layer__name')
        if not layername:
            layer_id = POST.get('layer__id')
            layer = Layer.objects.get(id=layer_id)
            layername = layer.name

        # move style file
        FILES['qml'] = FILES['style']

        response = qml_style(request, layername)

        if isinstance(response, TemplateResponse):
            if response.status_code == 201:
                obj = QGISServerStyle.objects.get(
                    layer_styles__layer__name=layername, name=POST['name'])
                updated_bundle = self.build_bundle(obj=obj, request=request)
                location = self.get_resource_uri(updated_bundle)

                if not self._meta.always_return_data:
                    return http.HttpCreated(location=location)
                else:
                    updated_bundle = self.full_dehydrate(updated_bundle)
                    updated_bundle = self.alter_detail_data_to_serialize(
                        request, updated_bundle)
                    return self.create_response(
                        request,
                        updated_bundle,
                        response_class=http.HttpCreated,
                        location=location)
            else:
                context = response.context_data
                # Check form valid
                style_upload_form = context['style_upload_form']
                if not style_upload_form.is_valid():
                    raise BadRequest(style_upload_form.errors.as_text())
                alert_message = context['alert_message']
                raise BadRequest(alert_message)
        elif isinstance(response, HttpResponse):
            response_class = None
            if response.status_code == 403:
                response_class = http.HttpForbidden
            return self.error_response(request,
                                       response.content,
                                       response_class=response_class)

    def delete_detail(self, request, **kwargs):
        """Attempt to redirect to QGIS Server Style management."""
        from geonode.qgis_server.views import qml_style
        style_id = kwargs.get('id')

        qgis_style = QGISServerStyle.objects.get(id=style_id)
        layername = qgis_style.layer_styles.first().layer.name

        response = qml_style(request, layername, style_name=qgis_style.name)

        if isinstance(response, TemplateResponse):
            if response.status_code == 200:
                # style deleted
                return http.HttpNoContent()
            else:
                context = response.context_data
                # Check form valid
                style_upload_form = context['style_upload_form']
                if not style_upload_form.is_valid():
                    raise BadRequest(style_upload_form.errors.as_text())
                alert_message = context['alert_message']
                raise BadRequest(alert_message)
        elif isinstance(response, HttpResponse):
            response_class = None
            if response.status_code == 403:
                response_class = http.HttpForbidden
            return self.error_response(request,
                                       response.content,
                                       response_class=response_class)

    def delete_list(self, request, **kwargs):
        """Do not allow delete list"""
        return http.HttpForbidden()
Esempio n. 10
0
class JobResource(ChromaModelResource):
    """
    Jobs refer to individual units of work that the server is doing.  Jobs
    may either run as part of a Command, or on their own.  Jobs which are necessary
    to the completion of more than one command may belong to more than one command.

    For example:

    * a Command to start a filesystem has a Job for starting each OST.
    * a Command to setup an OST has a series of Jobs for formatting, registering etc

    Jobs which are part of the same command may run in parallel to one another.

    The lock objects in the ``read_locks`` and ``write_locks`` fields have the
    following form:

    ::

        {
            id: "1",
            locked_item_id: 2,
            locked_item_content_type_id: 4,
        }

    The ``id`` and ``content_type_id`` of the locked object form a unique identifier
    which can be compared with API-readable objects which have such attributes.
    """

    description = fields.CharField(help_text="Human readable string around\
            one sentence long describing what the job is doing")
    wait_for = fields.ListField(
        'wait_for',
        null=True,
        help_text=
        "List of other jobs which must complete before this job can run")
    read_locks = fields.ListField(
        null=True,
        help_text="List of objects which must stay in the required state while\
            this job runs")
    write_locks = fields.ListField(
        null=True,
        help_text="List of objects which must be in a certain state for\
            this job to run, and may be modified by this job while it runs.")
    commands = fields.ToManyField(
        'chroma_api.command.CommandResource',
        lambda bundle: bundle.obj.command_set.all(),
        null=True,
        help_text="Commands which require this job to complete\
            sucessfully in order to succeed themselves")
    steps = fields.ToManyField('chroma_api.step.StepResource',
                               lambda bundle: bundle.obj.stepresult_set.all(),
                               null=True,
                               help_text="Steps executed within this job")
    step_results = fields.DictField(help_text="List of step results")
    class_name = fields.CharField(help_text="Internal class name of job")

    available_transitions = fields.DictField()

    def _dehydrate_locks(self, bundle, write):
        if bundle.obj.locks_json:
            locks = json.loads(bundle.obj.locks_json)
            locks = [
                StateLock.from_dict(bundle.obj, lock) for lock in locks
                if lock['write'] == write
            ]
            slr = StateLockResource()
            return [
                slr.full_dehydrate(slr.build_bundle(obj=l)).data for l in locks
            ]
        else:
            return []

    def dehydrate_wait_for(self, bundle):
        if not bundle.obj.wait_for_json:
            return []
        else:
            wait_fors = json.loads(bundle.obj.wait_for_json)
            return [
                JobResource().get_resource_uri(Job.objects.get(pk=i))
                for i in wait_fors
            ]

    def dehydrate_read_locks(self, bundle):
        return self._dehydrate_locks(bundle, write=False)

    def dehydrate_write_locks(self, bundle):
        return self._dehydrate_locks(bundle, write=True)

    def dehydrate_class_name(self, bundle):
        return bundle.obj.content_type.model_class().__name__

    def dehydrate_available_transitions(self, bundle):
        job = bundle.obj.downcast()
        if job.state == 'complete' or not job.cancellable:
            return []
        elif job.cancellable:
            return [{'state': 'cancelled', 'label': 'Cancel'}]

    def dehydrate_step_results(self, bundle):
        result = {}

        for step_result in bundle.obj.stepresult_set.all():
            result[StepResource().get_resource_uri(step_result)] = json.loads(
                step_result.result) if step_result.result else None
        return result

    def dehydrate_description(self, bundle):
        return bundle.obj.downcast().description()

    class Meta:
        queryset = Job.objects.all()
        resource_name = 'job'
        authorization = DjangoAuthorization()
        authentication = AnonymousAuthentication()
        excludes = ['task_id', 'locks_json', 'wait_for_json']
        ordering = ['created_at']
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get', 'put']
        filtering = {'id': ['exact', 'in'], 'state': ['exact', 'in']}
        always_return_data = True
        validation = JobValidation()

    @validate
    def obj_update(self, bundle, **kwargs):
        job = Job.objects.get(pk=kwargs['pk'])
        new_state = bundle.data['state']

        if new_state == 'cancelled':
            JobSchedulerClient.cancel_job(job.pk)
            Job.objects.get(pk=kwargs['pk'])

        bundle.obj = job
        return bundle
Esempio n. 11
0
class MemberResource(BaseResource):
    ''' The Parliament Member API '''
    class Meta(BaseResource.Meta):

        queryset = Member.objects.exclude(
            current_party__isnull=True).select_related('current_party')

        allowed_methods = ['get']
        ordering = [
            'name',
            'is_current',
            'bills_stats_proposed',
            'bills_stats_pre',
            'bills_stats_first',
            'bills_stats_approved',
        ]

        filtering = dict(
            name=ALL,
            is_current=ALL,
        )

        excludes = ['website', 'backlinks_enabled', 'area_of_residence']
        list_fields = ['name', 'id', 'img_url', 'is_current']
        include_absolute_url = True

    party_name = fields.CharField()
    party_url = fields.CharField()
    mmms_count = fields.IntegerField(null=True)
    votes_count = fields.IntegerField(null=True)
    video_about = fields.ToManyField(
        VideoResource,
        attribute=lambda b: get_videos_queryset(b.obj, group='about'),
        null=True,
        full=True)
    videos_related = fields.ToManyField(
        VideoResource,
        attribute=lambda b: get_videos_queryset(b.obj, group='related'),
        null=True)
    links = fields.ToManyField(
        LinkResource,
        attribute=lambda b: Link.objects.for_model(b.obj),
        full=True,
        null=True)
    bills_uri = fields.CharField()
    agendas_uri = fields.CharField()
    committees = fields.ListField()
    detailed_roles = fields.ToManyField(
        RoleResource,
        attribute=lambda b: Person.objects.get(mk=b.obj).roles.all(),
        full=True,
        null=True)
    fields.ToOneField(PartyResource, 'current_party', full=True)
    average_weekly_presence_rank = fields.IntegerField()

    def obj_get_list(self, bundle, **kwargs):
        simple = super(MemberResource, self).obj_get_list(bundle, **kwargs)

        if hasattr(bundle.request, 'GET'):
            # Grab a mutable copy.
            filters = bundle.request.GET.copy()

        # Update with the provided kwargs.
        filters.update(kwargs)
        name = filters.get('name')
        if name and not simple:
            try:
                return Member.objects.filter(person__aliases__name=name)
            except PersonAlias.DoesNotExist:
                return simple
        return simple

    def dehydrate_committees(self, bundle):
        temp_list = bundle.obj.committee_meetings.exclude(
            committee__type='plenum')
        temp_list = temp_list.values("committee", "committee__name").annotate(
            Count("id")).order_by('-id__count')[:5]
        return (map(
            lambda item:
            (item['committee__name'],
             reverse('committee-detail', args=[item['committee']])),
            temp_list))

    def dehydrate_bills_uri(self, bundle):
        return '%s?%s' % (reverse(
            'api_dispatch_list',
            kwargs={
                'resource_name': 'bill',
                'api_name': 'v2',
            }), urllib.urlencode(dict(proposer=bundle.obj.id)))

    def dehydrate_gender(self, bundle):
        return bundle.obj.get_gender_display()

    def dehydrate_agendas_uri(self, bundle):
        return reverse('api_dispatch_detail',
                       kwargs={
                           'resource_name': 'member-agendas',
                           'api_name': 'v2',
                           'pk': bundle.obj.id
                       })

    def dehydrate_party_name(self, bundle):
        party = bundle.obj.current_party
        return party.name if party else None

    def dehydrate_party_url(self, bundle):
        party = bundle.obj.current_party
        return party.get_absolute_url() if party else None

    def dehydrate_mmms_count(self, bundle):
        _cache_key = 'api_v2_member_mmms_' + str(bundle.obj.pk)
        count = cache.get(_cache_key)

        if count is None:
            count = bundle.obj.mmm_documents.count()
            cache.set(_cache_key, count, 24 * 3600)

        return count

    def dehydrate_votes_count(self, bundle):
        _cache_key = 'api_v2_member_votes_' + str(bundle.obj.pk)
        count = cache.get(_cache_key)

        if count is None:
            count = bundle.obj.votes.count()
            cache.set(_cache_key, count, 24 * 3600)

        return count

    def dehydrate_average_weekly_presence_rank(self, bundle):
        ''' Calculate the distribution of presence and place the user on a 5 level scale '''
        SCALE = 5
        member = bundle.obj

        rel_location = cache.get('average_presence_location_%d' % member.id)
        if not rel_location:

            presence_list = sorted(
                map(lambda member: member.average_weekly_presence_hours,
                    Member.objects.all()))
            presence_groups = int(math.ceil(len(presence_list) / float(SCALE)))

            # Generate cache for all members
            for mk in Member.objects.all():
                avg = mk.average_weekly_presence_hours
                if avg:
                    mk_location = 1 + (presence_list.index(avg) /
                                       presence_groups)
                else:
                    mk_location = 0

                cache.set('average_presence_location_%d' % mk.id, mk_location,
                          60 * 60 * 24)

                if mk.id == member.id:
                    rel_location = mk_location

        return rel_location

    def build_filters(self, filters=None):
        if filters is None:
            filters = {}

        try:
            knesset = int(filters.get('knesset', 0))
        except KeyError:
            knesset = 0

        orm_filters = super(MemberResource, self).build_filters(filters)

        if knesset:
            knesset = Knesset.objects.get(number=knesset)
            orm_filters['parties__knesset'] = knesset

        return orm_filters
Esempio n. 12
0
class TaskFlowInstanceResource(GCloudModelResource):
    business = fields.ForeignKey(BusinessResource, 'business', full=True)
    pipeline_instance = fields.ForeignKey(PipelineInstanceResource,
                                          'pipeline_instance')
    name = fields.CharField(attribute='name', readonly=True, null=True)
    instance_id = fields.IntegerField(attribute='instance_id', readonly=True)
    category_name = fields.CharField(attribute='category_name', readonly=True)
    create_time = fields.DateTimeField(attribute='create_time',
                                       readonly=True,
                                       null=True)
    start_time = fields.DateTimeField(attribute='start_time',
                                      readonly=True,
                                      null=True)
    finish_time = fields.DateTimeField(attribute='finish_time',
                                       readonly=True,
                                       null=True)
    elapsed_time = fields.IntegerField(attribute='elapsed_time', readonly=True)
    is_started = fields.BooleanField(attribute='is_started',
                                     readonly=True,
                                     null=True)
    is_finished = fields.BooleanField(attribute='is_finished',
                                      readonly=True,
                                      null=True)
    creator_name = fields.CharField(attribute='creator_name',
                                    readonly=True,
                                    null=True)
    executor_name = fields.CharField(attribute='executor_name',
                                     readonly=True,
                                     null=True)
    pipeline_tree = fields.DictField(attribute='pipeline_tree',
                                     use_in='detail',
                                     readonly=True,
                                     null=True)
    subprocess_info = fields.DictField(attribute='subprocess_info',
                                       use_in='detail',
                                       readonly=True)

    class Meta:
        queryset = TaskFlowInstance.objects.filter(
            pipeline_instance__isnull=False, is_deleted=False)
        resource_name = 'taskflow'
        authorization = TaskflowAuthorization()
        always_return_data = True
        serializer = AppSerializer()
        filtering = {
            "id": ALL,
            "business": ALL_WITH_RELATIONS,
            "name": ALL,
            "category": ALL,
            "create_method": ALL,
            "create_info": ALL,
            "template_source": ALL,
            "template_id": ALL,
            "pipeline_instance": ALL_WITH_RELATIONS,
        }
        q_fields = ["id", "pipeline_instance__name"]
        limit = 0

    @staticmethod
    def handle_task_name_attr(data):
        data['name'] = name_handler(data['name'], TASK_NAME_MAX_LENGTH)
        pipeline_node_name_handle(data['pipeline_tree'])

    def dehydrate_pipeline_tree(self, bundle):
        return json.dumps(bundle.data['pipeline_tree'])

    def obj_create(self, bundle, **kwargs):
        model = bundle.obj.__class__
        try:
            template_id = bundle.data['template_id']
            template_source = bundle.data.get('template_source', 'business')
            creator = bundle.request.user.username
            pipeline_instance_kwargs = {
                'name': bundle.data.pop('name'),
                'creator': creator,
                'pipeline_tree': json.loads(bundle.data.pop('pipeline_tree')),
            }
            if 'description' in bundle.data:
                pipeline_instance_kwargs['description'] = bundle.data.pop(
                    'description')
        except (KeyError, ValueError) as e:
            raise BadRequest(e.message)
        # XSS handle
        self.handle_task_name_attr(pipeline_instance_kwargs)
        # validate pipeline tree
        try:
            validate_web_pipeline_tree(
                pipeline_instance_kwargs['pipeline_tree'])
        except PipelineException as e:
            raise BadRequest(e.message)
        if template_source == 'business':
            try:
                template = TaskTemplate.objects.get(pk=template_id)
            except TaskTemplate.DoesNotExist:
                raise BadRequest('template[pk=%s] does not exist' %
                                 template_id)
        else:
            try:
                template = CommonTemplate.objects.get(pk=str(template_id),
                                                      is_deleted=False)
            except CommonTemplate.DoesNotExist:
                raise BadRequest('common template[pk=%s] does not exist' %
                                 template_id)

        try:
            pipeline_instance = model.objects.__class__.create_pipeline_instance(
                template, **pipeline_instance_kwargs)
        except PipelineException as e:
            raise BadRequest(e.message)
        kwargs['category'] = template.category
        if bundle.data['flow_type'] == 'common_func':
            kwargs['current_flow'] = 'func_claim'
        else:
            kwargs['current_flow'] = 'execute_task'
        kwargs['pipeline_instance_id'] = pipeline_instance.id
        super(TaskFlowInstanceResource, self).obj_create(bundle, **kwargs)
        return bundle
Esempio n. 13
0
class FeedbackResource(PotatoCaptchaResource, CORSResource,
                       MarketplaceResource):
    feedback = fields.CharField(attribute='feedback')
    platform = fields.CharField(attribute='platform', null=True)
    chromeless = fields.CharField(attribute='chromeless', null=True)
    from_url = fields.CharField(attribute='from_url', null=True)
    user = fields.CharField(attribute='user', null=True)
    user_agent = fields.CharField(attribute='user_agent', blank=True)
    ip_address = fields.CharField(attribute='ip_address', blank=True)

    class Meta(MarketplaceResource.Meta):
        resource_name = 'feedback'
        always_return_data = True
        list_allowed_methods = ['post']
        detail_allowed_methods = []
        authentication = OptionalOAuthAuthentication()
        authorization = Authorization()
        object_class = GenericObject
        include_resource_uri = False
        throttle = CacheThrottle(throttle_at=30)

    def _send_email(self, bundle):
        """
        Send feedback email from the valid bundle.
        """
        user = bundle.data.get('user')
        sender = getattr(user, 'email', settings.NOBODY_EMAIL)
        send_mail_jinja(u'Marketplace Feedback',
                        'account/email/feedback.txt',
                        bundle.data,
                        from_email=sender,
                        recipient_list=[settings.MKT_FEEDBACK_EMAIL])

    def hydrate(self, bundle):
        """
        Add the authenticated user to the bundle.
        """
        if 'platform' not in bundle.data:
            bundle.data['platform'] = bundle.request.GET.get('dev', '')

        bundle.data.update({
            'user':
            bundle.request.amo_user,
            'user_agent':
            bundle.request.META.get('HTTP_USER_AGENT', ''),
            'ip_address':
            bundle.request.META.get('REMOTE_ADDR', '')
        })
        return bundle

    def dehydrate(self, bundle):
        """
        Strip the `user_agent` and `ip_address` fields before presenting to the
        consumer.
        """
        del bundle.data['user_agent']
        del bundle.data['ip_address']
        return bundle

    def get_resource_uri(self, bundle_or_obj=None):
        """
        Noop needed to prevent NotImplementedError.
        """
        return ''

    def obj_create(self, bundle, request=None, **kwargs):
        bundle.obj = self._meta.object_class(**kwargs)
        bundle = self.full_hydrate(bundle)

        form = FeedbackForm(bundle.data, request=request)
        if not form.is_valid():
            raise self.form_errors(form)

        self._send_email(bundle)

        return bundle
Esempio n. 14
0
class FileItemResource(Resource):
    name = fields.CharField(attribute='name')

    class Meta:
        resource_name = 'fileservice'
        object_class = FileItem
        fields = ['name']
        include_resource_uri = False
        allowed_methods = ['get', 'post', 'put']
        list_allowed_methods = ['post']
        always_return_data = True
        authentication = SessionAuthentication()
        authorization = Authorization()

    def determine_format(self, request):
        return 'application/json'

    @staticmethod
    def get_file_items():
        file_names = helpers.get_fileservice_files()
        file_items = []
        for name in file_names:
            file_item = FileItem()
            file_item.name = name
            file_items.append(file_item)
        return file_items

    @staticmethod
    def get_file_item(kwargs):
        if 'name' in kwargs:
            return FileItemResource.get_file_item_by_name(kwargs['name'])
        elif 'pk' in kwargs:
            return FileItemResource.get_file_items()[int(kwargs['pk'])]
        return None

    @staticmethod
    def get_file_item_by_name(name):
        file_items = FileItemResource.get_file_items()
        for file_item in file_items:
            if file_item.name == helpers.u_to_str(name):
                return file_item

    def deserialize(self, request, data, format=None):
        if not format:
            format = request.META.get('CONTENT_TYPE', 'application/json')

        if format == 'application/x-www-form-urlencoded':
            return request.POST

        if format.startswith('multipart'):
            data = request.POST.copy()
            data.update(request.FILES)
            return data

        return super(Resource, self).deserialize(request, data, format)

    def detail_uri_kwargs(self, bundle_or_obj):
        if isinstance(bundle_or_obj, Bundle):
            return {'name': bundle_or_obj.obj.name}
        else:
            return {'name': bundle_or_obj.name}

    def get_object_list(self, request):
        # inner get of object list... this is where you'll need to
        # fetch the data from what ever data source
        return FileItemResource.get_file_items()

    def obj_get_list(self, request=None, **kwargs):
        # outer get of object list... this calls get_object_list and
        # could be a point at which additional filtering may be applied
        return self.get_object_list(request)

    def obj_get(self, request=None, **kwargs):
        # get one object from data source
        file_item = FileItemResource.get_file_item(kwargs)
        # if not file_item: raise NotFound("Object not found")
        return file_item

    def obj_create(self, bundle, request=None, **kwargs):
        # create a new File
        bundle.obj = FileItem()
        # full_hydrate does the heavy lifting mapping the
        # POST-ed payload key/values to object attribute/values
        bundle = self.full_hydrate(bundle)
        filename_name, file_extension = os.path.splitext(
            bundle.data[u'file'].name)

        # -- only allow uploading of files of types specified
        # in FILESERVICE_CONFIG.types_allowed
        types_allowed = helpers.get_fileservice_whitelist()
        if '*' not in types_allowed and file_extension.lower() \
                not in types_allowed:
            raise BadRequest('file type is not whitelisted in '
                             'FILESERVICE_CONFIG.types_allowed')

        file_data = bundle.data[u'file'].read()
        # TODO: support optional unique name generation from sha1 and uuid.
        #  file_sha1 = hashlib.sha1(file_data).hexdigest()
        #  is file_data only the bytes without filename etc?
        #  if file_extension:
        #    filename_name = '{}{}'.format(file_sha1, file_extension)
        #  else:
        #    filename_name = file_sha1

        # TODO: if the filename uploaded is not a valid sha1,
        # warn that it should at least be unique.
        bundle.obj.name = bundle.data[u'file'].name
        with open(helpers.get_filename_absolute(bundle.data[u'file'].name),
                  'wb+') as destination_file:
            destination_file.write(file_data)

        # remove the file object passed in so that the response is
        #  more concise about what this file will be referred to
        bundle.data.pop(u'file', None)
        return bundle

    def prepend_urls(self):
        """ Add the following array of urls to the resource base urls """

        view_action = 'download'
        if helpers.get_streaming_supported():
            view_action = 'view'

        return [
            # --- download
            url(r"^(?P<resource_name>%s)/download/(?P<name>[\w\d_.-]+)%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('download'),
                name="api_fileitem_download"),
            url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/download%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('download'),
                name="api_fileitem_download"),
            url(r"^(?P<resource_name>%s)/(?P<name>[\w\d_.-]+)/download%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('download'),
                name="api_fileitem_download"),

            # --- view
            url(r"^(?P<resource_name>%s)/view/(?P<name>[\w\d_.-]+)%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view(view_action),
                name='api_fileitem_{}'.format(view_action)),
            url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/view%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view(view_action),
                name='api_fileitem_{}'.format(view_action)),
            url(r"^(?P<resource_name>%s)/(?P<name>[\w\d_.-]+)/view%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view(view_action),
                name='api_fileitem_{}'.format(view_action)),

            # --- dispatch
            url(r"^(?P<resource_name>%s)/(?P<name>[\w\d_.-]+)/$" %
                self._meta.resource_name,
                self.wrap_view('dispatch_detail'),
                name="api_dispatch_detail_name"),
            url(r"^(?P<resource_name>%s)/(?P<id>[\d]+)/$" %
                self._meta.resource_name,
                self.wrap_view('dispatch_detail'),
                name="api_dispatch_detail"),
        ]

    def download(self, request, **kwargs):
        '''
        example use:
        http://.../fileservice/download/med.mp4/
        or
        http://.../fileservice/med.mp4/download/
        '''
        # method check to avoid bad requests
        self.method_check(request, allowed=['get'])
        # Must be done otherwise endpoint will be wide open
        self.is_authenticated(request)

        response = None
        file_item_name = kwargs.get('name', None)
        if file_item_name:
            filename_absolute = helpers.get_filename_absolute(file_item_name)
            if os.path.isfile(filename_absolute):
                response = serve(request, os.path.basename(filename_absolute),
                                 os.path.dirname(filename_absolute))
                response['Content-Disposition'] = 'attachment; ' \
                                                  'filename="{}"'.format(
                    os.path.basename(filename_absolute))

        if not response:
            response = self.create_response(request=request,
                                            data={},
                                            response_class=HttpNotFound)

        return response

    def view(self, request, **kwargs):
        '''
        allow a file to be viewed as opposed to download. This is particularly
        needed when a video file is stored
        in the fileservice and user wants to be able to use a view the
        video as opposed to having to download it
        first. It passes the serving of the file to nginx/apache which will
        return all the proper headers allowing,
        say, html5's video viewer's 'seek' indicator/knob to work. Otherwise
         the video is only played sequentially

        Note that nginx/apache need to be configured accordingly. nginx
        for example:
        location /var/lib/geoserver_data/file-service-store/ {
           # forces requests to be authorized
           internal;
           alias   /var/lib/geoserver_data/file-service-store/;
        }

        for apache, need to install xsendfile module, enable it, set
        the path and then
        XSendFile on
        XSendFilePath /var/lib/geoserver_data/file-service-store

        example use:
        /fileservice/view/med.mp4
        or
        /fileservice/med.mp4/view

        Note that media players tend to require the route to end with the
        filename like /fileservice/view/med.mp4
        '''

        # method check to avoid bad requests
        self.method_check(request, allowed=['get'])
        # Must be done otherwise endpoint will be wide open
        self.is_authenticated(request)

        file_item_name = kwargs.get('name', None)
        url = urllib.pathname2url(file_item_name)
        mime = MimeTypes()
        mime_type = mime.guess_type(url)
        response = HttpResponse(content_type=mime_type[0])
        file_with_route = smart_str('{}{}'.format(
            helpers.get_fileservice_dir(), file_item_name))
        # apache header
        response['X-Sendfile'] = file_with_route
        # nginx header
        response['X-Accel-Redirect'] = file_with_route

        return response
Esempio n. 15
0
class BaseApplicationResource(OpeniResource):
    category = fields.CharField(attribute='category', null=True, blank=True)

    class Meta(GenericMeta):
        resource_name = "Application"
        object_class = ApplicationModel
Esempio n. 16
0
class GeoserverStyleResource(ModelResource):
    """Styles API for Geoserver backend."""
    body = fields.CharField(attribute='sld_body', use_in='detail')
    name = fields.CharField(attribute='name')
    title = fields.CharField(attribute='sld_title')
    # layer_default_style is polymorphic, so it will have many to many
    # relation
    layer = fields.ManyToManyField(
        'geonode.api.resourcebase_api.LayerResource',
        attribute='layer_default_style',
        null=True)
    version = fields.CharField(attribute='sld_version', null=True, blank=True)
    style_url = fields.CharField(attribute='sld_url')
    workspace = fields.CharField(attribute='workspace', null=True)
    type = fields.CharField(attribute='type')

    class Meta:
        paginator_class = CrossSiteXHRPaginator
        queryset = Style.objects.all()
        resource_name = 'styles'
        detail_uri_name = 'id'
        authorization = GeoNodeStyleAuthorization()
        allowed_methods = ['get']
        filtering = {
            'id': ALL,
            'title': ALL,
            'name': ALL,
            'layer': ALL_WITH_RELATIONS
        }

    def build_filters(self, filters=None, **kwargs):
        """Apply custom filters for layer."""
        filters = super(GeoserverStyleResource,
                        self).build_filters(filters, **kwargs)
        # Convert layer__ filters into layer_styles__layer__
        updated_filters = {}
        for key, value in filters.iteritems():
            key = key.replace('layer__', 'layer_default_style__')
            updated_filters[key] = value
        return updated_filters

    def populate_object(self, style):
        """Populate results with necessary fields

        :param style: Style objects
        :type style: Style
        :return:
        """
        style.type = 'sld'
        return style

    def build_bundle(self, obj=None, data=None, request=None, **kwargs):
        """Override build_bundle method to add additional info."""

        if obj is None and self._meta.object_class:
            obj = self._meta.object_class()

        elif obj:
            obj = self.populate_object(obj)

        return Bundle(obj=obj, data=data, request=request, **kwargs)
Esempio n. 17
0
class RatingResource(CORSResource, MarketplaceModelResource):

    app = fields.ToOneField(AppResource, 'addon', readonly=True)
    user = fields.ToOneField(AccountResource, 'user', readonly=True, full=True)
    version = CompatToOneField(None,
                               'version',
                               rest='version',
                               readonly=True,
                               null=True,
                               extra_fields=('version', ))
    report_spam = fields.CharField()

    class Meta(MarketplaceModelResource.Meta):
        # Unfortunately, the model class name for ratings is "Review".
        queryset = Review.objects.valid()
        resource_name = 'rating'
        list_allowed_methods = ['get', 'post']
        detail_allowed_methods = ['get', 'put', 'delete']
        always_return_data = True
        authentication = (SharedSecretAuthentication(),
                          OptionalOAuthAuthentication())
        authorization = AnonymousReadOnlyAuthorization()
        fields = ['rating', 'body', 'modified', 'created']

        filtering = {
            'app': ('exact', ),
            'user': ('exact', ),
            'pk': ('exact', ),
        }

        ordering = ['created']

    def dehydrate(self, bundle):
        bundle = super(RatingResource, self).dehydrate(bundle)
        if bundle.request.amo_user:
            amo_user = bundle.request.amo_user
            bundle.data['is_author'] = bundle.obj.user.pk == amo_user.pk
            bundle.data['has_flagged'] = (
                not bundle.data['is_author']
                and bundle.obj.reviewflag_set.filter(user=amo_user).exists())
        return bundle

    def dehydrate_report_spam(self, bundle):
        return self._build_reverse_url('api_post_flag',
                                       kwargs={
                                           'api_name': self._meta.api_name,
                                           'resource_name':
                                           self._meta.resource_name,
                                           'review_id': bundle.obj.pk
                                       })

    def _review_data(self, request, app, form):
        data = dict(addon_id=app.id,
                    user_id=request.user.id,
                    ip_address=request.META.get('REMOTE_ADDR', ''))
        if app.is_packaged:
            data['version_id'] = app.current_version.id
        data.update(**form.cleaned_data)
        return data

    def get_app(self, ident):
        try:
            app = Webapp.objects.valid().get(id=ident)
        except (Webapp.DoesNotExist, ValueError):
            try:
                app = Webapp.objects.valid().get(app_slug=ident)
            except Webapp.DoesNotExist:
                raise self.non_form_errors([('app', 'Invalid app')])
        if not app.listed_in(region=REGIONS_DICT[get_region()]):
            raise self.non_form_errors([('app', 'Not available in this region')
                                        ])
        return app

    def build_filters(self, filters=None):
        """
        If `addon__exact` is a filter and its value cannot be coerced into an
        int, assume that it's a slug lookup.

        Run the query necessary to determine the app, and substitute the slug
        with the PK in the filter so tastypie will continue doing its thing.
        """
        built = super(RatingResource, self).build_filters(filters)
        if 'addon__exact' in built:
            try:
                int(built['addon__exact'])
            except ValueError:
                app = self.get_app(built['addon__exact'])
                if app:
                    built['addon__exact'] = str(app.pk)

        if built.get('user__exact', None) == 'mine':
            # This is a cheat. Would prefer /mine/ in the URL.
            user = get_user()
            if not user:
                # You must be logged in to use "mine".
                raise http_error(http.HttpUnauthorized,
                                 'You must be logged in to access "mine".')

            built['user__exact'] = user.pk
        return built

    def obj_create(self, bundle, request=None, **kwargs):
        """
        Handle POST requests to the resource. If the data validates, create a
        new Review from bundle data.
        """
        form = ReviewForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        app = self.get_app(bundle.data['app'])

        # Return 409 if the user has already reviewed this app.
        qs = self._meta.queryset.filter(addon=app, user=request.user)
        if app.is_packaged:
            qs = qs.filter(version_id=bundle.data['version'])
        if qs.exists():
            raise http_error(http.HttpConflict,
                             'You have already reviewed this app.')

        # Return 403 if the user is attempting to review their own app:
        if app.has_author(request.user):
            raise http_error(http.HttpForbidden,
                             'You may not review your own app.')

        # Return 403 if not a free app and the user hasn't purchased it.
        if app.is_premium() and not app.is_purchased(request.amo_user):
            raise http_error(
                http.HttpForbidden,
                "You may not review paid apps you haven't purchased.")

        bundle.obj = Review.objects.create(
            **self._review_data(request, app, form))

        amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
        log.debug('[Review:%s] Created by user %s ' %
                  (bundle.obj.id, request.user.id))
        record_action('new-review', request, {'app-id': app.id})

        return bundle

    def obj_update(self, bundle, request, **kwargs):
        """
        Handle PUT requests to the resource. If authorized and the data
        validates, update the indicated resource with bundle data.
        """
        form = ReviewForm(bundle.data)
        if not form.is_valid():
            raise self.form_errors(form)

        if 'app' in bundle.data:
            error = ('app', "Cannot update a rating's `app`")
            raise self.non_form_errors([error])

        sup = super(RatingResource, self).obj_update(bundle, request, **kwargs)

        amo.log(amo.LOG.EDIT_REVIEW, bundle.obj.addon, bundle.obj)
        log.debug('[Review:%s] Edited by %s' %
                  (bundle.obj.id, request.user.id))

        return sup

    def obj_delete(self, request, **kwargs):
        obj = self.get_by_resource_or_404(request, **kwargs)
        if not (AppOwnerAuthorization().is_authorized(request,
                                                      object=obj.addon)
                or OwnerAuthorization().is_authorized(request, object=obj) or
                PermissionAuthorization('Users', 'Edit').is_authorized(request)
                or PermissionAuthorization('Addons',
                                           'Edit').is_authorized(request)):
            raise http_error(
                http.HttpForbidden,
                'You do not have permission to delete this review.')

        log.info('Rating %s deleted from addon %s' % (obj.pk, obj.addon.pk))
        return super(RatingResource, self).obj_delete(request, **kwargs)

    def get_object_list(self, request):
        qs = MarketplaceModelResource.get_object_list(self, request)
        # Mature regions show only reviews from within that region.
        if not request.REGION.adolescent:
            qs = qs.filter(client_data__region=request.REGION.id)
        return qs

    def alter_list_data_to_serialize(self, request, data):
        if 'app' in request.GET:
            addon = self.get_app(request.GET['app'])
            data['info'] = {
                'average': addon.average_rating,
                'slug': addon.app_slug,
                'current_version': addon.current_version.version
            }

            filters = dict(addon=addon)
            if addon.is_packaged:
                filters['version'] = addon.current_version

            if not request.user.is_anonymous():
                filters['user'] = request.user
                existing_review = Review.objects.valid().filter(**filters)
                if addon.is_premium():
                    can_rate = addon.has_purchased(request.amo_user)
                else:
                    can_rate = not addon.has_author(request.user)
                data['user'] = {
                    'can_rate': can_rate,
                    'has_rated': existing_review.exists()
                }
            else:
                data['user'] = None

        return data

    def override_urls(self):
        # Based on 'nested resource' example in tastypie cookbook.
        return [
            url(r'^(?P<resource_name>%s)/(?P<review_id>\w[\w/-]*)/flag%s$' %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('post_flag'),
                name='api_post_flag')
        ]

    def post_flag(self, request, **kwargs):
        return RatingFlagResource().dispatch('list',
                                             request,
                                             review_id=kwargs['review_id'])
Esempio n. 18
0
class UserResource(ChromaModelResource):
    """
    A user account
    """

    groups = fields.ToManyField(
        "chroma_api.group.GroupResource",
        attribute="groups",
        full=True,
        null=True,
        readonly=True,
        help_text="List of groups that this user is a member of.",
    )
    alert_subscriptions = fields.ToManyField(
        "chroma_api.alert.AlertSubscriptionResource",
        attribute="alert_subscriptions",
        null=True,
        full=True,
        help_text="List of alert subscriptions (alerts for which this user"
        "will be sent emails.  See alert_subscription resource"
        "for format",
    )
    full_name = fields.CharField(
        help_text=
        "Human readable form derived from ``first_name`` and ``last_name``")

    password1 = fields.CharField(
        help_text=
        "Used when creating a user (request must be made by a superuser)")
    password2 = fields.CharField(
        help_text="Password confirmation, must match ``password1``")
    new_password1 = fields.CharField(
        help_text="Used for modifying password (request must be "
        "made by the same user or by a superuser)")
    new_password2 = fields.CharField(
        help_text="Password confirmation, must match ``new_password1``")

    is_superuser = fields.BooleanField(readonly=True,
                                       help_text="Is the user a superuser",
                                       attribute="is_superuser")

    def alter_deserialized_detail_data(self, request, data):
        def handle_groups(group):
            if isinstance(group, dict):
                return group["resource_uri"]
            elif isinstance(group, basestring):
                return group
            elif isinstance(group, Bundle):
                return group
            else:
                raise NotImplementedError(group.__class__)

        if "groups" in data:
            data["groups"] = map(handle_groups, data["groups"])

        return data

    def hydrate_groups(self, bundle):
        from chroma_api.group import GroupResource

        # Prevent non-superusers from modifying their groups
        if not bundle.request.user.is_superuser:
            if bundle.data.get("groups") is not None:
                group_ids = []

                for group in bundle.data["groups"]:
                    if isinstance(group, dict):
                        group_ids.append(int(group["id"]))
                    elif isinstance(group, basestring):
                        group_ids.append(
                            int(GroupResource().get_via_uri(
                                group, bundle.request).id))
                    elif isinstance(group, Bundle):
                        group_ids.append(int(group.obj.id))
                    else:
                        raise NotImplementedError(group.__class__)

                user_group_ids = [
                    int(group.pk)
                    for group in bundle.request.user.groups.all()
                ]

                if not set(group_ids) == set(user_group_ids):
                    raise ImmediateHttpResponse(HttpForbidden())

        return bundle

    # This seems wrong. Without it, the hydration goes awry with what
    # comes in via PUT. We aren't managing user alert subscriptions
    # via the User resource, though, so perhaps this is not so bad.
    def hydrate_alert_subscriptions(self, bundle):
        try:
            del bundle.data["alert_subscriptions"][:]
        except KeyError:
            pass

        return bundle

    def _hydrate_password(self, bundle, key):
        try:
            new_password = bundle.data[key]
            if new_password:
                bundle.obj.set_password(new_password)
        except KeyError:
            pass
        return bundle

    def hydrate_password2(self, bundle):
        return self._hydrate_password(bundle, "password2")

    def hydrate_new_password2(self, bundle):
        return self._hydrate_password(bundle, "new_password2")

    def obj_create(self, bundle, **kwargs):
        bundle = super(UserResource, self).obj_create(bundle, **kwargs)
        from django.contrib.auth.models import Group

        superuser_group = Group.objects.get(name="superusers")
        for g in bundle.obj.groups.all():
            if g == superuser_group:
                bundle.obj.is_superuser = True
                bundle.obj.save()

        return bundle

    def dehydrate_full_name(self, bundle):
        return bundle.obj.get_full_name()

    def delete_detail(self, request, **kwargs):
        if int(kwargs["pk"]) == request.user.id:
            return self.create_response(
                request,
                {"id": ["Cannot delete currently authenticated user"]},
                response_class=HttpBadRequest)
        else:
            return super(UserResource, self).delete_detail(request, **kwargs)

    class Meta:
        authentication = AnonymousAuthentication()
        authorization = UserAuthorization()
        queryset = User.objects.all()
        validation = UserValidation()
        fields = [
            "first_name",
            "full_name",
            "groups",
            "id",
            "last_name",
            "new_password1",
            "new_password2",
            "password1",
            "password2",
            "resource_uri",
            "username",
            "email",
        ]
        ordering = ["username", "email"]
        list_allowed_methods = ["get", "post"]
        detail_allowed_methods = ["get", "put", "patch", "delete"]
        always_return_data = True
Esempio n. 19
0
class FaceSearchResource(Resource):
    name = fields.CharField(attribute='name')

    class Meta:
        resource_name = 'facesearchservice'
        object_class = FaceSearch
        fields = ['name']
        include_resource_uri = False
        allowed_methods = ['post']
        always_return_data = True
        authentication = BasicAuthentication()
        authorization = Authorization()

    def determine_format(self, request):
        return 'application/json'

    def deserialize(self, request, data, format=None):
        if not format:
            format = request.META.get('CONTENT_TYPE', 'application/json')

        if format == 'application/x-www-form-urlencoded':
            return request.POST

        if format.startswith('multipart'):
            data = request.POST.copy()
            data.update(request.FILES)
            return data

        return super(Resource, self).deserialize(request, data, format)

    def detail_uri_kwargs(self, bundle_or_obj):
        if isinstance(bundle_or_obj, Bundle):
            return {'name': bundle_or_obj.obj.name}
        else:
            return {'name': bundle_or_obj.name}

    def prepend_urls(self):
        """ Add the following array of urls to the Tileset base urls """
        return [
            url(r"^(?P<resource_name>%s)/test_getfilename%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('test_getfilename'), name="test_getfilename"),
            url(r"^(?P<resource_name>%s)/reload_gallery%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('reload_gallery'), name="reload_gallery"),
        ]

    # This function is a REST end-point to perform a simple test of br_get_filename, which is giving us a problem
    # Make sure to have a picture /tmp/testimage1.jpg
    def test_getfilename(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        res = []

        # create a new File
        filename_name = u'/tmp/testimage1.jpg'
        file_data = open(filename_name, 'rb').read()

        facetmpl = br.br_load_img(file_data, len(file_data))
        print "Setting file name on template to " + os.path.basename(filename_name)
        logger.debug("Setting file name on template to " + os.path.basename(filename_name))
        br.br_set_filename(facetmpl, os.path.basename(filename_name))
        print "Retrieving file name from template"
        logger.debug("Retriving file name from template")
        filename = br.br_get_filename(facetmpl)
        logger.debug("Filename=" + filename)
        print filename
        response = self.create_response(request, res)
        return response

    def reload_gallery(self, request, **kwargs):
        reindex_gallery()
        galleryGalPath = get_gallery_file()
        galGallery = br.br_make_gallery(galleryGalPath)
        galTemplateList = br.br_load_from_gallery(galGallery)

        # compare and collect scores
        ntargets = br.br_num_templates(galTemplateList)
        logger.debug(str(ntargets) + " templates found in the gallery at " + galleryGalPath)
        res = str(ntargets) + " templates found in the gallery at " + galleryGalPath
        for r in range(ntargets):
            tmpl = br.br_get_template(galTemplateList, r)
            logger.debug("Filename = " + br.br_get_filename(tmpl))
        response = self.create_response(request, res)
        br.br_free_template_list(galTemplateList)
        br.br_close_gallery(galGallery)
        return response

    def obj_create(self, bundle, request=None, **kwargs):
        # create a new File
        bundle.obj = FaceSearch()
        # full_hydrate does the heavy lifting mapping the
        # POST-ed payload key/values to object attribute/values
        bundle = self.full_hydrate(bundle)
        file_data = bundle.data[u'file'].read()

        # write the file data to a temporary file
        filename_name, file_extension = os.path.splitext(bundle.data[u'file'].name)
        destination_file = tempfile.NamedTemporaryFile(suffix=file_extension)
        destination_file.write(bytearray(file_data))
        destination_file.flush()
        os.fsync(destination_file) # Need this, we were not getting all bytes written to file before proceeding

        temp_gal = tempfile.NamedTemporaryFile(suffix='.gal')
        args = ['br', '-algorithm', 'FaceRecognition', '-enroll', destination_file.name, temp_gal.name]
        subprocess.call(args)
        out_file = tempfile.NamedTemporaryFile(suffix='.csv')
        galleryGalPath = get_gallery_file()
        args = args[:3] + ['-compare', galleryGalPath, temp_gal.name, out_file.name]
        subprocess.call(args)

        with open(out_file.name, 'r') as scores_file:
            files_line = scores_file.readline().strip().split(',')[1:]
            scores_line = scores_file.readline().strip().split(',')
            probe = scores_line[0]
            score_list = scores_line[1:]
            scores= []
            for f, s in zip(files_line, score_list):
                logger.debug('%s -> %s: %s' % (probe, f, s))
                scores.append((os.path.basename(f), s))

        destination_file.close()
        out_file.close()
        temp_gal.close()

        peeps = Person.objects.filter(pic_filename__in=dict(scores).keys()).values()

        sorted_peeps = []

        scores.sort(key=lambda s: s[1], reverse=True)
        # TODO: Make 15 a parameter - right now we return the top 15 results
        logger.debug("Building result package")
        for s in scores[:15]:
            currfilename = s[0]
            logger.debug(currfilename)
            foundPeep = filter(lambda p: p['pic_filename'] == os.path.basename(s[0]), peeps)
            if foundPeep is not None and len(foundPeep) > 0:
                sorted_peeps.append(foundPeep[0])
            else:
                logger.info("Found picture with no link person " + currfilename)

        # bundle the search results
        bundle.obj.name = bundle.data[u'file'].name
        bundle.data.pop(u'file', None)
        bundle.data['meta'] = {
            "limit": len(peeps),
            "next": None,
            "offset": 0,
            "previous": None,
            "total_count": len(peeps)
        }

        bundle.data['objects'] = sorted_peeps
        bundle.data['scores'] = scores
        return bundle
Esempio n. 20
0
class InvoiceRevisionResource(VosaeResource):
    revision = base_fields.CharField(
        attribute='revision',
        readonly=True,
        help_text=HELP_TEXT['invoice_revision']['revision']
    )
    issue_date = base_fields.DateTimeField(
        attribute='issue_date',
        readonly=True,
        help_text=HELP_TEXT['invoice_revision']['issue_date']
    )
    sender = base_fields.CharField(
        attribute='sender',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['sender']
    )
    sender_organization = base_fields.CharField(
        attribute='sender_organization',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['invoice_revision']['sender_organization']
    )
    quotation_date = base_fields.DateField(
        attribute='quotation_date',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['quotation_date']
    )
    quotation_validity = base_fields.DateField(
        attribute='quotation_validity',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['quotation_validity']
    )
    purchase_order_date = base_fields.DateField(
        attribute='purchase_order_date',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['purchase_order_date']
    )
    invoicing_date = base_fields.DateField(
        attribute='invoicing_date',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['invoicing_date']
    )
    due_date = base_fields.DateField(
        attribute='due_date',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['due_date']
    )
    credit_note_emission_date = base_fields.DateField(
        attribute='credit_note_emission_date',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['credit_note_emission_date']
    )
    custom_payment_conditions = base_fields.CharField(
        attribute='custom_payment_conditions',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['custom_payment_conditions']
    )
    customer_reference = base_fields.CharField(
        attribute='customer_reference',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice_revision']['customer_reference']
    )
    taxes_application = base_fields.CharField(
        attribute='taxes_application',
        help_text=HELP_TEXT['invoice_revision']['taxes_application']
    )

    issuer = fields.ReferenceField(
        to='core.api.resources.VosaeUserResource',
        attribute='issuer',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['invoice_revision']['issuer']
    )
    sender_address = fields.EmbeddedDocumentField(
        embedded='contacts.api.resources.AddressResource',
        attribute='sender_address',
        null=True,
        help_text=HELP_TEXT['invoice_revision']['sender_address']
    )
    contact = fields.ReferenceField(
        to='contacts.api.resources.ContactResource',
        attribute='contact',
        null=True,
        help_text=HELP_TEXT['invoice_revision']['contact']
    )
    organization = fields.ReferenceField(
        to='contacts.api.resources.OrganizationResource',
        attribute='organization',
        null=True,
        help_text=HELP_TEXT['invoice_revision']['organization']
    )
    billing_address = fields.EmbeddedDocumentField(
        embedded='contacts.api.resources.AddressResource',
        attribute='billing_address',
        null=True,
        help_text=HELP_TEXT['invoice_revision']['billing_address']
    )
    delivery_address = fields.EmbeddedDocumentField(
        embedded='contacts.api.resources.AddressResource',
        attribute='delivery_address',
        null=True,
        help_text=HELP_TEXT['invoice_revision']['delivery_address']
    )
    currency = fields.EmbeddedDocumentField(
        embedded='invoicing.api.resources.SnapshotCurrencyResource',
        attribute='currency',
        help_text=HELP_TEXT['invoice_revision']['currency']
    )
    line_items = fields.EmbeddedListField(
        of='invoicing.api.resources.InvoiceItemResource',
        attribute='line_items',
        full=True,
        null=True,
        help_text=HELP_TEXT['invoice_revision']['line_items']
    )
    pdf = ReferencedDictField(
        of='core.api.resources.VosaeFileResource',
        attribute='pdf',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['invoice_revision']['pdf']
    )

    class Meta(VosaeResource.Meta):
        object_class = InvoiceRevision

    def hydrate(self, bundle):
        """Set issue data and issuer on POST, extracted from request"""
        bundle = super(InvoiceRevisionResource, self).hydrate(bundle)
        bundle.obj.issuer = bundle.request.vosae_user
        bundle.obj.issue_date = datetime_now()
        return bundle
Esempio n. 21
0
class SearchResource(DeprecatedModelResourceWithFieldsFilter):
    # Roses to the clever person that makes this introspect the model and
    # removes all this code.
    absolute_url = fields.CharField(
        attribute='absolute_url',
        help_text="The URL on CourtListener for the item.",
        null=True,
    )
    case_name = fields.CharField(
        attribute='caseName',
        help_text="The full name of the case",
        null=True,
    )
    case_number = fields.CharField(
        attribute='caseNumber',
        help_text="The combination of the citation and the docket number.",
        null=True,
    )
    citation = fields.CharField(
        attribute='citation',
        help_text="A concatenated list of all the citations for an opinion.",
        null=True,
    )
    cite_count = fields.IntegerField(
        attribute='citeCount',
        help_text="The number of times this document is cited by other cases",
    )
    court = fields.CharField(
        attribute='court',
        help_text="The name of the court where the document was filed",
        null=True,
    )
    court_id = fields.CharField(
        attribute='court_id',
        help_text='The court where the document was filed',
        null=True,
    )
    date_filed = fields.DateField(
        attribute='dateFiled',
        help_text='The date filed by the court',
        null=True,
    )
    docket_number = fields.CharField(
        attribute='docketNumber',
        help_text=
        'The docket numbers of a case, can be consolidated and quite long',
        null=True,
    )
    download_url = fields.CharField(
        attribute='download_url',
        help_text=
        'The URL on the court website where the document was originally scraped',
        null=True,
    )
    id = fields.CharField(
        attribute='id',
        help_text='The primary key for an opinion.',
    )
    judge = fields.CharField(
        attribute='judge',
        help_text='The judges that brought the opinion as a simple text string',
        null=True,
    )
    local_path = fields.CharField(
        attribute='local_path',
        help_text=
        'The location, relative to MEDIA_ROOT on the CourtListener server, where files are stored',
        null=True,
    )
    score = fields.FloatField(
        attribute='score',
        help_text='The relevance of the result. Will vary from query to query.',
    )
    source = fields.CharField(
        attribute='source',
        help_text='the source of the document, one of: %s' %
        ', '.join(['%s (%s)' % (t[0], t[1]) for t in SOURCES]),
        null=True,
    )
    snippet = fields.CharField(
        attribute='snippet',
        help_text=
        'a snippet as found in search results, utilizing <mark> for highlighting and &hellip; for ellipses',
        null=True,
    )
    status = fields.CharField(
        attribute='status',
        help_text='The precedential status of document, one of: %s' %
        ', '.join([('stat_%s' % t[1]).replace(' ', '+')
                   for t in DOCUMENT_STATUSES]),
        null=True,
    )
    suit_nature = fields.CharField(
        attribute='suitNature',
        help_text=
        "The nature of the suit. For the moment can be codes or laws or whatever",
        null=True,
    )
    text = fields.CharField(
        attribute='text',
        use_in='detail',  # Only shows on the detail page.
        help_text=
        "A concatenated copy of most fields in the item so those fields are available for search."
    )
    timestamp = fields.DateField(
        attribute='timestamp',
        help_text='The moment when an item was indexed by Solr.')

    class Meta:
        authentication = authentication.MultiAuthentication(
            BasicAuthenticationWithUser(realm="courtlistener.com"),
            authentication.SessionAuthentication())
        throttle = PerUserCacheThrottle(throttle_at=1000)
        resource_name = 'search'
        max_limit = 20
        include_absolute_url = True
        allowed_methods = ['get']
        filtering = {
            'q': ('search', ),
            'case_name': ('search', ),
            'judge': ('search', ),
            'stat_': ('boolean', ),
            'filed_after': ('date', ),
            'filed_before': ('date', ),
            'citation': ('search', ),
            'neutral_cite': ('search', ),
            'docket_number': ('search', ),
            'cited_gt': ('int', ),
            'cited_lt': ('int', ),
            'court': ('csv', ),
        }
        ordering = [
            'dateFiled+desc',
            'dateFiled+asc',
            'citeCount+desc',
            'citeCount+asc',
            'score+desc',
        ]

    def get_resource_uri(self,
                         bundle_or_obj=None,
                         url_name='api_dispatch_list'):
        """Creates a URI like /api/v1/search/$id/
        """
        url_str = '/api/rest/%s/%s/%s/'
        if bundle_or_obj:
            return url_str % (
                self.api_name,
                'opinion',
                bundle_or_obj.obj.id,
            )
        else:
            return ''

    def get_object_list(self, request=None, **kwargs):
        """Performs the Solr work."""
        main_query = {'caller': 'api_search'}
        try:
            main_query.update(build_main_query(kwargs['cd'], highlight='text'))
            sl = SolrList(main_query=main_query,
                          offset=request.GET.get('offset', 0),
                          limit=request.GET.get('limit', 20),
                          type=kwargs['cd']['type'])
        except KeyError:
            sf = forms.SearchForm({'q': "*:*"})
            if sf.is_valid():
                main_query.update(
                    build_main_query(sf.cleaned_data, highlight='text'))
            sl = SolrList(
                main_query=main_query,
                offset=request.GET.get('offset', 0),
                limit=request.GET.get('limit', 20),
            )

        return sl

    def obj_get_list(self, bundle, **kwargs):
        search_form = forms.SearchForm(bundle.request.GET)
        if search_form.is_valid():
            cd = search_form.cleaned_data
            if cd['q'] == '':
                cd['q'] = '*:*'  # Get everything.
            return self.get_object_list(bundle.request, cd=cd)
        else:
            BadRequest("Invalid resource lookup data provided. Unable to "
                       "complete your query.")

    def obj_get(self, bundle, **kwargs):
        search_form = forms.SearchForm(bundle.request.GET)
        if search_form.is_valid():
            cd = search_form.cleaned_data
            cd['q'] = 'id:%s' % kwargs['pk']
            return self.get_object_list(bundle.request, cd=cd)[0]
        else:
            BadRequest("Invalid resource lookup data provided. Unable to "
                       "complete your request.")

    def apply_sorting(self, obj_list, options=None):
        """Since we're not using Django Model sorting, we just want to use our
        own, which is already passed into the search form anyway.

        Thus: Do nothing here.
        """
        return obj_list
Esempio n. 22
0
File: api.py Progetto: iobis/geonode
class ThesaurusKeywordResource(TypeFilteredResource):
    """ThesaurusKeyword api"""

    thesaurus_identifier = fields.CharField(null=False)
    label_id = fields.CharField(null=False)

    def build_filters(self, filters={}, ignore_bad_filters=False):
        """adds filtering by current language"""
        _filters = filters.copy()
        id = _filters.pop('id', None)
        orm_filters = super().build_filters(_filters)

        if id is not None:
            orm_filters['id__in'] = id

        if 'thesaurus' in _filters:
            orm_filters['thesaurus__identifier'] = _filters['thesaurus']

        return orm_filters

    def serialize(self, request, data, format, options={}):
        options['count_type'] = 'tkeywords__id'

        return super().serialize(request, data, format, options)

    def dehydrate_id(self, bundle):
        return bundle.obj.id

    def dehydrate_label_id(self, bundle):
        return bundle.obj.id

    def dehydrate_thesaurus_identifier(self, bundle):
        return bundle.obj.thesaurus.identifier

    def dehydrate(self, bundle):
        lang = get_language()
        label = ThesaurusKeywordLabel.objects.filter(
            keyword=bundle.data['id']).filter(lang=lang)
        if label.exists():
            bundle.data['label_id'] = label.get().id
            bundle.data['label'] = label.get().label
            bundle.data['alt_label'] = label.get().label
        else:
            bundle.data['label'] = bundle.data['alt_label']

        return bundle

    class Meta:
        queryset = ThesaurusKeyword.objects \
            .all() \
            .order_by('alt_label') \
            .select_related('thesaurus')

        resource_name = 'thesaurus/keywords'
        allowed_methods = ['get']
        filtering = {
            'id': ALL,
            'alt_label': ALL,
            'thesaurus': ALL,
        }
        serializer = CountJSONSerializer()
        authorization = ApiLockdownAuthorization()
Esempio n. 23
0
class CommonTemplateResource(GCloudModelResource):
    pipeline_template = fields.ForeignKey(
        PipelineTemplateResource,
        'pipeline_template')
    name = fields.CharField(
        attribute='name',
        readonly=True,
        null=True)
    category_name = fields.CharField(
        attribute='category_name',
        readonly=True,
        null=True)
    creator_name = fields.CharField(
        attribute='creator_name',
        readonly=True,
        null=True)
    editor_name = fields.CharField(
        attribute='editor_name',
        readonly=True,
        null=True)
    create_time = fields.DateTimeField(
        attribute='create_time',
        readonly=True,
        null=True)
    edit_time = fields.DateTimeField(
        attribute='edit_time',
        readonly=True,
        null=True)
    pipeline_tree = fields.DictField(
        attribute='pipeline_tree',
        use_in='detail',
        readonly=True,
        null=True)
    template_id = fields.IntegerField(
        attribute='template_id',
        readonly=True)
    subprocess_info = fields.DictField(
        attribute='subprocess_info',
        use_in='detail',
        readonly=True
    )
    version = fields.CharField(
        attribute='version',
        readonly=True,
        null=True
    )
    subprocess_has_update = fields.BooleanField(
        attribute='subprocess_has_update',
        use_in='list',
        readonly=True
    )

    class Meta:
        queryset = CommonTemplate.objects.filter(pipeline_template__isnull=False, is_deleted=False)
        resource_name = 'common_template'
        authorization = CommonAuthorization()
        always_return_data = True
        serializer = AppSerializer()
        filtering = {
            "id": ALL,
            "name": ALL,
            "category": ALL,
            "pipeline_template": ALL_WITH_RELATIONS,
            "subprocess_has_update": ALL,
            "has_subprocess": ALL
        }
        q_fields = ["id", "pipeline_template__name"]
        limit = 0
        paginator_class = TemplateFilterPaginator

    @staticmethod
    def handle_template_name_attr(data):
        data['name'] = name_handler(data['name'],
                                    TEMPLATE_NODE_NAME_MAX_LENGTH)
        pipeline_node_name_handle(data['pipeline_tree'])

    def dehydrate_pipeline_tree(self, bundle):
        return json.dumps(bundle.data['pipeline_tree'])

    def alter_list_data_to_serialize(self, request, data):
        user_model = get_user_model()
        user = request.user
        collected_templates = user_model.objects.get(username=user.username) \
            .tasktemplate_set.all() \
            .values_list('id', flat=True)
        for bundle in data['objects']:
            if bundle.obj.id in collected_templates:
                bundle.data['is_add'] = 1
            else:
                bundle.data['is_add'] = 0

        return data

    def obj_create(self, bundle, **kwargs):
        model = bundle.obj.__class__
        try:
            pipeline_template_kwargs = {
                'name': bundle.data.pop('name'),
                'creator': bundle.request.user.username,
                'pipeline_tree': json.loads(bundle.data.pop('pipeline_tree')),
                'description': bundle.data.pop('description', ''),
            }
        except (KeyError, ValueError) as e:
            raise BadRequest(e.message)
        # XSS handle
        self.handle_template_name_attr(pipeline_template_kwargs)
        # validate pipeline tree
        try:
            validate_web_pipeline_tree(pipeline_template_kwargs['pipeline_tree'])
        except PipelineException as e:
            raise BadRequest(e.message)
        # Note: tastypie won't use model's create method
        try:
            pipeline_template = model.objects.create_pipeline_template(
                **pipeline_template_kwargs)
        except PipelineException as e:
            raise BadRequest(e.message)
        except CommonTemplate.DoesNotExist:
            raise BadRequest('flow template referred as SubProcess does not exist')
        kwargs['pipeline_template_id'] = pipeline_template.template_id
        return super(CommonTemplateResource, self).obj_create(bundle, **kwargs)

    def obj_update(self, bundle, skip_errors=False, **kwargs):
        obj = bundle.obj
        try:
            pipeline_template_kwargs = {
                'name': bundle.data.pop('name'),
                'editor': bundle.request.user.username,
                'pipeline_tree': json.loads(bundle.data.pop('pipeline_tree')),
            }
            if 'description' in bundle.data:
                pipeline_template_kwargs['description'] = bundle.data.pop('description')
        except (KeyError, ValueError) as e:
            raise BadRequest(e.message)
        # XSS handle
        self.handle_template_name_attr(pipeline_template_kwargs)
        try:
            obj.update_pipeline_template(**pipeline_template_kwargs)
        except PipelineException as e:
            raise BadRequest(e.message)
        bundle.data['pipeline_template'] = '/api/v3/pipeline_template/%s/' % obj.pipeline_template.pk
        return super(CommonTemplateResource, self).obj_update(bundle, **kwargs)

    def obj_delete(self, bundle, **kwargs):
        try:
            common_tmpl = CommonTemplate.objects.get(id=kwargs['pk'], is_deleted=False)
        except CommonTemplate.DoesNotExist:
            raise NotFound('flow template does not exist')
        referencer = common_tmpl.referencer()
        if referencer:
            flat = ','.join(['%s:%s' % (item['id'], item['name']) for item in referencer])
            raise BadRequest('flow template are referenced by other templates[%s], please delete them first' % flat)
        result = super(CommonTemplateResource, self).obj_delete(bundle, **kwargs)
        if result:
            common_tmpl.set_deleted()
        return result

    def build_filters(self, filters=None, ignore_bad_filters=False):
        filters = super(CommonTemplateResource, self).build_filters(filters=filters,
                                                                    ignore_bad_filters=ignore_bad_filters)

        if 'subprocess_has_update__exact' in filters:
            filters.pop('subprocess_has_update__exact')
        if 'has_subprocess__exact' in filters:
            filters.pop('has_subprocess__exact')

        return filters
Esempio n. 24
0
File: api.py Progetto: iobis/geonode
class ProfileResource(TypeFilteredResource):
    """Profile api"""
    avatar_100 = fields.CharField(null=True)
    profile_detail_url = fields.CharField()
    email = fields.CharField(default='')
    layers_count = fields.IntegerField(default=0)
    maps_count = fields.IntegerField(default=0)
    documents_count = fields.IntegerField(default=0)
    current_user = fields.BooleanField(default=False)
    activity_stream_url = fields.CharField(null=True)

    def build_filters(self, filters=None, ignore_bad_filters=False):
        """adds filtering by group functionality"""
        if filters is None:
            filters = {}

        orm_filters = super().build_filters(filters)

        if 'group' in filters:
            orm_filters['group'] = filters['group']

        if 'name__icontains' in filters:
            orm_filters['username__icontains'] = filters['name__icontains']

        return orm_filters

    def apply_filters(self, request, applicable_filters):
        """filter by group if applicable by group functionality"""

        group = applicable_filters.pop('group', None)
        name = applicable_filters.pop('name__icontains', None)

        semi_filtered = super().apply_filters(request, applicable_filters)

        if group is not None:
            semi_filtered = semi_filtered.filter(
                groupmember__group__slug=group)

        if name is not None:
            semi_filtered = semi_filtered.filter(
                profile__first_name__icontains=name)

        return semi_filtered

    def dehydrate_email(self, bundle):
        email = ''
        if bundle.request.user.is_superuser:
            email = bundle.obj.email

        return email

    def dehydrate_datasets_count(self, bundle):
        obj_with_perms = get_objects_for_user(
            bundle.request.user, 'base.view_resourcebase').filter(
                polymorphic_ctype__model='dataset')
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).filter(metadata_only=False)\
            .distinct().count()

    def dehydrate_maps_count(self, bundle):
        obj_with_perms = get_objects_for_user(
            bundle.request.user,
            'base.view_resourcebase').filter(polymorphic_ctype__model='map')
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).filter(metadata_only=False)\
            .distinct().count()

    def dehydrate_documents_count(self, bundle):
        obj_with_perms = get_objects_for_user(
            bundle.request.user, 'base.view_resourcebase').filter(
                polymorphic_ctype__model='document')
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).filter(metadata_only=False)\
            .distinct().count()

    def dehydrate_avatar_100(self, bundle):
        return avatar_url(bundle.obj, 240)

    def dehydrate_profile_detail_url(self, bundle):
        return bundle.obj.get_absolute_url()

    def dehydrate_current_user(self, bundle):
        return bundle.request.user.username == bundle.obj.username

    def dehydrate_activity_stream_url(self, bundle):
        return reverse('actstream_actor',
                       kwargs={
                           'content_type_id':
                           ContentType.objects.get_for_model(bundle.obj).pk,
                           'object_id':
                           bundle.obj.pk
                       })

    def dehydrate(self, bundle):
        """
        Protects user's personal information from non staff
        """
        is_owner = bundle.request.user == bundle.obj
        is_admin = bundle.request.user.is_staff or bundle.request.user.is_superuser
        if not (is_owner or is_admin):
            bundle.data = dict(
                id=bundle.data.get('id', ''),
                username=bundle.data.get('username', ''),
                first_name=bundle.data.get('first_name', ''),
                last_name=bundle.data.get('last_name', ''),
                avatar_100=bundle.data.get('avatar_100', ''),
                profile_detail_url=bundle.data.get('profile_detail_url', ''),
                documents_count=bundle.data.get('documents_count', 0),
                maps_count=bundle.data.get('maps_count', 0),
                layers_count=bundle.data.get('layers_count', 0),
            )
        return bundle

    def prepend_urls(self):
        if settings.HAYSTACK_SEARCH:
            return [
                url(r"^(?P<resource_name>{})/search{}$".format(
                    self._meta.resource_name, trailing_slash()),
                    self.wrap_view('get_search'),
                    name="api_get_search"),
            ]
        else:
            return []

    def serialize(self, request, data, format, options=None):
        if options is None:
            options = {}
        options['count_type'] = 'owner'

        return super().serialize(request, data, format, options)

    class Meta:
        queryset = get_user_model().objects.exclude(
            Q(username='******') | Q(is_active=False))
        resource_name = 'profiles'
        allowed_methods = ['get']
        ordering = ['username', 'date_joined']
        excludes = [
            'is_staff', 'password', 'is_superuser', 'is_active', 'last_login'
        ]

        filtering = {
            'username': ALL,
        }
        serializer = CountJSONSerializer()
        authorization = ApiLockdownAuthorization()
Esempio n. 25
0
class BulkUserResource(HqBaseResource, DomainSpecificResourceMixin):
    """
    A read-only user data resource based on elasticsearch.
    Supported Params: limit offset q fields
    """
    type = "bulk-user"
    id = fields.CharField(attribute='id', readonly=True, unique=True)
    email = fields.CharField(attribute='email')
    username = fields.CharField(attribute='username', unique=True)
    first_name = fields.CharField(attribute='first_name', null=True)
    last_name = fields.CharField(attribute='last_name', null=True)
    phone_numbers = fields.ListField(attribute='phone_numbers', null=True)

    @staticmethod
    def to_obj(user):
        '''
        Takes a flat dict and returns an object
        '''
        if '_id' in user:
            user['id'] = user.pop('_id')
        return namedtuple('user', list(user))(**user)

    class Meta(CustomResourceMeta):
        authentication = RequirePermissionAuthentication(Permissions.edit_commcare_users)
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get']
        object_class = object
        resource_name = 'bulk-user'

    def dehydrate(self, bundle):
        fields = bundle.request.GET.getlist('fields')
        data = {}
        if not fields:
            return bundle
        for field in fields:
            data[field] = bundle.data[field]
        bundle.data = data
        return bundle

    def obj_get_list(self, bundle, **kwargs):
        request_fields = bundle.request.GET.getlist('fields')
        for field in request_fields:
            if field not in self.fields:
                raise BadRequest('{0} is not a valid field'.format(field))

        params = bundle.request.GET
        param = lambda p: params.get(p, None)
        fields = list(self.fields)
        fields.remove('id')
        fields.append('_id')
        fn = MOCK_BULK_USER_ES or user_es_call
        users = fn(
            domain=kwargs['domain'],
            q=param('q'),
            fields=fields,
            size=param('limit'),
            start_at=param('offset'),
        )
        return list(map(self.to_obj, users))

    def detail_uri_kwargs(self, bundle_or_obj):
        return {
            'pk': get_obj(bundle_or_obj).id
        }
Esempio n. 26
0
class MemberResource(BaseResource):
    ''' The Parliament Member API '''
    class Meta(BaseResource.Meta):

        queryset = Member.objects.exclude(
            current_party__isnull=True).select_related('current_party')

        allowed_methods = ['get']
        ordering = [
            'name',
            'is_current',
            'bills_stats_proposed',
            'bills_stats_pre',
            'bills_stats_first',
            'bills_stats_approved',
        ]

        filtering = dict(
            name=ALL,
            is_current=ALL,
        )

        excludes = ['website', 'backlinks_enabled', 'area_of_residence']
        list_fields = ['name', 'id', 'img_url', 'is_current']
        include_absolute_url = True

    party_name = fields.CharField()
    party_url = fields.CharField()
    mmms_count = fields.IntegerField(null=True)
    votes_count = fields.IntegerField(null=True)
    video_about = fields.ToManyField(
        VideoResource,
        attribute=lambda b: get_videos_queryset(b.obj, group='about'),
        null=True,
        full=True)
    videos_related = fields.ToManyField(
        VideoResource,
        attribute=lambda b: get_videos_queryset(b.obj, group='related'),
        null=True)
    links = fields.ToManyField(
        LinkResource,
        attribute=lambda b: Link.objects.for_model(b.obj),
        full=True,
        null=True)
    bills_uri = fields.CharField()
    agendas_uri = fields.CharField()
    committees = fields.ListField()

    def dehydrate_committees(self, bundle):
        temp_list = bundle.obj.committee_meetings.values(
            "committee",
            "committee__name").annotate(Count("id")).order_by('-id__count')[:5]
        return (map(
            lambda item:
            (item['committee__name'],
             reverse('committee-detail', args=[item['committee']])),
            temp_list))

    def dehydrate_bills_uri(self, bundle):
        return '%s?%s' % (reverse(
            'api_dispatch_list',
            kwargs={
                'resource_name': 'bill',
                'api_name': 'v2',
            }), urllib.urlencode(dict(proposer=bundle.obj.id)))

    def dehydrate_gender(self, bundle):
        return bundle.obj.get_gender_display()

    def dehydrate_agendas_uri(self, bundle):
        return reverse('api_dispatch_detail',
                       kwargs={
                           'resource_name': 'member-agendas',
                           'api_name': 'v2',
                           'pk': bundle.obj.id
                       })

    def dehydrate_party_name(self, bundle):
        return bundle.obj.current_party.name

    def dehydrate_party_url(self, bundle):
        return bundle.obj.current_party.get_absolute_url()

    def dehydrate_mmms_count(self, bundle):
        _cache_key = 'api_v2_member_mmms_' + str(bundle.obj.pk)
        count = cache.get(_cache_key)

        if count is None:
            count = bundle.obj.mmm_documents.count()
            cache.set(_cache_key, count, 24 * 3600)

        return count

    def dehydrate_votes_count(self, bundle):
        _cache_key = 'api_v2_member_votes_' + str(bundle.obj.pk)
        count = cache.get(_cache_key)

        if count is None:
            count = bundle.obj.votes.count()
            cache.set(_cache_key, count, 24 * 3600)

        return count

    fields.ToOneField(PartyResource, 'current_party', full=True)

    def build_filters(self, filters=None):
        if filters is None:
            filters = {}

        try:
            knesset = int(filters.get('knesset', 0))
        except KeyError:
            knesset = 0

        orm_filters = super(MemberResource, self).build_filters(filters)

        if knesset:
            knesset = Knesset.objects.get(number=knesset)
            orm_filters['parties__knesset'] = knesset

        return orm_filters
Esempio n. 27
0
class WFPDocumentResource(ModelResource):
    """Resource for Static Map"""

    keywords = fields.ToManyField(TagResource, 'keywords', null=True)
    categories = fields.ToManyField(CategoryResource, 'categories', full=True)
    regions = fields.ToManyField(RegionResource, 'regions', full=True)
    file_size = fields.CharField(attribute='get_file_size', readonly=True)
    geonode_page = fields.CharField(attribute='detail_url', readonly=True)
    geonode_file = fields.FileField(attribute='doc_file')
    thumbnail = fields.CharField(attribute='thumbnail',
                                 readonly=True,
                                 null=True)
    is_public = fields.BooleanField(default=True)

    class Meta(CommonMetaApi):
        queryset = WFPDocument.objects.all().order_by('-date')
        resource_name = 'staticmaps'
        filtering = {
            'title': ALL,
            'keywords': ALL_WITH_RELATIONS,
            'categories': ALL_WITH_RELATIONS,
            'regions': ALL_WITH_RELATIONS,
            'date': ALL,
        }
        excludes = [
            'abstract',
            'bbox_x0',
            'bbox_x1',
            'bbox_y0',
            'bbox_y1',
            'constraints_other',
            'csw_anytext',
            'csw_insert_date',
            'csw_mdsource',
            'csw_schema',
            'csw_type',
            'csw_typename',
            'csw_wkt_geometry',
            'data_quality_statement',
            'date_type',
            'distribution_description',
            'distribution_url',
            'edition',
            'extension',
            'featured',
            'is_published',
            'language',
            'maintenance_frequency',
            'metadata_uploaded',
            'metadata_xml',
            'owner',
            'share_count',
            'srid',
            'supplemental_information',
            'temporal_extent_end',
            'temporal_extent_start',
            # renamed
            'doc_file',
        ]

    def dehydrate_is_public(self, bundle):
        anonymous_user = get_anonymous_user()
        public_wfpdocs_ids = get_objects_for_user(
            anonymous_user,
            'base.view_resourcebase').instance_of(WFPDocument).values_list(
                'id', flat=True)
        return bundle.obj.id in public_wfpdocs_ids

    def dehydrate_page_format(self, bundle):
        return WFPDocument.FORMAT_CHOICES[bundle.data['page_format']][1]

    def dehydrate_orientation(self, bundle):
        return WFPDocument.ORIENTATION_CHOICES[bundle.data['orientation']][1]

    def dehydrate_thumbnail(self, bundle):
        url = urlparse(bundle.obj.thumbnail_url)
        return url.path

    def build_schema(self):
        base_schema = super(WFPDocumentResource, self).build_schema()
        for f in self._meta.object_class._meta.fields:
            if f.name in base_schema['fields'] and f.choices:
                base_schema['fields'][f.name].update({
                    'choices': f.choices,
                })
        return base_schema
Esempio n. 28
0
class MediaResource(ModelResource):

    release = fields.ForeignKey('alibrary.api.ReleaseResource',
                                'release',
                                null=True,
                                full=True,
                                max_depth=2)
    artist = fields.ForeignKey('alibrary.api.ArtistResource',
                               'artist',
                               null=True,
                               full=True,
                               max_depth=2)
    message = fields.CharField(attribute='message', null=True)

    class Meta:
        queryset = Media.objects.order_by('tracknumber').all()
        list_allowed_methods = [
            'get',
        ]
        detail_allowed_methods = [
            'get',
        ]
        resource_name = 'library/track'
        detail_uri_name = 'uuid'
        excludes = ['updated', 'release__media']
        include_absolute_url = True
        authentication = MultiAuthentication(ApiKeyAuthentication(),
                                             SessionAuthentication(),
                                             Authentication())
        authorization = Authorization()
        limit = 50
        filtering = {
            'created': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'],
            'id': ['exact', 'in'],
        }

    def apply_sorting(self, obj_list, options=None):

        sorting = options.get('id__in', None)
        if not sorting:
            return obj_list

        obj_list_sorted = list()
        for pk in sorting.split(','):
            obj_list_sorted.append(obj_list.get(pk=int(pk)))

        return obj_list_sorted

    def dehydrate(self, bundle):

        obj = bundle.obj

        if obj.master:
            stream = {
                'uri':
                reverse_lazy('mediaasset-format',
                             kwargs={
                                 'media_uuid': bundle.obj.uuid,
                                 'quality': 'default',
                                 'encoding': 'mp3',
                             }),
            }
        else:
            stream = None

        bundle.data['stream'] = stream
        bundle.data['duration'] = bundle.obj.get_duration()
        bundle.data['waveform_image'] = reverse_lazy('mediaasset-waveform',
                                                     kwargs={
                                                         'media_uuid':
                                                         bundle.obj.uuid,
                                                         'type': 'w'
                                                     })
        bundle.data['spectrogram_image'] = reverse_lazy('mediaasset-waveform',
                                                        kwargs={
                                                            'media_uuid':
                                                            bundle.obj.uuid,
                                                            'type':
                                                            's'
                                                        })

        bundle.data['relations'] = relations_for_object(bundle.obj)

        # TODO: find a nicer way - disable ops-cache
        obj = Media.objects.filter(pk=obj.pk).nocache()[0]

        # votes
        try:
            user_vote = obj.votes.filter(user=bundle.request.user)[0].vote
        except (TypeError, IndexError) as e:
            user_vote = None

        try:
            votes = {
                'up': obj.total_upvotes,
                'down': obj.total_downvotes,
                'total': obj.vote_total,
                'user': user_vote,
            }
        except AttributeError as e:
            votes = None
        bundle.data['votes'] = votes
        """
        count playlist usage - #914
        """
        bundle.data['playlist_usage'] = len(bundle.obj.get_appearances())

        bundle.data['bitrate'] = bundle.obj.bitrate

        bundle.data['tags'] = [tag.name for tag in bundle.obj.tags]
        """
        TODO: verry hackish and incomplete imnplementation.
        label includes are needed for on-air app. should be built more flexible in the future!
        """
        if bundle.request.GET.get('includes', None):
            includes = bundle.request.GET['includes'].split(',')
            if 'label' in includes:
                try:
                    from alibrary.api.labelapi import LabelResource
                    label = bundle.obj.release.label
                    label_bundle = LabelResource().build_bundle(
                        obj=label, request=bundle.request)
                    label_resource = LabelResource().full_dehydrate(
                        label_bundle)
                except:
                    label_resource = None

                bundle.data['label'] = label_resource

        return bundle

    def build_filters(self, filters=None):
        """ Enable querying by fingerprint """
        if filters is None:
            filters = {}

        orm_filters = super(MediaResource, self).build_filters(filters)

        if "code" in filters:
            # re-implement fprint based lookups
            pass

        return orm_filters

    def prepend_urls(self):

        return [
            url(r"^(?P<resource_name>%s)/autocomplete%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('autocomplete'),
                name="alibrary-media_api-autocomplete"),
            url(r"^(?P<resource_name>%s)/(?P<uuid>\w[\w/-]*)/vote%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('vote'),
                name="alibrary-media_api-vote"),
            url(r"^(?P<resource_name>%s)/(?P<uuid>\w[\w/-]*)/stats%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('stats'),
                name="alibrary-media_api-stats"),
            url(r"^(?P<resource_name>%s)/(?P<uuid>\w[\w/-]*)/stream.mp3$" %
                self._meta.resource_name,
                self.wrap_view('stream_file'),
                name="alibrary-media_api-stream"),
        ]

    def autocomplete(self, request, **kwargs):

        self.method_check(request, allowed=['get'])
        self.throttle_check(request)

        q = request.GET.get('q', None)
        result = []
        object_list = []
        objects = []
        object_count = 0

        qs = None

        if q and len(q) > 1:

            # haystack version
            #sqs = SearchQuerySet().models(Media).filter(SQ(content__contains=q) | SQ(content_auto=q))
            sqs = SearchQuerySet().models(Media).filter(content=AutoQuery(q))
            qs = Media.objects.filter(
                id__in=[result.object.pk for result in sqs]).distinct()

            # ORM version
            #qs = Media.objects.order_by('name').filter(name__icontains=q)

            object_list = qs.distinct()[0:50]
            object_count = qs.distinct().count()

            for result in object_list:
                bundle = self.build_bundle(obj=result, request=request)
                bundle = self.autocomplete_dehydrate(bundle, q)
                objects.append(bundle)

        data = {
            'meta': {
                'query': q,
                'total_count': object_count
            },
            'objects': objects,
        }

        self.log_throttled_access(request)
        return self.create_response(request, data)

    def autocomplete_dehydrate(self, bundle, q):

        bundle.data['name'] = bundle.obj.name
        bundle.data['id'] = bundle.obj.pk
        bundle.data['ct'] = 'media'
        bundle.data['get_absolute_url'] = bundle.obj.get_absolute_url()
        bundle.data['resource_uri'] = bundle.obj.get_api_url()
        bundle.data['main_image'] = None
        bundle.data['duration'] = bundle.obj.get_duration()
        try:
            bundle.data['artist'] = bundle.obj.artist.name
        except:
            bundle.data['artist'] = None
        try:
            bundle.data['release'] = bundle.obj.release.name
        except:
            bundle.data['release'] = None
        try:
            opt = THUMBNAIL_OPT
            main_image = get_thumbnailer(
                bundle.obj.release.main_image).get_thumbnail(opt)
            bundle.data['main_image'] = main_image.url
        except:
            pass

        return bundle

    def vote(self, request, **kwargs):

        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        obj = Media.objects.get(**self.remove_api_resource_names(kwargs))

        # votes
        try:
            user_vote = obj.votes.filter(user=request.user)[0].vote
        except (TypeError, IndexError) as e:
            user_vote = None

        votes = {
            'up': obj.total_upvotes,
            'down': obj.total_downvotes,
            'total': obj.vote_total,
            'user': user_vote,
        }

        self.log_throttled_access(request)
        return self.create_response(request, votes)

    def stats(self, request, **kwargs):

        self.method_check(request, allowed=['get'])
        #self.is_authenticated(request)
        self.throttle_check(request)

        obj = Media.objects.get(**self.remove_api_resource_names(kwargs))

        from statistics.util import ObjectStatistics
        ostats = ObjectStatistics(obj=obj)
        stats = ostats.generate()

        self.log_throttled_access(request)
        return self.create_response(request, stats)

    def stream_file(self, request, **kwargs):
        """
        provides the default stream file as download.
        method is only used by API clients (radio website) at the moment
        """

        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        if not (request.user.has_perm('alibrary.play_media')):
            return HttpResponseForbidden('sorry. no permissions here!')

        obj = Media.objects.get(**self.remove_api_resource_names(kwargs))

        from media_asset.util import get_format

        format = get_format(obj, wait=True)

        return sendfile(request, format.path)
Esempio n. 29
0
class ProfileResource(TypeFilteredResource):
    """Profile api"""

    avatar_100 = fields.CharField(null=True)
    profile_detail_url = fields.CharField()
    email = fields.CharField(default='')
    layers_count = fields.IntegerField(default=0)
    maps_count = fields.IntegerField(default=0)
    documents_count = fields.IntegerField(default=0)
    current_user = fields.BooleanField(default=False)
    activity_stream_url = fields.CharField(null=True)

    def build_filters(self, filters={}):
        """adds filtering by group functionality"""

        orm_filters = super(ProfileResource, self).build_filters(filters)

        if 'group' in filters:
            orm_filters['group'] = filters['group']

        return orm_filters

    def apply_filters(self, request, applicable_filters):
        """filter by group if applicable by group functionality"""

        group = applicable_filters.pop('group', None)

        semi_filtered = super(
            ProfileResource,
            self).apply_filters(
            request,
            applicable_filters)

        if group is not None:
            semi_filtered = semi_filtered.filter(
                groupmember__group__slug=group)

        return semi_filtered

    def dehydrate_email(self, bundle):
        email = ''
        if bundle.request.user.is_authenticated():
            email = bundle.obj.email
        return email

    def dehydrate_layers_count(self, bundle):
        obj_with_perms = get_objects_for_user(bundle.request.user,
                                              'base.view_resourcebase').instance_of(Layer)
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).distinct().count()

    def dehydrate_maps_count(self, bundle):
        obj_with_perms = get_objects_for_user(bundle.request.user,
                                              'base.view_resourcebase').instance_of(Map)
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).distinct().count()

    def dehydrate_documents_count(self, bundle):
        obj_with_perms = get_objects_for_user(bundle.request.user,
                                              'base.view_resourcebase').instance_of(Document)
        return bundle.obj.resourcebase_set.filter(id__in=obj_with_perms.values('id')).distinct().count()

    def dehydrate_avatar_100(self, bundle):
        return avatar_url(bundle.obj, 100)

    def dehydrate_profile_detail_url(self, bundle):
        return bundle.obj.get_absolute_url()

    def dehydrate_current_user(self, bundle):
        return bundle.request.user.username == bundle.obj.username

    def dehydrate_activity_stream_url(self, bundle):
        return reverse(
            'actstream_actor',
            kwargs={
                'content_type_id': ContentType.objects.get_for_model(
                    bundle.obj).pk,
                'object_id': bundle.obj.pk})

    def prepend_urls(self):
        if settings.HAYSTACK_SEARCH:
            return [
                url(r"^(?P<resource_name>%s)/search%s$" % (
                    self._meta.resource_name, trailing_slash()
                ),
                    self.wrap_view('get_search'), name="api_get_search"),
            ]
        else:
            return []

    def serialize(self, request, data, format, options={}):
        options['count_type'] = 'owner'

        return super(ProfileResource, self).serialize(request, data, format, options)

    class Meta:
        queryset = get_user_model().objects.exclude(username='******')
        resource_name = 'profiles'
        allowed_methods = ['get']
        ordering = ['username', 'date_joined']
        excludes = ['is_staff', 'password', 'is_superuser',
                    'is_active', 'last_login']

        filtering = {
            'username': ALL,
        }
        serializer = CountJSONSerializer()
Esempio n. 30
0
class UserResource(ClientCacheResourceMixIn, GraphiteMixIn, ModelResource):
    """User Resource."""
    email = fields.CharField(attribute='user__email', null=True, readonly=True)
    username = fields.CharField(attribute='user__username',
                                null=True,
                                readonly=True)
    vouched_by = fields.IntegerField(attribute='vouched_by__id',
                                     null=True,
                                     readonly=True)
    groups = fields.CharField()
    skills = fields.CharField()
    languages = fields.CharField()
    url = fields.CharField()
    accounts = fields.CharField()

    class Meta:
        queryset = UserProfile.objects.all()
        authentication = AppAuthentication()
        authorization = ReadOnlyAuthorization()
        serializer = Serializer(formats=['json', 'jsonp'])
        paginator_class = Paginator
        cache_control = {'max-age': 0}
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get']
        resource_name = 'users'
        restrict_fields = False
        restricted_fields = ['email', 'is_vouched']
        fields = [
            'id', 'full_name', 'is_vouched', 'vouched_by', 'date_vouched',
            'groups', 'skills', 'bio', 'photo', 'ircname', 'country', 'region',
            'city', 'date_mozillian', 'timezone', 'email',
            'allows_mozilla_sites', 'allows_community_sites'
        ]

    def build_filters(self, filters=None):
        database_filters = {}
        valid_filters = [
            f for f in filters if f in [
                'email', 'country', 'region', 'city', 'ircname', 'username',
                'groups', 'skills', 'is_vouched', 'name', 'accounts'
            ]
        ]
        getvalue = lambda x: unquote(filters[x].lower())

        if 'accounts' in valid_filters:
            database_filters['accounts'] = Q(
                externalaccount__identifier__icontains=getvalue('accounts'))

        if 'email' in valid_filters:
            database_filters['email'] = Q(
                user__email__iexact=getvalue('email'))

        if 'username' in valid_filters:
            database_filters['username'] = Q(
                user__username__iexact=getvalue('username'))

        if 'name' in valid_filters:
            database_filters['name'] = Q(full_name__iexact=getvalue('name'))

        if 'is_vouched' in valid_filters:
            value = getvalue('is_vouched')
            if value == 'true':
                database_filters['is_vouched'] = Q(is_vouched=True)
            elif value == 'false':
                database_filters['is_vouched'] = Q(is_vouched=False)

        for possible_filter in ['country', 'region', 'city', 'ircname']:
            if possible_filter in valid_filters:
                database_filters[possible_filter] = Q(
                    **{
                        '{0}__iexact'.format(possible_filter):
                        getvalue(possible_filter)
                    })

        for group_filter in ['groups', 'skills']:
            if group_filter in valid_filters:
                database_filters[group_filter] = Q(
                    **{
                        '{0}__name__in'.format(group_filter):
                        getvalue(group_filter).split(',')
                    })

        return database_filters

    def dehydrate(self, bundle):
        if (bundle.request.GET.get('restricted', False)
                or not bundle.data['allows_mozilla_sites']):
            data = {}
            for key in self._meta.restricted_fields:
                data[key] = bundle.data[key]
            bundle = Bundle(obj=bundle.obj, data=data, request=bundle.request)
        return bundle

    def dehydrate_accounts(self, bundle):
        accounts = [{
            'identifier': a.identifier,
            'type': a.type
        } for a in bundle.obj.externalaccount_set.all()]
        return accounts

    def dehydrate_groups(self, bundle):
        groups = bundle.obj.groups.values_list('name', flat=True)
        return list(groups)

    def dehydrate_skills(self, bundle):
        skills = bundle.obj.skills.values_list('name', flat=True)
        return list(skills)

    def dehydrate_languages(self, bundle):
        languages = bundle.obj.languages.values_list('code', flat=True)
        return list(languages)

    def dehydrate_photo(self, bundle):
        if bundle.obj.photo:
            return urljoin(settings.SITE_URL, bundle.obj.photo.url)
        return ''

    def dehydrate_url(self, bundle):
        url = reverse('phonebook:profile_view',
                      args=[bundle.obj.user.username])
        return utils.absolutify(url)

    def get_detail(self, request, **kwargs):
        if request.GET.get('restricted', False):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        return super(UserResource, self).get_detail(request, **kwargs)

    def apply_filters(self, request, applicable_filters):
        if (request.GET.get('restricted', False)
                and 'email' not in applicable_filters
                and len(applicable_filters) != 1):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        mega_filter = Q()
        for db_filter in applicable_filters.values():
            mega_filter &= db_filter

        if request.GET.get('restricted', False):
            mega_filter &= Q(allows_community_sites=True)

        return UserProfile.objects.complete().filter(
            mega_filter).distinct().order_by('id')