def close_missing_case2(): json_body = app.current_request.json_body # Load json data into object schema = MissingClosingSchema() missing, errors = schema.load(json_body) # Invalid JSON body if errors: raise ChaliceViewError(errors) with contextlib.closing(session_factory()) as session: try: # Check resident id is valid resident = session.query(Resident).get(missing.resident_id) if not resident: raise NotFoundError('Resident not exists') resident.status = 0 session.merge(resident) # Close existing active missing cases updated = session.query(Missing).filter( Missing.resident_id == missing.resident_id, Missing.status == 1).all() count = session.query(Missing).filter(Missing.resident_id == missing.resident_id, Missing.status == 1) \ .update({'status': 0, 'closed_by': missing.closed_by, 'closure': missing.closure, 'closed_at': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}) notify_close_missing(db_session=session, missing=missing) # Call flush() to update id value in missing session.flush() session.commit() schema = MissingClosingSchema(many=True) return schema.dump(updated).data except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))
def reset_password(): json_body = app.current_request.json_body email = json_body['email'] token = str(json_body['token']) password = json_body['password'] if not (email or password or token): raise BadRequestError("Email, password and token mush be supplied.") with contextlib.closing(session_factory()) as session: user = session.query(User).filter(User.email == email).first() user_token = session.query(UserToken).filter( UserToken.user_id == user.id).first() if not user: raise NotFoundError("User not found") if datetime.now() > user_token.expire: raise BadRequestError("Token is expired.") if not user_token: raise BadRequestError("Please request for a token first") if not verify_password_reset_token(token=token, salt=user.password_salt, hashed_token=user_token.token): raise BadRequestError("Token is invalid") result = encode_password(password=password, salt=user.password_salt) session.query(User).filter(User.email == email).update( {'password_hash': result['hashed']}) session.flush() session.commit() jwt_token = get_jwt_token( user.email + "," + str(user.role) + "," + str(user.id), password, user.password_salt, user.password_hash, JWT_SECRET) info = {'token': jwt_token, 'user': user} schema = TokenSchema() response = schema.dumps(info) if response.errors: raise ChaliceViewError(response.errors) return response.data
def register(): json_body = app.current_request.json_body email = json_body['email'] password = json_body['password'] if not (email or password): raise BadRequestError("Email and password must be supplied.") result = encode_password(password) hashed_password = result['hashed'] salt_used = result['salt'] json_body.pop('password', None) schema = UserSchema() user, errors = schema.load(json_body) user.password_hash = hashed_password user.password_salt = salt_used with contextlib.closing(session_factory()) as session: try: session.add(user) session.commit() user_profile = UserProfile() user_profile.email = user.email user_profile.user_id = user.id session.add(user_profile) session.commit() user_schema = UserSchema(exclude=('password_hash', 'salt', 'access_token')) result = user_schema.dump(user) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))
def expire_missing_case_minutes_older(minutes): deadline = datetime.datetime.utcnow() - datetime.timedelta(minutes=minutes) hours = minutes / 60.0 with contextlib.closing(session_factory()) as session: query_missing = session.query(Missing) query_resident = session.query(Resident) try: expired_list = query_missing.filter( and_(Missing.created_at < deadline, Missing.status == 1)).all() for missing_case in expired_list: print(missing_case) # Update missing case as expired missing_case.status = 0 missing_case.closure = "Expired after {:.2f} hours".format( hours) missing_case.closed_at = datetime.datetime.utcnow() session.merge(missing_case) # Update resident status to 0 if missing is closed resident = query_resident.get(missing_case.resident_id) resident.status = 0 # Notify all caregivers notify_expired_missing(db_session=session, missing=missing_case) session.flush() session.commit() except Exception as e: session.rollback() raise ChaliceViewError(str(e))
def forgot_password(): json_body = app.current_request.json_body email = json_body['email'] if not email: raise BadRequestError("Email must be supplied.") # Generate 5 digit code token = str(randint(10000, 99999)) expire = datetime.now() + timedelta(days=1) with contextlib.closing(session_factory()) as session: try: user = session.query(User).filter(User.email == email).first() if not user: raise NotFoundError("User not found") # Uncomment this if we want to hash the token if user.password_salt is None: user.password_salt = base64.b64encode( os.urandom(16)).decode('utf-8') session.merge(user) result = encode_password_reset_token(token=token, salt=user.password_salt) hashed_token = result['hashed'] user_token = session.query(UserToken).filter( and_(UserToken.user_id == user.id, UserToken.label == UserToken.LABEL_PASSWORD_RESET)).first() if not user_token: schema = UserTokenSchema() json_body['user_id'] = user.id json_body['token'] = hashed_token user_token, errors = schema.load(json_body) user_token.expire = expire user_token.label = UserToken.LABEL_PASSWORD_RESET session.add(user_token) session.flush() else: # Update the existing user_token user_token.token = hashed_token user_token.expire = expire user_token.label = UserToken.LABEL_PASSWORD_RESET session.flush() if not user.user_profile: user_profile = UserProfile() user_profile.user_id = user.id user_profile.email = user.email session.add(user_profile) session.flush() session.commit() notify_password_reset(db_session=session, user=user, token=token) # return json.dumps({"token": token}) return json.dumps({ 'Code': 'Successful', 'Message': 'Reset code has been emailed to you.' }) except Exception as e: session.rollback() raise ChaliceViewError(str(e))
def get_missing_by_id(id): with contextlib.closing(session_factory()) as session: missing = session.query(Missing).get(id) if not missing: raise NotFoundError("Missing case not found") else: missing_schema = MissingSchema() result = missing_schema.dump(missing) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_all_beacons(): with contextlib.closing(session_factory()) as session: beacons = session.query(Beacon).all() if not beacons: raise NotFoundError("No beacon found") else: beacons_schema = BeaconSchema(many=True, exclude=('resident', )) result = beacons_schema.dump(beacons) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_settings(): with contextlib.closing(session_factory()) as session: settings = session.query(Setting).all() if not settings: raise NotFoundError("No setting available") else: settings_schema = SettingSchema(many=True) result = settings_schema.dump(settings) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def get_beacon_by_id(id): with contextlib.closing(session_factory()) as session: beacon = session.query(Beacon).get(id) if not beacon: raise NotFoundError("No beacon found") else: beacon_schema = BeaconSchema(exclude=('resident.missings', )) result = beacon_schema.dump(beacon) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_caregivers_by_resident_id(id): with contextlib.closing(session_factory()) as session: resident = session.query(Resident).get(id) if not resident: raise NotFoundError("Missing case not found") else: resident_schema = ResidentSchema(only=('caregivers', )) result = resident_schema.dump(resident) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def expire_missing_case(event): with contextlib.closing(session_factory()) as session: minutes = 24 * 60 # by default 24 hours try: setting = session.query(Setting).filter( Setting.label == Setting.LABEL_MINUTES_TO_EXPIRE_CASE) if setting: minutes = int(setting.val) except Exception as e: print(str(e)) expire_missing_case_minutes_older(minutes)
def add_location_by_beacon_info(): json_body = app.current_request.json_body # Load json data into object schema = LocationBeaconSchema() location, errors = schema.load(json_body) # Invalid JSON body if errors: raise ChaliceViewError(errors) with contextlib.closing(session_factory()) as session: try: beacon = session.query(Beacon).filter( Beacon.uuid == location['uuid'], Beacon.major == location['major'], Beacon.minor == location['minor']).first() if not beacon: raise BadRequestError("Invalid beacon id") if beacon.status != 1: raise BadRequestError("Beacon is disabled") missing = session.query(Missing).filter( Missing.resident_id == beacon.resident_id, Missing.status == 1).first() if not missing: raise BadRequestError("No active missing case") location['beacon_id'] = beacon.id location.pop('uuid', None) location.pop('major', None) location.pop('minor', None) location = Location(**location) location.resident_id = missing.resident_id location.missing_id = missing.id session.add(location) # Send notification on 1st time found if not (missing.latitude and missing.longitude): notify_found_missing(db_session=session, missing=missing) # Update latest location to missing missing.latitude = location.latitude missing.longitude = location.longitude missing.address = location.address session.merge(missing) # Call flush() to update id value in missing session.flush() session.commit() schema = LocationSchema(exclude=('user', 'locator', 'resident')) return schema.dump(location) except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))
def list_all_missing_cases(): with contextlib.closing(session_factory()) as session: missings = session.query(Missing).all() if not missings: raise NotFoundError("No missing case") else: missings_schema = MissingSchema(many=True, exclude=('resident.caregivers', 'resident.beacons')) result = missings_schema.dump(missings) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_uuid_of_active_missing_cases_beacons(): with contextlib.closing(session_factory()) as session: beacons = session.query(Beacon) \ .join(Resident, Resident.id == Beacon.resident_id) \ .join(Missing, Missing.resident_id == Resident.id) \ .filter(Missing.status == 1).all() if not beacons: raise NotFoundError("No beacon of missing residents found") else: uuid_list = set() for beacon in beacons: uuid_list.add(beacon.uuid) return json.dumps({"uuid_list": uuid_list}, cls=SetEncoder)
def list_all_residents(): with contextlib.closing(session_factory()) as session: residents = session.query(Resident).all() if not residents: raise NotFoundError("No resident found") else: residents_schema = ResidentSchema(exclude=('beacons', 'missings', 'caregivers'), many=True) result = residents_schema.dump(residents) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def get_beacon_by_resident_id(resident_id): with contextlib.closing(session_factory()) as session: beacons = session.query(Beacon) \ .join(Resident, Resident.id == Beacon.resident_id) \ .filter(Resident.id == resident_id).all() if not beacons: raise NotFoundError("No beacon found") else: beacons_schema = BeaconSchema(exclude=('resident', ), many=True) result = beacons_schema.dump(beacons) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def disable_beacon_by_id(id): with contextlib.closing(session_factory()) as session: try: beacon = session.query(Beacon).get(id) count = session.query(Beacon).filter( Beacon.id == id, Beacon.status == 1).update({'status': 0}) # Call flush() to update id value in missing session.flush() session.commit() schema = BeaconSchema(exclude=('resident', )) return schema.dump(beacon).data except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))
def list_missing_residents(): with contextlib.closing(session_factory()) as session: residents = session.query(Resident) \ .join(Missing, Missing.resident_id == Resident.id) \ .filter(and_(Resident.status == 1, Missing.status == 1)) \ .all() if not residents: raise NotFoundError("No missing resident found") else: residents_schema = ResidentSchema( exclude=('beacons', 'missings', 'caregivers', 'missing_active.locations'), many=True) result = residents_schema.dump(residents) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_beacons_of_active_missing_cases(): with contextlib.closing(session_factory()) as session: beacons = session.query(Beacon) \ .join(Resident, Resident.id == Beacon.resident_id) \ .join(Missing, Missing.resident_id == Resident.id) \ .filter(Missing.status == 1, Beacon.status == 1).all() if not beacons: raise NotFoundError("No beacon of missing residents found") else: beacons_schema = BeaconSchema(many=True, exclude=('resident.caregivers', 'resident.beacons', 'resident.missings')) result = beacons_schema.dump(beacons) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def update_beacon_status_by_id(id, status): if int(status) not in [0, 1]: raise BadRequestError("Status value can only be 0 or 1") with contextlib.closing(session_factory()) as session: try: beacon = session.query(Beacon).get(id) if beacon is None: raise NotFoundError("Beacon ({}) not exists.".format(id)) count = session.query(Beacon).filter(Beacon.id == id).update( {'status': status}) # Call flush() to update id value in missing session.flush() session.commit() schema = BeaconSchema(exclude=('resident', )) return schema.dump(beacon).data except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))
def list_latest_locations_of_missing_case(missing_id): with contextlib.closing(session_factory()) as session: locations = session.query(Location) \ .join(Missing, Missing.id == Location.missing_id) \ .filter(Missing.id == missing_id) \ .order_by(Location.id.desc()) \ .limit(20) \ .all() if not locations: raise NotFoundError("No location of this missing case found") else: locations_schema = LocationSchema(many=True, exclude=('resident', 'missing', 'locator', 'user')) result = locations_schema.dump(locations) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def list_relative_residents(): current_user = auth.get_authorized_user(app.current_request) with contextlib.closing(session_factory()) as session: residents = session.query(Resident) \ .join(Caregiver, Caregiver.resident_id == Resident.id) \ .filter(Caregiver.user_id == current_user['id']) \ .order_by(Resident.status.desc(), Resident.fullname.asc()) \ .all() if not residents: raise NotFoundError("No resident found") else: residents_schema = ResidentSchema( exclude=('beacons', 'missings', 'caregivers', 'missing_active.locations'), many=True) result = residents_schema.dump(residents) if result.errors: # errors not empty raise ChaliceViewError(result.errors) return result.data
def login(): json_body = app.current_request.json_body email = json_body['email'] password = json_body['password'] if not (email or password): raise BadRequestError("Email and password must be supplied.") with contextlib.closing(session_factory()) as session: user = session.query(User).filter(User.email == email).first() if not user: raise NotFoundError("User not found") print("{}, {}, {}".format(user.email, user.role, user.id)) # Add to token ==> email + "|" + role jwt_token = get_jwt_token( user.email + "," + str(user.role) + "," + str(user.id), password, user.password_salt, user.password_hash, JWT_SECRET) info = {'token': jwt_token, 'user': user} schema = TokenSchema() response = schema.dumps(info) if response.errors: raise ChaliceViewError(response.errors) return response.data
def create_new_missing_case2(): json_body = app.current_request.json_body # Load json data into object missing_schema = MissingSchema(exclude=('resident.beacons', 'resident.missings', 'resident.missing_active', 'resident.caregivers')) missing, errors = missing_schema.load(json_body) # Invalid JSON body if errors: raise ChaliceViewError(errors) with contextlib.closing(session_factory()) as session: try: # Check resident id is valid resident = session.query(Resident).get(missing.resident_id) if not resident: raise NotFoundError('Resident not exists') resident.status = 1 session.merge(resident) # Close existing active missing cases session.query(Missing).filter(Missing.resident_id == missing.resident_id, Missing.status == 1) \ .update({'status': 0, 'closed_by': missing.reported_by, 'closed_at': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}) # Add new missing case session.add(missing) # Notify other caregivers notify_new_missing(db_session=session, missing=missing) # Call flush() to update id value in missing session.flush() session.commit() return missing_schema.dump(missing).data except exc.SQLAlchemyError as e: session.rollback() raise ChaliceViewError(str(e))