Package caldavclientlibrary :: Package browser :: Package commands :: Module acl
[hide private]
[frames] | no frames]

Source Code for Module caldavclientlibrary.browser.commands.acl

  1  ## 
  2  # Copyright (c) 2007-2016 Apple Inc. All rights reserved. 
  3  # 
  4  # Licensed under the Apache License, Version 2.0 (the "License"); 
  5  # you may not use this file except in compliance with the License. 
  6  # You may obtain a copy of the License at 
  7  # 
  8  # http://www.apache.org/licenses/LICENSE-2.0 
  9  # 
 10  # Unless required by applicable law or agreed to in writing, software 
 11  # distributed under the License is distributed on an "AS IS" BASIS, 
 12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 13  # See the License for the specific language governing permissions and 
 14  # limitations under the License. 
 15  ## 
 16   
 17  from caldavclientlibrary.browser.command import Command 
 18  from caldavclientlibrary.browser.command import WrongOptions 
 19  from caldavclientlibrary.protocol.url import URL 
 20  from caldavclientlibrary.protocol.webdav.definitions import davxml 
 21  from caldavclientlibrary.browser.subshell import SubShell 
 22  from caldavclientlibrary.browser import commands 
 23  from caldavclientlibrary.protocol.webdav.ace import ACE 
 24  from caldavclientlibrary.browser import utils 
 25  from caldavclientlibrary.protocol.caldav.definitions import caldavxml 
 26  from xml.etree.ElementTree import QName 
 27  import readline 
 28  import os 
 29  import getopt 
 30  import shlex 
 31   
