Merge "Add some tests for checking private story behaviour"
This commit is contained in:
commit
363c64f47c
@ -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)
|
||||
|
@ -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},
|
||||
|
@ -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',
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user