Wednesday, October 25, 2017

Separate “coachings” from “clients”

While adapting the test suites after yesterday’s changes for #2115, I realized that it is time to split the coachings plugin into “coachings per se” and “clients”. And Lino Avanti uses only clients, not coachings. This fixes some less visible problems, e.g. the irritating unused menu entries for coachings in Lino Avanti.

Database migration: The models ClientContact and ClientContactType, and the choicelist ClientStates were moved from lino_xl.lib.coachings to lino_xl.lib.clients.

After these changes I had -as expected- some work to repair the test suites for Lino Welfare. For example at some moment there were only 23 instead of 58 clients in lino_welfare.projects.eupen. This was actually because of the default default value of the client_state field (see Monday, October 9, 2017).

Login via Google+

I continued on #1275. I reached the point where Google asks me to choose my account.

I saw this nice RuntimeError:

You called this URL via POST, but the URL doesn’t end in a slash and you have APPEND_SLASH set. Django can’t redirect to the slash URL while maintaining POST data. Change your form to point to localhost:8000/complete/google-plus/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.

And later, shortly after fixing above error:

AjaxExceptionResponse HTTPError: 403 Client Error: Forbidden for url:

in request POST /complete/google-plus/ (data: <QueryDict: {u'id_token': [u'...)
  File "/site-packages/django/core/handlers/", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/site-packages/django/views/decorators/", line 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/site-packages/django/views/decorators/", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/site-packages/social_django/", line 50, in wrapper
    return func(request, backend, *args, **kwargs)
  File "/site-packages/social_django/", line 32, in complete
    redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
  File "/site-packages/social_core/", line 41, in do_complete
    user = backend.complete(user=user, *args, **kwargs)
  File "/site-packages/social_core/backends/", line 40, in complete
    return self.auth_complete(*args, **kwargs)
  File "/site-packages/social_core/", line 252, in wrapper
    return func(*args, **kwargs)
  File "/site-packages/social_core/backends/", line 144, in auth_complete
    return self.do_auth(token, response=response, *args, **kwargs)
  File "/site-packages/social_core/", line 252, in wrapper
    return func(*args, **kwargs)
  File "/site-packages/social_core/backends/", line 403, in do_auth
    data = self.user_data(access_token, *args, **kwargs)
  File "/site-packages/social_core/backends/", line 59, in user_data
    'alt': 'json'
  File "/site-packages/social_core/backends/", line 233, in get_json
    return self.request(url, *args, **kwargs).json()
  File "/site-packages/social_core/backends/", line 229, in request
  File "/site-packages/requests/", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)

[25/Oct/2017 14:09:20] "POST /complete/google-plus/ HTTP/1.1" 400 1321

I didn’t yet understand what’s happening there… In the debugger I saw that the X-CSRFToken was null, maybe that’s the problem? But theoretically it is being set by the general beforerequest handler defined in linoweb.js

Ext.Ajax.on('beforerequest', function (conn, options) {
   if (!(/^http:.*/.test(options.url) || /^https:.*/.test(options.url))) {
     if (typeof(options.headers) == "undefined") {
       options.headers = {'X-CSRFToken': Ext.util.Cookies.get('csrftoken')};
     } else {
       options.headers.extend({'X-CSRFToken': Ext.util.Cookies.get('csrftoken')});
}, this);

To be continued…