1.1 --- a/imiptools/handlers/scheduling/access.py Sat Jan 30 17:24:39 2016 +0100
1.2 +++ b/imiptools/handlers/scheduling/access.py Sun Jan 31 00:45:26 2016 +0100
1.3 @@ -19,9 +19,97 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from imiptools.data import get_address
1.8 +from imiptools.data import get_address, get_addresses
1.9 +from imiptools.text import parse_line
1.10 +
1.11 +def access_control_list(handler, args):
1.12 +
1.13 + """
1.14 + Attempt to schedule the current object of the given 'handler' using an
1.15 + access control list provided in the given 'args', applying it to the
1.16 + organiser.
1.17 + """
1.18 +
1.19 + # Obtain either a file from the user's preferences directory...
1.20 +
1.21 + if not args:
1.22 + acl = handler.get_preferences().get("acl")
1.23 + lines = acl.strip().split("\n")
1.24 +
1.25 + # Or obtain the contents of a specific file.
1.26 +
1.27 + else:
1.28 + try:
1.29 + f = open(args[0])
1.30 + except IOError:
1.31 + return None
1.32 + try:
1.33 + lines = f.readlines()
1.34 + finally:
1.35 + f.close()
1.36 +
1.37 + # Use the current object's identities with the ACL rules.
1.38 +
1.39 + organiser = get_address(handler.obj.get_value("ORGANIZER"))
1.40 + attendees = get_addresses(handler.obj.get_values("ATTENDEE"))
1.41 +
1.42 + response = None
1.43 +
1.44 + for line in lines:
1.45 + parts = parse_line(line.strip())
1.46 +
1.47 + # Skip empty lines.
1.48 +
1.49 + if not parts:
1.50 + continue
1.51
1.52 -def same_domain_only(handler):
1.53 + # Accept either a single word with an action or a rule.
1.54 + # NOTE: Should signal an error with the format.
1.55 +
1.56 + if len(parts) == 1:
1.57 + action = parts[0]
1.58 + elif len(parts) >= 3:
1.59 + action, role, identities = parts[0], parts[1], map(get_address, parts[2:])
1.60 + else:
1.61 + return None
1.62 +
1.63 + if action.lower() == "accept":
1.64 + result = "ACCEPTED"
1.65 + elif action.lower() in ["decline", "reject"]:
1.66 + result = "DECLINED"
1.67 + else:
1.68 + return None
1.69 +
1.70 + # With only an action, prepare a default response in case none of
1.71 + # the rules match.
1.72 +
1.73 + if len(parts) == 1:
1.74 + response = result
1.75 + continue
1.76 +
1.77 + # Where no default has been set, use an implicit default based on
1.78 + # the action appearing in a rule.
1.79 +
1.80 + elif not response:
1.81 + response = result == "ACCEPTED" and "DECLINED" or "ACCEPTED"
1.82 +
1.83 + # Interpret a rule, attempting to match identities to properties.
1.84 +
1.85 + if role.lower() in ["organiser", "organizer"]:
1.86 + match = organiser in identities
1.87 + elif role.lower() in ["attendee", "attendees"]:
1.88 + match = set(attendees).intersection(identities)
1.89 + else:
1.90 + return None
1.91 +
1.92 + # Use the result of any match.
1.93 +
1.94 + if match:
1.95 + response = result
1.96 +
1.97 + return response
1.98 +
1.99 +def same_domain_only(handler, args):
1.100
1.101 """
1.102 Attempt to schedule the current object of the given 'handler' if the
1.103 @@ -39,6 +127,7 @@
1.104 # Registry of scheduling functions.
1.105
1.106 scheduling_functions = {
1.107 + "access_control_list" : access_control_list,
1.108 "same_domain_only" : same_domain_only,
1.109 }
1.110