How do I pytest flask form validators? - validation

I tried everything and I couldn't test the validators. I want to test a flask app that has validators.
This is the code I am trying to test.
class Createform(FlaskForm):
name = StringField('Name:', validators=[DataRequired(), Length(min=2, max=50)])
submit = SubmitField('Submit')
def validate_name(self, name):
name = Chef.query.filter_by(name=name.data).first()
if name:
raise ValidationError ('This name is taken')
I also could not test the following;
#app.route('/createchef', methods = ['POST','GET'])
def createchef():
createform = Createform()
if createform.validate_on_submit():
chef = Chef(name=createform.name.data)
db.session.add(chef)
db.session.commit()
return redirect(url_for('read'))
return render_template('createchef.html', form=createform)

Related

Mock method in class using MiniTest

I'm running into an issue mocking a method within a class using Ruby's MiniTest::Mock and stub feature and it's driving me insane. What I am trying to do is set up a way to get an access token by calling a Ruby API which will get the actual access token from a 3rd party site.
This is the class all work will be done in.
class ThisClass
attr_reader :hauler
def initialize(hauler)
#hauler = hauler
end
def get_access_token
access_token = Rails.cache.read("access_token_#{hauler.id}")
if access_token.blank?
access_token = ext_access_token
Rails.cache.write("access_token_#{#hauler.id}", access_token, { expires_in: 3600 })
end
access_token
end
def ext_access_token
# call to external url to get access_token
# Successful response will be { "data": { "authToken": "new-token"} }"
url = URI.parse("http://www.fake-login.com/auth/sign_in")
res = Net::HTTP.post_form(url, "userName" => #hauler[:client_id], "password" => #hauler[:client_secret])
json_response = JSON.parse(res.body)
json_response["data"]["authToken"]
end
end
The test is as follows
class ThisClassTest < ActiveSupport::TestCase
test "Get Access Token" do
hauler = haulers(:one)
tc = ThisClass.new(hauler)
mock_client = MiniTest::Mock.new
mock_client.expect :ext_access_token, "\"{ \"data\": { \"authToken\": \"new-token\"} }\""
ThisClass.stub(:ext_access_token, mock_client) do
puts tc.get_access_token
end
assert_equal true, true
end
end
When I run my tests, I get the following error
Error:
ThisClassTest#test_Get_Access_Token:
NameError: undefined method `ext_access_token' for class `ThisClass'
I'm clearly doing something wrong since all I want is for the ext_access_token method to return the same data string so I can run logic against it, but very much failing. ThisClass is fairly simplistic but outlines the setup I'll be going with moving forward for more complex methods based on the return from the external site.
The test can't find ext_access_token method because it's looking for a class method on the ThisClass, rather than an instance method.
So what you need is something like
tc.stub :ext_access_token, mock_client do
puts tc.get_access_token
end

Django rest auth with Allauth

I have implemented django rest auth with Allauth and its working fine if I login through google access_token but there is a case when some client device need to login by google id_token.
I am getting error if I use id_token instead of access_token
{
"non_field_errors": [
"Incorrect value"
]
}
please help me out
Update your files like
../allauth/socialaccount/providers/google/provider.py:
class GoogleProvider(OAuth2Provider):
....
def extract_uid(self, data):
try:
return str(data['id'])
except KeyError:
return str(data['user_id'])
../allauth/socialaccount/providers/google/views.py:
class GoogleOAuth2Adapter(OAuth2Adapter):
provider_id = GoogleProvider.id
access_token_url = 'https://accounts.google.com/o/oauth2/token'
authorize_url = 'https://accounts.google.com/o/oauth2/auth'
profile_url = 'https://www.googleapis.com/oauth2/v1/userinfo'
token_url = 'https://www.googleapis.com/oauth2/v1/tokeninfo'
def complete_login(self, request, app, token, **kwargs):
if 'rest-auth/google' in request.path:
print('rest-auth api')
# /api/rest-auth/google
# but not for website login with google
resp = requests.get(self.token_url,
params={'id_token': token.token,
'alt': 'json'})
else:
print('else else rest-auth api')
resp = requests.get(self.profile_url,
params={'access_token': token.token,
'alt': 'json'})
resp.raise_for_status()
extra_data = resp.json()
login = self.get_provider() \
.sociallogin_from_response(request,
extra_data)
return login
oauth2_login = OAuth2LoginView.adapter_view(GoogleOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(GoogleOAuth2Adapter)
For using id_token you will get only these fileds (access_type, audience, email, email_verified, expires_in, issued_at, issued_to, issuer, nonce, scope, user_id, verified_email). So if your user table required phone and name you can set the to empty name='' etc. For this you can use the following code.
Set user model required fields to empty for covering id_token case
It depends upon your user model, in my case we need both phone and name so I have set them empty. If you don't do this you will get failed constraints errors.
../allauth/socialaccount/providers/base.py
class Provider(object):
def sociallogin_from_response(self, request, response):
....
common_fields = self.extract_common_fields(response)
common_fields['name'] = common_fields.get('name', '')
common_fields['phone'] = common_fields.get('phone', '')
common_fields['username'] = uid
....
I have set the username to user id obtained from social platform api. Later I am forcing user to update its details (username, name, phone etc).

Okta api python sdk throwing json error

I'm trying to create a user with the python sdk. When I run my script, I get the following error:
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/sitepackages/oktasdk-python/okta/framework/ApiClient.py", line 53, in post
if self.__check_response(resp, attempts):
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/sitepackages/oktasdk-python/okta/framework/ApiClient.py", line 88, in __check_response
raise OktaError(json.loads(resp.text))
okta.framework.OktaError.OktaError: The request body was not well-formed: Could not read JSON
Here is a snippet of my code:
from okta.UsersClient import UsersClient
from collections import namedtuple
def main():
create_okta_user()
def create_okta_user():
usersClient = UsersClient("https://example.okta.com", "0d0d0dexamplekey")
User = namedtuple("User", ["login", "email", "firstName", "lastName"], verbose=False, rename=False)
user = User(login="test#example.com",
email="test#example.com",
firstName="user",
lastName="tester")
usersClient.create_user(user, activate=False)
#usersClient.activate_user(user)
main()
It looks like you're trying to use a namedtuple, which is serialized to a json list, not an object.
Try using the User model like this:
from okta import UsersClient
from okta.models.user import User
def main():
create_okta_user()
def create_okta_user():
usersClient = UsersClient("https://example.okta.com", "0d0d0dexamplekey")
user = User(login="test#example.com",
email="test#example.com",
firstName="user",
lastName="tester")
user = usersClient.create_user(user, activate=False)
#usersClient.activate_user(user)
main()
http://developer.okta.com/docs/sdk/core/python_api_sdk/quickstart.html#create-a-user

Shared state between WebSocketHandler and RequestHandler

I am writing chat app and I need session data in my websocket handler. Problem is that login and logout is done by AJAX request, and updating/clearing cookie cannot be seen by websocket handler - it sees only state from the time website was initially rendered. But it cannot see, when cookie is changed by AJAX request. Do you have any idea, how this can be implemented?
import json
import tornado.web
import tornado.websocket
class BaseHandler(object):
#property
def db(self):
return self.application.db
def get_current_user(self):
id = self.get_secure_cookie('user')
user = self.db.get_user_by_id(id) if id else ''
return user
class JsonHandler(BaseHandler, tornado.web.RequestHandler):
def write(self, response):
if response:
response = json.dumps(response)
TemplateHandler.write(self, response)
#property
def body(self):
return json.loads(self.request.body.decode())
class WebSocketHandler(BaseHandler, tornado.websocket.WebSocketHandler):
pass
class Login(JsonHandler):
def post(self):
login = self.body.get('login')
password = self.body.get('password')
user = self.db.validate_user(login, password)
if user:
self.set_secure_cookie('user', str(user['id']))
self.write(user)
else:
raise tornado.web.HTTPError(401)
class Logout(JsonHandler):
def post(self):
self.clear_cookie('user')
self.write('')
class WebSocket(WebSocketHandler):
clients = set()
def open(self):
WebSocket.clients.add(self)
def on_close(self):
WebSocket.clients.remove(self)
def on_message(self, message):
# how to use method self.get_current_user()
# it uses self.get_secure_cookie('user')
# but it is not updated dynamically by Login and Logout handlers
# because websocket does not share state with them
for client in WebSocket.clients:
client.write_message(message)

Pylons, FormEncode and external validation

I'm building a web frontend to a server-side application, using Pylons 1.0.
Right now I'm writing the first form, and I'm facing a problem concerning validation.. Using FormEncode and the #validate decorator I can easily validate the user input from a client-side perspective, but when I submit the data to the server, it may perform additional checks and eventually throw back exceptions that I need to show to the user.
My question: is there a concise way to integrate/emulate this exception handling into the FormEncode/validate flow? For example, redisplay the form with filled fields and an error message, as would happen if the exception had come from the #validate itself?
Here's what I have at the moment:
def edit(self, id):
return render('/edit_user.mako')
#validate(schema=form.UserForm(), form="edit")
def add_user(self):
if request.POST:
u = helpers.load_attributes(User(), self.form_result)
try:
model.save_to_server(u)
except MyBaseException, exc:
helpers.flash(unicode(exc))
return self.edit()
In this way, in case of a server-side exception I can see the "flash" message but the form of course will have empty fields :/
I like to implement:
from formencode import htmlfill
def create(self):
if request.params:
try:
Post.validate(request.paramse)
post = helpers.load_attributes(Post(), request.params)
model.save_to_server(post)
flash('OK', 'success')
redirect(...)
except InvalidException as e:
for key, message in e.unpack_errors().iteritems():
flash(message, 'error')
return htmlfill.render(render('/blogs/create.html'), request.params)
where my Post.validate:
#staticmethod
def validate(data):
schema = PostSchema()
schema.to_python(data)
In this way, if is the first time (request.params empty) html fills form with nothing, when user send datas html fills form with request.params
Another way (inspired by this answer) is to write a decorator similar to #validate that would catch the desired exceptions and use htmlfill to display their message:
def handle_exceptions(form):
def wrapper(func, self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except MyBaseException, e:
request = self._py_object.request
errors = { "exception" : unicode(e) }
params = request.POST
decoded = params.mixed()
request.environ['REQUEST_METHOD'] = 'GET'
self._py_object.tmpl_context.form_errors = errors
request.environ['pylons.routes_dict']['action'] = form
response = self._dispatch_call()
# If the form_content is an exception response, return it
if hasattr(response, '_exception'):
return response
htmlfill_kwargs2 = {}
htmlfill_kwargs2.setdefault('encoding', request.charset)
return htmlfill.render(response, defaults=params, errors=errors,
**htmlfill_kwargs2)
return decorator(wrapper)
The decorator would be used like:
#handle_exceptions("edit")
#validate(schema=form.UserForm(), form="edit")
def add_user(self):
if request.POST:
u = helpers.load_attributes(User(), self.form_result)
model.save_to_server(u)

Resources