Disable access to artifact with different artifact type

Now it's possible to get artifact info by providing
different artifact type.
For example, if artifact art_1 has type images, then users can
access it by url /artifacts/heat_templates/art_1 and any other
enabled artifact type.
For sure it should be accessed only by its own type, or by
metatype like 'all'. In all other cases 404 code should be returned.

Change-Id: I6a6bac273572671ae50528b44fb9c39503851b87
Closes-bug: #1743969
(cherry picked from commit c2cbdf076e)
This commit is contained in:
Mike Fedosin 2018-01-24 15:40:53 +03:00
parent 0183c47f50
commit 9d30f3d709
6 changed files with 72 additions and 13 deletions

View File

@ -87,15 +87,16 @@ class ArtifactAPI(object):
@retry(retry_on_exception=_retry_on_connection_error, wait_fixed=1000,
stop_max_attempt_number=20)
def get(self, context, artifact_id):
def get(self, context, type_name, artifact_id):
"""Return artifact values from database
:param context: user context
:param type_name: artifact type name or None for metatypes
:param artifact_id: id of the artifact
:return: dict of artifact values
"""
session = api.get_session()
return api.get(context, artifact_id, session)
return api.get(context, type_name, artifact_id, session)
@retry(retry_on_exception=_retry_on_connection_error, wait_fixed=1000,
stop_max_attempt_number=20)

View File

@ -128,7 +128,7 @@ def create_or_update(context, artifact_id, values, session):
artifact.id = values.pop('id')
else:
# update the existing artifact
artifact = _get(context, artifact_id, session)
artifact = _get(context, None, artifact_id, session)
if 'version' in values:
values['version'] = semver_db.parse(values['version'])
@ -164,10 +164,12 @@ def create_or_update(context, artifact_id, values, session):
return artifact.to_dict()
def _get(context, artifact_id, session):
def _get(context, type_name, artifact_id, session):
try:
query = _do_artifacts_query(context, session).filter_by(
id=artifact_id)
if type_name is not None:
query = query.filter_by(type_name=type_name)
artifact = query.one()
except orm.exc.NoResultFound:
msg = _("Artifact with id=%s not found.") % artifact_id
@ -176,8 +178,8 @@ def _get(context, artifact_id, session):
return artifact
def get(context, artifact_id, session):
return _get(context, artifact_id, session).to_dict()
def get(context, type_name, artifact_id, session):
return _get(context, type_name, artifact_id, session).to_dict()
def get_all(context, session, filters=None, marker=None, limit=None,
@ -274,7 +276,7 @@ def _get_all(context, session, filters=None, marker=None, limit=None,
marker_artifact = None
if marker is not None:
marker_artifact = get(context, marker, session)
marker_artifact = get(context, None, marker, session)
query = _do_paginate_query(query=query, limit=limit,
marker=marker_artifact, sort=sort)

View File

@ -284,7 +284,11 @@ Possible values:
:param artifact_id: id of requested artifact
:return: requested artifact object
"""
af = cls.db_api.get(context, artifact_id)
if cls.get_type_name() != 'all':
type_name = cls.get_type_name()
else:
type_name = None
af = cls.db_api.get(context, type_name, artifact_id)
return cls.init_artifact(context, af)
@classmethod

View File

@ -155,7 +155,7 @@ class LinkFieldType(fields.FieldType):
) % {'link': value, 'field': field})
# try to find the referenced artifact
try:
obj.db_api.get(obj.obj_context, result[3])
obj.db_api.get(obj.obj_context, None, result[3])
except exception.NotFound:
raise ValueError(
_("Link %(link)s is not valid in field %(field)s, because "

View File

@ -157,7 +157,7 @@ class TestVisibility(base.TestArtifact):
art1 = self.create_artifact(data={'name': 'my_art', 'version': 1.0},
type_name='images')
art2 = self.create_artifact(data={'name': 'my_art', 'version': 1.0},
type_name='heat_templates')
type_name='sample_artifact')
# User 1 sees his 2 artifacts
url = '/all?name=my_art&version=1'
self.assertEqual(2, len(self.get(url=url)['all']))
@ -166,7 +166,7 @@ class TestVisibility(base.TestArtifact):
self.create_artifact(data={'name': 'my_art', 'version': 1.0},
type_name='images')
self.create_artifact(data={'name': 'my_art', 'version': 1.0},
type_name='heat_templates')
type_name='sample_artifact')
# User 2 sees his 2 artifacts
url = '/all?name=my_art&version=1'
self.assertEqual(2, len(self.get(url=url)['all']))
@ -176,8 +176,10 @@ class TestVisibility(base.TestArtifact):
self.assertEqual(4, len(self.get(url=url)['all']))
# After publishing art1 and art2 user 2 can see 4 artifacts as well
url = '/sample_artifact/%s' % art1['id']
patch = [{"op": "replace", "path": "/string_required", "value": "gg"}]
url = '/images/%s' % art1['id']
patch = [
{"op": "replace", "path": "/disk_format", "value": "iso"},
{"op": "replace", "path": "/container_format", "value": "bare"}]
self.patch(url=url, data=patch)
self.patch(url=url, data=self.make_active)
self.patch(url=url, data=self.make_public)

View File

@ -0,0 +1,50 @@
# Copyright 2017 - Red Hat
#
# 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 glare.common import exception as exc
from glare.tests.unit import base
class TestArtifactShow(base.BaseTestArtifactAPI):
def test_show_basic(self):
# Create an artifact and get its info back
vals = {'name': 'art1', 'version': '0.0.1', 'string_required': 'str1',
'int1': 5, 'float1': 5.0, 'bool1': 'yes'}
art = self.controller.create(self.req, 'sample_artifact', vals)
# Read info about created artifact
show_art = self.controller.show(self.req, 'sample_artifact', art['id'])
self.assertEqual(art, show_art)
# Test that the artifact is not accessible from other non-metatype type
self.assertRaises(exc.ArtifactNotFound,
self.controller.show, self.req, 'images', art['id'])
# Test that the artifact is accessible from 'all' metatype
show_art = self.controller.show(self.req, 'all', art['id'])
self.assertEqual(art['id'], show_art['id'])
def test_show_basic_negative(self):
# If there is no artifact with given id glare raises ArtifactNotFound
self.assertRaises(
exc.ArtifactNotFound,
self.controller.show, self.req, 'images', 'wrong_id')
# If there is no artifact type glare raises TypeNotFound
self.assertRaises(
exc.TypeNotFound,
self.controller.show, self.req, 'wrong_type', 'wrong_id')