def put(self, id): json_data = request.get_json() if not json_data: return {'message': 'No input data received for updating CSR'}, 400 auth_csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) edit_csr = CSR.query.filter_by(csr_id=id).first_or_404() if auth_csr.csr_id != edit_csr.csr_id: return { 'message': 'You do not have permission to edit this CSR' }, 403 # Get Invited and Being Served states, to see if CSR has any open tickets. period_state_invited = PeriodState.get_state_by_name("Invited") period_state_being_served = PeriodState.get_state_by_name( "Being Served") # See if CSR has any open tickets. citizen = Citizen.query \ .join(Citizen.service_reqs) \ .join(ServiceReq.periods) \ .filter(Period.time_end.is_(None)) \ .filter(Period.csr_id==id) \ .filter(or_(Period.ps_id==period_state_invited.ps_id, Period.ps_id==period_state_being_served.ps_id)) \ .all() if len(citizen) != 0: return { 'message': 'CSR has an open ticket and cannot be edited.' }, 403 try: edit_csr = self.csr_schema.load(json_data, instance=edit_csr, partial=True) except ValidationError as err: return {'message': err.messages}, 422 db.session.add(edit_csr) db.session.commit() # Purge CSR cache, otherwise lazy loaded relationships # like Office will be out of date. CSR.update_user_cache(id) result = self.csr_schema.dump(edit_csr) socketio.emit('csr_update', \ { "csr_id": edit_csr.csr_id, \ "receptionist_ind" : edit_csr.receptionist_ind }, \ room=auth_csr.office.office_name) # Purge cache of old CSR record so the new one can be fetched by the next request for it. CSR.delete_user_cache(g.jwt_oidc_token_info['username']) return { 'csr': result, 'errors': self.csr_schema.validate(edit_csr) }, 200
def put(self, id): json_data = request.get_json() if not json_data: return {'message': 'No input data received for updating CSR'}, 400 auth_csr = CSR.find_by_username(g.oidc_token_info['username']) edit_csr = CSR.query.filter_by(csr_id=id).first_or_404() if auth_csr.csr_id != edit_csr.csr_id: return {'message': 'You do not have permission to edit this CSR'}, 403 try: edit_csr = self.csr_schema.load(json_data, instance=edit_csr, partial=True).data except ValidationError as err: return {'message': err.messages}, 422 db.session.add(edit_csr) db.session.commit() result = self.csr_schema.dump(edit_csr) socketio.emit('csr_update', \ { "csr_id": edit_csr.csr_id, \ "receptionist_ind" : edit_csr.receptionist_ind }, \ room=auth_csr.office_id) # Purge cache of old CSR record so the new one can be fetched by the next request for it. CSR.delete_user_cache(g.oidc_token_info['username']) return {'service_request': result.data, 'errors': result.errors}, 200
def on_join(message): cookie = request.cookies.get("oidc-jwt", None) if cookie is None: emit('joinRoomFail', {"sucess": False}) return if not oidc.validate_token(cookie): print("Cookie failed validation") emit('joinRoomFail', {"sucess": False}) return claims = jwt.get_unverified_claims(cookie) if claims["preferred_username"]: print( "==> In Python, @socketio.on('joinRoom'): claims['preferred_username'] is: " + str(claims["preferred_username"])) csr = CSR.find_by_username(claims["preferred_username"]) if csr: join_room(csr.office_id) print("==> In websocket.py, CSR joinroom, CSR: " + csr.username + "; request sid: " + str(request.sid)) emit('joinRoomSuccess', {"sucess": True}) emit('get_Csr_State_IDs', {"success": True}) emit('update_customer_list', {"success": True}) else: print("Fail") emit('joinRoomFail', {"success": False}) else: print("No preferred_username on request") emit('joinRoomFail', {"success": False})
def put(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return { "message": "No input data received for updating an series of appointments" } appointments = Appointment.query.filter_by(recurring_uuid=id)\ .filter_by(office_id=csr.office_id)\ .all() for appointment in appointments: appointment, warning = self.appointment_schema.load( json_data, instance=appointment, partial=True) if warning: logging.warning('WARNING: %s', warning) return {"message": warning}, 422 db.session.add(appointment) db.session.commit() result = self.appointment_schema.dump(appointments) if not application.config['DISABLE_AUTO_REFRESH']: socketio.emit('appointment_update', result.data) return {"appointments": result.data, "errors": result.errors}, 200
def get(self): try: user = g.jwt_oidc_token_info['username'] has_role([Role.internal_user.value], g.jwt_oidc_token_info['realm_access']['roles'], user, "CitizenList GET /citizens/") csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) if not csr: raise Exception('no user found with username: `{}`'.format( g.jwt_oidc_token_info['username'])) citizens = Citizen.query \ .options(joinedload(Citizen.service_reqs, innerjoin=True).joinedload(ServiceReq.periods).options(raiseload(Period.sr),joinedload(Period.csr).raiseload('*')),raiseload(Citizen.office),raiseload(Citizen.counter),raiseload(Citizen.user)) \ .filter_by(office_id=csr.office_id, cs_id=active_id) \ .order_by(Citizen.priority) result = self.citizens_schema.dump(citizens) return { 'citizens': result, 'errors': self.citizens_schema.validate(citizens) }, 200 except exc.SQLAlchemyError as e: print(e) return {'message': 'API is down'}, 500
def post(self, id): csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) citizen = Citizen.query\ .options(joinedload(Citizen.service_reqs).joinedload(ServiceReq.periods).options(raiseload(Period.sr),joinedload(Period.csr).raiseload('*')),joinedload(Citizen.office),raiseload(Citizen.user)) \ .filter_by(citizen_id=id, office_id=csr.office_id) citizen = citizen.first() my_print("==> POST /citizens/" + str(citizen.citizen_id) + '/place_on_hold/, Ticket: ' + citizen.ticket_number) active_service_request = citizen.get_active_service_request() if active_service_request is None: return {"message": "Citizen has no active service requests"} active_service_request.place_on_hold(csr) pending_service_state = SRState.get_state_by_name("Active") active_service_request.sr_state_id = pending_service_state.sr_state_id db.session.add(citizen) db.session.commit() socketio.emit('update_customer_list', {}, room=csr.office.office_name) result = self.citizen_schema.dump(citizen) socketio.emit('update_active_citizen', result, room=csr.office.office_name) return {'citizen': result, 'errors': self.citizen_schema.validate(citizen)}, 200
def on_model_change(self, form, model, is_created): csr = CSR.find_by_username(current_user.username) socketio.emit('clear_csr_cache', { "id": csr.csr_id}) socketio.emit('csr_update', {"csr_id": csr.csr_id, "receptionist_ind": csr.receptionist_ind}, room=csr.office_id) socketio.emit('digital_signage_msg_update')
def put(self, id): json_data = request.get_json() if not json_data: return { 'message': 'No input data received for updating citizen' }, 400 csr = CSR.find_by_username(g.oidc_token_info['username']) citizen = Citizen.query.filter_by(citizen_id=id, office_id=csr.office_id).first() try: citizen = self.citizen_schema.load(json_data, instance=citizen, partial=True).data except ValidationError as err: return {'message': err.messages}, 422 db.session.add(citizen) db.session.commit() result = self.citizen_schema.dump(citizen) socketio.emit('update_active_citizen', result.data, room=csr.office_id) return {'citizen': result.data, 'errors': result.errors}, 200
def put(self, id): json_data = request.get_json() if not json_data: return {'message': 'No input data received for updating citizen'}, 400 csr = CSR.find_by_username(g.oidc_token_info['username']) service_request = ServiceReq.query.filter_by(sr_id=id) \ .join(ServiceReq.citizen, aliased=True) \ .filter_by(office_id=csr.office_id).first_or_404() try: service_request = self.service_request_schema.load(json_data, instance=service_request, partial=True).data except ValidationError as err: return {'message': err.messages}, 422 db.session.add(service_request) db.session.commit() SnowPlow.choose_service(service_request, csr, "chooseservice") result = self.service_request_schema.dump(service_request) citizen_result = self.citizen_schema.dump(service_request.citizen) socketio.emit('update_active_citizen', citizen_result.data, room=csr.office_id) return {'service_request': result.data, 'errors': result.errors}, 200
def put(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for updating an exam"} exam = Exam.query.filter_by(exam_id=id).first_or_404() if not (exam.office_id == csr.office_id or csr.role.role_code == "LIAISON"): return {"The Exam Office ID and CSR Office ID do not match!"}, 403 exam, warning = self.exam_schema.load(json_data, instance=exam, partial=True) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 db.session.add(exam) db.session.commit() result = self.exam_schema.dump(exam) return {"exam": result.data, "errors": result.data}, 201
def post(self): json_data = request.get_json() csr = CSR.find_by_username(g.oidc_token_info['username']) try: citizen = self.citizen_schema.load(json_data).data citizen.office_id = csr.office_id citizen.start_time = datetime.now() except ValidationError as err: print(err) return {"message": err.messages}, 422 citizen_state = CitizenState.query.filter_by( cs_state_name="Active").first() citizen.cs_id = citizen_state.cs_id citizen.service_count = 1 db.session.add(citizen) db.session.commit() SnowPlow.add_citizen(citizen, csr) result = self.citizen_schema.dump(citizen) return {'citizen': result.data, 'errors': result.errors}, 201
def get(self): claims = g.jwt_oidc_token_info if claims["preferred_username"]: csr = CSR.find_by_username(claims["preferred_username"]) if csr: if csr.deleted is None: csr.is_active = True else: csr.is_active = False csr.is_authenticated = False csr.is_anonymous = False login_user(csr) if application.config['USE_HTTPS']: return redirect( url_for( "admin.index", _scheme=application.config['PREFERRED_URL_SCHEME'], _external=application.config['USE_HTTPS'])) else: return redirect(url_for("admin.index")) else: return abort(401, self.auth_string) else: return abort(401, self.auth_string)
def post(self, exam_id): csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) try: exam = Exam.query.filter_by(exam_id=exam_id).first() if not (exam.office_id == csr.office_id or csr.ita2_designate == 1): return {"The Exam Office ID and CSR Office ID do not match!" }, 403 bcmp_response = self.bcmp_service.send_exam_to_bcmp(exam) if bcmp_response: return {"bcmp": bcmp_response, "errors": {}}, 202 else: return { "message": "create_group_exam_bcmp failed", "error": bcmp_response }, 403 except exc.SQLAlchemyError as error: logging.error(error, exc_info=True) return {'message': 'API is down'}, 500
def get(self): csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) appt_limit_int = int(appt_limit) # today's date and time dt = datetime.now() upper_dt = dt - timedelta(days=appt_limit_int) filter_date = pytz.utc.localize(upper_dt) # print("filter_date",filter_date) try: appointments = Appointment.query.filter_by(office_id=csr.office_id)\ .filter(Appointment.start_time >= filter_date)\ .all() result = self.appointment_schema.dump(appointments) return { "appointments": result, "errors": { "errors": self.appointment_schema.validate(appointments) } }, 200 except exc.SQLAlchemyError as error: logging.error(error, exc_info=True) return {"message": "API is down"}, 500
def post(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) citizen = Citizen.query.filter_by(citizen_id=id).first() active_service_request = citizen.get_active_service_request() my_print("==> POST /citizens/" + str(citizen.citizen_id) + '/remove_from_queue, Ticket: ' + citizen.ticket_number) if active_service_request is None: return {"message": "Citizen has no active service requests"} appointment = Appointment.query.filter_by(citizen_id=id) \ .filter_by(office_id=csr.office_id) \ .filter(Appointment.checked_in_time.isnot(None)) \ .first_or_404() # This "un-check-in"s the appointment, returning it to calendar and removing from the queue. appointment.checked_in_time = None db.session.commit() # ARC - Is below necessary? Think not. Causes issue when re-checking in a removed one. # It DOES remove from queue, but stops it from being re-added? # active_service_request.remove_from_queue() # appointment, warning = self.appointment_schema.load(json_data, instance=appointment, partial=True) # if warning: # logging.warning("WARNING: %s", warning) # return {"message": warning}, 422 result = self.appointment_schema.dump(appointment) return {"appointment": result.data, "errors": result.errors}, 200
def put(self, id): csr = CSR.find_by_username(g.jwt_oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for updating an exam"} # TODO Deleted date filter original exam = Exam.query.filter_by(exam_id=id).first_or_404() if not (exam.office_id == csr.office_id or csr.ita2_designate == 1): return {"The Exam Office ID and CSR Office ID do not match!"}, 403 exam = self.exam_schema.load(json_data, instance=exam, partial=True) warning = self.exam_schema.validate(json_data) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 db.session.add(exam) db.session.commit() result = self.exam_schema.dump(exam) return {"exam": result, "errors": self.exam_schema.validate(exam)}, 201
def put(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for updating a booking"} booking = Booking.query.filter_by(booking_id=id).first_or_404() booking, warning = self.booking_schema.load(json_data, instance=booking, partial=True) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 if booking.office_id == csr.office_id or csr.liaison_designate == 1: db.session.add(booking) db.session.commit() result = self.booking_schema.dump(booking) return {"booking": result.data, "errors": result.errors}, 200 else: return { "The Booking Office ID and the CSR Office ID do not match!" }, 403
def put(self, id): json_data = request.get_json() counter = Counter.query.filter(Counter.counter_name == "Counter")[0] if 'counter_id' not in json_data: json_data['counter_id'] = counter.counter_id if not json_data: return { 'message': 'No input data received for updating citizen' }, 400 csr = CSR.find_by_username(g.oidc_token_info['username']) citizen = Citizen.query.filter_by(citizen_id=id, office_id=csr.office_id).first() my_print("==> PUT /citizens/" + str(citizen.citizen_id) + '/, Ticket: ' + str(citizen.ticket_number)) try: citizen = self.citizen_schema.load(json_data, instance=citizen, partial=True).data except ValidationError as err: return {'message': err.messages}, 422 db.session.add(citizen) db.session.commit() result = self.citizen_schema.dump(citizen) socketio.emit('update_active_citizen', result.data, room=csr.office_id) return {'citizen': result.data, 'errors': result.errors}, 200
def on_join(message): cookie = request.cookies.get("oidc-jwt", None) if cookie is None: emit('joinRoomFail', {"sucess": False}) return if not oidc.validate_token(cookie): print("Cookie failed validation") emit('joinRoomFail', {"sucess": False}) return claims = jwt.get_unverified_claims(cookie) if claims["preferred_username"]: csr = CSR.find_by_username(claims["preferred_username"]) if csr: join_room(csr.office_id) emit('joinRoomSuccess', {"sucess": True}) emit('get_Csr_State_IDs', {"success": True}) emit('update_customer_list', {"success": True}) else: print("Fail") emit('joinRoomFail', {"success": False}) else: print("No preferred_username on request") emit('joinRoomFail', {"success": False})
def post(self): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return { "message": "No input data received for creating an appointment" }, 400 appointment, warning = self.appointment_schema.load(json_data) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 if appointment.office_id == csr.office_id: db.session.add(appointment) db.session.commit() result = self.appointment_schema.dump(appointment) return {"appointment": result.data, "errors": result.errors}, 201 else: return { "The Appointment Office ID and CSR Office ID do not match!" }, 403
def put(self, id): print("==> In Python PUT /appointments/<id>/ endpoint") csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for updating an appointment"} appointment = Appointment.query.filter_by(appointment_id=id)\ .filter_by(office_id=csr.office_id)\ .first_or_404() appointment, warning = self.appointment_schema.load(json_data, instance=appointment, partial=True) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 db.session.add(appointment) db.session.commit() result = self.appointment_schema.dump(appointment) return {"appointment": result.data, "errors": result.errors}, 200
def put(self, id): json_data = request.get_json() if 'counter_id' not in json_data: json_data['counter_id'] = counter_id if not json_data: return {'message': 'No input data received for updating citizen'}, 400 csr = CSR.find_by_username(g.oidc_token_info['username']) citizen = Citizen.query.filter_by(citizen_id=id).first() my_print("==> PUT /citizens/" + str(citizen.citizen_id) + '/, Ticket: ' + str(citizen.ticket_number)) try: citizen = self.citizen_schema.load(json_data, instance=citizen, partial=True).data except ValidationError as err: return {'message': err.messages}, 422 db.session.add(citizen) db.session.commit() # If this put request is the result of an appointment checkin, make a Snowplow call. if ('snowplow_addcitizen' in json_data) and (json_data['snowplow_addcitizen'] == True): SnowPlow.add_citizen(citizen, csr) result = self.citizen_schema.dump(citizen) socketio.emit('update_active_citizen', result.data, room=csr.office_id) return {'citizen': result.data, 'errors': result.errors}, 200
def get(self): cookie = request.cookies.get("oidc-jwt", None) if cookie is None: return abort(401, self.auth_string) if not oidc.validate_token(cookie): return abort(401, self.auth_string) claims = jwt.get_unverified_claims(cookie) if claims["preferred_username"]: csr = CSR.find_by_username(claims["preferred_username"]) if csr: if csr.deleted is None: csr.is_active = True else: csr.is_active = False csr.is_authenticated = False csr.is_anonymous = False login_user(csr) if application.config['USE_HTTPS']: return redirect( url_for( "admin.index", _scheme=application.config['PREFERRED_URL_SCHEME'], _external=application.config['USE_HTTPS'])) else: return redirect(url_for("admin.index")) else: return abort(401, self.auth_string) else: return abort(401, self.auth_string)
def put(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return { "message": "No input data received for updating recurring bookings" } bookings = Booking.query.filter_by(recurring_uuid=id)\ .filter_by(office_id=csr.office_id)\ .all() for booking in bookings: booking, warning = self.booking_schema.load(json_data, instance=booking, partial=True) if warning: logging.warning('WARNING: %s', warning) return {"message": warning}, 422 db.session.add(booking) db.session.commit() result = self.booking_schema.dump(bookings) return {"bookings": result.data, "errors": result.errors}, 200
def post(self): json_data = request.get_json() csr = CSR.find_by_username(g.oidc_token_info['username']) if not csr: raise Exception('no user found with username: `{}`'.format( g.oidc_token_info['username'])) try: citizen = self.citizen_schema.load(json_data).data citizen.office_id = csr.office_id citizen.start_time = datetime.now() except ValidationError as err: print(err) return {"message": err.messages}, 422 citizen.cs_id = active_id citizen.service_count = 1 db.session.add(citizen) db.session.commit() SnowPlow.add_citizen(citizen, csr) result = self.citizen_schema.dump(citizen) return {'citizen': result.data, 'errors': result.errors}, 201
def post(self, id): lock = FileLock("lock/invite_citizen.lock") with lock: csr = CSR.find_by_username(g.oidc_token_info['username']) citizen = db.session.query(Citizen).with_lockmode('update').filter_by(citizen_id=id).first() active_service_state = SRState.get_state_by_name("Active") active_service_request = citizen.get_active_service_request() if active_service_request is None: return {"message": "Citizen has no active service requests"}, 400 try: active_service_request.invite(csr, invite_type="specific", sr_count = len(citizen.service_reqs)) except TypeError: return {"message": "Citizen has already been invited"}, 400 active_service_request.sr_state_id = active_service_state.sr_state_id db.session.add(citizen) db.session.commit() socketio.emit('update_customer_list', {}, room=csr.office_id) socketio.emit('citizen_invited', {}, room='sb-%s' % csr.office.office_number) result = self.citizen_schema.dump(citizen) socketio.emit('update_active_citizen', result.data, room=csr.office_id) return {'citizen': result.data, 'errors': result.errors}, 200
def post(self): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for creating a booking"}, 400 booking, warning = self.booking_schema.load(json_data) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 if booking.office_id is None: booking.office_id = csr.office_id if booking.office_id == csr.office_id or csr.liaison_designate == 1: db.session.add(booking) db.session.commit() result = self.booking_schema.dump(booking) return {"booking": result.data, "errors": result.errors}, 201 else: return {"The Booking Office ID and CSR Office ID do not match!"}, 403
def delete(self, id): today = datetime.today() string_today = today.strftime('%Y-%m-%d') print("==> In the python DELETE /bookings/recurring/<id> endpoint") csr = CSR.find_by_username(g.oidc_token_info['username']) bookings = Booking.query.filter_by(recurring_uuid=id)\ .filter(db.func.date(Booking.start_time) >= string_today)\ .all() for booking in bookings: if booking.office_id != csr.office_id and csr.liaison_designate != 1: abort(404) if booking.start_time.year == today.year and booking.start_time.month == today.month \ and booking.start_time.day == today.day and booking.start_time.hour <= 5: continue db.session.delete(booking) db.session.commit() return {}, 204
def put(self, id): csr = CSR.find_by_username(g.oidc_token_info['username']) json_data = request.get_json() if not json_data: return {"message": "No input data received for updating an appointment"} appointment = Appointment.query.filter_by(appointment_id=id)\ .filter_by(office_id=csr.office_id)\ .first_or_404() appointment, warning = self.appointment_schema.load(json_data, instance=appointment, partial=True) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 db.session.add(appointment) db.session.commit() # Make Snowplow call. schema = 'appointment_update' if "checked_in_time" in json_data: schema = 'appointment_checkin' SnowPlow.snowplow_appointment(None, csr, appointment, schema) result = self.appointment_schema.dump(appointment) return {"appointment": result.data, "errors": result.errors}, 200
def post(self): my_print("==> In AppointmentDraftPost, POST /appointments/draft") json_data = request.get_json() office_id = json_data.get('office_id') service_id = json_data.get('service_id') start_time = parse(json_data.get('start_time')) end_time = parse(json_data.get('end_time')) office = Office.find_by_id(office_id) service = Service.query.get(int(service_id)) if service_id else None # end_time can be null for CSRs when they click; whereas citizens know end-time. if not end_time: end_time = add_delta_to_time(start_time, minutes=office.appointment_duration, timezone=office.timezone.timezone_name) # Unauthenticated requests from citizens won't have name, so we set a fallback if (hasattr(g, 'oidc_token_info') and hasattr(g.oidc_token_info, 'username')): user = PublicUser.find_by_username(g.oidc_token_info['username']) citizen_name = user.display_name else: citizen_name = 'Draft' # Delete all expired drafts before checking availability Appointment.delete_expired_drafts() csr = None if (hasattr(g, 'oidc_token_info')): csr = CSR.find_by_username(g.oidc_token_info['username']) # CSRs are not limited by drafts, can always see other CSRs drafts # This mitigates two CSRs in office creating at same time for same meeting # Ensure there's no race condition when submitting a draft if not csr and not AvailabilityService.has_available_slots( office=office, start_time=start_time, end_time=end_time, service=service): return {"code": "CONFLICT_APPOINTMENT", "message": "Cannot create appointment due to scheduling conflict. Please pick another time."}, 400 # Set draft specific data json_data['is_draft'] = True json_data['citizen_name'] = citizen_name appointment, warning = self.appointment_schema.load(json_data) if warning: logging.warning("WARNING: %s", warning) return {"message": warning}, 422 db.session.add(appointment) db.session.commit() result = self.appointment_schema.dump(appointment) socketio.emit('appointment_create', result.data) return {"appointment": result.data, "warning" : warning}, 201