import imghdr
import sshpubkeys
import tornado.web
+import urllib.parse
from .. import countries
self.redirect("/users/%s" % account.uid)
+class SSODiscourse(auth.CacheMixin, base.BaseHandler):
+ def _get_discourse_params(self):
+ # Fetch Discourse's parameters
+ sso = self.get_argument("sso")
+ sig = self.get_argument("sig")
+
+ # Decode payload
+ try:
+ return self.accounts.decode_discourse_payload(sso, sig)
+
+ # Raise bad request if the signature is invalid
+ except ValueError:
+ raise tornado.web.HTTPError(400)
+
+ def _redirect_user_to_discourse(self, account, nonce, return_sso_url):
+ """
+ Redirects the user back to Discourse passing some
+ attributes of the user account to Discourse
+ """
+ args = {
+ "nonce" : nonce,
+ "external_id" : account.uid,
+
+ # Pass email address
+ "email" : account.email,
+ "require_activation" : "false",
+
+ # More details about the user
+ "username" : account.uid,
+ "name" : "%s" % account,
+
+ # Avatar
+ "avatar_url" : account.avatar_url(),
+ "avatar_force_update" : "true",
+
+ # Send a welcome message
+ "suppress_welcome_message" : "false",
+
+ # Group memberships
+ "admin" : "true" if account.is_admin() else "false",
+ "moderator" : "true" if account.is_staff() else "false",
+ }
+
+ # Format payload and sign it
+ payload = self.accounts.encode_discourse_payload(**args)
+ signature = self.accounts.sign_discourse_payload(payload)
+
+ qs = urllib.parse.urlencode({
+ "sso" : payload,
+ "sig" : signature,
+ })
+
+ # Redirect user
+ self.redirect("%s?%s" % (return_sso_url, qs))
+
+ @base.ratelimit(minutes=24*60, requests=100)
+ def get(self):
+ params = self._get_discourse_params()
+
+ # Redirect back if user is already logged in
+ if self.current_user:
+ return self._redirect_user_to_discourse(self.current_user, **params)
+
+ # Otherwise the user needs to authenticate
+ # XXX
+ raise tornado.web.HTTPError(401)
+
+
class NewAccountsModule(ui_modules.UIModule):
def render(self, days=14):
t = datetime.datetime.utcnow() - datetime.timedelta(days=days)