source: main/waeup.kofa/trunk/src/waeup/kofa/tests/test_kpasswd.py @ 17867

Last change on this file since 17867 was 17820, checked in by uli, 6 months ago

Add kpasswd for generating/setting kofa passwords.

File size: 8.1 KB
Line 
1# -*- coding: utf-8 -*-
2## $Id$d$: test_smtp.py 16428 2021-03-23 13:15:55Z henrik $
3##
4## Copyright (C) 2024 Uli Fouquet & Henrik Bettermann
5## This program is free software; you can redistribute it and/or modify
6## it under the terms of the GNU General Public License as published by
7## the Free Software Foundation; either version 2 of the License, or
8## (at your option) any later version.
9##
10## This program is distributed in the hope that it will be useful,
11## but WITHOUT ANY WARRANTY; without even the implied warranty of
12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13## GNU General Public License for more details.
14##
15## You should have received a copy of the GNU General Public License
16## along with this program; if not, write to the Free Software
17## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18##
19# Tests for kpasswd hash generator
20from __future__ import unicode_literals
21import mock
22import os
23import sys
24import tempfile
25import unittest
26import waeup.kofa.kpasswd
27
28try:
29    from StringIO import StringIO  # py2
30except ImportError:
31    from io import StringIO  # py3
32
33
34SITE_ZCML_TEMPL = """
35<configure xmlns="http://namespaces.zope.org/zope"
36           xmlns:browser="http://namespaces.zope.org/browser"
37           xmlns:kofa="http://namespaces.waeup.org/kofa"
38           i18n_domain="waeup.kofa">
39
40  <include package="waeup.kofa" />
41  <include package="waeup.kofa" file="mail.zcml" />
42  <!-- install job container
43
44       install a job container for asynchronous jobs. Pick one of the
45       two possibilites: 'single' for installation in the one big ZODB
46       or 'multidb' for setup with a dedicated ZODB for job handling.
47  -->
48  <!-- include package="waeup.kofa" file="async_single.zcml" / -->
49  <include package="waeup.kofa" file="async_multidb.zcml" />
50
51  <!-- install dispatcher and other needed async components
52
53       install other needed components for asynchronous jobs. Pick one
54       of the two possibilities: 'basic_dispatcher' for single ZODB
55       setup, 'multidb_dispatcher' for setup with a dedicated ZODB for
56       job handling. Make sure the setting matches the setting picked
57       above. -->
58  <!-- include package="zc.async" file="basic_dispatcher_policy.zcml" / -->
59  <include package="zc.async" file="multidb_dispatcher_policy.zcml" />
60
61  <!-- Where should the datacenter reside by default? -->
62  <kofa:datacenter
63      path="/home/kofa/waeup.kofa/trunk/var/datacenter" />
64
65    <configure i18n_domain="waeup.kofa">
66
67
68      <unauthenticatedPrincipal id="zope.anybody"
69                                title="Unauthenticated User" />
70      <unauthenticatedGroup id="zope.Anybody"
71                            title="Unauthenticated Users" />
72      <authenticatedGroup id="zope.Authenticated"
73                        title="Authenticated Users" />
74      <everybodyGroup id="zope.Everybody"
75                      title="All Users" />
76      <principal id="zope.manager"
77                 title="Manager"
78                 login="grok"
79                 password_manager="SHA1"
80                 password="321b9cd3739bd029629243732eb682db005a7541f7509622"
81                 />
82
83      <!-- XMLRPC user for demo and testing
84           Plaintext password is changeme
85           Don't use it in real deployment -->
86      <principal id="zope.xmlrpcuser1"
87                 title="XMLRPC User 1"
88                 login="xmlrpcuser1"
89                 password="{SSHA}WQ0Mr9Sf7Sc_wxyNaMzjxib3nFFN0Jf0"
90                 password_manager="SSHA"
91                 />
92
93      <grant role="waeup.xmlrpcusers1"
94             principal="zope.xmlrpcuser1" />
95
96
97      <!-- Replace the following directive if you do not want
98           public access -->
99      <grant permission="zope.app.dublincore.view"
100             principal="zope.Anybody" />
101      <grant permission="zope.View"
102             principal="zope.Authenticated" />
103      <grant permission="zope.app.dublincore.view"
104             principal="zope.Authenticated" />
105      <grant permission="waeup.Public"
106             principal="zope.Everybody" />
107      <grant permission="waeup.Anonymous"
108             principal="zope.Anybody" />
109      <grant permission="waeup.Authenticated"
110             principal="zope.Authenticated" />
111
112      <role id="zope.Manager" title="Site Manager" />
113      <grantAll role="zope.Manager" />
114      <grant role="zope.Manager"
115             principal="zope.manager" />
116   </configure>
117
118   <!-- session -->
119   <browser:beakerSession
120        key="waeup.kofa.session.id"
121        secret="KofaRocks"
122        timeout="3600"
123        type="cookie"
124        validate_key="thisMightBeChanged"
125        />
126
127</configure>
128"""
129
130
131class KPasswordTests(unittest.TestCase):
132
133    def setUp(self):
134        self.workdir = tempfile.mkdtemp()
135        self.site_zcml = os.path.join(self.workdir, "site.zcml")
136        open(self.site_zcml, "w").write(SITE_ZCML_TEMPL)
137        pass
138
139    @mock.patch("sys.stderr", new_callable=StringIO)
140    def test_parse_args_req_at_least_1_arg(self, mock_err):
141        # we require at least one argument (the password)
142        with self.assertRaises(SystemExit) as cm:
143            waeup.kofa.kpasswd.parse_args(["kpasswd"])
144        self.assertEqual(cm.exception.code, 2)
145        self.assertTrue("error: too few arguments" in mock_err.getvalue())
146
147    @mock.patch("sys.stdout", new_callable=StringIO)
148    def test_main_callable(self, mock_out):
149        result = waeup.kofa.kpasswd.main(["kpasswd", "foo"])
150        output = mock_out.getvalue()
151        self.assertEqual(result, 0)
152        self.assertTrue(output.startswith("{SSHA}"))
153
154    @mock.patch("sys.stderr", new_callable=StringIO)
155    def test_main_considers_argv(self, mock_err):
156        with mock.patch.object(
157            sys,
158            "argv",
159            [
160                "kpasswd-mark1",
161            ],
162        ):
163            waeup.kofa.kpasswd.main()
164        self.assertTrue(
165            "kpasswd-mark1: error: too few arguments" in mock_err.getvalue()
166        )
167
168    @mock.patch("sys.stdout", new_callable=StringIO)
169    def test_application_hash_password(self, mock_out):
170        # we can show an hashed password (SSHA)
171        options = waeup.kofa.kpasswd.parse_args(["kpasswd", "mypassword"])
172        app = waeup.kofa.kpasswd.Application(options)
173        app.run()
174        output = mock_out.getvalue()
175        self.assertTrue(output.startswith("{SSHA}"))
176
177    @mock.patch("sys.stdout", new_callable=StringIO)
178    def test_application_update_site_zcml(self, mock_out):
179        # we can update a given site.zcml file
180        options = waeup.kofa.kpasswd.parse_args(
181            ["kpasswd", "-c", self.site_zcml, "mypassword"]
182        )
183        app = waeup.kofa.kpasswd.Application(options)
184        old_content = open(self.site_zcml).read()
185        app.run()
186        output = mock_out.getvalue()
187        # we get a message, that the file was updated
188        self.assertTrue("Updated: %s" % self.site_zcml in output)
189        new_content = open(self.site_zcml).read()
190        # password hash has changed
191        self.assertNotEqual(old_content, new_content)
192        self.assertTrue("321b9cd3739bd029629243732eb682" not in new_content)
193
194    @mock.patch("sys.stdout", new_callable=StringIO)
195    def test_application_change_non_default_users(self, mock_out):
196        # we can change also users not being `grok`
197        options = waeup.kofa.kpasswd.parse_args(
198            [
199                "kpasswd",
200                "-c",
201                self.site_zcml,
202                "--id",
203                "zope.xmlrpcuser1",
204                "-l",
205                "xmlrpcuser1",
206                "mypassword",
207            ]
208        )
209        app = waeup.kofa.kpasswd.Application(options)
210        old_content = open(self.site_zcml).read()
211        app.run()
212        output = mock_out.getvalue()
213        # we get a message, that the file was updated
214        self.assertTrue("Updated: %s" % self.site_zcml in output)
215        new_content = open(self.site_zcml).read()
216        # password hash has changed
217        self.assertNotEqual(old_content, new_content)
218        # but this time not the one of the zope.manager...
219        self.assertTrue("321b9cd3739bd029629243732eb682" in new_content)
220        self.assertTrue("{SSHA}WQ0Mr9Sf7Sc_wxyNaMzjxib3nFFN0Jf0" not in new_content)
Note: See TracBrowser for help on using the repository browser.