Skip to content

Commit

Permalink
Merge pull request #19 from photos-network/feature/user_management
Browse files Browse the repository at this point in the history
Feature/user management
  • Loading branch information
thebino authored Apr 28, 2021
2 parents cade920 + c3d09c9 commit fccb403
Show file tree
Hide file tree
Showing 18 changed files with 672 additions and 185 deletions.
16 changes: 16 additions & 0 deletions core/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,22 @@ async def async_setup_addon(

return True

async def read(self, key):
"""read key/value pair from addon."""
try:
component = importlib.import_module(f"core.addons.{self.domain}")
except ImportError as err:
_LOGGER.error(f"Unable to import addon '{self.domain}': {err}")
return False
except Exception: # pylint: disable=broad-except
_LOGGER.exception(f"Setup failed for {self.domain}: unknown error")
return False

if hasattr(component, "read"):
await component.read(self.core, key)
else:
_LOGGER.error(f"Unable to read key from addon '{self.domain}'")

async def async_process_images_in_addons(self, images) -> bool:
"""Trigger image addons with images to process."""
if self.type == AddonType.IMAGE:
Expand Down
72 changes: 46 additions & 26 deletions core/addons/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import os
import pathlib
from datetime import datetime
from typing import Optional

from aiohttp import web

from core.addons.api.dto.details import Details
from core.addons.api.dto.location import Location
from core.addons.api.dto.photo import (PhotoDetailsResponse, PhotoEncoder,
PhotoResponse)
from core.addons.api.dto.photo import PhotoDetailsResponse, PhotoEncoder, PhotoResponse
from core.addons.api.dto.photo_response import PhotosResponse
from core.base import Session
from core.core import ApplicationCore
Expand Down Expand Up @@ -63,7 +62,7 @@ class PhotosView(RequestView):

async def get(self, core: ApplicationCore, request: web.Request) -> web.Response:
"""Get a list of all photo resources."""
_LOGGER.debug(f"GET /v1/photos")
_LOGGER.debug("GET /v1/photos")
await core.authentication.check_permission(request, "library:read")

user_id = await core.http.get_user_id(request)
Expand All @@ -79,7 +78,9 @@ async def get(self, core: ApplicationCore, request: web.Request) -> web.Response
if "offset" in request.query:
offset = int(request.query["offset"])

_LOGGER.debug(f"read {limit} photos for user_id {user_id} beginning with {offset}")
_LOGGER.debug(
f"read {limit} photos for user_id {user_id} beginning with {offset}"
)
user_photos = await core.storage.read_photos(user_id, offset, limit)

results = []
Expand All @@ -89,12 +90,16 @@ async def get(self, core: ApplicationCore, request: web.Request) -> web.Response
PhotoResponse(
id=photo.uuid,
name=photo.filename,
image_url=f"{core.config.external_url}/v1/file/{photo.uuid}"
image_url=f"{core.config.external_url}/v1/file/{photo.uuid}",
)
)

response = PhotosResponse(offset=offset, limit=limit, size=len(results), results=results)
return web.Response(text=json.dumps(response, cls=PhotoEncoder), content_type="application/json")
response = PhotosResponse(
offset=offset, limit=limit, size=len(results), results=results
)
return web.Response(
text=json.dumps(response, cls=PhotoEncoder), content_type="application/json"
)


class PhotoDetailsView(RequestView):
Expand All @@ -103,7 +108,9 @@ class PhotoDetailsView(RequestView):
url = "/v1/photo/{entity_id}"
name = "v1:photo"

async def get(self, core: ApplicationCore, request: web.Request, entity_id: str) -> web.Response:
async def get(
self, core: ApplicationCore, request: web.Request, entity_id: str
) -> web.Response:
"""Return an entity."""
_LOGGER.debug(f"GET /v1/photo/{entity_id}")

