Avoid reverse LIKE statements in SQL.
[pithos] / pithos / backends / lib / sqlite / permissions.py
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
38
39 READ = 0
40 WRITE = 1
41
42
43 class Permissions(XFeatures, Groups, Public):
44     
45     def __init__(self, **params):
46         XFeatures.__init__(self, **params)
47         Groups.__init__(self, **params)
48         Public.__init__(self, **params)
49     
50     def access_grant(self, path, access, members=()):
51         """Grant members with access to path.
52            Members can also be '*' (all),
53            or some group specified as 'owner:group'."""
54         
55         if not members:
56             return
57         feature = self.xfeature_create(path)
58         self.feature_setmany(feature, access, members)
59     
60     def access_set(self, path, permissions):
61         """Set permissions for path. The permissions dict
62            maps 'read', 'write' keys to member lists."""
63         
64         r = permissions.get('read', [])
65         w = permissions.get('write', [])
66         if not r and not w:
67             self.xfeature_destroy(path)
68             return
69         feature = self.xfeature_create(path)
70         if r:
71             self.feature_clear(feature, READ)
72             self.feature_setmany(feature, READ, r)
73         if w:
74             self.feature_clear(feature, WRITE)
75             self.feature_setmany(feature, WRITE, w)
76     
77     def access_get(self, path):
78         """Get permissions for path."""
79         
80         feature = self.xfeature_get(path)
81         if not feature:
82             return {}
83         permissions = self.feature_dict(feature)
84         if READ in permissions:
85             permissions['read'] = permissions[READ]
86             del(permissions[READ])
87         if WRITE in permissions:
88             permissions['write'] = permissions[WRITE]
89             del(permissions[WRITE])
90         return permissions
91     
92     def access_clear(self, path):
93         """Revoke access to path (both permissions and public)."""
94         
95         self.xfeature_destroy(path)
96         self.public_unset(path)
97     
98     def access_check(self, path, access, member):
99         """Return true if the member has this access to the path."""
100         
101         feature = self.xfeature_get(path)
102         if not feature:
103             return False
104         members = self.feature_get(feature, access)
105         if member in members or '*' in members:
106             return True
107         for owner, group in self.group_parents(member):
108             if owner + ':' + group in members:
109                 return True
110         return False
111     
112     def access_inherit(self, path):
113         """Return the paths influencing the access for path."""
114         
115 #         r = self.xfeature_inherit(path)
116 #         if not r:
117 #             return []
118 #         # Compute valid.
119 #         return [x[0] for x in r if x[0] in valid]
120         
121         # Only keep path components.
122         parts = path.rstrip('/').split('/')
123         valid = []
124         for i in range(1, len(parts)):
125             subp = '/'.join(parts[:i + 1])
126             valid.append(subp)
127             if subp != path:
128                 valid.append(subp + '/')
129         return [x for x in valid if self.xfeature_get(x)]
130     
131     def access_list_paths(self, member, prefix=None):
132         """Return the list of paths granted to member."""
133         
134         q = ("select distinct path from xfeatures inner join "
135              "   (select distinct feature_id, key from xfeaturevals inner join "
136              "      (select owner || ':' || name as value from groups "
137              "       where member = ? union select ? union select '*') "
138              "    using (value)) "
139              "using (feature_id)")
140         p = (member, member)
141         if prefix:
142             q += " where path like ? escape '\\'"
143             p += (self.escape_like(prefix) + '%',)
144         self.execute(q, p)
145         return [r[0] for r in self.fetchall()]
146     
147     def access_list_shared(self, prefix=''):
148         """Return the list of shared paths."""
149         
150         q = "select path from xfeatures where path like ? escape '\\'"
151         self.execute(q, (self.escape_like(prefix) + '%',))
152         return [r[0] for r in self.fetchall()]