def propertysheet(self):
     if self._sheet is not None:
         return self._sheet
     # build sheet from identities
     pdata = dict(id=self.userid)
     cfgs_providers = authomatic_cfg()
     for provider_name in cfgs_providers:
         identity = self.identity(provider_name)
         if identity is None:
             continue
         logger.debug(identity)
         cfg = cfgs_providers[provider_name]
         for akey, pkey in cfg.get('propertymap', {}).items():
             # Always search first on the user attributes, then on the raw
             # data this guaratees we do not break existing configurations
             ainfo = identity.get(akey, identity['data'].get(akey, None))
             if ainfo is None:
                 continue
             if isinstance(pkey, dict):
                 for k, v in pkey.items():
                     pdata[k] = ainfo.get(v)
             else:
                 pdata[pkey] = ainfo
     self._sheet = UserPropertySheet(**pdata)
     return self._sheet
Пример #2
0
 def __call__(self):
     cfg = authomatic_cfg()
     if cfg is None:
         return "Authomatic is not configured"
     if not (
         ISiteRoot.providedBy(self.context) or
         INavigationRoot.providedBy(self.context)
     ):
         # callback url is expected on either navigationroot or site root
         # so bevor going on redirect
         root = api.portal.get_navigation_root(self.context)
         self.request.response.redirect(
             "{0}/authomatic-handler/{1}".format(
                 root.absolute_url(),
                 getattr(self, 'provider', '')
             )
         )
         return "redirecting"
     if not hasattr(self, 'provider'):
         return self.template()
     if self.provider not in cfg:
         return "Provider not supported"
     if not self.is_anon:
         if self.provider in self._provider_names:
             raise ValueError(
                 'Provider {0} is already connected to current '
                 'user.'.format(self.provider)
             )
         # TODO: some sort of CSRF check might be needed, so that
         #       not an account got connected by CSRF. Research needed.
         pass
     auth = Authomatic(
         cfg,
         secret=authomatic_settings().secret.encode('utf8')
     )
     result = auth.login(
         ZopeRequestAdapter(self),
         self.provider
     )
     if not result:
         logger.info('return from view')
         # let authomatic do its work
         return
     if result.error:
         return result.error.message
     display = cfg[self.provider].get('display', {})
     provider_name = display.get('title', self.provider)
     if not self.is_anon:
         # now we delegate to PAS plugin to add the identity
         self._add_identity(result, provider_name)
         self.request.response.redirect(
             "{0}".format(self.context.absolute_url())
         )
     else:
         # now we delegate to PAS plugin in order to login
         self._remember_identity(result, provider_name)
         self.request.response.redirect(
             "{0}/login_success".format(self.context.absolute_url())
         )
     return "redirecting"
Пример #3
0
 def propertysheet(self):
     if self._sheet is not None:
         return self._sheet
     # build sheet from identities
     pdata = dict(id=self.userid)
     cfgs_providers = authomatic_cfg()
     for provider_name in cfgs_providers:
         identity = self.identity(provider_name)
         if identity is None:
             continue
         logger.debug(identity)
         cfg = cfgs_providers[provider_name]
         for akey, pkey in cfg.get('propertymap', {}).items():
             # Always search first on the user attributes, then on the raw
             # data this guaratees we do not break existing configurations
             ainfo = identity.get(akey, identity['data'].get(akey, None))
             if ainfo is None:
                 continue
             if isinstance(pkey, dict):
                 for k, v in pkey.items():
                     pdata[k] = ainfo.get(v)
             else:
                 pdata[pkey] = ainfo
     self._sheet = UserPropertySheet(**pdata)
     return self._sheet
