Beispiel #1
0
class VosaeCalendarResource(TenantResource):
    summary = base_fields.CharField(
        attribute='summary', help_text=HELP_TEXT['vosae_calendar']['summary'])
    description = base_fields.CharField(
        attribute='description',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_calendar']['description'])
    location = base_fields.CharField(
        attribute='location',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_calendar']['location'])
    timezone = base_fields.CharField(
        attribute='timezone',
        blank=True,
        help_text=HELP_TEXT['vosae_calendar']['timezone'])

    acl = fields.EmbeddedDocumentField(
        embedded='organizer.api.resources.CalendarAclResource',
        attribute='acl',
        help_text=HELP_TEXT['vosae_calendar']['acl'])

    class Meta(TenantResource.Meta):
        resource_name = 'vosae_calendar'
        queryset = VosaeCalendar.objects.all()
        excludes = ('tenant', 'occurrences', 'ical_data')

    def get_object_list(self, request):
        """Filters calendars on current user and its groups (extracted from request)"""
        object_list = super(VosaeCalendarResource,
                            self).get_object_list(request)
        principals = [request.vosae_user] + request.vosae_user.groups
        return object_list.filter(Q(acl__read_list__in=principals))
class EmbeddedListInEmbeddedDocTestResource(resources.MongoEngineResource):
    post = fields.EmbeddedDocumentField(embedded='test_project.test_app.api.resources.EmbeddedPostResource', attribute='post')

    class Meta:
        queryset = documents.EmbeddedListInEmbeddedDocTest.objects.all()
        allowed_methods = ('get', 'post', 'put', 'patch', 'delete')
        authorization = tastypie_authorization.Authorization()
Beispiel #3
0
class PurchaseOrderResource(InvoiceBaseResource, InvoiceMakableResourceMixin):
    state = base_fields.CharField(
        attribute='state',
        readonly=True,
        help_text=HELP_TEXT['purchase_order']['state']
    )

    current_revision = fields.EmbeddedDocumentField(
        embedded='invoicing.api.resources.PurchaseOrderRevisionResource',
        attribute='current_revision',
        help_text=HELP_TEXT['purchase_order']['current_revision']
    )
    revisions = fields.EmbeddedListField(
        of='invoicing.api.resources.PurchaseOrderRevisionResource',
        attribute='revisions',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['purchase_order']['revisions']
    )

    class Meta(InvoiceBaseResource.Meta):
        resource_name = 'purchase_order'
        queryset = PurchaseOrder.objects.all()
        detail_specific_methods = ('make_down_payment_invoice', 'make_invoice', 'mark_as_awaiting_approval')

    def prepend_urls(self):
        """Add urls for resources actions."""
        urls = super(PurchaseOrderResource, self).prepend_urls()
        urls.extend((
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/make_invoice%s$' % (self._meta.resource_name, trailing_slash()), self.wrap_view('make_invoice'), name='api_quotation_make_invoice'),
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/make_down_payment_invoice%s$' % (self._meta.resource_name, trailing_slash()), self.wrap_view('make_down_payment_invoice'), name='api_quotation_make_down_payment_invoice'),
        ))
        return urls
class EmbeddedDocumentFieldTestResource(resources.MongoEngineResource):
    customer = fields.EmbeddedDocumentField(embedded='test_project.test_app.api.resources.EmbeddedPersonResource', attribute='customer', null=True)

    class Meta:
        queryset = documents.EmbeddedDocumentFieldTest.objects.all()
        allowed_methods = ('get', 'post', 'put', 'patch', 'delete')
        authorization = tastypie_authorization.Authorization()
Beispiel #5
0
class InvoicingSettingsResource(VosaeResource):
    fy_start_month = base_fields.IntegerField(
        attribute='fy_start_month',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoicing_settings']['fy_start_month'])
    inv_taxes_application = base_fields.CharField(
        attribute='inv_taxes_application',
        help_text=HELP_TEXT['invoicing_settings']['inv_taxes_application'])
    quotation_validity = base_fields.CharField(
        attribute='quotation_validity',
        help_text=HELP_TEXT['invoicing_settings']['quotation_validity'])
    payment_conditions = base_fields.CharField(
        attribute='payment_conditions',
        help_text=HELP_TEXT['invoicing_settings']['payment_conditions'])
    custom_payment_conditions = base_fields.CharField(
        attribute='custom_payment_conditions',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoicing_settings']['custom_payment_conditions'])
    late_fee_rate = base_fields.DecimalField(
        attribute='late_fee_rate',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoicing_settings']['late_fee_rate'])
    accepted_payment_types = base_fields.ListField(
        attribute='accepted_payment_types',
        help_text=HELP_TEXT['invoicing_settings']['accepted_payment_types'])
    down_payment_percent = base_fields.DecimalField(
        attribute='down_payment_percent',
        help_text=HELP_TEXT['invoicing_settings']['down_payment_percent'])
    automatic_reminders = base_fields.BooleanField(
        attribute='automatic_reminders',
        help_text=HELP_TEXT['invoicing_settings']['automatic_reminders'])
    automatic_reminders_text = base_fields.CharField(
        attribute='automatic_reminders_text',
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoicing_settings']['automatic_reminders_text'])
    automatic_reminders_send_copy = base_fields.BooleanField(
        attribute='automatic_reminders_send_copy',
        help_text=HELP_TEXT['invoicing_settings']
        ['automatic_reminders_send_copy'])

    supported_currencies = SupportedCurrenciesListField(
        of='invoicing.api.resources.CurrencyResource',
        attribute='supported_currencies',
        help_text=HELP_TEXT['invoicing_settings']['supported_currencies'])
    default_currency = fields.ReferenceField(
        to='invoicing.api.resources.CurrencyResource',
        attribute='default_currency',
        help_text=HELP_TEXT['invoicing_settings']['default_currency'])
    numbering = fields.EmbeddedDocumentField(
        embedded=
        'vosae_settings.api.resources.invoicing_settings.InvoicingNumberingSettingsResource',
        attribute='numbering',
        help_text=HELP_TEXT['invoicing_settings']['numbering'])

    class Meta:
        object_class = InvoicingSettings
Beispiel #6
0
class CoreSettingsResource(VosaeResource):
    quotas = fields.EmbeddedDocumentField(
        embedded=
        'vosae_settings.api.resources.core_settings.StorageQuotasSettingsResource',
        attribute='quotas',
        readonly=True,
        help_text=HELP_TEXT['core_settings']['quotas'])

    class Meta:
        object_class = CoreSettings
Beispiel #7
0
class TenantSettingsResource(TenantResource):
    core = fields.EmbeddedDocumentField(
        embedded=
        'vosae_settings.api.resources.core_settings.CoreSettingsResource',
        attribute='core',
        null=True,  # XXX: Temp, because core settings are currently empty
        blank=True,  # XXX: Temp, because core settings are currently empty
    )
    invoicing = fields.EmbeddedDocumentField(
        embedded=
        'vosae_settings.api.resources.invoicing_settings.InvoicingSettingsResource',
        attribute='invoicing',
    )

    class Meta(TenantResource.Meta):
        resource_name = 'tenant_settings'
        queryset = TenantSettings.objects.all()
        excludes = ('tenant', 'id')
        list_allowed_methods = ()
        detail_allowed_methods = ('get', 'put')
        include_resource_uri = False

    def base_urls(self):
        return [
            url(r"^(?P<resource_name>%s)%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('dispatch_list'),
                name="api_dispatch_list"),
            url(r"^(?P<resource_name>%s)/schema%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_schema'),
                name="api_get_schema"),
        ]

    def dispatch_list(self, request, **kwargs):
        kwargs.update(pk=unicode(request.tenant.tenant_settings.id))
        return self.dispatch('detail', request, **kwargs)

    def dispatch(self, request_type, request, **kwargs):
        # Ancestor + 1 dispatch
        return super(VosaeResource, self).dispatch(request_type, request,
                                                   **kwargs)
class ReadonlyParentResource(resources.MongoEngineResource):
    tzdt = fields.EmbeddedDocumentField(
        embedded=
        'test_project.test_app.api.resources.TimezonedDateTimeResource',
        attribute='tzdt',
        readonly=True)

    class Meta(object):
        queryset = documents.ReadonlyParent.objects.all()
        allowed_methods = ('get', 'post', 'put', 'patch', 'delete')
        authorization = tastypie_authorization.Authorization()
Beispiel #9
0
class ClassificationResource(GenericPMResource):

    css_style = mongo_fields.EmbeddedDocumentField(
        embedded='protective_marking_app.api.CssStyleResource',
        attribute='css_style',
        help_text='CSS Style associated with this protective marking element',
        null=True)

    class Meta(GenericPMResource.Meta):
        queryset = documents.Classification.objects.all()
        resource_name = 'classification'
class BlankableParentResource(resources.MongoEngineResource):
    embedded = fields.EmbeddedDocumentField(
        embedded=
        'test_project.test_app.api.resources.BlankableEmbeddedResource',
        attribute='embedded',
        blank=True)

    class Meta(object):
        queryset = documents.BlankableParent.objects.all()
        allowed_methods = ('get', 'post', 'put', 'patch', 'delete')
        authorization = tastypie_authorization.Authorization()
Beispiel #11
0
class CreditNoteResource(InvoiceBaseResource):
    state = base_fields.CharField(
        attribute='state',
        readonly=True,
        help_text=HELP_TEXT['creditnote']['state']
    )

    current_revision = fields.EmbeddedDocumentField(
        embedded='invoicing.api.resources.CreditNoteRevisionResource',
        attribute='current_revision',
        help_text=HELP_TEXT['creditnote']['current_revision']
    )
    revisions = fields.EmbeddedListField(
        of='invoicing.api.resources.CreditNoteRevisionResource',
        attribute='revisions',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['creditnote']['revisions']
    )
    related_to = fields.ReferenceField(
        to='invoicing.api.resources.InvoiceResource',
        attribute='related_to',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['creditnote']['related_to']
    )

    class Meta(InvoiceBaseResource.Meta):
        resource_name = 'credit_note'
        queryset = CreditNote.objects.all()
        list_allowed_methods = ('get',)
        detail_allowed_methods = ('get',)
        detail_specific_methods = ('cancel',)

    def dehydrate_related_to(self, bundle):
        from invoicing.api.resources import DownPaymentInvoiceResource, InvoiceResource
        try:
            if bundle.obj.related_to.is_down_payment_invoice():
                resource = DownPaymentInvoiceResource()
            elif bundle.obj.related_to.is_invoice():
                resource = InvoiceResource()
            resource_bundle = resource.build_bundle(obj=bundle.obj.related_to, request=bundle.request)
            return resource.get_resource_uri(resource_bundle)
        except:
            return
Beispiel #12
0
class IdeaTagResource(resources.MongoEngineResource):
    """ the listed embedded subdocument tag as opposed to the result of the aggregate function"""

    tag_protective_marking = mongo_fields.EmbeddedDocumentField(
        embedded='ideasapp.api.ProtectiveMarkingResource',
        attribute='tag_protective_marking',
        help_text='protective marking of this comment',
        null=True)

    class Meta:
        resource_name = 'ideatag'
        object_class = documents.IdeaTag
        allowed_methods = ['get', 'post']
        serializer = CustomSerializer()

        authentication = CustomApiKeyAuthentication()
        authorization = Authorization()

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

        content_types = {
            'json': 'application/json',
            'jsonp': 'text/javascript',
            'xml': 'application/xml',
            'yaml': 'text/yaml',
            'html': 'text/html',
            'plist': 'application/x-plist',
            'csv': 'text/csv',
        }

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

    def post_list(self, request, **kwargs):
        """ Upon creation of a new idea tag, change the total count too"""

        # Update the current tag count + count of new tags
        doc_id = request.path.replace('/tags/', '').split('/')[-1]
        documents.Idea.objects(id=doc_id).update(**{'inc__tag_count': 1})
        return super(IdeaTagResource, self).post_list(request)
Beispiel #13
0
class VosaeEventResource(TenantResource):
    status = base_fields.CharField(
        attribute='status',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['status'])
    created_at = base_fields.DateTimeField(
        attribute='created_at',
        readonly=True,
        help_text=HELP_TEXT['vosae_event']['created_at'])
    updated_at = base_fields.DateTimeField(
        attribute='updated_at',
        readonly=True,
        help_text=HELP_TEXT['vosae_event']['updated_at'])
    summary = base_fields.CharField(
        attribute='summary', help_text=HELP_TEXT['vosae_event']['summary'])
    description = base_fields.CharField(
        attribute='description',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['description'])
    location = base_fields.CharField(
        attribute='location',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['location'])
    color = base_fields.CharField(attribute='color',
                                  null=True,
                                  blank=True,
                                  help_text=HELP_TEXT['vosae_event']['color'])
    start = fields.EmbeddedDocumentField(
        embedded='organizer.api.resources.EventDateTimeResource',
        attribute='start',
        help_text=HELP_TEXT['vosae_event']['start'])
    end = fields.EmbeddedDocumentField(
        embedded='organizer.api.resources.EventDateTimeResource',
        attribute='end',
        help_text=HELP_TEXT['vosae_event']['end'])
    recurrence = base_fields.CharField(
        attribute='recurrence',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['recurrence'])
    original_start = fields.EmbeddedDocumentField(
        embedded='organizer.api.resources.EventDateTimeResource',
        attribute='original_start',
        readonly=True,
        help_text=HELP_TEXT['vosae_event']['original_start'])
    instance_id = base_fields.CharField(
        attribute='instance_id',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['instance_id'])
    transparency = base_fields.CharField(
        attribute='transparency',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_event']['transparency'])

    calendar = fields.ReferenceField(
        to='organizer.api.resources.VosaeCalendarResource',
        attribute='calendar',
        help_text=HELP_TEXT['vosae_event']['calendar'])
    creator = fields.ReferenceField(
        to='core.api.resources.VosaeUserResource',
        attribute='creator',
        readonly=True,
        help_text=HELP_TEXT['vosae_event']['creator'])
    organizer = fields.ReferenceField(
        to='core.api.resources.VosaeUserResource',
        attribute='organizer',
        readonly=True,
        help_text=HELP_TEXT['vosae_event']['organizer'])
    attendees = fields.EmbeddedListField(
        of='organizer.api.resources.AttendeeResource',
        attribute='attendees',
        null=True,
        blank=True,
        full=True,
        help_text=HELP_TEXT['vosae_event']['attendees'])
    reminders = fields.EmbeddedDocumentField(
        embedded='organizer.api.resources.ReminderSettingsResource',
        attribute='reminders',
        blank=True,
        help_text=HELP_TEXT['vosae_event']['reminders'])

    class Meta(TenantResource.Meta):
        resource_name = 'vosae_event'
        queryset = VosaeEvent.objects.all()
        excludes = ('tenant', 'occurrences', 'next_reminder', 'ical_uid',
                    'ical_data')
        filtering = {
            'start': ('exact', 'gt', 'gte'),
            'end': ('exact', 'lt', 'lte'),
            'calendar': ('exact')
        }
        validation = EventValidation()

    def prepend_urls(self):
        """Add urls for resources actions."""
        urls = super(VosaeEventResource, self).prepend_urls()
        urls.extend(
            (url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/instances%s$' %
                 (self._meta.resource_name, trailing_slash()),
                 self.wrap_view('event_instances'),
                 name='api_vosae_event_instances'), ))
        return urls

    def build_filters(self, filters=None):
        qs_filters = super(VosaeEventResource, self).build_filters(filters)
        for filter_name, filter_value in qs_filters.iteritems():
            if filter_name.endswith('__exact'):
                new_name = filter_name[:filter_name.index('__exact')]
                qs_filters[new_name] = filter_value
                del qs_filters[filter_name]
                filter_name = new_name
            if filter_name in DATERANGE_FILTERS:
                if isinstance(filter_value, basestring):
                    qs_filters[filter_name] = parse(filter_value)
        return qs_filters

    def get_object_list(self, request):
        """Filters events based on calendar accesses (extracted from request user)"""
        from organizer.models import VosaeCalendar
        object_list = super(VosaeEventResource, self).get_object_list(request)
        principals = [request.vosae_user] + request.vosae_user.groups
        calendars = VosaeCalendar.objects.filter(
            acl__read_list__in=principals, acl__negate_list__nin=principals)
        return object_list.filter(calendar__in=list(calendars))

    def apply_filters(self, request, applicable_filters):
        object_list = super(VosaeEventResource,
                            self).apply_filters(request, applicable_filters)
        filters = request.GET
        if 'single_events' in filters and filters['single_events'] in [
                'true', 'True', True
        ]:
            start = None
            end = None
            for filter_name, filter_value in filters.iteritems():
                try:
                    if filter_name.startswith('start'):
                        start = parse(filter_value)
                    elif filter_name.startswith('end'):
                        end = parse(filter_value)
                except:
                    pass
            return object_list.with_instances(start, end)
        return object_list

    def event_instances(self, request, **kwargs):
        """List all instances of the event"""
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        try:
            bundle = self.build_bundle(request=request)
            objects = self.obj_get_list(
                bundle,
                **self.remove_api_resource_names(kwargs)).with_instances()
        except ObjectDoesNotExist:
            return http.HttpNotFound()

        if objects.count() < 2:
            return http.HttpNotFound()

        sorted_objects = self.apply_sorting(objects, options=request.GET)

        first_objects_bundle = self.build_bundle(obj=objects[0],
                                                 request=request)
        instances_resource_uri = '%sinstances/' % self.get_resource_uri(
            first_objects_bundle)
        paginator = self._meta.paginator_class(
            request.GET,
            sorted_objects,
            resource_uri=instances_resource_uri,
            limit=self._meta.limit)
        to_be_serialized = paginator.page()

        # Dehydrate the bundles in preparation for serialization.
        bundles = [
            self.build_bundle(obj=obj, request=request)
            for obj in to_be_serialized['objects']
        ]
        to_be_serialized['objects'] = [self.full_dehydrate(b) for b in bundles]
        to_be_serialized = self.alter_list_data_to_serialize(
            request, to_be_serialized)
        return self.create_response(request, to_be_serialized)

    def full_hydrate(self, bundle):
        """Set event's creator and organizer"""
        bundle = super(VosaeEventResource, self).full_hydrate(bundle)
        bundle.obj.creator = bundle.request.vosae_user
        # Organizer should be the user owner of the calendar
        try:
            organizer = bundle.obj.calendar.acl.get_owner()
        except:
            organizer = bundle.request.vosae_user
        bundle.obj.organizer = organizer
        return bundle

    def full_dehydrate(self, bundle, for_list=False):
        bundle = super(VosaeEventResource,
                       self).full_dehydrate(bundle, for_list=for_list)
        if not bundle.data['instance_id']:
            del bundle.data['instance_id']
        return bundle

    def dehydrate(self, bundle):
        """Dehydrates the appropriate CalendarList which differs according to user (extracted from request)"""
        from organizer.models import CalendarList
        from organizer.api.resources import CalendarListResource
        bundle = super(VosaeEventResource, self).dehydrate(bundle)
        calendar_list = CalendarList.objects.get(
            calendar=bundle.obj.calendar, vosae_user=bundle.request.vosae_user)
        calendar_list_resource = CalendarListResource()
        calendar_list_resource_bundle = calendar_list_resource.build_bundle(
            obj=calendar_list, request=bundle.request)
        bundle.data['calendar_list'] = calendar_list_resource.get_resource_uri(
            calendar_list_resource_bundle)
        return bundle
Beispiel #14
0
class VosaeUserResource(WakeUpMixinResource, ZombieMixinResource,
                        TenantResource):
    full_name = base_fields.CharField(
        attribute='get_full_name',
        readonly=True,
        help_text=HELP_TEXT['vosae_user']['full_name'])
    email = base_fields.CharField(attribute='email',
                                  help_text=HELP_TEXT['vosae_user']['email'])
    status = base_fields.CharField(attribute='status',
                                   blank=True,
                                   help_text=HELP_TEXT['vosae_user']['status'])
    photo_uri = base_fields.CharField(
        attribute='photo_uri',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_user']['photo_uri'])
    specific_permissions = base_fields.DictField(
        attribute='specific_permissions',
        blank=True,
        help_text=HELP_TEXT['vosae_user']['specific_permissions'])
    permissions = base_fields.ListField(
        readonly=True, help_text=HELP_TEXT['vosae_user']['permissions'])

    groups = fields.ReferencedListField(
        of='core.api.resources.VosaeGroupResource',
        attribute='groups',
        null=True,
        blank=True,
        help_text=HELP_TEXT['vosae_user']['groups'])
    settings = fields.EmbeddedDocumentField(
        embedded='core.api.resources.VosaeUserSettingsResource',
        attribute='settings',
        help_text=HELP_TEXT['vosae_user']['settings'])

    class Meta(TenantResource.Meta):
        resource_name = 'user'
        queryset = VosaeUser.objects.all()
        list_allowed_methods = ('get', 'post')
        excludes = ('tenant', )
        filtering = {"email": ('exact', )}

    @classmethod
    def post_create(self, sender, resource, bundle, **kwargs):
        """
        Post create hook.

        Fills initial data (based on request's language) after VosaeUser creation
        """
        # Fill user initial data (Tenant and VosaeUser are required)
        fill_user_initial_data.delay(bundle.obj, bundle.request.LANGUAGE_CODE)

    def hydrate_email(self, bundle):
        """
        Email can only be used on POST (creation) in order to link the
        :class:`~core.models.VosaeUser` to the Django user.
        """
        if bundle.request.method.lower() != 'post':
            bundle.data.update(email=bundle.obj.email)
        return bundle

    def dehydrate_permissions(self, bundle):
        """Returns the list of acquired permissions"""
        return list(bundle.obj.permissions.acquired)
Beispiel #15
0
class QuotationResource(InvoiceBaseResource, InvoiceMakableResourceMixin):
    state = base_fields.CharField(attribute='state',
                                  readonly=True,
                                  help_text=HELP_TEXT['quotation']['state'])

    current_revision = fields.EmbeddedDocumentField(
        embedded='invoicing.api.resources.QuotationRevisionResource',
        attribute='current_revision',
        help_text=HELP_TEXT['quotation']['current_revision'])
    revisions = fields.EmbeddedListField(
        of='invoicing.api.resources.QuotationRevisionResource',
        attribute='revisions',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['quotation']['revisions'])

    class Meta(InvoiceBaseResource.Meta):
        queryset = Quotation.objects.all()
        detail_specific_methods = ('make_purchase_order',
                                   'make_down_payment_invoice', 'make_invoice',
                                   'mark_as_awaiting_approval')

    def prepend_urls(self):
        """Add urls for resources actions."""
        urls = super(QuotationResource, self).prepend_urls()
        urls.extend((
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/make_purchase_order%s$'
                % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('make_purchase_order'),
                name='api_quotation_make_purchase_order'),
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/make_down_payment_invoice%s$'
                % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('make_down_payment_invoice'),
                name='api_quotation_make_down_payment_invoice'),
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/make_invoice%s$' %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('make_invoice'),
                name='api_quotation_make_invoice'),
        ))
        return urls

    def make_purchase_order(self, request, **kwargs):
        """Create a purchase order from a quotation"""
        from invoicing.api.resources.purchase_order import PurchaseOrderResource
        self.method_check(request, allowed=['put'])
        self.is_authenticated(request)
        self.throttle_check(request)

        try:
            bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()

        purchase_order = obj.make_purchase_order(request.vosae_user)
        invoicing_signals.post_make_purchase_order.send(
            obj.__class__,
            issuer=request.vosae_user,
            document=obj,
            new_document=purchase_order)
        purchase_order_resource = PurchaseOrderResource()
        purchase_order_resource_bundle = purchase_order_resource.build_bundle(
            obj=purchase_order, request=request)

        self.log_throttled_access(request)

        to_be_serialized = {
            'purchase_order_uri':
            purchase_order_resource.get_resource_uri(
                purchase_order_resource_bundle)
        }
        to_be_serialized = self.alter_list_data_to_serialize(
            request, to_be_serialized)
        return self.create_response(request, to_be_serialized)
Beispiel #16
0
class BaseRevisionResource(VosaeResource):
    revision = base_fields.CharField(
        attribute='revision',
        readonly=True,
        help_text=HELP_TEXT['base_revision']['revision'])
    issue_date = base_fields.DateTimeField(
        attribute='issue_date',
        readonly=True,
        help_text=HELP_TEXT['base_revision']['issue_date'])
    sender = base_fields.CharField(
        attribute='sender',
        null=True,
        blank=True,
        help_text=HELP_TEXT['base_revision']['sender'])
    sender_organization = base_fields.CharField(
        attribute='sender_organization',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['base_revision']['sender_organization'])
    custom_payment_conditions = base_fields.CharField(
        attribute='custom_payment_conditions',
        null=True,
        blank=True,
        help_text=HELP_TEXT['base_revision']['custom_payment_conditions'])
    customer_reference = base_fields.CharField(
        attribute='customer_reference',
        null=True,
        blank=True,
        help_text=HELP_TEXT['base_revision']['customer_reference'])
    taxes_application = base_fields.CharField(
        attribute='taxes_application',
        help_text=HELP_TEXT['base_revision']['taxes_application'])

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

    class Meta(VosaeResource.Meta):
        object_class = InvoiceRevision

    def hydrate(self, bundle):
        """Set issue data and issuer on POST, extracted from request"""
        bundle = super(BaseRevisionResource, self).hydrate(bundle)
        bundle.obj.issuer = bundle.request.vosae_user
        bundle.obj.issue_date = datetime_now()
        return bundle
Beispiel #17
0
class IdeaResource(BaseCorsResource, resources.MongoEngineResource):

    protective_marking = mongo_fields.EmbeddedDocumentField(
        embedded='ideasapp.api.ProtectiveMarkingResource',
        attribute='protective_marking',
        help_text=
        'protective marking of this idea, comprising classification, descriptor, codewords and national caveats.',
        null=True)
    comments = mongo_fields.EmbeddedListField(
        of='ideasapp.api.CommentResource',
        attribute='comments',
        full=True,
        null=True)
    likes = mongo_fields.EmbeddedListField(
        of='ideasapp.api.LikeResource',
        attribute='likes',
        help_text='The user likes recorded for this idea',
        full=True,
        null=True)
    dislikes = mongo_fields.EmbeddedListField(
        of='ideasapp.api.DislikeResource',
        attribute='dislikes',
        help_text='The user dislikes recorded for this idea',
        full=True,
        null=True)

    class Meta:
        queryset = documents.Idea.objects.all()
        resource_name = 'idea'
        # What is permitted at the list level and at the single instance level
        list_allowed_methods = ['get', 'post', 'delete', 'put']
        detailed_allowed_methods = ['get', 'post', 'put', 'delete', 'patch']

        # Setup to default print pretty - mainly for debuggin
        serializer = CustomSerializer()

        authentication = CustomApiKeyAuthentication()
        authorization = StatusAuthorization()

        max_limit = None

        filtering = {
            'created': ['gt', 'gte', 'lt', 'lte'],
            'modified': ['gt', 'gte', 'lt', 'lte'],
            'like_count': ['gt', 'gte', 'lt', 'lte'],
            'dislike_count': ['gt', 'gte', 'lt', 'lte'],
            'comment_count': ['gt', 'gte', 'lt', 'lte'],
            'vote_score': ['gt', 'gte', 'lt', 'lte'],
            'tag_count': ['gt', 'gte', 'lt', 'lte'],
            'verified': ['exact'],
            'verified_by': ['exact'],
            'tags': ['exact', 'in', 'contains'],
            'status': ['exact', 'in'],
            'user': ['exact'],
            'public': ['exact']
        }

        ordering = [
            'title', 'created', 'modified', 'like_count', 'dislike_count',
            'comment_count', 'verified', 'status', 'vote_score'
        ]

    def serialize(self, request, data, format, options=None):
        """
        Override of resource.serialize so that custom options
        can be built for the rss serializer
        """

        # Is it an rss feed
        if 'application/rss+xml' in format:

            options = {}

            # Has the feed been filtered?
            params = request.GET.keys()
            params.pop(params.index('format'))
            if params and len(params) > 0:
                filtered = ' (filtered)'
            else:
                filtered = ''

            # Build a title based on the end point
            path = request.path.strip('/').split('/')
            # If it's not a detail view
            if len(path[-1]) != 24:

                # If there are tags, then make them available for the title
                tags = request.GET.get('tags', None)
                if not tags:
                    tags = request.GET.get('tags__in', None)
                if tags:
                    filtered = ' (Tags:%s)' % (tags)

                # Build the title
                api_end_point = path[-1].lower()
                options['title'] = settings.END_POINT_DESCRIPTIONS[
                    api_end_point] + filtered

                current_site = get_current_site(request)
                options['link'] = current_site.domain + settings.FRONT_END_URL
                options['description'] = settings.END_POINT_DESCRIPTIONS[
                    api_end_point]

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

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

    def obj_create(self, bundle, **kwargs):
        """ Modifies the content before submission """

        # Add in the user
        bundle.data['user'] = bundle.request.user.username
        # These ensure that counts are present if ideas are created with tags/likes/dislikes and comments
        bundle = count_builder(bundle, 'comments', 'comment_count')
        bundle = count_builder(bundle, 'likes', 'like_count')
        bundle = count_builder(bundle, 'dislikes', 'dislike_count')
        bundle = count_builder(bundle, 'tags', 'tag_count')

        # Sanitize tags before they get submitted
        try:
            bundle.data['tags'] = cleanup_tags(bundle.data['tags'])
        except:
            pass

        # Finally build the score
        bundle.data['vote_score'] = vote_score(bundle.data['like_count'],
                                               bundle.data['dislike_count'])

        return super(IdeaResource, self).obj_create(bundle)

    # No obj_update here because updates to lists of embedded docs don't trigger that function.
    # See individual embedded doc lists for update calls

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

    def obj_update(self, bundle, **kwargs):
        """ Updates content when resource is PUT or PATCHed """

        # These ensure that counts are present if ideas are created with tags/likes/dislikes and comments
        bundle = count_builder(bundle, 'tags', 'tag_count')

        return super(IdeaResource, self).obj_create(bundle)

    # No obj_update here because updates to lists of embedded docs don't trigger that function.
    # See individual embedded doc lists for update calls

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

    def alter_detail_data_to_serialize(self, request, data):
        """ Modify the content just before serializing data for a specific item """

        # Don't apply the meta object if it's anything but GET
        if request.method == 'GET':
            # Add a meta element for the single item response
            response_data = {'meta': {}, 'objects': [data]}

            # Add max PM into a newly created meta object
            pms = get_all_pms(response_data['objects'],
                              subdocs_to_check=['comments'],
                              pm_name='protective_marking')
            response_data['meta']['max_pm'] = get_max_pm(pms)

            # Get the modified time for this 1 object
            response_data['meta']['modified'] = data.data['modified']

            # Filter out the meta and objects content based on the data_level
            response_data = filter_by_data_level(request, response_data)

        else:
            response_data = data

        return response_data

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

    def alter_list_data_to_serialize(self, request, data):
        """ Modify content just before serialized to output """

        # Try to get the modified timestamp. Except catches instance where no data
        try:
            idea_mod = documents.Idea.objects.order_by(
                '-modified')[0]['modified']
        except:
            return data

        # Retrieve all comment modified timestamps (idea, comments)
        res = documents.Idea._get_collection().aggregate([{
            "$project": {
                "_id": 0,
                "comments": 1
            }
        }, {
            "$unwind":
            "$comments"
        }, {
            "$project": {
                "modified": "$comments.modified"
            }
        }, {
            "$sort": {
                "modified": -1
            }
        }, {
            "$limit": 1
        }])['result']

        # In the event that there are no comments, chuck in an old date to guarantee the idea mod date wins
        if res:
            comments_mod = res[0]['modified']
        else:
            comments_mod = datetime.datetime(1970, 1, 1)

        # Assign the meta-level modified datetime to the most recent comment/idea modified datetime
        data['meta']['modified'] = max([idea_mod, comments_mod])

        # Tag-based filtering
        if request.method == 'GET' and request.GET.get('tags__in'):
            data = tag_based_filtering(request, data)

        # Find the highest protective marking in the dataset
        pms = get_all_pms(data['objects'],
                          subdocs_to_check=['comments'],
                          pm_name='protective_marking')
        data['meta']['max_pm'] = get_max_pm(pms)

        # Filter out the meta and objects content based on the data_level
        if request.method == 'GET':
            data = filter_by_data_level(request, data)

        return data

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

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

        content_types = {
            'json': 'application/json',
            'jsonp': 'text/javascript',
            'xml': 'application/xml',
            'yaml': 'text/yaml',
            'html': 'text/html',
            'plist': 'application/x-plist',
            'csv': 'text/csv',
            'rss': 'application/rss+xml',
        }

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

    # ------------------------------------------------------------------------------------------------------------
    '''    
    def hydrate(self, bundle):
        """ Need to pass through user all the way through to dehydrate,
            so enabling that here"""
        print 'in hydrate', bundle.request.user
        bundle = super(IdeaResource, self).hydrate(bundle) 
        
        return bundle
    '''

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

    def hydrate_modified(self, bundle):
        """ Updates the idea-level modified timestamp field if the idea
            is edited. It doesn't handle updates to comments because they are
            an embedded resource"""

        if bundle.request.method != 'GET':
            bundle.data['modified'] = datetime.datetime.utcnow()
        return bundle

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

    def dehydrate(self, bundle):
        """ Dehydrate - data on its way back to requester """

        # User gets passed through because CustomAuth now passes it even for GET requests
        bundle.data['user_voted'] = get_user_vote_status(bundle)

        # Class will always have a time_stamp due to default.
        bundle.data['informal_created'] = calculate_informal_time(
            bundle.data['created'])
        bundle.data['informal_modified'] = calculate_informal_time(
            bundle.data['modified'])

        # Get the useful protective marking elements
        bundle = get_top_level_pm_elements(bundle)

        # Lookup the user's info
        bundle = get_contributors_info(bundle)

        # Produce a truncated (by word), html-tag cleaned version
        if bundle.data.has_key('description'):
            bundle.data['description_snippet'] = derive_snippet(
                bundle.data['description'])

        return bundle
Beispiel #18
0
class TenantResource(RemoveFilesOnReplaceMixinResource, TenantRequiredOnPutMixinResource, VosaeResource):
    TO_REMOVE_ON_REPLACE = ['svg_logo', 'img_logo', 'terms']

    slug = base_fields.CharField(
        attribute='slug',
        readonly=True,
        help_text=HELP_TEXT['tenant']['slug']
    )
    name = base_fields.CharField(
        attribute='name',
        help_text=HELP_TEXT['tenant']['name']
    )
    email = base_fields.CharField(
        attribute='email',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['email']
    )
    phone = base_fields.CharField(
        attribute='phone',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['phone']
    )
    fax = base_fields.CharField(
        attribute='fax',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['fax']
    )

    postal_address = fields.EmbeddedDocumentField(
        embedded='contacts.api.resources.AddressResource',
        attribute='postal_address',
        null=True,
        help_text=HELP_TEXT['tenant']['postal_address']
    )
    billing_address = fields.EmbeddedDocumentField(
        embedded='contacts.api.resources.AddressResource',
        attribute='billing_address',
        null=True,
        help_text=HELP_TEXT['tenant']['billing_address']
    )
    svg_logo = fields.ReferenceField(
        to='core.api.resources.VosaeFileResource',
        attribute='svg_logo',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['svg_logo']
    )
    img_logo = fields.ReferenceField(
        to='core.api.resources.VosaeFileResource',
        attribute='img_logo',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['img_logo']
    )
    terms = fields.ReferenceField(
        to='core.api.resources.VosaeFileResource',
        attribute='terms',
        null=True,
        blank=True,
        help_text=HELP_TEXT['tenant']['terms']
    )
    registration_info = RegistrationInfoField(
        embedded='core.api.resources.RegistrationInfoResource',
        attribute='registration_info',
        help_text=HELP_TEXT['tenant']['registration_info']
    )
    report_settings = fields.EmbeddedDocumentField(
        embedded='core.api.resources.ReportSettingsResource',
        attribute='report_settings',
        null=True,
        help_text=HELP_TEXT['tenant']['report_settings']
    )

    class Meta(VosaeResource.Meta):
        queryset = Tenant.objects.all()
        excludes = ('tenant_settings', 'logo_cache')
        authorization = TenantAuthorization()
        list_allowed_methods = ('get', 'post')
        detail_allowed_methods = ('get', 'put')

    def get_object_list(self, request):
        """Filters associated tenants"""
        object_list = super(TenantResource, self).get_object_list(request)
        accessible_tenants = [g[0] for g in request.user.groups.values_list('name')]
        return object_list.filter(slug__in=accessible_tenants)

    @classmethod
    def post_create(self, sender, resource, bundle, **kwargs):
        """
        Some mandatory actions shoud be synchrounous after Tenant creation but
        before returning the response and should not be in `post_save` hooks since
        issuer is required (got from request).

        These actions are:

        - Adding the creator to the Django group (represents the Tenant)
        - Creation of the VosaeUser linked to the tenant
        - Initial data filling
        """
        from core.models import VosaeUser, VosaeGroup
        
        # Update django group associated to the Tenant
        group = Group.objects.get(name=bundle.obj.slug)
        group.user_set.add(bundle.request.user)
        group.save()

        # VosaeUser creation
        user = VosaeUser(
            tenant=bundle.obj,
            email=bundle.request.user.email,
            groups=list(VosaeGroup.objects.filter(tenant=bundle.obj))
        ).save()

        # Fill tenant initial data (Tenant and VosaeUser are required)
        fill_tenant_initial_data.delay(bundle.obj, bundle.request.LANGUAGE_CODE)

        # Fill first user initial data (Tenant and VosaeUser are required)
        fill_user_initial_data.delay(user, bundle.request.LANGUAGE_CODE)

    def full_hydrate(self, bundle):
        """Handle specific fields (supported_currencies/default_currency) on creation"""
        if bundle.request.method.lower() != 'post':
            return super(TenantResource, self).full_hydrate(bundle)

        # Set specific fields for creation
        self.fields.update(
            supported_currencies=SupportedCurrenciesListField(
                of='invoicing.api.resources.CurrencyResource',
                attribute=None
            ),
            default_currency=fields.ReferenceField(
                to='invoicing.api.resources.CurrencyResource',
                attribute=None
            )
        )
        self.fields['supported_currencies'].contribute_to_class(self, 'supported_currencies')
        self.fields['default_currency'].contribute_to_class(self, 'default_currency')
        bundle = super(TenantResource, self).full_hydrate(bundle)
        self.fields.pop('supported_currencies', None)
        self.fields.pop('default_currency', None)
        bundle.data.pop('supported_currencies', None)
        bundle.data.pop('default_currency', None)
        return bundle

    def hydrate_supported_currencies(self, bundle):
        bundle.obj.tenant_settings.invoicing.supported_currencies = self.fields['supported_currencies'].hydrate(bundle)
        return bundle

    def hydrate_default_currency(self, bundle):
        value = self.fields['default_currency'].hydrate(bundle)
        bundle.obj.tenant_settings.invoicing.default_currency = value.obj
        return bundle
Beispiel #19
0
class SiteContentResource(BaseCorsResource, resources.MongoEngineResource):

    protective_marking = mongo_fields.EmbeddedDocumentField(embedded='contentapp.api.ProtectiveMarkingResource', attribute='protective_marking', help_text='protective marking of this content', null=True)

    class Meta:
        resource_name = 'site_content'
        queryset = documents.Content.objects.all()
        serializer = CustomSerializer()
        allowed_methods = ('get', 'post', 'put', 'delete')

        authentication = CustomApiKeyAuthentication()
        #authorization = PrivilegedUsersOnlyAuthorization()
        authorization = StaffSuperAuthorization()

        filtering = {'created'  : ['gt', 'gte', 'lt', 'lte'],
                     'modified' : ['gt', 'gte', 'lt', 'lte'],
                     'status'   : ['exact'],
                     'type'     : ['exact'],
                     'index'    : ['exact'],    # Is this page the index for this 'type' - e.g. index page for faq type?
                     'user'     : ['exact']}

        ordering = ['index', 'type', 'title', 'created',
                    'modified', 'status', 'user', 'summary', 'body']

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

    def determine_format(self, request):
        """ Override the default format, so that format=json is not required """
    
        content_types = {
                        'json': 'application/json',
                        'jsonp': 'text/javascript',
                        'xml': 'application/xml',
                        'yaml': 'text/yaml',
                        'html': 'text/html',
                        'plist': 'application/x-plist',
                        'csv': 'text/csv',
                        'rss': 'application/rss+xml',
                    }
    
        format = request.GET.get('format', None)
        if format == None:
            return 'application/json'    
        else:
            return content_types[format]

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

    def obj_create(self, bundle, **kwargs):
        """ Add in the user information to the comment. """
        
        # Add the user to the data payload
        bundle.data['user'] = bundle.request.user.username
        return super(SiteContentResource, self).obj_create(bundle)

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

    def obj_update(self, bundle, **kwargs):
        """ Apply the authorization limits when put/patch-ing"""
        
        # We must get the primary key because the mongoengine obj_update function is
        # expecting one to access the object we want to modify.
        regExp = re.compile('.*/(?P<doc_id>[a-zA-Z0-9]{24})/')
        m = re.match(regExp, bundle.request.path).groupdict()
        if not getattr(bundle.obj, 'pk', None):
            bundle.obj.pk = m['doc_id']
        
        return super(SiteContentResource, self).obj_update(bundle)

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

    def hydrate_modified(self, bundle):
        """ Updates the top-level modified timestamp field if the idea
            is edited. It doesn't handle updates to comments because they are
            an embedded resource"""
        
        if bundle.request.method != 'GET':
            bundle.data['modified'] = datetime.datetime.utcnow()
        return bundle
    
    # ------------------------------------------------------------------------------------------------------------        

    def dehydrate(self, bundle):
        """ Dehydrate - data on its way back to requester """
        
        # Class will always have a time_stamp due to default.
        bundle.data['informal_created'] = calculate_informal_time(bundle.data['created'])
        bundle.data['informal_modified'] = calculate_informal_time(bundle.data['modified'])
        
        # Get the useful protective marking elements
        bundle = get_top_level_pm_elements(bundle)
               
        # Lookup the user's info
        bundle = get_contributors_info(bundle)
        
        return bundle

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

    def alter_detail_data_to_serialize(self, request, data):
        """ Modify the content just before serializing data for a specific item """
        
        # Don't apply the meta object if it's anything but GET
        if request.method == 'GET':
            # Add a meta element for the single item response
            response_data = {'meta':{},'objects':[data]}
    
            # Add max PM into a newly created meta object
            pms = get_all_pms(response_data['objects'], subdocs_to_check=[], pm_name='protective_marking')
            response_data['meta']['max_pm'] = get_max_pm(pms)    
    
            # Get the modified time for this 1 object
            response_data['meta']['modified'] = data.data['modified'] 

        else:
            response_data = data

        return response_data

# ------------------------------------------------------------------------------------------------------------        
    
    def alter_list_data_to_serialize(self, request, data):
        """ Modify content just before serialized to output """             

        # Try to get the modified timestamp. Except catches instance where no data
        try:
            idea_mod = documents.Content.objects.order_by('-modified')[0]['modified']
            data['meta']['modified'] = idea_mod
        except:
            return data
            
        # Find the highest protective marking in the dataset
        if request.method == 'GET':
            pms = get_all_pms(data['objects'], pm_name='protective_marking')
            data['meta']['max_pm'] = get_max_pm(pms)    
        
        return data
Beispiel #20
0
class CommentResource(BaseCorsResource, resources.MongoEngineResource):

    protective_marking = mongo_fields.EmbeddedDocumentField(
        embedded='ideasapp.api.ProtectiveMarkingResource',
        attribute='protective_marking',
        help_text='protective marking of this comment',
        null=True)

    class Meta:
        resource_name = 'comment'
        #queryset = documents.Comment.objects.all()
        object_class = documents.Comment
        serializer = CustomSerializer()
        allowed_methods = ('get', 'post', 'put', 'patch', 'delete')

        authentication = CustomApiKeyAuthentication()
        authorization = Authorization()

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

    def hydrate_modified(self, bundle):
        """ Updates the comment modified timestamp field if the comment
            is edited."""

        # Also change the parent if there is one for this call
        regExp = re.compile('.*/(?P<doc_id>[a-zA-Z0-9]{24})/.*')
        m = re.match(regExp, bundle.request.path).groupdict()
        if m:
            documents.Idea.objects.get(id=m['doc_id']).update(
                **{'set__modified': datetime.datetime.utcnow()})

        # Change the modified date for all calls
        if bundle.request.method != 'GET':
            bundle.data['modified'] = datetime.datetime.utcnow()

        return bundle

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

    def post_list(self, request, **kwargs):
        """ Upon creation of a new idea comment, change the total count too"""

        # Get the document
        regExp = re.compile('.*/(?P<doc_id>[a-zA-Z0-9]{24})/comments/')
        m = re.match(regExp, request.path).groupdict()
        if m:
            doc_id = m['doc_id']
        else:
            return super(CommentResource, self).post_list(request)

        doc = documents.Idea.objects.get(id=doc_id)

        if doc.status == 'published':
            #Assumes we already have a user otherwise they wouldn't have authenticated
            documents.Idea.objects(id=doc_id).update(
                **{'inc__comment_count': 1})
            return super(CommentResource, self).post_list(request)
        else:
            bundle = {
                "error":
                "User can only comment on ideas with status=published."
            }
            return self.create_response(request,
                                        bundle,
                                        response_class=http.HttpBadRequest)

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

    def obj_create(self, bundle, **kwargs):
        """ Add in the user information to the comment. """

        # Add the user to the data payload
        bundle.data['user'] = bundle.request.user.username

        return super(CommentResource, self).obj_create(bundle)

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

    def obj_delete(self, bundle, **kwargs):
        """ Determines how existing objects get deleted via the API  """

        # Get the document ID
        regExp = re.compile(
            '.*/(?P<doc_id>[a-zA-Z0-9]{24})/comments/(?P<comment_id>\d+)/')
        m = re.match(regExp, bundle.request.path).groupdict()

        # Decrement the comment count of the host document
        documents.Idea.objects.get(id=m['doc_id']).update(
            **{'inc__comment_count': -1})

        return super(CommentResource,
                     self).obj_delete(bundle, **{'pk': m['comment_id']})

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

    def alter_detail_data_to_serialize(self, request, data):
        """ Modify the content just before serializing data for a specific item """

        # Don't apply the meta object if it's anything but GET
        if request.method == 'GET':

            # Add a meta element for the single item response
            response_data = {'meta': {}, 'objects': [data]}

            # Add max PM into a newly created meta object
            pms = get_all_pms(response_data['objects'],
                              subdocs_to_check=[],
                              pm_name='protective_marking')
            response_data['meta']['max_pm'] = get_max_pm(pms)

            # Get the modified time for this 1 object
            response_data['meta']['modified'] = data.data['modified']

            # Filter out the meta and objects content based on the data_level
            response_data = filter_by_data_level(request, response_data)

        else:
            response_data = data

        return response_data
# ------------------------------------------------------------------------------------------------------------

    def alter_list_data_to_serialize(self, request, data):
        """ Modify content just before serialized to output """

        # Tag-based filtering
        if request.method == 'GET' and request.GET.get('tags__in'):
            data = tag_based_filtering(request, data)

        # Assign the meta-level modified datetime to the most recent comment/idea modified datetime
        object_modified_dts = [obj.data['modified'] for obj in data['objects']]
        if len(object_modified_dts) > 0:
            data['meta']['modified'] = max(object_modified_dts)

        # Find the highest protective marking in the dataset
        pms = get_all_pms(data['objects'],
                          subdocs_to_check=[],
                          pm_name='protective_marking')
        data['meta']['max_pm'] = get_max_pm(pms)

        # Filter out the meta and objects content based on the data_level
        if request.method == 'GET':
            data = filter_by_data_level(request, data)

        return data

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

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

        content_types = {
            'json': 'application/json',
            'jsonp': 'text/javascript',
            'xml': 'application/xml',
            'yaml': 'text/yaml',
            'html': 'text/html',
            'plist': 'application/x-plist',
            'csv': 'text/csv',
        }

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

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

    def dehydrate(self, bundle):
        """ Dehydrate to calc stuff on its way out """

        # Class will always have a created/modified due to default.
        bundle.data['informal_created'] = calculate_informal_time(
            bundle.data['created'])
        bundle.data['informal_modified'] = calculate_informal_time(
            bundle.data['modified'])

        if bundle.data.has_key('body'):
            bundle.data['body_snippet'] = derive_snippet(bundle.data['body'])

        # Lookup the user's info
        bundle = get_contributors_info(bundle)

        return bundle
Beispiel #21
0
class InvoiceResource(InvoiceBaseResource):
    state = base_fields.CharField(attribute='state',
                                  readonly=True,
                                  help_text=HELP_TEXT['invoice']['state'])
    paid = base_fields.DecimalField(attribute='paid',
                                    readonly=True,
                                    help_text=HELP_TEXT['invoice']['paid'])
    balance = base_fields.DecimalField(
        attribute='balance',
        readonly=True,
        help_text=HELP_TEXT['invoice']['balance'])
    has_temporary_reference = base_fields.BooleanField(
        attribute='has_temporary_reference',
        readonly=True,
        help_text=HELP_TEXT['invoice']['has_temporary_reference'])

    current_revision = fields.EmbeddedDocumentField(
        embedded='invoicing.api.resources.InvoiceRevisionResource',
        attribute='current_revision',
        help_text=HELP_TEXT['invoice']['current_revision'])
    revisions = fields.EmbeddedListField(
        of='invoicing.api.resources.InvoiceRevisionResource',
        attribute='revisions',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice']['revisions'])
    related_to = fields.ReferenceField(
        to='invoicing.api.resources.QuotationResource',
        attribute='related_to',
        readonly=True,
        null=True,
        help_text=HELP_TEXT['invoice']['related_to'])
    payments = fields.ReferencedListField(
        of='invoicing.api.resources.PaymentResource',
        attribute='payments',
        readonly=True,
        null=True,
        blank=True,
        help_text=HELP_TEXT['invoice']['payments'])

    class Meta(InvoiceBaseResource.Meta):
        queryset = Invoice.objects.all()
        detail_specific_methods = ('cancel', 'mark_as_registered')

    def prepend_urls(self):
        """Add urls for resources actions."""
        urls = super(InvoiceResource, self).prepend_urls()
        urls.extend(
            (url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/cancel%s$' %
                 (self._meta.resource_name, trailing_slash()),
                 self.wrap_view('invoice_cancel'),
                 name='api_invoice_cancel'), ))
        return urls

    def invoice_cancel(self, request, **kwargs):
        """Cancel the invoice and returns the associated credit note."""
        from invoicing.api.resources.credit_note import CreditNoteResource
        self.method_check(request, allowed=['put'])
        self.is_authenticated(request)
        self.throttle_check(request)

        try:
            bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()

        try:
            credit_note = obj.cancel(request.vosae_user)
            invoicing_signals.post_cancel_invoice.send(
                obj.__class__,
                issuer=request.vosae_user,
                document=obj,
                credit_note=credit_note)
            credit_note_resource = CreditNoteResource()
            credit_note_resource_bundle = credit_note_resource.build_bundle(
                obj=credit_note, request=request)
        except NotCancelableInvoice as e:
            raise BadRequest(e)

        self.log_throttled_access(request)

        to_be_serialized = {
            'credit_note_uri':
            credit_note_resource.get_resource_uri(credit_note_resource_bundle)
        }
        to_be_serialized = self.alter_list_data_to_serialize(
            request, to_be_serialized)
        return self.create_response(request, to_be_serialized)

    def dehydrate_related_to(self, bundle):
        from invoicing.api.resources import QuotationResource, PurchaseOrderResource
        try:
            if bundle.obj.related_to.is_quotation():
                resource = QuotationResource()
            elif bundle.obj.related_to.is_purchase_order():
                resource = PurchaseOrderResource()
            resource_bundle = resource.build_bundle(obj=bundle.obj.related_to,
                                                    request=bundle.request)
            return resource.get_resource_uri(resource_bundle)
        except:
            return
Beispiel #22
0
class FeedbackResource(BaseCorsResource, resources.MongoEngineResource):
    
    protective_marking = mongo_fields.EmbeddedDocumentField(embedded='contentapp.api.ProtectiveMarkingResource', attribute='protective_marking', help_text='protective marking of this content', null=True)
    comments           = mongo_fields.EmbeddedListField(of='contentapp.api.FeedbackCommentResource', attribute='comments', full=True, null=True)
    
    class Meta:
        resource_name = 'feedback'
        queryset = documents.Feedback.objects.all()
        serializer = CustomSerializer()
        allowed_methods = ('get', 'post', 'put', 'delete')
        
        authentication = CustomApiKeyAuthentication()
        authorization = PrivilegedAndSubmitterOnly()
        
        filtering = {'created'  : ['gt', 'gte', 'lt', 'lte'],
                     'modified' : ['gt', 'gte', 'lt', 'lte'],
                     'status'   : ['exact'],
                     'type'     : ['exact'],
                     'user'     : ['exact']}

        ordering = ['title', 'created', 'modified', 'status', 'user', 'summary', 'body']

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

    def determine_format(self, request):
        """ Override the default format, so that format=json is not required """
    
        content_types = {
                        'json': 'application/json',
                        'jsonp': 'text/javascript',
                        'xml': 'application/xml',
                        'yaml': 'text/yaml',
                        'html': 'text/html',
                        'plist': 'application/x-plist',
                        'csv': 'text/csv',
                        'rss': 'application/rss+xml',
                    }
    
        format = request.GET.get('format', None)
        if format == None:
            return 'application/json'    
        else:
            return content_types[format]

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

    def obj_create(self, bundle, **kwargs):
        """ How to create a feedback object  """
        
        # Add the user to the data payload
        bundle.data['user'] = bundle.request.user.username
        bundle = count_builder(bundle, 'comments',  'comment_count')
        
        return super(FeedbackResource, self).obj_create(bundle)
    
    # ------------------------------------------------------------------------------------------------------------        

    def obj_update(self, bundle, **kwargs):
        """ Apply the authorization limits when putting"""
        
        # We must get the primary key because the mongoengine obj_update function is
        # expecting one to access the object we want to modify.
        regExp = re.compile('.*/(?P<doc_id>[a-zA-Z0-9]{24})/')
        m = re.match(regExp, bundle.request.path).groupdict()
        if not getattr(bundle.obj, 'pk', None):
            bundle.obj.pk = m['doc_id']
        
        return super(FeedbackResource, self).obj_update(bundle)
    
    # ------------------------------------------------------------------------------------------------------------        

    def hydrate_modified(self, bundle):
        """ Updates the idea-level modified timestamp field if the idea
            is edited. It doesn't handle updates to comments because they are
            an embedded resource"""
        
        if bundle.request.method != 'GET':
            bundle.data['modified'] = datetime.datetime.utcnow()
        return bundle
    
    # ------------------------------------------------------------------------------------------------------------        

    def dehydrate(self, bundle):
        """ Dehydrate - data on its way back to requester """
        
        # Class will always have a time_stamp due to default.
        bundle.data['informal_created'] = calculate_informal_time(bundle.data['created'])
        bundle.data['informal_modified'] = calculate_informal_time(bundle.data['modified'])
        
        # Get the useful protective marking elements
        bundle = get_top_level_pm_elements(bundle)
               
        # Lookup the user's info
        bundle = get_contributors_info(bundle)
        
        return bundle

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

    def alter_detail_data_to_serialize(self, request, data):
        """ Modify the content just before serializing data for a specific item """
        
        # Don't apply the meta object if it's anything but GET
        if request.method == 'GET':
            # Add a meta element for the single item response
            response_data = {'meta':{},'objects':[data]}
    
            # Add max PM into a newly created meta object
            pms = get_all_pms(response_data['objects'], subdocs_to_check=['comments'], pm_name='protective_marking')
            response_data['meta']['max_pm'] = get_max_pm(pms)    
    
            # Get the modified time for this 1 object
            response_data['meta']['modified'] = data.data['modified'] 

        else:
            response_data = data

        return response_data

# ------------------------------------------------------------------------------------------------------------        
    
    def alter_list_data_to_serialize(self, request, data):
        """ Modify content just before serialized to output """             

        # Try to get the modified timestamp. Except catches instance where no data
        try:
            idea_mod = documents.Feedback.objects.order_by('-modified')[0]['modified']
            data['meta']['modified'] = idea_mod
        except:
            return data
            
        # Find the highest protective marking in the dataset
        if request.method == 'GET':
            pms = get_all_pms(data['objects'], subdocs_to_check=['comments'], pm_name='protective_marking')
            data['meta']['max_pm'] = get_max_pm(pms)    
        
        return data
    
    #-----------------------------------------------------------------------------
    
    def serialize(self, request, data, format, options=None):
        """
        Override of resource.serialize so that custom options
        can be built for the rss serializer
        """
        
        # Is it an rss feed
        if 'application/rss+xml' in format:
            
            options = {}
            
            # Has the feed been filtered?
            params = request.GET.keys()
            params.pop(params.index('format'))
            if params and len(params) > 0:
                filtered = ' (filtered)'
            else:
                filtered = ''
            
            # Build a title based on the end point
            path = request.path.strip('/').split('/')
            # If it's not a detail view
            if len(path[-1]) != 24:

                # If there are tags, then make them available for the title
                tags = request.GET.get('tags', None)
                if not tags:
                    tags = request.GET.get('tags__in', None)
                if tags:
                    filtered = ' (Tags:%s)'%(tags)

                # Build the title                
                api_end_point = path[-1].lower()
                options['title'] = settings.END_POINT_DESCRIPTIONS[api_end_point]
                
                current_site = get_current_site(request)
                options['link'] = current_site.domain + settings.FRONT_END_URL
                options['description'] = settings.END_POINT_DESCRIPTIONS[api_end_point]
            
        return super(FeedbackResource, self).serialize(request, data, format, options)