schema.py 8.42 KB
Newer Older
Denis Laxalde's avatar
Denis Laxalde committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""cubicweb-dataprocessing schema"""
18

19
20
from yams.buildobjs import (ComputedRelation, EntityType, RelationDefinition,
                            Int, String)
21

Denis Laxalde's avatar
Denis Laxalde committed
22
from cubicweb import _
23
from cubicweb.schema import (RRQLExpression, ERQLExpression,
24
                             RQLConstraint, WorkflowableEntityType)
25

26
from cubicweb_file.schema import File
27
28
29


DATAPROCESS_UPDATE_PERMS_RQLEXPR = (
30
    'U in_group G, G name "users", '
31
32
33
34
35
36
37
    'X in_state S, S name "wfs_dataprocess_initialized"')


class _DataProcess(WorkflowableEntityType):
    __abstract__ = True
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
38
39
        'update': ('managers',
                   ERQLExpression(DATAPROCESS_UPDATE_PERMS_RQLEXPR)),
40
41
        'delete': ('managers',
                   ERQLExpression(DATAPROCESS_UPDATE_PERMS_RQLEXPR)),
42
        'add': ('managers', 'users')
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    }


class DataTransformationProcess(_DataProcess):
    """Data transformation process"""


class DataValidationProcess(_DataProcess):
    """Data validation process"""


class process_depends_on(RelationDefinition):
    subject = 'DataTransformationProcess'
    object = 'DataValidationProcess'
    cardinality = '??'


class process_input_file(RelationDefinition):
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'add': ('managers', RRQLExpression(
64
            'U in_group G, G name "users", '
65
66
67
68
69
70
            'S in_state ST, ST name "wfs_dataprocess_initialized"')),
        'delete': ('managers', RRQLExpression('U has_update_permission S'))}
    subject = ('DataTransformationProcess', 'DataValidationProcess')
    object = 'File'
    cardinality = '?*'
    description = _('input file of the data process')
71
72
73
74
    constraints = [
        RQLConstraint('NOT EXISTS(SC implemented_by O)',
                      msg=_('file is used by a script')),
    ]
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96


class validated_by(RelationDefinition):
    """A File may be validated by a validation process"""
    __permissions__ = {'read': ('managers', 'users', 'guests'),
                       'add': (),
                       'delete': ()}
    subject = 'File'
    object = 'DataValidationProcess'
    cardinality = '**'


class produced_by(RelationDefinition):
    """A File may be produced by a transformation process"""
    __permissions__ = {'read': ('managers', 'users', 'guests'),
                       'add': (),
                       'delete': ()}
    subject = 'File'
    object = 'DataTransformationProcess'
    cardinality = '?*'


97
98
99
100
101
102
103
104
105
106
107
108
109
110
class process_stderr(RelationDefinition):
    __permissions__ = {
        'read': ('managers', 'users', 'guests',),
        'add': (),
        'delete': (),
    }
    subject = ('DataTransformationProcess', 'DataValidationProcess')
    object = 'File'
    cardinality = '??'
    inlined = True
    composite = 'subject'
    description = _('standard error output')


111
112
113
114
115
# Set File permissions:
#  * use `produced_by` relation to prevent modification of generated files
#  * bind the update permissions on the Script which uses the File as
#    implementation if any
_update_file_perms = ('managers', ERQLExpression(
116
    'U in_group G, G name "users", '
117
118
119
120
121
122
123
124
125
    'NOT EXISTS(X produced_by Y), '
    'NOT EXISTS(S1 implemented_by X)'
    ' OR EXISTS(S implemented_by X, U has_update_permission S)'
))
File.__permissions__ = File.__permissions__.copy()
File.__permissions__.update({'update': _update_file_perms,
                             'delete': _update_file_perms})


Denis Laxalde's avatar
Denis Laxalde committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
class _Script(EntityType):
    name = String(required=True, fulltextindexed=True)


class implemented_by(RelationDefinition):
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'add': (RRQLExpression('U has_update_permission S'), ),
        'delete': (RRQLExpression('U has_update_permission S'), ),
    }
    subject = ('ValidationScript', 'TransformationScript')
    object = 'File'
    cardinality = '1?'
    inlined = True
    composite = 'subject'
    description = _('the resource (file) implementing a script')


_validationscript_update_perms = (
    'managers',
    ERQLExpression('U in_group G, G name "users", '
                   'NOT EXISTS(P1 validation_script X) OR '
                   'EXISTS(P2 validation_script X, P2 in_state S,'
                   '       S name "wfs_dataprocess_initialized")'),
)


class ValidationScript(_Script):
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'update': _validationscript_update_perms,
        'delete': _validationscript_update_perms,
        'add': ('managers', 'users')
    }
    parameters = String(
        description=_('parameters for the script, will be used as JSON data '
                      'structure'))


165
class validation_script(RelationDefinition):
166
167
168
169
170
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'add': ('managers', 'users'),
        'delete': (RRQLExpression('U has_update_permission S'), )
    }
171
    subject = 'DataValidationProcess'
Denis Laxalde's avatar
Denis Laxalde committed
172
    object = 'ValidationScript'
173
174
    cardinality = '1*'
    inlined = True
175
176


Denis Laxalde's avatar
Denis Laxalde committed
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
_transformationscript_update_perms = (
    'managers',
    ERQLExpression('U in_group G, G name "users", '
                   'NOT EXISTS(S1 step_script X, S1 in_sequence SQ1,'
                   '           P1 transformation_sequence SQ1) OR '
                   'EXISTS(S2 step_script X, S2 in_sequence SQ2,'
                   '       P2 transformation_sequence SQ2, P2 in_state S,'
                   '       S name "wfs_dataprocess_initialized")'),
)


class TransformationScript(_Script):
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'update': _transformationscript_update_perms,
        'delete': _transformationscript_update_perms,
        'add': ('managers', 'users')
    }
    output_format = String(maxsize=128,
                           description=_('format (MIME type) of stderr data'))


199
class transformation_sequence(RelationDefinition):
200
201
202
203
204
    __permissions__ = {
        'read': ('managers', 'users'),
        'add': (RRQLExpression('U has_update_permission S'), ),
        'delete': (RRQLExpression('U has_update_permission S'), ),
    }
205
    subject = 'DataTransformationProcess'
Denis Laxalde's avatar
Denis Laxalde committed
206
    object = 'TransformationSequence'
207
208
209
    cardinality = '1*'


210
211
212
213
214
215
216
217
_transformationsequence_update_perms = (
    ERQLExpression('U in_group G, G name IN ("managers", "users"), '
                   'NOT EXISTS(P transformation_sequence X) OR '
                   'EXISTS(P transformation_sequence X,'
                   '       P name "wfs_dataprocess_initialized")'),
)


Denis Laxalde's avatar
Denis Laxalde committed
218
219
class TransformationSequence(EntityType):
    """A sequence of scripts involved in a given process."""
220
221
222
223
224
225
    __permissions__ = {
        'read': ('managers', 'users', 'guests'),
        'update': _transformationsequence_update_perms,
        'delete': _transformationsequence_update_perms,
        'add': ('managers', 'users')
    }
226
227


Denis Laxalde's avatar
Denis Laxalde committed
228
229
class TransformationStep(EntityType):
    """A step in a transformation sequence."""
230
231
    # TODO __permissions__
    index = Int(required=True,
Denis Laxalde's avatar
Denis Laxalde committed
232
233
234
235
                description=_('position in the transformation sequence'))
    parameters = String(
        description=_('parameters for the script, will be used as JSON data '
                      'structure'))
236
237
    __unique_together__ = [
        ('index', 'in_sequence'),
Denis Laxalde's avatar
Denis Laxalde committed
238
        ('in_sequence', 'step_script')
239
240
241
    ]


Denis Laxalde's avatar
Denis Laxalde committed
242
class step_script(RelationDefinition):
243
    # TODO __permissions__
Denis Laxalde's avatar
Denis Laxalde committed
244
245
246
    subject = 'TransformationStep'
    object = 'TransformationScript'
    cardinality = '1*'
247
248
249
    inlined = True


Denis Laxalde's avatar
Denis Laxalde committed
250
class in_sequence(RelationDefinition):
251
    # TODO __permissions__
Denis Laxalde's avatar
Denis Laxalde committed
252
253
254
    subject = 'TransformationStep'
    object = 'TransformationSequence'
    cardinality = '1+'
255
    composite = 'object'
Denis Laxalde's avatar
Denis Laxalde committed
256
    inlined = True
257
258


259
class transformation_scripts(ComputedRelation):
Denis Laxalde's avatar
Denis Laxalde committed
260
    rule = 'S transformation_sequence SEQ, O in_sequence SEQ'