Пример #4
0
 def __call__(self):
     cfg = authomatic_cfg()
     if cfg is None:
         return "Authomatic is not configured"
     if not (
         ISiteRoot.providedBy(self.context)
         or INavigationRoot.providedBy(self.context)
     ):
         # callback url is expected on either navigationroot or site root
         # so bevor going on redirect
         root = api.portal.get_navigation_root(self.context)
         self.request.response.redirect(
             "{0}/authomatic-handler/{1}".format(
                 root.absolute_url(), getattr(self, 'provider', '')
             )
         )
         return "redirecting"
     if not hasattr(self, 'provider'):
         return self.template()
     if self.provider not in cfg:
         return "Provider not supported"
     if not self.is_anon:
         if self.provider in self._provider_names:
             raise ValueError(
                 'Provider {0} is already connected to current '
                 'user.'.format(self.provider)
             )
         # TODO: some sort of CSRF check might be needed, so that
         #       not an account got connected by CSRF. Research needed.
         pass
     secret = authomatic_settings().secret
     if six.PY2 and isinstance(secret, six.text_type):
         secret = secret.encode('utf8')
     auth = Authomatic(cfg, secret=secret)
     result = auth.login(ZopeRequestAdapter(self), self.provider)
     if not result:
         logger.info('return from view')
         # let authomatic do its work
         return
     if result.error:
         return result.error.message
     display = cfg[self.provider].get('display', {})
     provider_name = display.get('title', self.provider)
     if not self.is_anon:
         # now we delegate to PAS plugin to add the identity
         self._add_identity(result, provider_name)
         self.request.response.redirect(
             "{0}".format(self.context.absolute_url())
         )
     else:
         # now we delegate to PAS plugin in order to login
         self._remember_identity(result, provider_name)
         if api.env.plone_version() < '5.2':
             self.request.response.redirect(
                 "{0}/login_success".format(self.context.absolute_url())
             )
         else:
             self.request.response.redirect(self.context.absolute_url())
     return "redirecting"
Пример #5
0
 def providers(self) -> dict:
     """Return Authomatic providers."""
     providers = self._providers
     if not providers:
         try:
             providers = authomatic_cfg()
         except KeyError:
             # Authomatic is not configured
             providers = {}
         except ModuleNotFoundError:
             # Bad configuration
             providers = {}
     return providers
Пример #6
0
    def __call__(self):
        cfg = authomatic_cfg()
        if cfg is None:
            return "Authomatic is not configured"
        if not (ISiteRoot.providedBy(self.context)
                or INavigationRoot.providedBy(self.context)):
            # callback url is expected on either navigationroot or site root
            # so bevor going on redirect
            root = api.portal.get_navigation_root(self.context)
            self.request.response.redirect("{}/authomatic-handler/{}".format(
                root.absolute_url(), getattr(self, "provider", "")))
            return "redirecting"
        if not getattr(self, "provider", None):
            return self.template()
        if self.provider not in cfg:
            return "Provider not supported"
        if not self.is_anon:
            if self.provider in self._provider_names:
                logger.warn(
                    "Provider %s is already connected to current "
                    "user.", self.provider)
                return self._redirect()
            # TODO: some sort of CSRF check might be needed, so that
            #       not an account got connected by CSRF. Research needed.
            pass
        secret = authomatic_settings().secret
        auth = Authomatic(cfg, secret=secret)
        result = auth.login(ZopeRequestAdapter(self), self.provider)
        if not result:
            logger.info("return from view")
            # let authomatic do its work
            return
        if result.error:
            return result.error.message
        display = cfg[self.provider].get("display", {})
        provider_name = display.get("title", self.provider)
        if not self.is_anon:
            # now we delegate to PAS plugin to add the identity
            self._add_identity(result, provider_name)
        else:
            # now we delegate to PAS plugin in order to login
            self._remember_identity(result, provider_name)

        return self._redirect()
Пример #7
0
 def providers(self):
     cfgs = authomatic_cfg()
     if not cfgs:
         raise ValueError("Authomatic configuration has errors.")
     for identifier, cfg in cfgs.items():
         entry = cfg.get('display', {})
         cssclasses = entry.get('cssclasses', {})
         record = {
             'identifier': identifier,
             'title': entry.get('title', identifier),
             'iconclasses': cssclasses.get(
                 'icon', 'glypicon glyphicon-log-in'
             ),
             'buttonclasses': cssclasses.get(
                 'button', 'plone-btn plone-btn-default'
             ),
             'as_form': entry.get('as_form', False),
         }
         yield record
