Thursday, December 7, 2017¶
Third-party authentication providers¶
I worked on #1197 (Add support for authentication via OpenID, Google or Facebook). This is actually the same as #1275 (Authenticate using Belgian ID card). See also Wednesday, October 18, 2017 and Sunday, October 22, 2017.
As mentioned earlier, the question is: how to integrate Python Social Auth to Lino at the web interface level?
I read Vitor Freita’s blog entry How to Add Social Login to Django. A great document. It helps us understand the difference between Lino and Django: as a Lino application developer I do not want to write this kind of things!
Which means that as a Lino core developer I must write a generic solution. This is what I did today. The first proof of concept works like a charm!
Summary of code changes:
Third-party Authentication support now works. It is just a new site attribute
social_auth_backends
.A working example is in the
lino_book.projects.team
demo project. Anybody can test the social auth functionality on your machine by doing:$ go team $ python manage.py prep $ runserver
For this to work out of the box, I created an application Social Auth Tester on GitHub (that link works only if you are logged in on GH and have permission to see this page, but here is a screenshot:)
The client secret of that GitHub application not really secret anymore since it is stored in the
settings.py
of the team demo project (more exactly here). But anyway the Home page URL of the application is http://127.0.0.1:8000/ which means that it is being used only on a local machine.
Side effects:
The
objects
ofusers.User
is now able to create users.It is now possible to use a
lino.core.fields.HtmlBox
or alino.core.fields.DisplayField
as parameter fields of an action. The trick is to specify a default value for them.The
SignInWithSocialAuth
action (inlino.modlib.users.actions
) is the first usage example.But we don’t currently use that action because after getting the new possibility to work, I discovered that it probably isn’t necessary, at least not for social authentication. It is more intuitive to leave the SignIn action dialog as it is and to add these social auth links after the “You will now probably want to sign in” message in (
admin_main.html
)
TODO:
Port my changes in
lino.modlib.extjs
(those in elems.py) also to extjs6. For testing it, uncomment the lines inlino.modlib.users.models
which install theSignInWithSocialAuth
action.Try it also with Facebook, Google and Belgian eID
Actually we might implement the feature as a plugin (
lino.modlib.social_auth
) and not as a Site attribute. That would be more Django-like. But OTOH a Site attribute is so easy to use and to configure! I am probably going to remove the plugin.
Here are some error messages I saw today when developing this:
AttributeError: ‘BaseUserManager’ object has no attribute ‘create_user’ in http://127.0.0.1:8000/oauth/complete/github/?redirect_state=UynmZVZAzLYd0dbsxjioBCOMt1BFH6h5&code=32e730c23e0989862b2d&state=UynmZVZAzLYd0dbsxjioBCOMt1BFH6h5
A hangout with Tonis for #352¶
#352 (ParameterStore of LayoutHandle for ParamsLayout X
expects a list of Y values but got N) is related to the
is_on_main_actor
attribute introduced on Monday, July 31, 2017. The
following test helped us to explore the problem. It is now also in the
specs (in About rendering action URLs).
>>> from lino import startup
>>> startup('lino_book.projects.team.settings.demo')
>>> from lino.api.doctest import *
>>> A = rt.models.clocking.SessionsByTicket
>>> obj = rt.models.tickets.Ticket.objects.get(pk=1)
>>> ses = rt.login('robin', renderer=settings.SITE.kernel.default_renderer)
>>> ses.is_on_main_actor
True
>>> ar = rt.models.tickets.Tickets.request(parent=ses)
>>> ar.is_on_main_actor
True
>>> ar.actor
lino_xl.lib.tickets.ui.Tickets
>>> html = A.get_slave_summary(obj, ar)
>>> print(E.tostring(html))
<div class="htmlText"><p><a href="javascript:Lino.tickets.Tickets.start_session(null,true,1,{ })" style="text-decoration:none">▶</a></p><p>Total 0:00 hours.</p><p>Active sessions: <span><a href="javascript:Lino.clocking.SessionsByTicket.detail.run(null,{ "record_id": 1 })">Jean since 09:00:00</a> <a href="javascript:Lino.clocking.Sessions.end_session(null,true,1,{ })" style="text-decoration:none">■</a></span>, <span><a href="javascript:Lino.clocking.SessionsByTicket.detail.run(null,{ "record_id": 5 })">Luc since 09:00:00</a> <a href="javascript:Lino.clocking.Sessions.end_session(null,true,5,{ })" style="text-decoration:none">■</a></span>, <span><a href="javascript:Lino.clocking.SessionsByTicket.detail.run(null,{ "record_id": 9 })">Mathieu since 09:00:00</a> <a href="javascript:Lino.clocking.Sessions.end_session(null,true,9,{ })" style="text-decoration:none">■</a></span></p></div>
>>> soup = BeautifulSoup(E.tostring(html), 'lxml')
>>> # print(soup.body.prettify())
>>> links = soup.body.find_all('a')
>>> len(links)
7
>>> for lnk in links:
... print(lnk['href'])
javascript:Lino.tickets.Tickets.start_session(null,true,1,{ })
javascript:Lino.clocking.Sessions.detail.run(null,{ "record_id": 1 })
javascript:Lino.clocking.Sessions.end_session(null,false,1,{ })
javascript:Lino.clocking.Sessions.detail.run(null,{ "record_id": 5 })
javascript:Lino.clocking.Sessions.end_session(null,false,5,{ })
javascript:Lino.clocking.Sessions.detail.run(null,{ "record_id": 9 })
javascript:Lino.clocking.Sessions.end_session(null,false,9,{ })
A bug for Tonis¶
Tonis, after our meeting I saw another reproducible bug in
lino_book.projects.tera1
which I recommend you to have a look
at:
sign in as robin
got to Patient Bernd BRECHT
Activate the “Family” tab. In the “Households memberships” panel you see:
BRECHT Bernd (177) is☐ Head of household in Bernd & Inge Brecht-Radermacher Isolated (186)Create a household : Married couple / Divorced couple / Factual household / Legal cohabitation / Isolated / OtherClick on the ☐.
This should actually mark that household as primary, causing the ☐ to change into a ☑.
You get an error mesage “Bad request. IndexError: list index out of range “