32 -class Cmd(Command):
33
34 - def __init__(self):
35 super(Command, self).__init__() 36 self.cmds = ("acl",) 37 self.subshell = None
38
39 - def execute(self, name, options):
40 41 interactive = False 42 path = None 43 44 try: 45 opts, args = getopt.getopt(shlex.split(options), 'i') 46 except getopt.GetoptError, e: 47 print str(e) 48 print self.usage(name) 49 raise WrongOptions 50 51 for name, _ignore_value in opts: 52 53 if name == "-i": 54 interactive = True 55 else: 56 print "Unknown option: %s" % (name,) 57 print self.usage(name) 58 raise WrongOptions 59 60 if len(args) > 1: 61 print "Wrong number of arguments: %d" % (len(args),) 62 print self.usage(name) 63 raise WrongOptions 64 elif args: 65 path = args[0] 66 if not path.startswith("/"): 67 path = os.path.join(self.shell.wd, path) 68 else: 69 path = self.shell.wd 70 if not path.endswith("/"): 71 path += "/" 72 resource = URL(url=path) 73 74 results, bad = self.shell.account.session.getProperties(resource, (davxml.acl,)) 75 if davxml.acl in bad: 76 print "Could not retrieve DAV:acl property, status=%d" % (bad[davxml.acl],) 77 else: 78 if interactive: 79 self.doInteractiveMode(resource, results[davxml.acl]) 80 else: 81 aces = ACE.parseFromACL(results[davxml.acl]) 82 print utils.printACEList(aces, self.shell.account) 83 84 return True
85
86 - def doInteractiveMode(self, resource, acls):
87 88 print "Entering ACL edit mode on resource: %s" % (resource.relativeURL(),) 89 if not self.subshell: 90 self.subshell = SubShell(self.shell, "ACL", ( 91 commands.help.Cmd(), 92 commands.logging.Cmd(), 93 commands.quit.Cmd(), 94 Add(), 95 Change(), 96 Remove(), 97 List(), 98 )) 99 self.subshell.resource = resource 100 self.subshell.account = self.shell.account 101 self.subshell.run()
102
103 - def usage(self, name):
104 return """Usage: %s [OPTIONS] [PATH] 105 PATH is a relative or absolute path. 106 107 Options: 108 -i interactive mode for adding, changing and deleting ACLs. 109 if not present, existing ACLs will be printed. 110 """ % (name,)
111
112 - def helpDescription(self):
113 return "Manage the access privileges of a directory or file."
114
115 -class CommonACLCommand(Command):
116
117 - def displayACEList(self):
118 # First list the current set 119 results, bad = self.shell.shell.account.session.getProperties(self.shell.resource, (davxml.acl,)) 120 if davxml.acl in bad: 121 print "Could not retrieve DAV:acl property, status=%d" % (bad[davxml.acl],) 122 return None 123 else: 124 aces = ACE.parseFromACL(results[davxml.acl]) 125 print utils.printACEList(aces, self.shell.shell.account) 126 return aces
127
128 - def createACE(self, oldace=None):
129 130 ace = ACE() 131 print "Principal Type:" 132 print " 1. Principal path" 133 print " 2. All" 134 print " 3. Authenticated" 135 print " 4. Unauthenticated" 136 print " 5. Property" 137 insert = None 138 if oldace: 139 mapper = { 140 str(davxml.href): "1", 141 str(davxml.all): "2", 142 str(davxml.authenticated): "3", 143 str(davxml.unauthenticated): "4", 144 str(davxml.property): "5", 145 } 146 insert = mapper.get(oldace.principal) 147 choice = utils.numericInput("Select type: ", 1, 5, insert=insert) 148 if choice == "q": 149 return None 150 151 if choice == 1: 152 href = utils.textInput("Enter principal path: ", insert=oldace.data if oldace else None) 153 principal = self.shell.shell.account.getPrincipal(URL(url=href)) 154 ace.principal = str(davxml.href) 155 ace.data = principal.principalURL.relativeURL() 156 elif choice == 2: 157 ace.principal = str(davxml.all) 158 elif choice == 3: 159 ace.principal = str(davxml.authenticated) 160 elif choice == 4: 161 ace.principal = str(davxml.unauthenticated) 162 elif choice == 5: 163 prop = utils.textInput("Enter property qname: ", insert=str(oldace.data) if oldace else None) 164 ace.principal = str(davxml.property) 165 ace.data = QName(prop) 166 167 invert = utils.yesNoInput("Invert principal [y/n]: ", insert=("y" if oldace.invert else "n") if oldace else None) 168 ace.invert = (invert == "y") 169 170 grant = utils.choiceInput("Grant or Deny privileges [g/d]: ", ("g", "d",), insert=("g" if oldace.grant else "d") if oldace else None) 171 ace.grant = (grant == "g") 172 173 print "Privileges:" 174 print " a. {DAV}read" 175 print " b. {DAV}write" 176 print " c. {DAV}write-properties" 177 print " d. {DAV}write-content" 178 print " e. {DAV}read-acl" 179 print " f. {DAV}read-current-user-privilege-set" 180 print " g. {DAV}write-acl" 181 print " h. {DAV}bind" 182 print " i. {DAV}unbind" 183 print " j. {DAV}all" 184 print " k. {CALDAV}read-free-busy" 185 print " l. {CALDAV}schedule" 186 print " q. quit without changes" 187 choice = utils.multiChoiceInput( 188 "Select multiple items: ", 189 [char for char in "abcdefghijklq"], 190 ) 191 if "q" in choice: 192 return None 193 194 mappedPrivs = { 195 'a': davxml.read, 196 'b': davxml.write, 197 'c': davxml.write_properties, 198 'd': davxml.write_content, 199 'e': davxml.read_acl, 200 'f': davxml.read_current_user_privilege_set, 201 'g': davxml.write_acl, 202 'h': davxml.bind, 203 'i': davxml.unbind, 204 'j': davxml.all, 205 'k': caldavxml.read_free_busy, 206 'l': caldavxml.schedule, 207 } 208 ace.privs = () 209 for char in choice: 210 ace.privs += (mappedPrivs[char],) 211 212 return ace
213
214 -class Add(CommonACLCommand):
215 - def __init__(self):
216 super(Command, self).__init__() 217 self.cmds = ("add",)
218
219 - def execute(self, name, options):
220 221 # First list the current set 222 aces = self.displayACEList() 223 if aces: 224 # Ask user which one to delete 225 while True: 226 result = raw_input("Add ACL before [1 - %d] or cancel [q]: " % (len(aces) + 1,)) 227 if readline.get_current_history_length(): 228 readline.remove_history_item(readline.get_current_history_length() - 1) 229 if not result: 230 continue 231 if result[0] == "q": 232 break 233 try: 234 number = int(result) 235 if number > len(aces): 236 number = len(aces) 237 except ValueError: 238 print "Invalid input, try again." 239 continue 240 241 # Try and get the new ace 242 ace = self.createACE() 243 if not ace: 244 break 245 aces.insert(number, ace) 246 247 # Now remove those that cannot be edited 248 aces = [ace for ace in aces if ace.canChange()] 249 250 # Now execute 251 self.shell.shell.account.session.setACL(self.shell.resource, aces) 252 break
253
254 - def usage(self, name):
255 return """Usage: %s 256 """ % (name,)
257
258 - def helpDescription(self):
259 return "Add ACL to existing resource."
260
261 -class Change(CommonACLCommand):
262 - def __init__(self):
263 super(Command, self).__init__() 264 self.cmds = ("change",)
265
266 - def execute(self, name, options):
267 268 # First list the current set 269 aces = self.displayACEList() 270 if aces: 271 # Ask user which one to delete 272 while True: 273 result = raw_input("Change ACL at [1 - %d] or cancel [q]: " % (len(aces),)) 274 if readline.get_current_history_length(): 275 readline.remove_history_item(readline.get_current_history_length() - 1) 276 if not result: 277 continue 278 if result[0] == "q": 279 break 280 try: 281 number = int(result) 282 except ValueError: 283 print "Invalid input, try again." 284 continue 285 286 # Check that the targeted ace is editable 287 if not aces[number - 1].canChange(): 288 print "You cannot change a protected or inherited ace." 289 break 290 291 # Try and get the new ace 292 ace = self.createACE(oldace=aces[number - 1]) 293 if not ace: 294 break 295 aces[number - 1] = ace 296 297 # Now remove those that cannot be edited 298 aces = [ace for ace in aces if ace.canChange()] 299 300 # Now execute 301 self.shell.shell.account.session.setACL(self.shell.resource, aces) 302 break
303
304 - def usage(self, name):
305 return """Usage: %s 306 """ % (name,)
307
308 - def helpDescription(self):
309 return "Change ACL on existing resource."
310
311 -class Remove(CommonACLCommand):
312 - def __init__(self):
313 super(Command, self).__init__() 314 self.cmds = ("remove",)
315
316 - def execute(self, name, options):
317 318 # First list the current set 319 aces = self.displayACEList() 320 if aces: 321 # Ask user which one to delete 322 while True: 323 result = raw_input("Remove ACL [1 - %d] or cancel [q]: " % (len(aces),)) 324 if readline.get_current_history_length(): 325 readline.remove_history_item(readline.get_current_history_length() - 1) 326 if not result: 327 continue 328 if result[0] == "q": 329 break 330 try: 331 number = int(result) 332 except ValueError: 333 print "Invalid input, try again." 334 continue 335 336 # Check that the targeted ace is editable 337 if not aces[number-1].canChange(): 338 print "You cannot remove a protected or inherited ace." 339 break 340 341 # Remove the one we are removing 342 del aces[number-1] 343 344 # Now remove those that cannot be edited 345 aces = [ace for ace in aces if ace.canChange()] 346 347 # Now execute 348 self.shell.shell.account.session.setACL(self.shell.resource, aces) 349 break
350
351 - def usage(self, name):
352 return """Usage: %s 353 """ % (name,)
354
355 - def helpDescription(self):
356 return "Remove ACL on existing resource."
357
358 -class List(CommonACLCommand):
359 - def __init__(self):
360 super(Command, self).__init__() 361 self.cmds = ("list",)
362
363 - def execute(self, name, options):
364 365 self.displayACEList() 366 return True
367
368 - def usage(self, name):
369 return """Usage: %s 370 """ % (name,)
371
372 - def helpDescription(self):
373 return "List current ACLs on existing resource."
374