Error 1064 sql syntax error - flask

I am trying to work on registration using WTF forms and I am facing a sql syntax error when I am trying to inject data through flask execution. But I can able to insert the data using normal sql query through mysql command line.
from wtforms import Form, BooleanField, StringField, PasswordField, validators
from MySQLdb import escape_string as thwart
class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35)])
password = PasswordField('New Password', [validators.DataRequired(), validators.EqualTo('confirm', message='Passwords must match')])
confirm = PasswordField('Repeat Password')
accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])
# for registering the user
#app.route('/register/', methods = ['GET', 'POST'])
def register_page():
try:
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
username = form.username.data
email = form.email.data
password = sha256_crypt.encrypt(str(form.password.data))
c, conn = connection()
x = c.execute("SELECT * FROM users WHERE username = '(%s)'" %(thwart(username),))
#x = c.fetchone()
if int(x) > 0:
flash ("that username already taken, please take another")
return render_template("register.html", form =form)
else:
c.execute("INSERT INTO users (username, password, email, tracking) VALUES (%s, %s, %s, %s)" %(thwart(username), thwart(password), thwart(email), thwart('/home/')))
c.commit()
flash("Thanks for registering")
c.close()
conn.close()
gc.collect()
session['logged_in'] = True
session['username'] = username
return redirect(url_for('dashboard'))
return render_template("register.html", form = form)
except Exception as e:
return render_template("register.html", error = e, form = form)
The error can be found below
After entering the password and matching it with confirm and submitting it. I am getting an error. Can anyone please help me on this.

Your SQLite statements look wrong.
x = c.execute("SELECT * FROM users WHERE username = '(%s)'" %(thwart(username),))
The single quotes are already being handled as far as I know, but in any case you can just use a prepared statement:
x = c.execute("SELECT * FROM users WHERE username = ?", (thwart(username)))
The same is true regarding your INSERT statement:
c.execute("INSERT INTO users (username, password, email, tracking) VALUES (?, ?, ?, ?)" (thwart(username), thwart(password), thwart(email), thwart('/home/')))
c.

query = "SELECT * FROM users WHERE username = %s"
x = c.execute(query, (thwart(username),))
similarly
query2 = "INSERT INTO users (username, password, email, tracking) VALUES (%s, %s, %s, %s)"
c.execute(query2, (thwart(username), thwart(password), thwart(email), thwart('/home/'))
worked!

Related

how to correctly use connection pool get & close w/ mysql.connector in python

I'm new to Python. I learned the concept of the connection pool recently, and I want to add it to my code, but have no idea about how to add get_connection() and .close() to my app...
from mysql.connector import pooling
poolname ="mysqlpool"
poolsize = 3
connectionpool = mysql.connector.pooling.MySQLConnectionPool(
pool_name =poolname,pool_size=poolsize, pool_reset_session=True, host='localhost',user='root',password=mySqlPassword())
#choose the database
conn = connectionpool.get_connection()
with conn.cursor() as cursor:
cursor.execute("USE website;")
conn.close
#session key
app =Flask(__name__)
app.secret_key= secret_key()
#homepage
#app.route("/")
def index():
return render_template("register.html")
#handling registering
#app.route("/signup",methods=["POST"])
def signup():
conn = connectionpool.get_connection()
with conn.cursor() as cursor:
nickname = request.form["nickname"]
username = request.form["username"]
password = request.form["password"]
sql = "SELECT username FROM member where username = %s"
user = (username,)
cursor.execute(sql, user)
result = cursor.fetchall()
if (not nickname or not username or not password):
return redirect("/error?message=empty")
if (result):
return redirect("/error?message=registered")
else:
hashed_password = bcrypt.generate_password_hash(password=password)
sql = "Insert into member (name, username, password ) values (%s, %s, %s)"
userInfo = (nickname, username, hashed_password)
cursor.execute(sql, userInfo)
conn.commit()
return redirect("/")
conn.close
There are many functions in my app. Once I add get_connection() and .close(), the next function can't get the database from pool.
err: mysql.connector.errors.ProgrammingError: 1046 (3D000): No database selected

Tuple index out of range in Airflow XCom

I am working with Airflow and XComs and want to return multiple values from the function, however, I am facing the problem. The following is my code:
def authenticate_api():
#Define the global variables
# API authentication
url = 'odoo'
db = 'db'
username = 'admin'
password = 'user'
logging.info("Variables assigned")
common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))
uid = common.authenticate(db, username, password, {})
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))
return db, models, uid, password
def get_max_date_from_odoo(**context):
# Variables
list = []
list2 = []
db = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
models = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
uid = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
password = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
#Get the customer id and date to use in the query
datesandids = models.execute_kw(db, uid, password,
'res.partner', 'search_read',
[[['is_company', '=', False]]],
{'fields': ['x_customer_register_date', 'x_customer_id']})
It returns:
('database', <ServerProxy for odoo069/xmlrpc/2/object>, 1, '1234')
as a tuple. Therefore I am getting an error of:
(db, uid, passwd ) = params[0], int(params[1]), params[2]\nIndexError: tuple index out of range\n'>
Any help would be really appreciated
Instead of getting the individual values, you are returning the tuple containing all values and assigning it to all of the variables.
Try this:
def get_max_date_from_odoo(**context):
# Variables
list = []
list2 = []
db, models, uid, password = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
...
That should save you hitting the database 4 times to get the same value.
Alternatively, since we are unsure of the type that is returned from the XCOM (expected tuple, could be json encoded).
def get_max_date_from_odoo(**context):
# Variables
list = []
list2 = []
values = context['task_instance'].xcom_pull(key=None, task_ids='authenticate_api')
if isinstance(values, tuple):
db, models, uid, password = values
elif isinstance(values, str):
import json
values = json.loads(values)
db, models, uid, password = values

