diff --git a/storyboard/api/v1/attachments.py b/storyboard/api/v1/attachments.py index 50b853ae..a8656be3 100644 --- a/storyboard/api/v1/attachments.py +++ b/storyboard/api/v1/attachments.py @@ -14,14 +14,20 @@ # limitations under the License. from oslo_config import cfg +from pecan import request from pecan import response from pecan import rest from pecan.secure import secure from wsme import types as wtypes import wsmeext.pecan as wsme_pecan +from storyboard._i18n import _ from storyboard.api.auth import authorization_checks as checks from storyboard.api.v1.storage import storage +from storyboard.api.v1 import wmodels +from storyboard.common import decorators +from storyboard.common import exception as exc +from storyboard.db.api import attachments as attachments_api CONF = cfg.CONF @@ -54,3 +60,50 @@ class AttachmentsController(rest.RestController): response.headers['X-Object-Name'] = name return STORAGE_BACKEND.get_upload_url() + + @decorators.db_exceptions + @secure(checks.guest) + @wsme_pecan.wsexpose(wmodels.Attachment, int, int) + def get_one(self, story_id, attachment_id): + """Retrieve details about a single attachment. + + Example:: + + curl https://my.example.org/api/v1/stories/1/attachments/1 + + :param story_id: ID of the story which has the attachment. + :param attachment_id: ID of the attachment to retrieve details + about. + + """ + attachment = attachments_api.get_by_id( + attachment_id, current_user=request.current_user_id) + + if attachment: + return wmodels.Attachment.from_db_model(attachment) + raise exc.NotFound(_("Attachment %s not found") % attachment_id) + + @decorators.db_exceptions + @secure(checks.guest) + @wsme_pecan.wsexpose([wmodels.Attachment], int) + def get_all(self, story_id): + """Retrieve details about all attachments for a given story. + + Example:: + + curl https://my.example.org/api/v1/stories/1/attachments + + :param story_id: ID of the story to view attachments of. + + """ + attachments = attachments_api.get_all( + story_id=story_id, + current_user=request.current_user_id + ) + attachment_count = attachments_api.get_count( + story_id=story_id, + current_user=request.current_user_id + ) + + response.headers['X-Total'] = str(attachment_count) + return [wmodels.Attachment.from_db_model(a) for a in attachments] diff --git a/storyboard/db/api/attachments.py b/storyboard/db/api/attachments.py new file mode 100644 index 00000000..4e317cb5 --- /dev/null +++ b/storyboard/db/api/attachments.py @@ -0,0 +1,53 @@ +# Copyright (c) 2019 Adam Coldrick +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from storyboard.db.api import base as api_base +from storyboard.db import models + + +def get_by_id(attachment_id, current_user=None, session=None): + query = api_base.model_query(models.Attachment, session=session) + query = query.filter(models.Attachment.id == attachment_id) + + # Filter out attachments related to stories that the current user lacks + # permissions to see + query = query.join(models.Story) + query = api_base.filter_private_stories(query, current_user) + + return query.first() + + +def _build_query(current_user=None, session=None, **kwargs): + query = api_base.model_query(models.Attachment, session=session) + query = api_base.apply_query_filters(query=query, + model=models.Attachment, + **kwargs) + + # Filter out attachments related to stories that the current user lacks + # permissions to see + query = query.join(models.Story) + query = api_base.filter_private_stories(query, current_user) + + return query + + +def get_all(current_user=None, session=None, **kwargs): + query = _build_query(current_user=current_user, session=session, **kwargs) + return query.all() + + +def get_count(current_user=None, session=None, **kwargs): + query = _build_query(current_user=current_user, session=session, **kwargs) + return query.count()