forked from platypush/platypush
Fixed and expanded integration tests to deal with HTTP user authentication
This commit is contained in:
parent
049a48e156
commit
e5c8adfc1b
3 changed files with 86 additions and 22 deletions
|
@ -1,7 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from flask import Blueprint, request, redirect, render_template, make_response, url_for
|
from flask import Blueprint, request, redirect, render_template, make_response, abort
|
||||||
|
|
||||||
from platypush.backend.http.app import template_folder
|
from platypush.backend.http.app import template_folder
|
||||||
from platypush.backend.http.utils import HttpUtils
|
from platypush.backend.http.utils import HttpUtils
|
||||||
|
@ -33,6 +33,9 @@ def register():
|
||||||
if user:
|
if user:
|
||||||
return redirect(redirect_page, 302)
|
return redirect(redirect_page, 302)
|
||||||
|
|
||||||
|
if user_manager.get_user_count() > 0:
|
||||||
|
return redirect('/login?redirect=' + redirect_page, 302)
|
||||||
|
|
||||||
if request.form:
|
if request.form:
|
||||||
username = request.form.get('username')
|
username = request.form.get('username')
|
||||||
password = request.form.get('password')
|
password = request.form.get('password')
|
||||||
|
@ -50,9 +53,8 @@ def register():
|
||||||
response = make_response(redirect_target)
|
response = make_response(redirect_target)
|
||||||
response.set_cookie('session_token', session.session_token)
|
response.set_cookie('session_token', session.session_token)
|
||||||
return response
|
return response
|
||||||
|
else:
|
||||||
if user_manager.get_user_count() > 0:
|
abort(400, 'Password mismatch')
|
||||||
return redirect('/login?redirect=' + redirect_page, 302)
|
|
||||||
|
|
||||||
return render_template('index.html', utils=HttpUtils)
|
return render_template('index.html', utils=HttpUtils)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
main.db:
|
||||||
|
engine: sqlite:////tmp/platypush-tests.db
|
||||||
|
|
||||||
backend.http:
|
backend.http:
|
||||||
port: 8123
|
port: 8123
|
||||||
disable_websocket: True
|
disable_websocket: True
|
||||||
|
|
||||||
backend.redis:
|
backend.redis:
|
||||||
disabled: False
|
disabled: False
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from .context import platypush, config_file, TestTimeoutException
|
import os
|
||||||
|
|
||||||
|
from .context import config_file, TestTimeoutException
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import sys
|
import sys
|
||||||
|
@ -15,55 +16,114 @@ from platypush.message import Message
|
||||||
from platypush.message.response import Response
|
from platypush.message.response import Response
|
||||||
from platypush.utils import set_timeout, clear_timeout
|
from platypush.utils import set_timeout, clear_timeout
|
||||||
|
|
||||||
|
|
||||||
class TestHttp(unittest.TestCase):
|
class TestHttp(unittest.TestCase):
|
||||||
""" Tests the full flow of a request/response on the HTTP backend.
|
""" Tests the full flow of a request/response on the HTTP backend.
|
||||||
Runs a remote command over HTTP via shell.exec plugin and gets the output """
|
Runs a remote command over HTTP via shell.exec plugin and gets the output """
|
||||||
|
|
||||||
timeout = 10
|
timeout = 10
|
||||||
sleep_secs = 10
|
sleep_secs = 10
|
||||||
|
db_file = '/tmp/platypush-tests.db'
|
||||||
|
test_user = 'platypush'
|
||||||
|
test_pass = 'test'
|
||||||
|
base_url = 'http://localhost:8123'
|
||||||
|
expected_registration_redirect = '{base_url}/register?redirect={base_url}/execute'.format(base_url=base_url)
|
||||||
|
expected_login_redirect = '{base_url}/login?redirect={base_url}/execute'.format(base_url=base_url)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.app = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
||||||
backends = Config.get_backends()
|
backends = Config.get_backends()
|
||||||
self.assertTrue('http' in backends)
|
self.assertTrue('http' in backends, 'Missing HTTP server configuration')
|
||||||
|
|
||||||
def test_request_exec_flow(self):
|
|
||||||
self.start_daemon()
|
self.start_daemon()
|
||||||
logging.info('Sleeping {} seconds while waiting for the daemon to start up'.format(self.sleep_secs))
|
logging.info('Sleeping {} seconds while waiting for the daemon to start up'.format(self.sleep_secs))
|
||||||
time.sleep(self.sleep_secs)
|
time.sleep(self.sleep_secs)
|
||||||
self.send_request()
|
|
||||||
|
def test_http_flow(self):
|
||||||
|
# An /execute request performed before any user is registered should redirect to the registration page.
|
||||||
|
response = self.send_request()
|
||||||
|
self.assertEqual(self.expected_registration_redirect, response.url,
|
||||||
|
'No users registered, but the application did not redirect us to the registration page')
|
||||||
|
|
||||||
|
# Emulate a first user registration through form and get the session_token.
|
||||||
|
response = self.register_user()
|
||||||
|
self.assertGreater(len(response.history), 0, 'Redirect missing from the history')
|
||||||
|
self.assertTrue('session_token' in response.history[0].cookies, 'No session_token returned upon registration')
|
||||||
|
self.assertEqual('{base_url}/'.format(base_url=self.base_url), response.url,
|
||||||
|
'The registration form did not redirect to the main panel')
|
||||||
|
|
||||||
|
# After a first user has been registered any unauthenticated call to /execute should redirect to /login.
|
||||||
|
response = self.send_request()
|
||||||
|
self.assertEqual(self.expected_login_redirect, response.url,
|
||||||
|
'An unauthenticated request after user registration should result in a login redirect')
|
||||||
|
|
||||||
|
# A request authenticated with user/pass should succeed.
|
||||||
|
response = self.parse_response(self.send_request(auth=(self.test_user, self.test_pass)))
|
||||||
|
self.assertEqual(response.__class__, Response, 'The request did not return a proper Response object')
|
||||||
|
self.assertEqual(response.output.strip(), 'ping', 'The request did not return the expected output')
|
||||||
|
|
||||||
|
# A request with the wrong user/pass should fail.
|
||||||
|
response = self.send_request(auth=('wrong', 'wrong'))
|
||||||
|
self.assertEqual(self.expected_login_redirect, response.url,
|
||||||
|
'A request with wrong credentials should fail')
|
||||||
|
|
||||||
def start_daemon(self):
|
def start_daemon(self):
|
||||||
def _f():
|
def _f():
|
||||||
self.receiver = Daemon(config_file=config_file)
|
self.app = Daemon(config_file=config_file)
|
||||||
self.receiver.start()
|
self.app.start()
|
||||||
|
|
||||||
Thread(target=_f).start()
|
Thread(target=_f).start()
|
||||||
|
|
||||||
def on_timeout(self, msg):
|
@staticmethod
|
||||||
|
def on_timeout(msg):
|
||||||
def _f(): raise TestTimeoutException(msg)
|
def _f(): raise TestTimeoutException(msg)
|
||||||
|
|
||||||
return _f
|
return _f
|
||||||
|
|
||||||
def send_request(self):
|
def send_request(self, **kwargs):
|
||||||
set_timeout(seconds=self.timeout,
|
set_timeout(seconds=self.timeout,
|
||||||
on_timeout=self.on_timeout('Receiver response timed out'))
|
on_timeout=self.on_timeout('Receiver response timed out'))
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
u'http://localhost:8123/execute',
|
'{}/execute'.format(self.base_url),
|
||||||
json={
|
json={
|
||||||
'type': 'request',
|
'type': 'request',
|
||||||
'target': Config.get('device_id'),
|
'target': Config.get('device_id'),
|
||||||
'action': 'shell.exec',
|
'action': 'shell.exec',
|
||||||
'args': {'cmd': 'echo ping'}
|
'args': {'cmd': 'echo ping'}
|
||||||
}
|
}, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
clear_timeout()
|
clear_timeout()
|
||||||
|
return response
|
||||||
|
|
||||||
response = Message.build(response.json())
|
def register_user(self):
|
||||||
self.assertTrue(isinstance(response, Response))
|
set_timeout(seconds=self.timeout,
|
||||||
self.assertEqual(response.output.strip(), 'ping')
|
on_timeout=self.on_timeout('User registration response timed out'))
|
||||||
self.receiver.stop_app()
|
|
||||||
|
response = requests.post('{base_url}/register?redirect={base_url}/'.format(base_url=self.base_url), data={
|
||||||
|
'username': self.test_user,
|
||||||
|
'password': self.test_pass,
|
||||||
|
'confirm_password': self.test_pass,
|
||||||
|
})
|
||||||
|
|
||||||
|
clear_timeout()
|
||||||
|
return response
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_response(response):
|
||||||
|
return Message.build(response.json())
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if self.app:
|
||||||
|
self.app.stop_app()
|
||||||
|
|
||||||
|
if os.path.isfile(self.db_file):
|
||||||
|
os.unlink(self.db_file)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in a new issue