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:
commit
79c2a3a484
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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'
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue