Пример #1
0
class BackendResource(ModelResource):
    dc = fields.ForeignKey(DcResource, 'dc', full=True)
    director = fields.ForeignKey(DirectorResource, 'director')
    tags = ListField()

    class Meta:
        queryset = Backend.objects.all()
        resource_name = 'backend'
        serializer = PrettyJSONSerializer()
        authorization = DjangoAuthorization()
        authentication = VaasMultiAuthentication(ApiKeyAuthentication())
        validation = ModelCleanedDataFormValidation(
            form_class=BackendModelForm)
        always_return_data = True
        filtering = {
            'dc': ALL_WITH_RELATIONS,
            'director': ALL_WITH_RELATIONS,
            'address': ['exact'],
            'port': ['exact']
        }

    def dehydrate(self, bundle):
        status = BackendStatus.objects.filter(address=bundle.data['address'],
                                              port=bundle.data['port'])
        if len(status) > 0:
            bundle.data['status'] = status[0].status
        else:
            bundle.data['status'] = "Unknown"

        bundle.data['time_profile'] = {
            'max_connections':
            bundle.obj.director.time_profile.max_connections,
            'connect_timeout':
            bundle.obj.director.time_profile.connect_timeout,
            'first_byte_timeout':
            bundle.obj.director.time_profile.first_byte_timeout,
            'between_bytes_timeout':
            bundle.obj.director.time_profile.between_bytes_timeout
        }

        return bundle

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

        orm_filters = super(BackendResource, self).build_filters(
            filters, ignore_bad_filters=ignore_bad_filters)

        if 'tag' in filters:
            orm_filters['tags__name__in'] = filters['tag'].split(',')
        return orm_filters

    def dehydrate_tags(self, bundle):
        return list(map(str, bundle.obj.tags.all()))

    def hydrate_tags(self, bundle):
        if isinstance(bundle.data.get('tags'), list):
            bundle.data['tags'] = ','.join(bundle.data['tags'])
        elif bundle.data.get('tags') is None:
            bundle.data['tags'] = ''
        return bundle

    def save_m2m(self, bundle):
        tags = bundle.data.get('tags', [])
        bundle.obj.tags.set(*tags)
        return super(BackendResource, self).save_m2m(bundle)
Пример #2
0
class PressReleaseResource(ModelResource):
    issue_uri = fields.ForeignKey(IssueResource, 'issue')
    translations = fields.OneToManyField(PressReleaseTranslationResource,
                                         'translations',
                                         full=True)
    articles = fields.CharField(readonly=True)
    issue_meta = fields.CharField(readonly=True)

    class Meta(ApiKeyAuthMeta):
        resource_name = 'pressreleases'
        queryset = RegularPressRelease.objects.all()
        allowed_methods = [
            'get',
        ]
        ordering = ['id']

    def build_filters(self, filters=None):
        """
        Custom filter that retrieves data by the article PID.
        """
        if filters is None:
            filters = {}

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

        if 'article_pid' in filters:
            preleases = RegularPressRelease.objects.filter(
                articles__article_pid=filters['article_pid'])
            orm_filters['pk__in'] = preleases

        elif 'journal_pid' in filters:
            preleases = RegularPressRelease.objects.by_journal_pid(
                filters['journal_pid'])
            orm_filters['pk__in'] = preleases
        elif 'issue_pid' in filters:
            preleases = RegularPressRelease.objects.by_issue_pid(
                filters['issue_pid'])
            orm_filters['pk__in'] = preleases

        return orm_filters

    def dehydrate_articles(self, bundle):
        return [art.article_pid for art in bundle.obj.articles.all()]

    def dehydrate_issue_meta(self, bundle):
        issue = bundle.obj.issue

        meta_data = {
            'scielo_pid':
            issue.scielo_pid,
            'short_title':
            issue.journal.short_title,
            'volume':
            issue.volume,
            'number':
            issue.number,
            'suppl_volume':
            issue.suppl_text
            if issue.type == 'supplement' and issue.volume else '',
            'suppl_number':
            issue.suppl_text
            if issue.type == 'supplement' and issue.number else '',
            'publication_start_month':
            issue.publication_start_month,
            'publication_end_month':
            issue.publication_end_month,
            'publication_city':
            issue.journal.publication_city,
            'publication_year':
            issue.publication_year,
        }

        return meta_data
Пример #3
0
class BaseAbuseResource(PotatoCaptchaResource, CORSResource,
                        MarketplaceResource):
    """
    Base resource for abuse reports.
    """
    text = fields.CharField(attribute='text')
    ip_address = fields.CharField(attribute='ip_address', blank=True)
    reporter = fields.ForeignKey(AccountResource, attribute='reporter',
                                 null=True, full=True)

    class Meta(MarketplaceResource.Meta):
        always_return_data = True
        list_allowed_methods = ['post']
        detail_allowed_methods = []
        authentication = OptionalOAuthAuthentication()
        authorization = Authorization()
        object_class = GenericObject
        include_resource_uri = False
        validation_form = None
        rename_field_map = [
            ('text', 'message'),
        ]
        throttle = CacheThrottle(throttle_at=30)

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

        bundle = self.full_hydrate(bundle)
        self.remove_potato(bundle)

        AbuseReport.objects.create(**self.rename_fields(bundle)).send()

        return bundle

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

    def hydrate(self, bundle):
        """
        Add the authenticated user to the bundle.
        """
        bundle.data.update({
            'reporter': bundle.request.amo_user,
            'ip_address': bundle.request.META.get('REMOTE_ADDR', '')
        })
        return bundle

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

    def rename_fields(self, bundle):
        """
        Rename fields as defined in Meta.rename_field_map. Used to rename
        fields in the bundle before sending to Model.objects.create().
        """
        data = bundle.data.copy()
        for old, new in self._meta.rename_field_map:
            data[new] = data[old]
            del data[old]
        return data
Пример #4
0
class TrackerResource(ModelResource):
    '''
    Submitting a Tracker
    '''
    user = fields.ForeignKey(UserResource, 'user')
    points = fields.IntegerField(readonly=True)
    badges = fields.IntegerField(readonly=True)
    scoring = fields.BooleanField(readonly=True)
    badging = fields.BooleanField(readonly=True)
    metadata = fields.CharField(readonly=True)
    course_points = fields.CharField(readonly=True)

    class Meta:
        queryset = Tracker.objects.all()
        resource_name = 'tracker'
        allowed_methods = ['post', 'patch']
        detail_allowed_methods = ['post', 'patch']
        authentication = ApiKeyAuthentication()
        authorization = Authorization()
        serializer = PrettyJSONSerializer()
        always_return_data = True
        fields = [
            'points', 'digest', 'data', 'tracker_date', 'badges', 'course',
            'completed', 'scoring', 'metadata', 'badging'
        ]
        validation = TrackerValidation()

    def process_tracker_bundle(self, bundle):
        try:
            if 'course' in bundle.data:
                media_objs = Media.objects.filter(
                    digest=bundle.data['digest'],
                    course__shortname=bundle.data['course'])[:1]
            else:
                media_objs = Media.objects.filter(
                    digest=bundle.data['digest'])[:1]
            if media_objs.count() > 0:
                media = media_objs[0]
                bundle.obj.course = media.course
                bundle.obj.type = 'media'
        except Media.DoesNotExist:
            pass

        try:
            json_data = json.loads(bundle.data['data'])
            if 'timetaken' in json_data:
                bundle.obj.time_taken = json_data['timetaken']
            if 'uuid' in json_data:
                bundle.obj.uuid = json_data['uuid']
            if 'lang' in json_data:
                bundle.obj.lang = json_data['lang']
        except ValueError:
            pass
        except KeyError:
            pass

        if 'points' in bundle.data:
            bundle.obj.points = bundle.data['points']

        if 'event' in bundle.data:
            bundle.obj.event = bundle.data['event']

        return bundle

    def hydrate(self, bundle, request=None):

        # remove any id if this is submitted - otherwise it may overwrite existing tracker item
        if 'id' in bundle.data:
            del bundle.obj.id
        bundle.obj.user = bundle.request.user
        bundle.obj.ip = bundle.request.META.get('REMOTE_ADDR',
                                                api.DEFAULT_IP_ADDRESS)
        bundle.obj.agent = bundle.request.META.get('HTTP_USER_AGENT',
                                                   'unknown')

        if 'type' in bundle.data and bundle.data['type'] == 'search':
            # if the tracker is a search, we just need to save it
            bundle.obj.course = None
            bundle.obj.type = "search"
            return bundle

        # find out the course & activity type from the digest
        try:
            if 'course' in bundle.data:
                activities = Activity.objects.filter(
                    digest=bundle.data['digest'],
                    section__course__shortname=bundle.data['course'])[:1]
            else:
                activities = Activity.objects.filter(
                    digest=bundle.data['digest'])[:1]
            if activities.count() > 0:
                activity = activities[0]
                bundle.obj.course = activity.section.course
                bundle.obj.type = activity.type
                bundle.obj.activity_title = activity.title
                bundle.obj.section_title = activity.section.title
            else:
                bundle.obj.course = None
                bundle.obj.type = ''
                bundle.obj.activity_title = ''
                bundle.obj.section_title = ''
        except Activity.DoesNotExist:
            bundle.obj.course = None
            bundle.obj.type = ''
            bundle.obj.activity_title = ''
            bundle.obj.section_title = ''

        bundle = self.process_tracker_bundle(bundle)

        return bundle

    def hydrate_tracker_date(self, bundle, request=None, **kwargs):
        # Fix tracker date if date submitted is in the future
        if 'tracker_date' in bundle.data:
            tracker_date = dateparse.parse_datetime(
                bundle.data['tracker_date'])
            if tracker_date > datetime.datetime.now():
                bundle.data['tracker_date'] = timezone.now()

        return bundle

    def dehydrate_points(self, bundle):
        points = Points.get_userscore(bundle.request.user)
        return points

    def dehydrate_badges(self, bundle):
        badges = Award.get_userawards(bundle.request.user)
        return badges

    def dehydrate_scoring(self, bundle):
        return settings.OPPIA_POINTS_ENABLED

    def dehydrate_badging(self, bundle):
        return settings.OPPIA_BADGES_ENABLED

    def dehydrate_metadata(self, bundle):
        return settings.OPPIA_METADATA

    def dehydrate_course_points(self, bundle):
        course_points = list(
            Points.objects.exclude(course=None).filter(
                user=bundle.request.user).values('course__shortname').annotate(
                    total_points=Sum('points')))
        return course_points

    def patch_list(self, request, **kwargs):
        request = convert_post_to_patch(request)
        deserialized = self.deserialize(request,
                                        request.body,
                                        format=request.META.get(
                                            'CONTENT_TYPE',
                                            'application/json'))
        for data in deserialized["objects"]:
            data = self.alter_deserialized_detail_data(request, data)
            bundle = self.build_bundle(data=dict_strip_unicode_keys(data))
            bundle.request.user = request.user
            bundle.request.META['REMOTE_ADDR'] = request.META.get(
                'REMOTE_ADDR', api.DEFAULT_IP_ADDRESS)
            bundle.request.META['HTTP_USER_AGENT'] = request.META.get(
                'HTTP_USER_AGENT', 'unknown')
            # check UUID not already submitted
            if 'data' in bundle.data:
                json_data = json.loads(bundle.data['data'])
                if 'uuid' in json_data:
                    uuids = Tracker.objects.filter(uuid=json_data['uuid'])
                    if uuids.count() == 0:
                        self.obj_create(bundle, request=request)
                else:
                    self.obj_create(bundle, request=request)
            else:
                self.obj_create(bundle, request=request)

        response_data = {
            'points': self.dehydrate_points(bundle),
            'badges': self.dehydrate_badges(bundle),
            'scoring': self.dehydrate_scoring(bundle),
            'badging': self.dehydrate_badging(bundle),
            'metadata': self.dehydrate_metadata(bundle),
            'course_points': self.dehydrate_course_points(bundle),
        }
        response = HttpResponse(content=json.dumps(response_data),
                                content_type="application/json; charset=utf-8")
        return response
