async def test_main(request): """ The main route. Accepts POST requests with the following "Content-Type" headers: - application/json - octet-stream If the request has a json content type, then the request body should contain a "url" key with the location from where the resource should be downloaded. In case of the octet-stream, the binary data is considered a resource. """ try: validate_request(request) # TODO move to middleware except AssertionError: return json({'success': False, 'error': 'Wrong content type'}, 400) if is_binary_request(request): try: header, data, encoded_data = parse_raw_body(request.body) except Exception: return json({'success': False, 'error': 'Failed to parse request body'}, 400) elif is_json_request(request): data = request.load_json() else: return json({'success': False, 'error': 'Wrong content type'}, 400) try: await save_resource(app, request.content_type, data) except Exception as e: return json({'success': False, 'error': str(e)}, 400) return json({'success': True}, 201)
def new_product_movement(): """ docstring """ try: request_data = request.get_json() schema = new_movement_schema() [valid, error] = validate_request(request_data, schema) if not valid: return {"success": False, "message": str(error)}, 400 movement_id = generate_unique_code("PM-") duplicate_check = call_procedure("CALL get_one_product_movement(%s);", (movement_id)) while duplicate_check: movement_id = generate_unique_code("PM-") duplicate_check = call_procedure( "CALL get_one_product_movement(%s);", (movement_id)) timestamp = get_utcnow_time_string() from_location = request_data.get('from_location') to_location = request_data.get('to_location') # Check if from and to location => both are not null if from_location == to_location: return { "success": False, "message": "From And To Locations cannot be Same " + "OR Both cannot be Null (Need to specify either one in that case)" }, 400 product_id = request_data.get('product_id') qty = request_data.get('qty') print("QTY", qty) # check sufficient qty available in from location if from_location is not null if from_location: check = call_procedure("CALL check_available_quantity(%s,%s)", (product_id, from_location)) if not check: return { "success": False, "message": "Insufficient Qty in From Location" }, 400 elif qty > check['qty']: return { "success": False, "message": "Insufficient Qty in From Location" }, 400 result = call_procedure( "CALL add_product_movement(%s, %s, %s, %s, %s, %s);", (movement_id, timestamp, from_location, to_location, product_id, qty)) return {"data": result, "success": True}, 200 except Exception as e: print(e.args) return {"success": False, "message": str(e.args)}, 500
def edit_product_movement(product_movement_id): """ docstring """ try: request_data = request.get_json() schema = new_movement_schema() [valid, error] = validate_request(request_data, schema) if not valid: return {"success": False, "message": str(error)}, 400 timestamp = get_utcnow_time_string() new_from_location = request_data.get('from_location') new_to_location = request_data.get('to_location') if new_from_location == new_to_location: return { "success": False, "message": "From And To Locations cannot be Same " + "OR Both cannot be Null (Need to specify either one in that case)" }, 400 new_product_id = request_data.get('product_id') result = call_procedure("CALL get_one_product_movement(%s);", (product_movement_id)) if not result: return {"success": False, "message": "Not Found"}, 404 new_qty = request_data.get('qty') old_from_location = result.get('from_location') old_to_location = result.get('to_location') old_product_id = result.get('product_id') old_qty = result.get('qty') print("product id", old_product_id) query_output = call_procedure( "CALL update_product_movement(%s,%s,%s,%s,%s,%s,%s,%s,%s)", (product_movement_id, old_from_location, old_to_location, old_product_id, old_qty, new_from_location, new_to_location, new_product_id, new_qty)) return {"success": True, "data": query_output}, 200 except MySQLError as e: return {"success": False, "message": e.args[1]}, 500 except Exception as e: print(e.args) return {"success": False, "message": e.args}, 500
def reset_password_request(): """Respond to existing user's request to reset their password.""" class ResetPasswordSchema(Schema): email = email_field try: data = validate_request(request, ResetPasswordSchema) user = User.query.filter_by(email=data['email']).first() if not user: raise ValueError("No matching user for email.") else: send_reset_password_email(user, request.args.get('next')) except ValueError as e: return Response(str(e), 400)
def reset_password(token): """Reset an existing user's password.""" class ResetPasswordSchema(Schema): password = password_field try: data = validate_request(request, ResetPasswordSchema) user = User.reset_password(token, data['password']) if not user: raise ValueError( "The password reset link is invalid or has expired") else: resp = authenticate(user) return resp, 200 except ValueError as e: return Response(str(e), 400)
def balance_qty(): """ docstring """ try: request_data = request.get_json() schema = balance_schema() [valid, error] = validate_request(request_data, schema) if not valid: return {"success": False, "message": str(error)}, 400 product = request_data.get('product') location = request_data.get('location') result = call_procedure("CALL balance(%s,%s);", (product, location)) result['total_qty'] = int(result['total_qty']) return {"success": True, "data": result}, 200 except Exception as e: return {"success": False, "message": str(e.args)}, 500
def change_user_info(current_user): """Change an existing user's email.""" class ChangeUserInfoSchema(Schema): first_name = fields.Str(required=False, validate=name_validate) last_name = fields.Str(required=False, validate=name_validate) try: data = validate_request(request, ChangeUserInfoSchema) if len(data) == 0: raise ValueError("Request didn't include any changes.") if 'first_name' in data: current_user.first_name = data['first_name'] if 'last_name' in data: current_user.last_name = data['last_name'] db_session.add(current_user) db_session.commit() return authenticate_payload(current_user), 200 except ValueError as e: return Response(str(e), 400)
def change_password(current_user): """Change an existing user's password.""" class ChangePasswordSchema(Schema): old_password = password_field new_password = password_field try: data = validate_request(request, ChangePasswordSchema) if current_user.verify_password(data['old_password']): current_user.password = data['new_password'] db_session.add(current_user) db_session.commit() # TODO: send email confirming password change return jsonify({}), 200 else: raise ValueError("Original password is invalid.") except ValueError as e: return Response(str(e), 400)
def edit_product(product_id): """ docstring """ try: request_data = request.get_json() schema = new_product_location_schema() [valid, error] = validate_request(request_data, schema) if not valid: return {"success": False, "message": str(error)}, 400 name = request_data.get('name') check = call_procedure("CALL get_one_product(%s);", (product_id)) if not check: return {"success": False, "message": "Not Found"}, 404 result = call_procedure("CALL update_product(%s,%s);", (product_id, name)) return {"data": result, "success": True}, 200 except Exception as e: print(e.args) return {"success": False, "message": str(e.args)}, 500
def change_email(current_user): """Change an existing user's email.""" class ChangeEmailSchema(Schema): new_email = email_field try: data = validate_request(request, ChangeEmailSchema) if User.query.filter_by(email=data['new_email']).first() is not None: raise ValueError("Email already in use.") else: current_user.email = data['new_email'] current_user.verified_email = not current_user.is_admin( ) # Don't lock out admins db_session.expire_on_commit = False db_session.add(current_user) db_session.commit() send_change_email(current_user) # TODO: send email to old email notifying email change return jsonify({}), 200 except ValueError as e: return Response(str(e), 400)
def sign_up(): """Register a new user, and send them a confirmation email.""" class RegisterSchema(Schema): first_name = name_field last_name = name_field email = email_field password = password_field try: data = validate_request(request, RegisterSchema) if User.query.filter_by(email=data['email']).first() is not None: raise ValueError("Email already in use.") else: user = User(**data) db_session.expire_on_commit = False db_session.add(user) db_session.commit() send_confirm_email(user) resp = authenticate(user) return resp, 200 except ValueError as e: return Response(str(e), 400)
def login(): """Log in an existing user.""" class LoginSchema(Schema): email = email_field password = password_field try: data = validate_request(request, LoginSchema) email, password = itemgetter('email', 'password')(data) user = User.query.filter_by(email=email).first() if user is None: raise ValueError("No matching user for email.") elif user.password_hash is None: raise ValueError( "Password not set. Please check for email invite.") elif not user.verify_password(password): raise ValueError("Incorrect password.") else: resp = authenticate(user) return resp, 200 except ValueError as e: return Response(str(e), 400)
def new_product(): """ docstring """ try: request_data = request.get_json() schema = new_product_location_schema() [valid, error] = validate_request(request_data, schema) if not valid: return {"success": False, "message": str(error)}, 400 name = request_data.get('name') product_id = generate_unique_code("P-") duplicate_check = call_procedure("CALL get_one_product(%s);", (product_id)) while duplicate_check: product_id = generate_unique_code("P-") duplicate_check = call_procedure("CALL get_one_product(%s);", (product_id)) result = call_procedure("CALL add_product(%s,%s);", (product_id, name)) return {"data": result, "success": True}, 200 except Exception as e: print(e) return {"success": False, "message": str(e.args)}, 500
def update_user(user_id): """Update information on a user's account.""" class UpdateUserSchema(Schema): first_name = fields.Str(required=False, validate=name_validate) last_name = fields.Str(required=False, validate=name_validate) email = fields.Email(required=False, validate=email_validate) role = fields.Str(required=False, validate=validate.OneOf(Role.get_roles())) verified_email = fields.Boolean(required=False) try: user = User.query.filter_by(id=user_id).first() if user is None: abort(404) data = validate_request(request, UpdateUserSchema) user_updated = False email_updated = False if len(data) > 0: for field, new_value in data.items(): old_value = getattr(user, field) if field == 'role': new_value = Role(new_value) if old_value != new_value: if field == 'email': email_updated = True setattr(user, field, new_value) user_updated |= True if user_updated: if email_updated: user.verified_email = not user.is_admin( ) # Don't lock out admins db_session.add(user) db_session.commit() return jsonify(get_user_payload(user)), 200 raise ValueError("Request didn't include any changes.") except ValueError as e: return Response(str(e), 400)
def join_from_invite(token): """Reset an existing user's password.""" class JoinFromInviteSchema(Schema): password = password_field try: request_data = validate_request(request, JoinFromInviteSchema) token_data = deserialize_data(token) if token_data: user_id = token_data.get('id') user = User.query.filter_by(id=user_id).first() if not user: logging.warning(f"User with id {user_id} does not exist.") else: user.verified_email = True user.password = request_data['password'] db_session.add(user) db_session.commit() resp = authenticate(user) return resp, 200 raise ValueError( "The join from invite link is invalid or has expired.", 400) except ValueError as e: return Response(str(e), 400)
def invite_user(): """Invites a new user to create an account and set their own password.""" class InviteUserSchema(Schema): first_name = name_field last_name = name_field email = email_field role = fields.Str(validate=validate.OneOf(Role.get_roles())) try: data = validate_request(request, InviteUserSchema) if User.query.filter_by(email=data['email']).first() is not None: raise ValueError("Email already in use.") user = User( role=Role(data['role']), first_name=data['first_name'], last_name=data['last_name'], email=data['email'], ) db_session.add(user) db_session.commit() send_join_from_invite_email(user) return jsonify({user.id: get_user_payload(user)}), 200 except ValueError as e: return Response(str(e), 400)