Access camera images using access token
This commit is contained in:
parent
585fbb1c02
commit
fe794d7fd8
2 changed files with 35 additions and 18 deletions
|
@ -52,6 +52,11 @@ class Camera(Entity):
|
||||||
"""Initialize a camera."""
|
"""Initialize a camera."""
|
||||||
self.is_streaming = False
|
self.is_streaming = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def access_token(self):
|
||||||
|
"""Access token for this camera."""
|
||||||
|
return str(id(self))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
"""No need to poll cameras."""
|
"""No need to poll cameras."""
|
||||||
|
@ -124,7 +129,9 @@ class Camera(Entity):
|
||||||
@property
|
@property
|
||||||
def state_attributes(self):
|
def state_attributes(self):
|
||||||
"""Camera state attributes."""
|
"""Camera state attributes."""
|
||||||
attr = {}
|
attr = {
|
||||||
|
'access_token': self.access_token,
|
||||||
|
}
|
||||||
|
|
||||||
if self.model:
|
if self.model:
|
||||||
attr['model_name'] = self.model
|
attr['model_name'] = self.model
|
||||||
|
@ -138,11 +145,32 @@ class Camera(Entity):
|
||||||
class CameraView(HomeAssistantView):
|
class CameraView(HomeAssistantView):
|
||||||
"""Base CameraView."""
|
"""Base CameraView."""
|
||||||
|
|
||||||
|
requires_auth = False
|
||||||
|
|
||||||
def __init__(self, hass, entities):
|
def __init__(self, hass, entities):
|
||||||
"""Initialize a basic camera view."""
|
"""Initialize a basic camera view."""
|
||||||
super().__init__(hass)
|
super().__init__(hass)
|
||||||
self.entities = entities
|
self.entities = entities
|
||||||
|
|
||||||
|
def get(self, request, entity_id):
|
||||||
|
"""Start a get request."""
|
||||||
|
camera = self.entities.get(entity_id)
|
||||||
|
|
||||||
|
if camera is None:
|
||||||
|
return self.Response(status=404)
|
||||||
|
|
||||||
|
authenticated = (request.authenticated or
|
||||||
|
request.args.get('token') == camera.access_token)
|
||||||
|
|
||||||
|
if not authenticated:
|
||||||
|
return self.Response(status=401)
|
||||||
|
|
||||||
|
return self.handle(camera)
|
||||||
|
|
||||||
|
def handle(self, camera):
|
||||||
|
"""Hanlde the camera request."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class CameraImageView(CameraView):
|
class CameraImageView(CameraView):
|
||||||
"""Camera view to serve an image."""
|
"""Camera view to serve an image."""
|
||||||
|
@ -150,13 +178,8 @@ class CameraImageView(CameraView):
|
||||||
url = "/api/camera_proxy/<entity(domain=camera):entity_id>"
|
url = "/api/camera_proxy/<entity(domain=camera):entity_id>"
|
||||||
name = "api:camera:image"
|
name = "api:camera:image"
|
||||||
|
|
||||||
def get(self, request, entity_id):
|
def handle(self, camera):
|
||||||
"""Serve camera image."""
|
"""Serve camera image."""
|
||||||
camera = self.entities.get(entity_id)
|
|
||||||
|
|
||||||
if camera is None:
|
|
||||||
return self.Response(status=404)
|
|
||||||
|
|
||||||
response = camera.camera_image()
|
response = camera.camera_image()
|
||||||
|
|
||||||
if response is None:
|
if response is None:
|
||||||
|
@ -171,11 +194,6 @@ class CameraMjpegStream(CameraView):
|
||||||
url = "/api/camera_proxy_stream/<entity(domain=camera):entity_id>"
|
url = "/api/camera_proxy_stream/<entity(domain=camera):entity_id>"
|
||||||
name = "api:camera:stream"
|
name = "api:camera:stream"
|
||||||
|
|
||||||
def get(self, request, entity_id):
|
def handle(self, camera):
|
||||||
"""Serve camera image."""
|
"""Serve camera image."""
|
||||||
camera = self.entities.get(entity_id)
|
|
||||||
|
|
||||||
if camera is None:
|
|
||||||
return self.Response(status=404)
|
|
||||||
|
|
||||||
return camera.mjpeg_stream(self.Response())
|
return camera.mjpeg_stream(self.Response())
|
||||||
|
|
|
@ -339,10 +339,7 @@ class HomeAssistantView(object):
|
||||||
# Auth code verbose on purpose
|
# Auth code verbose on purpose
|
||||||
authenticated = False
|
authenticated = False
|
||||||
|
|
||||||
if not self.requires_auth:
|
if self.hass.wsgi.api_password is None:
|
||||||
authenticated = True
|
|
||||||
|
|
||||||
elif self.hass.wsgi.api_password is None:
|
|
||||||
authenticated = True
|
authenticated = True
|
||||||
|
|
||||||
elif hmac.compare_digest(request.headers.get(HTTP_HEADER_HA_AUTH, ''),
|
elif hmac.compare_digest(request.headers.get(HTTP_HEADER_HA_AUTH, ''),
|
||||||
|
@ -366,9 +363,11 @@ class HomeAssistantView(object):
|
||||||
except BadRequest:
|
except BadRequest:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not authenticated:
|
if self.requires_auth and not authenticated:
|
||||||
raise Unauthorized()
|
raise Unauthorized()
|
||||||
|
|
||||||
|
request.authenticated = authenticated
|
||||||
|
|
||||||
result = handler(request, **values)
|
result = handler(request, **values)
|
||||||
|
|
||||||
if isinstance(result, self.Response):
|
if isinstance(result, self.Response):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue