Refactor MembershipWorks handling into separate class/file
This commit is contained in:
parent
25532bf21b
commit
c52b76534c
82
MembershipWorks.py
Normal file
82
MembershipWorks.py
Normal file
@ -0,0 +1,82 @@
|
||||
import csv
|
||||
from io import StringIO
|
||||
import requests
|
||||
|
||||
BASE_URL = "https://api.membershipworks.com/v1/"
|
||||
|
||||
class MembershipWorksRemoteError(Exception):
|
||||
def __init__(self, reason, r):
|
||||
super().__init__(
|
||||
f"Error when attempting {reason}: {r.status_code} {r.reason}\n{r.text}")
|
||||
|
||||
class MembershipWorks:
|
||||
def __init__(self):
|
||||
self.auth_token = None
|
||||
self.org_num = None
|
||||
|
||||
def login(self, username, password):
|
||||
"""Authenticate against the membershipworks api"""
|
||||
r = requests.post(BASE_URL + 'usr',
|
||||
data={"_st": "all",
|
||||
"eml": username,
|
||||
"org": "10000",
|
||||
"pwd": password})
|
||||
if r.status_code != 200 or 'SF' not in r.json():
|
||||
raise MembershipWorksRemoteError('login', r)
|
||||
self.auth_token = r.json()['SF']
|
||||
self.org_num = r.json()['org']
|
||||
|
||||
def _inject_auth(self, kwargs):
|
||||
# TODO: should probably be a decorator or something
|
||||
if self.auth_token is None:
|
||||
raise RuntimeError('Not Logged in to MembershipWorks')
|
||||
# add auth token to params
|
||||
if 'params' not in kwargs:
|
||||
kwargs['params'] = {}
|
||||
kwargs['params']["SF"] = self.auth_token
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
self._inject_auth(kwargs)
|
||||
# TODO: should probably do some error handling in here
|
||||
return requests.get(*args, **kwargs)
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
self._inject_auth(kwargs)
|
||||
# TODO: should probably do some error handling in here
|
||||
return requests.post(*args, **kwargs)
|
||||
|
||||
def get_member_ids(self, folders):
|
||||
# TODO: this is hardcoded for CMS
|
||||
folder_map = {
|
||||
'members': '5ae37979f033bfe8534f8799',
|
||||
'staff': '5771675edcdf126302a2f6b9',
|
||||
'misc': '5b69ee9bf033bf8e7346c434'
|
||||
}
|
||||
|
||||
r = self._get(BASE_URL + "ylp", params={
|
||||
"lbl": ",".join([folder_map[f] for f in folders]),
|
||||
"org": self.org_num,
|
||||
"var": "_id,nam,ctc"})
|
||||
if r.status_code != 200 or 'usr' not in r.json():
|
||||
raise MembershipWorksRemoteError('user listing', r)
|
||||
|
||||
# get list of member/staff IDs
|
||||
return [user['uid'] for user in r.json()['usr']]
|
||||
|
||||
def get_members(self, folders, columns):
|
||||
""" Pull the members csv from the membershipworks api
|
||||
folders: a list of the names of the folders to get
|
||||
(see folder_map in this function for mapping to ids)
|
||||
columns: which columns to get"""
|
||||
ids = self.get_member_ids(folders)
|
||||
|
||||
# get members CSV
|
||||
# TODO: maybe can just use previous get instead? would return JSON
|
||||
r = self._post(BASE_URL + "csv",
|
||||
data={"_rt": "946702800", # unknown
|
||||
"mux": "", # unknown
|
||||
"tid": ",".join(ids), # ids of members to get
|
||||
"var": columns})
|
||||
if r.status_code != 200:
|
||||
raise MembershipWorksRemoteError('csv generation', r)
|
||||
return list(csv.DictReader(StringIO(r.text)))
|
59
common.py
59
common.py
@ -1,15 +1,12 @@
|
||||
import csv
|
||||
from ruamel.yaml import YAML
|
||||
import urllib3
|
||||
import os
|
||||
import sys
|
||||
from io import StringIO
|
||||
import requests
|
||||
from hid.DoorController import DoorController
|
||||
|
||||
from passwords import (DOOR_USERNAME, DOOR_PASSWORD,
|
||||
MEMBERSHIPWORKS_USERNAME, MEMBERSHIPWORKS_PASSWORD)
|
||||
from passwords import DOOR_USERNAME, DOOR_PASSWORD
|
||||
from passwords import MEMBERSHIPWORKS_USERNAME, MEMBERSHIPWORKS_PASSWORD
|
||||
|
||||
from MembershipWorks import MembershipWorks
|
||||
# it's fine, ssl certs are for losers anyway
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
@ -28,51 +25,5 @@ doors = {doorName: DoorController(doorData['ip'],
|
||||
memberLevels = config['memberLevels']
|
||||
doorSpecificSchedules = config['doorSpecificSchedules']
|
||||
|
||||
def getMembershipworksData(folders, columns):
|
||||
""" Pull the members csv from the membershipworks api
|
||||
folders: a list of the names of the folders to get
|
||||
(see folder_map in this function for mapping to ids)
|
||||
columns: which columns to get"""
|
||||
BASE_URL = "https://api.membershipworks.com/v1/"
|
||||
folder_map = {'members': '5ae37979f033bfe8534f8799',
|
||||
'staff': '5771675edcdf126302a2f6b9',
|
||||
'misc': '5b69ee9bf033bf8e7346c434'}
|
||||
|
||||
# login
|
||||
r = requests.post(BASE_URL + 'usr',
|
||||
data={"_st": "all",
|
||||
"eml": MEMBERSHIPWORKS_USERNAME,
|
||||
"org": "10000",
|
||||
"pwd": MEMBERSHIPWORKS_PASSWORD})
|
||||
if r.status_code != 200 or 'SF' not in r.json():
|
||||
print("MembershipWorks Login Error: ", r.status_code, r.reason)
|
||||
print(r.text)
|
||||
sys.exit(1)
|
||||
login_data = r.json()
|
||||
|
||||
# get list of member/staff IDs
|
||||
r = requests.get(BASE_URL + "ylp",
|
||||
params={"SF": login_data['SF'],
|
||||
"lbl": ",".join([folder_map[f] for f in folders]),
|
||||
"org": login_data['org'],
|
||||
"var": "_id,nam,ctc"})
|
||||
if r.status_code != 200 or 'usr' not in r.json():
|
||||
print("MembershipWorks User Listing Error: ", r.status_code, r.reason)
|
||||
print(r.text)
|
||||
sys.exit(1)
|
||||
ids = [user['uid'] for user in r.json()['usr']]
|
||||
|
||||
# get members CSV
|
||||
# TODO: maybe can just use previous get instead? would return JSON
|
||||
r = requests.post(BASE_URL + "csv",
|
||||
params={"SF": login_data['SF']},
|
||||
data={"_rt": "946702800", # unknown
|
||||
"mux": "", # unknown
|
||||
"tid": ",".join(ids), # ids of members to get
|
||||
"var": columns})
|
||||
if r.status_code != 200:
|
||||
print("MembershipWorks CSV Generation Error: ", r.status_code, r.reason)
|
||||
print(r.text)
|
||||
sys.exit(1)
|
||||
|
||||
return list(csv.DictReader(StringIO(r.text)))
|
||||
membershipworks = MembershipWorks()
|
||||
membershipworks.login(MEMBERSHIPWORKS_USERNAME, MEMBERSHIPWORKS_PASSWORD)
|
||||
|
@ -1,11 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from common import (doors, getMembershipworksData, memberLevels,
|
||||
doorSpecificSchedules)
|
||||
from common import doors, membershipworks, memberLevels, doorSpecificSchedules
|
||||
from hid.Credential import Credential
|
||||
from hid.DoorController import ROOT, E
|
||||
|
||||
|
||||
class Member():
|
||||
def __init__(self, forename="", surname="", membershipWorksID="",
|
||||
middleName="", email="", phone="",
|
||||
@ -230,7 +228,7 @@ def update_door(door, members):
|
||||
|
||||
|
||||
def main():
|
||||
memberData = getMembershipworksData(
|
||||
memberData = membershipworks.get_members(
|
||||
['members', 'staff', 'misc'],
|
||||
"_id,nam,phn,eml,lvl,lbl,xws,xms,xsc,xas,xfd,xac,xcf,xeh,xse")
|
||||
|
||||
|
@ -6,8 +6,7 @@ from flask import Flask, render_template, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
from common import *
|
||||
from hid.DoorController import DoorController
|
||||
from common import doors, membershipworks
|
||||
|
||||
def parse_list(member, regex):
|
||||
data_list = []
|
||||
@ -46,7 +45,7 @@ def main():
|
||||
return render_template("members.html",
|
||||
error="Enter at least 3 characters to search")
|
||||
|
||||
data = getMembershipworksData(
|
||||
data = membershipworks.get_members(
|
||||
['members', 'staff'],
|
||||
"lvl,xws,xms,xsc,xas,xfd,xac,phn,eml,lbl,xcf,nam,end")
|
||||
|
||||
|
@ -4,7 +4,7 @@ import re
|
||||
import string
|
||||
import subprocess
|
||||
|
||||
from common import getMembershipworksData
|
||||
from common import membershipworks
|
||||
|
||||
LDAP_BASE = "cn=users,dc=sawtooth,dc=claremontmakerspace,dc=org"
|
||||
GROUP_BASE = "cn=groups,dc=sawtooth,dc=claremontmakerspace,dc=org"
|
||||
@ -32,7 +32,7 @@ def makeAppendGroups(member):
|
||||
for group in groups], [])
|
||||
|
||||
def main():
|
||||
members = getMembershipworksData(['members', 'staff'],
|
||||
members = membershipworks.get_members(['members', 'staff'],
|
||||
"lvl,phn,eml,lbl,nam,end,_id")
|
||||
makeGroups(members)
|
||||
|
||||
|
Reference in New Issue
Block a user