Flask REST - UPDATE user model - rest

i am building a REST api with JWT authorization abstracting the user model. So these are some of the functions I define in my user model definition:
def save_to_db(self):
db.session.add(self)
db.session.commit()
def update_db(self):
db.session.commit()
def delete_from_db(self):
db.session.delete(self)
db.session.commit()
and these are the methods:
#jwt_required()
def get(self):
user = UserModel.find_by_email(current_identity.email)
if user:
return user.json(), 200
return {'message': 'User not found'}, 400
def post(self):
data = UserRegister.parser.parse_args()
if UserModel.find_by_email(data['email']):
return {"message": "User already exists"}, 400
user = UserModel(**data)
user.save_to_db()
return user.json(), 200
#jwt_required()
def put(self):
user = UserModel.find_by_email(current_identity.email)
if user:
data = UserRegister.parser.parse_args()
try:
user = UserModel(**data)
user.update_db()
return user.json(), 200
except:
return {'message': 'An error ocurred while inserting user data.'}, 400
Everything is working except the PUT method. It does not store the actual value in the database, I am wondering why.

Related

MongoDB not connecting to the server

Every time I try to connect to my mongodb atlas via my app, I keep getting this error.
ERROR 'f len([h for h in host if "/" in h]) > 1: TypeError: 'Flask' object is not iterable'
from turtle import turtlesize
from flask import Flask, redirect, render_template, request, url_for
from pymongo import MongoClient
app = Flask(__name__)
#app.config['SECRET KEY'] = ''
app.config['MONGO_URI'] = 'mongodb+srv:// admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'
mongodb_client = MongoClient(app)
db = mongodb_client.db
cluster = db['Studentsdb']
collection = cluster['students']
#app.route('/', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Credentials. Please try again.'
else:
return redirect(url_for('student_forms'))
return render_template('login.html', error=error)
#app.route("/")
def products():
#return "<p>This is a proejcts page</p>"
return render_template('index.html')
#app.route("/student_forms", methods = ['GET','POST'])
def student_forms():
if request.method == 'POST':
name = request.form['name']
gender = request.form['gender']
class_admit = request.form['class']
dob = request.form['birthdate']
collection.insert_one({'name':name, 'gender':gender, 'class': class_admit, 'dob': dob})
return redirect(url_for('student_forms'))
return render_template('studentform.html', form=student_forms)
if __name__ == '__main__':
app.run(debug=True, port=8000)
You may have a number of issues but the first is your connection string should not have a space:
app.config['MONGO_URI'] = 'mongodb+srv:// admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'
->
app.config['MONGO_URI'] = 'mongodb+srv://admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'

How mock requests exception using Pytest fixture for mock_requests?

So I was using the requests-mock library to mock the HTTP requests that I do with the requests library and everything went fine until I had to do a test to catch the exception.
Example of my function to be tested
def get_wordpress_installed_plugins(url: str, user: str, password: str) -> bytes:
try:
credentials = user + ':' + password
token = base64.b64encode(credentials.encode())
header = {'Authorization': 'Basic ' + token.decode('utf-8')}
response = requests.get(url, headers=header, verify=False)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
logger.exception(f"Got response from {url} correctly with error {err}.")
raise CouldNotConnectWithApi(f"Problem retrieving information.")
logger.info(f"Got response from {url} correctly.")
return response.content
And the test to assert function did ok
#mock.patch("checkpluginsversion.logging.Logger.info")
def test_api_wordpress_list_plugins(logger_mock, requests_mock):
user = "user"
password = "password"
url = "https://www.example.com"
expected_result = b'[{"plugin": "akismet\\/akismet", "status": "active", "name": "Akismet Anti-Spam","version": "4.2.2"}]'
requests_mock.get(url,
content=b'[{"plugin": "akismet\\/akismet", "status": "active", "name": "Akismet Anti-Spam","version": "4.2.2"}]')
result = get_wordpress_installed_plugins(url, user, password)
assert result == expected_result
logger_mock.assert_called_with(f"Got response from {url} correctly.")
To be honest, I don't know if using pytest fixture mode of this library is the best way, but ok it is working for me. So the problem I have is when I have to test the function and raise the exception. Eventually, I did a workaround with #mock.patch, and worked for me.
#mock.patch("checkpluginsversion.requests.get")
#mock.patch("checkpluginsversion.logging.Logger.exception")
def test_api_should_return_an_exception(logger_mock,my_request_mock):
user = "user"
password = "password"
url = "https://www.example.com"
expected_result = b'[{"plugin": "akismet\\/akismet", "status": "active", "name": "Akismet Anti-Spam","version": "4.2.2"}]'
my_request_mock.side_effect = requests.exceptions.HTTPError
with pytest.raises(CouldNotConnectWithApi):
result = get_wordpress_installed_plugins(url, user, password)
#assert result == expected_result
logger_mock.assert_called_with(f"Got response from {url} correctly with error .")
But I would know and I will really appreciate it if someone could explain to me how to do a test to raise an exception using the pytest fixture of requests_mock library, thanks!

