Просмотр исходного кода

Merge branch 'master' of git://github.com/cristen/Radicale into cristen-master

Conflicts:
	radicale/storage/database.py
	schema.sql
Guillaume Ayoub 12 лет назад
Родитель
Сommit
fae2b30ec4
5 измененных файлов с 65 добавлено и 48 удалено
  1. 4 0
      config
  2. 3 1
      radicale/__init__.py
  3. 2 0
      radicale/config.py
  4. 35 29
      radicale/storage/database.py
  5. 21 18
      schema.sql

+ 4 - 0
config

@@ -25,6 +25,10 @@ ssl = False
 certificate = /etc/apache2/ssl/server.crt
 # SSL private key
 key = /etc/apache2/ssl/server.key
+# SSL Protocol used. See python's ssl module for available values
+protocol = PROTOCOL_SSLv23
+# Ciphers available. See python's ssl module for available ciphers
+ciphers =
 # Reverse DNS to resolve client address in logs
 dns_lookup = True
 # Root URL of Radicale (starting and ending with a slash)

+ 3 - 1
radicale/__init__.py

@@ -98,7 +98,9 @@ class HTTPSServer(HTTPServer):
             server_side=True,
             certfile=config.get("server", "certificate"),
             keyfile=config.get("server", "key"),
-            ssl_version=ssl.PROTOCOL_SSLv23)
+            ssl_version=getattr(ssl, config.get("server", "protocol"),
+                                ssl.PROTOCOL_SSLv23),
+            ciphers=config.get("server", "ciphers") or None)
 
         self.server_bind()
         self.server_activate()

+ 2 - 0
radicale/config.py

@@ -45,6 +45,8 @@ INITIAL_CONFIG = {
         "ssl": "False",
         "certificate": "/etc/apache2/ssl/server.crt",
         "key": "/etc/apache2/ssl/server.key",
+        "protocol": "PROTOCOL_SSLv23",
+        "ciphers": "",
         "dns_lookup": "True",
         "base_prefix": "/",
         "realm": "Radicale - Password Required"},

+ 35 - 29
radicale/storage/database.py

@@ -24,7 +24,7 @@ SQLAlchemy storage backend.
 import time
 from datetime import datetime
 from contextlib import contextmanager
-from sqlalchemy import create_engine, Column, String, DateTime, ForeignKey
+from sqlalchemy import create_engine, Column, Unicode, Integer, ForeignKey
 from sqlalchemy import func
 from sqlalchemy.orm import sessionmaker, relationship
 from sqlalchemy.ext.declarative import declarative_base
@@ -44,17 +44,20 @@ class DBCollection(Base):
     """Table of collections."""
     __tablename__ = "collection"
 
-    path = Column(String, primary_key=True)
-    parent_path = Column(String)
+    path = Column(Unicode, primary_key=True)
+    parent_path = Column(Unicode, ForeignKey("collection.path"))
+
+    parent = relationship(
+        "DBCollection", backref="children", remote_side=[path])
 
 
 class DBItem(Base):
     """Table of collection's items."""
     __tablename__ = "item"
 
-    name = Column(String, primary_key=True)
-    tag = Column(String)
-    collection_path = Column(String, ForeignKey("collection.path"))
+    name = Column(Unicode, primary_key=True)
+    tag = Column(Unicode)
+    collection_path = Column(Unicode, ForeignKey("collection.path"))
 
     collection = relationship("DBCollection", backref="items")
 
@@ -63,10 +66,10 @@ class DBHeader(Base):
     """Table of item's headers."""
     __tablename__ = "header"
 
-    key = Column(String, primary_key=True)
-    value = Column(String)
+    name = Column(Unicode, primary_key=True)
+    value = Column(Unicode)
     collection_path = Column(
-        String, ForeignKey("collection.path"), primary_key=True)
+        Unicode, ForeignKey("collection.path"), primary_key=True)
 
     collection = relationship("DBCollection", backref="headers")
 
@@ -75,23 +78,23 @@ class DBLine(Base):
     """Table of item's lines."""
     __tablename__ = "line"
 
-    key = Column(String)
-    value = Column(String)
-    item_name = Column(String, ForeignKey("item.name"))
-    timestamp = Column(DateTime, default=datetime.now, primary_key=True)
+    name = Column(Unicode)
+    value = Column(Unicode)
+    item_name = Column(Unicode, ForeignKey("item.name"))
+    timestamp = Column(
+        Integer, default=lambda: time.time() * 10 ** 6, primary_key=True)
 
-    item = relationship(
-        "DBItem", backref="lines", order_by=timestamp)
+    item = relationship("DBItem", backref="lines", order_by=timestamp)
 
 
 class DBProperty(Base):
     """Table of collection's properties."""
     __tablename__ = "property"
 
