示例#1
0
    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}))
        }