Changeset 5680065
- Timestamp:
- Mar 29, 2012, 12:53:54 AM (14 years ago)
- Branches:
- master, space-access, stable, stage
- Children:
- a53f8ee
- Parents:
- 94f3a39
- git-author:
- Alex Dehnert <adehnert@…> (03/29/12 00:53:54)
- git-committer:
- Alex Dehnert <adehnert@…> (03/29/12 00:53:54)
- Location:
- asadb
- Files:
-
- 2 added
- 6 edited
-
space/admin.py (modified) (1 diff)
-
space/diffs.py (modified) (8 diffs)
-
space/import_into_db.py (modified) (1 diff)
-
space/migrations/0001_initial.py (added)
-
space/migrations/__init__.py (added)
-
space/models.py (modified) (3 diffs)
-
template/space/cac-change-email.txt (modified) (1 diff)
-
template/space/group-change-email.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
asadb/space/admin.py
rf1e4d44 r5680065 8 8 'number', 9 9 'asa_owned', 10 'merged_acl', 10 11 ) 11 12 list_display_links = ( 'id', 'number', ) -
asadb/space/diffs.py
r94f3a39 r5680065 23 23 24 24 role = { 25 'office': groups.models.OfficerRole.objects.get(slug='office-access') 25 'office': groups.models.OfficerRole.objects.get(slug='office-access'), 26 'locker': groups.models.OfficerRole.objects.get(slug='locker-access'), 26 27 } 27 28 … … 60 61 self.group = group 61 62 self.offices = {} # Space.pk -> (ID -> (Set name, Set name)) 62 if not role: 63 role['office'] = groups.models.OfficerRole.objects.get(slug='office-access') 64 65 def learn_access(self, space_pk, old, new): 63 self.locker_acl = {} 64 self.locker_messages = [] 65 self.changes = False 66 67 def learn_office_access(self, space_pk, old, new): 66 68 group_pk = self.group.pk 67 69 if group_pk in old: … … 97 99 self.add_office_signatories_per_time(1, new_time) 98 100 99 def list_ changes(self, ):101 def list_office_changes(self, ): 100 102 cac_lines = [] 101 103 group_lines = [] … … 103 105 cac_lines.append("%s:\t%s:\t%s" % (mit_id, verb, name)) 104 106 group_lines.append("%s:\t%s" % (verb, name)) 105 changes = False106 107 for space_pk, space_data in self.offices.items(): 107 108 line = "Changes in %s:" % (all_spaces[space_pk].number, ) … … 113 114 pass 114 115 else: 115 changes = True116 self.changes = True 116 117 for name in old_names: 117 118 if name in new_names: … … 129 130 cac_msg = "\n".join(cac_lines) 130 131 group_msg = "\n".join(group_lines) 131 return changes, cac_msg, group_msg 132 return cac_msg, group_msg 133 134 def add_locker_signatories(self, space_access, time): 135 # space_access: ID -> (Name -> (Set Group.pk)) 136 if time in self.locker_acl: 137 locker_acl = self.locker_acl[time] 138 else: 139 locker_acl = self.group.officers(as_of=time, role=role['locker']) 140 self.locker_acl[time] = locker_acl 141 for holder in locker_acl: 142 fill_people(holder) 143 holder_name = people_name[holder.person] 144 holder_id = people_id[holder.person] 145 space_access[holder_id][holder_name].add(self.group.pk) 132 146 133 147 def init_groups(the_groups, assignments): … … 137 151 the_groups[group.id] = GroupInfo(group) 138 152 139 def space_specific_access(group_data, old_time, new_time, ): 140 process_spaces = space.models.Space.objects.all() 141 #process_spaces = process_spaces.filter(number="W20-467") 142 for the_space in process_spaces: 143 old_data = the_space.build_access(time=old_time) 144 new_data = the_space.build_access(time=new_time) 145 all_spaces[the_space.pk] = the_space 146 init_groups(group_data, old_data[2]) 147 init_groups(group_data, new_data[2]) 148 for group_pk, group in group_data.items(): 149 if group_pk in old_data[0] or group_pk in new_data[0]: 150 group.learn_access(the_space.pk, old_data[0], new_data[0]) 151 153 def flip_dict(dct): 154 new = collections.defaultdict(set) 155 for key, vals in dct.items(): 156 for val in vals: 157 new[val].add(key) 158 return new 159 160 def joint_keys(dct1, dct2): 161 return set(dct1.keys()).union(dct2.keys()) 162 163 class LockerAccessChangeEntry(object): 164 def __init__(self, mit_id, verb, name, groups): 165 self.mit_id = mit_id 166 self.verb = verb 167 self.name = name 168 self.cac_msgs = "" 169 self.group_msgs = "" 170 self.groups = groups 171 172 def cac_format(self): 173 return "%s\t%s\t%s\t%s" % (self.mit_id, self.verb, self.name, self.cac_msgs) 174 175 def group_format(self): 176 return "%s\t%s\t%s" % (self.verb, self.name, self.group_msgs) 177 178 def safe_add_change_real(change_by_name, change): 179 name = change.name 180 if name in change_by_name: 181 if change_by_name[name].verb != change.verb or change_by_name[name].groups != change.groups: 182 print "change_by_name=%s" % (change_by_name, ) 183 print "change: old=%s; new=%s" % (change_by_name[name], change) 184 assert False 185 else: 186 change_by_name[name] = change 187 188 def locker_access_diff(the_space, group_data, old_access, new_access, ): 189 cac_msgs = [] # [String] 190 for mit_id in joint_keys(old_access, new_access): 191 change_by_name = {} # name -> LockerAccessChangeEntry 192 def safe_add(change): 193 safe_add_change_real(change_by_name, change) 194 old_by_names = old_access[mit_id] 195 new_by_names = new_access[mit_id] 196 old_by_group = flip_dict(old_by_names) 197 new_by_group = flip_dict(new_by_names) 198 unchanged = (old_by_names == new_by_names) 199 if unchanged: continue 200 print "ID=%s (%s):\n\t%s\t(%s)\n\t%s\t(%s)\n" % (mit_id, unchanged, old_by_names, old_by_group, new_by_names, new_by_group, ), 201 for group_pk in joint_keys(old_by_group, new_by_group): 202 old_names = old_by_group[group_pk] 203 new_names = new_by_group[group_pk] 204 for name in old_names.union(new_names): 205 changed_groups = old_by_names[name] ^ new_by_names[name] 206 207 def mkchange(verb): 208 change = LockerAccessChangeEntry( 209 mit_id=mit_id, 210 verb=verb, 211 name=name, 212 groups=changed_groups, 213 ) 214 if verb == "Keep": 215 change.group_msgs = "(other groups involved)" 216 change.cac_msgs = "(groups: %s -> %s)" % (old_by_names[name], new_by_names[name]) 217 return change 218 219 if name in old_names and name in new_names: # keep 220 safe_add(mkchange("Keep")) 221 elif name in old_names: # remove from this group 222 if new_by_names[name]: # keep b/c other groups 223 safe_add(mkchange("Keep")) 224 else: 225 safe_add(mkchange("Remove")) 226 elif name in new_names: # add for this group 227 if old_by_names[name]: # keep b/c other groups 228 safe_add(mkchange("Keep")) 229 else: 230 safe_add(mkchange("Add")) 231 else: 232 assert False, "in old_names or new_names, but not in both, one, or the other..." 233 234 # Handle reporting the results... 235 for change in change_by_name.values(): 236 cac_msgs.append(change.cac_format()) 237 group_msg = "%s\t%s" % (the_space.number, change.group_format()) 238 for group_pk in change.groups: 239 group_data[group_pk].locker_messages.append(group_msg) 240 group_data[group_pk].changes = True 241 242 return cac_msgs 243 244 def space_specific_access(the_space, group_data, old_time, new_time, ): 245 old_data = the_space.build_access(time=old_time) 246 new_data = the_space.build_access(time=new_time) 247 all_spaces[the_space.pk] = the_space 248 init_groups(group_data, old_data[2]) 249 init_groups(group_data, new_data[2]) 250 for group_pk, group_info in group_data.items(): 251 if group_pk in old_data[0] or group_pk in new_data[0]: 252 if the_space.merged_acl: 253 group_info.add_locker_signatories(old_data[1], old_time) 254 group_info.add_locker_signatories(new_data[1], new_time) 255 else: 256 group_info.learn_office_access(the_space.pk, old_data[0], new_data[0]) 257 cac_msgs = [] 258 if the_space.merged_acl: 259 cac_msgs = locker_access_diff(the_space, group_data, old_data[1], new_data[1]) 260 return cac_msgs 152 261 153 262 def space_access_diffs(): … … 156 265 bulk_fill_people([old_time, new_time]) 157 266 group_data = {} # Group.pk -> GroupInfo 267 cac_locker_msgs = [] 268 269 process_spaces = space.models.Space.objects.all() 270 for the_space in process_spaces: 271 new_cac_msgs = space_specific_access(the_space, group_data, old_time, new_time) 272 if new_cac_msgs: 273 cac_locker_msgs.append("%s\n%s\n" % (the_space.number, "\n".join(new_cac_msgs))) 274 158 275 changed_groups = [] 159 space_specific_access(group_data, old_time, new_time)160 276 for group_pk, group_info in group_data.items(): 161 277 group_info.add_office_signatories(old_time, new_time) 162 c hanges, cac_changes, group_changes = group_info.list_changes()163 if changes:164 changed_groups.append((group_info.group, cac_changes, group_ changes))278 cac_changes, group_office_changes = group_info.list_office_changes() 279 if group_info.changes: 280 changed_groups.append((group_info.group, cac_changes, group_office_changes, group_info.locker_messages, )) 165 281 166 282 asa_rcpts = ['asa-space@mit.edu', 'asa-db@mit.edu', ] 167 283 util.emails.email_from_template( 168 284 tmpl='space/cac-change-email.txt', 169 context={'changed_groups': changed_groups },170 subject=" Office access updates",285 context={'changed_groups': changed_groups, 'locker_msgs':cac_locker_msgs, }, 286 subject="Space access updates", 171 287 to=['caclocks@mit.edu'], 172 288 cc=asa_rcpts, 173 289 ).send() 174 for group, cac_msg, group_ msgin changed_groups:290 for group, cac_msg, group_office_msg, group_locker_msgs in changed_groups: 175 291 util.emails.email_from_template( 176 292 tmpl='space/group-change-email.txt', 177 293 context={ 178 294 'group':group, 179 'msg':group_msg, 295 'office_msg':group_office_msg, 296 'locker_msgs':group_locker_msgs, 180 297 }, 181 subject=" Office access updates",298 subject="[ASA DB] Space access updates", 182 299 to=[group.officer_email], 183 300 cc=asa_rcpts, 184 301 ).send() 185 302 186 303 187 304 if __name__ == "__main__": -
asadb/space/import_into_db.py
ra86a924 r5680065 22 22 print "Ignoring missing group: %s: %s" % (line['group'], line, ) 23 23 return 24 the_space, created = space.models.Space.objects.get_or_create(number=line['office_number']) 24 the_space, created = space.models.Space.objects.get_or_create( 25 number=line['office_number'], 26 defaults=dict(merged_acl=bool(line['locker_number'])), 27 ) 25 28 group = groups.models.Group.objects.get(id=group_id) 26 29 try: -
asadb/space/models.py
r94f3a39 r5680065 14 14 number = models.CharField(max_length=20, unique=True, ) 15 15 asa_owned = models.BooleanField(default=True, ) 16 merged_acl = models.BooleanField(default=False, help_text="Does this room have a single merged ACL, that combines all groups together, or CAC maintain a separate ACL per-group? Generally, the shared storage offices get a merged ACL and everything else doesn't.") 16 17 notes = models.TextField(blank=True, ) 17 18 … … 70 71 aces = aces.filter(group=group) 71 72 access = {} # Group.pk -> (ID -> Set name) 72 access_by_id = {} # ID -> (Name -> (Set Group.pk)) 73 # ID -> (Name -> (Set Group.pk)) 74 access_by_id = collections.defaultdict(lambda: collections.defaultdict(set)) 73 75 for assignment in assignments: 74 76 if assignment.group.pk not in access: … … 77 79 if ace.group.pk in access: 78 80 access[ace.group.pk][ace.card_number].add(ace.name) 79 if ace.card_number not in access_by_id:80 access_by_id[ace.card_number] = collections.defaultdict(set)81 81 access_by_id[ace.card_number][ace.name].add(ace.group.pk) 82 82 else: -
asadb/template/space/cac-change-email.txt
rbec7760 r5680065 6 6 ASA Exec 7 7 8 {% for group, cac_changes, group_changes in changed_groups %} 8 {% if locker_msgs %}Locker room access: 9 {% for msg in locker_msgs %} 10 {{msg}} 11 {% endfor %} 12 {% endif %} 13 14 15 {% for group, cac_changes, group_office_changes, group_locker_changes in changed_groups %} 9 16 Group: {{group.name}} (ID#{{group.pk}}) 10 17 Officer email: {{group.officer_email}} 11 18 12 { {cac_changes}}19 {% if cac_changes %}{{cac_changes}} 13 20 14 15 {% endfor %}{% endautoescape %} 21 {% endif %} 22 {% endfor %} 23 {% endautoescape %} -
asadb/template/space/group-change-email.txt
rbec7760 r5680065 1 1 {% autoescape off %} 2 2 Hi {{group.name}}, 3 Thank you for updating office access on the ASA database today. We've forwarded the following changes on to CAC:3 Thank you for updating space access on the ASA database today. We've forwarded the following changes on to CAC: 4 4 5 {{msg}} 5 {% if office_msg %} 6 Office access: 7 8 {{office_msg}} 9 {% endif %}{% if locker_msgs %} 10 Locker (shared storage) access: 11 {% for msg in locker_msgs %} 12 {{msg}}{% endfor %} 13 {% endif %} 14 15 If you believe these changes are incorrect in any way, please let us know --- beyond just notifying CAC, we also want to find out why the errors happened. 6 16 7 17 Thanks,
Note: See TracChangeset
for help on using the changeset viewer.