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