Beispiel #1
0
    def log_model(self):
        start_ts = self.request.GET.get("start_ts") or ""
        try:
            f = DateTimeField()
            distr = f.to_internal_value(start_ts).strftime("%Y%m%d")
        except Exception:
            distr = None

        return create_index_model(self.index, distr=distr)
Beispiel #2
0
class BlogDetailPage(Page):
    """Define our general Blog Post model"""
    # SETTINGS
    parent_page_types = ['blog.BlogListingPage']
    # FIELDS
    post_title = models.CharField(max_length=100, null=True, blank=False)
    post_image = models.ForeignKey(
        "wagtailimages.Image",
        blank=True,
        null=True,
        related_name="+",
        on_delete=models.SET_NULL,
    )
    post_summary = RichTextField(
        blank=False,
        null=True,
        help_text="A helpful short summary of what this post is about.",
    )
    categories = ParentalManyToManyField("blog.BlogCategory", blank=True)

    content = StreamField([
        ('title_and_text', TitleAndTextBlock()),
        ('richtext', RichtextBlock()),
        ('cards', CardBlock())
    ], null=True, blank=True)

    # DEFINE FIELDS TO SEARCH
    search_fields = Page.search_fields + [
        index.SearchField("post_title"),
        index.SearchField("post_summary"),
        index.SearchField("categories"),
        index.SearchField("content"),
    ]
    # ADMIN INTERFACE
    content_panels = Page.content_panels + [
        FieldPanel("post_title"),
        RichTextFieldPanel("post_summary"),
        ImageChooserPanel("post_image"),
        StreamFieldPanel("content"),
        MultiFieldPanel([
            InlinePanel('blog_authors', label='Author', min_num=1)
        ], heading='Blog Authors'),
        MultiFieldPanel([
            FieldPanel("categories", widget=forms.CheckboxSelectMultiple)
        ], heading='Categories'),
    ]
    # API FIELDS
    api_fields = [
        APIField("post_title"),
        APIField("post_image"),
        APIField("post_summary"),
        APIField("content"),
        APIField("categories"),
        APIField('first_published_at',
                 serializer=DateTimeField(format='%A, %h %d, %Y %I:%M %P'))
    ]

    class Meta:
        verbose_name = "Blog Detail"
        verbose_name_plural = "Blog Details"

    def save(self, *args, **kwargs):
        """Clear cache for specific objects when saved."""
        # TODO ([email protected]): Add cache clearing when caching is implemented
        return super().save(*args, **kwargs)
Beispiel #3
0
def api_time_format(dt):
    """Convert a datetime to string according to the API settings"""
    from rest_framework.fields import DateTimeField

    field = DateTimeField()
    return field.to_representation(dt)
Beispiel #4
0
class DateTimeRangeField(RangeField):
    child = DateTimeField()
    range_type = DateTimeTZRange
Beispiel #5
0
class ConceptVersionDetailSerializer(ModelSerializer):
    type = CharField(source='resource_type')
    uuid = CharField(source='id')
    id = EncodedDecodedCharField(source='mnemonic')
    names = LocalizedNameSerializer(many=True)
    descriptions = LocalizedDescriptionSerializer(many=True, required=False, allow_null=True)
    source = CharField(source='parent_resource')
    source_url = URLField(source='parent_url')
    owner = CharField(source='owner_name')
    created_on = DateTimeField(source='created_at', read_only=True)
    updated_on = DateTimeField(source='updated_at', read_only=True)
    version_created_on = DateTimeField(source='created_at')
    version_created_by = CharField(source='created_by')
    locale = CharField(source='iso_639_1_locale')
    mappings = SerializerMethodField()
    url = CharField(source='versioned_object_url', read_only=True)
    previous_version_url = CharField(source='prev_version_uri', read_only=True)
    update_comment = CharField(source='comment', required=False, allow_null=True, allow_blank=True)
    parent_concepts = SerializerMethodField()
    child_concepts = SerializerMethodField()
    parent_concept_urls = ListField(read_only=True)
    child_concept_urls = ListField(read_only=True)
    source_versions = ListField(read_only=True)
    collection_versions = ListField(read_only=True)

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')

        self.include_indirect_mappings = False
        self.include_direct_mappings = False
        self.query_params = params.dict() if params else dict()
        self.include_indirect_mappings = self.query_params.get(INCLUDE_INVERSE_MAPPINGS_PARAM) == 'true'
        self.include_direct_mappings = self.query_params.get(INCLUDE_MAPPINGS_PARAM) == 'true'
        self.include_parent_concepts = self.query_params.get(INCLUDE_PARENT_CONCEPTS) in ['true', True]
        self.include_child_concepts = self.query_params.get(INCLUDE_CHILD_CONCEPTS) in ['true', True]

        try:
            if not self.include_parent_concepts:
                self.fields.pop('parent_concepts', None)
            if not self.include_child_concepts:
                self.fields.pop('child_concepts', None)
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    class Meta:
        model = Concept
        fields = (
            'type', 'uuid', 'id', 'external_id', 'concept_class', 'datatype', 'display_name', 'display_locale',
            'names', 'descriptions', 'extras', 'retired', 'source', 'source_url', 'owner', 'owner_name', 'owner_url',
            'version', 'created_on', 'updated_on', 'version_created_on', 'version_created_by', 'update_comment',
            'is_latest_version', 'locale', 'url', 'owner_type', 'version_url', 'mappings', 'previous_version_url',
            'internal_reference_id', 'parent_concepts', 'child_concepts', 'parent_concept_urls', 'child_concept_urls',
            'source_versions', 'collection_versions'
        )

    def get_mappings(self, obj):
        from core.mappings.serializers import MappingDetailSerializer
        context = get(self, 'context')
        if self.include_direct_mappings:
            return MappingDetailSerializer(obj.get_unidirectional_mappings(), many=True, context=context).data
        if self.include_indirect_mappings:
            return MappingDetailSerializer(obj.get_bidirectional_mappings(), many=True, context=context).data

        return []

    def get_child_concepts(self, obj):
        if self.include_child_concepts:
            return ConceptDetailSerializer(obj.child_concepts.all(), many=True).data
        return None

    def get_parent_concepts(self, obj):
        if self.include_parent_concepts:
            return ConceptDetailSerializer(obj.parent_concepts.all(), many=True).data
        return None
Beispiel #6
0
class TransactionSerializer(Serializer):
    inputs = TransactionInputSerializer(many=True)
    outputs = TransactionOutputSerializer(many=True)
    timestamp = DateTimeField()
Beispiel #7
0
class PostPage(Page):
    body = MarkdownField()
    date = models.DateTimeField(verbose_name="Post date",
                                default=datetime.datetime.today)
    excerpt = MarkdownField(
        verbose_name='excerpt',
        blank=True,
    )

    header_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
    tags = ClusterTaggableManager(through='blog.BlogPageTag', blank=True)

    content_panels = Page.content_panels + [
        ImageChooserPanel('header_image'),
        MarkdownPanel("body"),
        MarkdownPanel("excerpt"),
        FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
        FieldPanel('tags'),
    ]

    settings_panels = Page.settings_panels + [
        FieldPanel('date'),
    ]

    api_fields = (
        'header_image',
        APIField('header_image_url',
                 serializer=ImageRenditionField('original',
                                                source='header_image')),
        APIField('owner'),
        APIField('api_categories',
                 serializer=CategoryField(source='categories')),
        APIField('api_tags', serializer=TagField(source='tags')),
        APIField('pub_date',
                 serializer=DateTimeField(format='%d %B %Y', source='date')),
        APIField(
            'md_excerpt',
            serializer=MarkdownAPIField(source='excerpt'),
        ),
        APIField(
            'md_body',
            serializer=MarkdownAPIField(source='body'),
        ),
    )

    @property
    def blog_page(self):
        return self.get_parent().specific

    def get_context(self, request, *args, **kwargs):
        context = super(PostPage, self).get_context(request, *args, **kwargs)
        context['blog_page'] = self.blog_page
        context['post'] = self
        return context
