def export_single(request): key = request.META.get('HTTP_AUTHORIZATION', None) id = request.GET.get('id', None) if key is None: raise AuthenticationError('No API key specified!') try: api_key = ApiKey.objects.get(key=key) except ApiKey.DoesNotExist: raise AuthenticationError('Invalid API key specified!') try: api_key.scopes.get(id=SCOPE_EXPORT) except Scope.DoesNotExist: raise AuthenticationError('Invalid API key scope!') if id is None: raise ApiException('Missing id!', status=400) try: badge = Badge.objects.get(id=id) except Badge.DoesNotExist: raise ApiException('Invalid id!', status=400) return ApiResponse(dict( id=badge.id, name=badge.name, mac=badge.mac, image=badge.render().decode('ascii'), ))
def post_get(request): key = request.META.get('HTTP_AUTHORIZATION', None) try: limit = int(request.GET.get('limit', None)) except ValueError: limit = 10 if key is None: raise AuthenticationError('No API key specified!') try: api_key = ApiKey.objects.get(key=key) except ApiKey.DoesNotExist: raise AuthenticationError('Invalid API key specified!') try: api_key.scopes.get(id=SCOPE_POSTS) except Scope.DoesNotExist: raise AuthenticationError('Invalid API key scope!') return ApiResponse(dict( posts=[ dict( sender=dict( id=post.sender.id, name=post.sender.name, ), content=post.content, ) for post in Post.objects.all().order_by('-created_at')[:limit] ], ))
def vote_get(request): key = request.META.get('HTTP_AUTHORIZATION', None) if key is None: raise AuthenticationError('No API key specified!') try: api_key = ApiKey.objects.get(key=key) except ApiKey.DoesNotExist: raise AuthenticationError('Invalid API key specified!') try: api_key.scopes.get(id=SCOPE_VOTES) except Scope.DoesNotExist: raise AuthenticationError('Invalid API key scope!') return ApiResponse(dict( votes=[ dict( talk=dict( id=talk.agenda_id, slug=talk.slug, ), **( lambda votes: dict( rating=statistics.mean(votes) if len(votes) > 0 else 0, ratings=len(votes), ) )([vote.rating for vote in Vote.objects.filter(talk=talk)]) ) for talk in Talk.objects.all() ], ))
def get_badge(request, raise_exception=True): badge_id = request.META.get('HTTP_X_ID', None) session_id = request.META.get('HTTP_AUTHORIZATION', None) if badge_id is not None: signature = request.META.get('HTTP_X_SIGNATURE', None) try: badge = Badge.objects.get(id=badge_id) except Badge.DoesNotExist: if raise_exception: raise AuthenticationError('Badge does not exist!') return None if not signature or bytes.fromhex( signature) != badge.calculate_signature(request): if raise_exception: raise AuthenticationError('Invalid signature!') return None return badge if session_id is not None: try: session = AuthCode.objects.get(id=session_id, long_lived=True) except AuthCode.DoesNotExist: if raise_exception: raise AuthenticationError('Invalid session!') return None return session.badge if raise_exception: raise AuthenticationError('Invalid request!') return None
def create_auth_code(self, badge: Badge, long_lived=False, after_delete=False): self.delete_expired() if AuthCode.objects.filter( long_lived=False, badge__id=badge.id).count() > settings.AUTHCODE_LIMIT: raise AuthenticationError( 'Badge has reached its limit for auth codes for the moment! Try again later.' ) try: auth_code = AuthCode.objects.create( id=uuid.uuid4() if long_lived else hex( random.getrandbits(4 * settings.AUTHCODE_LENGTH))[2:], badge=badge, long_lived=long_lived, ) auth_code.save() return auth_code except IntegrityError as ie: pass if after_delete: raise AuthenticationError('Could not create a AuthCode!') self.delete_expired() return self.create_authcode(badge, long_lived, True)
def auth(request): badge = utils.get_badge(request, False) token = request.JSON.get('auth', None) if badge is None and auth is None: raise AuthenticationError('Invalid request!', 404) if badge is not None: auth_code = AuthCode.objects.create_auth_code(badge) return ApiResponse(dict(token=auth_code.id)) if token is not None: session = AuthCode.objects.authenticate_auth_code(token) return ApiResponse(dict(token=session.id)) raise AuthenticationError('Invalid request!', 400)
def authenticate_auth_code(self, token): try: auth_code = super().get_queryset().get(id=token) except self.model.DoesNotExist: raise AuthenticationError("Invalid token.", 401) if auth_code.expired: raise AuthenticationError("Session expired.", 401) session = AuthCode.objects.create_auth_code(auth_code.badge, True) session.save() auth_code.delete() return session
def ota_update(request): badge = utils.get_badge(request, False) if not badge: raise AuthenticationError('Unknown badge!', 404) installed = request.JSON.get('versions', {}) logger.debug(','.join(['{}:{}'.format(key, installed[key]) for key in installed.keys()])) available = App.objects.values_list('name', flat=True).distinct() to_install = [] for app_name in available: app = App.objects.filter(name=app_name).order_by('-version')[0] try: version = int(installed.get(app.name, -1)) except TypeError: version = -1 if version < app.version: to_install.append(app) logger.debug(','.join(available)) if len(to_install) == 0: return ApiResponse('No updates available', 204) try: buffer = FileStream() result = tarfile.open(mode='w', fileobj=buffer) for app in to_install: SafeTar.add(result, path.join(settings.MEDIA_ROOT, app.extract_path(), app.name), app.name) response = HttpResponse(buffer.pop(), status=200, content_type='application/force-download') response['Content-Disposition'] = 'attachment; filename=update.tar' return response except Exception as e: pass return HttpResponse('Something went wrong!', status=500)
def export_all(request): key = request.META.get('HTTP_AUTHORIZATION', None) images = request.GET.get('images', None) is not None if key is None: raise AuthenticationError('No API key specified!') try: api_key = ApiKey.objects.get(key=key) except ApiKey.DoesNotExist: raise AuthenticationError('Invalid API key specified!') try: api_key.scopes.get(id=SCOPE_EXPORT) except Scope.DoesNotExist: raise AuthenticationError('Invalid API key scope!') return ApiResponse(dict( badges=[ dict( id=badge.id, name=badge.name, image=badge.render().decode('ascii') if images else None, ) for badge in Badge.objects.all() ], ))