소스 검색

Merge branch 'master' into lightning

Guillaume Ayoub 14 년 전
부모
커밋
264bc66051
10개의 변경된 파일82개의 추가작업 그리고 13개의 파일을 삭제
  1. 2 1
      NEWS
  2. 4 0
      config
  3. 9 0
      radicale.py
  4. 26 0
      radicale.wsgi
  5. 14 6
      radicale/__init__.py
  6. 3 3
      radicale/acl/LDAP.py
  7. 18 0
      radicale/acl/__init__.py
  8. 2 2
      radicale/acl/htpasswd.py
  9. 4 0
      radicale/config.py
  10. 0 1
      setup.py

+ 2 - 1
NEWS

@@ -14,7 +14,8 @@
 * Smart, verbose and configurable logs
 * Apple iCal 4 and iPhone support (by Łukasz Langa)
 * LDAP auth backend (by Corentin Le Bail)
-* Owner-less calendars (by René Neumann)
+* Public and private calendars (by René Neumann)
+* PID file
 * Journal entries support
 * Drop Python 2.5 support
 

+ 4 - 0
config

@@ -36,6 +36,10 @@ stock = utf-8
 # Access method
 # Value: None | htpasswd | LDAP
 type = None
+# Usernames used for public calendars, separated by a comma
+public_users = public
+# Usernames used for private calendars, separated by a comma
+private_users = private
 # Htpasswd filename
 htpasswd_filename = /etc/radicale/users
 # Htpasswd encryption method

+ 9 - 0
radicale.py

@@ -32,6 +32,7 @@ Launch the server according to configuration and command-line options.
 
 """
 
+import atexit
 import os
 import sys
 import optparse
@@ -101,6 +102,14 @@ if options.daemon:
             sys.exit()
     sys.stdout = sys.stderr = open(os.devnull, "w")
 
+# Register exit function
+def cleanup():
+    radicale.log.LOGGER.debug("Cleaning up")
+    # Remove PID file
+    if options.pid and options.daemon:
+        os.unlink(options.pid)
+
+atexit.register(cleanup)
 radicale.log.LOGGER.info("Starting Radicale")
 
 # Create calendar servers

+ 26 - 0
radicale.wsgi

@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# This file is part of Radicale Server - Calendar Server
+# Copyright © 2011 Guillaume Ayoub
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Radicale WSGI file (mod_wsgi and uWSGI compliant).
+
+"""
+
+import radicale
+application = radicale.Application()

+ 14 - 6
radicale/__init__.py

@@ -183,16 +183,24 @@ class Application(object):
                     if last_allowed:
                         calendars.append(calendar)
                     continue
-                log.LOGGER.info(
-                    "Checking rights for calendar owned by %s" % calendar.owner)
 
-                if self.acl.has_right(calendar.owner, user, password):
-                    log.LOGGER.info("%s allowed" % (user or "anonymous user"))
+                if calendar.owner in acl.PUBLIC_USERS:
+                    log.LOGGER.info("Public calendar")
                     calendars.append(calendar)
                     last_allowed = True
                 else:
-                    log.LOGGER.info("%s refused" % (user or "anonymous user"))
-                    last_allowed = False
+                    log.LOGGER.info(
+                        "Checking rights for calendar owned by %s" % (
+                            calendar.owner or "nobody"))
+                    if self.acl.has_right(calendar.owner, user, password):
+                        log.LOGGER.info(
+                            "%s allowed" % (user or "Anonymous user"))
+                        calendars.append(calendar)
+                        last_allowed = True
+                    else:
+                        log.LOGGER.info(
+                            "%s refused" % (user or "Anonymous user"))
+                        last_allowed = False
 
             if calendars:
                 status, headers, answer = function(environ, calendars, content)

+ 3 - 3
radicale/acl/LDAP.py

@@ -26,7 +26,7 @@ Authentication based on the ``python-ldap`` module
 """
 
 import ldap
-from radicale import config, log
+from radicale import acl, config, log
 
 
 BASE = config.get("acl", "ldap_base")
@@ -38,8 +38,8 @@ PASSWORD = config.get("acl", "ldap_password")
 
 def has_right(owner, user, password):
     """Check if ``user``/``password`` couple is valid."""
-    if not user or (owner and user != owner):
-        # No user given, or owner is set and is not user, forbidden
+    if not user or (owner not in acl.PRIVATE_USERS and user != owner):
+        # No user given, or owner is not private and is not user, forbidden
         return False
 
     if BINDDN and PASSWORD:

+ 18 - 0
radicale/acl/__init__.py

@@ -29,11 +29,29 @@ configuration.
 from radicale import config
 
 
+PUBLIC_USERS = []
+PRIVATE_USERS = []
+
+
+def _config_users(name):
+    """Get an iterable of strings from the configuraton string [acl] ``name``.
+
+    The values must be separated by a comma. The whitespace characters are
+    stripped at the beginning and at the end of the values.
+
+    """
+    for user in config.get("acl", name).split(","):
+        user = user.strip()
+        yield None if user == "None" else user
+
+
 def load():
     """Load list of available ACL managers."""
     acl_type = config.get("acl", "type")
     if acl_type == "None":
         return None
     else:
+        PUBLIC_USERS.extend(_config_users("public_users"))
+        PRIVATE_USERS.extend(_config_users("private_users"))
         module = __import__("radicale.acl", fromlist=[acl_type])
         return getattr(module, acl_type)

+ 2 - 2
radicale/acl/htpasswd.py

@@ -30,7 +30,7 @@ supported, but md5 is not (see ``htpasswd`` man page to understand why).
 import base64
 import hashlib
 
-from radicale import config
+from radicale import acl, config
 
 
 FILENAME = config.get("acl", "htpasswd_filename")
@@ -63,6 +63,6 @@ def has_right(owner, user, password):
     for line in open(FILENAME).readlines():
         if line.strip():
             login, hash_value = line.strip().split(":")
-            if login == user and (not owner or owner == user):
+            if login == user and (owner in acl.PRIVATE_USERS or owner == user):
                 return globals()["_%s" % ENCRYPTION](hash_value, password)
     return False

+ 4 - 0
radicale/config.py

@@ -50,6 +50,8 @@ INITIAL_CONFIG = {
         "stock": "utf-8"},
     "acl": {
         "type": "None",
+        "public_users": "public",
+        "private_users": "private",
         "httpasswd_filename": "/etc/radicale/users",
         "httpasswd_encryption": "crypt",
         "ldap_url": "ldap://localhost:389/",
@@ -74,6 +76,8 @@ for section, values in INITIAL_CONFIG.items():
 
 _CONFIG_PARSER.read("/etc/radicale/config")
 _CONFIG_PARSER.read(os.path.expanduser("~/.config/radicale/config"))
+if 'RADICALE_CONFIG' in os.environ:
+    _CONFIG_PARSER.read(os.environ['RADICALE_CONFIG'])
 
 # Wrap config module into ConfigParser instance
 sys.modules[__name__] = _CONFIG_PARSER

+ 0 - 1
setup.py

@@ -88,7 +88,6 @@ setup(
         "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.0",
         "Programming Language :: Python :: 3.1",
         "Programming Language :: Python :: 3.2",
         "Topic :: Office/Business :: Groupware"])