Merged in issue-30-add-api-support-for-site-manipulation (pull request #15)

Issue 30 add api support for site manipulation
This commit is contained in:
Dorian Pula 2016-12-21 09:04:59 -05:00
commit 79c2a3a484
6 changed files with 197 additions and 28 deletions

View File

@ -2,6 +2,8 @@
Changelog
=========
* :feature:`30` Add support to create, modify and delete sites, menus and pages via API.
* :feature:`30` Link pages to individual sites.
* :support:`0` Convert rote build infrastructure to use simpler Makefile and scripts setup.
* :support:`28` Make invoke the main entry point for everything in the API server.
* :bug:`24` Enable upgrade to the latest version of Flask, by fixing the way exception handlers are registered.

View File

@ -15,10 +15,14 @@ def pytest_addoption(parser):
@pytest.fixture
def server_hostname(request):
return request.config.getoption("--server-hostname")
def api_base_uri(request):
"""
The base URI of the API server to build request to API. The base URI is the format http://hostname:port, provided
by the server hostname and server port pytest parameters.
@pytest.fixture
def server_port(request):
return request.config.getoption("--server-port")
:param request: The request for the test.
:return: The base URI of the API server.
"""
server_hostname = request.config.getoption("--server-hostname")
server_port = request.config.getoption("--server-port")
return "http://{hostname}:{port}".format(hostname=server_hostname, port=server_port)

View File

@ -0,0 +1,58 @@
Feature: Site Management
The site endpoints allows an app admin user to create, modify and delete sites.
Scenario: Admin user can create a new site
Given I am an admin user
When I create a site
Then I get a valid site
And I get a valid site menu
Scenario: Editor user can not create a new site
Given I am an editor user
When I create a site
Then I get an unauthorized response
Scenario: Any user can get an existing site
Given I am an unauthenticated user
When I get an existing site
Then I get a valid site
And I get a valid site menu
Scenario: Admin user can modify a site
Given I am an admin user
When I get an existing site
And I modify the site
Then my updates are reflected in the site
And I get a valid site menu
Scenario: Admin user can modify a site's menu
Given I am an admin user
When I get an existing site menu
And I modify the site menu
Then my updates are reflected in the site menu
Scenario: Editor user can not modify a site
Given I am an editor user
When I get an existing site
And I modify the site
Then I get an unauthorized response
Scenario: Editor user can not modify a site's menu
Given I am an editor user
When I get an existing site menu
And I modify the site menu
Then I get an unauthorized response
Scenario: Admin user can delete a site
Given I am an admin user
When I get an existing site
And I delete the site
Then I get an error that the site is missing
And I get an error that the site menu is missing
Scenario: Editor user can not delete a site
Given I am an editor user
When I get an existing site
And I delete the site
Then I get an unauthorized response

View File

@ -0,0 +1,99 @@
"""
Functional tests for the managing sites.
:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""
import http
from pytest import mark
import pytest_bdd as bdd
from pytest_bdd import parsers
import requests
# TODO: Figure out how to generate a JWT using the correct hash.
USER_ROLE_JWT_MAPPING = {
'admin': 'password',
'editor': 'some_other_login',
}
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Admin user can create a new site')
def test_site_creation_by_admin():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Editor user can not create a new site')
def test_site_creation_permissions_for_editor():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Any user can get an existing site')
def test_site_fetch():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Admin user can modify a site')
def test_site_modification_by_admin():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Editor user can not modify a site')
def test_site_modifications_permissions_for_editor():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Admin user can modify a site\'s menu')
def test_site_menu_modification_by_admin():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Editor user can not modify a site\'s menu')
def test_site_menu_modifications_permissions_for_editor():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Admin user can delete a site')
def test_site_deletion_by_admin():
pass
@mark.skip(reason="Test scenarios need work")
@bdd.scenario('site_management.feature', 'Editor user can not delete a site')
def test_site_deletion_permissions_for_editor():
pass
@bdd.given(parsers.parse('I am an {user_role} user'))
def user_credentials(user_role):
return USER_ROLE_JWT_MAPPING[user_role]
@bdd.when('I create a site')
def posted_response_from_auth_endpoint(user_credentials, api_base_uri):
# TODO: Needs work
response = requests.post("{}/auth".format(api_base_uri), json={
'username': user_credentials.username,
'password': user_credentials.password,
})
user_credentials.response['status'] = response.status_code
user_credentials.response['json'] = response.json()
@bdd.then('I get an unauthorized response')
def assert_unauthorized_response(user_credentials):
# TODO: Needs work
assert user_credentials.response['status'] == http.HTTPStatus.UNAUTHORIZED
assert user_credentials.response['json']['status_code'] == http.HTTPStatus.UNAUTHORIZED
assert user_credentials.response['json']['error'] == 'Bad Request'
assert user_credentials.response['json']['description'] == 'Invalid credentials'

View File

@ -1,5 +1,5 @@
"""
Feature tests for the user authentication feature.
Functional tests for the user authentication feature.
:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
@ -8,48 +8,51 @@ Feature tests for the user authentication feature.
import collections
import http
import jwt
import pytest_bdd as bdd
from pytest_bdd import parsers
import requests
TEST_USERS = {
'admin': {
'correct': 'password',
'incorrect': '123',
'valid': {
'valid': 'password',
'invalid': '123',
},
'non-registered': {'correct': 'loging'},
'invalid': {'some': 'login'},
}
Credentials = collections.namedtuple('Credentials', ['username', 'password', 'response'])
@bdd.scenario('user_authentication.feature', 'Allowed admin user can authenticate against site')
@bdd.scenario('user_authentication.feature', 'Valid user can authenticate against site with valid credentials')
def test_authentication_with_valid_credentials():
pass
@bdd.scenario('user_authentication.feature', 'Allowed admin user cannot authenticate against site with bad credentials')
@bdd.scenario('user_authentication.feature', 'Valid user cannot authenticate against site with invalid credentials')
def test_authentication_with_invalid_credentials():
pass
@bdd.scenario('user_authentication.feature', 'Non-register user cannot authenticate against site with credentials')
@bdd.scenario('user_authentication.feature', 'Invalid user cannot authenticate against site with credentials')
def test_authentication_with_invalid_user():
pass
@bdd.given(parsers.parse('I am the {user_name} user with the {login_type} credentials'))
def user_credentials(user_name, login_type):
password = TEST_USERS.get(user_name, {}).get(login_type, '')
@bdd.given(parsers.parse('I am a {user_type} user with {login_type} credentials'))
def user_credentials(user_type, login_type):
user_name = 'random_user'
if user_type == 'valid':
user_name = 'admin'
password = TEST_USERS.get(user_type, {}).get(login_type, '')
return Credentials(username=user_name, password=password, response={})
@bdd.when('I post my credentials against the auth endpoint')
def posted_response_from_auth_endpoint(user_credentials, server_hostname, server_port):
uri_base = "http://{}:{}".format(server_hostname, server_port)
response = requests.post("{}/auth".format(uri_base), json={
def posted_response_from_auth_endpoint(user_credentials, api_base_uri):
response = requests.post("{}/auth".format(api_base_uri), json={
'username': user_credentials.username,
'password': user_credentials.password,
})
@ -61,15 +64,18 @@ def posted_response_from_auth_endpoint(user_credentials, server_hostname, server
def assert_valid_user_json_web_token(user_credentials):
assert user_credentials.response['status'] == http.HTTPStatus.OK
assert user_credentials.response['json']['token'] is not None
jwt_token = user_credentials.response['json']['token']
assert jwt_token is not None
validated_user_credentials = user_credentials.response['json']['user']
assert user_credentials.username == validated_user_credentials.get('username')
decoded_jwt = jwt.decode(jwt_token, verify=False)
assert 'identity' in decoded_jwt
@bdd.then('I get an unauthorized response')
def assert_unauthorized_response(user_credentials):
assert user_credentials.response['status'] == http.HTTPStatus.UNAUTHORIZED
assert user_credentials.response['json']['status_code'] == http.HTTPStatus.UNAUTHORIZED
assert user_credentials.response['json']['error'] == 'Bad Request'
assert user_credentials.response['json']['description'] == 'Invalid credentials'

View File

@ -2,19 +2,19 @@ Feature: User Authentication
The user endpoint allows user to authenticate against the system
Scenario: Allowed admin user can authenticate against site
Given I am the admin user with the correct credentials
Scenario: Valid user can authenticate against site with valid credentials
Given I am a valid user with valid credentials
When I post my credentials against the auth endpoint
Then I get a valid JWT
Scenario: Allowed admin user cannot authenticate against site with bad credentials
Given I am the admin user with the wrong credentials
Scenario: Valid user cannot authenticate against site with invalid credentials
Given I am a valid user with invalid credentials
When I post my credentials against the auth endpoint
Then I get an unauthorized response
Scenario: Non-register user cannot authenticate against site with credentials
Given I am the non-registered user with the correct credentials
Scenario: Invalid user cannot authenticate against site with credentials
Given I am a invalid user with some credentials
When I post my credentials against the auth endpoint
Then I get an unauthorized response