WriteError in pymongo through using test in Postman - python

I am getting this error in my application after trying to do a test case like this: test case in Postman
Here is my application code, I am quite unsure as to why python is throwing this error at me. It seems to not like me trying to add a new review through Postman which is in this format here: enter image description here
from flask import Flask, request, jsonify, make_response
from pymongo import MongoClient
from bson import ObjectId
import json
import jwt
import datetime
from functools import wraps
import bcrypt
def jwt_required(func):
#wraps(func)
def jwt_required_wrapper(*args, **kwargs):
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return jsonify( { 'message' : 'Token is missing' }), 401
try:
data = jwt.decode(token, app.config['SECRET_KEY'])
except:
return jsonify({ 'message' : 'Token is invalid' }), 401
bl_token = blacklist.find_one( { "token" : token })
if bl_token is not None:
return make_response( jsonify ( { "message" : "Token has been cancelled "}), 401)
return func(*args, **kwargs)
return jwt_required_wrapper
def admin_required(func):
#wraps(func)
def admin_required_wrapper(*args, **kwargs):
token = request.headers['x-access-token']
data = jwt.decode(token, app.config['SECRET_KEY'])
if data["admin"]:
return func(*args, **kwargs)
else:
return make_response( jsonify ( { "message" : "Admin access required"}), 401)
return admin_required_wrapper
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, ObjectId):
return str(obj)
return super(MyEncoder, self).default(obj)
app = Flask(__name__)
app.config['SECRET_KEY'] = 'password123'
client = MongoClient("mongodb://127.0.0.1:27017")
db = client.bizDB
businesses = db.biz
users = db.users
blacklist = db.blacklist
app.json_encoder = MyEncoder
with app.test_request_context():
db.mycollection.insert_one({'a': 1})
doc = db.mycollection.find_one({'a': 1})
print(jsonify(doc).response)
#app.route("/api/v1.0/businesses", methods=["GET"])
def show_all_businesses():
page_num, page_size = 1, 10
if request.args.get("pn"):
page_num = int(request.args.get("pn"))
if request.args.get("ps"):
page_size = int(request.args.get("ps"))
page_start = page_size * (page_num - 1)
data_to_return = []
for business in businesses.find().skip(page_start).limit(page_size):
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
data_to_return.append(business)
return make_response( jsonify( data_to_return ), 200 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["GET"])
#jwt_required
def show_one_business(id):
business = businesses.find_one({"_id":ObjectId(id)})
if business is not None:
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
return make_response ( jsonify ( business ), 200)
else:
return make_response (jsonify({ "error" : "Invalid Business ID" } ), 404)
#app.route("/api/v1.0/businesses", methods=["POST"])
#jwt_required
def add_business():
if "name" in request.form and "town" in request.form and "rating" in request.form:
new_business = { "name" : request.form["name"],
"town" : request.form["town"],
"rating" : request.form["rating"],
"reviews" : {}
}
new_business_id = businesses.insert_one(new_business)
new_business_link = "http://localhost:5000/api/v1.0/businesses/" + str(new_business_id.inserted_id)
return make_response( jsonify( { "url" : new_business_link } ), 201 )
else:
return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["PUT"])
def edit_business(id):
if "name" in request.form and "town" in request.form and "rating" in request.form:
result = businesses.update_one(
{"_id" : ObjectId(id)},
{
"$set": {
"name" : request.form["name"],
"town" : request.form["town"],
"rating" : request.form["rating"]
}
}
)
if result.matched_count == 1:
edited_business_link = "http://localhost:5000/api/v1.0/businesses/" + id
return make_response( jsonify( { "url": edited_business_link } ), 200 )
else:
return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )
else:
return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["DELETE"])
#jwt_required
#admin_required
def delete_business(id):
result = businesses.delete_one( { "_id" : ObjectId(id) })
if result.deleted_count == 1:
return make_response( jsonify( {} ), 204)
else:
return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["POST"])
#jwt_required
def add_new_review(id):
new_review = {
"_id" : ObjectId(),
"username" : request.form["username"],
"comment" : request.form["comment"],
"stars" : request.form["stars"]
}
businesses.update_one( { "_id" : ObjectId(id)} , {"$push" : { "reviews" : new_review}})
new_review_link = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + str(new_review["_id"])
return make_response( jsonify( { "url" : new_review_link } ), 201 )
#app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["GET"])
def fetch_all_reviews(id):
data_to_return = []
business = businesses.find_one( {"_id" : ObjectId(id) }, { "reviews" : 1, "_id" : 0})
for review in business["reviews"]:
review["_id"] = str(review["_id"])
data_to_return.append(review)
return make_response( jsonify( data_to_return), 200 )
#app.route("/api/v1.0/businesses/<string:business_id>/reviews/<string:review_id>", methods=["GET"])
def fetch_one_review(business_id, review_id):
business = businesses.find_one( { "reviews._id" : ObjectId(review_id)}, {"_id" : 0, "reviews.$" : 1} )
if business is None:
return make_response ( jsonify( { "error" : "Invalid business ID or Review ID" } ), 404 )
business["reviews"][0]["_id"] = str(business["reviews"][0]["_id"])
return make_response( jsonify( business["reviews"][0] ), 200)
#app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["PUT"])
def edit_review(id, review_id):
edited_review = {
"reviews.$.username" : request.form["username"],
"reviews.$.comment" : request.form["comment"],
"reviews.$.stars" : request.form["stars"]
}
businesses.update_one( { "reviews._id" : ObjectId(review_id) }, {"$set" : edited_review })
edit_review_url = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + review_id
return make_response( jsonify({ "url" : edit_review_url } ), 200 )
#app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["DELETE"])
#jwt_required
#admin_required
def delete_review(id, review_id):
businesses.update_one( { "_id" : ObjectId(id) }, { "$pull" : {"reviews" : { "_id" : ObjectId(review_id) } } } )
return make_response( jsonify( {} ), 204)
#app.route("/api/v1.0/login", methods = ["GET"])
def login():
auth = request.authorization
if auth:
user = users.find_one( { "username" : auth.username } )
if user is not None:
if bcrypt.checkpw(bytes(auth.password, 'UTF-8'), user["password"]):
token = jwt.encode( {
'user' : auth.username,
'admin' : user["admin"],
'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'])
return make_response (jsonify({ 'token' : token.decode('UTF-8') }), 200)
else:
return make_response(jsonify({ "message" : "Bad password" } ), 401 )
else:
return make_response(jsonify({ "message" : "Bad username" } ), 401 )
return make_response(jsonify({ "message" : "Authentication required" } ), 401 )
#app.route("/api/v1.0/logout", methods=["GET"])
#jwt_required
def logout():
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return make_response(jsonify({ "message" : "Token is missing" } ), 401 )
else:
blacklist.insert_one( { "token" : token } )
return make_response(jsonify({ "message" : "Logout Successful" } ), 200 )
if __name__ == "__main__":
app.run(debug=True)
The error I get back is simply:
pymongo.errors.WriteError: The field 'reviews' must be an array but is of type object in document {_id:
ObjectId('5ff3b9a145f6d9013ddb7586')}, full error: {'index': 0, 'code': 2, 'errmsg': "The field 'reviews'
must be an array but is of type object in document {_id: ObjectId('5ff3b9a145f6d9013ddb7586')}"}

You're using a $push on a field that isn't an array. Likely because you are setting it to a dict somewhere. Possibly change the line
"reviews" : {}
to
"reviews" : []

Related

Bad Request Did not attempt to load JSON data because the request Content-Type was not 'application/json'

Hello I am getting the mentioned error above in my python flask website
here is the code for adding expenses in my auth.py file
#auth.route('/add_expenses', methods=['GET', 'POST'] )
def adding_new_expenses():
name_user = request.args.get("user")
user = None
if name_user is None:
return redirect (url_for("auth.home"))
else:
form = AddExpense(request.form)
if request.method == 'GET':
return render_template("add_expenses.html", form=form)
else:
user = User.query.filter_by(id=name_user).first()
if user is not None:
if form.validate_on_submit():
new_expense = Expenses(expense_category_name=form.expense_category_name.data,
description_expense=form.description_expense.data,
date_purchase=form.date_purchase.data,
amount=form.amount.data,
user_id=user.id)
db.session.add(new_expense)
db.session.commit()
flash("Expense added successfully.")
return redirect(url_for("auth.home", user = name_user))
and my views.py:
#views.route('/add_expenses', methods=['POST'])
def adding_new_expenses():
data = request.json
name_user = data.get("user")
expense_category_name = data.get('expense_category_name')
description = data.get('description_expense')
date = data.get('date_purchase')
amount = data.get('amount')
if name_user is None or expense_category_name is None or description is None or date is None or amount is None:
return jsonify({"error": "Missing required fields"}), 400
user = session.query(User).filter_by(id=name_user).first()
if user is None:
return jsonify({"error": "User not found"}), 400
new_expense = Expenses(expense_category_name=expense_category_name, description_expense=description,
date_purchase=date,
amount=amount, user_id=user.id)
db.session.add(new_expense)
db.session.commit()
return jsonify({"message": "Expense added successfully."}), 200
and my javascript code:
function adding_new_expenses(name_user, type, description, date, amount) {
fetch("/add_expenses", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name_user: name_user,
expense_category_name: type,
description_expense: description,
date_purchase: date,
amount: amount
})
})
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("An error occurred while adding the expense.");
}
})
.then(data => {
if (data.message === "Expense added successfully.") {
console.log("Expense added successfully.");
window.location.href = '/home?user=' + name_user;
} else {
console.log(data.error)
}
})
.catch(error => {
console.error(error);
})
}
i can't seem to figure out this error, maybe someone can help me out here.
i am using python flask as my framework, slqalchemy as my database, jinja2 template, bootstrap, and a javascript code