Line Breaks and rendering HTML in Django Rest Framework's ValidationError

Working on a Django/DRF-React-Redux project. So I want to return specific messages for user login validation. If the credentials don't match, they get one error string, if the user is inactive they get another error string.
What I am trying to do is for one of the messages I need two line breaks and the other I want to render HTML because it should contain an email address. Anything I have read on SO, is not working. For example, regarding the HTML:
Put HTML into ValidationError in Django
Here is the method:
def validate(self, data):
username = data['username']
password = data['password']
user_qs = User.objects.filter(username__iexact=username)
# user_b = User.objects.filter(email__iexact=username)
# user_qs = (user_a | user_b).distinct()
if user_qs.exists() and user_qs.count() == 1:
user_obj = user_qs.first()
password_passes = user_obj.check_password(password)
if not user_obj.is_active:
raise ValidationError((mark_safe('This user is inactive. Please contact The Company at accounts#example.com.')))
if password_passes:
data['username'] = user_obj.username
payload = jwt_payload_handler(user_obj)
token = jwt_encode_handler(payload)
data['token'] = token
return data
raise ValidationError('The credentials provided are invalid.\nPlease verify the username and password are correct.')
Needless to say it isn't rendering as expected on the front-end. Doesn't break the lines and doesn't render HTML, just just displays it as typed.
I guess if all else fails, I can simplify the server responses to "Invalid" or "Inactive" and just render the full message client-side.
Well, I ended up coming across: dangerouslySetInnerHTML which took care of the issue.
https://facebook.github.io/react/docs/dom-elements.html#dangerouslysetinnerhtml
I changed the following for the DRF serializer.
def validate(self, data):
username = data['username']
password = data['password']
user_qs = User.objects.filter(username__iexact=username)
# user_b = User.objects.filter(email__iexact=username)
# user_qs = (user_a | user_b).distinct()
if user_qs.exists() and user_qs.count() == 1:
user_obj = user_qs.first()
password_passes = user_obj.check_password(password)
if not user_obj.is_active:
raise ValidationError(mark_safe('This user is inactive.<br><br>Please contact The Company at accounts#example.com.'))
if password_passes:
data['username'] = user_obj.username
payload = jwt_payload_handler(user_obj)
token = jwt_encode_handler(payload)
data['token'] = token
return data
raise ValidationError(mark_safe('The credentials provided are invalid.<br><br>Please verify the username and password are correct.'))
Then on the React FE I had to change the signin.js container from:
renderAlert() {
if (this.props.errorMessage) {
return (
<div className="alert alert-danger">
{this.props.errorMessage}
</div>
);
}
}
To:
renderAlert() {
if (this.props.errorMessage) {
return (
<div className="alert alert-danger"
dangerouslySetInnerHTML={{__html: this.props.errorMessage}}>
</div>
);
}
}

Raising validation error in django form for the api