Пример #8
0
 def providers(self):
     cfgs = authomatic_cfg()
     if not cfgs:
         raise ValueError("Authomatic configuration has errors.")
     for identifier, cfg in cfgs.items():
         entry = cfg.get("display", {})
         cssclasses = entry.get("cssclasses", {})
         record = {
             "identifier":
             identifier,
             "title":
             entry.get("title", identifier),
             "iconclasses":
             cssclasses.get("icon", "glypicon glyphicon-log-in"),
             "buttonclasses":
             cssclasses.get("button", "plone-btn plone-btn-default"),
             "as_form":
             entry.get("as_form", False),
         }
         yield record
Пример #9
0
    def list_plugins() -> List[Dict]:
        """List all configured Authomatic plugins.

        :returns: List of login options.
        """
        try:
            providers = authomatic_cfg()
        except KeyError:
            # Authomatic is not configured
            providers = {}
        plugins = []
        for provider_id, provider in providers.items():
            entry = provider.get("display", {})
            title = entry.get("title", provider_id)
            plugins.append(
                dict(
                    id=provider_id,
                    plugin="authomatic",
                    title=title,
                ))
        return plugins
Пример #10
0
 def providers(self):
     cfgs = authomatic_cfg()
     if not cfgs:
         raise ValueError("Authomatic configuration has errors.")
     for identifier, cfg in cfgs.items():
         entry = cfg.get('display', {})
         cssclasses = entry.get('cssclasses', {})
         record = {
             'identifier': identifier,
             'title': entry.get('title', identifier),
             'iconclasses': cssclasses.get(
                 'icon',
                 'glypicon glyphicon-log-in'
             ),
             'buttonclasses': cssclasses.get(
                 'button',
                 'plone-btn plone-btn-default'
             ),
             'as_form': entry.get('as_form', False),
         }
         yield record
 def credentials(self):
     cfg = authomatic_cfg()
     return Credentials.deserialize(cfg, self.user['credentials'])
Пример #12
0
 def _provider_names(self):
     cfgs = authomatic_cfg()
     if not cfgs:
         raise ValueError("Authomatic configuration has errors.")
     return cfgs.keys()
Пример #13
0
 def credentials(self):
     cfg = authomatic_cfg()
     return Credentials.deserialize(cfg, self.user['credentials'])
Пример #14
0
 def _provider_names(self):
     cfgs = authomatic_cfg()
     if not cfgs:
         raise ValueError("Authomatic configuration has errors.")
     return cfgs.keys()
Пример #15
0
    def __call__(self):

        # callback url is expected on site root
        if not ISiteRoot.providedBy(self.context):
            root = api.portal.get()
            self.request.response.redirect("{0}/authomatic-handler/{1}".format(
                root.absolute_url(), getattr(self, 'provider', '')))
            return "redirecting"

        self.authopas = authomatic_plugin()
        self.cfgs = authomatic_cfg()
        if self.cfgs is None:
            return "Authomatic is not configured"
        self.is_anon = api.user.is_anonymous()
        if not self.is_anon:
            self.user = api.user.get_current()
            self.user_providers = self.authopas._useridentities_by_userid.get(
                self.user.id).providers()

        # Validate provider
        if not hasattr(self, 'provider'):
            return self.template()
        if self.provider not in self.cfgs:
            return "Provider not supported"
        if not self.is_anon and self.provider in self.user_providers:
            action = self.request.form.get('action', None)
            if action == 'unlink':
                alsoProvides(self.request, IDisableCSRFProtection)
                self.authopas.remove_identity(self.user.id, self.provider)
                api.portal.show_message(
                    _('Unlink account with {provider} provider',
                      mapping={'provider': self.provider}), self.request)
                return self.template()
            #Any other action ?
            else:
                api.portal.show_message(
                    _('Provider {provider} is already connected to current user',
                      mapping={'provider': self.provider}), self.request)
                return self.template()

            # TODO: some sort of CSRF check might be needed, so that
            #       not an account got connected by CSRF. Research needed.

        #Authomatic login
        auth = Authomatic(self.cfgs,
                          secret=authomatic_settings().secret.encode('utf8'))
        result = auth.login(ZopeRequestAdapter(self), self.provider)
        if not result:
            logger.info('return from view')
            # let authomatic do its work
            return
        if result.error:
            return result.error.message
        # fetch provider specific user-data
        result.user.update()

        display = self.cfgs[self.provider].get('display', {})
        provider_name = display.get('title', self.provider)
        if not self.is_anon:
            # now we delegate to PAS plugin to add the identity
            self._add_identity(result, provider_name)
            self.request.response.redirect("{0}".format(
                self.context.absolute_url()))
        else:
            # now we delegate to PAS plugin in order to login
            self._remember_identity(result, provider_name)
            redirect = self.cfgs[self.provider].get(
                'redirect_url', "${portal_url}/login_success")
            redirect = redirect.replace("${portal_url}",
                                        api.portal.get().absolute_url())
            self.request.response.redirect(redirect)
        return "redirecting"