Django request.session don't save data

I'm trying to retrieve the session data after login but it doesn't seem to be saving the information
.
class getSession(View):
def post(self, request):
print('====================>')
print(request.session.get('usuario'))
sesion = request.session.get('usuario')
return JsonResponse({'nombre': sesion.nombre, 'rut':sesion.rut})
class Login(View):
def post(self, request):
data = json.loads(request.body)
try:
usuario = Usuario.objects.get(rut=data['rut'], password=data['password'])
request.session['usuario'] = {'nombre': usuario.idpersona.name, 'rut': usuario.rut}
request.session.modified = True
#print(self.request.session['usuario'])
return JsonResponse({'usuario':usuario.rut})
except:
return JsonResponse({'usuario':'no existe'})
I'm get this error.
AttributeError: 'NoneType' object has no attribute 'nombre'
I'am using fetch with react.
async login() {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
rut: this.state.rut,
password: this.state.password,
}),
};
const response = await fetch("http://127.0.0.1:8000/test", requestOptions);
const data = await response.json();
if (data.usuario == "no existe") {
mensajeError("RUT o contraseña inválidos.");
} else {
mensajeExitoso("Usuario validado correctamente.");
setTimeout(() => {
window.location.href = "/Inicio";
}, 2000);
}
console.log(data.usuario);
}
try setting SESSION_SAVE_EVERY_REQUEST = True in settings.py

