Doc Webdav: implement model for DAV properties (at dirs)
authorP. Christeas <p_christ@hol.gr>
Tue, 12 Oct 2010 10:38:59 +0000 (13:38 +0300)
committerP. Christeas <p_christ@hol.gr>
Tue, 12 Oct 2010 10:38:59 +0000 (13:38 +0300)
In normative setups of WebDAV, we need to place some extra properties
on selected directories.

bzr revid: p_christ@hol.gr-20101012103859-dcwsrzylxwpzbpq1

addons/document_webdav/__openerp__.py
addons/document_webdav/document_webdav.py
addons/document_webdav/nodes.py
addons/document_webdav/security/ir.model.access.csv [new file with mode: 0644]
addons/document_webdav/webdav_view.xml [new file with mode: 0644]

index 39330f6..4daaa88 100644 (file)
@@ -30,7 +30,7 @@
 
 {
        "name" : "WebDAV server for Document Management",
-       "version" : "2.0",
+       "version" : "2.1",
        "author" : "OpenERP SA",
        "category" : "Generic Modules/Others",
        "website": "http://www.openerp.com",
@@ -41,7 +41,7 @@
 """,
        "depends" : ["base", "document"],
        "init_xml" : [],
-       "update_xml" : [],
+       "update_xml" : ['security/ir.model.access.csv', "webdav_view.xml", ],
        "demo_xml" : [],
        "active": False,
        "installable": True
index 2db183e..fb0b62c 100644 (file)
@@ -25,6 +25,11 @@ import nodes
 class document_davdir(osv.osv):
     _inherit = 'document.directory'
 
+    _columns = {
+        # Placed here just for a reference
+        'dav_prop_ids': fields.one2many('document.webdav.dir.property', 'dir_id', 'DAV properties'),
+        }
+
     def get_node_class(self, cr, uid, ids, dbro=None, context=None):
         # Note: in this function, nodes come from document_webdav/nodes.py !
         if dbro is None:
@@ -43,5 +48,40 @@ class document_davdir(osv.osv):
         nctx.node_file_class = nodes.node_file
         return
 
+    def _locate_child(self, cr, uid, root_id, uri,nparent, ncontext):
+        """ try to locate the node in uri,
+            Return a tuple (node_dir, remaining_path)
+        """
+        return (nodes.node_database(context=ncontext), uri)
+
 document_davdir()
+
+class dav_dir_property(osv.osv):
+    """ Arbitrary WebDAV properties, attached to document.directories.
+    
+    Some DAV properties have to be settable at directories, depending
+    on the database directory structure.
+    
+    Example would be the principal-URL.
+    
+    There _can_ be properties without a directory, which means that they
+    globally apply to all the directories (aka. collections) of the
+    present database.
+    """
+    _name = 'document.webdav.dir.property'
+    
+    _columns = {
+        'dir_id': fields.many2one('document.directory', 'Directory', required=False, select=1),
+        'namespace': fields.char('Namespace', size=127, required=True),
+        'name': fields.char('Name', size=64, required=True),
+        'value': fields.text('Value'),
+        'do_subst': fields.boolean('Substitute', required=True),
+        }
+        
+    _defaults = {
+        'do_subst': False,
+        }
+        
+dav_dir_property()
+
 #eof
\ No newline at end of file
index 6e9d85a..ce847ef 100644 (file)
@@ -21,6 +21,8 @@
 
 
 from document import nodes
+from tools.safe_eval import safe_eval as eval
+import urllib
 
 class node_acl_mixin(object):
     def _get_dav_owner(self, cr):
@@ -35,7 +37,76 @@ class node_acl_mixin(object):
     def _get_dav_current_user_privilege_set(self, cr):
         return '' # TODO
 
+    def _get_dav_props_hlpr(self, cr, par_class, prop_model, 
+                            prop_ref_field, res_id):
+        """ Helper for dav properties, usable in subclasses
+        
+        @param par_class The parent class
+        @param prop_model The name of the orm model holding the properties
+        @param prop_ref_field The name of the field at prop_model pointing to us
+        @param res_id the id of self in the corresponing orm table, that should
+                        match prop_model.prop_ref_field
+        """
+        ret = par_class.get_dav_props(self, cr)
+        if prop_model:
+            propobj = self.context._dirobj.pool.get(prop_model)
+            uid = self.context.uid
+            ctx = self.context.context.copy()
+            ctx.update(self.dctx)
+            sdomain = [(prop_ref_field, '=', False),]
+            if res_id:
+                sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
+            prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
+            if prop_ids:
+                ret = ret.copy()
+                for pbro in propobj.browse(cr, uid, prop_ids, context=ctx):
+                    ret[pbro.namespace] = ret.get(pbro.namespace, ()) + \
+                        (pbro.name,)
+                    # Note that we cannot have properties to conditionally appear
+                    # on the context, yet.
+                
+        return ret
+
+    def _get_dav_eprop_hlpr(self, cr, ns, prop,
+                            par_class, prop_model, 
+                            prop_ref_field, res_id):
+        """ Helper for get dav eprop, usable in subclasses
+        
+        @param namespace the one to search for
+        @param name Name to search for
+        @param par_class The parent class
+        @param prop_model The name of the orm model holding the properties
+        @param prop_ref_field The name of the field at prop_model pointing to us
+        @param res_id the id of self in the corresponing orm table, that should
+                        match prop_model.prop_ref_field
+        """
+        ret = par_class.get_dav_eprop(self, cr, ns, prop)
+        if ret is not None:
+            return ret
+        if prop_model:
+            propobj = self.context._dirobj.pool.get(prop_model)
+            uid = self.context.uid
+            ctx = self.context.context.copy()
+            ctx.update(self.dctx)
+            sdomain = [(prop_ref_field, '=', False),('namespace', '=', ns), ('name','=', prop)]
+            if res_id:
+                sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
+            prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
+            if prop_ids:
+                pbro = propobj.browse(cr, uid, prop_ids[0], context=ctx)
+                val = pbro.value
+                if pbro.do_subst:
+                    if val.startswith("('") and val.endswith(")"):
+                        glbls = { 'urlquote': urllib.quote, }
+                        val = eval(val, glbls, ctx)
+                    else:
+                        val = val % ctx
+                return val
+        return None
+
 class node_dir(node_acl_mixin, nodes.node_dir):
+    """ override node_dir and add DAV functionality
+    """
     DAV_PROPS = { "DAV:": ('owner', 'group', 
                             'supported-privilege-set', 
                             'current-user-privilege-set'), 
@@ -43,6 +114,17 @@ class node_dir(node_acl_mixin, nodes.node_dir):
     DAV_M_NS = { "DAV:" : '_get_dav',}
     http_options = { 'DAV': ['access-control',] }
 
+    def get_dav_resourcetype(self, cr):
+        return ('collection', 'DAV:')
+
+    def get_dav_props(self, cr):
+        return self._get_dav_props_hlpr(cr, nodes.node_dir, 
+                'document.webdav.dir.property', 'dir_id', self.dir_id)
+
+    def get_dav_eprop(self, cr, ns, prop):
+        return self._get_dav_eprop_hlpr(cr, ns, prop, nodes.node_dir,
+                'document.webdav.dir.property', 'dir_id', self.dir_id)
+
 
 class node_file(node_acl_mixin, nodes.node_file):
     DAV_PROPS = { "DAV:": ('owner', 'group', 
@@ -53,5 +135,27 @@ class node_file(node_acl_mixin, nodes.node_file):
     http_options = { 'DAV': ['access-control', ] }
     pass
 
+    def get_dav_resourcetype(self, cr):
+        return ''
+
+    def get_dav_props(self, cr):
+        return self._get_dav_props_hlpr(cr, nodes.node_dir, 
+                None, 'file_id', self.file_id)
+                #'document.webdav.dir.property', 'dir_id', self.dir_id)
+
+    #def get_dav_eprop(self, cr, ns, prop):
+
+class node_database(nodes.node_database):
+    def get_dav_resourcetype(self, cr):
+        return ('collection', 'DAV:')
+
+    def get_dav_props(self, cr):
+        return self._get_dav_props_hlpr(cr, nodes.node_dir,
+                'document.webdav.dir.property', 'dir_id', False)
+
+    def get_dav_eprop(self, cr, ns, prop):
+        return self._get_dav_eprop_hlpr(cr, nodes.node_dir, ns, prop,
+                'document.webdav.dir.property', 'dir_id', False)
+
 
 #eof
diff --git a/addons/document_webdav/security/ir.model.access.csv b/addons/document_webdav/security/ir.model.access.csv
new file mode 100644 (file)
index 0000000..a77304e
--- /dev/null
@@ -0,0 +1,4 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+"access_webdav_dir_property_all","webdav.dir.property all","model_document_webdav_dir_property",,1,0,0,0
+"access_webdav_dir_property_group_doc_manager","webdav.dir.property document manager","model_document_webdav_dir_property","base.group_system",1,1,1,1
+"access_webdav_dir_property_group_system","webdav.dir.property group system","model_document_webdav_dir_property","base.group_system",1,1,1,1
diff --git a/addons/document_webdav/webdav_view.xml b/addons/document_webdav/webdav_view.xml
new file mode 100644 (file)
index 0000000..2ea0bca
--- /dev/null
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<openerp>
+<data>
+
+    <record model="ir.ui.view" id="view_dir_props_form">
+        <field name="name">document.webdav.dir.property.form</field>
+        <field name="model">document.webdav.dir.property</field>
+        <field name="type">form</field>
+        <field name="arch" type="xml">
+            <form string="Properties">
+               <field name="namespace"/>
+               <field name="name"/>
+               <newline />
+               <field name="dir_id" />
+               <field name="do_subst" />
+               <newline />
+               <field name="value" colspan="4" />
+            </form>
+        </field>
+    </record>
+
+    <record model="ir.ui.view" id="view_dir_props_tree">
+        <field name="name">document.webdav.dir.property.tree</field>
+        <field name="model">document.webdav.dir.property</field>
+        <field name="type">tree</field>
+        <field name="arch" type="xml">
+            <tree string="Properties" toolbar="1">
+               <field name="dir_id" />
+               <field name="namespace"/>
+               <field name="name"/>
+            </tree>
+        </field>
+    </record>
+
+    <record id="view_dir_props_filter" model="ir.ui.view">
+            <field name="name">Search View: Directory DAV properties</field>
+            <field name="model">document.webdav.dir.property</field>
+            <field name="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Search Document storage">
+                    <field name="name" />
+                    <field name="namespace" />
+                    <newline/>
+                    <group expand="0" string="Group By..." groups="base.group_extended">
+                        <filter string="Dir" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'dir_id'}"/>
+                        <filter string="Namespace" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'namespace'}"/>
+                    </group>
+               </search>
+            </field>
+        </record>
+
+    <record model="ir.actions.act_window" id="action_dir_props_form">
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">document.webdav.dir.property</field>
+        <field name="view_type">form</field>
+        <field name="view_mode">tree,form</field>
+        <field name="search_view_id" ref="view_dir_props_filter"/>
+    </record>
+   <menuitem
+        name="DAV properties for folders"
+        action="action_dir_props_form"
+        id="menu_dir_props"
+        groups="base.group_extended"
+        parent="document.menu_document_management_configuration"/>
+
+    <!-- Add the properties to the directory form -->
+    <record model="ir.ui.view" id="view_document_directory_form1">
+        <field name="name">document.directory.webdav.inherit</field>
+        <field name="model">document.directory</field>
+        <field name="inherit_id" ref="document.view_document_directory_form" />
+        <field name="type">form</field>
+        <field name="arch" type="xml">
+           <page string="Dynamic context" position="after">
+               <page string="WebDAV properties">
+                   <label string="These properties will be added to WebDAV requests" colspan="4" />
+                   
+                   <field name="dav_prop_ids" nolabel="1" colspan="4">
+                       <tree string="Properties">
+                           <field name="namespace"/>
+                           <field name="name"/>
+                       </tree>
+                       <form string="Properties">
+                           <field name="namespace"/>
+                           <field name="name"/>
+                           <newline />
+                           <field name="do_subst" />
+                           <newline />
+                           <field name="value" colspan="4" />
+                       </form>
+                   </field>
+               </page>
+           </page>
+       </field>
+    </record>
+
+
+</data>
+</openerp>