Пример #16
0
 def __call__(self):
     cfg = authomatic_cfg()
     if cfg is None:
         return "Authomatic is not configured"
     if not (ISiteRoot.providedBy(self.context)
             or INavigationRoot.providedBy(self.context)):
         # callback url is expected on either navigationroot or site root
         # so bevor going on redirect
         root = api.portal.get_navigation_root(self.context)
         self.request.response.redirect(
             "{0}/authomatic-handler/{1}{2}".format(
                 root.absolute_url(), getattr(self, 'provider', ''),
                 ('?' + self.request.QUERY_STRING
                  if self.request.QUERY_STRING else '')))
         return "redirecting"
     if not hasattr(self, 'provider'):
         return self.template()
     if self.provider not in cfg:
         return "Provider not supported"
     if not self.is_anon:
         if self.provider in self._provider_names:
             raise ValueError(
                 'Provider {0} is already connected to current '
                 'user.'.format(self.provider))
         # TODO: some sort of CSRF check might be needed, so that
         #       not an account got connected by CSRF. Research needed.
         pass
     auth = Authomatic(cfg,
                       secret=authomatic_settings().secret.encode('utf8'))
     additional_params = {}
     for key in ('came_from', 'next'):
         if key in self.request.form:
             additional_params[key] = self.request.form[key]
             # TODO: expire after 1800s (30m)
             # TODO: single cookie for next and came_from ?
             self.request.response.setCookie(
                 'authomatic_{0}'.format(key),
                 self.request.form[key],
                 http_only=True,
                 path=api.portal.get().absolute_url_path())
             del (self.request.form[key])
         # TODO: expire cookie(s) after successful login, not here.
         elif self.request.cookies.get('authomatic_{0}'.format(key)):
             additional_params[key] = self.request.cookies.get(
                 'authomatic_{0}'.format(key))
             self.request.response.expireCookie(
                 'authomatic_{0}'.format(key),
                 path=api.portal.get().absolute_url_path())
     result = auth.login(ZopeRequestAdapter(self), self.provider)
     if not result:
         logger.info('return from view')
         return
     if result.error:
         return result.error.message
     display = cfg[self.provider].get('display', {})
     provider_name = display.get('title', self.provider)
     if not self.is_anon:
         # now we delegate to PAS plugin to add the identity
         logger.info('add_identity %s', additional_params)
         self._add_identity(result, provider_name)
         self.request.response.redirect(
             additional_params.get('came_from',
                                   self.context.absolute_url()))
     else:
         # now we delegate to PAS plugin in order to login
         logger.info('remember_identity %s', additional_params)
         self._remember_identity(result, provider_name)
         if additional_params:
             self.request.response.redirect("{0}/logged_in?{1}".format(
                 self.context.absolute_url(), urlencode(additional_params)))
         else:
             self.request.response.redirect("{0}/login_success".format(
                 self.context.absolute_url()))
     return "redirecting"