Пример #5
0
class PipelineTemplateResource(ModelResource):
    data = fields.ForeignKey(SnapshotResource, 'snapshot')

    class Meta:
        queryset = PipelineTemplate.objects.filter(is_deleted=False)
        resource_name = 'templates'
        excludes = ['is_deleted']
        always_return_data = True
        detail_uri_name = 'template_id'
        list_allowed_methods = ['get', 'post']
        detail_allowed_methods = ['get', 'patch', 'post', 'delete']
        filtering = {
            'template_id': ALL_WITH_RELATIONS,
        }

        authorization = Authorization()
        serializer = PipelineSerializer()
        validation = FormValidation(form_class=forms.PipelineTemplateForm)

    def dehydrate_data(self, bundle):
        return json.dumps(bundle.obj.snapshot.data)

    def hydrate(self, bundle):
        pop_keys = ['template_id', 'create_time', 'edit_time', 'version']
        for key in pop_keys:
            if key in bundle.data:
                bundle.data.pop(key)

        return super(PipelineTemplateResource, self).hydrate(bundle)

    def obj_update(self, bundle, skip_errors=False, **kwargs):
        json_data = bundle.data['data']
        try:
            data = json.loads(json_data)
        except Exception:
            raise_validation_error(self, bundle, 'templates', 'data',
                                   _(u"JSON 格式不合法"))

        result, msg = self.subprocess_ref_validate(
            bundle,
            data,
            root_id=bundle.obj.template_id,
            root_name=bundle.obj.name)
        if not result:
            raise_validation_error(self, bundle, 'templates', 'data', msg)
        self.gateway_validate(bundle, data)

        bundle.obj.snapshot, __ = Snapshot.objects.create_or_get_snapshot(data)
        bundle.data.pop('data')
        return super(PipelineTemplateResource,
                     self).obj_update(bundle,
                                      skip_errors=skip_errors,
                                      **kwargs)

    def obj_create(self, bundle, **kwargs):
        json_data = bundle.data.get('data')
        try:
            data = json.loads(json_data)
        except Exception:
            raise_validation_error(self, bundle, 'templates', 'data',
                                   _(u"JSON 格式不合法"))

        result, msg = self.subprocess_ref_validate(bundle, data)
        if not result:
            raise_validation_error(self, bundle, 'templates', 'data', msg)
        self.gateway_validate(bundle, data)

        snapshot, __ = Snapshot.objects.create_or_get_snapshot(data)
        kwargs['snapshot_id'] = snapshot.id
        kwargs['template_id'] = node_uniqid()
        # must pop data field after the creation of snapshot is finished.
        bundle.data.pop('data')

        return super(PipelineTemplateResource,
                     self).obj_create(bundle, **kwargs)

    def obj_delete(self, bundle, **kwargs):
        template_id = kwargs['template_id']
        PipelineTemplate.objects.delete_model(template_id)

    def alter_list_data_to_serialize(self, request, data):
        for bundle in data['objects']:
            bundle.data.pop('id')
            bundle.data.pop('data')
            bundle.data.pop('description')
            bundle.data['version'] = bundle.obj.pipeline_template.version
            bundle.data[
                'subprocess_has_update'] = bundle.obj.pipeline_template.subprocess_has_update

        return data

    def alter_detail_data_to_serialize(self, request, data):
        bundle = data
        bundle.data.pop('id')
        bundle.data[
            'subprocess_version_info'] = bundle.obj.pipeline_template.subprocess_version_info

        return data

    def gateway_validate(self, bundle, data):
        try:
            validate_converge_gateway(data)
        except exceptions.ConvergeMatchError as e:
            raise_validation_error(self, bundle, 'templates', 'data',
                                   e.message)
Пример #6
0
class ActivityResource(ModelResource):
    countries = fields.ToManyField(OnlyCountryResource,
                                   'recipient_country',
                                   full=True,
                                   null=True,
                                   use_in='all')
    regions = fields.ToManyField(OnlyRegionResource,
                                 'recipient_region',
                                 full=True,
                                 null=True,
                                 use_in='all')
    sectors = fields.ToManyField(ActivityViewSectorResource,
                                 'sector',
                                 full=True,
                                 null=True,
                                 use_in='all')
    titles = fields.ToManyField(TitleResource,
                                'title_set',
                                full=True,
                                null=True,
                                use_in='all')
    descriptions = fields.ToManyField(DescriptionResource,
                                      'description_set',
                                      full=True,
                                      null=True,
                                      use_in='all')
    participating_organisations = fields.ToManyField(
        ActivityViewOrganisationResource,
        'participating_organisation',
        full=True,
        null=True,
        use_in='all')
    reporting_organisation = fields.ForeignKey(
        ActivityViewOrganisationResource,
        'reporting_organisation',
        full=True,
        null=True,
        use_in='detail')
    activity_status = fields.ForeignKey(ActivityViewActivityStatusResource,
                                        'activity_status',
                                        full=True,
                                        null=True,
                                        use_in='detail')
    websites = fields.ToManyField(WebsiteResource,
                                  'activity_website_set',
                                  full=True,
                                  null=True,
                                  use_in='detail')
    policy_markers = fields.ToManyField(PolicyMarkerResource,
                                        'policy_marker',
                                        full=True,
                                        null=True,
                                        use_in='detail')
    collaboration_type = fields.ForeignKey(
        ActivityViewCollaborationTypeResource,
        attribute='collaboration_type',
        full=True,
        null=True,
        use_in='detail')
    default_flow_type = fields.ForeignKey(ActivityViewFlowTypeResource,
                                          attribute='default_flow_type',
                                          full=True,
                                          null=True,
                                          use_in='detail')
    default_finance_type = fields.ForeignKey(FinanceTypeResource,
                                             attribute='default_finance_type',
                                             full=True,
                                             null=True,
                                             use_in='detail')
    default_aid_type = fields.ForeignKey(ActivityViewAidTypeResource,
                                         attribute='default_aid_type',
                                         full=True,
                                         null=True,
                                         use_in='detail')
    default_tied_status = fields.ForeignKey(ActivityViewTiedStatusResource,
                                            attribute='default_tied_status',
                                            full=True,
                                            null=True,
                                            use_in='detail')
    activity_scope = fields.ForeignKey(ActivityViewActivityScopeResource,
                                       attribute='scope',
                                       full=True,
                                       null=True,
                                       use_in='detail')
    default_currency = fields.ForeignKey(ActivityViewCurrencyResource,
                                         attribute='default_currency',
                                         full=True,
                                         null=True,
                                         use_in='detail')
    budget = fields.ToManyField(ActivityBudgetResource,
                                'budget_set',
                                full=True,
                                null=True,
                                use_in='detail')
    transactions = fields.ToManyField(ActivityViewTransactionResource,
                                      'transaction_set',
                                      full=True,
                                      null=True,
                                      use_in='detail')
    documents = fields.ToManyField(DocumentResource,
                                   'documentlink_set',
                                   full=True,
                                   null=True,
                                   use_in='detail')
    other_identifier = fields.ToManyField(OtherIdentifierResource,
                                          'otheridentifier_set',
                                          full=True,
                                          null=True,
                                          use_in='detail')
    locations = fields.ToManyField(ActivityLocationResource,
                                   'location_set',
                                   full=True,
                                   null=True,
                                   use_in='all')
    results = fields.ToManyField(ActivityResultResource,
                                 'results',
                                 full=True,
                                 null=True,
                                 use_in='all')
    related_activities = fields.ToManyField(RelatedActivityResource,
                                            'related_activities',
                                            full=True,
                                            null=True,
                                            use_in='detail')

    # to add:
    # conditions
    # contact
    # country-budget?
    # crsadd
    # disbursement channel?
    # ffs
    # ffs forecast?
    # planned disbursement
    # related activity
    # verification status
    # vocabulary?

    class Meta:
        queryset = Activity.objects.all()
        resource_name = 'activities'
        max_limit = 1000
        serializer = CsvSerializer()
        excludes = ['date_created']
        ordering = [
            'start_actual', 'start_planned', 'end_actual', 'end_planned',
            'sectors', 'total_budget'
        ]
        filtering = {
            'id': 'in',
            'iati_identifier': 'exact',
            'start_planned': ALL,
            'start_actual': ALL,
            'end_planned': ALL,
            'end_actual': ALL,
            'total_budget': ALL,
            'sectors': ('exact', 'in'),
            'regions': ('exact', 'in'),
            'countries': ('exact', 'in'),
            'reporting_organisation': ('exact', 'in'),
            'documents': ALL_WITH_RELATIONS,
            'results': ALL_WITH_RELATIONS
        }
        cache = NoTransformCache()
        paginator_class = NoCountPaginator

    def apply_filters(self, request, applicable_filters):
        activity_list = super(ActivityResource, self).apply_filters(
            request, applicable_filters).prefetch_related(
                'title_set').prefetch_related('description_set')
        query = request.GET.get('query', None)
        filter_year_param = request.GET.get('start_year_planned__in', None)

        if query:
            search_fields = comma_separated_parameter_to_list(
                request.GET.get('search_fields', None))
            activity_list = activity_list.search(query, search_fields)

        if filter_year_param:
            years = comma_separated_parameter_to_list(filter_year_param)
            activity_list = activity_list.filter_years(years)

        return activity_list.distinct_if_necessary(applicable_filters)

    def full_dehydrate(self, bundle, for_list=False):
        #If the select_fields param is found, run this overwritten method.
        #Otherwise run the default Tastypie method
        select_fields_param = bundle.request.GET.get('select_fields', None)
        if select_fields_param:
            select_fields = comma_separated_parameter_to_list(
                select_fields_param)
            for field_name, field_object in self.fields.items():
                #If the field_name is in the list of requested fields dehydrate it
                if (field_name) in select_fields:

                    # A touch leaky but it makes URI resolution work.
                    if getattr(field_object, 'dehydrated_type',
                               None) == 'related':
                        field_object.api_name = self._meta.api_name
                        field_object.resource_name = self._meta.resource_name

                    bundle.data[field_name] = field_object.dehydrate(
                        bundle, for_list=for_list)

                    # Check for an optional method to do further dehydration.
                    method = getattr(self, "dehydrate_%s" % field_name, None)

                    if method:
                        bundle.data[field_name] = method(bundle)

            bundle = self.dehydrate(bundle)
            return bundle
        else:
            return super(ActivityResource,
                         self).full_dehydrate(bundle, for_list)

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

        # check if call is cached using validator.is_cached
        # check if call contains flush, if it does the call comes from the cache updater and shouldn't return cached results
        validator = Validator()
        cururl = request.META['PATH_INFO'] + "?" + request.META['QUERY_STRING']

        if not 'flush' in cururl and validator.is_cached(cururl):
            return HttpResponse(validator.get_cached_call(cururl),
                                mimetype='application/json')
        else:
            return super(ActivityResource, self).get_list(request, **kwargs)

    def alter_list_data_to_serialize(self, request, data):
        select_fields_param = request.GET.get('select_fields', None)
        if select_fields_param:
            select_fields = comma_separated_parameter_to_list(
                select_fields_param)
            data['meta']['selectable_fields'] = {
                f[0]
                for f in self.fields.items()
            } - {f
                 for f in select_fields}
        return data
