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:
parent
0183c47f50
commit
9d30f3d709
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
Loading…
Reference in New Issue