Merge "Add some tests for checking private story behaviour"

This commit is contained in:
Zuul 2019-04-10 21:53:59 +00:00 committed by Gerrit Code Review
commit 363c64f47c
5 changed files with 220 additions and 37 deletions

View File

@ -36,6 +36,24 @@ class TestComments(base.FunctionalTest):
response = self.get_json(self.comments_resource % self.story_id)
self.assertEqual(0, len(response))
def test_comments_privacy(self):
url = '/stories/6/comments'
response = self.get_json(url, expect_errors=True)
self.assertEqual(200, response.status_code)
self.assertEqual(1, len(response.json))
# The user with token `valid_user_token` can't see the story, and
# so shouldn't be able to see the comment
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(url, headers=headers, expect_errors=True)
self.assertEqual(0, len(response.json))
# Unauthenticated users shouldn't be able to see anything in private
# stories
self.default_headers.pop('Authorization')
response = self.get_json(url, expect_errors=True)
self.assertEqual(0, len(response.json))
def test_create(self):
self.post_json(self.comments_resource % self.story_id, self.comment_01)
self.post_json(self.comments_resource % self.story_id, self.comment_02)

View File

@ -33,7 +33,29 @@ class TestStories(base.FunctionalTest):
def test_stories_endpoint(self):
response = self.get_json(self.resource)
self.assertEqual(5, len(response))
self.assertEqual(6, len(response))
def test_private_story_visibility(self):
url = self.resource + '/6'
story = self.get_json(url)
# User with token `valid_superuser_token` has permission to see
# the story, so should be able to get it without issue.
self.assertEqual(story['title'], 'Test Private Story')
self.assertTrue(story['private'])
self.assertEqual(1, len(story['users']))
self.assertEqual('Super User', story['users'][0]['full_name'])
self.assertEqual(0, len(story['teams']))
# User with token `valid_user_token` doesn't have permission
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(url, headers=headers, expect_errors=True)
self.assertEqual(404, response.status_code)
# Unauthenticated users shouldn't be able to see private stories
self.default_headers.pop('Authorization')
response = self.get_json(url, expect_errors=True)
self.assertEqual(404, response.status_code)
def test_create(self):
response = self.post_json(self.resource, self.story_01)
@ -62,22 +84,22 @@ class TestStories(base.FunctionalTest):
self.assertEqual(story['story_type_id'],
created_story['story_type_id'])
@unittest.skip("vulnerabilities are not supported.")
def test_create_private_vulnerability(self):
def test_create_private_story(self):
story = {
'title': 'StoryBoard',
'description': 'Awesome Task Tracker',
'story_type_id': 3
'private': True,
'users': [{'id': 1}]
}
response = self.post_json(self.resource, story)
created_story = response.json
self.assertEqual(story['title'], created_story['title'])
self.assertEqual(story['description'], created_story['description'])
self.assertEqual(story['story_type_id'],
created_story['story_type_id'])
self.assertEqual(story['private'],
created_story['private'])
@unittest.skip("vulnerabilities are not supported.")
@unittest.skip("public vulnerabilities are not supported.")
def test_create_public_vulnerability(self):
story = {
'title': 'StoryBoard',
@ -129,25 +151,31 @@ class TestStories(base.FunctionalTest):
{'story_type_id': story_type_id})
self.assertEqual(story_type_id, response.json['story_type_id'])
@unittest.skip("vulnerabilities are not supported.")
def test_update_private_to_public_vulnerability(self):
def test_update_private_to_public(self):
story = {
'title': 'StoryBoard',
'description': 'Awesome Task Tracker',
'story_type_id': 3
'private': True
}
response = self.post_json(self.resource, story)
created_story = response.json
self.assertEqual(story["story_type_id"],
created_story["story_type_id"])
self.assertEqual(story['private'],
created_story['private'])
response = self.put_json(self.resource +
('/%s' % created_story["id"]),
{'story_type_id': 4})
created_story = response.json
self.assertEqual(4, created_story['story_type_id'])
('/%s' % created_story['id']),
{'private': False})
updated_story = response.json
self.assertFalse(updated_story['private'])
# Check that a different user can see the story
headers = {'Authorization': 'Bearer valid_user_token'}
api_story = self.get_json(self.resource + '/%s' % created_story['id'],
headers=headers)
self.assertEqual(story['title'], api_story['title'])
self.assertEqual(story['description'], api_story['description'])
def test_update_restricted_branches(self):
response = self.put_json(self.resource + '/1', {'story_type_id': 2},

View File

@ -107,7 +107,34 @@ class TestTasksPrimary(base.FunctionalTest):
def test_tasks_endpoint(self):
response = self.get_json(self.resource)
self.assertEqual(5, len(response))
# Check that tasks in private stories are correctly filtered
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(self.resource, headers=headers)
self.assertEqual(4, len(response))
self.default_headers.pop('Authorization')
response = self.get_json(self.resource)
self.assertEqual(4, len(response))
def test_private_task_visibility(self):
url = self.resource + '/5'
# Task with id 5 is in a private story which the user with token
# `valid_superuser_token` can see
response = self.get_json(url)
self.assertEqual('Task in private story', response['title'])
# The user with token `valid_user_token` can't see the story, and
# so shouldn't be able to see the task
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(url, headers=headers, expect_errors=True)
self.assertEqual(404, response.status_code)
# Unauthenticated users shouldn't be able to see anything in private
# stories
self.default_headers.pop('Authorization')
response = self.get_json(url, expect_errors=True)
self.assertEqual(404, response.status_code)
def test_create(self):
result = self.post_json(self.resource, self.task_01)
@ -274,6 +301,38 @@ class TestTasksNestedController(base.FunctionalTest):
self.assertEqual(400, response.status_code)
def test_tasks_endpoint_privacy(self):
self.resource = '/stories/6/tasks'
response = self.get_json(self.resource)
self.assertEqual(1, len(response))
# Check that tasks in private stories are correctly filtered
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(self.resource, headers=headers)
self.assertEqual(0, len(response))
self.default_headers.pop('Authorization')
response = self.get_json(self.resource)
self.assertEqual(0, len(response))
def test_private_task_visibility(self):
url = '/stories/6/tasks/5'
# Task with id 5 is in a private story which the user with token
# `valid_superuser_token` can see
response = self.get_json(url)
self.assertEqual('Task in private story', response['title'])
# The user with token `valid_user_token` can't see the story, and
# so shouldn't be able to see the task
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(url, headers=headers, expect_errors=True)
self.assertEqual(404, response.status_code)
# Unauthenticated users shouldn't be able to see anything in private
# stories
self.default_headers.pop('Authorization')
response = self.get_json(url, expect_errors=True)
self.assertEqual(404, response.status_code)
def test_create(self):
result = self.post_json(self.resource, {
'title': 'StoryBoard',

View File

@ -18,6 +18,10 @@ from storyboard.tests import base
class TestTimelineEvents(base.FunctionalTest):
def setUp(self):
super(TestTimelineEvents, self).setUp()
self.default_headers['Authorization'] = 'Bearer valid_superuser_token'
def test_get_all_events(self):
"""Assert that we can retrieve a list of events from a story."""
@ -27,6 +31,26 @@ class TestTimelineEvents(base.FunctionalTest):
self.assertEqual(200, response.status_code)
self.assertEqual(3, len(response.json))
def test_get_all_events_privacy(self):
"""Assert that events for private stories are access controlled."""
url = '/stories/6/events'
response = self.get_json(url, expect_errors=True)
self.assertEqual(200, response.status_code)
self.assertEqual(2, len(response.json))
# The user with token `valid_user_token` can't see the story, and
# so shouldn't be able to see the events
headers = {'Authorization': 'Bearer valid_user_token'}
response = self.get_json(url, headers=headers, expect_errors=True)
self.assertEqual(0, len(response.json))
# Unauthenticated users shouldn't be able to see anything in private
# stories
self.default_headers.pop('Authorization')
response = self.get_json(url, expect_errors=True)
self.assertEqual(0, len(response.json))
def test_filter_by_event_type(self):
"""Assert that we can correctly filter an event by event type."""
response = self.get_json('/stories/1/events?event_type=story_created'

View File

@ -21,6 +21,7 @@ from storyboard.db.models import AccessToken
from storyboard.db.models import Branch
from storyboard.db.models import Comment
from storyboard.db.models import Milestone
from storyboard.db.models import Permission
from storyboard.db.models import Project
from storyboard.db.models import ProjectGroup
from storyboard.db.models import Story
@ -36,6 +37,7 @@ def load():
"""Load a batch of useful data into the database that our tests can work
with.
"""
session = db.get_session(autocommit=False, in_request=False)
now = datetime.datetime.now(tz=pytz.utc)
expires_at = now + datetime.timedelta(seconds=3600)
expired_at = now + datetime.timedelta(seconds=-3600)
@ -57,7 +59,8 @@ def load():
openid='otheruser_openid',
full_name='Other User',
is_superuser=False)
])
], session)
users = session.query(User).all()
# Load some preferences for the above users.
load_data([
@ -86,7 +89,7 @@ def load():
key='plugin_email_digest',
value='False',
type='bool'),
])
], session)
# Load a variety of sensibly named access tokens.
load_data([
@ -110,7 +113,7 @@ def load():
access_token='expired_user_token',
expires_in=3600,
expires_at=expired_at)
])
], session)
# Create some test projects.
projects = load_data([
@ -126,7 +129,7 @@ def load():
id=3,
name='tests/project3',
description='Project 1 Description - foo')
])
], session)
# Create some test project groups.
load_data([
@ -153,7 +156,17 @@ def load():
name='projectgroup3',
title='A Sort - foo'
)
])
], session)
# Create some permissions
load_data([
Permission(
name='view_story_6',
codename='view_story',
users=[users[0]]
)
], session)
permissions = session.query(Permission).all()
# Create some stories.
load_data([
@ -181,8 +194,15 @@ def load():
id=5,
title="A Test story 5 - oh hai",
description="Test Description - oh hai"
),
Story(
id=6,
title="Test Private Story",
description="For Super User's eyes only",
private=True,
permissions=[permissions[0]]
)
])
], session)
# Create some tasks
load_data([
@ -229,8 +249,19 @@ def load():
branch_id=2,
assignee_id=1,
priority='medium'
),
Task(
id=5,
creator_id=1,
title='Task in private story',
status='todo',
story_id=6,
project_id=2,
branch_id=2,
assignee_id=1,
priority='medium'
)
])
], session)
# Generate some timeline events for the above stories.
load_data([
@ -280,28 +311,48 @@ def load():
'"old_assignee_id": null, '
'"task_id": 1, '
'"new_assignee_id": 2}'
),
TimeLineEvent(
id=7,
story_id=6,
author_id=1,
event_type=event.STORY_CREATED,
event_info='{"story_id": 6, '
'"story_title": "Test Private Story"}'
)
])
], session)
# Create a comment.
# Create some comments.
load_data([
Comment(
id=1,
content="Test Comment",
is_active=True
),
Comment(
id=2,
content="Comment on a private story",
is_active=True
)
])
], session)
# Create a timeline event for the above comment.
# Create timeline events for the above comments.
load_data([
TimeLineEvent(
id=7,
id=8,
story_id=1,
comment_id=1,
author_id=1,
event_type=event.USER_COMMENT
),
TimeLineEvent(
id=9,
story_id=6,
comment_id=2,
author_id=1,
event_type=event.USER_COMMENT
)
])
], session)
# Load some subscriptions.
load_data([
@ -323,7 +374,7 @@ def load():
target_type='story',
target_id=1
),
])
], session)
# Load some branches
load_data([
@ -345,7 +396,7 @@ def load():
name='master',
restricted=True
)
])
], session)
# Load some milestones
load_data([
@ -359,27 +410,30 @@ def load():
name='test_milestone_02',
branch_id=2
)
])
], session)
# Load some teams
load_data([
Team(
id=1,
name='test_team_1'
name='test_team_1',
users=[users[0]]
),
Team(
id=2,
name='test_team_2'
name='test_team_2',
users=users[1:]
)
])
], session)
def load_data(data):
def load_data(data, session=None):
"""Pre load test data into the database.
:param data An iterable collection of database models.
"""
session = db.get_session(autocommit=False, in_request=False)
if session is None:
session = db.get_session(autocommit=False, in_request=False)
for entity in data:
session.add(entity)