Beispiel #8
0
class SourceDetailSerializer(SourceCreateOrUpdateSerializer):
    type = CharField(source='resource_type')
    uuid = CharField(source='id')
    id = CharField(source='mnemonic')
    short_code = CharField(source='mnemonic')
    owner = CharField(source='parent_resource')
    owner_type = CharField(source='parent_resource_type')
    owner_url = CharField(source='parent_url')
    created_on = DateTimeField(source='created_at')
    updated_on = DateTimeField(source='updated_at')
    supported_locales = ListField(required=False, allow_empty=True)
    created_by = CharField(source='created_by.username', read_only=True)
    updated_by = DateTimeField(source='updated_by.username', read_only=True)
    summary = SerializerMethodField()
    client_configs = SerializerMethodField()
    hierarchy_root = SerializerMethodField()
    hierarchy_root_url = CharField(source='hierarchy_root.url',
                                   required=False,
                                   allow_blank=True,
                                   allow_null=True)

    class Meta:
        model = Source
        lookup_field = 'mnemonic'
        fields = ('type', 'uuid', 'id', 'short_code', 'name', 'full_name',
                  'description', 'source_type', 'custom_validation_schema',
                  'public_access', 'default_locale', 'supported_locales',
                  'website', 'url', 'owner', 'owner_type', 'owner_url',
                  'created_on', 'updated_on', 'created_by', 'updated_by',
                  'extras', 'external_id', 'versions_url', 'version',
                  'concepts_url', 'mappings_url', 'canonical_url',
                  'identifier', 'publisher', 'contact', 'jurisdiction',
                  'purpose', 'copyright', 'content_type', 'revision_date',
                  'logo_url', 'summary', 'text', 'client_configs',
                  'experimental', 'case_sensitive', 'collection_reference',
                  'hierarchy_meaning', 'compositional', 'version_needed',
                  'internal_reference_id', 'hierarchy_root_url',
                  'hierarchy_root', 'meta')

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')
        self.query_params = params.dict() if params else dict()
        self.include_summary = self.query_params.get(INCLUDE_SUMMARY) in [
            'true', True
        ]
        self.include_client_configs = self.query_params.get(
            INCLUDE_CLIENT_CONFIGS) in ['true', True]
        self.include_hierarchy_root = self.query_params.get(
            INCLUDE_HIERARCHY_ROOT) in ['true', True]

        try:
            if not self.include_summary:
                self.fields.pop('summary', None)
            if not self.include_client_configs:
                self.fields.pop('client_configs')
            if not self.include_hierarchy_root:
                self.fields.pop('hierarchy_root')
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    def get_summary(self, obj):
        summary = None

        if self.include_summary:
            summary = SourceSummarySerializer(obj).data

        return summary

    def get_client_configs(self, obj):
        if self.include_client_configs:
            return ClientConfigSerializer(
                obj.client_configs.filter(is_active=True), many=True).data

        return None

    def get_hierarchy_root(self, obj):
        if self.include_hierarchy_root:
            from core.concepts.serializers import ConceptDetailSerializer
            return ConceptDetailSerializer(obj.hierarchy_root).data
        return None
Beispiel #9
0
 def datetime_to_representation(cls, value: datetime.datetime) -> str:
     return DateTimeField().to_representation(value)
Beispiel #10
0
    def test_assertions_pagination(self):
        self.user = self.setup_user(authenticate=True)

        test_issuer_user = self.setup_user(authenticate=False)
        test_issuer = self.setup_issuer(owner=test_issuer_user)
        assertions = []

        with mock.patch('mainsite.blacklist.api_query_is_in_blacklist',
                        new=lambda a, b: False):
            for _ in range(25):
                test_badgeclass = self.setup_badgeclass(issuer=test_issuer)
                assertions.append(
                    test_badgeclass.issue(self.user.email, notify=False))
        response = self.client.get('/bcv1/assertions?limit=10&offset=0')
        self.assertEqual(len(response.data['results']), 10)
        self.assertTrue(response.has_header('Link'))
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=10>; rel="next"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=20>; rel="last"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0>; rel="first"'
            in response['Link'])
        for x in range(0, 10):
            self.assertEqual(response.data['results'][x]['id'],
                             assertions[24 - x].jsonld_id)

        response = self.client.get('/bcv1/assertions?limit=10&offset=10')
        self.assertEqual(len(response.data['results']), 10)
        self.assertTrue(response.has_header('Link'))
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=20>; rel="next"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=20>; rel="last"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0>; rel="first"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0>; rel="prev"'
            in response['Link'])
        for x in range(0, 10):
            self.assertEqual(response.data['results'][x]['id'],
                             assertions[24 - (x + 10)].jsonld_id)

        response = self.client.get('/bcv1/assertions?limit=10&offset=20')
        self.assertEqual(len(response.data['results']), 5)
        self.assertTrue(response.has_header('Link'))
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=20>; rel="last"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0>; rel="first"'
            in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=10>; rel="prev"'
            in response['Link'])
        for x in range(0, 5):
            self.assertEqual(response.data['results'][x]['id'],
                             assertions[24 - (x + 20)].jsonld_id)

        since = parse.quote(DateTimeField().to_representation(
            assertions[5].created_at))
        response = self.client.get(
            '/bcv1/assertions?limit=10&offset=0&since=' + since)
        self.assertEqual(len(response.data['results']), 10)
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=10&since=%s>; rel="next"'
            % since in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=10&since=%s>; rel="last"'
            % since in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0&since=%s>; rel="first"'
            % since in response['Link'])
        for x in range(0, 10):
            self.assertEqual(response.data['results'][x]['id'],
                             assertions[24 - x].jsonld_id)

        response = self.client.get(
            '/bcv1/assertions?limit=10&offset=10&since=' + since)
        self.assertEqual(len(response.data['results']), 10)
        self.assertTrue(response.has_header('Link'))
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=10&since=%s>; rel="last"'
            % since in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0&since=%s>; rel="first"'
            % since in response['Link'])
        self.assertTrue(
            '<http://testserver/bcv1/assertions?limit=10&offset=0&since=%s>; rel="prev"'
            % since in response['Link'])
        for x in range(0, 10):
            self.assertEqual(response.data['results'][x]['id'],
                             assertions[24 - (x + 10)].jsonld_id)