"RuntimeError: 1 validation error for WorkBoardCreateUserResponse E success E field required (type=value_error.missing)

I'm trying to unit test my code and make sure the my code returns a dict that matches the class. The error says the success field required (type=value_error.missing). If when I make the bool Optional it shows my actual results with success = None, message = None etc. So my actual class is returning empty and not equal to my wb_response.
class WorkBoardCreateUserResponse(BaseModel):
success: bool
message: Optional[str]
data: Optional[CreateUserData]
error: Optional[str]
error_description: Optional[str]
#mock.patch("workboard.requests.post")
#mock.patch("workboard.requests.get")
def test_create_workboard_user(self, mock_get, mock_post):
wb_response = {
"success":True,
"message": "",
"data": {
"totalCount": 1,
"user":
{ "user_id": 1,
"user_name":"",
"wb_email":"wb#email",
"email": "abc#company",
"first_name": "F name",
"last_name": "L name",
"manager_id": "manager#company",
"profile": {
"title": "emp",
"company": "company"
}
}
}
}
wb_user = WorkBoardUserRequest(
email= "abc#capone",
first_name= "F name",
last_name= "L name",
manager_id= "manager#company",
profile=WorkBoardProfile(
title="title",
company="company"
)
)
workboard_resp = json.dumps(wb_response)
mock_post.return_value.text = token_resp
mock_post.status_code = 200
mock_get.json.return_value.text = workboard_resp
final_response = json.loads(workboard_resp)
print(type(final_response))
employee = WorkBoard("client", "secret", "env", "vendor_token")
response = employee.create_workboard_user(wb_user)
self.assertEqual(response, WorkBoardCreateUserResponse(**final_response))
def create_workboard_user(self, wbUser: WorkBoardUserRequest) -> WorkBoardResponse:
"""
Grant access to the user by invoking the Third Party API
"""
wb_url = (PROD_URL if self.environment ==
"PROD" else NON_PROD_URL) + CREATE_USER_ENDPOINT
# Invoke the WorkBoard API to create user access
try:
create_user_response = requests.post(
wb_url, data=wbUser.json(), verify=True, allow_redirects=False, headers=self.headers
)
response = json.loads(create_user_response.text)
create_user_response = WorkBoardCreateUserResponse(**response)
logger.info(f"WorkBoard create user response : (%s)", create_user_response)
except ValidationError as validation_error:
print(f"Error while reading response : ", str(validation_error))
raise RuntimeError(str(validation_error))
except Exception as err:
logger.exception(f"Error while creating workboard user : %s", str(err))
raise RuntimeError(str(err))
return create_user_response

