Doc webdav: context for DAV properties, dynamic folders
[odoo/odoo.git] / addons / document_webdav / nodes.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22
23 from document import nodes
24 from tools.safe_eval import safe_eval as eval
25 import urllib
26
27 def dict_filter(srcdic, keys, res=None):
28     ''' Return a copy of srcdic that has only keys set.
29     If any of keys are missing from srcdic, the result won't have them, 
30     either.
31     @param res If given, result will be updated there, instead of a new dict.
32     '''
33     if res is None:
34         res = {}
35     for k in keys:
36         if k in srcdic:
37             res[k] = srcdic[k]
38     return res
39     
40 class node_acl_mixin(object):
41     def _get_dav_owner(self, cr):
42         return self.uuser
43
44     def _get_dav_group(self, cr):
45         return self.ugroup
46         
47     def _get_dav_supported_privilege_set(self, cr):
48         return '' # TODO
49     
50     def _get_dav_current_user_privilege_set(self, cr):
51         return '' # TODO
52
53     def _get_dav_props_hlpr(self, cr, par_class, prop_model, 
54                             prop_ref_field, res_id):
55         """ Helper for dav properties, usable in subclasses
56         
57         @param par_class The parent class
58         @param prop_model The name of the orm model holding the properties
59         @param prop_ref_field The name of the field at prop_model pointing to us
60         @param res_id the id of self in the corresponing orm table, that should
61                         match prop_model.prop_ref_field
62         """
63         ret = par_class.get_dav_props(self, cr)
64         if prop_model:
65             propobj = self.context._dirobj.pool.get(prop_model)
66             uid = self.context.uid
67             ctx = self.context.context.copy()
68             ctx.update(self.dctx)
69             # Not really needed because we don't do eval here:
70             # ctx.update({'uid': uid, 'dbname': self.context.dbname })
71             # dict_filter(self.context.extra_ctx, ['username', 'groupname', 'webdav_path'], ctx)
72             sdomain = [(prop_ref_field, '=', False),]
73             if res_id:
74                 sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
75             prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
76             if prop_ids:
77                 ret = ret.copy()
78                 for pbro in propobj.browse(cr, uid, prop_ids, context=ctx):
79                     ret[pbro.namespace] = ret.get(pbro.namespace, ()) + \
80                         (pbro.name,)
81                     # Note that we cannot have properties to conditionally appear
82                     # on the context, yet.
83                 
84         return ret
85
86     def _get_dav_eprop_hlpr(self, cr, ns, prop,
87                             par_class, prop_model, 
88                             prop_ref_field, res_id):
89         """ Helper for get dav eprop, usable in subclasses
90         
91         @param namespace the one to search for
92         @param name Name to search for
93         @param par_class The parent class
94         @param prop_model The name of the orm model holding the properties
95         @param prop_ref_field The name of the field at prop_model pointing to us
96         @param res_id the id of self in the corresponing orm table, that should
97                         match prop_model.prop_ref_field
98         """
99         ret = par_class.get_dav_eprop(self, cr, ns, prop)
100         if ret is not None:
101             return ret
102         if prop_model:
103             propobj = self.context._dirobj.pool.get(prop_model)
104             uid = self.context.uid
105             ctx = self.context.context.copy()
106             ctx.update(self.dctx)
107             ctx.update({'uid': uid, 'dbname': self.context.dbname })
108             ctx['node_classname'] = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
109             dict_filter(self.context.extra_ctx, ['username', 'groupname', 'webdav_path'], ctx)
110             sdomain = [(prop_ref_field, '=', False),('namespace', '=', ns), ('name','=', prop)]
111             if res_id:
112                 sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
113             prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
114             if prop_ids:
115                 pbro = propobj.browse(cr, uid, prop_ids[0], context=ctx)
116                 val = pbro.value
117                 if pbro.do_subst:
118                     if val.startswith("('") and val.endswith(")"):
119                         glbls = { 'urlquote': urllib.quote, }
120                         val = eval(val, glbls, ctx)
121                     else:
122                         val = val % ctx
123                 return val
124         return None
125
126 class node_dir(node_acl_mixin, nodes.node_dir):
127     """ override node_dir and add DAV functionality
128     """
129     DAV_PROPS = { "DAV:": ('owner', 'group', 
130                             'supported-privilege-set', 
131                             'current-user-privilege-set'), 
132                 }
133     DAV_M_NS = { "DAV:" : '_get_dav',}
134     http_options = { 'DAV': ['access-control',] }
135
136     def get_dav_resourcetype(self, cr):
137         return ('collection', 'DAV:')
138
139     def get_dav_props(self, cr):
140         return self._get_dav_props_hlpr(cr, nodes.node_dir, 
141                 'document.webdav.dir.property', 'dir_id', self.dir_id)
142
143     def get_dav_eprop(self, cr, ns, prop):
144         return self._get_dav_eprop_hlpr(cr, ns, prop, nodes.node_dir,
145                 'document.webdav.dir.property', 'dir_id', self.dir_id)
146
147
148 class node_file(node_acl_mixin, nodes.node_file):
149     DAV_PROPS = { "DAV:": ('owner', 'group', 
150                             'supported-privilege-set', 
151                             'current-user-privilege-set'), 
152                 }
153     DAV_M_NS = { "DAV:" : '_get_dav',}
154     http_options = { 'DAV': ['access-control', ] }
155     pass
156
157     def get_dav_resourcetype(self, cr):
158         return ''
159
160     def get_dav_props(self, cr):
161         return self._get_dav_props_hlpr(cr, nodes.node_dir, 
162                 None, 'file_id', self.file_id)
163                 #'document.webdav.dir.property', 'dir_id', self.dir_id)
164
165     #def get_dav_eprop(self, cr, ns, prop):
166
167 class node_database(nodes.node_database):
168     def get_dav_resourcetype(self, cr):
169         return ('collection', 'DAV:')
170
171     def get_dav_props(self, cr):
172         return self._get_dav_props_hlpr(cr, nodes.node_dir,
173                 'document.webdav.dir.property', 'dir_id', False)
174
175     def get_dav_eprop(self, cr, ns, prop):
176         return self._get_dav_eprop_hlpr(cr, nodes.node_dir, ns, prop,
177                 'document.webdav.dir.property', 'dir_id', False)
178
179 class node_res_obj(node_acl_mixin, nodes.node_res_obj):
180     DAV_PROPS = { "DAV:": ('owner', 'group', 
181                             'supported-privilege-set', 
182                             'current-user-privilege-set'), 
183                 }
184     DAV_M_NS = { "DAV:" : '_get_dav',}
185     http_options = { 'DAV': ['access-control',] }
186
187     def get_dav_resourcetype(self, cr):
188         return ('collection', 'DAV:')
189
190     def get_dav_props(self, cr):
191         return self._get_dav_props_hlpr(cr, nodes.node_res_obj, 
192                 'document.webdav.dir.property', 'dir_id', self.dir_id)
193
194     def get_dav_eprop(self, cr, ns, prop):
195         return self._get_dav_eprop_hlpr(cr, ns, prop, nodes.node_res_obj,
196                 'document.webdav.dir.property', 'dir_id', self.dir_id)
197
198
199 class node_res_dir(node_acl_mixin, nodes.node_res_dir):
200     DAV_PROPS = { "DAV:": ('owner', 'group', 
201                             'supported-privilege-set', 
202                             'current-user-privilege-set'), 
203                 }
204     DAV_M_NS = { "DAV:" : '_get_dav',}
205     http_options = { 'DAV': ['access-control',] }
206     res_obj_class = node_res_obj
207
208     def get_dav_resourcetype(self, cr):
209         return ('collection', 'DAV:')
210
211     def get_dav_props(self, cr):
212         return self._get_dav_props_hlpr(cr, nodes.node_res_dir, 
213                 'document.webdav.dir.property', 'dir_id', self.dir_id)
214
215     def get_dav_eprop(self, cr, ns, prop):
216         return self._get_dav_eprop_hlpr(cr, ns, prop, nodes.node_res_dir,
217                 'document.webdav.dir.property', 'dir_id', self.dir_id)
218
219 # Some copies, so that this module can replace 'from document import nodes'
220 get_node_context = nodes.get_node_context
221 node_context = nodes.node_context
222 node_class = nodes.node_class
223 node_descriptor = nodes.node_descriptor
224
225
226 #eof