def post(self): """ Synchronize user details and return authentication url. Important: Email addresses need to be validated by external site. """ request = self.request sso_key = request.validated['sso_key'] sso_external_id = request.validated['sso_external_id'] user = request.validated['sso_user'] if user is None: # create new user user = User( username=request.validated['username'], name=request.validated['name'], forum_username=request.validated['forum_username'], email=request.validated['email'], email_validated=True, # MUST be validated by external site lang=request.validated['lang'], password=generate_token() # random password ) # directly create the user profile, the document id of the profile # is the user id lang = user.lang user.profile = UserProfile( categories=['amateur'], locales=[DocumentLocale(lang=lang, title='')], ) DBSession.add(user) DBSession.flush() if sso_external_id is None: sso_external_id = SsoExternalId( domain=sso_key.domain, external_id=request.validated['external_id'], user=user, ) DBSession.add(sso_external_id) sso_external_id.token = generate_token() sso_external_id.expire = sso_expire_from_now() client = get_discourse_client(request.registry.settings) discourse_userid = call_discourse(get_discourse_userid, client, user.id) if discourse_userid is None: call_discourse(client.sync_sso, user) discourse_userid = client.get_userid(user.id) # From cache # Groups are added to discourse, not removed group_ids = [] discourse_groups = None groups = request.validated['groups'] or '' for group_name in groups.split(','): if group_name == '': continue group_id = None if discourse_groups is None: discourse_groups = call_discourse(client.client.groups) group_id = None for discourse_group in discourse_groups: if discourse_group['name'] == group_name: group_id = discourse_group['id'] if group_id is None: # If group is not found, we ignore it as we want to return # a valid token for user authentication pass else: group_ids.append(group_id) for group_id in group_ids: call_discourse(client.client.add_user_to_group, group_id, discourse_userid) return { 'url': '{}/sso-login?no_redirect&{}'.format( request.registry.settings['ui.url'], urlencode({'token': sso_external_id.token})) }