commit
6cf7a7bffa
1
Pipfile
1
Pipfile
@ -7,7 +7,6 @@ name = "pypi"
|
||||
tornado = "==5.0.2"
|
||||
webassets = "==0.12.1"
|
||||
Unipath = "==1.1"
|
||||
requests = "*"
|
||||
|
||||
[dev-packages]
|
||||
pytest = "==3.6.0"
|
||||
|
38
Pipfile.lock
generated
38
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "68a0d5093979093899f0f86faa82eb55f90f9a67a16b11a5701ea85096e72ee8"
|
||||
"sha256": "391e254ddb902877afca9c07aa2306710ce6d1e207b029c1a8b5dc0115ee99a5"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -16,35 +16,6 @@
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
|
||||
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
|
||||
],
|
||||
"version": "==2018.4.16"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
|
||||
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
|
||||
],
|
||||
"version": "==2.6"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
|
||||
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.18.4"
|
||||
},
|
||||
"tornado": {
|
||||
"hashes": [
|
||||
"sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7",
|
||||
@ -64,13 +35,6 @@
|
||||
"index": "pypi",
|
||||
"version": "==1.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
|
||||
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
|
||||
],
|
||||
"version": "==1.22"
|
||||
},
|
||||
"webassets": {
|
||||
"hashes": [
|
||||
"sha256:e7d9c8887343123fd5b32309b33167428cb1318cdda97ece12d0907fd69d38db"
|
||||
|
@ -33,7 +33,7 @@ class ApiClient(object):
|
||||
kwargs['body'] = dumps(kwargs['json'])
|
||||
del kwargs['json']
|
||||
headers = kwargs.get('headers', {})
|
||||
headers['Content-Type'] = 'application-json'
|
||||
headers['Content-Type'] = 'application/json'
|
||||
kwargs['headers'] = headers
|
||||
|
||||
response = yield self.client.fetch(url, method=method, **kwargs)
|
||||
|
66
atst/app.py
66
atst/app.py
@ -4,34 +4,62 @@ import tornado.web
|
||||
from tornado.web import url
|
||||
|
||||
from atst.handlers.main import MainHandler
|
||||
from atst.handlers.home import Home
|
||||
from atst.handlers.login import Login
|
||||
from atst.handlers.workspace import Workspace
|
||||
from atst.handlers.request import Request
|
||||
from atst.handlers.request_new import RequestNew
|
||||
from atst.handlers.dev import Dev
|
||||
from atst.home import home
|
||||
from atst.api_client import ApiClient
|
||||
|
||||
ENV = os.getenv("TORNADO_ENV", "dev")
|
||||
|
||||
|
||||
def make_app(config):
|
||||
|
||||
authz_client = ApiClient(config['default']['AUTHZ_BASE_URL'])
|
||||
authz_client = ApiClient(config["default"]["AUTHZ_BASE_URL"])
|
||||
authnid_client = ApiClient(config["default"]["AUTHNID_BASE_URL"])
|
||||
|
||||
routes = [
|
||||
url(r"/", Home, {"page": "login"}, name="main"),
|
||||
url(
|
||||
r"/login",
|
||||
Login,
|
||||
{"authnid_client": authnid_client},
|
||||
name="login",
|
||||
),
|
||||
url(r"/home", MainHandler, {"page": "home"}, name="home"),
|
||||
url( r"/workspaces/blank", MainHandler, {'page': 'workspaces_blank'}, name='workspaces_blank' ),
|
||||
url(
|
||||
r"/workspaces",
|
||||
Workspace,
|
||||
{"page": "workspaces", "authz_client": authz_client},
|
||||
name="workspaces",
|
||||
),
|
||||
url(r"/requests", Request, {"page": "requests"}, name="requests"),
|
||||
url(r"/requests/new", RequestNew, {"page": "requests_new"}, name="request_new"),
|
||||
url(
|
||||
r"/requests/new/([0-9])",
|
||||
RequestNew,
|
||||
{"page": "requests_new"},
|
||||
name="request_form",
|
||||
),
|
||||
url(r"/users", MainHandler, {"page": "users"}, name="users"),
|
||||
url(r"/reports", MainHandler, {"page": "reports"}, name="reports"),
|
||||
url(r"/calculator", MainHandler, {"page": "calculator"}, name="calculator"),
|
||||
]
|
||||
|
||||
if not ENV == "production":
|
||||
routes += [url(r"/login-dev", Dev, {"action": "login"}, name="dev-login")]
|
||||
|
||||
app = tornado.web.Application(
|
||||
routes,
|
||||
login_url="/",
|
||||
|
||||
app = tornado.web.Application([
|
||||
url( r"/", MainHandler, {'page': 'login'}, name='login' ),
|
||||
url( r"/home", MainHandler, {'page': 'home'}, name='home' ),
|
||||
url( r"/workspaces/blank", MainHandler, {'page': 'workspaces_blank'}, name='workspaces_blank' ),
|
||||
url( r"/workspaces",
|
||||
Workspace,
|
||||
{'page': 'workspaces', 'authz_client': authz_client},
|
||||
name='workspaces'),
|
||||
url( r"/requests", Request, {'page': 'requests'}, name='requests' ),
|
||||
url( r"/requests/new", RequestNew, {'page': 'requests_new'}, name='request_new' ),
|
||||
url( r"/requests/new/([0-9])", RequestNew, {'page': 'requests_new'}, name='request_form' ),
|
||||
url( r"/users", MainHandler, {'page': 'users'}, name='users' ),
|
||||
url( r"/reports", MainHandler, {'page': 'reports'}, name='reports' ),
|
||||
url( r"/calculator", MainHandler, {'page': 'calculator'}, name='calculator' ),
|
||||
],
|
||||
template_path = home.child('templates'),
|
||||
static_path = home.child('static'),
|
||||
cookie_secret=config["default"]["COOKIE_SECRET"],
|
||||
debug=config['default'].getboolean('DEBUG')
|
||||
)
|
||||
return app
|
||||
@ -40,12 +68,12 @@ def make_app(config):
|
||||
def make_config():
|
||||
BASE_CONFIG_FILENAME = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../config/base.ini',
|
||||
"../config/base.ini"
|
||||
)
|
||||
ENV_CONFIG_FILENAME = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../config/',
|
||||
'{}.ini'.format(os.getenv('TORNADO_ENV', 'dev').lower())
|
||||
"../config/",
|
||||
"{}.ini".format(ENV.lower())
|
||||
)
|
||||
config = ConfigParser()
|
||||
|
||||
|
@ -25,3 +25,13 @@ class BaseHandler(tornado.web.RequestHandler):
|
||||
ns = super(BaseHandler, self).get_template_namespace()
|
||||
ns.update(helpers)
|
||||
return ns
|
||||
|
||||
def get_current_user(self):
|
||||
if self.get_secure_cookie('atst'):
|
||||
return True
|
||||
else:
|
||||
False
|
||||
|
||||
# this is a temporary implementation until we have real sessions
|
||||
def _start_session(self):
|
||||
self.set_secure_cookie('atst', 'valid-user-session')
|
||||
|
13
atst/handlers/dev.py
Normal file
13
atst/handlers/dev.py
Normal file
@ -0,0 +1,13 @@
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
class Dev(BaseHandler):
|
||||
def initialize(self, action):
|
||||
self.action = action
|
||||
|
||||
def get(self):
|
||||
if self.action == 'login':
|
||||
self._login()
|
||||
|
||||
def _login(self):
|
||||
self._start_session()
|
||||
self.redirect("/home")
|
10
atst/handlers/home.py
Normal file
10
atst/handlers/home.py
Normal file
@ -0,0 +1,10 @@
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
class Home(BaseHandler):
|
||||
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
||||
def get(self):
|
||||
self.render( '%s.html.to' % self.page, page = self.page )
|
37
atst/handlers/login.py
Normal file
37
atst/handlers/login.py
Normal file
@ -0,0 +1,37 @@
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
|
||||
class Login(BaseHandler):
|
||||
|
||||
def initialize(self, authnid_client):
|
||||
self.authnid_client = authnid_client
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
token = self.get_query_argument("bearer-token")
|
||||
if token:
|
||||
valid = yield self._validate_login_token(token)
|
||||
if valid:
|
||||
self._start_session()
|
||||
self.redirect("/home")
|
||||
return
|
||||
|
||||
url = self.get_login_url()
|
||||
self.redirect(url)
|
||||
return
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def _validate_login_token(self, token):
|
||||
try:
|
||||
response = yield self.authnid_client.post(
|
||||
"/api/v1/validate", json={"token": token}
|
||||
)
|
||||
return response.code == 200
|
||||
|
||||
except tornado.httpclient.HTTPError as error:
|
||||
if error.response.code == 401:
|
||||
return False
|
||||
|
||||
else:
|
||||
raise error
|
@ -1,3 +1,5 @@
|
||||
import atst
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
class MainHandler(BaseHandler):
|
||||
@ -5,5 +7,6 @@ class MainHandler(BaseHandler):
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
||||
@tornado.web.authenticated
|
||||
def get(self):
|
||||
self.render( '%s.html.to' % self.page, page = self.page )
|
||||
|
@ -1,3 +1,4 @@
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
mock_requests = [
|
||||
@ -31,5 +32,6 @@ class Request(BaseHandler):
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
||||
@tornado.web.authenticated
|
||||
def get(self):
|
||||
self.render('requests.html.to', page = self.page, requests = mock_requests )
|
||||
|
@ -1,3 +1,4 @@
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
class RequestNew(BaseHandler):
|
||||
@ -22,6 +23,7 @@ class RequestNew(BaseHandler):
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
||||
@tornado.web.authenticated
|
||||
def get(self, screen = 1):
|
||||
self.render( 'requests/screen-%d.html.to' % int(screen),
|
||||
page = self.page,
|
||||
|
@ -1,5 +1,5 @@
|
||||
from atst.handler import BaseHandler
|
||||
import requests
|
||||
import tornado
|
||||
import tornado.gen
|
||||
|
||||
mock_workspaces = [
|
||||
@ -13,8 +13,6 @@ mock_workspaces = [
|
||||
}
|
||||
]
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
class Workspace(BaseHandler):
|
||||
|
||||
def initialize(self, page, authz_client):
|
||||
@ -22,5 +20,6 @@ class Workspace(BaseHandler):
|
||||
self.authz_client = authz_client
|
||||
|
||||
@tornado.gen.coroutine
|
||||
@tornado.web.authenticated
|
||||
def get(self):
|
||||
self.render( 'workspaces.html.to', page = self.page, workspaces = mock_workspaces )
|
||||
|
@ -1,5 +1,7 @@
|
||||
[default]
|
||||
PORT=8000
|
||||
ENVIRONMENT = dev
|
||||
DEBUG = true
|
||||
AUTHZ_BASE_URL = http://localhost
|
||||
PORT = 8000
|
||||
AUTHNID_BASE_URL= http://localhost
|
||||
COOKIE_SECRET = some-secret-please-replace
|
||||
|
55
tests/test_auth.py
Normal file
55
tests/test_auth.py
Normal file
@ -0,0 +1,55 @@
|
||||
import re
|
||||
import pytest
|
||||
import tornado.web
|
||||
import tornado.gen
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_redirects_when_not_logged_in(http_client, base_url):
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/home", raise_error=False, follow_redirects=False
|
||||
)
|
||||
location = response.headers['Location']
|
||||
assert response.code == 302
|
||||
assert response.error
|
||||
assert re.match('/\??', location)
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url):
|
||||
@tornado.gen.coroutine
|
||||
def _validate_login_token(c, t):
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(
|
||||
"atst.handlers.login.Login._validate_login_token",
|
||||
_validate_login_token
|
||||
)
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/login?bearer-token=abc-123",
|
||||
follow_redirects=False,
|
||||
raise_error=False
|
||||
)
|
||||
assert response.headers["Set-Cookie"].startswith("atst")
|
||||
assert response.headers['Location'] == '/home'
|
||||
assert response.code == 302
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_login_via_dev_endpoint(app, http_client, base_url):
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/login-dev", raise_error=False, follow_redirects=False
|
||||
)
|
||||
assert response.headers["Set-Cookie"].startswith("atst")
|
||||
assert response.code == 302
|
||||
assert response.headers["Location"] == "/home"
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
@pytest.mark.skip(reason="need to work out auth error user paths")
|
||||
def test_login_with_invalid_bearer_token(http_client, base_url):
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/home",
|
||||
raise_error=False,
|
||||
headers={"Cookie": "bearer-token=anything"},
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user