Beispiel #11
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        type = self.request.data.get('type', None) or Checkin.TYPE_ENTRY
        if type not in dict(Checkin.CHECKIN_TYPES):
            raise ValidationError("Invalid check-in type.")
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(
                self.request.data.get('datetime'))
        else:
            dt = now()

        common_checkin_args = dict(
            raw_barcode=self.kwargs['pk'],
            type=type,
            list=self.checkinlist,
            datetime=dt,
            device=self.request.auth
            if isinstance(self.request.auth, Device) else None,
            gate=self.request.auth.gate
            if isinstance(self.request.auth, Device) else None,
            nonce=nonce,
            forced=force,
        )

        try:
            queryset = self.get_queryset(ignore_status=True,
                                         ignore_products=True)
            if self.kwargs['pk'].isnumeric():
                op = queryset.get(
                    Q(pk=self.kwargs['pk']) | Q(secret=self.kwargs['pk']))
            else:
                op = queryset.get(secret=self.kwargs['pk'])
        except OrderPosition.DoesNotExist:
            revoked_matches = list(
                self.request.event.revoked_secrets.filter(
                    secret=self.kwargs['pk']))
            if len(revoked_matches) == 0:
                self.request.event.log_action('pretix.event.checkin.unknown',
                                              data={
                                                  'datetime': dt,
                                                  'type': type,
                                                  'list': self.checkinlist.pk,
                                                  'barcode': self.kwargs['pk']
                                              },
                                              user=self.request.user,
                                              auth=self.request.auth)

                for k, s in self.request.event.ticket_secret_generators.items(
                ):
                    try:
                        parsed = s.parse_secret(self.kwargs['pk'])
                        common_checkin_args.update({
                            'raw_item':
                            parsed.item,
                            'raw_variation':
                            parsed.variation,
                            'raw_subevent':
                            parsed.subevent,
                        })
                    except:
                        pass

                Checkin.objects.create(
                    position=None,
                    successful=False,
                    error_reason=Checkin.REASON_INVALID,
                    **common_checkin_args,
                )
                raise Http404()
            else:
                op = revoked_matches[0].position
                op.order.log_action('pretix.event.checkin.revoked',
                                    data={
                                        'datetime': dt,
                                        'type': type,
                                        'list': self.checkinlist.pk,
                                        'barcode': self.kwargs['pk']
                                    },
                                    user=self.request.user,
                                    auth=self.request.auth)
                Checkin.objects.create(position=op,
                                       successful=False,
                                       error_reason=Checkin.REASON_REVOKED,
                                       **common_checkin_args)
                return Response(
                    {
                        'status':
                        'error',
                        'reason':
                        Checkin.REASON_REVOKED,
                        'reason_explanation':
                        None,
                        'require_attention':
                        False,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=400)

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        if q.type == Question.TYPE_FILE:
                            given_answers[q] = self._handle_file_upload(
                                aws[str(q.pk)])
                        else:
                            given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        with language(self.request.event.settings.locale):
            try:
                perform_checkin(
                    op=op,
                    clist=self.checkinlist,
                    given_answers=given_answers,
                    force=force,
                    ignore_unpaid=ignore_unpaid,
                    nonce=nonce,
                    datetime=dt,
                    questions_supported=self.request.data.get(
                        'questions_supported', True),
                    canceled_supported=self.request.data.get(
                        'canceled_supported', False),
                    user=self.request.user,
                    auth=self.request.auth,
                    type=type,
                    raw_barcode=None,
                )
            except RequiredQuestionsError as e:
                return Response(
                    {
                        'status':
                        'incomplete',
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data,
                        'questions':
                        [QuestionSerializer(q).data for q in e.questions]
                    },
                    status=400)
            except CheckInError as e:
                op.order.log_action('pretix.event.checkin.denied',
                                    data={
                                        'position': op.id,
                                        'positionid': op.positionid,
                                        'errorcode': e.code,
                                        'reason_explanation': e.reason,
                                        'force': force,
                                        'datetime': dt,
                                        'type': type,
                                        'list': self.checkinlist.pk
                                    },
                                    user=self.request.user,
                                    auth=self.request.auth)
                Checkin.objects.create(
                    position=op,
                    successful=False,
                    error_reason=e.code,
                    error_explanation=e.reason,
                    **common_checkin_args,
                )
                return Response(
                    {
                        'status':
                        'error',
                        'reason':
                        e.code,
                        'reason_explanation':
                        e.reason,
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=400)
            else:
                return Response(
                    {
                        'status':
                        'ok',
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=201)
Beispiel #12
0
class PostPage(RoutablePageMixin, Page):
    title_th = models.CharField(max_length=255)
    body_en = RichTextField(blank=True)
    body_th = RichTextField(blank=True)
    date = models.DateTimeField(verbose_name="Post date",
                                default=datetime.today)
    categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
    tags = ClusterTaggableManager(through='blog.BlogPageTag', blank=True)
    feed_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')
    content_panels = Page.content_panels + [
        FieldPanel('title_th', classname='full'),
        FieldPanel('body_en', classname='full'),
        FieldPanel('body_th', classname='full'),
        FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
        FieldPanel('tags'),
    ]

    settings_panels = Page.settings_panels + [
        FieldPanel('date'),
    ]

    promote_panels = [
        ImageChooserPanel('feed_image'),
    ]

    api_fields = [
        APIField('pubdate',
                 serializer=DateTimeField(format='%A %d %B %Y',
                                          source='date')),
        APIField('title_th'),
        APIField('slug'),
        APIField('body_th'),
        APIField('categories'),
        APIField('tags'),
        APIField('feed_image_thumbnail',
                 serializer=ImageRenditionField('width-200',
                                                source='feed_image')),
    ]

    translated_title = TranslatedField(
        'title',
        'title_th',
    )
    body = TranslatedField(
        'body_en',
        'body_th',
    )

    @property
    def blog_page(self):
        return self.get_parent().specific

    def get_context(self, request, *args, **kwargs):
        context = super(PostPage, self).get_context(request, *args, **kwargs)
        context['blog_page'] = self.blog_page
        context['comment_form'] = PostCommentForm()
        return context
Beispiel #13
0
class ArticlePage(Page):
    tags = ClusterTaggableManager(through=ArticlePageTag, blank=True)
    author_image = models.ForeignKey('wagtailimages.Image',
                                     null=True,
                                     blank=True,
                                     on_delete=models.SET_NULL,
                                     related_name='+')
    author_name = models.CharField(max_length=10,
                                   validators=[MinLengthValidator(2)])
    article_datetime = models.DateTimeField()
    article_cover = models.ForeignKey('wagtailimages.Image',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL,
                                      related_name='+')
    article_cover_app = models.ForeignKey('wagtailimages.Image',
                                          null=True,
                                          blank=True,
                                          on_delete=models.SET_NULL,
                                          related_name='+')
    description = models.TextField(blank=True)
    liked_count = models.IntegerField(default=0)

    body = StreamField([
        ('Paragraph', blocks.RichTextBlock()),
        ('RawHTML', blocks.RawHTMLBlock()),
        ('DocumentChooser', DocumentChooserBlock()),
    ])

    content_panels = Page.content_panels + [
        HelpPanel('建议文章标题不超过30个字'),
        FieldPanel('tags'),
        HelpPanel('建议标签数量最多2个,标签字数1~5个'),
        FieldPanel('description'),
        ImageChooserPanel('author_image'),
        FieldPanel('author_name'),
        FieldPanel('article_datetime'),
        ImageChooserPanel('article_cover'),
        ImageChooserPanel('article_cover_app'),
        StreamFieldPanel('body'),
    ]

    api_fields = [
        APIField('tags'),
        APIField('author_image'),
        APIField('author_name'),
        APIField('article_datetime',
                 serializer=DateTimeField(format="%Y-%m-%d %H:%M")),
        APIField('article_cover'),
        APIField('article_cover_app'),
        APIField('description'),
        APIField('liked_count'),
        # This will nest the relevant BlogPageAuthor objects in the API response
    ]

    parent_page_types = ['ArticleListPage']
    subpage_types = []

    def get_datetime_format(self):

        return self.article_datetime.strftime("%Y-%m-%d %H:%I")

    @property
    def first_tag(self):
        if self.tags:
            return self.tags.first()
        else:
            return None
Beispiel #14
0
class CollectionDetailSerializer(CollectionCreateOrUpdateSerializer):
    type = CharField(source='resource_type')
    uuid = CharField(source='id')
    id = CharField(source='mnemonic')
    short_code = CharField(source='mnemonic')
    owner = CharField(source='parent_resource')
    owner_type = CharField(source='parent_resource_type')
    owner_url = CharField(source='parent_url')
    created_on = DateTimeField(source='created_at')
    updated_on = DateTimeField(source='updated_at')
    supported_locales = ListField(required=False, allow_empty=True)
    created_by = CharField(read_only=True, source='created_by.username')
    updated_by = CharField(read_only=True, source='updated_by.username')
    references = SerializerMethodField()
    summary = SerializerMethodField()
    client_configs = SerializerMethodField()

    class Meta:
        model = Collection
        lookup_field = 'mnemonic'
        fields = (
            'type',
            'uuid',
            'id',
            'short_code',
            'name',
            'full_name',
            'description',
            'collection_type',
            'custom_validation_schema',
            'public_access',
            'default_locale',
            'supported_locales',
            'website',
            'url',
            'owner',
            'owner_type',
            'owner_url',
            'created_on',
            'updated_on',
            'created_by',
            'updated_by',
            'extras',
            'external_id',
            'versions_url',
            'version',
            'concepts_url',
            'mappings_url',
            'custom_resources_linked_source',
            'repository_type',
            'preferred_source',
            'references',
            'canonical_url',
            'identifier',
            'publisher',
            'contact',
            'jurisdiction',
            'purpose',
            'copyright',
            'immutable',
            'revision_date',
            'logo_url',
            'summary',
            'text',
            'client_configs',
        )

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')
        self.query_params = params.dict() if params else dict()
        self.include_summary = self.query_params.get(INCLUDE_SUMMARY) in [
            'true', True
        ]
        self.include_client_configs = self.query_params.get(
            INCLUDE_CLIENT_CONFIGS) in ['true', True]

        try:
            if not self.include_summary:
                self.fields.pop('summary', None)
            if not self.include_client_configs:
                self.fields.pop('client_configs', None)
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    def get_summary(self, obj):
        summary = None

        if self.include_summary:
            summary = CollectionSummarySerializer(obj).data

        return summary

    def get_client_configs(self, obj):
        if self.include_client_configs:
            return ClientConfigSerializer(
                obj.client_configs.filter(is_active=True), many=True).data

        return None

    def get_references(self, obj):
        if self.context.get(INCLUDE_REFERENCES_PARAM, False):
            return CollectionReferenceSerializer(obj.references.all(),
                                                 many=True).data

        return []
Beispiel #15
0
class CertificateKeyPairSerializer(ModelSerializer):
    """CertificateKeyPair Serializer"""

    cert_expiry = DateTimeField(source="certificate.not_valid_after",
                                read_only=True)
    cert_subject = SerializerMethodField()
    private_key_available = SerializerMethodField()
    private_key_type = SerializerMethodField()

    certificate_download_url = SerializerMethodField()
    private_key_download_url = SerializerMethodField()

    def get_cert_subject(self, instance: CertificateKeyPair) -> str:
        """Get certificate subject as full rfc4514"""
        return instance.certificate.subject.rfc4514_string()

    def get_private_key_available(self, instance: CertificateKeyPair) -> bool:
        """Show if this keypair has a private key configured or not"""
        return instance.key_data != "" and instance.key_data is not None

    def get_private_key_type(self,
                             instance: CertificateKeyPair) -> Optional[str]:
        """Get the private key's type, if set"""
        key = instance.private_key
        if key:
            return key.__class__.__name__.replace("_", "").lower().replace(
                "privatekey", "")
        return None

    def get_certificate_download_url(self,
                                     instance: CertificateKeyPair) -> str:
        """Get URL to download certificate"""
        return (reverse(
            "authentik_api:certificatekeypair-view-certificate",
            kwargs={"pk": instance.pk},
        ) + "?download")

    def get_private_key_download_url(self,
                                     instance: CertificateKeyPair) -> str:
        """Get URL to download private key"""
        return (reverse(
            "authentik_api:certificatekeypair-view-private-key",
            kwargs={"pk": instance.pk},
        ) + "?download")

    def validate_certificate_data(self, value: str) -> str:
        """Verify that input is a valid PEM x509 Certificate"""
        try:
            # Cast to string to fully load and parse certificate
            # Prevents issues like https://github.com/goauthentik/authentik/issues/2082
            str(
                load_pem_x509_certificate(value.encode("utf-8"),
                                          default_backend()))
        except ValueError as exc:
            LOGGER.warning("Failed to load certificate", exc=exc)
            raise ValidationError("Unable to load certificate.")
        return value

    def validate_key_data(self, value: str) -> str:
        """Verify that input is a valid PEM Key"""
        # Since this field is optional, data can be empty.
        if value != "":
            try:
                # Cast to string to fully load and parse certificate
                # Prevents issues like https://github.com/goauthentik/authentik/issues/2082
                str(
                    load_pem_private_key(
                        str.encode("\n".join(
                            [x.strip() for x in value.split("\n")])),
                        password=None,
                        backend=default_backend(),
                    ))
            except (ValueError, TypeError) as exc:
                LOGGER.warning("Failed to load private key", exc=exc)
                raise ValidationError(
                    "Unable to load private key (possibly encrypted?).")
        return value

    class Meta:

        model = CertificateKeyPair
        fields = [
            "pk",
            "name",
            "fingerprint_sha256",
            "fingerprint_sha1",
            "certificate_data",
            "key_data",
            "cert_expiry",
            "cert_subject",
            "private_key_available",
            "private_key_type",
            "certificate_download_url",
            "private_key_download_url",
            "managed",
        ]
        extra_kwargs = {
            "key_data": {
                "write_only": True
            },
            "certificate_data": {
                "write_only": True
            },
        }
Beispiel #16
0
class ComentarioSerializer(ModelSerializer):
    criado_em = DateTimeField(read_only=True, format="%d/%m/%Y %H:%M:%S")

    class Meta:
        model = Comentario
        fields = ('id', 'usuario', 'comentario', 'aprovado', 'criado_em')
Beispiel #17
0
class ConceptListSerializer(ModelSerializer):
    uuid = CharField(source='id', read_only=True)
    id = CharField(source='mnemonic')
    source = CharField(source='parent_resource')
    owner = CharField(source='owner_name')
    update_comment = CharField(source='comment',
                               required=False,
                               allow_null=True,
                               allow_blank=True)
    locale = SerializerMethodField()
    url = CharField(required=False, source='versioned_object_url')
    version_created_on = DateTimeField(source='created_at', read_only=True)
    version_created_by = DateTimeField(source='created_by.username',
                                       read_only=True)
    mappings = SerializerMethodField()

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')
        self.query_params = params.dict() if params else dict()
        self.include_indirect_mappings = self.query_params.get(
            INCLUDE_INVERSE_MAPPINGS_PARAM) in ['true', True]
        self.include_direct_mappings = self.query_params.get(
            INCLUDE_MAPPINGS_PARAM) in ['true', True]
        self.include_extras = self.query_params.get(INCLUDE_EXTRAS_PARAM) in [
            'true', True
        ]

        try:
            if not self.include_extras:
                self.fields.pop('extras', None)
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    class Meta:
        model = Concept
        fields = (
            'uuid',
            'id',
            'external_id',
            'concept_class',
            'datatype',
            'url',
            'retired',
            'source',
            'owner',
            'owner_type',
            'owner_url',
            'display_name',
            'display_locale',
            'version',
            'update_comment',
            'locale',
            'version_created_by',
            'version_created_on',
            'mappings',
            'is_latest_version',
            'versions_url',
            'version_url',
            'extras',
        )

    @staticmethod
    def get_locale(obj):
        return obj.iso_639_1_locale

    def get_mappings(self, obj):
        from core.mappings.serializers import MappingDetailSerializer
        context = get(self, 'context')
        if self.include_direct_mappings:
            return MappingDetailSerializer(obj.get_unidirectional_mappings(),
                                           many=True,
                                           context=context).data
        if self.include_indirect_mappings:
            return MappingDetailSerializer(obj.get_bidirectional_mappings(),
                                           many=True,
                                           context=context).data

        return []
Beispiel #18
0
class SourceVersionDetailSerializer(SourceCreateOrUpdateSerializer):
    type = CharField(source='resource_version_type')
    uuid = CharField(source='id')
    id = CharField(source='version')
    short_code = CharField(source='mnemonic')
    owner = CharField(source='parent_resource')
    owner_type = CharField(source='parent_resource_type')
    owner_url = CharField(source='parent_url')
    created_on = DateTimeField(source='created_at')
    updated_on = DateTimeField(source='updated_at')
    created_by = CharField(source='created_by.username', read_only=True)
    updated_by = DateTimeField(source='updated_by.username', read_only=True)
    supported_locales = ListField(required=False, allow_empty=True)
    is_processing = BooleanField(read_only=True)
    released = BooleanField(default=False)
    version_url = CharField(source='uri')
    url = CharField(source='versioned_object_url')
    previous_version_url = CharField(source='prev_version_uri')
    summary = SerializerMethodField()

    class Meta:
        model = Source
        lookup_field = 'mnemonic'
        fields = ('type', 'uuid', 'id', 'short_code', 'name', 'full_name',
                  'description', 'source_type', 'custom_validation_schema',
                  'public_access', 'default_locale', 'supported_locales',
                  'website', 'url', 'owner', 'owner_type', 'owner_url',
                  'retired', 'version_url', 'previous_version_url',
                  'created_on', 'updated_on', 'created_by', 'updated_by',
                  'extras', 'external_id', 'version', 'concepts_url',
                  'mappings_url', 'is_processing', 'released', 'canonical_url',
                  'identifier', 'publisher', 'contact', 'jurisdiction',
                  'purpose', 'copyright', 'content_type', 'revision_date',
                  'summary', 'text', 'meta', 'experimental', 'case_sensitive',
                  'collection_reference', 'hierarchy_meaning', 'compositional',
                  'version_needed', 'internal_reference_id')

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')
        self.include_summary = False
        if params:
            self.query_params = params.dict()
            self.include_summary = self.query_params.get(INCLUDE_SUMMARY) in [
                'true', True
            ]

        try:
            if not self.include_summary:
                self.fields.pop('summary', None)
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    def get_summary(self, obj):
        summary = None

        if self.include_summary:
            summary = SourceVersionSummarySerializer(obj).data

        return summary
Beispiel #19
0
def format_datetime(dt):
    return DateTimeField().to_representation(dt)
def test_exporting_json_writes_file_to_storage(data_fixture, api_client,
                                               tmpdir, settings):
    user, token = data_fixture.create_user_and_token()
    table = data_fixture.create_database_table(user=user)
    text_field = data_fixture.create_text_field(table=table,
                                                name="text_field",
                                                order=0)
    option_field = data_fixture.create_single_select_field(table=table,
                                                           name="option_field",
                                                           order=1)
    option_a = data_fixture.create_select_option(field=option_field,
                                                 value="A",
                                                 color="blue")
    option_b = data_fixture.create_select_option(field=option_field,
                                                 value="B",
                                                 color="red")
    date_field = data_fixture.create_date_field(
        table=table,
        date_include_time=True,
        date_format="US",
        name="date_field",
        order=2,
    )

    grid_view = data_fixture.create_grid_view(table=table)
    data_fixture.create_view_filter(view=grid_view,
                                    field=text_field,
                                    type="contains",
                                    value="test")
    data_fixture.create_view_sort(view=grid_view,
                                  field=text_field,
                                  order="ASC")

    row_handler = RowHandler()
    row_handler.create_row(
        user=user,
        table=table,
        values={
            text_field.id: "test",
            date_field.id: "2020-02-01 01:23",
            option_field.id: option_b.id,
        },
    )
    row_handler.create_row(
        user=user,
        table=table,
        values={
            text_field.id: "atest",
            date_field.id: "2020-02-01 01:23",
            option_field.id: option_a.id,
        },
    )
    storage = FileSystemStorage(location=(str(tmpdir)),
                                base_url="http://localhost")

    with patch("baserow.contrib.database.export.handler.default_storage",
               new=storage):
        run_time = make_aware(parse_datetime("2020-02-01 01:00"), timezone=utc)
        expected_created_at = DateTimeField().to_representation(run_time)
        with freeze_time(run_time):
            with capture_on_commit_callbacks(execute=True):
                response = api_client.post(
                    reverse(
                        "api:database:export:export_table",
                        kwargs={"table_id": table.id},
                    ),
                    data={
                        "view_id": grid_view.id,
                        "exporter_type": "json",
                        "json_charset": "utf-8",
                    },
                    format="json",
                    HTTP_AUTHORIZATION=f"JWT {token}",
                )
            response_json = response.json()
            assert "id" in response_json
            job_id = response_json["id"]
            assert response_json == {
                "id": job_id,
                "created_at": expected_created_at,
                "exported_file_name": None,
                "exporter_type": "json",
                "progress_percentage": 0.0,
                "status": "pending",
                "table": table.id,
                "view": grid_view.id,
                "url": None,
            }
            response = api_client.get(
                reverse("api:database:export:get", kwargs={"job_id": job_id}),
                format="json",
                HTTP_AUTHORIZATION=f"JWT {token}",
            )
            response_json = response.json()
            assert "exported_file_name" in response_json
            filename = response_json["exported_file_name"]
            assert response_json == {
                "id": job_id,
                "created_at": expected_created_at,
                "exported_file_name": filename,
                "exporter_type": "json",
                "progress_percentage": 1.0,
                "status": "complete",
                "table": table.id,
                "view": grid_view.id,
                "url": f"http://localhost:8000/media/export_files/{filename}",
            }

            file_path = tmpdir.join(settings.EXPORT_FILES_DIRECTORY, filename)
            assert file_path.isfile()
            expected = """[
{
    "id": 2,
    "text_field": "atest",
    "option_field": "A",
    "date_field": "02/01/2020 01:23"
},
{
    "id": 1,
    "text_field": "test",
    "option_field": "B",
    "date_field": "02/01/2020 01:23"
}
]
"""
            with open(file_path, "r", encoding="utf-8") as written_file:
                real = written_file.read()
                assert real == expected
Beispiel #21
0
    return tzinfo.normalize(dt.astimezone(tzinfo))


def as_china_cst(dt: datetime.datetime):
    return astimezone(dt, pytz.timezone('Asia/Shanghai'))


def as_current_tz(dt: datetime.datetime):
    return astimezone(dt, dj_timezone.get_current_timezone())


def utc_now():
    return dj_timezone.now()


def local_now():
    return dj_timezone.localtime(dj_timezone.now())


def local_now_display(fmt='%Y-%m-%d %H:%M:%S'):
    return local_now().strftime(fmt)


def local_now_date_display(fmt='%Y-%m-%d'):
    return local_now().strftime(fmt)


_rest_dt_field = DateTimeField()
dt_parser = _rest_dt_field.to_internal_value
dt_formatter = _rest_dt_field.to_representation
Beispiel #22
0
class ConceptDetailSerializer(ModelSerializer):
    uuid = CharField(source='id', read_only=True)
    version = CharField(read_only=True)
    type = CharField(source='versioned_resource_type', read_only=True)
    id = EncodedDecodedCharField(source='mnemonic', required=True)
    source = CharField(source='parent_resource', read_only=True)
    parent_id = UUIDField(write_only=True)
    owner = CharField(source='owner_name', read_only=True)
    created_on = DateTimeField(source='created_at', read_only=True)
    updated_on = DateTimeField(source='updated_at', read_only=True)
    names = LocalizedNameSerializer(many=True)
    descriptions = LocalizedDescriptionSerializer(many=True, allow_null=True, required=False)
    external_id = CharField(required=False, allow_blank=True)
    concept_class = CharField(required=True)
    datatype = CharField(required=True)
    display_name = CharField(read_only=True)
    display_locale = CharField(read_only=True)
    retired = BooleanField(required=False)
    owner_type = CharField(read_only=True)
    owner_url = URLField(read_only=True)
    extras = JSONField(required=False, allow_null=True)
    update_comment = CharField(required=False, source='comment', allow_null=True, allow_blank=True)
    url = CharField(required=False, source='versioned_object_url')
    updated_by = DateTimeField(source='updated_by.username', read_only=True)
    created_by = DateTimeField(source='created_by.username', read_only=True)
    parent_concept_urls = ListField(allow_null=True, required=False, allow_empty=True)
    child_concept_urls = ListField(read_only=True)
    mappings = SerializerMethodField()
    parent_concepts = SerializerMethodField()
    child_concepts = SerializerMethodField()

    def __init__(self, *args, **kwargs):
        params = get(kwargs, 'context.request.query_params')
        self.query_params = params.dict() if params else dict()
        self.include_indirect_mappings = self.query_params.get(INCLUDE_INVERSE_MAPPINGS_PARAM) in ['true', True]
        self.include_direct_mappings = self.query_params.get(INCLUDE_MAPPINGS_PARAM) in ['true', True]
        self.include_parent_concepts = self.query_params.get(INCLUDE_PARENT_CONCEPTS) in ['true', True]
        self.include_child_concepts = self.query_params.get(INCLUDE_CHILD_CONCEPTS) in ['true', True]

        try:
            if not self.include_parent_concepts:
                self.fields.pop('parent_concepts', None)
            if not self.include_child_concepts:
                self.fields.pop('child_concepts', None)
        except:  # pylint: disable=bare-except
            pass

        super().__init__(*args, **kwargs)

    class Meta:
        model = Concept
        fields = (
            'uuid', 'id', 'external_id', 'concept_class', 'datatype', 'url', 'retired', 'source',
            'owner', 'owner_type', 'owner_url', 'display_name', 'display_locale', 'names', 'descriptions',
            'created_on', 'updated_on', 'versions_url', 'version', 'extras', 'parent_id', 'name', 'type',
            'update_comment', 'version_url', 'mappings', 'updated_by', 'created_by', 'internal_reference_id',
            'parent_concept_urls', 'child_concept_urls', 'parent_concepts', 'child_concepts'
        )

    def get_mappings(self, obj):
        from core.mappings.serializers import MappingDetailSerializer
        context = get(self, 'context')
        if self.include_indirect_mappings:
            return MappingDetailSerializer(obj.get_bidirectional_mappings(), many=True, context=context).data
        if self.include_direct_mappings:
            return MappingDetailSerializer(obj.get_unidirectional_mappings(), many=True, context=context).data

        return []

    def create(self, validated_data):
        concept = Concept.persist_new(data=validated_data, user=self.context.get('request').user)
        if concept.errors:
            self._errors.update(concept.errors)
        return concept

    def update(self, instance, validated_data):
        errors = Concept.create_new_version_for(instance, validated_data, self.context.get('request').user)
        if errors:
            self._errors.update(errors)
        return instance

    def get_child_concepts(self, obj):
        if self.include_child_concepts:
            return ConceptDetailSerializer(obj.child_concepts.all(), many=True).data
        return None

    def get_parent_concepts(self, obj):
        if self.include_parent_concepts:
            return ConceptDetailSerializer(obj.parent_concepts.all(), many=True).data
        return None
Beispiel #23
0
class VideoSerializer(serializers.ModelSerializer):
    """
    Serializer for Video object

    encoded_videos takes a list of dicts EncodedVideo data.
    """
    encoded_videos = EncodedVideoSerializer(many=True)
    courses = CourseSerializer(many=True,
                               read_only=False,
                               required=False,
                               queryset=CourseVideo.objects.all())
    url = serializers.SerializerMethodField()

    # Django Rest Framework v3 converts datetimes to unicode by default.
    # Specify format=None to leave them as datetimes.
    created = DateTimeField(required=False, format=None)

    class Meta:  # pylint: disable=C1001, C0111
        model = Video
        lookup_field = "edx_video_id"
        exclude = ('id', )

    def get_url(self, obj):
        """
        Return relative url for the object
        """
        return obj.get_absolute_url()

    def validate(self, data):
        """
        Check that the video data is valid.
        """
        if data is not None and not isinstance(data, dict):
            raise serializers.ValidationError("Invalid data")

        try:
            profiles = [ev["profile"] for ev in data.get("encoded_videos", [])]
            if len(profiles) != len(set(profiles)):
                raise serializers.ValidationError(
                    "Invalid data: duplicate profiles")
        except KeyError:
            raise serializers.ValidationError(
                "profile required for deserializing")
        except TypeError:
            raise serializers.ValidationError(
                "profile field needs to be a profile_name (str)")

        # Clean course_video list from any invalid data.
        course_videos = [(course_video, image)
                         for course_video, image in data.get('courses', [])
                         if course_video]
        data['courses'] = course_videos

        return data

    def create(self, validated_data):
        """
        Create the video and its nested resources.
        """
        courses = validated_data.pop("courses", [])
        encoded_videos = validated_data.pop("encoded_videos", [])

        video = Video.objects.create(**validated_data)

        EncodedVideo.objects.bulk_create(
            EncodedVideo(video=video, **video_data)
            for video_data in encoded_videos)

        # The CourseSerializer will already have converted the course data
        # to CourseVideo models, so we can just set the video and save.
        # Also create VideoImage objects if an image filename is present
        for course_video, image_name in courses:
            course_video.video = video
            course_video.save()
            if image_name:
                VideoImage.create_or_update(course_video, image_name)

        return video

    def update(self, instance, validated_data):
        """
        Update an existing video resource.
        """
        instance.status = validated_data["status"]
        instance.client_video_id = validated_data["client_video_id"]
        instance.duration = validated_data["duration"]
        instance.save()

        # Set encoded videos
        instance.encoded_videos.all().delete()
        EncodedVideo.objects.bulk_create(
            EncodedVideo(video=instance, **video_data)
            for video_data in validated_data.get("encoded_videos", []))

        # Set courses
        # NOTE: for backwards compatibility with the DRF v2 behavior,
        # we do NOT delete existing course videos during the update.
        # Also update VideoImage objects if an image filename is present
        for course_video, image_name in validated_data.get("courses", []):
            course_video.video = instance
            course_video.save()
            if image_name:
                VideoImage.create_or_update(course_video, image_name)

        return instance
Beispiel #24
0
def serialize_datetime(data):
    return DateTimeField().to_representation(data)
Beispiel #25
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        type = self.request.data.get('type', None) or Checkin.TYPE_ENTRY
        if type not in dict(Checkin.CHECKIN_TYPES):
            raise ValidationError("Invalid check-in type.")
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(
                self.request.data.get('datetime'))
        else:
            dt = now()

        try:
            queryset = self.get_queryset(ignore_status=True,
                                         ignore_products=True)
            if self.kwargs['pk'].isnumeric():
                op = queryset.get(
                    Q(pk=self.kwargs['pk']) | Q(secret=self.kwargs['pk']))
            else:
                op = queryset.get(secret=self.kwargs['pk'])
        except OrderPosition.DoesNotExist:
            self.request.event.log_action('pretix.event.checkin.unknown',
                                          data={
                                              'datetime': dt,
                                              'type': type,
                                              'list': self.checkinlist.pk,
                                              'barcode': self.kwargs['pk']
                                          },
                                          user=self.request.user,
                                          auth=self.request.auth)
            raise Http404()

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        try:
            perform_checkin(
                op=op,
                clist=self.checkinlist,
                given_answers=given_answers,
                force=force,
                ignore_unpaid=ignore_unpaid,
                nonce=nonce,
                datetime=dt,
                questions_supported=self.request.data.get(
                    'questions_supported', True),
                canceled_supported=self.request.data.get(
                    'canceled_supported', False),
                user=self.request.user,
                auth=self.request.auth,
                type=type,
            )
        except RequiredQuestionsError as e:
            return Response(
                {
                    'status':
                    'incomplete',
                    'require_attention':
                    op.item.checkin_attention or op.order.checkin_attention,
                    'position':
                    CheckinListOrderPositionSerializer(
                        op, context=self.get_serializer_context()).data,
                    'questions':
                    [QuestionSerializer(q).data for q in e.questions]
                },
                status=400)
        except CheckInError as e:
            op.order.log_action('pretix.event.checkin.denied',
                                data={
                                    'position': op.id,
                                    'positionid': op.positionid,
                                    'errorcode': e.code,
                                    'datetime': dt,
                                    'type': type,
                                    'list': self.checkinlist.pk
                                },
                                user=self.request.user,
                                auth=self.request.auth)
            return Response(
                {
                    'status':
                    'error',
                    'reason':
                    e.code,
                    'require_attention':
                    op.item.checkin_attention or op.order.checkin_attention,
                    'position':
                    CheckinListOrderPositionSerializer(
                        op, context=self.get_serializer_context()).data
                },
                status=400)
        else:
            return Response(
                {
                    'status':
                    'ok',
                    'require_attention':
                    op.item.checkin_attention or op.order.checkin_attention,
                    'position':
                    CheckinListOrderPositionSerializer(
                        op, context=self.get_serializer_context()).data
                },
                status=201)
Beispiel #26
0
 def check_time(self, iso, t):
     # Compare equality of iso 8601 formatted string and datetime
     self.assertEqual(DateTimeField().to_internal_value(iso), t)
Beispiel #27
0
class ConceptDetailSerializer(ModelSerializer):
    uuid = CharField(source='id', read_only=True)
    version = CharField(read_only=True)
    type = CharField(source='versioned_resource_type', read_only=True)
    id = CharField(source='mnemonic', required=True)
    source = CharField(source='parent_resource', read_only=True)
    parent_id = UUIDField()
    owner = CharField(source='owner_name', read_only=True)
    created_on = DateTimeField(source='created_at', read_only=True)
    updated_on = DateTimeField(source='updated_at', read_only=True)
    names = LocalizedNameSerializer(many=True)
    descriptions = LocalizedDescriptionSerializer(many=True, allow_null=True)
    external_id = CharField(required=False, allow_blank=True)
    concept_class = CharField(required=True)
    datatype = CharField(required=True)
    display_name = CharField(read_only=True)
    display_locale = CharField(read_only=True)
    retired = BooleanField(required=False)
    url = URLField(read_only=True)
    owner_type = CharField(read_only=True)
    owner_url = URLField(read_only=True)
    extras = JSONField(required=False, allow_null=True)
    update_comment = CharField(required=False, source='comment')
    mappings = SerializerMethodField()

    def __init__(self, *args, **kwargs):
        self.query_params = kwargs.get('context').get(
            'request').query_params.dict()
        self.include_indirect_mappings = self.query_params.get(
            INCLUDE_INVERSE_MAPPINGS_PARAM) == 'true'
        self.include_direct_mappings = self.query_params.get(
            INCLUDE_MAPPINGS_PARAM) == 'true'

        super().__init__(*args, **kwargs)

    class Meta:
        model = Concept
        fields = ('uuid', 'id', 'external_id', 'concept_class', 'datatype',
                  'url', 'retired', 'source', 'owner', 'owner_type',
                  'owner_url', 'display_name', 'display_locale', 'names',
                  'descriptions', 'created_on', 'updated_on', 'versions_url',
                  'version', 'extras', 'parent_id', 'name', 'type',
                  'update_comment', 'version_url', 'mappings')

    def get_mappings(self, obj):
        if self.include_indirect_mappings:
            return MappingDetailSerializer(obj.get_bidirectional_mappings(),
                                           many=True).data
        if self.include_direct_mappings:
            return MappingDetailSerializer(obj.get_unidirectional_mappings(),
                                           many=True).data

        return []

    def create(self, validated_data):
        concept = Concept.persist_new(data=validated_data,
                                      user=self.context.get('request').user)
        self._errors.update(concept.errors)
        return concept

    def update(self, instance, validated_data):
        instance.concept_class = validated_data.get('concept_class',
                                                    instance.concept_class)
        instance.datatype = validated_data.get('datatype', instance.datatype)
        instance.extras = validated_data.get('extras', instance.extras)
        instance.external_id = validated_data.get('external_id',
                                                  instance.external_id)
        instance.comment = validated_data.get(
            'update_comment') or validated_data.get('comment')
        instance.retired = validated_data.get('retired', instance.retired)

        new_names = [
            LocalizedText(
                **{k: v
                   for k, v in name.items() if k not in ['name_type']})
            for name in validated_data.get('names', [])
        ]
        new_descriptions = [
            LocalizedText(**{
                k: v
                for k, v in desc.items() if k not in ['description_type']
            }) for desc in validated_data.get('descriptions', [])
        ]

        instance.cloned_names = compact(new_names)
        instance.cloned_descriptions = compact(new_descriptions)
        errors = Concept.persist_clone(instance,
                                       self.context.get('request').user)
        if errors:
            self._errors.update(errors)
        return instance
Beispiel #28
0
def django_time_format(dtstr):
    """Convert a datetime to string according to the API settings"""
    from rest_framework.fields import DateTimeField

    field = DateTimeField()
    return field.to_internal_value(dtstr)
Beispiel #29
0
class ConceptListSerializer(ModelSerializer):
    uuid = CharField(source='id', read_only=True)
    id = CharField(source='mnemonic')
    source = CharField(source='parent_resource')
    owner = CharField(source='owner_name')
    update_comment = CharField(source='comment')
    locale = SerializerMethodField()
    url = CharField(source='uri', read_only=True)
    version_created_on = DateTimeField(source='created_at', read_only=True)
    version_created_by = DateTimeField(source='created_by.username',
                                       read_only=True)
    mappings = SerializerMethodField()

    def __init__(self, *args, **kwargs):
        self.query_params = kwargs.get('context').get(
            'request').query_params.dict()
        self.include_indirect_mappings = self.query_params.get(
            INCLUDE_INVERSE_MAPPINGS_PARAM) == 'true'
        self.include_direct_mappings = self.query_params.get(
            INCLUDE_MAPPINGS_PARAM) == 'true'

        super().__init__(*args, **kwargs)

    class Meta:
        model = Concept
        fields = (
            'uuid',
            'id',
            'external_id',
            'concept_class',
            'datatype',
            'url',
            'retired',
            'source',
            'owner',
            'owner_type',
            'owner_url',
            'display_name',
            'display_locale',
            'version',
            'update_comment',
            'locale',
            'version_created_by',
            'version_created_on',
            'mappings',
            'is_latest_version',
            'versions_url',
        )

    @staticmethod
    def get_locale(obj):
        return obj.iso_639_1_locale

    def get_mappings(self, obj):
        if self.include_direct_mappings:
            return MappingDetailSerializer(obj.get_unidirectional_mappings(),
                                           many=True).data
        if self.include_indirect_mappings:
            return MappingDetailSerializer(obj.get_bidirectional_mappings(),
                                           many=True).data

        return []
Beispiel #30
0
class CollectionCreateSerializer(CollectionCreateOrUpdateSerializer):
    type = CharField(source='resource_type', read_only=True)
    uuid = CharField(source='id', read_only=True)
    id = CharField(required=True,
                   validators=[RegexValidator(regex=NAMESPACE_REGEX)],
                   source='mnemonic')
    short_code = CharField(source='mnemonic', read_only=True)
    name = CharField(required=True)
    full_name = CharField(required=False)
    description = CharField(required=False, allow_blank=True)
    text = CharField(required=False, allow_blank=True)
    collection_type = CharField(required=False)
    custom_validation_schema = CharField(required=False,
                                         allow_blank=True,
                                         allow_null=True)
    public_access = ChoiceField(required=False, choices=ACCESS_TYPE_CHOICES)
    default_locale = CharField(required=False, allow_blank=True)
    supported_locales = ListField(required=False, allow_empty=True)
    website = CharField(required=False, allow_blank=True)
    url = CharField(read_only=True)
    canonical_url = CharField(required=False,
                              allow_null=True,
                              allow_blank=True)
    custom_resources_linked_source = CharField(required=False,
                                               allow_null=True,
                                               allow_blank=True)
    repository_type = CharField(required=False,
                                allow_null=True,
                                allow_blank=True)
    preferred_source = CharField(required=False,
                                 allow_null=True,
                                 allow_blank=True)
    versions_url = CharField(read_only=True)
    concepts_url = CharField(read_only=True)
    mappings_url = CharField(read_only=True)
    owner = CharField(source='parent_resource', read_only=True)
    owner_type = CharField(source='parent_resource_type', read_only=True)
    owner_url = CharField(source='parent_url', read_only=True)
    versions = IntegerField(source='num_versions', read_only=True)
    created_on = DateTimeField(source='created_at', read_only=True)
    updated_on = DateTimeField(source='updated_at', read_only=True)
    created_by = CharField(source='owner', read_only=True)
    updated_by = CharField(read_only=True)
    extras = JSONField(required=False, allow_null=True)
    external_id = CharField(required=False, allow_blank=True)
    user_id = PrimaryKeyRelatedField(required=False,
                                     queryset=UserProfile.objects.all(),
                                     allow_null=True)
    organization_id = PrimaryKeyRelatedField(
        required=False, queryset=Organization.objects.all(), allow_null=True)
    version = CharField(default=HEAD)
    identifier = JSONField(required=False, allow_null=True)
    contact = JSONField(required=False, allow_null=True)
    jurisdiction = JSONField(required=False, allow_null=True)
    publisher = CharField(required=False, allow_null=True, allow_blank=True)
    purpose = CharField(required=False, allow_null=True, allow_blank=True)
    copyright = CharField(required=False, allow_null=True, allow_blank=True)

    def create(self, validated_data):
        collection = self.prepare_object(validated_data)
        user = self.context['request'].user
        errors = Collection.persist_new(collection, user)
        self._errors.update(errors)
        return collection

    def create_version(self, validated_data):
        collection = self.prepare_object(validated_data)
        user = self.context['request'].user
        errors = Collection.persist_new_version(collection, user)
        self._errors.update(errors)
        return collection
Beispiel #31
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        type = self.request.data.get('type', None) or Checkin.TYPE_ENTRY
        if type not in dict(Checkin.CHECKIN_TYPES):
            raise ValidationError("Invalid check-in type.")
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')
        op = self.get_object(ignore_status=True)

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(self.request.data.get('datetime'))
        else:
            dt = now()

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        try:
            perform_checkin(
                op=op,
                clist=self.checkinlist,
                given_answers=given_answers,
                force=force,
                ignore_unpaid=ignore_unpaid,
                nonce=nonce,
                datetime=dt,
                questions_supported=self.request.data.get('questions_supported', True),
                canceled_supported=self.request.data.get('canceled_supported', False),
                user=self.request.user,
                auth=self.request.auth,
                type=type,
            )
        except RequiredQuestionsError as e:
            return Response({
                'status': 'incomplete',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data,
                'questions': [
                    QuestionSerializer(q).data for q in e.questions
                ]
            }, status=400)
        except CheckInError as e:
            return Response({
                'status': 'error',
                'reason': e.code,
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=400)
        else:
            return Response({
                'status': 'ok',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=201)
Beispiel #32
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        type = self.request.data.get('type', None) or Checkin.TYPE_ENTRY
        if type not in dict(Checkin.CHECKIN_TYPES):
            raise ValidationError("Invalid check-in type.")
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(
                self.request.data.get('datetime'))
        else:
            dt = now()

        common_checkin_args = dict(
            raw_barcode=self.kwargs['pk'],
            type=type,
            list=self.checkinlist,
            datetime=dt,
            device=self.request.auth
            if isinstance(self.request.auth, Device) else None,
            gate=self.request.auth.gate
            if isinstance(self.request.auth, Device) else None,
            nonce=nonce,
            forced=force,
        )
        raw_barcode_for_checkin = None

        try:
            queryset = self.get_queryset(ignore_status=True,
                                         ignore_products=True)
            if self.kwargs['pk'].isnumeric():
                op = queryset.get(
                    Q(pk=self.kwargs['pk']) | Q(secret=self.kwargs['pk']))
            else:
                op = queryset.get(secret=self.kwargs['pk'])
        except OrderPosition.DoesNotExist:
            revoked_matches = list(
                self.request.event.revoked_secrets.filter(
                    secret=self.kwargs['pk']))
            if len(revoked_matches) == 0:
                self.request.event.log_action('pretix.event.checkin.unknown',
                                              data={
                                                  'datetime': dt,
                                                  'type': type,
                                                  'list': self.checkinlist.pk,
                                                  'barcode': self.kwargs['pk']
                                              },
                                              user=self.request.user,
                                              auth=self.request.auth)

                for k, s in self.request.event.ticket_secret_generators.items(
                ):
                    try:
                        parsed = s.parse_secret(self.kwargs['pk'])
                        common_checkin_args.update({
                            'raw_item':
                            parsed.item,
                            'raw_variation':
                            parsed.variation,
                            'raw_subevent':
                            parsed.subevent,
                        })
                    except:
                        pass

                Checkin.objects.create(
                    position=None,
                    successful=False,
                    error_reason=Checkin.REASON_INVALID,
                    **common_checkin_args,
                )

                if force and isinstance(self.request.auth, Device):
                    # There was a bug in libpretixsync: If you scanned a ticket in offline mode that was
                    # valid at the time but no longer exists at time of upload, the device would retry to
                    # upload the same scan over and over again. Since we can't update all devices quickly,
                    # here's a dirty workaround to make it stop.
                    try:
                        brand = self.request.auth.software_brand
                        ver = parse(self.request.auth.software_version)
                        legacy_mode = ((brand == 'pretixSCANPROXY'
                                        and ver < parse('0.0.3'))
                                       or (brand == 'pretixSCAN Android'
                                           and ver < parse('1.11.2'))
                                       or (brand == 'pretixSCAN'
                                           and ver < parse('1.11.2')))
                        if legacy_mode:
                            return Response(
                                {
                                    'status':
                                    'error',
                                    'reason':
                                    Checkin.REASON_ALREADY_REDEEMED,
                                    'reason_explanation':
                                    None,
                                    'require_attention':
                                    False,
                                    '__warning':
                                    'Compatibility hack active due to detected old pretixSCAN version',
                                },
                                status=400)
                    except:  # we don't care e.g. about invalid version numbers
                        pass

                return Response(
                    {
                        'detail': 'Not found.',  # for backwards compatibility
                        'status': 'error',
                        'reason': Checkin.REASON_INVALID,
                        'reason_explanation': None,
                        'require_attention': False,
                    },
                    status=404)
            elif revoked_matches and force:
                op = revoked_matches[0].position
                raw_barcode_for_checkin = self.kwargs['pk']
            else:
                op = revoked_matches[0].position
                op.order.log_action('pretix.event.checkin.revoked',
                                    data={
                                        'datetime': dt,
                                        'type': type,
                                        'list': self.checkinlist.pk,
                                        'barcode': self.kwargs['pk']
                                    },
                                    user=self.request.user,
                                    auth=self.request.auth)
                Checkin.objects.create(position=op,
                                       successful=False,
                                       error_reason=Checkin.REASON_REVOKED,
                                       **common_checkin_args)
                return Response(
                    {
                        'status':
                        'error',
                        'reason':
                        Checkin.REASON_REVOKED,
                        'reason_explanation':
                        None,
                        'require_attention':
                        False,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=400)

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        if q.type == Question.TYPE_FILE:
                            given_answers[q] = self._handle_file_upload(
                                aws[str(q.pk)])
                        else:
                            given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        with language(self.request.event.settings.locale):
            try:
                perform_checkin(
                    op=op,
                    clist=self.checkinlist,
                    given_answers=given_answers,
                    force=force,
                    ignore_unpaid=ignore_unpaid,
                    nonce=nonce,
                    datetime=dt,
                    questions_supported=self.request.data.get(
                        'questions_supported', True),
                    canceled_supported=self.request.data.get(
                        'canceled_supported', False),
                    user=self.request.user,
                    auth=self.request.auth,
                    type=type,
                    raw_barcode=raw_barcode_for_checkin,
                    from_revoked_secret=True,
                )
            except RequiredQuestionsError as e:
                return Response(
                    {
                        'status':
                        'incomplete',
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data,
                        'questions':
                        [QuestionSerializer(q).data for q in e.questions]
                    },
                    status=400)
            except CheckInError as e:
                op.order.log_action('pretix.event.checkin.denied',
                                    data={
                                        'position': op.id,
                                        'positionid': op.positionid,
                                        'errorcode': e.code,
                                        'reason_explanation': e.reason,
                                        'force': force,
                                        'datetime': dt,
                                        'type': type,
                                        'list': self.checkinlist.pk
                                    },
                                    user=self.request.user,
                                    auth=self.request.auth)
                Checkin.objects.create(
                    position=op,
                    successful=False,
                    error_reason=e.code,
                    error_explanation=e.reason,
                    **common_checkin_args,
                )
                return Response(
                    {
                        'status':
                        'error',
                        'reason':
                        e.code,
                        'reason_explanation':
                        e.reason,
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=400)
            else:
                return Response(
                    {
                        'status':
                        'ok',
                        'require_attention':
                        op.item.checkin_attention
                        or op.order.checkin_attention,
                        'position':
                        CheckinListOrderPositionSerializer(
                            op, context=self.get_serializer_context()).data
                    },
                    status=201)
Beispiel #33
0
class CertificateKeyPairSerializer(ModelSerializer):
    """CertificateKeyPair Serializer"""

    cert_expiry = DateTimeField(source="certificate.not_valid_after",
                                read_only=True)
    cert_subject = SerializerMethodField()
    private_key_available = SerializerMethodField()

    def get_cert_subject(self, instance: CertificateKeyPair) -> str:
        """Get certificate subject as full rfc4514"""
        return instance.certificate.subject.rfc4514_string()

    def get_private_key_available(self, instance: CertificateKeyPair) -> bool:
        """Show if this keypair has a private key configured or not"""
        return instance.key_data != "" and instance.key_data is not None

    def validate_certificate_data(self, value: str) -> str:
        """Verify that input is a valid PEM x509 Certificate"""
        try:
            load_pem_x509_certificate(value.encode("utf-8"), default_backend())
        except ValueError:
            raise ValidationError("Unable to load certificate.")
        return value

    def validate_key_data(self, value: str) -> str:
        """Verify that input is a valid PEM RSA Key"""
        # Since this field is optional, data can be empty.
        if value != "":
            try:
                load_pem_private_key(
                    str.encode("\n".join(
                        [x.strip() for x in value.split("\n")])),
                    password=None,
                    backend=default_backend(),
                )
            except (ValueError, TypeError):
                raise ValidationError(
                    "Unable to load private key (possibly encrypted?).")
        return value

    class Meta:

        model = CertificateKeyPair
        fields = [
            "pk",
            "name",
            "fingerprint",
            "certificate_data",
            "key_data",
            "cert_expiry",
            "cert_subject",
            "private_key_available",
        ]
        extra_kwargs = {
            "key_data": {
                "write_only": True
            },
            "certificate_data": {
                "write_only": True
            },
        }