root / snf-pithos-backend / pithos / backends / lib / sqlalchemy / permissions.py @ 3759eddb
History | View | Annotate | Download (10.1 kB)
1 | 2e662088 | Antony Chazapis | # Copyright 2011-2012 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 2715ade4 | Sofia Papagiannaki | #
|
3 | 4f917833 | Sofia Papagiannaki | # Redistribution and use in source and binary forms, with or
|
4 | 4f917833 | Sofia Papagiannaki | # without modification, are permitted provided that the following
|
5 | 4f917833 | Sofia Papagiannaki | # conditions are met:
|
6 | 2715ade4 | Sofia Papagiannaki | #
|
7 | 4f917833 | Sofia Papagiannaki | # 1. Redistributions of source code must retain the above
|
8 | 4f917833 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
9 | 4f917833 | Sofia Papagiannaki | # disclaimer.
|
10 | 2715ade4 | Sofia Papagiannaki | #
|
11 | 4f917833 | Sofia Papagiannaki | # 2. Redistributions in binary form must reproduce the above
|
12 | 4f917833 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
13 | 4f917833 | Sofia Papagiannaki | # disclaimer in the documentation and/or other materials
|
14 | 4f917833 | Sofia Papagiannaki | # provided with the distribution.
|
15 | 2715ade4 | Sofia Papagiannaki | #
|
16 | 4f917833 | Sofia Papagiannaki | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 4f917833 | Sofia Papagiannaki | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 4f917833 | Sofia Papagiannaki | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 4f917833 | Sofia Papagiannaki | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 4f917833 | Sofia Papagiannaki | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 4f917833 | Sofia Papagiannaki | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 4f917833 | Sofia Papagiannaki | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 4f917833 | Sofia Papagiannaki | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 4f917833 | Sofia Papagiannaki | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 4f917833 | Sofia Papagiannaki | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 4f917833 | Sofia Papagiannaki | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 4f917833 | Sofia Papagiannaki | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 2715ade4 | Sofia Papagiannaki | #
|
29 | 4f917833 | Sofia Papagiannaki | # The views and conclusions contained in the software and
|
30 | 4f917833 | Sofia Papagiannaki | # documentation are those of the authors and should not be
|
31 | 4f917833 | Sofia Papagiannaki | # interpreted as representing official policies, either expressed
|
32 | 4f917833 | Sofia Papagiannaki | # or implied, of GRNET S.A.
|
33 | 4f917833 | Sofia Papagiannaki | |
34 | dc88754b | Nanakos Chrysostomos | from sqlalchemy.sql import select, literal, or_, and_ |
35 | 4f1bc0a6 | Sofia Papagiannaki | from sqlalchemy.sql.expression import join, union |
36 | 4f917833 | Sofia Papagiannaki | |
37 | 4f917833 | Sofia Papagiannaki | from xfeatures import XFeatures |
38 | 4f917833 | Sofia Papagiannaki | from groups import Groups |
39 | 4f917833 | Sofia Papagiannaki | from public import Public |
40 | a63f36a2 | Sofia Papagiannaki | from node import Node |
41 | dc88754b | Nanakos Chrysostomos | from collections import defaultdict |
42 | 4f917833 | Sofia Papagiannaki | |
43 | 235a4227 | Sofia Papagiannaki | from dbworker import ESCAPE_CHAR |
44 | 235a4227 | Sofia Papagiannaki | |
45 | 4f917833 | Sofia Papagiannaki | |
46 | 4f917833 | Sofia Papagiannaki | READ = 0
|
47 | 4f917833 | Sofia Papagiannaki | WRITE = 1
|
48 | 4f917833 | Sofia Papagiannaki | |
49 | 4f917833 | Sofia Papagiannaki | |
50 | a63f36a2 | Sofia Papagiannaki | class Permissions(XFeatures, Groups, Public, Node): |
51 | 2715ade4 | Sofia Papagiannaki | |
52 | 4f917833 | Sofia Papagiannaki | def __init__(self, **params): |
53 | 4f917833 | Sofia Papagiannaki | XFeatures.__init__(self, **params)
|
54 | 4f917833 | Sofia Papagiannaki | Groups.__init__(self, **params)
|
55 | 4f917833 | Sofia Papagiannaki | Public.__init__(self, **params)
|
56 | a63f36a2 | Sofia Papagiannaki | Node.__init__(self, **params)
|
57 | 2715ade4 | Sofia Papagiannaki | |
58 | 4f917833 | Sofia Papagiannaki | def access_grant(self, path, access, members=()): |
59 | 4f917833 | Sofia Papagiannaki | """Grant members with access to path.
|
60 | 4f917833 | Sofia Papagiannaki | Members can also be '*' (all),
|
61 | 4f917833 | Sofia Papagiannaki | or some group specified as 'owner:group'."""
|
62 | 2715ade4 | Sofia Papagiannaki | |
63 | 4f917833 | Sofia Papagiannaki | if not members: |
64 | 4f917833 | Sofia Papagiannaki | return
|
65 | 4f917833 | Sofia Papagiannaki | feature = self.xfeature_create(path)
|
66 | 4f917833 | Sofia Papagiannaki | self.feature_setmany(feature, access, members)
|
67 | 2715ade4 | Sofia Papagiannaki | |
68 | 4f917833 | Sofia Papagiannaki | def access_set(self, path, permissions): |
69 | 4f917833 | Sofia Papagiannaki | """Set permissions for path. The permissions dict
|
70 | 4f917833 | Sofia Papagiannaki | maps 'read', 'write' keys to member lists."""
|
71 | 2715ade4 | Sofia Papagiannaki | |
72 | cf341da4 | Antony Chazapis | r = permissions.get('read', [])
|
73 | cf341da4 | Antony Chazapis | w = permissions.get('write', [])
|
74 | cf341da4 | Antony Chazapis | if not r and not w: |
75 | cf341da4 | Antony Chazapis | self.xfeature_destroy(path)
|
76 | cf341da4 | Antony Chazapis | return
|
77 | cf341da4 | Antony Chazapis | feature = self.xfeature_create(path)
|
78 | 345dcf39 | Antony Chazapis | self.feature_clear(feature, READ)
|
79 | 345dcf39 | Antony Chazapis | self.feature_clear(feature, WRITE)
|
80 | cf341da4 | Antony Chazapis | if r:
|
81 | cf341da4 | Antony Chazapis | self.feature_setmany(feature, READ, r)
|
82 | cf341da4 | Antony Chazapis | if w:
|
83 | cf341da4 | Antony Chazapis | self.feature_setmany(feature, WRITE, w)
|
84 | 2715ade4 | Sofia Papagiannaki | |
85 | dc88754b | Nanakos Chrysostomos | def access_get_for_bulk(self, perms): |
86 | dc88754b | Nanakos Chrysostomos | """Get permissions for path."""
|
87 | dc88754b | Nanakos Chrysostomos | allowed = None
|
88 | dc88754b | Nanakos Chrysostomos | d = defaultdict(list)
|
89 | dc88754b | Nanakos Chrysostomos | for value, feature_id, key in perms: |
90 | dc88754b | Nanakos Chrysostomos | d[key].append(value) |
91 | dc88754b | Nanakos Chrysostomos | permissions = d |
92 | dc88754b | Nanakos Chrysostomos | if READ in permissions: |
93 | dc88754b | Nanakos Chrysostomos | allowed = 0
|
94 | dc88754b | Nanakos Chrysostomos | permissions['read'] = permissions[READ]
|
95 | dc88754b | Nanakos Chrysostomos | del(permissions[READ])
|
96 | dc88754b | Nanakos Chrysostomos | if WRITE in permissions: |
97 | dc88754b | Nanakos Chrysostomos | allowed = 1
|
98 | dc88754b | Nanakos Chrysostomos | permissions['write'] = permissions[WRITE]
|
99 | dc88754b | Nanakos Chrysostomos | del(permissions[WRITE])
|
100 | dc88754b | Nanakos Chrysostomos | return (permissions, allowed)
|
101 | dc88754b | Nanakos Chrysostomos | |
102 | cf341da4 | Antony Chazapis | def access_get(self, path): |
103 | cf341da4 | Antony Chazapis | """Get permissions for path."""
|
104 | 2715ade4 | Sofia Papagiannaki | |
105 | cf341da4 | Antony Chazapis | feature = self.xfeature_get(path)
|
106 | cf341da4 | Antony Chazapis | if not feature: |
107 | cf341da4 | Antony Chazapis | return {}
|
108 | cf341da4 | Antony Chazapis | permissions = self.feature_dict(feature)
|
109 | cf341da4 | Antony Chazapis | if READ in permissions: |
110 | cf341da4 | Antony Chazapis | permissions['read'] = permissions[READ]
|
111 | cf341da4 | Antony Chazapis | del(permissions[READ])
|
112 | cf341da4 | Antony Chazapis | if WRITE in permissions: |
113 | cf341da4 | Antony Chazapis | permissions['write'] = permissions[WRITE]
|
114 | cf341da4 | Antony Chazapis | del(permissions[WRITE])
|
115 | cf341da4 | Antony Chazapis | return permissions
|
116 | 2715ade4 | Sofia Papagiannaki | |
117 | a74ba506 | Sofia Papagiannaki | def access_members(self, path): |
118 | a74ba506 | Sofia Papagiannaki | feature = self.xfeature_get(path)
|
119 | a74ba506 | Sofia Papagiannaki | if not feature: |
120 | a74ba506 | Sofia Papagiannaki | return []
|
121 | a74ba506 | Sofia Papagiannaki | permissions = self.feature_dict(feature)
|
122 | a74ba506 | Sofia Papagiannaki | members = set()
|
123 | a74ba506 | Sofia Papagiannaki | members.update(permissions.get(READ, [])) |
124 | a74ba506 | Sofia Papagiannaki | members.update(permissions.get(WRITE, [])) |
125 | a74ba506 | Sofia Papagiannaki | for m in set(members): |
126 | a74ba506 | Sofia Papagiannaki | parts = m.split(':', 1) |
127 | a74ba506 | Sofia Papagiannaki | if len(parts) != 2: |
128 | a74ba506 | Sofia Papagiannaki | continue
|
129 | a74ba506 | Sofia Papagiannaki | user, group = parts |
130 | a74ba506 | Sofia Papagiannaki | members.remove(m) |
131 | a74ba506 | Sofia Papagiannaki | members.update(self.group_members(user, group))
|
132 | a74ba506 | Sofia Papagiannaki | return list(members) |
133 | 2715ade4 | Sofia Papagiannaki | |
134 | 4f917833 | Sofia Papagiannaki | def access_clear(self, path): |
135 | 4f917833 | Sofia Papagiannaki | """Revoke access to path (both permissions and public)."""
|
136 | 2715ade4 | Sofia Papagiannaki | |
137 | 4f917833 | Sofia Papagiannaki | self.xfeature_destroy(path)
|
138 | 4f917833 | Sofia Papagiannaki | self.public_unset(path)
|
139 | 2715ade4 | Sofia Papagiannaki | |
140 | 8221c89d | Sofia Papagiannaki | def access_clear_bulk(self, paths): |
141 | 8221c89d | Sofia Papagiannaki | """Revoke access to path (both permissions and public)."""
|
142 | 2715ade4 | Sofia Papagiannaki | |
143 | 8221c89d | Sofia Papagiannaki | self.xfeature_destroy_bulk(paths)
|
144 | 8221c89d | Sofia Papagiannaki | self.public_unset_bulk(paths)
|
145 | 2715ade4 | Sofia Papagiannaki | |
146 | 4f917833 | Sofia Papagiannaki | def access_check(self, path, access, member): |
147 | 4f917833 | Sofia Papagiannaki | """Return true if the member has this access to the path."""
|
148 | 2715ade4 | Sofia Papagiannaki | |
149 | cf341da4 | Antony Chazapis | feature = self.xfeature_get(path)
|
150 | cf341da4 | Antony Chazapis | if not feature: |
151 | 4f917833 | Sofia Papagiannaki | return False |
152 | 4f917833 | Sofia Papagiannaki | members = self.feature_get(feature, access)
|
153 | 4f917833 | Sofia Papagiannaki | if member in members or '*' in members: |
154 | 4f917833 | Sofia Papagiannaki | return True |
155 | 4f917833 | Sofia Papagiannaki | for owner, group in self.group_parents(member): |
156 | 4f917833 | Sofia Papagiannaki | if owner + ':' + group in members: |
157 | 4f917833 | Sofia Papagiannaki | return True |
158 | 4f917833 | Sofia Papagiannaki | return False |
159 | 2715ade4 | Sofia Papagiannaki | |
160 | dc88754b | Nanakos Chrysostomos | def access_check_bulk(self, paths, member): |
161 | dc88754b | Nanakos Chrysostomos | rows = None
|
162 | a3622324 | Chrysostomos Nanakos | xfeatures_xfeaturevals = \ |
163 | a3622324 | Chrysostomos Nanakos | self.xfeaturevals.join(self.xfeatures, |
164 | a3622324 | Chrysostomos Nanakos | onclause= |
165 | a3622324 | Chrysostomos Nanakos | and_(self.xfeatures.c.feature_id ==
|
166 | a3622324 | Chrysostomos Nanakos | self.xfeaturevals.c.feature_id,
|
167 | a3622324 | Chrysostomos Nanakos | self.xfeatures.c.path.in_(paths)))
|
168 | dc88754b | Nanakos Chrysostomos | s = select([self.xfeatures.c.path,
|
169 | a3622324 | Chrysostomos Nanakos | self.xfeaturevals.c.value,
|
170 | a3622324 | Chrysostomos Nanakos | self.xfeaturevals.c.feature_id,
|
171 | a3622324 | Chrysostomos Nanakos | self.xfeaturevals.c.key],
|
172 | a3622324 | Chrysostomos Nanakos | from_obj=[xfeatures_xfeaturevals]) |
173 | dc88754b | Nanakos Chrysostomos | r = self.conn.execute(s)
|
174 | dc88754b | Nanakos Chrysostomos | rows = r.fetchall() |
175 | dc88754b | Nanakos Chrysostomos | r.close() |
176 | dc88754b | Nanakos Chrysostomos | if rows:
|
177 | dc88754b | Nanakos Chrysostomos | access_check_paths = {} |
178 | dc88754b | Nanakos Chrysostomos | for path, value, feature_id, key in rows: |
179 | dc88754b | Nanakos Chrysostomos | try:
|
180 | dc88754b | Nanakos Chrysostomos | access_check_paths[path].append((value, feature_id, key)) |
181 | dc88754b | Nanakos Chrysostomos | except KeyError: |
182 | dc88754b | Nanakos Chrysostomos | access_check_paths[path] = [(value, feature_id, key)] |
183 | dc88754b | Nanakos Chrysostomos | access_check_paths['group_parents'] = self.group_parents(member) |
184 | dc88754b | Nanakos Chrysostomos | return access_check_paths
|
185 | dc88754b | Nanakos Chrysostomos | return None |
186 | dc88754b | Nanakos Chrysostomos | |
187 | 4f917833 | Sofia Papagiannaki | def access_inherit(self, path): |
188 | cf341da4 | Antony Chazapis | """Return the paths influencing the access for path."""
|
189 | 2715ade4 | Sofia Papagiannaki | |
190 | d83c93c9 | Antony Chazapis | # r = self.xfeature_inherit(path)
|
191 | d83c93c9 | Antony Chazapis | # if not r:
|
192 | d83c93c9 | Antony Chazapis | # return []
|
193 | d83c93c9 | Antony Chazapis | # # Compute valid.
|
194 | d83c93c9 | Antony Chazapis | # return [x[0] for x in r if x[0] in valid]
|
195 | 2715ade4 | Sofia Papagiannaki | |
196 | cf341da4 | Antony Chazapis | # Only keep path components.
|
197 | cf341da4 | Antony Chazapis | parts = path.rstrip('/').split('/') |
198 | cf341da4 | Antony Chazapis | valid = [] |
199 | cf341da4 | Antony Chazapis | for i in range(1, len(parts)): |
200 | cf341da4 | Antony Chazapis | subp = '/'.join(parts[:i + 1]) |
201 | cf341da4 | Antony Chazapis | valid.append(subp) |
202 | d83c93c9 | Antony Chazapis | if subp != path:
|
203 | d83c93c9 | Antony Chazapis | valid.append(subp + '/')
|
204 | d83c93c9 | Antony Chazapis | return [x for x in valid if self.xfeature_get(x)] |
205 | 2715ade4 | Sofia Papagiannaki | |
206 | dc88754b | Nanakos Chrysostomos | def access_inherit_bulk(self, paths): |
207 | dc88754b | Nanakos Chrysostomos | """Return the paths influencing the access for path."""
|
208 | dc88754b | Nanakos Chrysostomos | |
209 | dc88754b | Nanakos Chrysostomos | # Only keep path components.
|
210 | dc88754b | Nanakos Chrysostomos | valid = [] |
211 | dc88754b | Nanakos Chrysostomos | for path in paths: |
212 | dc88754b | Nanakos Chrysostomos | parts = path.rstrip('/').split('/') |
213 | dc88754b | Nanakos Chrysostomos | for i in range(1, len(parts)): |
214 | dc88754b | Nanakos Chrysostomos | subp = '/'.join(parts[:i + 1]) |
215 | dc88754b | Nanakos Chrysostomos | valid.append(subp) |
216 | dc88754b | Nanakos Chrysostomos | if subp != path:
|
217 | dc88754b | Nanakos Chrysostomos | valid.append(subp + '/')
|
218 | dc88754b | Nanakos Chrysostomos | valid = self.xfeature_get_bulk(valid)
|
219 | dc88754b | Nanakos Chrysostomos | return [x[1] for x in valid] |
220 | dc88754b | Nanakos Chrysostomos | |
221 | a63f36a2 | Sofia Papagiannaki | def access_list_paths(self, member, prefix=None, include_owned=False, |
222 | a63f36a2 | Sofia Papagiannaki | include_containers=True):
|
223 | a63f36a2 | Sofia Papagiannaki | """Return the list of paths granted to member.
|
224 | a63f36a2 | Sofia Papagiannaki |
|
225 | a63f36a2 | Sofia Papagiannaki | Keyword arguments:
|
226 | a63f36a2 | Sofia Papagiannaki | prefix -- return only paths starting with prefix (default None)
|
227 | a63f36a2 | Sofia Papagiannaki | include_owned -- return also paths owned by member (default False)
|
228 | a63f36a2 | Sofia Papagiannaki | include_containers -- return also container paths owned by member
|
229 | a63f36a2 | Sofia Papagiannaki | (default True)
|
230 | a63f36a2 | Sofia Papagiannaki |
|
231 | a63f36a2 | Sofia Papagiannaki | """
|
232 | 2715ade4 | Sofia Papagiannaki | |
233 | 2715ade4 | Sofia Papagiannaki | xfeatures_xfeaturevals = self.xfeatures.join(self.xfeaturevals) |
234 | 2715ade4 | Sofia Papagiannaki | |
235 | 4f917833 | Sofia Papagiannaki | selectable = (self.groups.c.owner + ':' + self.groups.c.name) |
236 | 4f917833 | Sofia Papagiannaki | member_groups = select([selectable.label('value')],
|
237 | 2715ade4 | Sofia Papagiannaki | self.groups.c.member == member)
|
238 | 2715ade4 | Sofia Papagiannaki | |
239 | 4f917833 | Sofia Papagiannaki | members = select([literal(member).label('value')])
|
240 | f992aa60 | Sofia Papagiannaki | any = select([literal('*').label('value')]) |
241 | 2715ade4 | Sofia Papagiannaki | |
242 | fe232f24 | Sofia Papagiannaki | u = union(member_groups, members, any).alias()
|
243 | 4f1bc0a6 | Sofia Papagiannaki | inner_join = join(xfeatures_xfeaturevals, u, |
244 | 2715ade4 | Sofia Papagiannaki | self.xfeaturevals.c.value == u.c.value)
|
245 | 4f917833 | Sofia Papagiannaki | s = select([self.xfeatures.c.path], from_obj=[inner_join]).distinct()
|
246 | 4f917833 | Sofia Papagiannaki | if prefix:
|
247 | 6e0f3e65 | Sofia Papagiannaki | like = lambda p: self.xfeatures.c.path.like( |
248 | 6e0f3e65 | Sofia Papagiannaki | self.escape_like(p) + '%', escape=ESCAPE_CHAR) |
249 | 6e0f3e65 | Sofia Papagiannaki | s = s.where(or_(*map(like,
|
250 | 6e0f3e65 | Sofia Papagiannaki | self.access_inherit(prefix) or [prefix]))) |
251 | 4f917833 | Sofia Papagiannaki | r = self.conn.execute(s)
|
252 | 4f917833 | Sofia Papagiannaki | l = [row[0] for row in r.fetchall()] |
253 | 4f917833 | Sofia Papagiannaki | r.close() |
254 | a63f36a2 | Sofia Papagiannaki | |
255 | a63f36a2 | Sofia Papagiannaki | if include_owned:
|
256 | a63f36a2 | Sofia Papagiannaki | container_nodes = select( |
257 | a63f36a2 | Sofia Papagiannaki | [self.nodes.c.node],
|
258 | a63f36a2 | Sofia Papagiannaki | self.nodes.c.parent == self.node_lookup(member)) |
259 | a63f36a2 | Sofia Papagiannaki | condition = self.nodes.c.parent.in_(container_nodes)
|
260 | a63f36a2 | Sofia Papagiannaki | if include_containers:
|
261 | a63f36a2 | Sofia Papagiannaki | condition = or_(condition, |
262 | a63f36a2 | Sofia Papagiannaki | self.nodes.c.node.in_(container_nodes))
|
263 | a63f36a2 | Sofia Papagiannaki | s = select([self.nodes.c.path], condition)
|
264 | a63f36a2 | Sofia Papagiannaki | r = self.conn.execute(s)
|
265 | a63f36a2 | Sofia Papagiannaki | l += [row[0] for row in r.fetchall() if row[0] not in l] |
266 | a63f36a2 | Sofia Papagiannaki | r.close() |
267 | 4f917833 | Sofia Papagiannaki | return l
|
268 | 2715ade4 | Sofia Papagiannaki | |
269 | 4f917833 | Sofia Papagiannaki | def access_list_shared(self, prefix=''): |
270 | 4f917833 | Sofia Papagiannaki | """Return the list of shared paths."""
|
271 | 2715ade4 | Sofia Papagiannaki | |
272 | 6e0f3e65 | Sofia Papagiannaki | s = select([self.xfeatures.c.path])
|
273 | 6e0f3e65 | Sofia Papagiannaki | like = lambda p: self.xfeatures.c.path.like( |
274 | 6e0f3e65 | Sofia Papagiannaki | self.escape_like(p) + '%', escape=ESCAPE_CHAR) |
275 | 6e0f3e65 | Sofia Papagiannaki | s = s.where(or_(*map(like, self.access_inherit(prefix) or [prefix]))) |
276 | 6e0f3e65 | Sofia Papagiannaki | s = s.order_by(self.xfeatures.c.path.asc())
|
277 | 4f917833 | Sofia Papagiannaki | r = self.conn.execute(s)
|
278 | 4f917833 | Sofia Papagiannaki | l = [row[0] for row in r.fetchall()] |
279 | 4f917833 | Sofia Papagiannaki | r.close() |
280 | 937dc831 | Antony Chazapis | return l |