Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / lib / sqlalchemy / permissions.py @ 18d46d23

History | View | Annotate | Download (7.7 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 18d46d23 Sofia Papagiannaki
from sqlalchemy.sql import select, literal, or_
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 18d46d23 Sofia Papagiannaki
from node import Node
41 4f917833 Sofia Papagiannaki
42 235a4227 Sofia Papagiannaki
from dbworker import ESCAPE_CHAR
43 235a4227 Sofia Papagiannaki
44 4f917833 Sofia Papagiannaki
45 4f917833 Sofia Papagiannaki
READ = 0
46 4f917833 Sofia Papagiannaki
WRITE = 1
47 4f917833 Sofia Papagiannaki
48 4f917833 Sofia Papagiannaki
49 18d46d23 Sofia Papagiannaki
class Permissions(XFeatures, Groups, Public, Node):
50 2715ade4 Sofia Papagiannaki
51 4f917833 Sofia Papagiannaki
    def __init__(self, **params):
52 4f917833 Sofia Papagiannaki
        XFeatures.__init__(self, **params)
53 4f917833 Sofia Papagiannaki
        Groups.__init__(self, **params)
54 4f917833 Sofia Papagiannaki
        Public.__init__(self, **params)
55 18d46d23 Sofia Papagiannaki
        Node.__init__(self, **params)
56 2715ade4 Sofia Papagiannaki
57 4f917833 Sofia Papagiannaki
    def access_grant(self, path, access, members=()):
58 4f917833 Sofia Papagiannaki
        """Grant members with access to path.
59 4f917833 Sofia Papagiannaki
           Members can also be '*' (all),
60 4f917833 Sofia Papagiannaki
           or some group specified as 'owner:group'."""
61 2715ade4 Sofia Papagiannaki
62 4f917833 Sofia Papagiannaki
        if not members:
63 4f917833 Sofia Papagiannaki
            return
64 4f917833 Sofia Papagiannaki
        feature = self.xfeature_create(path)
65 4f917833 Sofia Papagiannaki
        self.feature_setmany(feature, access, members)
66 2715ade4 Sofia Papagiannaki
67 4f917833 Sofia Papagiannaki
    def access_set(self, path, permissions):
68 4f917833 Sofia Papagiannaki
        """Set permissions for path. The permissions dict
69 4f917833 Sofia Papagiannaki
           maps 'read', 'write' keys to member lists."""
70 2715ade4 Sofia Papagiannaki
71 cf341da4 Antony Chazapis
        r = permissions.get('read', [])
72 cf341da4 Antony Chazapis
        w = permissions.get('write', [])
73 cf341da4 Antony Chazapis
        if not r and not w:
74 cf341da4 Antony Chazapis
            self.xfeature_destroy(path)
75 cf341da4 Antony Chazapis
            return
76 cf341da4 Antony Chazapis
        feature = self.xfeature_create(path)
77 345dcf39 Antony Chazapis
        self.feature_clear(feature, READ)
78 345dcf39 Antony Chazapis
        self.feature_clear(feature, WRITE)
79 cf341da4 Antony Chazapis
        if r:
80 cf341da4 Antony Chazapis
            self.feature_setmany(feature, READ, r)
81 cf341da4 Antony Chazapis
        if w:
82 cf341da4 Antony Chazapis
            self.feature_setmany(feature, WRITE, w)
83 2715ade4 Sofia Papagiannaki
84 cf341da4 Antony Chazapis
    def access_get(self, path):
85 cf341da4 Antony Chazapis
        """Get permissions for path."""
86 2715ade4 Sofia Papagiannaki
87 cf341da4 Antony Chazapis
        feature = self.xfeature_get(path)
88 cf341da4 Antony Chazapis
        if not feature:
89 cf341da4 Antony Chazapis
            return {}
90 cf341da4 Antony Chazapis
        permissions = self.feature_dict(feature)
91 cf341da4 Antony Chazapis
        if READ in permissions:
92 cf341da4 Antony Chazapis
            permissions['read'] = permissions[READ]
93 cf341da4 Antony Chazapis
            del(permissions[READ])
94 cf341da4 Antony Chazapis
        if WRITE in permissions:
95 cf341da4 Antony Chazapis
            permissions['write'] = permissions[WRITE]
96 cf341da4 Antony Chazapis
            del(permissions[WRITE])
97 cf341da4 Antony Chazapis
        return permissions
98 2715ade4 Sofia Papagiannaki
99 a74ba506 Sofia Papagiannaki
    def access_members(self, path):
100 a74ba506 Sofia Papagiannaki
        feature = self.xfeature_get(path)
101 a74ba506 Sofia Papagiannaki
        if not feature:
102 a74ba506 Sofia Papagiannaki
            return []
103 a74ba506 Sofia Papagiannaki
        permissions = self.feature_dict(feature)
104 a74ba506 Sofia Papagiannaki
        members = set()
105 a74ba506 Sofia Papagiannaki
        members.update(permissions.get(READ, []))
106 a74ba506 Sofia Papagiannaki
        members.update(permissions.get(WRITE, []))
107 a74ba506 Sofia Papagiannaki
        for m in set(members):
108 a74ba506 Sofia Papagiannaki
            parts = m.split(':', 1)
109 a74ba506 Sofia Papagiannaki
            if len(parts) != 2:
110 a74ba506 Sofia Papagiannaki
                continue
111 a74ba506 Sofia Papagiannaki
            user, group = parts
112 a74ba506 Sofia Papagiannaki
            members.remove(m)
113 a74ba506 Sofia Papagiannaki
            members.update(self.group_members(user, group))
114 a74ba506 Sofia Papagiannaki
        return list(members)
115 2715ade4 Sofia Papagiannaki
116 4f917833 Sofia Papagiannaki
    def access_clear(self, path):
117 4f917833 Sofia Papagiannaki
        """Revoke access to path (both permissions and public)."""
118 2715ade4 Sofia Papagiannaki
119 4f917833 Sofia Papagiannaki
        self.xfeature_destroy(path)
120 4f917833 Sofia Papagiannaki
        self.public_unset(path)
121 2715ade4 Sofia Papagiannaki
122 8221c89d Sofia Papagiannaki
    def access_clear_bulk(self, paths):
123 8221c89d Sofia Papagiannaki
        """Revoke access to path (both permissions and public)."""
124 2715ade4 Sofia Papagiannaki
125 8221c89d Sofia Papagiannaki
        self.xfeature_destroy_bulk(paths)
126 8221c89d Sofia Papagiannaki
        self.public_unset_bulk(paths)
127 2715ade4 Sofia Papagiannaki
128 4f917833 Sofia Papagiannaki
    def access_check(self, path, access, member):
129 4f917833 Sofia Papagiannaki
        """Return true if the member has this access to the path."""
130 2715ade4 Sofia Papagiannaki
131 cf341da4 Antony Chazapis
        feature = self.xfeature_get(path)
132 cf341da4 Antony Chazapis
        if not feature:
133 4f917833 Sofia Papagiannaki
            return False
134 4f917833 Sofia Papagiannaki
        members = self.feature_get(feature, access)
135 4f917833 Sofia Papagiannaki
        if member in members or '*' in members:
136 4f917833 Sofia Papagiannaki
            return True
137 4f917833 Sofia Papagiannaki
        for owner, group in self.group_parents(member):
138 4f917833 Sofia Papagiannaki
            if owner + ':' + group in members:
139 4f917833 Sofia Papagiannaki
                return True
140 4f917833 Sofia Papagiannaki
        return False
141 2715ade4 Sofia Papagiannaki
142 4f917833 Sofia Papagiannaki
    def access_inherit(self, path):
143 cf341da4 Antony Chazapis
        """Return the paths influencing the access for path."""
144 2715ade4 Sofia Papagiannaki
145 d83c93c9 Antony Chazapis
#         r = self.xfeature_inherit(path)
146 d83c93c9 Antony Chazapis
#         if not r:
147 d83c93c9 Antony Chazapis
#             return []
148 d83c93c9 Antony Chazapis
#         # Compute valid.
149 d83c93c9 Antony Chazapis
#         return [x[0] for x in r if x[0] in valid]
150 2715ade4 Sofia Papagiannaki
151 cf341da4 Antony Chazapis
        # Only keep path components.
152 cf341da4 Antony Chazapis
        parts = path.rstrip('/').split('/')
153 cf341da4 Antony Chazapis
        valid = []
154 cf341da4 Antony Chazapis
        for i in range(1, len(parts)):
155 cf341da4 Antony Chazapis
            subp = '/'.join(parts[:i + 1])
156 cf341da4 Antony Chazapis
            valid.append(subp)
157 d83c93c9 Antony Chazapis
            if subp != path:
158 d83c93c9 Antony Chazapis
                valid.append(subp + '/')
159 d83c93c9 Antony Chazapis
        return [x for x in valid if self.xfeature_get(x)]
160 2715ade4 Sofia Papagiannaki
161 18d46d23 Sofia Papagiannaki
    def access_list_paths(self, member, prefix=None, include_owned=False,
162 18d46d23 Sofia Papagiannaki
                          include_containers=True):
163 18d46d23 Sofia Papagiannaki
        """Return the list of paths granted to member.
164 18d46d23 Sofia Papagiannaki

165 18d46d23 Sofia Papagiannaki
        Keyword arguments:
166 18d46d23 Sofia Papagiannaki
        prefix -- return only paths starting with prefix (default None)
167 18d46d23 Sofia Papagiannaki
        include_owned -- return also paths owned by member (default False)
168 18d46d23 Sofia Papagiannaki
        include_containers -- return also container paths owned by member
169 18d46d23 Sofia Papagiannaki
                              (default True)
170 18d46d23 Sofia Papagiannaki

171 18d46d23 Sofia Papagiannaki
        """
172 2715ade4 Sofia Papagiannaki
173 2715ade4 Sofia Papagiannaki
        xfeatures_xfeaturevals = self.xfeatures.join(self.xfeaturevals)
174 2715ade4 Sofia Papagiannaki
175 4f917833 Sofia Papagiannaki
        selectable = (self.groups.c.owner + ':' + self.groups.c.name)
176 4f917833 Sofia Papagiannaki
        member_groups = select([selectable.label('value')],
177 2715ade4 Sofia Papagiannaki
                               self.groups.c.member == member)
178 2715ade4 Sofia Papagiannaki
179 4f917833 Sofia Papagiannaki
        members = select([literal(member).label('value')])
180 f992aa60 Sofia Papagiannaki
        any = select([literal('*').label('value')])
181 2715ade4 Sofia Papagiannaki
182 fe232f24 Sofia Papagiannaki
        u = union(member_groups, members, any).alias()
183 4f1bc0a6 Sofia Papagiannaki
        inner_join = join(xfeatures_xfeaturevals, u,
184 2715ade4 Sofia Papagiannaki
                          self.xfeaturevals.c.value == u.c.value)
185 4f917833 Sofia Papagiannaki
        s = select([self.xfeatures.c.path], from_obj=[inner_join]).distinct()
186 4f917833 Sofia Papagiannaki
        if prefix:
187 2715ade4 Sofia Papagiannaki
            s = s.where(self.xfeatures.c.path.like(
188 235a4227 Sofia Papagiannaki
                self.escape_like(prefix) + '%', escape=ESCAPE_CHAR
189 235a4227 Sofia Papagiannaki
            ))
190 4f917833 Sofia Papagiannaki
        r = self.conn.execute(s)
191 4f917833 Sofia Papagiannaki
        l = [row[0] for row in r.fetchall()]
192 4f917833 Sofia Papagiannaki
        r.close()
193 18d46d23 Sofia Papagiannaki
194 18d46d23 Sofia Papagiannaki
        if include_owned:
195 18d46d23 Sofia Papagiannaki
            container_nodes = select(
196 18d46d23 Sofia Papagiannaki
                [self.nodes.c.node],
197 18d46d23 Sofia Papagiannaki
                self.nodes.c.parent == self.node_lookup(member))
198 18d46d23 Sofia Papagiannaki
            condition = self.nodes.c.parent.in_(container_nodes)
199 18d46d23 Sofia Papagiannaki
            if include_containers:
200 18d46d23 Sofia Papagiannaki
                condition = or_(condition,
201 18d46d23 Sofia Papagiannaki
                                self.nodes.c.node.in_(container_nodes))
202 18d46d23 Sofia Papagiannaki
            s = select([self.nodes.c.path], condition)
203 18d46d23 Sofia Papagiannaki
            r = self.conn.execute(s)
204 18d46d23 Sofia Papagiannaki
            l += [row[0] for row in r.fetchall() if row[0] not in l]
205 18d46d23 Sofia Papagiannaki
            r.close()
206 4f917833 Sofia Papagiannaki
        return l
207 2715ade4 Sofia Papagiannaki
208 4f917833 Sofia Papagiannaki
    def access_list_shared(self, prefix=''):
209 4f917833 Sofia Papagiannaki
        """Return the list of shared paths."""
210 2715ade4 Sofia Papagiannaki
211 4f917833 Sofia Papagiannaki
        s = select([self.xfeatures.c.path],
212 235a4227 Sofia Papagiannaki
                   self.xfeatures.c.path.like(self.escape_like(prefix) + '%',
213 235a4227 Sofia Papagiannaki
                                              escape=ESCAPE_CHAR
214 235a4227 Sofia Papagiannaki
                   )
215 235a4227 Sofia Papagiannaki
        ).order_by(self.xfeatures.c.path.asc())
216 4f917833 Sofia Papagiannaki
        r = self.conn.execute(s)
217 4f917833 Sofia Papagiannaki
        l = [row[0] for row in r.fetchall()]
218 4f917833 Sofia Papagiannaki
        r.close()
219 937dc831 Antony Chazapis
        return l