passerelle/passerelle/apps/qrcode/models.py

115 lines
3.8 KiB
Python

import os
import uuid
from django.core.validators import RegexValidator
from django.db import models
from django.shortcuts import get_object_or_404
from django.utils.dateparse import parse_datetime
from django.utils.translation import gettext_lazy as _
from passerelle.base.models import BaseResource
from passerelle.utils.api import endpoint
CERTIFICATE_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'unflatten': True,
'additionalProperties': False,
'properties': {
'data': {
'type': 'object',
'title': _('Data to encode in the certificate'),
'additionalProperties': {'type': 'string'},
},
'validity_start': {'type': 'string', 'format': 'date-time'},
'validity_end': {'type': 'string', 'format': 'date-time'},
},
}
def generate_key():
key = os.urandom(32)
return ''.join(format(x, '02x') for x in key)
UUID_PATTERN = '(?P<uuid>[0-9|a-f]{8}-[0-9|a-f]{4}-[0-9|a-f]{4}-[0-9|a-f]{4}-[0-9a-f]{12})'
class QRCodeConnector(BaseResource):
category = _('Misc')
key = models.CharField(
_('Private Key'),
max_length=64,
default=generate_key,
validators=[RegexValidator(r'[a-z|0-9]{64}', 'Key should be a 32 bytes hexadecimal string')],
)
class Meta:
verbose_name = _('QR Code')
@endpoint(
name='save-certificate',
pattern=f'^{UUID_PATTERN}?$',
example_pattern='{uuid}',
description=_('Create or update a certificate'),
post={'request_body': {'schema': {'application/json': CERTIFICATE_SCHEMA}}},
parameters={
'uuid': {
'description': _('Certificate identifier'),
'example_value': '12345678-1234-1234-1234-123456789012',
}
},
)
def save_certificate(self, request, uuid=None, post_data=None):
validity_start = parse_datetime(post_data['validity_start'])
validity_end = parse_datetime(post_data['validity_end'])
data = post_data['data']
if not uuid:
certificate = self.certificates.create(
data=data,
validity_start=validity_start,
validity_end=validity_end,
)
else:
certificate = get_object_or_404(self.certificates, uuid=uuid)
certificate.validity_start = validity_start
certificate.validity_end = validity_end
certificate.data = data
certificate.save()
return {'data': {'uuid': certificate.uuid}}
@endpoint(
name='get-certificate',
description=_('Retrieve an existing certificate'),
pattern=f'^{UUID_PATTERN}$',
example_pattern='{uuid}',
parameters={
'uuid': {
'description': _('Certificate identifier'),
'example_value': '12345678-1234-1234-1234-123456789012',
}
},
)
def get_certificate(self, request, uuid):
certificate = get_object_or_404(self.certificates, uuid=uuid)
return {
'err': 0,
'data': {
'uuid': certificate.uuid,
'data': certificate.data,
'validity_start': certificate.validity_start.isoformat(),
'validity_end': certificate.validity_end.isoformat(),
},
}
class Certificate(models.Model):
uuid = models.UUIDField(verbose_name=_('UUID'), unique=True, default=uuid.uuid4)
validity_start = models.DateTimeField(verbose_name=_('Validity Start Date'))
validity_end = models.DateTimeField(verbose_name=_('Validity End Date'))
data = models.JSONField(null=True, verbose_name='Certificate Data')
resource = models.ForeignKey(QRCodeConnector, on_delete=models.CASCADE, related_name='certificates')