Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / lib / sqlite / permissions.py @ 6e0f3e65

History | View | Annotate | Download (7.2 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from xfeatures import XFeatures
35
from groups import Groups
36
from public import Public
37
from node import Node
38

    
39

    
40
READ = 0
41
WRITE = 1
42

    
43

    
44
class Permissions(XFeatures, Groups, Public, Node):
45

    
46
    def __init__(self, **params):
47
        XFeatures.__init__(self, **params)
48
        Groups.__init__(self, **params)
49
        Public.__init__(self, **params)
50
        Node.__init__(self, **params)
51

    
52
    def access_grant(self, path, access, members=()):
53
        """Grant members with access to path.
54
           Members can also be '*' (all),
55
           or some group specified as 'owner:group'."""
56

    
57
        if not members:
58
            return
59
        feature = self.xfeature_create(path)
60
        self.feature_setmany(feature, access, members)
61

    
62
    def access_set(self, path, permissions):
63
        """Set permissions for path. The permissions dict
64
           maps 'read', 'write' keys to member lists."""
65

    
66
        r = permissions.get('read', [])
67
        w = permissions.get('write', [])
68
        if not r and not w:
69
            self.xfeature_destroy(path)
70
            return
71
        feature = self.xfeature_create(path)
72
        self.feature_clear(feature, READ)
73
        self.feature_clear(feature, WRITE)
74
        if r:
75
            self.feature_setmany(feature, READ, r)
76
        if w:
77
            self.feature_setmany(feature, WRITE, w)
78

    
79
    def access_get(self, path):
80
        """Get permissions for path."""
81

    
82
        feature = self.xfeature_get(path)
83
        if not feature:
84
            return {}
85
        permissions = self.feature_dict(feature)
86
        if READ in permissions:
87
            permissions['read'] = permissions[READ]
88
            del(permissions[READ])
89
        if WRITE in permissions:
90
            permissions['write'] = permissions[WRITE]
91
            del(permissions[WRITE])
92
        return permissions
93

    
94
    def access_members(self, path):
95
        feature = self.xfeature_get(path)
96
        if not feature:
97
            return []
98
        permissions = self.feature_dict(feature)
99
        members = set()
100
        members.update(permissions.get(READ, []))
101
        members.update(permissions.get(WRITE, []))
102
        for m in set(members):
103
            parts = m.split(':', 1)
104
            if len(parts) != 2:
105
                continue
106
            user, group = parts
107
            members.remove(m)
108
            members.update(self.group_members(user, group))
109
        return members
110

    
111
    def access_clear(self, path):
112
        """Revoke access to path (both permissions and public)."""
113

    
114
        self.xfeature_destroy(path)
115
        self.public_unset(path)
116

    
117
    def access_clear_bulk(self, paths):
118
        """Revoke access to path (both permissions and public)."""
119

    
120
        self.xfeature_destroy_bulk(paths)
121
        self.public_unset_bulk(paths)
122

    
123
    def access_check(self, path, access, member):
124
        """Return true if the member has this access to the path."""
125

    
126
        feature = self.xfeature_get(path)
127
        if not feature:
128
            return False
129
        members = self.feature_get(feature, access)
130
        if member in members or '*' in members:
131
            return True
132
        for owner, group in self.group_parents(member):
133
            if owner + ':' + group in members:
134
                return True
135
        return False
136

    
137
    def access_inherit(self, path):
138
        """Return the paths influencing the access for path."""
139

    
140
#         r = self.xfeature_inherit(path)
141
#         if not r:
142
#             return []
143
#         # Compute valid.
144
#         return [x[0] for x in r if x[0] in valid]
145

    
146
        # Only keep path components.
147
        parts = path.rstrip('/').split('/')
148
        valid = []
149
        for i in range(1, len(parts)):
150
            subp = '/'.join(parts[:i + 1])
151
            valid.append(subp)
152
            if subp != path:
153
                valid.append(subp + '/')
154
        return [x for x in valid if self.xfeature_get(x)]
155

    
156
    def access_list_paths(self, member, prefix=None, include_owned=False,
157
                          include_containers=True):
158
        """Return the list of paths granted to member.
159

160
        Keyword arguments:
161
        prefix -- return only paths starting with prefix (default None)
162
        include_owned -- return also paths owned by member (default False)
163
        include_containers -- return also container paths owned by member
164
                              (default True)
165

166
        """
167

    
168
        q = ("select distinct path from xfeatures inner join "
169
             "  (select distinct feature_id, key from xfeaturevals inner join "
170
             "     (select owner || ':' || name as value from groups "
171
             "      where member = ? union select ? union select '*') "
172
             "   using (value)) "
173
             "using (feature_id)")
174
        p = (member, member)
175
        if prefix:
176
            q += " where"
177
            for path in self.access_inherit(prefix) or [prefix]:
178
                q += " path like ? escape '\\'"
179
                p += (self.escape_like(path) + '%',)
180
        self.execute(q, p)
181

    
182
        l = [r[0] for r in self.fetchall()]
183
        if include_owned:
184
            node = self.node_lookup(member)
185
            select_containers = "select node from nodes where parent = ? "
186
            q = ("select path from nodes where parent in (%s) " %
187
                 select_containers)
188
            args = [node]
189
            if include_containers:
190
                q += ("or node in (%s)" % select_containers)
191
                args += [node]
192
            self.execute(q, args)
193
            l += [r[0] for r in self.fetchall() if r[0] not in l]
194
        return l
195

    
196
    def access_list_shared(self, prefix=''):
197
        """Return the list of shared paths."""
198

    
199
        q = "select path from xfeatures where"
200
        p = []
201
        for path in self.access_inherit(prefix) or [prefix]:
202
            q += " path like ? escape '\\'"
203
            p += (self.escape_like(path) + '%',)
204
        self.execute(q, p)
205
        return [r[0] for r in self.fetchall()]