Merge branch 'master' into lightning
This commit is contained in:
		
							
								
								
									
										3
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								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
									
								
								config
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								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 | ||||
|   | ||||
| @@ -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
									
								
								radicale.wsgi
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								radicale.wsgi
									
									
									
									
									
										Executable file
									
								
							| @@ -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() | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										1
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										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"]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Guillaume Ayoub
					Guillaume Ayoub