Move various functionality from doorUpdater to DoorController

This commit is contained in:
Adam Goldsmith 2020-05-29 17:56:09 -04:00
parent 5401e8b185
commit 4d38ac5840
2 changed files with 88 additions and 77 deletions

View File

@ -178,48 +178,14 @@ class DoorMember(Member):
"custom2": self.membershipWorksID,
}
def make_schedules(self, schedulesMap):
roles = [
E.Role(
{
"roleID": self.cardholderID,
"scheduleID": schedulesMap[schedule],
"resourceID": "0",
}
)
for schedule in self.schedules
]
return E.RoleSet(
{"action": "UD", "roleSetID": self.cardholderID}, E.Roles(*roles)
)
def make_credentials(self, newCredentials, cardFormats):
out = [
E.Credential(
{
"formatName": str(credential.code[0]),
"cardNumber": str(credential.code[1]),
"formatID": cardFormats[str(credential.code[0])],
"isCard": "true",
"cardholderID": self.cardholderID,
}
)
for credential in newCredentials
]
return E.Credentials({"action": "AD"}, *out)
def update_door(door, members):
cardFormats = door.get_cardFormats()
cardholders = {
member.membershipWorksID: member
for member in [
DoorMember.from_cardholder(ch, door) for ch in door.get_cardholders()
]
}
schedulesMap = door.get_scheduleMap()
allCredentials = set(
Credential(hex=c.attrib["rawCardNumber"]) for c in door.get_credentials()
)
@ -231,9 +197,7 @@ def update_door(door, members):
if member.membershipWorksID not in cardholders:
print("- Adding Member {member.forename} {member.surname}:")
print(f" - {member.attribs()}")
resp = door.doXMLRequest(
ROOT(E.Cardholders({"action": "AD"}, E.Cardholder(member.attribs())))
)
resp = door.add_cardholder(member.attribs)
member.cardholderID = resp.find("{*}Cardholders/{*}Cardholder").attrib[
"cardholderID"
]
@ -252,14 +216,7 @@ def update_door(door, members):
print(f"- Updating profile for {member.forename} {member.surname}")
print(f" - Old: {ch.attribs()}")
print(f" - New: {member.attribs()}")
door.doXMLRequest(
ROOT(
E.Cardholders(
{"action": "UD", "cardholderID": member.cardholderID},
E.CardHolder(member.attribs()),
)
)
)
door.update_cardholder(member.cardholderID, member.attribs)
if member.credentials != ch.credentials:
print(f"- Updating card for {member.forename} {member.surname}")
@ -277,18 +234,7 @@ def update_door(door, members):
# cards removed, and won't be reassigned to someone else
for card in (oldCards - newCards) - allNewCards:
door.doXMLRequest(
ROOT(
E.Credentials(
{
"action": "UD",
"rawCardNumber": card.hex,
"isCard": "true",
},
E.Credential({"cardholderID": ""}),
)
)
)
door.assign_credential(card, None)
if newCards - oldCards: # cards added
for card in newCards & allNewCards: # new card exists in another member
@ -304,28 +250,11 @@ def update_door(door, members):
# card existed in door, and needs to be reassigned
for card in newCards & allCredentials:
door.doXMLRequest(
ROOT(
E.Credentials(
{
"action": "UD",
"rawCardNumber": card.hex,
"isCard": "true",
},
E.Credential({"cardholderID": member.cardholderID}),
)
)
)
door.assign_credential(card, member.cardholderID)
# cards that never existed, and need to be created
if newCards - allCredentials:
door.doXMLRequest(
ROOT(
member.make_credentials(
newCards - allCredentials, cardFormats
)
)
)
door.add_credentials(newCards - allCredentials, member.cardholderID)
if member.schedules != ch.schedules:
print(
@ -333,7 +262,7 @@ def update_door(door, members):
+ f" {member.forename} {member.surname}:"
+ f" {ch.schedules} -> {member.schedules}"
)
door.doXMLRequest(ROOT(member.make_schedules(schedulesMap)))
door.set_cardholder_schedules(member.cardholderID, member.schedules)
# TODO: delete cardholders that are no longer members?

View File

@ -40,6 +40,19 @@ class DoorController:
self.name = name
self.access = access
# lazy evaluated, hopefully won't change for the lifetime of this object
@property
def cardFormats(self):
if not self._cardFormats:
self._cardFormats = self.get_cardFormats()
return self._cardFormats
@property
def schedulesMap(self):
if not self._schedulesMap:
self._schedulesMap = self.get_schedulesMap()
return self._schedulesMap
def doImport(self, params=None, files=None):
"""Send a request to the door control import script"""
r = requests.post(
@ -131,6 +144,24 @@ class DoorController:
# load new schedules
self.doXMLRequest(schedules)
def set_cardholder_schedules(self, cardholderID, schedules):
roles = [
E.Role(
{
"roleID": cardholderID,
"scheduleID": self.schedulesMap[schedule],
"resourceID": "0",
}
)
for schedule in schedules
]
roleSet = E.RoleSet(
{"action": "UD", "roleSetID": cardholderID}, E.Roles(*roles)
)
return self.doXMLRequest(ROOT(roleSet))
def get_cardFormats(self):
cardFormats = self.doXMLRequest(
ROOT(E.CardFormats({"action": "LR", "responseFormat": "expanded"}))
@ -192,9 +223,60 @@ class DoorController:
def get_cardholders(self):
return self.get_records(E.Cardholders, 1000, {"responseFormat": "expanded"})
def add_cardholder(self, attribs):
return self.doXMLRequest(
ROOT(E.Cardholders({"action": "AD"}, E.Cardholder(attribs)))
)
def update_cardholder(self, cardholderID, attribs):
return self.doXMLRequest(
ROOT(
E.Cardholders(
{"action": "UD", "cardholderID": cardholderID},
E.CardHolder(attribs),
)
)
)
def get_credentials(self):
return self.get_records(E.Credentials, 1000)
def add_credentials(self, credentials, cardholderID=None):
"""Create new Credentials. If a cardholderID is provided, assign the
new credentials to that cardholder"""
creds = [
E.Credential(
{
"formatName": str(credential.code[0]),
"cardNumber": str(credential.code[1]),
"formatID": self.cardFormats[str(credential.code[0])],
"isCard": "true",
**({"cardholderID": cardholderID} if cardholderID else {}),
}
)
for credential in credentials
]
return self.doXMLRequest(ROOT(E.Credentials({"action": "AD"}, *creds)))
def assign_credential(self, credential, cardholderID=None):
# empty string removes assignment
if cardholderID is None:
cardholderID = ""
return self.doXMLRequest(
ROOT(
E.Credentials(
{
"action": "UD",
"rawCardNumber": credential.hex,
"isCard": "true",
},
E.Credential({"cardholderID": cardholderID}),
)
)
)
def get_events(self, threshold):
def event_newer_than_threshold(event):
return datetime.fromisoformat(event.attrib["timestamp"]) > threshold