def testLogoutWithRememberMe(self):
     form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home', rememberMeCookie=True)
     observer = CallTrace(onlySpecifiedMethods=True)
     observer.returnValues['cookieName'] = 'remember-cookie'
     observer.returnValues['removeCookie'] = None
     form.addObserver(observer)
     session = {'user': '******', 'someother': 'value'}
     result = asString(form.logout(session=session, ignored='kwarg', Headers={'Cookie':'remember-cookie=cookieId;othercookie=value'}))
     self.assertEquals('HTTP/1.0 302 Found\r\nSet-Cookie: remember-cookie=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/\r\nLocation: /home\r\n\r\n', result)
     self.assertEqual({'someother': 'value'}, session)
     self.assertEqual(['cookieName', 'removeCookie'], observer.calledMethodNames())
     self.assertEquals(('cookieId',), observer.calledMethods[1].args)
    def testSetRememberMeCookie(self):
        observer = CallTrace(
            methods={
                'validateUser': lambda username, password: True,
                'createCookie': lambda user: dict(
                    cookie='THIS IS THE COOKIE VALUE',
                    header='Set-Cookie: somevalue',
                )
            },
            onlySpecifiedMethods=True,
            returnValues={'hasUser': True})

        basicHtmlLoginForm = BasicHtmlLoginForm(
            action="/action",
            loginPath="/",
            home="/index",
            rememberMeCookie=True)
        basicHtmlLoginForm._now = lambda: 3600

        dna = be(
            (Observable(),
                (basicHtmlLoginForm,
                    (observer, )
                )
            )
        )

        session = {}
        header, _ = asString(dna.all.handleRequest(
            Method="POST",
            path="/",
            session=session,
            Body=urlencode(dict(username="******", password="******", rememberMe="on"))
        )).split('\r\n\r\n', 1)

        self.assertTrue('user' in session, session)
        headers = headerToDict(header)
        self.assertEquals("/index", headers['Location'])

        self.assertTrue('Set-Cookie' in headers, headers)
        self.assertEquals("somevalue", headers['Set-Cookie'])