Expand Down Expand Up @@ -133,31 +140,38 @@ async def get(self, core: ApplicationCore, request: web.Request, entity_id: str)
if latitude is not None and longitude is not None:
altitude = await core.storage.read("altitude")
if altitude is not None:
location = Location(latitude=latitude, longitude=longitude, altitude=altitude)
location = Location(
latitude=latitude, longitude=longitude, altitude=altitude
)
else:
location = Location(latitude=latitude, longitude=longitude, altitude="0.0")
location = Location(
latitude=latitude, longitude=longitude, altitude="0.0"
)

# photo tags
tags = await core.storage.read("tags")

result = PhotoDetailsResponse(
id=photo.uuid,
name=photo.filename,
author=photo.owner,
owner=photo.owner,
created_at=ctime.isoformat(),
modified_at=mtime.isoformat(),
details=Details(
camera="Nikon Z7",
lens="Nikkor 200mm F1.8",
focal_length="200",
iso="400",
shutter_speed="1/2000",
aperture="4.0",
camera="Nikon Z7",
lens="Nikkor 200mm F1.8",
focal_length="200",
iso="400",
shutter_speed="1/2000",
aperture="4.0",
),
tags=tags,
location=location,
image_url=f"{core.config.external_url}/v1/file/{entity_id}"
image_url=f"{core.config.external_url}/v1/file/{entity_id}",
)
return web.Response(
text=json.dumps(result, cls=PhotoEncoder), content_type="application/json"
)
return web.Response(text=json.dumps(result, cls=PhotoEncoder), content_type="application/json")


class PhotoView(RequestView):
Expand All @@ -168,7 +182,9 @@ class PhotoView(RequestView):
url = "/v1/file/{entity_id}"
name = "v1:file"

async def get(self, core: ApplicationCore, request: web.Request, entity_id: str) -> web.Response:
async def get(
self, core: ApplicationCore, request: web.Request, entity_id: str
) -> web.Response:
"""Return an entity."""
_LOGGER.debug(f"GET /v1/file/{entity_id}")

Expand All @@ -179,10 +195,12 @@ async def get(self, core: ApplicationCore, request: web.Request, entity_id: str)
# -d remove exif data

result = Session.query(Photo).filter(Photo.uuid == entity_id).first()

file = os.path.join(result.directory, result.filename)
if os.path.exists(os.path.join(file)):
return web.FileResponse(path=file, status=200)
if result:
file = os.path.join(result.directory, result.filename)
if os.path.exists(os.path.join(file)):
return web.FileResponse(path=file, status=200)
else:
raise web.HTTPNotFound()
else:
raise web.HTTPNotFound()

Expand Down Expand Up @@ -224,7 +242,9 @@ async def post(self, core: ApplicationCore, request: web.Request) -> web.Respons

status_code = HTTP_CREATED if new_entity_created else HTTP_OK

resp = self.json_message(f"File successfully added with ID: {new_entity_id}", status_code)
resp = self.json_message(
f"File successfully added with ID: {new_entity_id}", status_code
)
resp.headers.add("Location", f"/api/photo/{new_entity_id}")

return resp
Expand Down
17 changes: 13 additions & 4 deletions core/addons/api/dto/photo.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ def default(self, o):
"""Encode all properties."""
return o.__dict__


class PhotoResponse:
"""Photo response object."""

def __init__(
self, id, name, image_url
):
def __init__(self, id, name, image_url):
"""Initialize photo response object."""
self.id = id
self.name = name
Expand All @@ -25,13 +24,23 @@ class PhotoDetailsResponse:
"""Photo response object."""

def __init__(
self, id, name, owner, created_at, details, tags, location, image_url
self,
id,
name,
owner,
created_at,
modified_at,
details,
tags,
location,
image_url,
):
"""Initialize photo response object."""
self.id = id
self.name = name
self.owner = owner
self.created_at = created_at
self.modified_at = modified_at
self.details = details
self.tags = tags
self.location = location
Expand Down
Loading

0 comments on commit fccb403

Please sign in to comment.