I would like to know id it’s possible to make some categories restricted to authenticated users. On my old indico (1.1) installation I had a cron script putting all users to a ‘everybody’ group and restrict to this group, but this seems absurd. Is there a better way in 2.0 ?
I have restricted authentication to ip’s inside my network, so I’m not concerned about people registering to peek in my restricted categories.
Unfortunately there’s no “all users” kind of ACL entry. But writing a plugin that populates a group with everyone would be quite easy. You can even hook into the users.registered signal to add them automatically when an account is created instead of running a cronjob going over all users.
Use indico shell to get a python shell in the Indico environment. Some parts are pretty dependent on specific import order (models being imported first) and our code takes care of doing this.
I wrote the following small (test) plugin, and activated it in my configuration, but nothing happens when a new user registers : does it mean the signal is not well connected ?
from __future__ import unicode_literals
from indico.core import signals
from indico.core.plugins import IndicoPlugin, IndicoPluginBlueprint
from indico.core.db import db
from indico.modules.groups.models.groups import LocalGroup
class DefaultGroupPlugin(IndicoPlugin):
"""Default Group
This plugin add all new users to a default group
to mimic an 'authenticated' ACL
"""
def init(self):
super(DefaultGroupPlugin, self).init()
self.connect(signals.users.registered, self._add_user_to_defgroup)
def get_blueprints(self):
return IndicoPluginBlueprint(self.name, __name__)
def _add_user_to_defgroup(self, sender, **kwargs):
defgroup = LocalGroup.query.filter("name = 'Everybody'").first()
if defgroup:
defgroup.members.add(sender)
db.session.commit()
return 0
Ideally you add a plugin setting (quite easy to do, look at other plugins the define a settings form) where you enter the ID of that group. Dropdown would work as well, but it’s more tricky so maybe overkill for something as simple as this.
If you passed a string to .filter() it’ll evaluate to WHERE true, i.e. no filtering was done. Probably you had only one group or the group was the first one returned by the query so it worked by coincidence.
Why create new users all the time? You can trigger the signal manually from indico shell using signals.users.registered.send(user)
Anyway, those users aren’t linked to anything, so db.session.delete(user) in the shell (followed by a commit) may work.
We are currently considering allowing people to login using their CERN account, in order to make life easier for speakers in conferences.
However I don’t know how it will play with the above plugin: will ‘external’ users be put in the group when they first login ? I would like to avoid that: what property of the user should I check in my plugin to exclude external users ?
Update: I was able to distinguish between local and SSO users by using the local_identities user property.
However, this does not prevent an external user to use the ‘create local account’ feature later, which I guess would trigger a ‘registered’ event and add them to the default group. Is there a way to prevent that from happening ?
“Create local account” is available whenever local accounts are not disabled. Unfortunately there’s no easy/clean way to change this behavior through a plugin.
The not-so-clean way: Monkeypatch indico.modules.auth.controllers.RHAccounts with a subclass of that class where _handle_add_local_account flashes an error message and doesn’t do anything else. Then the UI to create a local account will still be there but at least you can show a message telling people why they cannot create one.
I guess that such a modification would not survive through updates, though. Also, it’s a bit above my abilities ;).
Another option in my case would be to enable registration moderation, but it would mean that I would check for each request if that’s a local or external account, which is easy, but not convenient.
edit: I just realized you probably suggested to monkey-patch inside a plugin, which would indeed survive updates. The only remaining obstavle in my own abilities then.
Moderation applies only to new registration, not to someone adding a local account to their existing Indico account.
It is only called when an existing user adds a local account.
Yeah, but in the end it makes no difference. And IMHO subclassing is cleaner:
from flask import flash
from indico.modules.auth import controllers as auth_controllers
class RHAccounts(auth_controllers.RHAccounts):
def _handle_add_local_account(self, form):
flash('Sorry, adding local accounts is disabled.', 'warning')
# inside init() of your plugin:
auth_controllers.RHAccounts = RHAccounts