def setup(self): super().setup() self.colpath = tempfile.mkdtemp() self.configuration.set("storage", "filesystem_folder", self.colpath) self.configuration.set("storage", 'radicale_storage_by_index_fields', 'dtstart, dtend, uid, summary, organizer') self.application = Application(self.configuration, self.logger)
def _test_rights(self, rights_type, user, path, mode, expected_status, with_auth=True): assert mode in ("r", "w") assert user in ("", "tmp") htpasswd_file_path = os.path.join(self.colpath, ".htpasswd") with open(htpasswd_file_path, "w") as f: f.write("tmp:bepo\nother:bepo") self.configuration.update( { "rights": { "type": rights_type }, "auth": { "type": "htpasswd" if with_auth else "none", "htpasswd_filename": htpasswd_file_path, "htpasswd_encryption": "plain" } }, "test") self.application = Application(self.configuration) for u in ("tmp", "other"): status, _ = self.propfind("/%s/" % u, HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("%s:bepo" % u).encode()).decode()) status, _ = (self.propfind if mode == "r" else self.proppatch)( path, check=False, HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("tmp:bepo").encode()).decode() if user else "") assert status == expected_status
def _test_rights(self, rights_type, user, path, mode, expected_status, with_auth=True): assert mode in ("r", "w") assert user in ("", "tmp") htpasswd_file_path = os.path.join(self.colpath, ".htpasswd") with open(htpasswd_file_path, "w") as f: f.write("tmp:bepo\nother:bepo") self.configuration.update( { "rights": { "type": rights_type }, "auth": { "type": "htpasswd" if with_auth else "none", "htpasswd_filename": htpasswd_file_path, "htpasswd_encryption": "plain" } }, "test") self.application = Application(self.configuration) for u in ("tmp", "other"): # Indirect creation of principal collection self.propfind("/%s/" % u, login="******" % u) (self.propfind if mode == "r" else self.proppatch)( path, check=expected_status, login="******" if user else None)
def _test_htpasswd(self, htpasswd_encryption, htpasswd_content, test_matrix=None): """Test htpasswd authentication with user "tmp" and password "bepo".""" htpasswd_file_path = os.path.join(self.colpath, ".htpasswd") with open(htpasswd_file_path, "w") as f: f.write(htpasswd_content) self.configuration["auth"]["type"] = "htpasswd" self.configuration["auth"]["htpasswd_filename"] = htpasswd_file_path self.configuration["auth"]["htpasswd_encryption"] = htpasswd_encryption self.application = Application(self.configuration, self.logger) if test_matrix is None: test_matrix = ( ("tmp", "bepo", 207), ("tmp", "tmp", 401), ("tmp", "", 401), ("unk", "unk", 401), ("unk", "", 401), ("", "", 401), ) for user, password, expected_status in test_matrix: status, _, answer = self.request( "PROPFIND", "/", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode(("%s:%s" % (user, password)).encode()).decode(), ) assert status == expected_status
def _test_htpasswd(self, htpasswd_encryption, htpasswd_content, test_matrix="ascii"): """Test htpasswd authentication with user "tmp" and password "bepo" for ``test_matrix`` "ascii" or user "😀" and password "🔑" for ``test_matrix`` "unicode".""" if htpasswd_encryption == "bcrypt": try: from passlib.exc import MissingBackendError from passlib.hash import bcrypt except ImportError: pytest.skip("passlib[bcrypt] is not installed") try: bcrypt.hash("test-bcrypt-backend") except MissingBackendError: pytest.skip("bcrypt backend for passlib is not installed") htpasswd_file_path = os.path.join(self.colpath, ".htpasswd") encoding = self.configuration.get("encoding", "stock") with open(htpasswd_file_path, "w", encoding=encoding) as f: f.write(htpasswd_content) self.configuration.update({ "auth": {"type": "htpasswd", "htpasswd_filename": htpasswd_file_path, "htpasswd_encryption": htpasswd_encryption}}, "test") self.application = Application(self.configuration) if test_matrix == "ascii": test_matrix = (("tmp", "bepo", True), ("tmp", "tmp", False), ("tmp", "", False), ("unk", "unk", False), ("unk", "", False), ("", "", False)) elif test_matrix == "unicode": test_matrix = (("😀", "🔑", True), ("😀", "🌹", False), ("😁", "🔑", False), ("😀", "", False), ("", "🔑", False), ("", "", False)) for user, password, valid in test_matrix: self.propfind("/", check=207 if valid else 401, login="******" % (user, password))
def test_from_file_limited_get(self): rights_file_path = os.path.join(self.colpath, "rights") with open(rights_file_path, "w") as f: f.write("""\ [write-all] user: tmp collection: .* permissions: RrWw [limited-public] user: .* collection: public/[^/]* permissions: i""") self.configuration.update( {"rights": { "type": "from_file", "file": rights_file_path }}, "test") self.application = Application(self.configuration) self.mkcalendar("/tmp/calendar", login="******") self.mkcol("/public", login="******") self.mkcalendar("/public/calendar", login="******") self.get("/tmp/calendar", check=401) self.get("/public/", check=401) self.get("/public/calendar") self.get("/public/calendar/1.ics", check=401)
def _test_rights(self, rights_type, user, path, mode, expected_status, with_auth=True): assert mode in ("r", "w") assert user in ("", "tmp") htpasswd_file_path = os.path.join(self.colpath, ".htpasswd") with open(htpasswd_file_path, "w") as f: f.write("tmp:bepo\nother:bepo") self.configuration["rights"]["type"] = rights_type if with_auth: self.configuration["auth"]["type"] = "htpasswd" self.configuration["auth"]["htpasswd_filename"] = htpasswd_file_path self.configuration["auth"]["htpasswd_encryption"] = "plain" self.application = Application(self.configuration) for u in ("tmp", "other"): status, _, _ = self.request("PROPFIND", "/%s" % u, HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("%s:bepo" % u).encode()).decode()) assert status == 207 status, _, _ = self.request( "PROPFIND" if mode == "r" else "PROPPATCH", path, HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("tmp:bepo").encode()).decode() if user else "") assert status == expected_status
def test_custom(self): """Custom web plugin.""" self.configuration["web"]["type"] = "tests.custom.web" self.application = Application(self.configuration) status, _, answer = self.request("GET", "/.web") assert status == 200 assert answer == "custom"
def setup(self): self.configuration = config.load() self.colpath = tempfile.mkdtemp() self.configuration["storage"]["filesystem_folder"] = self.colpath # Disable syncing to disk for better performance self.configuration["internal"]["filesystem_fsync"] = "False" self.application = Application(self.configuration)
def test_authentication(self): """Test if server sends authentication request.""" self.configuration.set("rights", "type", "owner_only") self.application = Application(self.configuration, self.logger) status, headers, answer = self.request("MKCOL", "/user/") assert status in (401, 403) assert headers.get("WWW-Authenticate")
def test_none(self): self.configuration.update({"web": {"type": "none"}}, "test") self.application = Application(self.configuration) _, answer = self.get("/.web") assert answer self.get("/.web/", check=404) self.post("/.web", check=405)
def test_custom(self): """Custom authentication.""" self.configuration.update( {"auth": { "type": "radicale.tests.custom.auth" }}, "test") self.application = Application(self.configuration) self.propfind("/tmp/", login="******")
def test_none(self): self.configuration["web"]["type"] = "none" self.application = Application(self.configuration) status, _, answer = self.request("GET", "/.web") assert status == 200 assert answer status, _, answer = self.request("GET", "/.web/") assert status == 404
def test_custom(self): """Custom web plugin.""" self.configuration.update({ "web": {"type": "tests.custom.web"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request("GET", "/.web") assert status == 200 assert answer == "custom"
def setup(self): self.configuration = config.load() self.colpath = tempfile.mkdtemp() self.configuration.update({ "storage": {"filesystem_folder": self.colpath}, # Disable syncing to disk for better performance "internal": {"filesystem_fsync": "False"}}, "test", internal=True) self.application = Application(self.configuration)
def test_none(self): self.configuration.update({"web": {"type": "none"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request("GET", "/.web") assert status == 200 assert answer status, _, answer = self.request("GET", "/.web/") assert status == 404
def test_put_collections_and_items(self): """Test rights for creation of calendars and items with PUT.""" self.application = Application(self.configuration) self.put("/user/", "BEGIN:VCALENDAR\r\nEND:VCALENDAR", check=401) self.mkcol("/user/") self.put("/user/calendar/", "BEGIN:VCALENDAR\r\nEND:VCALENDAR") event1 = get_file_content("event1.ics") self.put("/user/calendar/event1.ics", event1)
def test_custom(self): """Custom authentication.""" self.configuration["auth"]["type"] = "tests.custom.auth" self.application = Application(self.configuration, self.logger) status, _, answer = self.request( "PROPFIND", "/tmp", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode(("tmp:").encode()).decode()) assert status == 207
def test_custom(self): """Custom authentication.""" self.configuration.update( {"auth": {"type": "radicale.tests.custom.auth"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request( "PROPFIND", "/tmp", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode(("tmp:").encode()).decode()) assert status == 207
def test_custom(self): """Custom web plugin.""" self.configuration.update( {"web": { "type": "radicale.tests.custom.web" }}, "test") self.application = Application(self.configuration) _, answer = self.get("/.web") assert answer == "custom"
def test_authentication(self): """Test if server sends authentication request.""" self.configuration["auth"]["type"] = "htpasswd" self.configuration["auth"]["htpasswd_filename"] = os.devnull self.configuration["auth"]["htpasswd_encryption"] = "plain" self.configuration["rights"]["type"] = "owner_only" self.application = Application(self.configuration, self.logger) status, headers, answer = self.request("MKCOL", "/user/") assert status in (401, 403) assert headers.get("WWW-Authenticate")
def test_custom(self): """Custom authentication.""" self.configuration.update( {"auth": { "type": "radicale.tests.custom.auth" }}, "test") self.application = Application(self.configuration) self.propfind("/tmp/", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("tmp:").encode()).decode())
def test_env_not_set(self): self._reset_env() self.configuration.update({"auth": {"type": "env"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request( "PROPFIND", "/", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("%s:%s" % ('admin', 'password')).encode()).decode()) assert status == 401
def setup(self): self.configuration = config.load() self.configuration["storage"]["type"] = self.storage_type self.colpath = tempfile.mkdtemp() self.configuration["storage"]["filesystem_folder"] = self.colpath # Disable syncing to disk for better performance self.configuration["storage"]["filesystem_fsync"] = "False" # Required on Windows, doesn't matter on Unix self.configuration["storage"]["filesystem_close_lock_file"] = "True" self.application = Application(self.configuration, self.logger)
def setup(self): self.configuration = config.load() self.configuration.set("storage", "type", self.storage_type) self.logger = logging.getLogger("radicale_test") self.colpath = tempfile.mkdtemp() self.configuration.set("storage", "filesystem_folder", self.colpath) # Disable syncing to disk for better performance self.configuration.set("storage", "filesystem_fsync", "False") # Required on Windows, doesn't matter on Unix self.configuration.set("storage", "close_lock_file", "True") self.application = Application(self.configuration, self.logger)
def test_custom(self): """Custom authentication.""" configuration = config.load() configuration.set("auth", "type", "tests.custom.auth") self.application = Application(configuration, logging.getLogger("radicale_test")) status, headers, answer = self.request( "GET", "/", HTTP_AUTHORIZATION="dG1wOmJlcG8=") assert status == 200 assert "Radicale works!" in answer
def test_env_set_password_wrong(self): os.environ["RADICALE_LOGIN"] = '******' os.environ["RADICALE_PASSWORD"] = '******' self.configuration.update({"auth": {"type": "env"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request( "PROPFIND", "/", HTTP_AUTHORIZATION="Basic %s" % base64.b64encode( ("%s:%s" % ('admin', 'password')).encode()).decode()) assert status == 401 self._reset_env()
def test_remote_user(self): self.configuration.update({"auth": {"type": "remote_user"}}, "test") self.application = Application(self.configuration) status, _, answer = self.request( "PROPFIND", "/", """<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"> <prop> <current-user-principal /> </prop> </propfind>""", REMOTE_USER="******") assert status == 207 assert ">/test/<" in answer
def test_remote_user(self): self.configuration.update({"auth": {"type": "remote_user"}}, "test") self.application = Application(self.configuration) _, responses = self.propfind("/", """\ <?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"> <prop> <current-user-principal /> </prop> </propfind>""", REMOTE_USER="******") status, prop = responses["/"]["D:current-user-principal"] assert status == 200 assert prop.find(xmlutils.make_clark("D:href")).text == "/test/"
def test_http_x_remote_user(self): self.configuration["auth"]["type"] = "http_x_remote_user" self.application = Application(self.configuration, self.logger) status, _, answer = self.request( "PROPFIND", "/", """<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"> <prop> <current-user-principal /> </prop> </propfind>""", HTTP_X_REMOTE_USER="******") assert status == 207 assert ">/test/<" in answer
test_events = gen_events() def get_col(): return list(app.Collection.discover(environ['PATH_INFO'], '0')) for type in ('multifilesystem', 'radicale_timerange_indexed_storage'): if len(sys.argv) > 2 and type not in sys.argv[2:]: continue shutil.rmtree(collection_folder, True) os.mkdir(collection_folder) app = Application( load(extra_config=dict( storage=dict( type=type, filesystem_folder=collection_folder ))), getLogger('rt')) collections = get_col() app.do_MKCALENDAR(environ, collections, collections, mkcal, None) collections = get_col() t0 = time() app.do_PUT(environ, collections, collections, test_events, None) print('PUT using %s %f' % (type, time() - t0)) def f(y): return y['y'], y['m'], y['d'], y['h']