Exemple #3
0
 def testIsAdmin(self):
     user = BasicHtmlLoginForm.User('username')
     self.groups.enrichUser(user)
     self.assertFalse(user.isAdmin())
     self.groups.setGroupsForUser(username='******',
                                  groupnames=['admin', 'users'])
     self.assertTrue(user.isAdmin())
     self.groups.setGroupsForUser(username='******', groupnames=['users'])
     self.assertFalse(user.isAdmin())
     self.groups.setGroupsForUser(username='******',
                                  groupnames=['users', 'management'])
     self.assertFalse(user.isAdmin())
    def testDeleteUserAsAdmin(self):
        observer = CallTrace(returnValues={'hasUser': True})
        self.form.addObserver(observer)
        result = asString(self.form.handleRequest(
            path='/login/remove',
            Client=('127.0.0.1', 3451),
            Method='POST',
            Body=urlencode(dict(username='******', formUrl='/show/userlist')),
            session={'user': BasicHtmlLoginForm.User('admin')}))

        self.assertEquals(['hasUser', 'enrichUser', 'removeUser', 'removeCookies', 'removeCookies'], [m.name for m in observer.calledMethods])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/userlist\r\n\r\n", result)
    def testDeleteNonExistingUser(self):
        observer = CallTrace(returnValues={'hasUser': False}, )
        self.form.addObserver(observer)
        session = {'user': BasicHtmlLoginForm.User('admin')}
        result = asString(self.form.handleRequest(
            path='/login/remove',
            Client=('127.0.0.1', 3451),
            Method='POST',
            Body=urlencode(dict(username='******', formUrl='/show/userlist')),
            session=session))

        self.assertEquals(['hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals('HTTP/1.0 401 Unauthorized\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nUnauthorized access.', result)
    def testChangePasswordNoOldForAdminNotAllowed(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform'))
        session = {
            'user': BasicHtmlLoginForm.User('admin'),
            'BasicHtmlLoginForm.formValues': {}
        }

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals({'username':'******', 'errorMessage': 'Username and password do not match'}, session['BasicHtmlLoginForm.formValues'])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/changepasswordform\r\n\r\n", result)
    def testChangePasswordNoOldForAdminOnlyAllowedForOtherUsers(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform', returnUrl='/home'))
        session = {
            'user': BasicHtmlLoginForm.User('admin'),
            'BasicHtmlLoginForm.formValues': {}
        }

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals(['setPassword'], [m.name for m in observer.calledMethods])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /home\r\n\r\n", result)
    def testLoginForWithRememberMe(self):
        form = BasicHtmlLoginForm(
            action='/action',
            loginPath='/login',
            home='/home',
            rememberMeCookie=True)
        result = asString(form.loginForm(session={}, path='/page/login2'))
        self.assertEqualsWS("""<div id="login-form">
    <form method="POST" name="login" action="/action">
    <input type="hidden" name="formUrl" value="/page/login2"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dt>&nbsp;</dt><dd class="rememberMe"><input type="checkbox" name="rememberMe" id="rememberMe" /><label for="rememberMe">Remember me</label></dd>
            <dd class="submit"><input type="submit" id="submitLogin" value="Login"/></dd>
        </dl>
    </form>
    <script type="text/javascript">
        document.getElementById("submitLogin").focus()
    </script>
</div>""", result)
Exemple #9
0
 def testManagementGroups(self):
     user = BasicHtmlLoginForm.User('username')
     self.groups.enrichUser(user)
     self.assertEquals(set(), user.managementGroups())
     self.groups.setGroupsForUser(username='******',
                                  groupnames=['admin', 'users'])
     self.assertEquals(set(['admin']), user.managementGroups())
     self.groups.setGroupsForUser(username='******',
                                  groupnames=['management', 'users'])
     self.assertEquals(set(['management']), user.managementGroups())
     self.groups.setGroupsForUser(
         username='******', groupnames=['management', 'admin', 'users'])
     self.assertEquals(set(['admin', 'management']),
                       user.managementGroups())
Exemple #10
0
 def testCanEdit(self):
     self.groups.setGroupsForUser('admin1', ['admin'])
     self.groups.setGroupsForUser('admin2', ['admin'])
     self.groups.setGroupsForUser('manager1', ['management'])
     self.groups.setGroupsForUser('manager2', ['management'])
     self.groups.setGroupsForUser('user1', ['users'])
     self.groups.setGroupsForUser('user2', ['users'])
     admin1 = BasicHtmlLoginForm.User('admin1')
     manager1 = BasicHtmlLoginForm.User('manager1')
     user1 = BasicHtmlLoginForm.User('user1')
     self.groups.enrichUser(admin1)
     self.groups.enrichUser(manager1)
     self.groups.enrichUser(user1)
     self.assertTrue(admin1.canEdit())  #any user
     self.assertTrue(admin1.canEdit('admin1'))
     self.assertTrue(admin1.canEdit(admin1))
     self.assertTrue(admin1.canEdit('manager1'))
     self.assertTrue(admin1.canEdit(manager1))
     self.assertTrue(admin1.canEdit('admin2'))
     self.assertTrue(admin1.canEdit('user1'))
     self.assertTrue(admin1.canEdit(user1))
     self.assertTrue(admin1.canEdit('unexisting'))
     self.assertTrue(manager1.canEdit())
     self.assertTrue(manager1.canEdit('manager1'))
     self.assertTrue(manager1.canEdit(manager1))
     self.assertTrue(manager1.canEdit('manager2'))
     self.assertFalse(manager1.canEdit('admin1'))
     self.assertFalse(manager1.canEdit(admin1))
     self.assertTrue(manager1.canEdit('user1'))
     self.assertTrue(manager1.canEdit('unexisting'))
     self.assertFalse(user1.canEdit())
     self.assertTrue(user1.canEdit('user1'))
     self.assertFalse(user1.canEdit('manager1'))
     self.assertFalse(user1.canEdit('admin1'))
     self.assertFalse(user1.canEdit('user2'))
     self.assertFalse(user1.canEdit('unexisting'))
    def testNewUserWithPOSTFailsDifferentPasswords(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'admin']), set(pf.listUsernames()))
        self.assertEquals({'errorMessage':'Passwords do not match', 'username':'******'}, session['BasicHtmlLoginForm.newUserFormValues'])
    def testNewEmptyPassword(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', oldPassword='******', newPassword='', retypedPassword='', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('existing', 'password'))
        self.assertEquals({'errorMessage':'New password is invalid.', 'username':'******'}, session['BasicHtmlLoginForm.formValues'])
    def testLoginWithPOSTsucceeds(self):
        observer = CallTrace(onlySpecifiedMethods=True, returnValues={'hasUser': True})
        self.form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home')
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = True
        Body = urlencode(dict(username='******', password='******'))
        session = {}

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertEquals('admin', session['user'].name)
        self.assertEquals(True, session['user'].isAdmin())
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /home' in header)

        self.assertEquals(['validateUser', 'hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals({'username': '******', 'password':'******'}, observer.calledMethods[0].kwargs)
Exemple #14
0
    def testAdminCanChangeOtherAdmins(self):
        otherAdminUser = BasicHtmlLoginForm.User('johan')
        self.groupsFile.enrichUser(otherAdminUser)

        Body = urlencode(
            {
                'username': [otherAdminUser.name],
                'groupname': ['special'],
                'formUrl': ['/useraccount']
            },
            doseq=True)
        session = {'user': self.adminUser}
        result = asString(
            self.userGroups.handleRequest(Method='POST',
                                          path='/action/updateGroupsForUser',
                                          session=session,
                                          Body=Body))
        self.assertEquals(
            'HTTP/1.0 302 Found\r\nLocation: /useraccount\r\n\r\n', result)

        self.assertEquals(set(['special']), otherAdminUser.groups())
    def testNewUserWithPOSTsucceeds(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        observer = CallTrace()
        self.form.addObserver(observer)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /return' in header)

        self.assertEquals(set(['existing', 'newuser', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('newuser', 'secret'))
        self.assertEquals('Added user "newuser"', session['BasicHtmlLoginForm.newUserFormValues']['successMessage'])
        self.assertEqual(['addUser', 'handleNewUser'], observer.calledMethodNames())
        self.assertEqual({'username': '******', 'password': '******'}, observer.calledMethods[0].kwargs)
        self.assertEqual({'Body': 'username=newuser&formUrl=%2Fpage%2FnewUser&password=secret&returnUrl=%2Freturn&retypedPassword=secret', 'username': '******'}, observer.calledMethods[1].kwargs)
    def testNewUserFormEN(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.newUserFormValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.newUserForm(session=session, path='/page/login2', returnUrl='/return'))
        self.assertEqualsWS("""<div id="login-new-user-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="newUser" action="/action/newUser">
    <input type="hidden" name="formUrl" value="/page/login2"/>
    <input type="hidden" name="returnUrl" value="/return"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dt>Retype password</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Create"/></dd>
        </dl>
    </form>
</div>""", result)
    def testShowChangePasswordFormForSpecifiedUser(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', lang="nl", arguments=dict(user=['myuser']), user='******', onlyNewPassword=True))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="changePassword" action="/action/changepassword">
    <input type="hidden" name="formUrl" value="/show/changepasswordform?user=myuser"/>
    <input type="hidden" name="returnUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="username" value="myuser"/>
        <dl>
            <dt>Nieuw wachtwoord</dt>
            <dd><input type="password" name="newPassword"/></dd>
            <dt>Herhaal nieuw wachtwoord</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Aanpassen"/></dd>
        </dl>
    </form>
</div>""", result)
    def testShowChangePasswordFormEn(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', arguments={}))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="changePassword" action="/action/changepassword">
    <input type="hidden" name="formUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="returnUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="username" value="username"/>
        <dl>
            <dt>Old password</dt>
            <dd><input type="password" name="oldPassword"/></dd>
            <dt>New password</dt>
            <dd><input type="password" name="newPassword"/></dd>
            <dt>Retype new password</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Change"/></dd>
        </dl>
    </form>
</div>""", result)
Exemple #19
0
def dna(reactor, port, dataPath, logPath, statePath, externalUrl, customerLogoUrl, deproxyIps=None, **ignored):
    environment = createEnvironment(dataPath)
    harvesterData = environment.createHarvesterData()
    harvesterDataRetrieve = environment.createHarvesterDataRetrieve()
    deproxy = Deproxy(deproxyForIps=deproxyIps)
    repositoryStatus = be(
        (RepositoryStatus(logPath, statePath),
            (harvesterData, )
        )
    )
    configDict = JsonDict(
        logPath=logPath,
        statePath=statePath,
        externaUrl=externalUrl,
        dataPath=dataPath,
    )
    print("Started Metastreams with configuration:\n" + configDict.pretty_print())

    userGroup = initializeUserGroupManagement(join(statePath, 'users'), harvesterData)
    basicHtmlLoginHelix = (BasicHtmlLoginForm(
        action="/login.action",
        loginPath="/login",
        home="/index",
        rememberMeCookie=False,
        lang="nl"),

        (userGroup.basicHtmlObserver,),
    )
    varWwwdataPath = join(statePath, 'www-data', 'var')
    isdir(varWwwdataPath) or makedirs(varWwwdataPath)

    staticFilePaths = []
    staticFiles = Transparent()
    for path, libdir in [
            ('/js/bootstrap', '/usr/share/javascript/bootstrap5/js'),
            ('/css/bootstrap', '/usr/share/javascript/bootstrap5/css'),
            ('/css/bootstrap-icons', '/usr/share/javascript/bootstrap-icons'),
            ('/js/jquery', '/usr/share/javascript/jquery'),
            ('/js/jquery-tablesorter', '/usr/share/javascript/jquery-tablesorter'),
            ('/css/jquery-tablesorter', '/usr/share/javascript/jquery-tablesorter/css'),
            ('/js/autosize', '/usr/share/javascript/autosize'),
            ('/static', staticHtmlPath),
            ('/var', varWwwdataPath),
            ]:
        staticFiles.addObserver(StaticFiles(libdir=libdir, path=path))
        staticFilePaths.append(path)

    return \
    (Observable(),
        (ObservableHttpServer(reactor, port),
            (LogCollector(),
                (ApacheLogWriter(stdout),),
                (deproxy,
                    (HandleRequestLog(),
                        (BasicHttpHandler(),
                            (SessionHandler(),
                                (CookieMemoryStore(name="meresco-harvester", timeout=2*60*60), ),
                                (UserFromSession(),
                                    (PathFilter("/info/version"),
                                        (StringServer(VERSION_STRING, ContentTypePlainText), )
                                    ),
                                    (PathFilter("/info/config"),
                                        (StringServer(configDict.dumps(), ContentTypeJson), )
                                    ),
                                    (PathFilter('/login.action'),
                                        basicHtmlLoginHelix
                                    ),
                                    (staticFiles,),
                                    (PathFilter('/', excluding=['/info/version', '/info/config', '/action', '/login.action'] + harvesterDataRetrieve.paths + staticFilePaths),
                                        (SecureZone("/login", excluding=["/index", "/invalid", "/rss", '/running.rss', '/showHarvesterStatus'], defaultLanguage="nl"),
                                            (PathFilter('/', excluding=userGroup.excludedPaths),
                                                (DynamicHtml(
                                                        [dynamicHtmlPath],
                                                        reactor=reactor,
                                                        additionalGlobals={
                                                            'externalUrl': externalUrl,
                                                            'escapeXml': escapeXml,
                                                            'compose': compose,
                                                            'dumps': dumps,
                                                            'VERSION': VERSION,
                                                            'CONFIG': configDict,
                                                            'Timeslot': Timeslot,
                                                            'ThroughputAnalyser': ThroughputAnalyser,
                                                            'dateSince': dateSince,
                                                            'callable': callable,
                                                            'OnlineHarvest': OnlineHarvest,
                                                            'StringIO': StringIO,
                                                            'okPlainText': okPlainText,
                                                            'ZuluTime': ZuluTime,
                                                            'xpathFirst': xpathFirst,
                                                            'customerLogoUrl': customerLogoUrl,
                                                            'uuid': lambda: str(uuid4()),
                                                        },
                                                        indexPage="/index",
                                                    ),
                                                    basicHtmlLoginHelix,
                                                    (harvesterData,),
                                                    (repositoryStatus,),
                                                    (userGroup.dynamicHtmlObserver,),
                                                )
                                            ),
                                            (userGroup.actions,),
                                        ),
                                    ),
                                    (PathFilter('/action'),
                                        (HarvesterDataActions(),
                                            (harvesterData,)
                                        ),
                                    ),
                                    (PathFilter(harvesterDataRetrieve.paths),
                                        (harvesterDataRetrieve,
                                            (FilterFields(),
                                                (harvesterData,),
                                            ),
                                            (repositoryStatus,),
                                        )
                                    )
                                )
                            )
                        )
                    )
                )
            )
        )
    )
class BasicHtmlLoginFormTest(SeecrTestCase):
    def setUp(self):
        SeecrTestCase.setUp(self)

        self.form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home')

    def testLoginFormEnglish(self):
        result = asString(self.form.loginForm(session={}, path='/page/login2'))

        self.assertEqualsWS("""<div id="login-form">
    <form method="POST" name="login" action="/action">
    <input type="hidden" name="formUrl" value="/page/login2"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dd class="submit"><input type="submit" id="submitLogin" value="Login"/></dd>
        </dl>
    </form>
    <script type="text/javascript">
        document.getElementById("submitLogin").focus()
    </script>
</div>""", result)

    def testLoginFormDutch(self):
        result = asString(self.form.loginForm(session={}, path='/page/login2', lang='nl'))

        self.assertEqualsWS("""<div id="login-form">
    <form method="POST" name="login" action="/action">
    <input type="hidden" name="formUrl" value="/page/login2"/>
        <dl>
            <dt>Gebruikersnaam</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Wachtwoord</dt>
            <dd><input type="password" name="password"/></dd>
            <dd class="submit"><input type="submit" id="submitLogin" value="Inloggen"/></dd>
        </dl>
    </form>
    <script type="text/javascript">
        document.getElementById("submitLogin").focus()
    </script>
</div>""", result)

    def testNewUserFormEN(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.newUserFormValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.newUserForm(session=session, path='/page/login2', returnUrl='/return'))
        self.assertEqualsWS("""<div id="login-new-user-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="newUser" action="/action/newUser">
    <input type="hidden" name="formUrl" value="/page/login2"/>
    <input type="hidden" name="returnUrl" value="/return"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dt>Retype password</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Create"/></dd>
        </dl>
    </form>
</div>""", result)

    def testNewUserFormNL(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.newUserFormValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.newUserForm(session=session, path='/page/login2', returnUrl='/return', lang="nl"))
        self.assertEqualsWS("""<div id="login-new-user-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="newUser" action="/action/newUser">
    <input type="hidden" name="formUrl" value="/page/login2"/>
    <input type="hidden" name="returnUrl" value="/return"/>
        <dl>
            <dt>Gebruikersnaam</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Wachtwoord</dt>
            <dd><input type="password" name="password"/></dd>
            <dt>Herhaal wachtwoord </dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Aanmaken"/></dd>
        </dl>
    </form>
</div>""", result)

    def testRedirectOnGet(self):
        result = asString(self.form.handleRequest(path='/whatever', Client=('127.0.0.1', 3451), Method='GET'))
        header, body = result.split(CRLF*2)
        self.assertTrue('405' in header)

    def testLoginWithPOSTsucceedsRedirectsToOriginalPath(self):
        observer = CallTrace(onlySpecifiedMethods=True, returnValues={'hasUser': True})
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = True
        Body = urlencode(dict(username='******', password='******'))
        session = {ORIGINAL_PATH:'/please/go/here'}

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertEquals('user', session['user'].name)
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /please/go/here' in header)
        user = session['user']
        self.assertFalse(user.isAdmin())

        self.assertEquals(['validateUser', 'hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals({'username': '******', 'password':'******'}, observer.calledMethods[0].kwargs)

    def testLoginWithPOSTsucceedsRedirectsToOriginalPathOnlyOnce(self):
        observer = CallTrace(onlySpecifiedMethods=True, returnValues={'hasUser': True})
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = True
        Body = urlencode(dict(username='******', password='******'))
        session = {ORIGINAL_PATH:'/please/go/here'}

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertEquals('user', session['user'].name)
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /please/go/here' in header)
        self.assertFalse(session['user'].isAdmin())

        self.assertEquals(['validateUser', 'hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals({'username': '******', 'password':'******'}, observer.calledMethods[0].kwargs)

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /home' in header, header)

    def testLoginWithPOSTsucceeds(self):
        observer = CallTrace(onlySpecifiedMethods=True, returnValues={'hasUser': True})
        self.form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home')
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = True
        Body = urlencode(dict(username='******', password='******'))
        session = {}

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertEquals('admin', session['user'].name)
        self.assertEquals(True, session['user'].isAdmin())
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /home' in header)

        self.assertEquals(['validateUser', 'hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals({'username': '******', 'password':'******'}, observer.calledMethods[0].kwargs)

    def testLoginWithPOSTfails(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False
        Body = urlencode(dict(username='******', password='******'))
        session = {}

        result = asString(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertFalse('user' in session)
        self.assertEquals({'username':'******', 'errorMessage': 'Invalid username or password'}, session['BasicHtmlLoginForm.formValues'])
        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /login' in header, header)

        self.assertEquals(['validateUser'], [m.name for m in observer.calledMethods])
        self.assertEquals({'username': '******', 'password':'******'}, observer.calledMethods[0].kwargs)

    def testLoginEnrichesAUserByAnObserver(self):
        observer = CallTrace(returnValues={'hasUser': True, 'validateUser': True})
        def enrichUser(user):
            user.title = lambda: "Full username"
            user.additionalInfo = "more info"
        observer.methods['enrichUser'] = enrichUser
        self.form.addObserver(observer)
        Body = urlencode(dict(username='******', password='******'))
        session = {}

        consume(self.form.handleRequest(path='/login', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        self.assertEquals("more info", session['user'].additionalInfo)
        self.assertEquals('Full username', session['user'].title())
        self.assertEquals(['validateUser', 'hasUser', 'enrichUser'], observer.calledMethodNames())


    def testLoginFormWithError(self):
        session = {}
        session['BasicHtmlLoginForm.formValues']={'username': '******', 'errorMessage': 'Invalid <username> or "password"'}
        result = asString(self.form.loginForm(session=session, path='/show/login'))

        self.assertEqualsWS("""<div id="login-form">
    <p class="error">Invalid &lt;username&gt; or "password"</p>
    <form method="POST" name="login" action="/action">
    <input type="hidden" name="formUrl" value="/show/login"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value='&lt;us"er&gt;'/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dd class="submit"><input type="submit" id="submitLogin" value="Login"/></dd>
        </dl>
    </form>
    <script type="text/javascript">
        document.getElementById("submitLogin").focus()
    </script>
</div>""", result)

    def testShowChangePasswordFormEn(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', arguments={}))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="changePassword" action="/action/changepassword">
    <input type="hidden" name="formUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="returnUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="username" value="username"/>
        <dl>
            <dt>Old password</dt>
            <dd><input type="password" name="oldPassword"/></dd>
            <dt>New password</dt>
            <dd><input type="password" name="newPassword"/></dd>
            <dt>Retype new password</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Change"/></dd>
        </dl>
    </form>
</div>""", result)

    def testShowChangePasswordFormNl(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', lang="nl", arguments={}))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="changePassword" action="/action/changepassword">
    <input type="hidden" name="formUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="returnUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="username" value="username"/>
        <dl>
            <dt>Oud wachtwoord</dt>
            <dd><input type="password" name="oldPassword"/></dd>
            <dt>Nieuw wachtwoord</dt>
            <dd><input type="password" name="newPassword"/></dd>
            <dt>Herhaal nieuw wachtwoord</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Aanpassen"/></dd>
        </dl>
    </form>
</div>""", result)

    def testShowChangePasswordFormForSpecifiedUser(self):
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {'errorMessage': 'BAD BOY'},
        }
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', lang="nl", arguments=dict(user=['myuser']), user='******', onlyNewPassword=True))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">BAD BOY</p>
    <form method="POST" name="changePassword" action="/action/changepassword">
    <input type="hidden" name="formUrl" value="/show/changepasswordform?user=myuser"/>
    <input type="hidden" name="returnUrl" value="/show/changepasswordform"/>
    <input type="hidden" name="username" value="myuser"/>
        <dl>
            <dt>Nieuw wachtwoord</dt>
            <dd><input type="password" name="newPassword"/></dd>
            <dt>Herhaal nieuw wachtwoord</dt>
            <dd><input type="password" name="retypedPassword"/></dd>
            <dd class="submit"><input type="submit" value="Aanpassen"/></dd>
        </dl>
    </form>
</div>""", result)

    def testShowChangePasswordFormErrorWithoutUser(self):
        session = {}
        result = asString(self.form.changePasswordForm(session=session, path='/show/changepasswordform', arguments={}))

        self.assertEqualsWS("""<div id="login-change-password-form">
    <p class="error">Please login to change password.</p>
</div>""", result)

    def testChangePasswordMismatch(self):
        Body = urlencode(dict(username='******', oldPassword='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform'))
        session = {'user': BasicHtmlLoginForm.User('user')}

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals({'username':'******', 'errorMessage': 'New passwords do not match'}, session['BasicHtmlLoginForm.formValues'])
        self.assertEqualsWS("""HTTP/1.0 302 Found\r\nLocation: /show/changepasswordform\r\n\r\n""", result)

    def testChangePasswordWrongOld(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', oldPassword='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform'))
        session = {'user': BasicHtmlLoginForm.User('user')}

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals({'username':'******', 'errorMessage': 'Username and password do not match'}, session['BasicHtmlLoginForm.formValues'])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/changepasswordform\r\n\r\n", result)

    def testChangePasswordNoOldNotAllowed(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform'))
        session = {
            'user': BasicHtmlLoginForm.User('username'),
            'BasicHtmlLoginForm.formValues': {}
        }

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals({'username':'******', 'errorMessage': 'Username and password do not match'}, session['BasicHtmlLoginForm.formValues'])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/changepasswordform\r\n\r\n", result)

    def testChangePasswordNoOldForAdminOnlyAllowedForOtherUsers(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform', returnUrl='/home'))
        session = {
            'user': BasicHtmlLoginForm.User('admin'),
            'BasicHtmlLoginForm.formValues': {}
        }

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals(['setPassword'], [m.name for m in observer.calledMethods])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /home\r\n\r\n", result)

    def testChangePasswordNoOldForAdminNotAllowed(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = False

        Body = urlencode(dict(username='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform'))
        session = {
            'user': BasicHtmlLoginForm.User('admin'),
            'BasicHtmlLoginForm.formValues': {}
        }

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals({'username':'******', 'errorMessage': 'Username and password do not match'}, session['BasicHtmlLoginForm.formValues'])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/changepasswordform\r\n\r\n", result)

    def testChangePassword(self):
        observer = CallTrace()
        self.form.addObserver(observer)
        observer.returnValues['validateUser'] = True

        Body = urlencode(dict( username='******', oldPassword='******', newPassword="******", retypedPassword="******", formUrl='/show/changepasswordform', returnUrl='/home'))
        session = {'user': BasicHtmlLoginForm.User('user')}

        result = asString(self.form.handleRequest(path='/login/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        self.assertEquals(['validateUser', 'setPassword'], [m.name for m in observer.calledMethods])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /home\r\n\r\n", result)


    def testDeleteUserNoAdmin(self):
        observer = CallTrace(returnValues={'hasUser': True})
        self.form.addObserver(observer)
        result = asString(self.form.handleRequest(
            path='/login/remove',
            Client=('127.0.0.1', 3451),
            Method='POST',
            Body=urlencode(dict(username='******', formUrl='/show/userlist')),
            session={}))
        self.assertEquals(['hasUser', 'enrichUser'], [m.name for m in observer.calledMethods])
        self.assertEquals('HTTP/1.0 401 Unauthorized\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nUnauthorized access.', result)

    def testDeleteUserAsAdmin(self):
        observer = CallTrace(returnValues={'hasUser': True})
        self.form.addObserver(observer)
        result = asString(self.form.handleRequest(
            path='/login/remove',
            Client=('127.0.0.1', 3451),
            Method='POST',
            Body=urlencode(dict(username='******', formUrl='/show/userlist')),
            session={'user': BasicHtmlLoginForm.User('admin')}))

        self.assertEquals(['hasUser', 'enrichUser', 'removeUser', 'removeCookies', 'removeCookies'], [m.name for m in observer.calledMethods])
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /show/userlist\r\n\r\n", result)

    def testDeleteNonExistingUser(self):
        observer = CallTrace(returnValues={'hasUser': False}, )
        self.form.addObserver(observer)
        session = {'user': BasicHtmlLoginForm.User('admin')}
        result = asString(self.form.handleRequest(
            path='/login/remove',
            Client=('127.0.0.1', 3451),
            Method='POST',
            Body=urlencode(dict(username='******', formUrl='/show/userlist')),
            session=session))

        self.assertEquals(['hasUser'], [m.name for m in observer.calledMethods])
        self.assertEquals('HTTP/1.0 401 Unauthorized\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nUnauthorized access.', result)

    def testDeleteByAdministriveUser(self):
        observer = CallTrace(returnValues={'hasUser': True, 'removeUser': None}, onlySpecifiedMethods=True)
        self.form.addObserver(observer)
        session = {'user': self.form.loginAsUser('admin')}
        observer.calledMethods.reset()
        result = asString(self.form.handleRemove(session=session, Body=urlencode(dict(username='******'))))
        self.assertEquals("HTTP/1.0 302 Found\r\nLocation: /home\r\n\r\n", result)
        self.assertEquals(['hasUser', 'removeUser'], [m.name for m in observer.calledMethods])

    def testDeleteByUserOfAdminNotAllowed(self):
        observer = CallTrace(returnValues={'hasUser': True, 'removeUser': None}, onlySpecifiedMethods=True)
        self.form.addObserver(observer)
        session = {'user': self.form.loginAsUser('user')}
        observer.calledMethods.reset()
        result = asString(self.form.handleRemove(session=session, Body=urlencode(dict(username='******'))))
        self.assertEquals('HTTP/1.0 401 Unauthorized\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nUnauthorized access.', result)
        self.assertEquals(['hasUser'], [m.name for m in observer.calledMethods])

    def testDeleteSelfNotAllowed(self):
        observer = CallTrace(returnValues={'hasUser': True, 'removeUser': None}, onlySpecifiedMethods=True)
        self.form.addObserver(observer)
        session = {'user': self.form.loginAsUser('admin')}
        observer.calledMethods.reset()
        result = asString(self.form.handleRemove(session=session, Body=urlencode(dict(username='******'))))
        self.assertEquals('HTTP/1.0 401 Unauthorized\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nUnauthorized access.', result)
        self.assertEquals(['hasUser'], [m.name for m in observer.calledMethods])

    @stdout_replaced
    def testNewUserWithPOSTsucceeds(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        observer = CallTrace()
        self.form.addObserver(observer)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /return' in header)

        self.assertEquals(set(['existing', 'newuser', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('newuser', 'secret'))
        self.assertEquals('Added user "newuser"', session['BasicHtmlLoginForm.newUserFormValues']['successMessage'])
        self.assertEqual(['addUser', 'handleNewUser'], observer.calledMethodNames())
        self.assertEqual({'username': '******', 'password': '******'}, observer.calledMethods[0].kwargs)
        self.assertEqual({'Body': 'username=newuser&formUrl=%2Fpage%2FnewUser&password=secret&returnUrl=%2Freturn&retypedPassword=secret', 'username': '******'}, observer.calledMethods[1].kwargs)


    @stdout_replaced
    def testNewUserWithoutAnyUser(self):
        session = {}
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        header, body = result.split(CRLF*2)
        self.assertEquals(['admin'], pf.listUsernames())
        self.assertTrue('401' in header)

    @stdout_replaced
    def testNewUserWithoutRights(self):
        session = {'user': BasicHtmlLoginForm.User('auser')}
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))
        header, body = result.split(CRLF*2)
        self.assertEquals(['admin'], pf.listUsernames())
        self.assertTrue('401' in header)

    @stdout_replaced
    def testNewUserWithPOSTFails(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        pf.addUser('newuser', 'oldpassword')
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'newuser', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('newuser', 'oldpassword'))
        self.assertFalse(pf.validateUser('newuser', 'newpassword'))
        self.assertEquals({'errorMessage':'User already exists.', 'username':'******'}, session['BasicHtmlLoginForm.newUserFormValues'])

    @stdout_replaced
    def testNewEmptyPassword(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', oldPassword='******', newPassword='', retypedPassword='', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('existing', 'password'))
        self.assertEquals({'errorMessage':'New password is invalid.', 'username':'******'}, session['BasicHtmlLoginForm.formValues'])

    @stdout_replaced
    def testChangePassword_withEmptySession(self):
        # A.k.a. not logged-in.
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', oldPassword='******', newPassword='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {}

        result = asString(self.form.handleRequest(path='/action/changepassword', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'admin']), set(pf.listUsernames()))
        self.assertTrue(pf.validateUser('existing', 'password'))
        self.assertEquals(
            {'errorMessage': 'Login required for "change password".',
             'username': '******'},
            session['BasicHtmlLoginForm.formValues'])

    @stdout_replaced
    def testNewUserWithPOSTFailsDifferentPasswords(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('existing', 'password')
        Body = urlencode(dict(username='******', password='******', retypedPassword='******', formUrl='/page/newUser', returnUrl='/return'))
        session = {'user': BasicHtmlLoginForm.User('admin')}

        result = asString(self.form.handleRequest(path='/action/newUser', Client=('127.0.0.1', 3451), Method='POST', Body=Body, session=session))

        header, body = result.split(CRLF*2)
        self.assertTrue('302' in header)
        self.assertTrue('Location: /page/newUser' in header)

        self.assertEquals(set(['existing', 'admin']), set(pf.listUsernames()))
        self.assertEquals({'errorMessage':'Passwords do not match', 'username':'******'}, session['BasicHtmlLoginForm.newUserFormValues'])

    @stdout_replaced
    def testShowUserList(self):
        pf = PasswordFile(join(self.tempdir, 'passwd'))
        self.form.addObserver(pf)
        pf.addUser('one', 'password')
        pf.addUser('two', 'password')
        pf.addUser('three', 'password')
        def enrichUser(user):
            user.title = lambda: user.name.title()
        o = CallTrace(onlySpecifiedMethods=True, methods=dict(enrichUser=enrichUser))
        self.form.addObserver(o)

        session = {'user': self.form.loginAsUser('two')}
        session['user'].canEdit = lambda username=None: username not in ['two', 'admin']

        result = asString(self.form.userList(session=session, path='/show/login'))

        self.assertEqualsWS("""<div id="login-user-list">
    <script type="text/javascript">
function deleteUser(username) {
    if (confirm("Are you sure?")) {
        document.removeUser.username.value = username;
        document.removeUser.submit();
    }
}
</script>
<form name="removeUser" method="POST" action="/action/remove">
    <input type="hidden" name="formUrl" value="/show/login"/>
    <input type="hidden" name="username"/>
</form>
    <ul>
        <li>Admin</li>
        <li>One <a href="javascript:deleteUser('one');">delete</a></li>
        <li>Three <a href="javascript:deleteUser('three');">delete</a></li>
        <li>Two</li>
    </ul>
</div>""", result)

        result = asString(self.form.userList(session=session, path='/show/login', userLink='/user'))

        self.assertEqualsWS("""<div id="login-user-list">
    <script type="text/javascript">
function deleteUser(username) {
    if (confirm("Are you sure?")) {
        document.removeUser.username.value = username;
        document.removeUser.submit();
    }
}
</script>
<form name="removeUser" method="POST" action="/action/remove">
    <input type="hidden" name="formUrl" value="/show/login"/>
    <input type="hidden" name="username"/>
</form>
    <ul>
        <li><a href="/user?user=admin">Admin</a></li>
        <li><a href="/user?user=one">One</a> <a href="javascript:deleteUser('one');">delete</a></li>
        <li><a href="/user?user=three">Three</a> <a href="javascript:deleteUser('three');">delete</a></li>
        <li><a href="/user?user=two">Two</a></li>
    </ul>
</div>""", result)

    def testBroadcastAddUserToAllObservers(self):
        values = []
        dna = be(
            (Observable(),
                (BasicHtmlLoginForm(action="/action", loginPath="/"),
                    (CallTrace(methods={'addUser': lambda *args, **kwargs: values.append(("1st", args, kwargs))}),),
                    (CallTrace(methods={'addUser': lambda *args, **kwargs: values.append(("2nd", args, kwargs))}),),
                    (CallTrace(methods={'addUser': lambda *args, **kwargs: values.append(("3rd", args, kwargs))}),),
                )
            )
        )

        asString(dna.all.handleNewUser(session={'user': BasicHtmlLoginForm.User('admin')}, Body=urlencode(dict(password="******", retypedPassword="******", username='******'))))
        self.assertEquals(3, len(values))

    def testSetRememberMeCookie(self):
        observer = CallTrace(
            methods={
                'validateUser': lambda username, password: True,
                'createCookie': lambda user: dict(
                    cookie='THIS IS THE COOKIE VALUE',
                    header='Set-Cookie: somevalue',
                )
            },
            onlySpecifiedMethods=True,
            returnValues={'hasUser': True})

        basicHtmlLoginForm = BasicHtmlLoginForm(
            action="/action",
            loginPath="/",
            home="/index",
            rememberMeCookie=True)
        basicHtmlLoginForm._now = lambda: 3600

        dna = be(
            (Observable(),
                (basicHtmlLoginForm,
                    (observer, )
                )
            )
        )

        session = {}
        header, _ = asString(dna.all.handleRequest(
            Method="POST",
            path="/",
            session=session,
            Body=urlencode(dict(username="******", password="******", rememberMe="on"))
        )).split('\r\n\r\n', 1)

        self.assertTrue('user' in session, session)
        headers = headerToDict(header)
        self.assertEquals("/index", headers['Location'])

        self.assertTrue('Set-Cookie' in headers, headers)
        self.assertEquals("somevalue", headers['Set-Cookie'])

    def testLoginForWithRememberMe(self):
        form = BasicHtmlLoginForm(
            action='/action',
            loginPath='/login',
            home='/home',
            rememberMeCookie=True)
        result = asString(form.loginForm(session={}, path='/page/login2'))
        self.assertEqualsWS("""<div id="login-form">
    <form method="POST" name="login" action="/action">
    <input type="hidden" name="formUrl" value="/page/login2"/>
        <dl>
            <dt>Username</dt>
            <dd><input type="text" name="username" value=""/></dd>
            <dt>Password</dt>
            <dd><input type="password" name="password"/></dd>
            <dt>&nbsp;</dt><dd class="rememberMe"><input type="checkbox" name="rememberMe" id="rememberMe" /><label for="rememberMe">Remember me</label></dd>
            <dd class="submit"><input type="submit" id="submitLogin" value="Login"/></dd>
        </dl>
    </form>
    <script type="text/javascript">
        document.getElementById("submitLogin").focus()
    </script>
</div>""", result)

    def testLogout(self):
        session = {'user': '******', 'someother': 'value'}
        result = asString(self.form.logout(session=session, ignored='kwarg', Headers={}))
        self.assertEquals(redirectHttp % '/home', result)
        self.assertEqual({'someother': 'value'}, session)

    def testLogoutWithRememberMe(self):
        form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home', rememberMeCookie=True)
        observer = CallTrace(onlySpecifiedMethods=True)
        observer.returnValues['cookieName'] = 'remember-cookie'
        observer.returnValues['removeCookie'] = None
        form.addObserver(observer)
        session = {'user': '******', 'someother': 'value'}
        result = asString(form.logout(session=session, ignored='kwarg', Headers={'Cookie':'remember-cookie=cookieId;othercookie=value'}))
        self.assertEquals('HTTP/1.0 302 Found\r\nSet-Cookie: remember-cookie=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/\r\nLocation: /home\r\n\r\n', result)
        self.assertEqual({'someother': 'value'}, session)
        self.assertEqual(['cookieName', 'removeCookie'], observer.calledMethodNames())
        self.assertEquals(('cookieId',), observer.calledMethods[1].args)

    def testCanEdit(self):
        admin = BasicHtmlLoginForm.User('admin')
        other = BasicHtmlLoginForm.User('other')
        self.assertTrue(admin.canEdit('other'))
        self.assertTrue(admin.canEdit(other))
        self.assertTrue(other.canEdit('other'))
        self.assertTrue(other.canEdit(other))
        self.assertFalse(other.canEdit('admin'))
        self.assertFalse(other.canEdit(admin))
Exemple #21
0
 def testUserNoGroups(self):
     user = BasicHtmlLoginForm.User('username')
     self.groups.enrichUser(user)
     self.assertEquals(set(), user.groups())
    def setUp(self):
        SeecrTestCase.setUp(self)

        self.form = BasicHtmlLoginForm(action='/action', loginPath='/login', home='/home')