Check Permissions in FastAPI + Stawberry GraphQL

I'm using BasePermission decorator as specified in documentation.
#strawberry.type
class Query:
#strawberry.field(permission_classes=[IsAuthenticated])
def user(self) -> User:
# get by token OFC
return User(user_id=1, email="vladimir#cw.tech", first_name = "Vladimir", last_name = "Kirilov")
In my impementation I use VerifyToken class as described in FastAPI auth0 documentation.
class IsAuthenticated(BasePermission):
message = "User is not authenticated"
def has_permission(self, source: Any, info: Info, **kwargs) -> bool:
print(source)
print(info)
token: str = Depends(token_auth_scheme)
print(token)
result = VerifyToken(token.credentials).verify()
if result.get("status"):
print(result)
return False
return True
So I'm trying to get and verify the BEARER from the request, but I'm not able to extract it to process it further and get the error, please advise.
{
"data": null,
"errors": [
{
"message": "'Depends' object has no attribute 'credentials'",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"user"
]
}
]
}
Figured it out, not the cleanest way, but here it is
class IsAuthenticated(BasePermission):
message = "User is not authenticated"
async def has_permission(self, source: Any, info: Info, **kwargs) -> bool:
request: Union[Request, WebSocket] = info.context["request"]
print(request.headers)
if "Authorization" in request.headers:
print(request.headers['Authorization'])
result = VerifyToken( request.headers['Authorization'][7:] ).verify()
if result.get("status") == "error":
print(result.get("msg"))
return False
if result.get("sub"):
print(result)
return True
return False

Change JSON-RPC RESPONSE

I am using ODOO 11.0
how to return simple JSON object without JSON-RPC additional parameters
Here is my odoo controller code:
#http.route('/userappoint/webhook_test/',type='json', auth='public',method=['POST'], csrf=False,website=True)
def webhook_test(self,**kw):
response = {
'speech' : 'hello my name is shubham',
'displayText' : 'hello testing',
'source' : 'webhook'
}
return response
And I am getting this result :
{
"result": {
"displayText": "hello testing",
"source": "webhook",
"speech": "hello my name is shubham"
},
"id": "6eaced3e-6b0d-4518-9710-de91eaf16dd9",
"jsonrpc": "2.0"
}
But I need this :
{
"speech": "hello my name is shubham",
"displayText": "hello testing",
"source": "webhook"
}
Any help to point me in the right direction?
Thanks
Works on Odoo11. Just edit below portion of the function _json_response defined at odoo/odoo11/odoo/http.py near about line no : 621-630 as below & Restart the odoo service.
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
to new:
def _json_response(self, result=None, error=None):
response = {}
if error is not None:
response = error
if result is not None:
response = result
Then, restart the odoo service
Place the following code in any of your controller before you initialize the controller class
from odoo import http
from odoo.http import request, Response, JsonRequest
from odoo.tools import date_utils
class JsonRequestNew(JsonRequest):
def _json_response(self, result=None, error=None):
# response = {
# 'jsonrpc': '2.0',
# 'id': self.jsonrequest.get('id')
# }
# if error is not None:
# response['error'] = error
# if result is not None:
# response['result'] = result
responseData = super(JsonRequestNew, self)._json_response(result=result,error=error)
response = {}
if error is not None:
response = error
if result is not None:
response = result
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
class RootNew(http.Root):
def get_request(self, httprequest):
# deduce type of request
jsonResponse = super(RootNew, self).get_request(httprequest=httprequest)
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequestNew(httprequest)
else:
return jsonResponse
http.root = RootNew()
class MyController(http.Controller):

Categories

Resources