import os import re import shutil import tempfile import unittest from paste.deploy import loadapp from urlparse import parse_qsl from webob import Request, Response from webtest import TestApp as WebTestApp # avoid py.test skip message from waeup.cas.authenticators import DummyAuthenticator from waeup.cas.db import DB, LoginTicket, ServiceTicket, TicketGrantingCookie from waeup.cas.server import ( CASServer, create_service_ticket, create_login_ticket, create_tgc_value, check_login_ticket, set_session_cookie, check_session_cookie, get_template, delete_session_cookie, check_service_ticket, update_url ) RE_ALPHABET = re.compile('^[a-zA-Z0-9\-]*$') RE_COOKIE = re.compile('^cas-tgc=[A-Za-z0-9\-]+; Path=/; secure; HttpOnly$') RE_COOKIE_DEL = re.compile( '^cas-tgc=; Max-Age=\-[0-9]+; Path=/; ' 'expires=Thu, 01-Jan-1970 00:00:00 GMT; secure; HttpOnly$') class CASServerTests(unittest.TestCase): def setUp(self): # Create a new location where tempfiles are created. This way # also temporary dirs of local CASServers can be removed on # tear-down. self._new_tmpdir = tempfile.mkdtemp() self._old_tmpdir = tempfile.tempdir tempfile.tempdir = self._new_tmpdir self.workdir = os.path.join(self._new_tmpdir, 'home') self.db_path = os.path.join(self.workdir, 'mycas.db') os.mkdir(self.workdir) self.paste_conf1 = os.path.join( os.path.dirname(__file__), 'sample1.ini') self.paste_conf2 = os.path.join( os.path.dirname(__file__), 'sample2.ini') def tearDown(self): # remove local tempfile and reset old tempdir setting if os.path.isdir(self._new_tmpdir): shutil.rmtree(self._new_tmpdir) tempfile.tempdir = self._old_tmpdir def test_paste_deploy_loader(self): # we can load the CAS server via paste.deploy plugin app = loadapp('config:%s' % self.paste_conf1) assert isinstance(app, CASServer) assert hasattr(app, 'db') assert isinstance(app.db, DB) assert hasattr(app, 'auth') def test_paste_deploy_options(self): # we can set CAS server-related options via paste.deploy config app = loadapp('config:%s' % self.paste_conf2) assert isinstance(app, CASServer) assert app.db_connection_string == 'sqlite:///:memory:' assert isinstance(app.auth, DummyAuthenticator) def test_init(self): # we get a `DB` instance created automatically app = CASServer() assert hasattr(app, 'db') assert app.db is not None def test_init_explicit_db_path(self): # we can set a db_path explicitly app = CASServer(db='sqlite:///%s' % self.db_path) assert hasattr(app, 'db') assert isinstance(app.db, DB) assert os.path.isfile(self.db_path) def test_get_template(self): app = CASServer() assert app._get_template('login.html') is not None assert app._get_template('not-existent.html') is None def test_call_root(self): # the CAS protocol requires no root app = CASServer() req = Request.blank('http://localhost/') resp = app(req) assert resp.status == '404 Not Found' def test_first_time_login(self): # we can get a login page app = CASServer() req = Request.blank('http://localhost/login') resp = app(req) assert resp.status == '200 OK' def test_validate(self): # we can access a validation page app = CASServer() req = Request.blank('http://localhost/validate?service=foo&ticket=bar') resp = app(req) assert resp.status == '200 OK' def test_logout(self): # we can access a logout page app = CASServer() req = Request.blank('http://localhost/logout') resp = app(req) assert resp.status == '200 OK' def test_login_simple(self): # a simple login with no service will result in login screen # (2.1.1#service of protocol specs) app = CASServer() req = Request.blank('http://localhost/login') resp = app(req) assert resp.status == '200 OK' assert resp.content_type == 'text/html' assert b'