1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
3 # |
|
4 # This file is part of CubicWeb. |
|
5 # |
|
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
|
7 # terms of the GNU Lesser General Public License as published by the Free |
|
8 # Software Foundation, either version 2.1 of the License, or (at your option) |
|
9 # any later version. |
|
10 # |
|
11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
|
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
|
14 # details. |
|
15 # |
|
16 # You should have received a copy of the GNU Lesser General Public License along |
|
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
|
18 """core CubicWeb schema, but not necessary at bootstrap time""" |
|
19 |
|
20 __docformat__ = "restructuredtext en" |
|
21 from cubicweb import _ |
|
22 |
|
23 from yams.buildobjs import (EntityType, RelationType, RelationDefinition, |
|
24 SubjectRelation, |
|
25 String, TZDatetime, Datetime, Password, Interval, |
|
26 Boolean, UniqueConstraint) |
|
27 from cubicweb.schema import ( |
|
28 RQLConstraint, WorkflowableEntityType, ERQLExpression, RRQLExpression, |
|
29 PUB_SYSTEM_ENTITY_PERMS, PUB_SYSTEM_REL_PERMS, PUB_SYSTEM_ATTR_PERMS, |
|
30 RO_ATTR_PERMS) |
|
31 |
|
32 class CWUser(WorkflowableEntityType): |
|
33 """define a CubicWeb user""" |
|
34 __permissions__ = { |
|
35 'read': ('managers', 'users', ERQLExpression('X identity U')), |
|
36 'add': ('managers',), |
|
37 'delete': ('managers',), |
|
38 'update': ('managers', ERQLExpression('X identity U, NOT U in_group G, G name "guests"'),), |
|
39 } |
|
40 |
|
41 login = String(required=True, unique=True, maxsize=64, |
|
42 description=_('unique identifier used to connect to the application')) |
|
43 upassword = Password(required=True) # password is a reserved word for mysql |
|
44 firstname = String(maxsize=64) |
|
45 surname = String(maxsize=64) |
|
46 last_login_time = TZDatetime(description=_('last connection date')) |
|
47 in_group = SubjectRelation('CWGroup', cardinality='+*', |
|
48 constraints=[RQLConstraint('NOT O name "owners"')], |
|
49 description=_('groups grant permissions to the user')) |
|
50 |
|
51 |
|
52 class EmailAddress(EntityType): |
|
53 """an electronic mail address associated to a short alias""" |
|
54 __permissions__ = { |
|
55 # application that wishes public email, or use it for something else |
|
56 # than users (eg Company, Person), should explicitly change permissions |
|
57 'read': ('managers', ERQLExpression('U use_email X')), |
|
58 'add': ('managers', 'users',), |
|
59 'delete': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')), |
|
60 'update': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')), |
|
61 } |
|
62 |
|
63 alias = String(fulltextindexed=True, maxsize=56) |
|
64 address = String(required=True, fulltextindexed=True, |
|
65 indexed=True, unique=True, maxsize=128) |
|
66 prefered_form = SubjectRelation('EmailAddress', cardinality='?*', |
|
67 description=_('when multiple addresses are equivalent \ |
|
68 (such as python-projects@logilab.org and python-projects@lists.logilab.org), set this \ |
|
69 to indicate which is the preferred form.')) |
|
70 |
|
71 class use_email(RelationType): |
|
72 fulltext_container = 'subject' |
|
73 |
|
74 |
|
75 class use_email_relation(RelationDefinition): |
|
76 """user's email account""" |
|
77 name = "use_email" |
|
78 __permissions__ = { |
|
79 'read': ('managers', 'users', 'guests',), |
|
80 'add': ('managers', RRQLExpression('U has_update_permission S'),), |
|
81 'delete': ('managers', RRQLExpression('U has_update_permission S'),), |
|
82 } |
|
83 subject = "CWUser" |
|
84 object = "EmailAddress" |
|
85 cardinality = '*?' |
|
86 composite = 'subject' |
|
87 |
|
88 |
|
89 class primary_email(RelationDefinition): |
|
90 """the prefered email""" |
|
91 __permissions__ = { |
|
92 'read': ('managers', 'users', 'guests',), |
|
93 'add': ('managers', RRQLExpression('U has_update_permission S'),), |
|
94 'delete': ('managers', RRQLExpression('U has_update_permission S'),), |
|
95 } |
|
96 subject = "CWUser" |
|
97 object = "EmailAddress" |
|
98 cardinality = '??' |
|
99 constraints= [RQLConstraint('S use_email O')] |
|
100 |
|
101 |
|
102 class prefered_form(RelationType): |
|
103 __permissions__ = { |
|
104 'read': ('managers', 'users', 'guests',), |
|
105 # XXX should have update __permissions__ on both subject and object, |
|
106 # though by doing this we will probably have no way to add |
|
107 # this relation in the web ui. The easiest way to acheive this |
|
108 # is probably to be able to have "U has_update_permission O" as |
|
109 # RQLConstraint of the relation definition, though this is not yet |
|
110 # possible |
|
111 'add': ('managers', RRQLExpression('U has_update_permission S'),), |
|
112 'delete': ('managers', RRQLExpression('U has_update_permission S'),), |
|
113 } |
|
114 |
|
115 class in_group(RelationType): |
|
116 """core relation indicating a user's groups""" |
|
117 __permissions__ = PUB_SYSTEM_REL_PERMS |
|
118 |
|
119 class owned_by(RelationType): |
|
120 """core relation indicating owners of an entity. This relation |
|
121 implicitly put the owner into the owners group for the entity |
|
122 """ |
|
123 __permissions__ = { |
|
124 'read': ('managers', 'users', 'guests'), |
|
125 'add': ('managers', RRQLExpression('S owned_by U'),), |
|
126 'delete': ('managers', RRQLExpression('S owned_by U'),), |
|
127 } |
|
128 # 0..n cardinality for entities created by internal session (no attached user) |
|
129 # and to support later deletion of a user which has created some entities |
|
130 cardinality = '**' |
|
131 subject = '*' |
|
132 object = 'CWUser' |
|
133 |
|
134 class created_by(RelationType): |
|
135 """core relation indicating the original creator of an entity""" |
|
136 __permissions__ = { |
|
137 'read': ('managers', 'users', 'guests'), |
|
138 'add': ('managers',), |
|
139 'delete': ('managers',), |
|
140 } |
|
141 # 0..1 cardinality for entities created by internal session (no attached user) |
|
142 # and to support later deletion of a user which has created some entities |
|
143 cardinality = '?*' |
|
144 subject = '*' |
|
145 object = 'CWUser' |
|
146 |
|
147 |
|
148 class creation_date(RelationType): |
|
149 """creation time of an entity""" |
|
150 __permissions__ = PUB_SYSTEM_ATTR_PERMS |
|
151 cardinality = '11' |
|
152 subject = '*' |
|
153 object = 'TZDatetime' |
|
154 |
|
155 |
|
156 class modification_date(RelationType): |
|
157 """latest modification time of an entity""" |
|
158 __permissions__ = PUB_SYSTEM_ATTR_PERMS |
|
159 cardinality = '11' |
|
160 subject = '*' |
|
161 object = 'TZDatetime' |
|
162 |
|
163 |
|
164 class cwuri(RelationType): |
|
165 """internal entity uri""" |
|
166 __permissions__ = RO_ATTR_PERMS |
|
167 cardinality = '11' |
|
168 subject = '*' |
|
169 object = 'String' |
|
170 |
|
171 |
|
172 # XXX find a better relation name |
|
173 class for_user(RelationType): |
|
174 """link a property to the user which want this property customization. Unless |
|
175 you're a site manager, this relation will be handled automatically. |
|
176 """ |
|
177 __permissions__ = { |
|
178 'read': ('managers', 'users', 'guests'), |
|
179 'add': ('managers',), |
|
180 'delete': ('managers',), |
|
181 } |
|
182 inlined = True |
|
183 subject = 'CWProperty' |
|
184 object = 'CWUser' |
|
185 composite = 'object' |
|
186 cardinality = '?*' |
|
187 |
|
188 |
|
189 class ExternalUri(EntityType): |
|
190 """a URI representing an object in external data store""" |
|
191 uri = String(required=True, unique=True, maxsize=256, |
|
192 description=_('the URI of the object')) |
|
193 |
|
194 |
|
195 class same_as(RelationType): |
|
196 """generic relation to specify that an external entity represent the same |
|
197 object as a local one: |
|
198 http://www.w3.org/TR/owl-ref/#sameAs-def |
|
199 """ |
|
200 #NOTE: You'll have to explicitly declare which entity types can have a |
|
201 #same_as relation |
|
202 __permissions__ = { |
|
203 'read': ('managers', 'users', 'guests',), |
|
204 'add': ('managers', 'users'), |
|
205 'delete': ('managers', 'owners'), |
|
206 } |
|
207 cardinality = '**' |
|
208 symmetric = True |
|
209 # NOTE: the 'object = ExternalUri' declaration will still be mandatory |
|
210 # in the cube's schema. |
|
211 object = 'ExternalUri' |
|
212 |
|
213 |
|
214 class CWCache(EntityType): |
|
215 """a simple cache entity characterized by a name and |
|
216 a validity date. |
|
217 |
|
218 The target application is responsible for updating timestamp |
|
219 when necessary to invalidate the cache (typically in hooks). |
|
220 |
|
221 Also, checkout the AppObject.get_cache() method. |
|
222 """ |
|
223 # XXX only handle by hooks, shouldn't be readable/editable at all through |
|
224 # the ui and so no permissions should be granted, no? |
|
225 __permissions__ = { |
|
226 'read': ('managers', 'users', 'guests'), |
|
227 'add': ('managers',), |
|
228 'update': ('managers', 'users',), # XXX |
|
229 'delete': ('managers',), |
|
230 } |
|
231 |
|
232 name = String(required=True, unique=True, maxsize=128, |
|
233 description=_('name of the cache')) |
|
234 timestamp = TZDatetime(default='NOW') |
|
235 |
|
236 |
|
237 class CWSource(EntityType): |
|
238 __permissions__ = { |
|
239 'read': ('managers', 'users', 'guests'), |
|
240 'add': ('managers',), |
|
241 'update': ('managers',), |
|
242 'delete': ('managers',), |
|
243 } |
|
244 name = String(required=True, unique=True, maxsize=128, |
|
245 description=_('name of the source')) |
|
246 type = String(required=True, maxsize=20, description=_('type of the source')) |
|
247 config = String(description=_('source\'s configuration. One key=value per ' |
|
248 'line, authorized keys depending on the ' |
|
249 'source\'s type'), |
|
250 __permissions__={ |
|
251 'read': ('managers',), |
|
252 'add': ('managers',), |
|
253 'update': ('managers',), |
|
254 }) |
|
255 # put this here and not in a subclass even if it's only for some sources |
|
256 # since having subclasses on generic relation (cw_source) double the number |
|
257 # of rdef in the schema, and make ms planning harder since queries solutions |
|
258 # may changes when sources are specified |
|
259 url = String(description=_('URLs from which content will be imported. You can put one url per line')) |
|
260 parser = String(description=_('parser to use to extract entities from content retrieved at given URLs.')) |
|
261 latest_retrieval = TZDatetime(description=_('latest synchronization time')) |
|
262 in_synchronization = TZDatetime(description=_('start timestamp of the currently in synchronization, or NULL when no synchronization in progress.')) |
|
263 |
|
264 |
|
265 ENTITY_MANAGERS_PERMISSIONS = { |
|
266 'read': ('managers',), |
|
267 'add': ('managers',), |
|
268 'update': ('managers',), |
|
269 'delete': ('managers',), |
|
270 } |
|
271 RELATION_MANAGERS_PERMISSIONS = { |
|
272 'read': ('managers',), |
|
273 'add': ('managers',), |
|
274 'delete': ('managers',), |
|
275 } |
|
276 |
|
277 |
|
278 class CWSourceHostConfig(EntityType): |
|
279 __permissions__ = ENTITY_MANAGERS_PERMISSIONS |
|
280 __unique_together__ = [('match_host', 'cw_host_config_of')] |
|
281 match_host = String(required=True, maxsize=128, |
|
282 description=_('regexp matching host(s) to which this config applies')) |
|
283 config = String(required=True, |
|
284 description=_('Source\'s configuration for a particular host. ' |
|
285 'One key=value per line, authorized keys ' |
|
286 'depending on the source\'s type, overriding ' |
|
287 'values defined on the source.'), |
|
288 __permissions__={ |
|
289 'read': ('managers',), |
|
290 'add': ('managers',), |
|
291 'update': ('managers',), |
|
292 }) |
|
293 |
|
294 |
|
295 class cw_host_config_of(RelationDefinition): |
|
296 __permissions__ = RELATION_MANAGERS_PERMISSIONS |
|
297 subject = 'CWSourceHostConfig' |
|
298 object = 'CWSource' |
|
299 cardinality = '1*' |
|
300 composite = 'object' |
|
301 inlined = True |
|
302 |
|
303 class cw_source(RelationDefinition): |
|
304 __permissions__ = { |
|
305 'read': ('managers', 'users', 'guests'), |
|
306 'add': ('managers',), |
|
307 'delete': ('managers',), |
|
308 } |
|
309 subject = '*' |
|
310 object = 'CWSource' |
|
311 cardinality = '1*' |
|
312 composite = 'object' |
|
313 |
|
314 |
|
315 class CWDataImport(EntityType): |
|
316 __permissions__ = ENTITY_MANAGERS_PERMISSIONS |
|
317 start_timestamp = TZDatetime() |
|
318 end_timestamp = TZDatetime() |
|
319 log = String() |
|
320 status = String(required=True, internationalizable=True, indexed=True, |
|
321 default='in progress', |
|
322 vocabulary=[_('in progress'), _('success'), _('failed')]) |
|
323 |
|
324 class cw_import_of(RelationDefinition): |
|
325 __permissions__ = RELATION_MANAGERS_PERMISSIONS |
|
326 subject = 'CWDataImport' |
|
327 object = 'CWSource' |
|
328 cardinality = '1*' |
|
329 composite = 'object' |
|
330 |
|
331 |
|
332 class CWSourceSchemaConfig(EntityType): |
|
333 __permissions__ = ENTITY_MANAGERS_PERMISSIONS |
|
334 cw_for_source = SubjectRelation( |
|
335 'CWSource', inlined=True, cardinality='1*', composite='object', |
|
336 __permissions__=RELATION_MANAGERS_PERMISSIONS) |
|
337 options = String(description=_('allowed options depends on the source type')) |
|
338 |
|
339 |
|
340 class rtype_cw_schema(RelationDefinition): |
|
341 __permissions__ = RELATION_MANAGERS_PERMISSIONS |
|
342 name = 'cw_schema' |
|
343 subject = 'CWSourceSchemaConfig' |
|
344 object = ('CWEType', 'CWRType') |
|
345 inlined = True |
|
346 cardinality = '1*' |
|
347 composite = 'object' |
|
348 constraints = [RQLConstraint('NOT O final TRUE')] |
|
349 |
|
350 class rdef_cw_schema(RelationDefinition): |
|
351 __permissions__ = RELATION_MANAGERS_PERMISSIONS |
|
352 name = 'cw_schema' |
|
353 subject = 'CWSourceSchemaConfig' |
|
354 object = 'CWRelation' |
|
355 inlined = True |
|
356 cardinality = '1*' |
|
357 composite = 'object' |
|
358 |
|
359 # "abtract" relation types, no definition in cubicweb itself ################### |
|
360 |
|
361 class identical_to(RelationType): |
|
362 """identical to""" |
|
363 symmetric = True |
|
364 __permissions__ = { |
|
365 'read': ('managers', 'users', 'guests',), |
|
366 # XXX should have update __permissions__ on both subject and object, |
|
367 # though by doing this we will probably have no way to add |
|
368 # this relation in the web ui. The easiest way to acheive this |
|
369 # is probably to be able to have "U has_update_permission O" as |
|
370 # RQLConstraint of the relation definition, though this is not yet |
|
371 # possible |
|
372 'add': ('managers', RRQLExpression('U has_update_permission S'),), |
|
373 'delete': ('managers', RRQLExpression('U has_update_permission S'),), |
|
374 } |
|
375 |
|
376 class see_also(RelationType): |
|
377 """generic relation to link one entity to another""" |
|
378 symmetric = True |
|
379 __permissions__ = { |
|
380 'read': ('managers', 'users', 'guests',), |
|
381 'add': ('managers', RRQLExpression('U has_update_permission S'),), |
|
382 'delete': ('managers', RRQLExpression('U has_update_permission S'),), |
|
383 } |
|