-    key = Column(String, primary_key=True)
-    value = Column(String)
+    name = Column(Unicode, primary_key=True)
+    value = Column(Unicode)
     collection_path = Column(
-        String, ForeignKey("collection.path"), primary_key=True)
+        Unicode, ForeignKey("collection.path"), primary_key=True)
 
     collection = relationship(
         "DBCollection", backref="properties", cascade="delete")
@@ -116,17 +119,20 @@ class Collection(ical.Collection):
                 .order_by(DBItem.name).all())
             for item in items:
                 text = "\n".join(
-                    "%s:%s" % (line.key, line.value) for line in item.lines)
+                    "%s:%s" % (line.name, line.value) for line in item.lines)
                 item_objects.append(item_type(text, item.name))
         return item_objects
 
     @property
     def _modification_time(self):
         """Collection's last modification time."""
-        return (
+        timestamp = (
             self.session.query(func.max(DBLine.timestamp))
-            .join(DBItem).filter_by(collection_path=self.path).first()[0]
-            or datetime.now())
+            .join(DBItem).filter_by(collection_path=self.path).first()[0])
+        if timestamp:
+            return datetime.fromtimestamp(float(timestamp) / 10 ** 6)
+        else:
+            return datetime.now()
 
     @property
     def _db_collection(self):
@@ -154,7 +160,7 @@ class Collection(ical.Collection):
 
         for header in headers:
             db_header = DBHeader()
-            db_header.key, db_header.value = header.text.split(":", 1)
+            db_header.name, db_header.value = header.text.split(":", 1)
             db_header.collection_path = self.path
             self.session.add(db_header)
 
@@ -167,7 +173,7 @@ class Collection(ical.Collection):
 
             for line in ical.unfold(item.text):
                 db_line = DBLine()
-                db_line.key, db_line.value = line.split(":", 1)
+                db_line.name, db_line.value = line.split(":", 1)
                 db_line.item_name = item.name
                 self.session.add(db_line)
 
@@ -187,9 +193,9 @@ class Collection(ical.Collection):
         headers = (
             self.session.query(DBHeader)
             .filter_by(collection_path=self.path)
-            .order_by(DBHeader.key).all())
+            .order_by(DBHeader.name).all())
         return [
-            ical.Header("%s:%s" % (header.key, header.value))
+            ical.Header("%s:%s" % (header.name, header.value))
             for header in headers]
 
     @classmethod
@@ -238,16 +244,16 @@ class Collection(ical.Collection):
             self.session.query(DBProperty)
             .filter_by(collection_path=self.path).all())
         for prop in db_properties:
-            properties[prop.key] = prop.value
+            properties[prop.name] = prop.value
         old_properties = properties.copy()
         yield properties
         # On exit
         if self._db_collection and old_properties != properties:
             for prop in db_properties:
                 self.session.delete(prop)
-            for key, value in properties.items():
+            for name, value in properties.items():
                 prop = DBProperty()
-                prop.key = key
+                prop.name = name
                 prop.value = value
                 prop.collection_path = self.path
                 self.session.add(prop)

+ 21 - 18
schema.sql

@@ -1,28 +1,31 @@
--- This is the database schema for PostgreSQL.
+-- This is the database schema for PostgreSQL and MySQL and SQLite.
 
 create table collection (
-       path varchar primary key not null,
-       parent_path varchar not null);
+       path varchar(200) not null,
+       parent_path varchar(200) references collection (path),
+       primary key (path));
 
 create table item (
-       name varchar primary key not null,
-       tag varchar not null,
-       collection_path varchar references collection (path) not null);
+       name varchar(200) not null,
+       tag text not null,
+       collection_path varchar(200) references collection (path),
+       primary key (name));
 
 create table header (
-       key varchar not null,
-       value varchar not null,
-       collection_path varchar references collection (path) not null,
-       primary key (key, collection_path));
+       name varchar(200) not null,
+       value text not null,
+       collection_path varchar(200) references collection (path),
+       primary key (name, collection_path));
 
 create table line (
-       key varchar not null,
-       value varchar not null,
-       item_name varchar references item (name) not null,
-       timestamp timestamp not null);
+       name text not null,
+       value text not null,
+       item_name varchar(200) references item (name),
+       timestamp bigint not null,
+       primary key (timestamp));
 
 create table property (
-       key varchar not null,
-       value varchar not null,
-       collection_path varchar references collection (path) not null,
-       primary key (key, collection_path));
+       name varchar(200) not null,
+       value text not null,
+       collection_path varchar(200) references collection (path),
+       primary key (name, collection_path));