I am new to django and python development and am naive in my understanding of how to handle exceptions.
I am registering a user through an api call by calling the method register, and would like to push the success status or the error messages while registration.
def register(self,request, **kwargs):
try:
data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
email = data['email']
password = data['password']
firstname = data['firstname']
lastname = data['lastname']
newdata = {'email' : email , 'password1': password , 'password2':password, 'firstname':'firstname' , 'lastname':lastname }
registrationform = UserEmailRegistrationForm(newdata)
print registrationform.errors.as_text
print registrationform.cleaned_data
cleaned_data = registrationform.cleaned_data
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
new_user = RegistrationProfile.objects.create_inactive_user(cleaned_data['username'],cleaned_data['email'],cleaned_data['password1'], site)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request,**cleaned_data)
registerUser = collections.OrderedDict()
registerUser['return']='0'
registerUser['code']='0'
registerUser['message']='registered user'
return HttpResponse(registerUser, content_type="application/json")
except Exception, e:
logging.exception(e)
registerUser = collections.OrderedDict()
registerUser['return']='0'
registerUser['code']='0'
registerUser['message']='registered user'
return HttpResponse(registerUser, content_type="application/json")
When I execute this, for example with an already registered email, I get the following in registrationform.errors.as_text
bound method ErrorDict.as_text of {'email': [u'A user with that email already exists.']}>
What would be the right way to code exceptions so that I can pass the success message if the form was validated and user was registered, and the error message if there was a validation error?
Any help is much appreciated!
You might want to have a look in the form's is_valid() method: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.is_valid
For example
if registrationform.is_valid():
//do your stuff
....
register['error'] = False
else:
//return the errors
registerUser['message'] = _('Oops! Please fix the following errors')
register['error'] = True
register['errors'] = registrationform.errors
....

Problem with pymongo and django unique value

I am writing django app that as a beckend is using mongodb. I am curently writing register part. Here is how I connecto to database in settings.py
if socket.gethostname() == "Production server":
CON = Connection()
DB = CON.fish
else:
CON = Connection()
DB = CON.test
DB.user.ensure_index([("username", ASCENDING),("email",ASCENDING)],unique = True)#,drop_dups=True
Here is mye register view:
def register(request):
"""
handle user registration
code variable is for testing purposes
"""
if request.method== 'GET':
form = RegisterForm(auto_id=False)
code = 1
return render_to_response('register_home.html',locals(),context_instance=RequestContext(request))
elif request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
password = form.cleaned_data['password']
password_confirmation = form.cleaned_data['password_confirmation']
if password == password_confirmation:
login = form.cleaned_data['login']
email = form.cleaned_data['email']
newsletter = form.cleaned_data['newsletter']
key = register_user(login,email,password,newsletter)
if key:
#send email
send_mail("Dziękujemy za rejestrację"," Klucz aktywacyjny to " + key,settings.EMAIL_HOST_USER,[email])
request.session['email'] = email
return redirect(register_success)
else:
code = 4
error = "Login/email taken"
return render_to_response('register_home.html',locals(),context_instance=RequestContext(request))
else:
code = 3
error = "invalid password"
return render_to_response('register_home.html',locals(),context_instance=RequestContext(request))
else:
code = 2
return render_to_response('register_home.html',locals(),context_instance=RequestContext(request))
Here is my function I use to register user:
def register_user(login,email,password,newsletter):
"""
This function will return activation key for this user if user was added successfully or none otherwise
"""
key = generate_activation_key()
user = {
"username":login,
"email":email,
"password":crypt_password(password),
"date_join": datetime.now(),
"key": key
}
if newsletter:
user['newsletter'] = True
try:
settings.DB.user.insert(user,safe = True)
except DuplicateKeyError, error:
logging.debug("error raise during saving user")
return None
except OperationFailure, error:
logging.critical("Cannot save to database")
logging.critical(error)
else:
#we have no errors users is registred
return key
And when I test it in the browser it seems to be working. But I write test for it and it isn't working anymore. Here is code for test:
def test_valid_credentials(self):
#now try to register valid user
data = {'login':'test','password':'zaq12wsx','password_confirmation':'zaq12wsx','terms':True,'newsletter':True,'email':'test#test.com'}
response = self.c.post(reverse('register'),data)
#our user should be registred
self.assertEquals(302, response.status_code,'We dont have benn redirected')
self.assertEqual(len(mail.outbox), 1,'No activation email was sent')
#clen email box
mail.outbox = []
#now try to add another user with the same data
response = self.c.post(reverse('register'),data)
#template should be rendered with error message about used login and email
self.assertEquals(200, response.status_code)#this fails
And here is error that i get.
self.assertEquals(200, response.status_code)
AssertionError: 200 != 302
So user was registred with the same username and email which shoudn't happen. Any sugestions? Thanks in advance
Why don't you use https://github.com/django-mongodb-engine/mongodb-engine it works almost perfect with Django ORM. Works like a charm for me.