Пример #7
0
class EyeHistoryResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user')
    message = fields.ToManyField(EyeHistoryMessageResource,
                                 'eyehistorymessage_set',
                                 null=True,
                                 blank=True,
                                 full=True)

    class Meta(BaseMeta):
        queryset = EyeHistory.objects.select_related().all().order_by(
            '-start_time')
        resource_name = 'history-data'

        list_allowed_methods = ['get', 'post']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        filtering = {
            'user': ALL_WITH_RELATIONS,
            'url': ALL,
            'title': ALL,
            'start_time': ALL,
            'end_time': ALL,
            'total_time': ALL,
        }
        paginator_class = Paginator
        authentication = PublicGetAuthentication()

    def dehydrate(self, bundle):
        bundle.data['username'] = bundle.obj.user.username
        bundle.data['pic_url'] = gravatar_for_user(
            User.objects.get(username=bundle.obj.user.username))

        return bundle.data

    def obj_create(self, bundle, request=None, **kwargs):
        url = bundle.data['url']
        domain = url_domain(url)

        bundle.data['domain'] = domain

        title = bundle.data.get('title')
        start_time = bundle.data.get('start_time')
        start_event = bundle.data.get('start_event')
        end_time = bundle.data.get('end_time')
        end_event = bundle.data.get('end_event')
        favicon_url = bundle.data.get('favIconUrl')
        bundle.data['favicon_url'] = favicon_url
        src = bundle.data.get('src')
        tags = bundle.data.get('tags')

        if tags:
            tags = json.loads(tags)

        if end_time and start_time:
            end_time = datetime.datetime.strptime(
                end_time, '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=pytz.utc)
            start_time = datetime.datetime.strptime(
                start_time, '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=pytz.utc)
        else:
            end_time = datetime.datetime.now().replace(tzinfo=pytz.utc)
            start_time = datetime.datetime.now().replace(tzinfo=pytz.utc)

        message = bundle.data.get('message')
        highlight = bundle.data.get('highlight')
        parent_comment = bundle.data.get('parent_comment')

        if message and message.strip() == '':
            message = None

        if message:
            bundle.data.pop('message', None)
        if highlight:
            bundle.data.pop('highlight', None)
        if parent_comment:
            bundle.data.pop('parent_comment', None)

        try:
            exists = EyeHistory.objects.filter(user=request.user,
                                               url=url,
                                               title=title,
                                               src=src,
                                               favicon_url=favicon_url,
                                               start_time__gt=start_time -
                                               datetime.timedelta(minutes=1),
                                               start_event=start_event)
            if exists.count() > 0:
                eye_his = exists[0]
                eye_his.end_time = end_time
                eye_his.end_event = end_event
                elapsed_time = end_time - start_time
                eye_his.total_time = int(
                    round((elapsed_time.microseconds / 1.0E3) +
                          (elapsed_time.seconds * 1000) +
                          (elapsed_time.days * 8.64E7)))
                eye_his.humanize_time = humanize_time(elapsed_time)
                eye_his.save()
                if message:
                    eye_message, _ = EyeHistoryMessage.objects.get_or_create(
                        eyehistory=eye_his, message=message)
                    notify_message(message=eye_message)
            else:
                # save_raw_eyehistory(request.user, url, title, start_event, end_event, start_time, end_time, src, domain, favicon_url)
                dup_histories = EyeHistory.objects.filter(
                    user=request.user,
                    url=url,
                    title=title,
                    end_time__gt=start_time - datetime.timedelta(minutes=5))
                if dup_histories.count() > 0:
                    obj = merge_histories(dup_histories, end_time, end_event)
                    if message:
                        eye_message, _ = EyeHistoryMessage.objects.get_or_create(
                            eyehistory=obj, message=message)
                        notify_message(message=eye_message)
                else:
                    bundle_res = super(EyeHistoryResource,
                                       self).obj_create(bundle,
                                                        request,
                                                        user=request.user,
                                                        **kwargs)
                    check_bumps(request.user, start_time, end_time, url)
                    if message:
                        eye_message = None
                        if parent_comment:
                            h = Highlight.objects.get(id=highlight)
                            eye_message, _ = EyeHistoryMessage.objects.get_or_create(
                                eyehistory=bundle_res.obj,
                                message=message,
                                highlight=h,
                                parent_comment=parent_comment)
                        elif highlight:
                            h = Highlight.objects.get(id=highlight)
                            eye_message, _ = EyeHistoryMessage.objects.get_or_create(
                                eyehistory=bundle_res.obj,
                                message=message,
                                highlight=h)
                        else:
                            eye_message, _ = EyeHistoryMessage.objects.get_or_create(
                                eyehistory=bundle_res.obj, message=message)

                        if tags:
                            for tag in tags:
                                if len(
                                        Tag.objects.filter(
                                            comment=eye_message,
                                            common_tag__name=tag)) == 0:
                                    try:
                                        common_tag = CommonTag.objects.get(
                                            name=tag)
                                        vt = Tag(
                                            common_tag=common_tag,
                                            user=request.user,
                                            comment=eye_message,
                                        )
                                        vt.save()
                                    except CommonTag.DoesNotExist:
                                        pass

                        notify_message(message=eye_message)
                    return bundle_res
        except MultipleObjectsReturned as e:
            logger.info(e)
            # multiple items created, delete duplicates
            call_command('remove_duplicate_history')

        return bundle
Пример #8
0
class MovieResource(ModelResource):
    actor = fields.ForeignKey(ActorResource, 'actor')

    class Meta:
        queryset = Movie.objects.all()
        resource_name = 'movie'
Пример #9
0
class AppMakerResource(GCloudModelResource):
    business = fields.ForeignKey(BusinessResource, 'business', full=True)
    creator_name = fields.CharField(attribute='creator_name',
                                    readonly=True,
                                    null=True)
    editor_name = fields.CharField(attribute='editor_name',
                                   readonly=True,
                                   null=True)
    template_scheme_id = fields.CharField(attribute='template_scheme_id',
                                          readonly=True,
                                          blank=True)
    task_template = fields.ForeignKey(
        TaskTemplateResource,
        'task_template',
    )
    template_id = fields.CharField(attribute='task_template_id',
                                   readonly=True,
                                   null=True)
    template_name = fields.CharField(attribute='task_template_name',
                                     readonly=True,
                                     null=True)
    category = fields.CharField(attribute='category', readonly=True, null=True)

    class Meta:
        queryset = AppMaker.objects.filter(is_deleted=False)
        resource_name = 'appmaker'
        excludes = []
        authorization = GCloudGenericAuthorization()
        always_return_data = True
        serializer = AppSerializer()
        filtering = {
            "business": ALL_WITH_RELATIONS,
            "template": ALL_WITH_RELATIONS,
            "name": ALL,
            "creator": ALL,
            "editor": ALL,
            'create_time': ['gte', 'lte'],
            'edit_time': ['gte', 'lte'],
        }
        limit = 0

    def obj_delete(self, bundle, **kwargs):
        try:
            appmaker_id = kwargs['pk']
            appmaker = AppMaker.objects.get(pk=appmaker_id)
        except Exception:
            raise BadRequest('appmaker[id=%s] does not exist' % appmaker_id)
        biz_cc_id = appmaker.business.cc_id
        business = get_business_for_user(bundle.request.user,
                                         ['manage_business'])
        if not business.filter(cc_id=biz_cc_id).exists():
            raise ImmediateHttpResponse(
                HttpResponseForbidden(
                    'you have no permissions to delete appmaker'))

        if settings.IS_LOCAL:
            fake = True
        else:
            fake = False

        result, data = AppMaker.objects.del_app_maker(biz_cc_id, appmaker_id,
                                                      fake)
        if not result:
            raise BadRequest(data)
Пример #10
0
class LayerResource(CommonModelApi):
    """Layer API"""
    links = fields.ListField(attribute='links',
                             null=True,
                             use_in='all',
                             default=[])
    if check_ogc_backend(qgis_server.BACKEND_PACKAGE):
        default_style = fields.ForeignKey('geonode.api.api.StyleResource',
                                          attribute='qgis_default_style',
                                          null=True)
        styles = fields.ManyToManyField('geonode.api.api.StyleResource',
                                        attribute='qgis_styles',
                                        null=True,
                                        use_in='detail')
    elif check_ogc_backend(geoserver.BACKEND_PACKAGE):
        default_style = fields.ForeignKey('geonode.api.api.StyleResource',
                                          attribute='default_style',
                                          null=True)
        styles = fields.ManyToManyField('geonode.api.api.StyleResource',
                                        attribute='styles',
                                        null=True,
                                        use_in='detail')

    def format_objects(self, objects):
        """
        Formats the object.
        """
        formatted_objects = []
        for obj in objects:
            # convert the object to a dict using the standard values.
            # includes other values
            values = self.VALUES + ['alternate', 'name']
            formatted_obj = model_to_dict(obj, fields=values)
            username = obj.owner.get_username()
            full_name = (obj.owner.get_full_name() or username)
            formatted_obj['owner__username'] = username
            formatted_obj['owner_name'] = full_name
            if obj.category:
                formatted_obj[
                    'category__gn_description'] = obj.category.gn_description
            if obj.group:
                formatted_obj['group'] = obj.group
                try:
                    formatted_obj['group_name'] = GroupProfile.objects.get(
                        slug=obj.group.name)
                except GroupProfile.DoesNotExist:
                    formatted_obj['group_name'] = obj.group

            formatted_obj['keywords'] = [k.name for k in obj.keywords.all()
                                         ] if obj.keywords else []

            # embrapa #

            #formatted_obj['embrapa_keywords'] = [ek.name for ek in obj.embrapa_keywords.all()] if objects.embrapa_keywords else []

            formatted_obj['regions'] = [r.name for r in obj.regions.all()
                                        ] if obj.regions else []

            # provide style information
            bundle = self.build_bundle(obj=obj)
            formatted_obj['default_style'] = self.default_style.dehydrate(
                bundle, for_list=True)

            # Add resource uri
            formatted_obj['resource_uri'] = self.get_resource_uri(bundle)

            formatted_obj['links'] = self.dehydrate_ogc_links(bundle)

            if 'site_url' not in formatted_obj or len(
                    formatted_obj['site_url']) == 0:
                formatted_obj['site_url'] = settings.SITEURL

            # Probe Remote Services
            formatted_obj['store_type'] = 'dataset'
            formatted_obj['online'] = True
            if hasattr(obj, 'storeType'):
                formatted_obj['store_type'] = obj.storeType
                if obj.storeType == 'remoteStore' and hasattr(
                        obj, 'remote_service'):
                    if obj.remote_service:
                        formatted_obj['online'] = (
                            obj.remote_service.probe == 200)
                    else:
                        formatted_obj['online'] = False

            formatted_obj['gtype'] = self.dehydrate_gtype(bundle)

            # replace thumbnail_url with curated_thumbs
            if hasattr(obj, 'curatedthumbnail'):
                formatted_obj[
                    'thumbnail_url'] = obj.curatedthumbnail.thumbnail_url

            # put the object on the response stack
            formatted_objects.append(formatted_obj)
        return formatted_objects

    def _dehydrate_links(self, bundle, link_types=None):
        """Dehydrate links field."""

        dehydrated = []
        obj = bundle.obj
        link_fields = ['extension', 'link_type', 'name', 'mime', 'url']

        links = obj.link_set.all()
        if link_types:
            links = links.filter(link_type__in=link_types)
        for l in links:
            formatted_link = model_to_dict(l, fields=link_fields)
            dehydrated.append(formatted_link)

        return dehydrated

    def dehydrate_links(self, bundle):
        return self._dehydrate_links(bundle)

    def dehydrate_ogc_links(self, bundle):
        return self._dehydrate_links(bundle, ['OGC:WMS', 'OGC:WFS', 'OGC:WCS'])

    def dehydrate_gtype(self, bundle):
        return bundle.obj.gtype

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

        :param obj: Layer obj
        :type obj: Layer
        :return:
        """
        if check_ogc_backend(qgis_server.BACKEND_PACKAGE):
            # Provides custom links for QGIS Server styles info
            # Default style
            try:
                obj.qgis_default_style = obj.qgis_layer.default_style
            except Exception:
                obj.qgis_default_style = None

            # Styles
            try:
                obj.qgis_styles = obj.qgis_layer.styles
            except Exception:
                obj.qgis_styles = []
        return obj

    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 patch_detail(self, request, **kwargs):
        """Allow patch request to update default_style.

        Request body must match this:

        {
            'default_style': <resource_uri_to_style>
        }

        """
        reason = 'Can only patch "default_style" field.'
        try:
            body = json.loads(request.body)
            if 'default_style' not in body:
                return http.HttpBadRequest(reason=reason)
            match = resolve(body['default_style'])
            style_id = match.kwargs['id']
            api_name = match.kwargs['api_name']
            resource_name = match.kwargs['resource_name']
            if not (resource_name == 'styles' and api_name == 'api'):
                raise Exception()

            from geonode.qgis_server.models import QGISServerStyle

            style = QGISServerStyle.objects.get(id=style_id)

            layer_id = kwargs['id']
            layer = Layer.objects.get(id=layer_id)
        except Exception:
            return http.HttpBadRequest(reason=reason)

        from geonode.qgis_server.views import default_qml_style

        request.method = 'POST'
        response = default_qml_style(request,
                                     layername=layer.name,
                                     style_name=style.name)

        if isinstance(response, TemplateResponse):
            if response.status_code == 200:
                return HttpResponse(status=200)

        return self.error_response(request, response.content)

    # copy parent attribute before modifying
    VALUES = CommonModelApi.VALUES[:]
    VALUES.append('typename')

    class Meta(CommonMetaApi):
        paginator_class = CrossSiteXHRPaginator
        queryset = Layer.objects.distinct().order_by('-date')
        resource_name = 'layers'
        detail_uri_name = 'id'
        include_resource_uri = True
        allowed_methods = ['get', 'patch']
        excludes = ['csw_anytext', 'metadata_xml']
        authentication = MultiAuthentication(SessionAuthentication(),
                                             OAuthAuthentication(),
                                             GeonodeApiKeyAuthentication())
        filtering = CommonMetaApi.filtering
        # Allow filtering using ID
        filtering.update({
            'id': ALL,
            'name': ALL,
            'alternate': ALL,
        })
Пример #11
0
class TaskResource(ModelResource):
    # people = fields.ToManyField(InternalUserProfileResource, 'people', full=True, null=True)
    user = fields.ForeignKey(InternalUserProfileResource,
                             'user',
                             full=True,
                             null=False)
    total_records = fields.CharField(attribute='total_records',
                                     default=0,
                                     readonly=True)

    class Meta(object):
        queryset = Task.objects \
            .all() \
            .select_related() \
            .prefetch_related('user')
        resource_name = 'tasks'
        filtering = {'title': ALL, 'id': ALL}
        authentication = ApiKeyAuthenticationExt()
        authorization = UserObjectsOnlyAuthorization()
        always_return_data = True
        paginator_class = PageNumberPaginator
        include_resource_uri = False

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/listing%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_tasks'),
                name="api_get_tasks")
        ]

    def validation(self, bundle):
        if bundle.request.method == 'POST':
            if bundle.data.get('title', '') == '' \
                    or bundle.data.get('select_date', '') == '' \
                    or bundle.data.get('select_time', '') == '':
                raise CustomBadRequest(error_type='INVALID_OPERATOR',
                                       error_message="Cant create the task")

    def validate_duplicate(self, bundle):
        title = bundle.data['title']
        date = bundle.data['select_date']
        time = bundle.data['select_time']
        if title and date and time:
            if Task.objects.filter(title__iexact=title,
                                   select_time__iexact=time,
                                   select_date__iexact=date).exists():
                raise CustomBadRequest(
                    error_type='DUPLICATE_TASK',
                    error_message="A same task is already in your list")

    def hydrate(self, bundle):
        # Always tie task to the current user profile
        if bundle.request.method == 'POST':
            bundle.data["user"] = bundle.request.user.userprofile
        rq_date = bundle.data["select_date"]
        bundle.data["task_date"] = convert_to_date(rq_date)
        return super(TaskResource, self).hydrate(bundle)

    def dehydrate(self, bundle):
        if "user" in bundle.data:
            bundle.data.pop("user", None)
        if "total_records" in bundle.data:
            bundle.data.pop('total_records', None)
        if 'task_date' in bundle.data:
            bundle.data.pop('task_date', None)
        return super(TaskResource, self).dehydrate(bundle)

    def build_filters(self, filters=None):

        if filters is None:
            filters = {}
        q = None
        if 'q' in filters:
            q = filters.pop('q')
        orm_filters = super(TaskResource, self).build_filters(filters)
        if q:
            orm_filters['q'] = q

        return orm_filters

    def apply_filters(self, request, applicable_filters):
        if 'q' in applicable_filters:
            q = applicable_filters.pop('q')
        else:
            q = None
        semi_filtered = super(TaskResource,
                              self).apply_filters(request, applicable_filters)

        # Always get task belong to an user
        semi_filtered = semi_filtered.filter(
            user_id=request.user.userprofile.id, is_deleted=False)
        # Just only get tasks that has date is greater than the current dates
        q_date = request.GET.get('date', None)
        if q_date is None:
            current_date = get_current_date()
        else:
            current_date = convert_to_date(q_date)
        semi_filtered = semi_filtered.filter(task_date=current_date)
        if q:
            semi_filtered = semi_filtered.search(q[0],
                                                 raw=True,
                                                 fields=('title', ))
        return semi_filtered

    def obj_get(self, bundle, **kwargs):
        return super(TaskResource, self).obj_get(bundle, **kwargs)

    def obj_create(self, bundle, **kwargs):
        self.validation(bundle)
        # self.validate_duplicate(bundle)
        try:
            return super(TaskResource, self).obj_create(bundle, **kwargs)
        except Exception as e:
            raise CustomBadRequest(error_type='UNKNOWNERROR',
                                   error_message=str(e))

    # def save_m2m(self, bundle):
    #     people = bundle.data['people']
    #     for user in people:
    #         user.data['user'] = bundle.obj
    #
    #     return super(TaskResource, self).save_m2m(bundle)

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

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

        self.log_throttled_access(request)
        return self.get_list(request)
Пример #12
0
class IPReadingResource(ModelResource):
    ipseries = fields.ForeignKey(IPSeriesResource, 'ipseries')
    class Meta:
        queryset = IPReading.objects.all()
        resource_name = 'ipreading'
        ordering = ['timestamp', 'id', 'pk']
Пример #13
0
class TempReadingResource(ModelResource):
    tempseries = fields.ForeignKey(TempSeriesResource, 'tempseries')
    class Meta:
        queryset = TempReading.objects.all()
        resource_name = 'tempreading'
        ordering = ['timestamp', 'id', 'pk']
Пример #14
0
class DirectorResource(ModelResource):
    probe = fields.ForeignKey(ProbeResource, 'probe', full=True)
    time_profile = fields.ForeignKey(TimeProfileResource,
                                     'time_profile',
                                     full=True)
    backends = fields.ToManyField('vaas.manager.api.BackendResource',
                                  'backends',
                                  null=True)
    cluster = fields.ToManyField('vaas.cluster.api.LogicalClusterResource',
                                 'cluster',
                                 null=False,
                                 full=True)

    class Meta:
        queryset = Director.objects.all()
        resource_name = 'director'
        serializer = PrettyJSONSerializer()
        authorization = DjangoAuthorization()
        authentication = VaasMultiAuthentication(ApiKeyAuthentication(),
                                                 SessionAuthentication())
        validation = ModelCleanedDataFormValidation(
            form_class=DirectorModelForm)
        always_return_data = True
        filtering = {
            'name': ['exact'],
            'enabled': ['exact'],
            'probe': ALL_WITH_RELATIONS,
            'cluster': ALL_WITH_RELATIONS,
            'service': ['exact']
        }

    def save_m2m(self, bundle):
        try:
            new_uris = bundle.obj.new_clusters_uris
            bundle.obj.new_clusters = [
                cluster.obj for cluster in bundle.data['cluster']
                if cluster.data['resource_uri'] in new_uris
            ]
            logger.info("[DirectorResource.save_m2m()] new_clusters = %s",
                        bundle.obj.new_clusters)
        except (AttributeError, KeyError):
            pass

        return super(DirectorResource, self).save_m2m(bundle)

    def update_in_place(self, request, original_bundle, new_data):
        try:
            original_bundle.obj.old_clusters = list(
                original_bundle.obj.cluster.all())
        except AttributeError:
            original_bundle.obj.old_clusters = []
        logger.info("[DirectorResource.update_in_place()] old_clusters = %s",
                    original_bundle.obj.old_clusters)
        try:
            original_bundle.obj.new_clusters_uris = new_data['cluster']
        except KeyError:
            original_bundle.obj.new_clusters_uris = []
        original_bundle.obj.new_data = new_data

        return super(DirectorResource,
                     self).update_in_place(request, original_bundle, new_data)
Пример #15
0
class VersionResource(ModelResource):
    project = fields.ForeignKey(ProjectResource, 'project', full=True)

    class Meta(object):
        allowed_methods = ['get', 'put', 'post']
        always_return_data = True
        queryset = Version.objects.api()
        authentication = PostAuthentication()
        authorization = DjangoAuthorization()
        filtering = {
            "project": ALL_WITH_RELATIONS,
            "slug": ALL_WITH_RELATIONS,
            "active": ALL,
        }

    # Find a better name for this before including it.
    # def dehydrate(self, bundle):
    #     bundle.data['subdomain'] = "http://%s/en/%s/" % (
    #         bundle.obj.project.subdomain, bundle.obj.slug
    #     )
    #     return bundle

    def get_object_list(self, request):
        self._meta.queryset = Version.objects.api(user=request.user,
                                                  only_active=False)
        return super(VersionResource, self).get_object_list(request)

    def version_compare(self, request, project_slug, base=None, **kwargs):
        project = get_object_or_404(Project, slug=project_slug)
        if base and base != LATEST:
            try:
                base_version = project.versions.get(slug=base)
            except (Version.DoesNotExist, TypeError):
                base_version = None
        else:
            base_version = None
        ret_val = get_version_compare_data(project, base_version)
        return self.create_response(request, ret_val)

    def build_version(self, request, **kwargs):
        project = get_object_or_404(Project, slug=kwargs['project_slug'])
        version = kwargs.get('version_slug', LATEST)
        version_obj = project.versions.get(slug=version)
        trigger_build(project=project, version=version_obj)
        return self.create_response(request, {'building': True})

    def override_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/schema/$" % self._meta.resource_name,
                self.wrap_view('get_schema'),
                name="api_get_schema"),
            url((r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/highest/"
                 r"(?P<base>.+)/$") % self._meta.resource_name,
                self.wrap_view('version_compare'),
                name="version_compare"),
            url(r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/highest/$"
                % self._meta.resource_name,
                self.wrap_view('version_compare'),
                name="version_compare"),
            url(
                r"^(?P<resource_name>%s)/(?P<project__slug>[a-z-_]+[a-z0-9-_]+)/$"  # noqa
                % self._meta.resource_name,
                self.wrap_view('dispatch_list'),
                name="api_version_list"),
            url((r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/(?P"
                 r"<version_slug>[a-z0-9-_.]+)/build/$") %
                self._meta.resource_name,
                self.wrap_view('build_version'),
                name="api_version_build_slug"),
        ]
Пример #16
0
class GroupResource(SlimGroupResource):
    owner = fields.ForeignKey(SlimProfileResource, 'owner')
    students = fields.ToManyField(SlimProfileResource, 'students', full=True)

    class Meta(SlimGroupResource.Meta):
        queryset = SlimGroupResource.Meta.queryset.prefetch_related(
            'students__user').select_related('owner__user')
        fields = SlimGroupResource.Meta.fields + ['owner', 'students']

    def _group_unread_counts(self, groups, request, profile):
        # This is called when the group queryset is evaluated; we attach an
        # `all_students_group` to the request, and send it along for the
        # unread-counts-fetching along with the other groups.
        request.all_students_group = model.AllStudentsGroup(profile)
        all_groups = [request.all_students_group] + list(groups)
        counts = super(GroupResource,
                       self)._group_unread_counts(all_groups, request, profile)
        request.all_students_group.unread_count = counts.pop(
            request.all_students_group)
        return counts

    def full_dehydrate(self, bundle):
        """Special handling for all-students group."""
        if bundle.obj.is_all:
            profile_resource = SlimProfileResource()

            def dehydrate_student(student):
                b = profile_resource.build_bundle(obj=student,
                                                  request=bundle.request)
                return profile_resource.full_dehydrate(b)

            bundle.data.update({
                'id':
                bundle.obj.id,
                'name':
                bundle.obj.name,
                'students_uri':
                reverse(
                    'api_dispatch_list',
                    kwargs={
                        'resource_name': 'user',
                        'api_name': 'v1'
                    },
                ) + '?elders=%s' % bundle.obj.owner.id,
                'group_uri':
                reverse('all_students_dash'),
                'add_student_uri':
                reverse('add_student'),
                'owner':
                reverse(
                    'api_dispatch_detail',
                    kwargs={
                        'resource_name': 'user',
                        'api_name': 'v1',
                        'pk': bundle.obj.owner.id,
                    },
                ),
                'unread_count':
                bundle.obj.unread_count,
                'students':
                [dehydrate_student(s) for s in bundle.obj.owner.students],
            })

        else:
            bundle = super(GroupResource, self).full_dehydrate(bundle)
        return bundle

    def obj_get_list(self, request=None, **kwargs):
        qs = super(GroupResource, self).obj_get_list(request, **kwargs)
        # Evaluate the group queryset (populates request.all_students_group)
        groups = list(qs)
        if request is not None:  # pragma: no cover
            # Actually add the all-students-group to the list of groups
            groups.insert(0, request.all_students_group)
        return groups
Пример #17
0
class ProjectResource(ModelResource):

    author = fields.ForeignKey(UserResource, 'author', full=True)

    date_fmt = "%m/%d/%y %I:%M %p"

    def __init__(self, *args, **kwargs):
        # @todo: extras is a side-effect of the Mustache templating system
        # not supporting the ability to reference variables in the parent
        # context. ideally, the templating system should be switched out to
        # something more reasonable
        self.editable = kwargs.pop('editable', {})
        self.record_viewer = kwargs.pop('record_viewer', {})
        self.is_viewer_faculty = kwargs.pop('is_viewer_faculty', False)
        self.extras = kwargs.pop('extras', {})
        super(ProjectResource, self).__init__(*args, **kwargs)

    class Meta:
        queryset = Project.objects.all().order_by('id')
        excludes = [
            'participants', 'body', 'submitted', 'feedback', 'sherdnote_set'
        ]
        list_allowed_methods = []
        detail_allowed_methods = []
        authentication = ClassLevelAuthentication()
        ordering = ['id', 'title']

    def dehydrate(self, bundle):
        bundle.data['is_assignment'] = \
            bundle.obj.visibility_short() == 'Assignment'
        bundle.data['is_response'] = bundle.obj.assignment() is not None
        bundle.data['attribution'] = bundle.obj.attribution()
        bundle.data['url'] = bundle.obj.get_absolute_url()
        bundle.data['due_date'] = bundle.obj.get_due_date()
        bundle.data['modified_date'] = bundle.obj.modified.strftime("%m/%d/%y")
        bundle.data['modified_time'] = bundle.obj.modified.strftime("%I:%M %p")
        bundle.data['editable'] = self.editable
        bundle.data['is_faculty'] = self.is_viewer_faculty

        participants = bundle.obj.attribution_list()
        bundle.data['participants'] = [{
            'name':
            p.get_full_name(),
            'username':
            p.username,
            'public_name':
            get_public_name(p, bundle.request),
            'is_viewer':
            self.record_viewer == p.username,
            'last':
            idx == (len(participants) - 1)
        } for idx, p in enumerate(participants)]
        bundle.data['status'] = bundle.obj.status()

        for key, value in self.extras.items():
            bundle.data[key] = value

        return bundle

    def render_one(self, request, project, version_number=None):
        bundle = self.build_bundle(obj=project, request=request)
        dehydrated = self.full_dehydrate(bundle)
        project_ctx = self._meta.serializer.to_simple(dehydrated, None)
        project_ctx['body'] = project.body
        project_ctx['public_url'] = project.public_url()
        project_ctx['current_version'] = version_number
        project_ctx['visibility'] = project.visibility_short()
        project_ctx['type'] = ('assignment' if project.is_assignment(request)
                               else 'composition')

        rand = ''.join([choice(letters) for i in range(5)])

        asset_resource = AssetResource()
        sherd_resource = SherdNoteResource()

        assets = {}
        notes = []
        for note in project.citations():
            notes.append(sherd_resource.render_one(request, note, rand))
            if (note.title not in ["Annotation Deleted", 'Asset Deleted']):
                key = '%s_%s' % (rand, note.asset.pk)
                if key not in assets.keys():
                    assets[key] = \
                        asset_resource.render_one(request, note.asset)

        data = {
            'project': project_ctx,
            'type': 'project',
            'can_edit': self.editable,
            'annotations': notes,
            'assets': assets
        }

        data['responses'] = []
        for response in project.responses(request):
            if response.can_read(request):
                obj = {
                    'url': response.get_absolute_url(),
                    'title': response.title,
                    'modified': response.modified.strftime(self.date_fmt),
                    'attribution_list': []
                }

                last = len(response.attribution_list()) - 1
                for idx, author in enumerate(response.attribution_list()):
                    obj['attribution_list'].append({
                        'name':
                        get_public_name(author, request),
                        'last':
                        idx == last
                    })

                data['responses'].append(obj)
        data['response_count'] = len(data['responses'])

        my_responses = []
        for response in project.responses_by(request, request.user):
            obj = {
                'url': response.get_absolute_url(),
                'title': response.title,
                'modified': response.modified.strftime(self.date_fmt),
                'attribution_list': []
            }

            last = len(response.attribution_list()) - 1
            for idx, author in enumerate(response.attribution_list()):
                obj['attribution_list'].append({
                    'name':
                    get_public_name(author, request),
                    'last':
                    idx == last
                })

            my_responses.append(obj)

        if len(my_responses) == 1:
            data['my_response'] = my_responses[0]
        elif len(my_responses) > 1:
            data['my_responses'] = my_responses
            data['my_responses_count'] = len(my_responses)

        if project.is_participant(request.user):
            data['revisions'] = [{
                'version_number':
                v.version_number,
                'versioned_id':
                v.versioned_id,
                'author':
                get_public_name(v.instance().author, request),
                'modified':
                v.modified.strftime("%m/%d/%y %I:%M %p")
            } for v in project.versions.order_by('-change_time')]

        if self.editable:
            projectform = ProjectForm(request, instance=project)
            data['form'] = {
                'participants': projectform['participants'].__unicode__(),
                'publish': projectform['publish'].__unicode__()
            }

        return data

    def render_assignments(self, request, assignments):
        lst = []
        for a in assignments:
            bundle = self.build_bundle(obj=a, request=request)
            dehydrated = self.full_dehydrate(bundle)
            ctx = self._meta.serializer.to_simple(dehydrated, None)
            ctx['display_as_assignment'] = True
            lst.append(ctx)
        return lst

    def render_projects(self, request, projects):
        lst = []
        for project in projects:
            abundle = self.build_bundle(obj=project, request=request)
            dehydrated = self.full_dehydrate(abundle)
            ctx = self._meta.serializer.to_simple(dehydrated, None)

            if self.editable:
                feedback = project.feedback_discussion()
                if feedback:
                    ctx['feedback'] = feedback.id

            parent_assignment = project.assignment()
            if parent_assignment:
                ctx['collaboration'] = {}
                ctx['collaboration']['title'] = parent_assignment.title
                ctx['collaboration']['url'] = \
                    parent_assignment.get_absolute_url()
                ctx['collaboration']['due_date'] = \
                    parent_assignment.get_due_date()

            is_assignment = project.is_assignment(request)
            if is_assignment:
                count = 0
                for response in project.responses(request):
                    if response.can_read(request):
                        count += 1
                ctx['responses'] = count

                ctx['is_assignment'] = True
                ctx['responses'] = len(project.responses(request))

            ctx['display_as_assignment'] = \
                is_assignment or parent_assignment is not None

            lst.append(ctx)
        return lst

    def render_list(self, request, projects):
        lst = []
        for project in projects.all():
            bundle = self.build_bundle(obj=project, request=request)
            dehydrated = self.full_dehydrate(bundle)
            ctx = self._meta.serializer.to_simple(dehydrated, None)
            lst.append(ctx)
        return sorted(lst, key=lambda item: item['title'])
Пример #18
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 Exception:
            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.items():
            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()
Пример #19
0
class TaskResource(ModelResource):

    project = fields.ForeignKey('project.apps.base.api.ProjectResource',
                                'project')
    version = fields.ForeignKey('project.apps.base.api.VersionResource',
                                'version',
                                null=True,
                                blank=True)
    author = fields.ForeignKey(UserResource, 'author')
    assigned_to = fields.ForeignKey(UserResource,
                                    'assigned_to',
                                    null=True,
                                    blank=True)

    class Meta:
        queryset = RedTask.objects.all()
        resource_name = 'task'
        filtering = {
            'project': ALL_WITH_RELATIONS,
            'version': ALL_WITH_RELATIONS,
            'author': ALL_WITH_RELATIONS,
            'assigned_to': ALL_WITH_RELATIONS,
        }

        include_resource_uri = False
        # cache = SimpleCache(timeout=10)
        authentication = BasicAuthentication()

    def get_object_list(self, request):

        projects = []

        if request.user.is_superuser:
            user_perm = False
        else:
            try:
                user_perm = request.user.reduser
                rolesets = RedRoleSet.objects.filter(users=user_perm)
                for role in rolesets:
                    projects.append(role.project)
            except RedUser.DoesNotExist:
                user_perm = False

        if user_perm:
            tasks = RedTask.objects.filter(project__in=projects)
        else:
            tasks = RedTask.objects.all()

        return tasks

    def dehydrate_project(self, bundle):
        return bundle.obj.project.id

    def dehydrate_version(self, bundle):
        if bundle.obj.version:
            return bundle.obj.version.id
        else:
            return None

    def dehydrate_author(self, bundle):
        return bundle.obj.author.id

    def dehydrate_assigned_to(self, bundle):
        if bundle.obj.assigned_to:
            return bundle.obj.assigned_to.id
        else:
            return None
Пример #20
0
class ExperimentParameterResource(ParameterResource):
    parameterset = fields.ForeignKey(ExperimentParameterSetResource,
                                     'parameterset')

    class Meta(ParameterResource.Meta):
        queryset = ExperimentParameter.objects.all()
Пример #21
0
class LayerResource(CommonModelApi):

    """Layer API"""
    links = fields.ListField(
        attribute='links',
        null=True,
        use_in='all',
        default=[])
    if check_ogc_backend(geoserver.BACKEND_PACKAGE):
        default_style = fields.ForeignKey(
            'geonode.api.api.StyleResource',
            attribute='default_style',
            null=True)
        styles = fields.ManyToManyField(
            'geonode.api.api.StyleResource',
            attribute='styles',
            null=True,
            use_in='detail')

    def format_objects(self, objects):
        """
        Formats the object.
        """
        formatted_objects = []
        for obj in objects:
            # convert the object to a dict using the standard values.
            # includes other values
            values = self.VALUES + [
                'alternate',
                'name'
            ]
            formatted_obj = model_to_dict(obj, fields=values)
            username = obj.owner.get_username()
            full_name = (obj.owner.get_full_name() or username)
            formatted_obj['owner__username'] = username
            formatted_obj['owner_name'] = full_name
            if obj.category:
                formatted_obj['category__gn_description'] = _(obj.category.gn_description)
            if obj.group:
                formatted_obj['group'] = obj.group
                try:
                    formatted_obj['group_name'] = GroupProfile.objects.get(slug=obj.group.name)
                except GroupProfile.DoesNotExist:
                    formatted_obj['group_name'] = obj.group

            formatted_obj['keywords'] = [k.name for k in obj.keywords.all()] if obj.keywords else []
            formatted_obj['regions'] = [r.name for r in obj.regions.all()] if obj.regions else []

            # provide style information
            bundle = self.build_bundle(obj=obj)
            formatted_obj['default_style'] = self.default_style.dehydrate(
                bundle, for_list=True)

            # Add resource uri
            formatted_obj['resource_uri'] = self.get_resource_uri(bundle)

            formatted_obj['links'] = self.dehydrate_ogc_links(bundle)

            if 'site_url' not in formatted_obj or len(formatted_obj['site_url']) == 0:
                formatted_obj['site_url'] = settings.SITEURL

            # Probe Remote Services
            formatted_obj['store_type'] = 'dataset'
            formatted_obj['online'] = True
            if hasattr(obj, 'storeType'):
                formatted_obj['store_type'] = obj.storeType
                if obj.storeType == 'remoteStore' and hasattr(obj, 'remote_service'):
                    if obj.remote_service:
                        formatted_obj['online'] = (obj.remote_service.probe == 200)
                    else:
                        formatted_obj['online'] = False

            formatted_obj['gtype'] = self.dehydrate_gtype(bundle)

            # replace thumbnail_url with curated_thumbs
            if hasattr(obj, 'curatedthumbnail'):
                formatted_obj['thumbnail_url'] = obj.curatedthumbnail.thumbnail_url

            formatted_obj['processed'] = obj.instance_is_processed
            # put the object on the response stack
            formatted_objects.append(formatted_obj)
        return formatted_objects

    def _dehydrate_links(self, bundle, link_types=None):
        """Dehydrate links field."""

        dehydrated = []
        obj = bundle.obj
        link_fields = [
            'extension',
            'link_type',
            'name',
            'mime',
            'url'
        ]

        links = obj.link_set.all()
        if link_types:
            links = links.filter(link_type__in=link_types)
        for lnk in links:
            formatted_link = model_to_dict(lnk, fields=link_fields)
            dehydrated.append(formatted_link)

        return dehydrated

    def dehydrate_links(self, bundle):
        return self._dehydrate_links(bundle)

    def dehydrate_ogc_links(self, bundle):
        return self._dehydrate_links(bundle, ['OGC:WMS', 'OGC:WFS', 'OGC:WCS'])

    def dehydrate_gtype(self, bundle):
        return bundle.obj.gtype

    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 populate_object(self, obj):
        """Populate results with necessary fields

        :param obj: Layer obj
        :type obj: Layer
        :return:
        """
        return obj

    # copy parent attribute before modifying
    VALUES = CommonModelApi.VALUES[:]
    VALUES.append('typename')

    class Meta(CommonMetaApi):
        paginator_class = CrossSiteXHRPaginator
        queryset = Layer.objects.distinct().order_by('-date')
        resource_name = 'layers'
        detail_uri_name = 'id'
        include_resource_uri = True
        allowed_methods = ['get', 'patch']
        excludes = ['csw_anytext', 'metadata_xml']
        authentication = MultiAuthentication(SessionAuthentication(),
                                             OAuthAuthentication(),
                                             GeonodeApiKeyAuthentication())
        filtering = CommonMetaApi.filtering
        # Allow filtering using ID
        filtering.update({
            'id': ALL,
            'name': ALL,
            'alternate': ALL,
        })
Пример #22
0
class ExperimentResource(MyTardisModelResource):
    '''API for Experiments
    also creates a default ACL and allows ExperimentParameterSets to be read
    and written.

    TODO: catch duplicate schema submissions for parameter sets
    '''
    created_by = fields.ForeignKey(UserResource, 'created_by')
    parameter_sets = fields.ToManyField(
        'tardis.tardis_portal.api.ExperimentParameterSetResource',
        'experimentparameterset_set',
        related_name='experiment',
        full=True,
        null=True)

    class Meta(MyTardisModelResource.Meta):
        queryset = Experiment.objects.all()
        filtering = {
            'id': ('exact', ),
            'title': ('exact', ),
        }
        ordering = ['id', 'title', 'created_time', 'update_time']
        always_return_data = True

    def dehydrate(self, bundle):
        exp = bundle.obj
        authors = [{
            'name': a.author,
            'url': a.url
        } for a in exp.experimentauthor_set.all()]
        bundle.data['authors'] = authors
        lic = exp.license
        if lic is not None:
            bundle.data['license'] = {
                'name': lic.name,
                'url': lic.url,
                'description': lic.internal_description,
                'image_url': lic.image_url,
                'allows_distribution': lic.allows_distribution,
            }
        owners = exp.get_owners()
        bundle.data['owner_ids'] = [o.id for o in owners]
        return bundle

    def hydrate_m2m(self, bundle):
        '''
        create ACL before any related objects are created in order to use
        ACL permissions for those objects.
        '''
        if getattr(bundle.obj, 'id', False):
            experiment = bundle.obj
            # TODO: unify this with the view function's ACL creation,
            # maybe through an ACL toolbox.
            acl = ObjectACL(content_type=experiment.get_ct(),
                            object_id=experiment.id,
                            pluginId=django_user,
                            entityId=str(bundle.request.user.id),
                            canRead=True,
                            canWrite=True,
                            canDelete=True,
                            isOwner=True,
                            aclOwnershipType=ObjectACL.OWNER_OWNED)
            acl.save()

        return super(ExperimentResource, self).hydrate_m2m(bundle)

    def obj_create(self, bundle, **kwargs):
        '''experiments need at least one ACL to be available through the
        ExperimentManager (Experiment.safe)
        Currently not tested for failed db transactions as sqlite does not
        enforce limits.
        '''
        user = bundle.request.user
        bundle.data['created_by'] = user
        bundle = super(ExperimentResource, self).obj_create(bundle, **kwargs)
        return bundle
Пример #23
0
class PipelineInstanceResource(ModelResource):
    data = fields.ForeignKey(SnapshotResource, 'snapshot')
    exec_data = fields.ForeignKey(SnapshotResource, 'execution_snapshot')
    template = fields.ForeignKey(PipelineTemplateResource, 'template')

    pop_keys = [
        'is_deleted', 'edit_time', 'create_time', 'snapshot', 'template',
        'is_finished', 'is_started', 'finish_time', 'start_time',
        'instance_id', 'execution_snapshot'
    ]

    class Meta:
        queryset = PipelineInstance.objects.filter(is_deleted=False)
        resource_name = 'instances'
        excludes = ['is_deleted', 'id']
        always_return_data = True
        detail_uri_name = 'instance_id'
        list_allowed_method = ['get', 'post']
        detail_allowed_methods = ['get', 'patch', 'post', 'delete']
        filtering = {
            'template': ALL_WITH_RELATIONS,
        }

        authorization = Authorization()
        serializer = PipelineSerializer()

    def dehydrate_data(self, bundle):
        return json.dumps(bundle.obj.snapshot.data)

    def dehydrate_exec_data(self, bundle):
        return json.dumps(bundle.obj.execution_snapshot.data)

    def hydrate(self, bundle):
        for key in self.pop_keys:
            if key in bundle.data:
                bundle.data.pop(key)

        return super(PipelineInstanceResource, self).hydrate(bundle)

    def alter_list_data_to_serialize(self, request, data):
        for bundle in data['objects']:
            bundle.data.pop('data')
            bundle.data.pop('exec_data')
            bundle.data.pop('description')
            bundle.data.pop('template')

        return data

    def alter_detail_data_to_serialize(self, request, data):
        bundle = data
        bundle.data.pop('template')

        return data

    def obj_create(self, bundle, **kwargs):
        template_id = bundle.data.get('template_id')
        try:
            template = PipelineTemplate.objects.get(template_id=template_id)
        except Exception:
            raise_validation_error(self, bundle, 'instances', 'template_id',
                                   _(u"模板不存在"))

        exec_data = bundle.data.get('exec_data')
        try:
            exec_data = json.loads(exec_data)
        except Exception:
            raise_validation_error(self, bundle, 'instances', 'exec_data',
                                   _(u"JSON 格式不合法"))

        # unfold subprocess
        unfold_subprocess(exec_data)
        instance_id = node_uniqid()
        exec_data['id'] = instance_id
        exec_snapshot, __ = Snapshot.objects.create_or_get_snapshot(exec_data)
        kwargs['template_id'] = template.id
        kwargs['instance_id'] = instance_id
        kwargs['snapshot_id'] = template.snapshot.id
        kwargs['execution_snapshot_id'] = exec_snapshot.id
        bundle.data.pop('exec_data')
        return super(PipelineInstanceResource,
                     self).obj_create(bundle, **kwargs)

    def obj_update(self, bundle, skip_errors=False, **kwargs):
        exec_data = bundle.data['exec_data']
        try:
            data = json.loads(exec_data)
        except Exception:
            raise_validation_error(self, bundle, 'instances', 'exec_data',
                                   _(u"JSON 格式不合法"))

        bundle.obj.execution_snapshot, __ = Snapshot.objects.create_or_get_snapshot(
            data)
        bundle.data.pop('exec_data')
        bundle.data.pop('data')
        return super(PipelineInstanceResource,
                     self).obj_update(bundle,
                                      skip_errors=skip_errors,
                                      **kwargs)

    def obj_delete(self, bundle, **kwargs):
        instance_id = kwargs['instance_id']
        PipelineInstance.objects.delete_model(instance_id)
Пример #24
0
class DatasetResource(MyTardisModelResource):
    experiments = fields.ToManyField(ExperimentResource,
                                     'experiments',
                                     related_name='datasets')
    parameter_sets = fields.ToManyField(
        'tardis.tardis_portal.api.DatasetParameterSetResource',
        'datasetparameterset_set',
        related_name='dataset',
        full=True,
        null=True)
    instrument = fields.ForeignKey(InstrumentResource,
                                   'instrument',
                                   null=True,
                                   full=True)

    class Meta(MyTardisModelResource.Meta):
        queryset = Dataset.objects.all()
        filtering = {
            'id': ('exact', ),
            'experiments': ALL_WITH_RELATIONS,
            'description': ('exact', ),
            'directory': ('exact', ),
            'instrument': ALL_WITH_RELATIONS,
        }
        ordering = ['id', 'description']
        always_return_data = True

    def prepend_urls(self):
        return [
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/files/'
                r'(?:(?P<file_path>.+))?$' % self._meta.resource_name,
                self.wrap_view('get_datafiles'),
                name='api_get_datafiles_for_dataset'),
        ]

    def get_datafiles(self, request, **kwargs):
        file_path = kwargs.get('file_path', None)
        dataset_id = kwargs['pk']

        datafiles = DataFile.objects.filter(dataset__id=dataset_id)
        auth_bundle = self.build_bundle(request=request)
        auth_bundle.obj = DataFile()
        self.authorized_read_list(datafiles, auth_bundle)
        del kwargs['pk']
        del kwargs['file_path']
        kwargs['dataset__id'] = dataset_id
        if file_path is not None:
            kwargs['directory__startswith'] = file_path
        df_res = DataFileResource()
        return df_res.dispatch('list', request, **kwargs)

    def hydrate_m2m(self, bundle):
        '''
        Create experiment-dataset associations first, because they affect
        authorization for adding other related resources, e.g. metadata
        '''
        if getattr(bundle.obj, 'id', False):
            for exp_uri in bundle.data.get('experiments', []):
                try:
                    exp = ExperimentResource.get_via_uri(
                        ExperimentResource(), exp_uri, bundle.request)
                    bundle.obj.experiments.add(exp)
                except NotFound:
                    pass
        return super(DatasetResource, self).hydrate_m2m(bundle)
Пример #25
0
class JournalResource(ModelResource):
    missions = fields.CharField(readonly=True)
    other_titles = fields.CharField(readonly=True)
    creator = fields.ForeignKey(UserResource, 'creator')
    abstract_keyword_languages = fields.CharField(readonly=True)
    languages = fields.CharField(readonly=True)
    use_license = fields.ForeignKey(UseLicenseResource,
                                    'use_license',
                                    full=True)
    sponsors = fields.ManyToManyField(SponsorResource, 'sponsor')
    collections = fields.ManyToManyField(CollectionResource, 'collections')
    issues = fields.OneToManyField(IssueResource, 'issue_set')
    sections = fields.OneToManyField(SectionResource, 'section_set')
    pub_status_history = fields.ListField(readonly=True)
    contact = fields.DictField(readonly=True)
    study_areas = fields.ListField(readonly=True)
    pub_status = fields.CharField(readonly=True)
    pub_status_reason = fields.CharField(readonly=True)

    #recursive field
    previous_title = fields.ForeignKey('self', 'previous_title', null=True)

    class Meta(ApiKeyAuthMeta):
        queryset = Journal.objects.all().filter()
        resource_name = 'journals'
        allowed_methods = [
            'get',
        ]
        filtering = {
            'is_trashed': ('exact', ),
            'eletronic_issn': ('exact', ),
            'print_issn': ('exact', ),
        }

    def build_filters(self, filters=None):
        """
        Custom filter that retrieves data by the collection's name_slug.
        """
        if filters is None:
            filters = {}

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

        if 'collection' in filters:
            journals = Journal.objects.filter(
                collections__name_slug=filters['collection'])
            orm_filters['pk__in'] = journals

        if 'pubstatus' in filters:
            # keep the previous filtering
            try:
                j = orm_filters['pk__in']
            except KeyError:
                j = Journal.objects

            statuses = filters.getlist('pubstatus')
            journals = j.filter(membership__status__in=statuses)
            orm_filters['pk__in'] = journals

        return orm_filters

    def dehydrate_missions(self, bundle):
        return [(mission.language.iso_code, mission.description)
                for mission in bundle.obj.missions.all()]

    def dehydrate_other_titles(self, bundle):
        return [(title.category, title.title)
                for title in bundle.obj.other_titles.all()]

    def dehydrate_languages(self, bundle):
        return [language.iso_code for language in bundle.obj.languages.all()]

    def dehydrate_pub_status_history(self, bundle):
        return [{
            'date': event.since,
            'status': event.status
        } for event in bundle.obj.statuses.order_by('-since').all()]

    def dehydrate_study_areas(self, bundle):
        return [area.study_area for area in bundle.obj.study_areas.all()]

    def dehydrate_collections(self, bundle):
        """Only works com v1, without multiple collections per journal.
        """
        try:
            return bundle.data['collections'][0]
        except IndexError:
            return ''

    def dehydrate_pub_status(self, bundle):
        col = bundle.obj.collections.get()
        return bundle.obj.membership_info(col, 'status')

    def dehydrate_pub_status_reason(self, bundle):
        col = bundle.obj.collections.get()
        return bundle.obj.membership_info(col, 'reason')
Пример #26
0
class DataFileResource(MyTardisModelResource):
    dataset = fields.ForeignKey(DatasetResource, 'dataset')
    parameter_sets = fields.ToManyField(
        'tardis.tardis_portal.api.DatafileParameterSetResource',
        'datafileparameterset_set',
        related_name='datafile',
        full=True,
        null=True)
    datafile = fields.FileField()
    replicas = fields.ToManyField('tardis.tardis_portal.api.ReplicaResource',
                                  'file_objects',
                                  related_name='datafile',
                                  full=True,
                                  null=True)
    temp_url = None

    class Meta(MyTardisModelResource.Meta):
        queryset = DataFile.objects.all()
        filtering = {
            'directory': ('exact', 'startswith'),
            'dataset': ALL_WITH_RELATIONS,
            'filename': ('exact', ),
        }
        ordering = ['id', 'filename', 'modification_time']
        resource_name = 'dataset_file'

    def download_file(self, request, **kwargs):
        '''
        curl needs the -J switch to get the filename right
        auth needs to be added manually here
        '''
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        if not has_datafile_download_access(request=request,
                                            datafile_id=kwargs['pk']):
            return HttpResponseForbidden()

        file_record = self._meta.queryset.get(pk=kwargs['pk'])
        self.authorized_read_detail([file_record],
                                    self.build_bundle(obj=file_record,
                                                      request=request))

        preferred_dfo = file_record.get_preferred_dfo()
        if not preferred_dfo:
            # No verified DataFileObject exists for this DataFile
            return HttpResponseNotFound()

        storage_class_name = preferred_dfo.storage_box.django_storage_class
        download_uri_templates = getattr(settings, 'DOWNLOAD_URI_TEMPLATES',
                                         {})
        if storage_class_name in download_uri_templates:
            template = URITemplate(download_uri_templates[storage_class_name])
            return redirect(template.expand(dfo_id=preferred_dfo.id))

        file_object = file_record.get_file()
        wrapper = FileWrapper(file_object)
        tracker_data = dict(label='file',
                            session_id=request.COOKIES.get('_ga'),
                            ip=request.META.get('REMOTE_ADDR', ''),
                            user=request.user,
                            total_size=file_record.size,
                            num_files=1,
                            ua=request.META.get('HTTP_USER_AGENT', None))
        response = StreamingHttpResponse(IteratorTracker(
            wrapper, tracker_data),
                                         content_type=file_record.mimetype)
        response['Content-Length'] = file_record.size
        response['Content-Disposition'] = 'attachment; filename="%s"' % \
                                          file_record.filename
        self.log_throttled_access(request)
        return response

    def verify_file(self, request, **kwargs):
        '''triggers verification of file, e.g. after non-POST upload complete
        '''
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        if not has_datafile_download_access(request=request,
                                            datafile_id=kwargs['pk']):
            return HttpResponseForbidden()

        file_record = self._meta.queryset.get(pk=kwargs['pk'])
        self.authorized_read_detail([file_record],
                                    self.build_bundle(obj=file_record,
                                                      request=request))
        for dfo in file_record.file_objects.all():
            shadow = 'dfo_verify location:%s' % dfo.storage_box.name
            tasks.dfo_verify.apply_async(args=[dfo.id],
                                         priority=dfo.priority,
                                         shadow=shadow)
        return HttpResponse()

    def hydrate(self, bundle):
        if 'attached_file' in bundle.data:
            # have POSTed file
            newfile = bundle.data['attached_file'][0]
            compute_md5 = getattr(settings, 'COMPUTE_MD5', True)
            compute_sha512 = getattr(settings, 'COMPUTE_SHA512', False)
            if (compute_md5 and 'md5sum' not in bundle.data) or \
                    (compute_sha512 and 'sha512sum' not in bundle.data):
                checksums = compute_checksums(newfile,
                                              compute_md5=compute_md5,
                                              compute_sha512=compute_sha512,
                                              close_file=False)
                if compute_md5:
                    bundle.data['md5sum'] = checksums['md5sum']
                if compute_sha512:
                    bundle.data['sha512sum'] = checksums['sha512sum']

            if 'replicas' in bundle.data:
                for replica in bundle.data['replicas']:
                    replica.update({'file_object': newfile})
            else:
                bundle.data['replicas'] = [{'file_object': newfile}]

            del (bundle.data['attached_file'])
        return bundle

    def obj_create(self, bundle, **kwargs):
        '''
        Creates a new DataFile object from the provided bundle.data dict.

        If a duplicate key error occurs, responds with HTTP Error 409: CONFLICT
        '''
        try:
            retval = super(DataFileResource, self).obj_create(bundle, **kwargs)
        except IntegrityError as err:
            if "duplicate key" in str(err):
                raise ImmediateHttpResponse(HttpResponse(status=409))
            raise
        if 'replicas' not in bundle.data or not bundle.data['replicas']:
            # no replica specified: return upload path and create dfo for
            # new path
            sbox = bundle.obj.get_receiving_storage_box()
            if sbox is None:
                raise NotImplementedError
            dfo = DataFileObject(datafile=bundle.obj, storage_box=sbox)
            dfo.create_set_uri()
            dfo.save()
            self.temp_url = dfo.get_full_path()
        return retval

    def post_list(self, request, **kwargs):
        response = super(DataFileResource, self).post_list(request, **kwargs)
        if self.temp_url is not None:
            response.content = self.temp_url
            self.temp_url = None
        return response

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/download%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('download_file'),
                name="api_download_file"),
            url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/verify%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('verify_file'),
                name="api_verify_file"),
        ]

    def deserialize(self, request, data, format=None):
        '''
        from https://github.com/toastdriven/django-tastypie/issues/42
        modified to deserialize json sent via POST. Would fail if data is sent
        in a different format.
        uses a hack to get back pure json from request.POST
        '''
        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'):
            jsondata = request.POST['json_data']
            data = json.loads(jsondata)
            data.update(request.FILES)
            return data
        return super(DataFileResource, self).deserialize(request, data, format)

    def put_detail(self, request, **kwargs):
        '''
        from https://github.com/toastdriven/django-tastypie/issues/42
        '''
        if request.META.get('CONTENT_TYPE').startswith('multipart') and \
                not hasattr(request, '_body'):
            request._body = ''

        return super(DataFileResource, self).put_detail(request, **kwargs)
Пример #27
0
class IssueResource(ModelResource):
    journal = fields.ForeignKey('api.resources.JournalResource', 'journal')
    sections = fields.ManyToManyField(SectionResource, 'section')
    thematic_titles = fields.CharField(readonly=True)
    is_press_release = fields.BooleanField(readonly=True)
    suppl_volume = fields.CharField(readonly=True)
    suppl_number = fields.CharField(readonly=True)

    class Meta(ApiKeyAuthMeta):
        queryset = Issue.objects.all()
        resource_name = 'issues'
        allowed_methods = [
            'get',
        ]
        filtering = {
            "journal": ('exact'),
            "is_marked_up": ('exact'),
            "volume": ('exact'),
            "number": ('exact'),
            "publication_year": ('exact'),
            "suppl_number": ('exact'),
            "suppl_volume": ('exact')
        }

    def build_filters(self, filters=None):
        """
        Custom filter that retrieves data by the collection's name_slug.
        """
        if filters is None:
            filters = {}

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

        if 'collection' in filters:
            issues = Issue.objects.filter(
                journal__collection__name_slug=filters['collection'])
            orm_filters['pk__in'] = issues

        if 'eletronic_issn' in filters:
            issues = Issue.objects.filter(
                journal__eletronic_issn=filters['eletronic_issn'])
            orm_filters['pk__in'] = issues

        if 'print_issn' in filters:
            issues = Issue.objects.filter(
                journal__print_issn=filters['print_issn'])
            orm_filters['pk__in'] = issues

        return orm_filters

    def dehydrate_thematic_titles(self, bundle):
        return dict([title.language.iso_code, title.title]
                    for title in bundle.obj.issuetitle_set.all())

    def dehydrate_is_press_release(self, bundle):
        return False

    def dehydrate_suppl_volume(self, bundle):
        if bundle.obj.type == 'supplement':
            return bundle.obj.suppl_text if bundle.obj.volume else ''
        else:
            return ''

    def dehydrate_suppl_number(self, bundle):
        if bundle.obj.type == 'supplement':
            return bundle.obj.suppl_text if bundle.obj.number else ''
        else:
            return ''
Пример #28
0
class DatafileParameterResource(ParameterResource):
    parameterset = fields.ForeignKey(DatafileParameterSetResource,
                                     'parameterset')

    class Meta(ParameterResource.Meta):
        queryset = DatafileParameter.objects.all()
Пример #29
0
class UserAbuseResource(BaseAbuseResource):
    user = fields.ForeignKey(AccountResource, attribute='user', full=True)

    class Meta(BaseAbuseResource.Meta):
        resource_name = 'user'
        validation = RequestFormValidation(form_class=UserAbuseForm)
Пример #30
0
class OMSInstanceResource(ModelResource):
    host = fields.ForeignKey(OMSHostResource, 'host')

    class Meta:
        queryset = OMSInstance.objects.all()
        resource_name = 'instance'