def block_assignments(event): if request.method == "GET": if not check_permission("hotel_block.*.read", event=event): return "", 403 subquery = db.query(RoomNightRequest.badge).filter(RoomNightRequest.event == event, RoomNightRequest.requested == True).distinct().subquery().select() rows = db.query(Badge, HotelRoomRequest.declined, HotelRoomRequest.hotel_block, HotelRoomRequest.id, HotelRoomRequest.notes).options(joinedload('departments')).filter(HotelRoomRequest.event == event, HotelRoomRequest.badge.in_(subquery)).join(HotelRoomRequest, HotelRoomRequest.badge == Badge.id).all() badge_dicts = [] for badge, declined, block, hrr, notes in rows: if not declined: badge_dicts.append({ "id": badge.id, "notes": notes, "public_name": badge.public_name, "departments": [x.id for x in badge.departments], "department_names": [x.name for x in badge.departments], "badge_type": badge.badge_type, "hotel_block": block, "hotel_room_request": hrr }) return jsonify(badge_dicts) elif request.method == "POST": if not check_permission("hotel_block.*.write", event=event): return "", 403 room_requests = {x['id']: x['hotel_block'] for x in g.data['updates']} hotel_room_requests = db.query(HotelRoomRequest).filter(HotelRoomRequest.id.in_(room_requests.keys()), HotelRoomRequest.event == event).all() for hotel_room_request in hotel_room_requests: hotel_room_request.hotel_block = room_requests[hotel_room_request.id] db.commit() return "null", 200 return "", 406
def add_roommates(event, hotel_block, room_id): if not check_permission(f'hotel_block.{hotel_block}.write', event=event): return "", 403 reqs = db.query(HotelRoomRequest).filter(HotelRoomRequest.event==event, HotelRoomRequest.badge.in_(g.data['roommates'])).all() room_nights = db.query(HotelRoomNight).filter(HotelRoomNight.event==event).all() room_nights = {x.id: x for x in room_nights} for req in reqs: for night in req.room_night_requests: assign = False if night.requested: if room_nights[night.room_night].restricted: for approval in req.room_night_approvals: if approval.room_night == night.room_night and approval.approved: assign = True break else: assign = True for assignment in req.room_night_assignments: if assignment.room_night == night.room_night: assign = False break if assign: db.add(RoomNightAssignment(event=event, badge=req.badge, room_night=night.room_night, hotel_room=room_id)) update_room_request_props(db, reqs, assigned=True) for req in reqs: db.add(req) db.commit() return "null", 200
def shift_signup(event, shift): if 'badge' in request.json: badge = db.query(Badge).filter(Badge.id == request.json['badge']).one() elif g.badge: badge = g.badge else: return "The current user does not have a badge, and thus cannot sign up for shifts.", 412 shift = db.query(Shift).filter(Shift.id == shift).one() if shift.filledslots >= shift.slots: return "The shift is full.", 412 shift.filledslots += 1 assignment = ShiftAssignment(shift=shift.id, badge=badge.id, event=event) signup = ShiftSignup(badge=badge.id, shift=shift.id, job=shift.job, schedule=shift.schedule, schedule_event=shift.schedule_event, starttime=shift.starttime, duration=shift.duration) db.add(shift) db.add(assignment) db.add(signup) db.commit() return jsonify(shift=Shift.serialize(shift), shift_assignment=ShiftAssignment.serialize(assignment), shift_signup=ShiftSignup.serialize(signup))
def _store_response(self, job_id, iterable): with self.lock: if self.context[job_id]['state'] == "pending": self.context[job_id]['state'] = "immediate" return request_context = json.dumps({ "status": self.context[job_id]['status'], "response_headers": self.context[job_id]['response_headers'] }) del self.context[job_id] progress = json.dumps({ "complete": True, "amount": 0, "messages": "", "status": "" }) if r: r.set(f"{job_id}/context", request_context) for data in iterable: r.append(f"{job_id}/data", data) r.set(f"{job_id}/progress", progress) else: data = bytes() for chunk in iterable: data = data + chunk with self.lock: job = db.query(BackgroundJob).filter( BackgroundJob.uuid == job_id).one() job.progress = progress job.result = data job.context = request_context db.add(job) db.commit()
def logout(): if g.user: db.query(Session).filter(Session.user == g.user.id).delete() if 'session' in request.cookies: db.query(Session).filter( Session.secret == request.cookies.get('session')).delete() db.commit() return "null", 200
def flush_session_perms(user_id=None): if user_id: sessions = db.query(Session).filter(Session.user == user_id).all() else: sessions = db.query(Session).all() for session in sessions: perms = get_permissions(user_id=session.user) session.permissions=json.dumps(perms) db.add(session) db.commit()
def remove_roommates(event, hotel_block, room_id): if not check_permission(f'hotel_block.{hotel_block}.write', event=event): return "", 403 db.query(RoomNightAssignment).filter(RoomNightAssignment.event==event, RoomNightAssignment.hotel_room==room_id, RoomNightAssignment.badge.in_(g.data['roommates'])).delete() reqs = db.query(HotelRoomRequest).filter(HotelRoomRequest.event==event, HotelRoomRequest.badge.in_(g.data['roommates'])).all() update_room_request_props(db, reqs, assigned=False) for req in reqs: db.add(req) db.commit() return "null", 200
def change_password(user_id): if not check_permission(f"user.{user_id}.change_password" ) and not check_permission(f"user.{user_id}.self"): return "", 403 user = db.query(User).filter(User.id == user_id).one() if not 'password' in g.data: return "You must provide a password", 406 if len(g.data['password']) < 8: return "Your password must be at least 8 characters.", 406 user.password = sha256_crypt.hash(g.data['password']) db.add(user) db.commit() return "null", 200
def crud_single(model, event=None, department=None, id=None): perms = model_permissions(model.__tablename__.lower()) if request.method == "GET": if READ_PERMS.intersection( perms['*']) or (id in perms and READ_PERMS.intersection(perms[id])): full = request.args.get("full", False, type=lambda x: x.lower() == 'true') instance = db.query(model).filter(model.id == id).one_or_none() return jsonify( model.serialize(instance, serialize_relationships=full)) raise PermissionDenied() elif request.method == "PATCH": if WRITE_PERMS.intersection( perms['*']) or (id in perms and WRITE_PERMS.intersection(perms[id])): g.data['id'] = id g.data = {k: v for k, v in g.data.items() if hasattr(model, k)} instance = model.deserialize(g.data) db.add(instance) if hasattr(instance, 'onchange_cb'): db.flush() for cb in instance.onchange_cb: cb(db, instance) db.commit() return jsonify(model.serialize(instance)) raise PermissionDenied() elif request.method == "DELETE": if WRITE_PERMS.intersection( perms['*']) or (id in perms and WRITE_PERMS.intersection(perms[id])): instance = db.query(model).filter(model.id == id).one_or_none() if not instance: return "", 404 instance_data = None if hasattr(instance, 'onchange_cb'): instance_data = model.serialize(instance, serialize_relationships=True) db.delete(instance) if hasattr(instance, 'onchange_cb'): db.flush() for cb in instance.onchange_cb: cb(db, instance, deleted=instance_data) db.commit() return "null" raise PermissionDenied() raise MethodNotAllowed()
def initial_setup(): if User.query.first(): return "Initial setup has already completed.", 403 if request.json['username'] and request.json['email'] and request.json[ 'password']: user = User(username=request.json['username'], email=request.json['email'], password=sha256_crypt.hash(request.json['password']), active=True) role = Role(name="Server Admin", description="Allowed to do anything.") db.add(user) db.add(role) db.flush() perm = Permission(operation="*.*.*", role=role.id) grant = Grant(user=user.id, role=role.id) db.add(perm) db.add(grant) db.commit() return "null", 200 return "", 406
def hotel_approve(event, department): if check_permission("hotel_request.*.approve", event=event, department=department): room_night_request = db.query(RoomNightRequest).filter(RoomNightRequest.room_night == request.json['room_night'], RoomNightRequest.badge == request.json['badge']).one_or_none() if not room_night_request: return "Could not find corresponding request.", 404 approval = db.query(RoomNightApproval).filter(RoomNightApproval.badge == request.json['badge'], RoomNightApproval.room_night == request.json['room_night'], RoomNightApproval.department == department).one_or_none() if request.json['approved'] is None: if approval: db.delete(approval) else: if not approval: approval = RoomNightApproval(event=event, badge=request.json['badge'], department=department) approval.approved = request.json['approved'] approval.room_night = request.json['room_night'] db.add(approval) hotel_room_request = db.query(HotelRoomRequest).filter(HotelRoomRequest.badge == room_night_request.badge).one() update_room_request_props(db, [hotel_room_request,]) db.add(room_night_request) db.commit() return "null", 200 return "", 403
def login(): if request.json['username'] and request.json['password']: user = db.query(User).filter( User.username == request.json['username']).one_or_none() if user: if sha256_crypt.verify(request.json['password'], user.password): badges = db.query(Badge).filter(Badge.user == user.id).all() badge = None if badges: badge = badges[0].id perm_cache = get_permissions(user=user.id) session = Session(user=user.id, badge=badge, last_active=datetime.datetime.now(), secret=str(uuid.uuid4()), permissions=json.dumps(perm_cache)) db.add(session) db.commit() response = jsonify(session.secret) response.set_cookie('session', session.secret) return response return "", 406
def progress(self, amount, status=""): job_id = request.environ.get("TUBER_JOB_ID", "") if not job_id: return with self.lock: if r: progress = json.loads(r.get(f"{job_id}/progress")) progress['amount'] = amount if status: progress['status'] = status progress['messages'] += status + "\n" r.set(f"{job_id}/progress", json.dumps(progress)) else: job = db.query(BackgroundJob).filter( BackgroundJob.uuid == job_id).one() progress = json.loads(job.progress) progress['amount'] = amount if status: progress['status'] = status progress['messages'] += status + "\n" job.progress = json.dumps(progress) db.add(job) db.commit()
def run_staff_import(email, password, url, event): session = requests.Session() db.post(url + "/accounts/login", data={ "email": email, "password": password, "original_location": "homepage" }) attendees = get_uber_csv(session, "Attendee", url) num_staff = 0 print("Retrieved export") role = db.query(Role).filter(Role.name == "Default Staff").one_or_none() if not role: role = Role(name="Default Staff", description="Automatically assigned to staff.", event=event) db.add(role) db.flush() for perm in [ 'staff.search_names', 'hotel_request.create', 'event.read' ]: permission = Permission(operation=perm, role=role.id) db.add(permission) dh_role = db.query(Role).filter( Role.name == "Department Head").one_or_none() if not dh_role: dh_role = Role( name="Department Head", description="Automatically assigned to department heads.", event=event) db.add(dh_role) db.flush() for perm in ['department.write', 'hotel_request.approve']: permission = Permission(operation=perm, role=dh_role.id) db.add(permission) print("Adding attendees...") for attendee in attendees: if attendee['hotel_eligible'].lower() == "true": num_staff += 1 user = db.query(User).filter( User.password == attendee['id']).one_or_none() if not user: user = User(username=attendee['id'], email=attendee['id'], password=attendee['id'], active=False) db.add(user) db.flush() grant = db.query(Grant).filter( Grant.user == user.id, Grant.role == role.id).one_or_none() if not grant: grant = Grant(user=user.id, role=role.id) db.add(grant) badge = db.query(Badge).filter( Badge.event == event, Badge.uber_id == attendee['id']).one_or_none() if badge: badge.printed_number = attendee['badge_num'] badge.printed_name = attendee['badge_printed_name'] badge.search_name = "{} {}".format( attendee['first_name'].lower(), attendee['last_name'].lower()) badge.first_name = attendee['first_name'] badge.last_name = attendee['last_name'] badge.legal_name = attendee['legal_name'] badge.legal_name_matches = bool(attendee['legal_name']) badge.email = attendee['email'] badge.phone = attendee['cellphone'] db.add(badge) if not badge: badge = Badge(uber_id=attendee['id'], event=event, printed_number=attendee['badge_num'], printed_name=attendee['badge_printed_name'], search_name="{} {}".format( attendee['first_name'].lower(), attendee['last_name'].lower()), first_name=attendee['first_name'], last_name=attendee['last_name'], legal_name=attendee['legal_name'], legal_name_matches=bool(attendee['legal_name']), email=attendee['email'], phone=attendee['cellphone'], user_id=user.id) db.add(badge) print("Adding departments...") departments = get_uber_csv(session, "Department", url) for department in departments: current = db.query(Department).filter( Department.event == event, Department.uber_id == department['id']).one_or_none() if not current: dept = Department(uber_id=department['id'], name=department['name'], description=department['description'], event=event) db.add(dept) print("Adding staffers to departments...") deptmembers = get_uber_csv(session, "DeptMembership", url) for dm in deptmembers: badge = db.query(Badge).filter( Badge.event == event, Badge.uber_id == dm['attendee_id']).one_or_none() if not badge: print("Could not find badge {} to place in department {}.".format( dm['attendee_id'], dm['department_id'])) continue department = db.query(Department).filter( Department.event == event, Department.uber_id == dm['department_id']).one_or_none() if not department: print("Could not find department {} for attendee {}.".format( dm['department_id'], dm['attendee_id'])) continue existing = db.query(BadgeToDepartment).filter( BadgeToDepartment.badge == badge.id, BadgeToDepartment.department == department.id).one_or_none() if not existing: department_member = BadgeToDepartment(badge=badge.id, department=department.id) db.add(department_member) grant = db.query(Grant).filter( Grant.user == badge.user_id, Grant.role == dh_role.id, Grant.department == department.id).one_or_none() if (dm['is_dept_head'].lower() == "true") or (dm['is_checklist_admin'].lower() == "true"): if not grant: grant = Grant(user=badge.user_id, role=dh_role.id, department=department.id) db.add(grant) elif grant: db.delete(grant) print("Committing changes...") db.commit() print("Done.")
def import_mock(): if not 'event' in request.json: return "Event is a required parament.", 406 event = db.query(Event).filter( Event.id == request.json['event']).one_or_none() if not event: return "Could not locate event {}".format(escape( request.json['event'])), 404 badges = db.query(Badge).filter(Badge.event == event.id).all() if badges: return "You cannot generate mock data if there are already badges. Please delete the badges first if you really want junk data.", 412 staff_badge_type = db.query(BadgeType).filter( BadgeType.name == "Staff").one_or_none() if not staff_badge_type: staff_badge_type = BadgeType(name="Staff", description="Helps run the show") db.add(staff_badge_type) attendee_badge_type = db.query(BadgeType).filter( BadgeType.name == "Attendee").one_or_none() if not attendee_badge_type: attendee_badge_type = BadgeType(name="Attendee", description="Come to see the show") db.add(attendee_badge_type) db.flush() if 'attendees' in request.json: print("Generating {} attendees".format(request.json['attendees'])) for i in range(request.json['attendees']): if i % 1000 == 0: print(" ...{}/{}".format(i, request.json['attendees'])) first_name = names.get_first_name() last_name = names.get_last_name() legal_name = "{} {}".format(first_name, last_name) full_name = legal_name legal_name_matches = True printed_name = legal_name if random.random() > 0.95: legal_name = names.get_full_name() legal_name_matches = False if random.random() > 0.75: printed_name = names.get_last_name() provider = random.choice( ["verizon", "gmail", "yahoo", "aol", "magfest"]) site = random.choice(["net", "com", "org", "co.uk"]) email = "{}.{}@{}.{}".format(first_name, last_name, provider, site) badge = Badge( event=event.id, badge_type=attendee_badge_type.id, printed_number=(((i + request.json['staffers']) // 1000 + 1) * 1000) if 'staffers' in request.json else i, printed_name=printed_name, search_name=printed_name.lower(), first_name=first_name, last_name=last_name, legal_name=legal_name, legal_name_matches=legal_name_matches, email=email) db.add(badge) departments = [] if 'departments' in request.json: print("Generating {} departments...".format( request.json['departments'])) dept_names = {} while len(dept_names.keys()) < request.json['departments']: name = random.choice([ "Tech", "Staff", "Arcade", "Game", "Medical", "Hotel", "Cat", "Concert", "Music", "Security", "Food", "Rescue", "Warehouse", "Logistics", "Truck", "Management" ]) name += random.choice([ " Ops", " Management", " Wranglers", " Herders", "", " Chasers", " Fixers", " Breakers", " Managers", " Destroyers", " Cleaners" ]) name = ''.join( [x.upper() if random.random() < 0.05 else x for x in name]) dept_names[name] = None for name in dept_names.keys(): description = "The {} department.".format(name) department = Department(name=name, description=description, event=event.id) db.add(department) departments.append(department) staffers = [] if 'staffers' in request.json: print("Generating {} staffers...".format(request.json['staffers'])) for i in range(request.json['staffers']): if i % 1000 == 0: print(" ...{}/{}".format(i, request.json['staffers'])) first_name = names.get_first_name() last_name = names.get_last_name() legal_name = "{} {}".format(first_name, last_name) full_name = legal_name legal_name_matches = True printed_name = legal_name if random.random() > 0.95: legal_name = names.get_full_name() legal_name_matches = False if random.random() > 0.75: printed_name = names.get_last_name() provider = random.choice( ["verizon", "gmail", "yahoo", "aol", "magfest"]) site = random.choice(["net", "com", "org", "co.uk"]) email = "{}.{}@{}.{}".format(first_name, last_name, provider, site) badge = Badge(event=event.id, badge_type=staff_badge_type.id, printed_number=i, printed_name=printed_name, search_name=printed_name.lower(), first_name=first_name, last_name=last_name, legal_name=legal_name, legal_name_matches=legal_name_matches, email=email) db.add(badge) staffers.append(badge) print("Flushing database...") db.flush() print("Adding hotel information...") room_block = HotelRoomBlock(event=event.id, name="The staff block", description="") db.add(room_block) hotel_location = HotelLocation(name="The Really Big Hotel", address="123 Waterfront", event=event.id) db.add(hotel_location) room_nights = [] for i in ["Wednesday", "Thursday"]: room_night = HotelRoomNight(name=i, event=event.id, restricted=True, restriction_type="Setup", hidden=False) db.add(room_night) room_nights.append(room_night) for i in ["Friday", "Saturday", "Sunday"]: room_night = HotelRoomNight(name=i, event=event.id, restricted=False, restriction_type="Setup", hidden=False) db.add(room_night) room_nights.append(room_night) print("Flushing database...") db.flush() print("Adding staffers to departments...") requested_room = [] for staffer in staffers: staffer_depts = list(departments) hotel_requested = False declined = False preferred_department = None for i in range(int(random.random() / 0.3)): staffer_dept = random.choice(staffer_depts) staffer_depts.remove(staffer_dept) assignment = BadgeToDepartment(badge=staffer.id, department=staffer_dept.id) db.add(assignment) preferred_department = staffer_dept.id if random.random() > 0.3: hotel_requested = True if random.random() > 0.1: declined = True else: requested_room.append(staffer) hotel_request = HotelRoomRequest( badge=staffer.id, declined=declined, prefer_department=random.random() > 0.1, preferred_department=preferred_department, notes="Please give room.", prefer_single_gender=random.random() > 0.3, preferred_gender=random.choice(['male', 'female', 'other']), noise_level=random.choice([ 'Quiet - I am quiet, and prefer quiet.', "Moderate - I don't make a lot of noise.", "Loud - I'm ok if someone snores or I snore.", ]), smoke_sensitive=random.choice([True, False]), sleep_time=random.choice( ['2am-4am', '4am-6am', '6am-8am', '8am-10am']), ) db.add(hotel_request) print("Requesting Roommates...") requested_roommates = [] for staffer in requested_room: for i in room_nights: if random.random() > 0.2: req = RoomNightRequest(badge=staffer.id, requested=True, room_night=i.id) db.add(req) for i in range(random.randrange(0, 3)): other = random.choice(requested_room) if other == staffer: continue if random.random() > 0.2: if not (staffer.id, other.id) in requested_roommates: req = HotelRoommateRequest(requester=staffer.id, requested=other.id) requested_roommates.append((staffer.id, other.id)) db.add(req) if random.random() > 0.6: if not (other.id, staffer.id) in requested_roommates: req = HotelRoommateRequest(requester=other.id, requested=staffer.id) requested_roommates.append((other.id, staffer.id)) db.add(req) else: if not (staffer.id, other.id) in requested_roommates: req = HotelAntiRoommateRequest(requester=staffer.id, requested=other.id) requested_roommates.append((staffer.id, other.id)) db.add(req) if random.random() > 0.9: if not (other.id, staffer.id) in requested_roommates: req = HotelAntiRoommateRequest(requester=other.id, requested=staffer.id) requested_roommates.append((other.id, staffer.id)) db.add(req) print("Flushing db...") db.flush() print("Committing...") db.commit() print("Done!") return "null", 200
def csv_import(): if request.method == "GET": if not check_permission("export.*.csv"): return "Permission Denied", 403 export_type = request.args['csv_type'] model = globals()[export_type] data = db.query(model).all() cols = model.__table__.columns.keys() def generate(): yield ','.join(cols) + "\n" for row in data: yield ','.join([str(getattr(row, x)) for x in cols]) + "\n" response = Response(generate(), mimetype="text/csv") response.headers.set('Content-Disposition', 'attachment; filename={}.csv'.format(export_type)) return response elif request.method == "POST": if not check_permission("import.*.csv"): return "Permission Denied", 403 import_type = request.form['csv_type'] model = globals()[import_type] raw_import = request.form['raw_import'].lower().strip() == "true" full_import = request.form['full_import'].lower().strip() == "true" file = request.files['files'] data = file.read().decode('UTF-8').replace("\r\n", "\n") if full_import: db.query(model).delete() rows = data.split("\n") cols = rows[0].split(",") rows = rows[1:] def convert(key, val): col = model.__table__.columns[key] if col.nullable: if val == 'None': return None coltype = type(col.type) if coltype is sqlalchemy.sql.sqltypes.Integer: if val == '': return None return int(val) if coltype is sqlalchemy.sql.sqltypes.Boolean: if val.lower() == "true": return True return False return val count = 0 for row in rows: if not row.strip(): continue row = row.split(",") new = model( **{key: convert(key, val) for key, val in zip(cols, row)}) db.add(new) count += 1 db.commit() return str(count), 200
def department_sync(): if not check_permission("department.*.sync"): return "", 403 event = config.uber_event req = {"method": "hotel.eligible_attendees"} eligible = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'] req = {"method": "dept.list"} uber_depts = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'] uber_depts_names = {} for dept_id in uber_depts: uber_depts_names[uber_depts[dept_id]] = dept_id departments = db.query(Department).filter(Department.event == event).all() dept_names = {} for dept in departments: dept_names[dept.name] = dept badges = db.query(Badge).filter(Badge.event == event).options(joinedload('departments')).all() badgelookup = {badge.uber_id: badge for badge in badges} for attendee in eligible: req = { "method": "attendee.search", "params": [ attendee, "full" ] } uber_model = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'][0] if attendee in badgelookup: badge = badgelookup[attendee] if uber_model['full_name'] != badge.public_name: print(f"Updating public name from {badge.public_name} to {uber_model['full_name']}") badge.first_name = uber_model['first_name'] badge.last_name = uber_model['last_name'] badge.public_name = uber_model['full_name'] db.add(badge) if uber_model['badge_status_label'] == "Deferred": if attendee in badgelookup: print(f"Deleting deferred attendee {attendee} ({badgelookup[attendee].public_name})") rnrs = badgelookup[attendee].room_night_requests if any([x.requested for x in rnrs]): print("WARNING: ATTENDEE REQUESTED ROOM NIGHTS") #db.delete(badgelookup[attendee]) else: if not attendee in badgelookup: print(f"Missing attendee: {attendee}") new_badge = create_attendee(uber_model, event) badgelookup[attendee] = new_badge badge = badgelookup[attendee] for dept_name in uber_model['assigned_depts_labels']: if not dept_name in dept_names and dept_name in uber_depts_names: new_dept = Department(uber_id=uber_depts_names[dept_name], event=event, name=dept_name) dept_names[dept_name] = new_dept print(f"Creating department {dept_name}") db.add(new_dept) if not dept_names[dept_name] in badge.departments: badge.departments.append(dept_names[dept_name]) print(f"Adding {badge.public_name} to {dept_name}") to_remove = [] for dept in badge.departments: if not dept.name in uber_model['assigned_depts_labels']: to_remove.append(dept) for dept in to_remove: print(f"Removing {badge.public_name} from {dept.name}") badge.departments.remove(dept) db.add(badge) db.commit() return "", 200
def staffer_auth(): if not User.query.first(): return "You must set up this server before using this method to log in.", 403 event = config.uber_event req = { "method": "attendee.search", "params": [ request.json['token'], "full" ] } results = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'] if len(results) == 0: return "no result", 403 result = results[0] if not 'id' in result: return "no id", 403 uber_id = result['id'] if uber_id != request.json['token']: return "wrong token", 403 if result['badge_status_label'] == "Deferred": return "Badge is deferred", 403 badge = db.query(Badge).filter(Badge.uber_id == uber_id).one_or_none() hotel_request = None if badge: hotel_request = db.query(HotelRoomRequest).filter(HotelRoomRequest.badge == badge.id).one_or_none() if not hotel_request or not badge: req = {"method": "hotel.eligible_attendees"} eligible = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'] if len(eligible) == 0: return "Failed to load eligible attendees", 403 if not uber_id in eligible: return "You are not eligible", 403 if not badge: staff_badge_type = db.query(BadgeType).filter(BadgeType.event == event, BadgeType.name == "Staff").one_or_none() if not staff_badge_type: staff_badge_type = BadgeType(name="Staff", description="Experienced Volunteers", event=event) db.flush() badge = Badge( event=event, badge_type=staff_badge_type.id, printed_number=result['badge_num'], printed_name=result['badge_printed_name'], public_name=result['full_name'], search_name=result['full_name'].lower(), first_name=result['first_name'], last_name=result['last_name'], legal_name_matches=(not result['legal_name']), emergency_contact_name=result['ec_name'], emergency_contact_phone=result['ec_phone'], phone=result['cellphone'], email=result['email'], uber_id=result['id'] ) req = { "method": "dept.list", "params": [] } uber_depts = requests.post(config.uber_api_url, headers=headers, json=req).json()['result'] uber_depts_names = {} for dept_id in uber_depts: uber_depts_names[uber_depts[dept_id]] = dept_id departments = db.query(Department).filter(Department.event == event).all() dept_names = {} for dept in departments: dept_names[dept.name] = dept for dept_name in result['assigned_depts_labels']: if not dept_name in dept_names and dept_name in uber_depts_names: new_dept = Department(uber_id=uber_depts_names[dept_name], event=event, name=dept_name) db.add(new_dept) badge.departments.append(new_dept) elif dept_name in dept_names: badge.departments.append(dept_names[dept_name]) db.add(badge) db.flush() if not hotel_request: hotel_request = HotelRoomRequest(event=event, badge=badge.id) db.add(hotel_request) db.flush() permissions = { "event": { str(event): [ "rooming.*.request", "badge.*.searchname", f"hotel_room_request.{hotel_request.id}.write", "hotel_room_block.*.read", "hotel_location.*.read", "hotel_room_night.*.read", ], "*": [ "event.*.read", f"badge.{badge.id}.read", "department.*.read" ] }, "department": {} } for department in badge.departments: req = { "method": "dept.members", "params": { "department_id": department.uber_id } } result = requests.post(config.uber_api_url, headers=headers, json=req).json() if 'error' in result: print(f"Could not locate {department.name} ({department.uber_id})") continue uber_dept_members = result['result'] for attendee in uber_dept_members['checklist_admins']: if attendee['id'] == badge.uber_id: if not str(event) in permissions["department"]: permissions["department"][str(event)] = {} permissions["department"][str(event)][str(department.id)] = [ f"department.*.checklist_admin", "hotel_request.*.approve" ] session = Session(badge=badge.id, secret=str(uuid.uuid4()), permissions=json.dumps(permissions), last_active=datetime.datetime.now()) db.add(session) db.commit() response = jsonify(session.secret) response.set_cookie('session', session.secret) return response
def crud_group(model, event=None, department=None): start = time.time() if request.method == "GET": count = request.args.get("count", False, type=lambda x: x.lower() == 'true') sort = request.args.get("sort", "") order = request.args.get("order", "asc") limit = request.args.get("limit", 0, type=int) offset = request.args.get("offset", 0, type=int) page = request.args.get("page", 0, type=int) search = request.args.get("search", "", type=str) search_field = request.args.get("search_field", "", type=str) search_mode = request.args.get("search_mode", "contains", type=str) search_case_sensitive = request.args.get( "search_case_sensitive", False, type=lambda x: x.lower() == 'true') full = request.args.get("full", False, type=lambda x: x.lower() == 'true') deep = request.args.get("deep", False, type=lambda x: x.lower() == 'true') if page: offset = page * 10 if limit: offset = page * limit filters = [] perms = model_permissions(model.__tablename__.lower()) if not READ_PERMS.intersection(perms['*']): ids = [ int(x) for x in perms.keys() if READ_PERMS.intersection(perms[x]) ] if not ids: raise PermissionDenied( f"User is not able to read any values in {model.__tablename__}" ) filters.append(model.id.in_(ids)) if event: filters.append(model.event == event) if department: filters.append(model.department == department) if search_field: if hasattr(model, search_field): columns, relationships = model.get_fields() relationships = {x.key: x for x in relationships} if search_field in relationships: search_model = getattr(model, search_field) model.get_modelclasses() rel_model = model.modelclasses[ relationships[search_field].target.name] search = [int(x) for x in search.split(",")] filters.append(search_model.any(rel_model.id.in_(search))) else: if search_case_sensitive: search_model = getattr(model, search_field) else: search_model = func.lower(getattr(model, search_field)) search = search.lower() if search_mode == "contains": filters.append( search_model.contains(search, autoescape=True)) elif search_mode == "startswith": filters.append( search_model.startswith(search, autoescape=True)) elif search_mode == "endswith": filters.append( search_model.endswith(search, autoescape=True)) elif search_mode == "equals": filters.append(search_model == search) elif search_mode == "notEquals": filters.append(search_model != search) for key, val in request.args.items(): if hasattr(model, key): filters.append(getattr(model, key) == val) rows = db.query(model).filter(*filters) if full: columns, relationships = model.get_fields() for relation in relationships: rows = rows.options(joinedload(relation.key)) if count: return json.dumps(rows.count()), 200 if hasattr(model, sort): if order == "asc": rows = rows.order_by(getattr(model, sort)) else: rows = rows.order_by(getattr(model, sort).desc()) if limit: rows = rows.offset(offset).limit(limit) elif offset: rows = rows.offset(offset).limit(10) rows = rows.all() now = time.time() print(f"{request.path} Load time {now - start}s") data = model.serialize(rows, serialize_relationships=full, deep=deep) print(f"{request.path} Serialize time {time.time() - now}s") return jsonify(data) elif request.method == "POST": if event: g.data['event'] = event if department: g.data['department'] = department instance = model.deserialize(g.data) db.add(instance) if hasattr(instance, 'onchange_cb'): db.flush() for cb in instance.onchange_cb: cb(db, instance) db.commit() return jsonify(model.serialize(instance)) raise MethodNotAllowed()
def load_session(endpoint, values): g.user = None g.badge = None g.session = None g.event = None g.department = None g.perms = { "event": {}, "department": {} } if request.method != "GET": if not request.json is None: g.data = dict(request.json) elif not request.form is None: g.data = dict(request.form) elif not request.args is None: g.data = dict(request.args) if not values: values = {} if 'event' in values: g.event = int(values['event']) if 'department' in values: g.department = int(values['department']) if 'session' in request.cookies: session = db.query(Session).filter(Session.secret == request.cookies.get('session')).one_or_none() if session: if datetime.datetime.now() < session.last_active + datetime.timedelta(seconds=config.session_duration): session.last_active = datetime.datetime.now() g.session = session g.user = db.query(User).filter(User.id == session.user).one_or_none() g.badge = db.query(Badge).filter(Badge.id == session.badge).one_or_none() if "event" in values and not g.badge and g.user: g.badge = db.query(Badge).filter(Badge.user == g.user.id, Badge.event == values['event']).one_or_none() perms = json.loads(session.permissions) g.perms = { "event": {int(k) if k != '*' else k: v for k, v in perms['event'].items()}, "department": {int(k) if k != '*' else k: {int(m) if m != '*' else m: n for m, n in v.items()} for k, v in perms['department'].items()} } db.add(session) else: db.delete(session) db.commit() elif request.headers.get('X-Auth-Token', ""): key = request.headers.get('X-Auth-Token') apikey = db.query(APIKey).filter(APIKey.key == key).one_or_none() if not apikey: raise PermissionDenied(message="Invalid API Key") if not apikey.enabled: raise PermissionDenied(message="API Key is disabled") user = db.query(User).filter(User.id == apikey.user).one_or_none() if not user: raise PermissionDenied(message="Invalid API Key") if not user.active: raise PermissionDenied(message="API Key is disabled") g.user=user perms = get_permissions() g.perms = { "event": {int(k) if k != '*' else k: v for k, v in perms['event'].items()}, "department": {int(k) if k != '*' else k: {int(m) if m != '*' else m: n for m, n in v.items()} for k, v in perms['department'].items()} } if "event" in values and not g.badge and g.user: g.badge = db.query(Badge).filter(Badge.user == g.user.id, Badge.event == values['event']).one_or_none()
def __call__(self, environ, start_response): if environ['REQUEST_URI'].startswith("/api/job/"): job_id = environ['REQUEST_URI'].split("/api/job/")[1] if r: progress = json.loads(r.get(f"{job_id}/progress")) if not progress: start_response("404 Not Found", []) return [bytes()] if not progress['complete']: start_response("202 Accepted", [("Content-Type", "application/json")]) return [json.dumps(progress).encode()] data = r.get(f"{job_id}/data") start_response("200 Ok", [("Content-Type", "application/json")]) return [data] else: job = db.query(BackgroundJob).filter( BackgroundJob.uuid == job_id).one_or_none() if not job: start_response("404 Not Found", []) return [bytes()] else: progress = json.loads(job.progress) if progress['complete']: start_response("200 Ok", [("Content-Type", "application/json")]) return [job.result] start_response("202 Accepted", [("Content-Type", "application/json")]) return [job.progress.encode()] job_id = str(uuid.uuid4()) environ['TUBER_JOB_ID'] = job_id request_context = { "state": "pending", "status": "202 Accepted", "response_headers": [("Location", f"/api/job/{job_id}")] } with self.lock: if len(self.context) > config.circuitbreaker_threads: start_response("504 Gateway Timeout", []) return [bytes()] self.context[job_id] = request_context thread = self.pool.apply_async( self.application, (environ, lambda *args, **kwargs: self. _start_response(job_id, *args, **kwargs)), callback=lambda *args, **kwargs: self._store_response( job_id, *args, **kwargs)) thread.wait(timeout=config.circuitbreaker_timeout) with self.lock: start_response(request_context['status'], request_context['response_headers']) if request_context['state'] == "immediate": del self.context[job_id] return thread.get() request_context['state'] = "deferred" progress = json.dumps({ "complete": False, "amount": 0, "messages": "", "status": "" }) if r: r.set(f"{job_id}/progress", progress) else: job = BackgroundJob(uuid=job_id, progress=progress) db.add(job) db.commit() return [bytes()]
def hotel_request_single_api(event, request_id): if not check_permission("rooming.*.manage", event=event) and not check_permission(f"hotel_room_request.{request_id}.write", event=event): return "", 403 if request.method == "GET": hotel_request = db.query(HotelRoomRequest).filter(HotelRoomRequest.id == request_id).one_or_none() if not hotel_request: return "Could not locate hotel room request", 404 room_nights = [] requested = db.query(RoomNightRequest, HotelRoomNight).join(HotelRoomNight, RoomNightRequest.room_night == HotelRoomNight.id).filter(RoomNightRequest.badge == hotel_request.badge).all() for req, night in requested: if not night.hidden: room_nights.append({ "id": night.id, "requested": req.requested, "date": night.date, "name": night.name, "restricted": night.restricted, "restriction_type": night.restriction_type, }) all_room_nights = db.query(HotelRoomNight).filter(HotelRoomNight.event == event).all() for room_night in all_room_nights: for existing in room_nights: if existing['id'] == room_night.id: break else: room_nights.append({ "id": room_night.id, "requested": False, "date": room_night.date, "name": room_night.name, "restricted": room_night.restricted, "restriction_type": room_night.restriction_type }) room_nights.sort(key=lambda x: x['date']) return jsonify({ "event": hotel_request.event, "badge": hotel_request.badge, "first_name": hotel_request.first_name or "", "last_name": hotel_request.last_name or "", "declined": hotel_request.declined, "prefer_department": hotel_request.prefer_department, "preferred_department": hotel_request.preferred_department, "notes": hotel_request.notes or "", "prefer_single_gender": hotel_request.prefer_single_gender, "preferred_gender": hotel_request.preferred_gender or "", "noise_level": hotel_request.noise_level or "", "smoke_sensitive": hotel_request.smoke_sensitive, "sleep_time": hotel_request.sleep_time or "", "room_night_justification": hotel_request.room_night_justification or "", "requested_roommates": [x.id for x in hotel_request.roommate_requests], "antirequested_roommates": [x.id for x in hotel_request.roommate_anti_requests], "room_nights": room_nights }) elif request.method == "PATCH": hotel_request = db.query(HotelRoomRequest).filter(HotelRoomRequest.id == request_id).one_or_none() if not hotel_request: return "Could not locate hotel room request", 404 hotel_request.first_name = g.data['first_name'] hotel_request.last_name = g.data['last_name'] hotel_request.declined = g.data['declined'] hotel_request.prefer_department = g.data['prefer_department'] hotel_request.preferred_department = g.data['preferred_department'] hotel_request.notes = g.data['notes'] hotel_request.prefer_single_gender = g.data['prefer_single_gender'] hotel_request.preferred_gender = g.data['preferred_gender'] hotel_request.noise_level = g.data['noise_level'] hotel_request.smoke_sensitive = g.data['smoke_sensitive'] hotel_request.sleep_time = g.data['sleep_time'] hotel_request.room_night_justification = g.data['room_night_justification'] hotel_request.roommate_requests = db.query(Badge).filter(Badge.id.in_(g.data['requested_roommates'])).all() hotel_request.roommate_anti_requests = db.query(Badge).filter(Badge.id.in_(g.data['antirequested_roommates'])).all() db.add(hotel_request) requested = db.query(RoomNightRequest, HotelRoomNight).join(HotelRoomNight, RoomNightRequest.room_night == HotelRoomNight.id).filter(RoomNightRequest.badge == hotel_request.badge).all() night_status = {} for req, night in requested: night_status[night.id] = req for room_night_request in g.data['room_nights']: if room_night_request['id'] in night_status: night_status[room_night_request['id']].requested = room_night_request['requested'] db.add(night_status[room_night_request['id']]) else: requested_night = RoomNightRequest(event=event, badge=hotel_request.badge, requested=room_night_request['requested'], room_night=room_night_request['id']) db.add(requested_night) update_room_request_props(db, [hotel_request,]) db.commit() return "null", 200
def update_requests(event): if not check_permission("rooming.*.admin"): return "", 403 updates = { "requests": {}, "badges": {} } badges = db.query(Badge).filter(Badge.event == event).all() for badge in badges: if not badge.public_name and badge.printed_name: badge.public_name = badge.printed_name updates['badges'][badge.id] = badge.public_name db.add(badge) badgeLookup = {x.id: x for x in badges} room_nights = db.query(HotelRoomNight).filter(HotelRoomNight.event == event).all() room_night_lookup = {x.id: x for x in room_nights} block = db.query(HotelRoomBlock).filter(HotelRoomBlock.event == event).first() reqs = db.query(HotelRoomRequest).filter(HotelRoomRequest.event == event).options(joinedload('room_night_requests')).all() for req in reqs: req.requested = False req.approved = False if not req.declined: for rnr in req.room_night_requests: if rnr.requested: req.requested = True if not room_night_lookup[rnr.room_night].restricted: req.approved = True else: for rna in req.room_night_approvals: if rna.room_night == rnr.room_night and rna.approved: req.approved = True req.assigned = bool(req.room_night_assignments) updates['requests'][req.id] = { "requested": req.requested, "approved": req.approved, "assigned": req.assigned } badge_name = " " badge = badgeLookup[req.badge] if badge.public_name: badge_name = badge.public_name elif badge.search_name: badge_name = " ".join([x.capitalize() for x in badge.search_name.split(" ")]) elif badge.legal_name: badge_name = badge.legal_name elif badge.printed_name: badge_name = badge.printed_name badge_first_name = badge.first_name if not badge_first_name: badge_first_name = badge_name.split(" ")[0] badge_last_name = badge.last_name if not badge_last_name: badge_last_name = badge_name.split(" ", 1)[1] if not req.first_name: if badge_first_name: req.first_name = badge_first_name updates['requests'][req.id]['first_name'] = req.first_name if not req.last_name: if badge_last_name: req.last_name = badge_last_name updates['requests'][req.id]['last_name'] = req.last_name if not req.hotel_block: req.hotel_block = block.id db.add(req) db.commit() return jsonify(updates), 200