Misunderstood, an example from the documentation Pytest authorization

I decided to look at Pytest and immediately misunderstood, an example from the documentation, but there is no authorization, the test crashes with a code of 301, can anyone know what is the reason?
def test_with_authenticated_client(client, django_user_model):
username = "TestUser"
password = "1234567"
user = django_user_model.objects.create_user(username=username,
password=password)
# Use this:
client.force_login(user)
response = client.get('/new')
assert response.status_code == 200
def test_with_authenticated_client2(client):
username = "user2"
password = "bar"
# Or this:
client.login(username=username, password=password)
response = client.get('/new')
assert response.status_code == 200
with an unauthorized client, expected code 301
def test_make_not_authorized_user(client):
response = client.get('/new')
assert response.status_code in (302, 301)

Momoko, Jinja2 and Tornado

there is something fundamentally wrong with my code. These are my
tornado handlers with basic authentication and jinja2 as template
engine. The following works without the momoko db parts.
class BaseHandler(tornado.web.RequestHandler):
#property
def db(self):
return self.application.db
def get_current_user(self):
return self.get_secure_cookie("user")
class TemplateHandler(BaseHandler):
"""Request handler for writing HTML templates."""
def render(self, template_name, **kwargs):
"""Renders a Jinja2 template."""
kwargs['options'] = options.as_dict()
template = templates.environment.get_template(template_name)
html = template.render(kwargs)
self.write(html)
class AuthLoginHandler(TemplateHandler):
def get(self):
try:
errormessage = self.get_argument("error")
except:
errormessage = ""
self.render("login.html", errormessage = errormessage)
def check_permission(self, password, username):
if username == "admin" and password == "admin":
return True
return False
def post(self):
username = self.get_argument("username", "")
password = self.get_argument("password", "")
auth = self.check_permission(password, username)
if auth:
self.set_current_user(username)
self.redirect(self.get_argument("next", u"/"))
else:
error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect")
self.redirect(u"/auth/login/" + error_msg)
def set_current_user(self, user):
if user:
self.set_secure_cookie("user", tornado.escape.json_encode(user))
else:
self.clear_cookie("user")
class AuthLogoutHandler(TemplateHandler):
def get(self):
self.clear_cookie("user")
self.redirect(self.get_argument("next", "/"))
class MainHandler(TemplateHandler):
#gen.engine
def get(self):
username = tornado.escape.xhtml_escape(self.current_user)
try:
cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM products;')
except Exception as error:
self.write(str(error))
res = 'Query results: '+''.join(str(cursor.fetchall()))
self.render("index.html", username = username, cip = self.request.remote_ip, res = res)
For the logged in client, this code should execute a basic query and then print the result to the defined location ( {{ res }} ) within the jinja template. When I try to start the server, I get this:
line 22, in render
kwargs['options'] = options.as_dict()
AttributeError: 'module' object has no attribute 'as_dict'
We'll need to see your "import" statements to know what's wrong for certain. I suspect you have:
from tornado import options
But you need:
from tornado.options import options

About interacting and testing with django tastypie

I read many tutorial about django testing but I don't know how can I test for function insde resource , for example this User resource with signin function and obj_create. I really appreciate any helps because I can not figure out how to test them. k thanks.
class UserResource(ModelResource):
school = fields.ToOneField('frittie.app.api.api.LocationResource', 'user')
class Meta:
queryset = UserProfile.objects.all()
resource_name = 'User'
allowed_methods = ['get','post']
serializer = Serializer(formats=['json', 'plist'])
authorization= Authorization()
#models.signals.post_save.connect(create_api_key, sender=User)
#fields = ['username', 'email']
def obj_create(self, bundle, request=None, **kwargs):
if not request.method == "POST":
raise BadRequest('Object not found or not allowed to create a new one.')
username, email, password = bundle.data['username'], bundle.data['password'], bundle.data['password'],
try:
bundle.obj = User.objects.create_user(username, email, password)
except IntegrityError:
raise BadRequest('That username already exists')
return bundle
def signin(self, request, **kwargs):
self.method_check(request, allowed=['post'])
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return self.create_response(request, {'success': True})
else:
# Return a 'disabled account' error message
return self.create_response(request, {'success': False})
else:
# Return an 'invalid login' error message.
return self.create_response(request, {'success': False})
Tastypie has a descent testing documentation - ResourceTestCase API Reference