Example #1
0
    def get(self):
        code = self.get_argument('code')
        client = AsyncHTTPClient()
        # https://api.github.com/users/no13bus
        params = {
            'client_id': githubapi['CLIENT_ID'],
            'redirect_uri': githubapi['REDIRECT_URL'],
            'client_secret': githubapi['CLIENT_SECRET'],
            'code': code
        }
        url = url_concat("https://github.com/login/oauth/access_token", params)
        req = HTTPRequest(url=url, method="POST",headers={"Accept": "application/json"}, body='')
        res = yield client.fetch(req)
        resp_json = json.loads(res.body)
        token = resp_json['access_token']
        req_url = url_concat("https://api.github.com/user", {'access_token': token})
        req_user = HTTPRequest(url=req_url, method="GET")
        res_user = yield client.fetch(req_user)

        user_info = json.loads(res_user.body)
        username = user_info['login']
        avatar_url = user_info['avatar_url']
        user = yield self.db.user.find_one({'username': username})
        if not user:
            user_id = yield self.db.user.insert({'username': username, 'token': token, 'avatar_url': avatar_url})
            print user_id

        self.set_secure_cookie("token",token)
        self.set_secure_cookie("username",username)
        self.set_secure_cookie("avatar_url",avatar_url)
        self.redirect('/')
Example #2
0
  def post(self):
      self.set_secure_cookie("user", '', expires_days = -1)
      if self.get_argument("code", False):
          #print "Got code: %s url: %s" % (self.get_argument("code", False), self._url_)
          self.get_authenticated_user(
            redirect_uri=settings.canvas_page,
            client_id=settings.fb_appid,
            client_secret=settings.fb_secret,
            code=self.get_argument("code"),
            callback=self.async_callback(
              self.onAuth))
          return
      
#      self.authorize_redirect(redirect_uri=self._url_,
#                              client_id=settings.fb_appid,
#                              extra_params={"scope": "publish_stream,offline_access"})

      args = {
          "redirect_uri": settings.canvas_page,

          "client_id": settings.fb_appid,
          "scope": "publish_stream,offline_access"
        }
        
      print url_concat(self._OAUTH_AUTHORIZE_URL, args)
      self.write('<script> top.location.href = "' + url_concat(self._OAUTH_AUTHORIZE_URL, args) + '";</script>');
      self.finish()
Example #3
0
def fetch(url, method='GET', params=None, headers=None, cookies=None,
          data=None, streaming_callback=None, header_callback=None,
          connect_timeout=None, request_timeout=None):
    """Make an HTTP request and return a Future.

    This is mostly just a wrapper for tornado.httpclient, but adds support for
    sending cookies.

    Raises HTTPError and IOError.
    """
    if headers is None:
        headers = {}
    if params is not None:
        url = httputil.url_concat(url, params)
    if cookies is not None:
        # abuse SimpleCookie to escape our cookies for us
        simple_cookies = http.cookies.SimpleCookie(cookies)
        headers['cookie'] = '; '.join(val.output(header='')[1:]
                                      for val in simple_cookies.values())
    http_client = httpclient.AsyncHTTPClient()
    res = yield http_client.fetch(httpclient.HTTPRequest(
        httputil.url_concat(url, params), method=method,
        headers=httputil.HTTPHeaders(headers), body=data,
        streaming_callback=streaming_callback, header_callback=header_callback,
        connect_timeout=connect_timeout, request_timeout=request_timeout
    ))
    return res
Example #4
0
    def get(self, name, user_path):
        current_user = self.get_current_user()
        if current_user and current_user.name == name:
            # If people visit /user/:name directly on the Hub,
            # the redirects will just loop, because the proxy is bypassed.
            # Try to check for that and warn,
            # though the user-facing behavior is unchainged
            host_info = urlparse(self.request.full_url())
            port = host_info.port
            if not port:
                port = 443 if host_info.scheme == 'https' else 80
            if port != Server.from_url(self.proxy.public_url).port and port == self.hub.port:
                self.log.warning("""
                    Detected possible direct connection to Hub's private ip: %s, bypassing proxy.
                    This will result in a redirect loop.
                    Make sure to connect to the proxied public URL %s
                    """, self.request.full_url(), self.proxy.public_url)

            # logged in as correct user, spawn the server
            if current_user.spawner:
                if current_user.spawn_pending or current_user.proxy_pending:
                    # spawn has started, but not finished
                    self.statsd.incr('redirects.user_spawn_pending', 1)
                    html = self.render_template("spawn_pending.html", user=current_user)
                    self.finish(html)
                    return

                # spawn has supposedly finished, check on the status
                status = yield current_user.spawner.poll()
                if status is not None:
                    if current_user.spawner.options_form:
                        self.redirect(url_concat(url_path_join(self.hub.base_url, 'spawn'),
                                                 {'next': self.request.uri}))
                        return
                    else:
                        yield self.spawn_single_user(current_user)
            # set login cookie anew
            self.set_login_cookie(current_user)
            without_prefix = self.request.uri[len(self.hub.base_url):]
            target = url_path_join(self.base_url, without_prefix)
            if self.subdomain_host:
                target = current_user.host + target
            self.redirect(target)
            self.statsd.incr('redirects.user_after_login')
        elif current_user:
            # logged in as a different user, redirect
            self.statsd.incr('redirects.user_to_user', 1)
            target = url_path_join(current_user.url, user_path or '')
            self.redirect(target)
        else:
            # not logged in, clear any cookies and reload
            self.statsd.incr('redirects.user_to_login', 1)
            self.clear_login_cookie()
            self.redirect(url_concat(
                self.settings['login_url'],
                {'next': self.request.uri},
            ))
Example #5
0
    def authenticate(self, handler, data=None):

        code = handler.get_argument("code", False)
        if not code:
            raise web.HTTPError(400, "OAUTH_CALLBACK_URL has been called without a token")

        http_client = AsyncHTTPClient()

        # Exchange the OAuth code for a Custom OAuth Access Token
        # API specifies a GET request yet requires URL parameters
        token_req_param = dict(
            client_id=self.client_id,
            client_secret=self.client_secret,
            grant_type=self.grant_type,
            redirect_uri=self.oauth_callback_url,
            code=code
        )

        if not self.oauth_access_token_url:
            raise web.HTTPError(400, "OAUTH_ACCESS_TOKEN_URL is not defined")

        token_url = url_concat(self.oauth_access_token_url, token_req_param)
        token_req = HTTPRequest(url=token_url,
                          method="GET",
                          headers={"Accept": "application/json"},
                          validate_cert=True,
                          ca_certs=self.client_cert_path
                          )

        resp = yield http_client.fetch(token_req)
        
        resp_json = self.parse_response(resp)

        profile_req_params = dict(
            access_token=resp_json['access_token']
        )
        # Retrieve user information with a valid token obtained from the previous
        # request
        if not self.oauth_profile_url:
            raise web.HTTPError(400, "OAUTH_PROFILE_URL is not defined")
        profile_url = url_concat(self.oauth_profile_url, profile_req_params)
        profile_req = HTTPRequest(
                          url=profile_url,
                          validate_cert=True,
                          ca_certs=self.client_cert_path)
        # This request returns a JSON string
        resp = yield http_client.fetch(profile_req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))
        user_id = resp_json['id']
        self.log.info("OAuth user id: %s" % user_id)
        # Check is user is authorized to access to Stratio Intelligence
        if not self.is_allowed(resp_json):
            raise web.HTTPError(403, "User " + user_id + " is not allowed to access to Stratio Intelligence")
        # User id is returned to be registered into app data base
        return user_id
Example #6
0
 def get_ips_by_array_id(self,array_id):
     urlfilter={"filter":'storagesystem eq "%s"'%(array_id),"per_page":100}
     url = url_concat(SWARM_API_URL_IP,urlfilter)
     response_body= self.send_swarm_request(url,method="GET")
     ip_entries=json.loads(response_body)["entries"]
     ipids=map(lambda x: str(x["ipid"]),ip_entries)
     urlfilter={"filter":'id in (%s)'%(",".join(ipids))}
     url = url_concat(SWARM_API_URL_SINGLE_IP,urlfilter)
     response_body= self.send_swarm_request(url,method="GET")
     ips=json.loads(response_body)["entries"]
     return ips
Example #7
0
 def get_reserved_array_by_user_id(self,user_id):
     reservations=self.get_active_reservation_by_user_id(user_id)
     reservation_ids=map(lambda x: str(x["id"]),reservations)
     urlfilter={"filter":'reservation in (%s)'%(",".join(reservation_ids)),"per_page":100}
     url = url_concat(SWARM_API_URL_ARRAY_RESERVATION,urlfilter)
     response_body= self.send_swarm_request(url,method="GET")
     reservation_arrays=json.loads(response_body)["entries"]
     array_ids=map(lambda x:str(x["storagesystem"]),reservation_arrays)
     urlfilter={"filter":'id in (%s)'%(",".join(array_ids)),"per_page":100}
     url=url_concat(SWARM_API_URL_ARRAY,urlfilter)
     response_body= self.send_swarm_request(url,method="GET")
     reserved_arrays=json.loads(response_body)["entries"]
     return reserved_arrays
Example #8
0
    def request(self, url_path, method="GET", **kwargs):
        params = self.build_params(url_path, **kwargs)

        if not urlparse.urlparse(url_path).netloc:
            url = url_concat(self.build_url(url_path, **kwargs), params)
        else:
            url = url_concat(url_path, params)

        client = AsyncHTTPClient(force_instance=True)
        try:
            result = yield client.fetch(url, method=method, headers=self.build_headers())
            raise Return(result)
        finally:
            client.close()
Example #9
0
    def get_access_token(self, code, callback, grant_type='code', redirect_uri=None):
        if grant_type == 'refresh_token':
            args = {
                'grant_type': 'refresh_token',
                'refresh_token': code,
            }
        elif redirect_uri:
            args = {
                'grant_type': 'authorization_code',
                'code': code,
                'redirect_uri': redirect_uri,
            }
        else:
            logging.error('Renren Get Access Token Error. redirect_uri required')
            return
        args.update(self._oauth_consumer_token())

        http = httpclient.AsyncHTTPClient()
        http.fetch(url_concat(self._OAUTH_ACCESS_TOKEN_URL, args),
                   callback=(yield gen.Callback('_RenrenGraphMixin.get_access_token')))
        response = yield gen.Wait('_RenrenGraphMixin.get_access_token')

        if response.error and not response.body:
            logging.warning("Error response %s fetching %s", response.error,
                    response.request.url)
            callback(None)
            return

        callback(response)
        return
Example #10
0
    def watch(self, url_path, on_data, **kwargs):
        class WatchFuture(Future):

            def cancel(self):
                client.close()
                logging.debug("AsyncHTTPClient closed")

        def data_callback(data):
            on_data(json.loads(data))

        params = self.build_params(url_path, **kwargs)
        url = url_concat(self.build_url(url_path, **kwargs), params)

        request = HTTPRequest(
            url=url,
            method="GET",
            headers=self.build_headers(),
            request_timeout=3600,
            streaming_callback=data_callback)

        client = AsyncHTTPClient(force_instance=True)
        future = WatchFuture()

        chain_future(client.fetch(request), future)
        return future
Example #11
0
 def toProfilesAPI(self, mid):
     u"""PROFILES APIでLINEServerにプロフィールを問い合わせ
     ※Contact Response ObjectのJSONデータが返却されてくる
     ※TODO:複数一括リクエストは未対応
     """
     # リクエストはGetでユーザーの識別子 (複数時はカンマ区切り)を渡す
     http_client = tornado.httpclient.HTTPClient()
     url = url_concat(self.PROFILES_API, {"mids": mid})
     print(url)
     result = None
     try:
         response = http_client.fetch(
             url,
             method='GET',
             headers=self.REQUEST_HEADER,
             body=None
         )
         json_dic = tornado.escape.json_decode(response.body)
         result = json_dic["contacts"]
     except http_client.HTTPError as e:
         # HTTPError is raised for non-200 responses
         print("Error: " + str(e))
     except Exception as e:
         # Other errors
         print("Error: " + str(e))
     http_client.close()
     return result
Example #12
0
 def _check_group_whitelist(self, username, user_id, is_admin, access_token):
     http_client = AsyncHTTPClient()
     headers = _api_headers(access_token)
     if is_admin:
         # For admins, /groups returns *all* groups. As a workaround
         # we check if we are a member of each group in the whitelist
         for group in map(url_escape, self.gitlab_group_whitelist):
             url = "%s/groups/%s/members/%d" % (GITLAB_API, group, user_id)
             req = HTTPRequest(url, method="GET", headers=headers)
             resp = yield http_client.fetch(req, raise_error=False)
             if resp.code == 200:
                 return True  # user _is_ in group
     else:
         # For regular users we get all the groups to which they have access
         # and check if any of these are in the whitelisted groups
         next_page = url_concat("%s/groups" % GITLAB_API,
                                dict(all_available=True))
         while next_page:
             req = HTTPRequest(next_page, method="GET", headers=headers)
             resp = yield http_client.fetch(req)
             resp_json = json.loads(resp.body.decode('utf8', 'replace'))
             next_page = next_page_from_links(resp)
             user_groups = set(entry["path"] for entry in resp_json)
             # check if any of the organizations seen thus far are in whitelist
             if len(self.gitlab_group_whitelist & user_groups) > 0:
                 return True
         return False
Example #13
0
    def authorize_redirect(
        self,
        redirect_uri: str = None,
        client_id: str = None,
        client_secret: str = None,
        extra_params: Dict[str, Any] = None,
        scope: str = None,
        response_type: str = "code",
    ) -> None:
        """Redirects the user to obtain OAuth authorization for this service.

        Some providers require that you register a redirect URL with
        your application instead of passing one via this method. You
        should call this method to log the user in, and then call
        ``get_authenticated_user`` in the handler for your
        redirect URL to complete the authorization process.

        .. versionchanged:: 6.0

           The ``callback`` argument and returned awaitable were removed;
           this is now an ordinary synchronous function.
        """
        handler = cast(RequestHandler, self)
        args = {"response_type": response_type}
        if redirect_uri is not None:
            args["redirect_uri"] = redirect_uri
        if client_id is not None:
            args["client_id"] = client_id
        if extra_params:
            args.update(extra_params)
        if scope:
            args["scope"] = " ".join(scope)
        url = self._OAUTH_AUTHORIZE_URL  # type: ignore
        handler.redirect(url_concat(url, args))
    def _get_certivox_server_secret_share_dta(self, expires):
        path = 'serverSecret'
        url_params = url_concat('{0}{1}'.format(Keys.certivoxServer(), path), {
            'app_id': self.app_id,
            'expires': expires,
            'signature': signMessage('{0}{1}{2}'.format(path, self.app_id, expires), self.app_key)
        })
        log.debug('MIRACL server secret request: {0}'.format(url_params))
        httpclient = tornado.httpclient.HTTPClient()
        try:
            response = httpclient.fetch(url_params, **fetchConfig(url_params))
        except tornado.httpclient.HTTPError as e:
            log.error(e)
            raise SecretsError('Unable to get Server Secret from the MIRACL TA server')
        httpclient.close()

        try:
            data = json.loads(response.body)
        except ValueError as e:
            log.error(e)
            raise SecretsError('Invalid response from TA server')

        if 'serverSecret' not in data:
            raise SecretsError('serverSecret not in response from TA server')

        return data["serverSecret"]
Example #15
0
 async def get(self):
     self.statsd.incr('login.request')
     user = self.current_user
     if user:
         # set new login cookie
         # because single-user cookie may have been cleared or incorrect
         self.set_login_cookie(user)
         self.redirect(self.get_next_url(user), permanent=False)
     else:
         if self.authenticator.auto_login:
             auto_login_url = self.authenticator.login_url(self.hub.base_url)
             if auto_login_url == self.settings['login_url']:
                 # auto_login without a custom login handler
                 # means that auth info is already in the request
                 # (e.g. REMOTE_USER header)
                 user = await self.login_user()
                 if user is None:
                     # auto_login failed, just 403
                     raise web.HTTPError(403)
                 else:
                     self.redirect(self.get_next_url(user))
             else:
                 if self.get_argument('next', default=False):
                     auto_login_url = url_concat(
                         auto_login_url, {'next': self.get_next_url()}
                     )
                 self.redirect(auto_login_url)
             return
         username = self.get_argument('username', default='')
         self.finish(self._render(username=username))
Example #16
0
    def post(self):
        form = Form(self.request.arguments, shop_schema)

        if not form.validate():
            return self.render("distributor/shop.html", form=form, error="error")

        if form.url.value:
            form.url.value = form.url.value.lower()
            if not re.match(r"https?", form.url.value):
                form.url.value = "http://" + form.url.value

        shop_id = self.get_argument("id")
        distributor_shop = self.db.get("select * from distributor_shop where deleted =0 and id = %s", shop_id)
        distributor_id = distributor_shop.distributor_id

        self.db.execute(
            "update distributor_shop set name = %s,taobao_nick= %s,money_manager = %s,url = %s " "where id = %s",
            form.name.value.strip(),
            form.taobao_nick.value.strip(),
            form.money_manager.value,
            form.url.value,
            shop_id,
        )

        self.redirect(
            url_concat(
                self.reverse_url("distributor.show_shop_list"), {"distributor_id": distributor_id, "id": shop_id}
            )
        )
Example #17
0
    def post(self):
        form = Form(self.request.arguments, shop_schema)

        if not form.validate():
            return self.render("distributor/shop.html", form=form, error="error")

        if form.url.value:
            form.url.value = form.url.value.lower()
            if not re.match(r"https?", form.url.value):
                form.url.value = "http://" + form.url.value

        distributor_id = self.get_argument("distributor-id")
        distributor = self.db.get("select name from distributor where id = %s", distributor_id)

        # 新建分销商铺
        shop_id = self.db.execute_lastrowid(
            "insert into distributor_shop (distributor_id,name,taobao_nick,money_manager,"
            "url,distributor_name,created_at,created_by) values (%s,%s,%s,%s,%s,%s,now(),%s)",
            distributor_id,
            form.name.value.strip(),
            form.taobao_nick.value.strip(),
            form.money_manager.value,
            form.url.value,
            distributor.name,
            self.current_user.name,
        )

        self.redirect(url_concat(self.reverse_url("distributor.show_shop_list"), {"distributor_id": distributor_id}))
Example #18
0
def test_login_redirect(app, running, next_url, location):
    cookies = yield app.login_user('river')
    user = app.users['river']
    if location:
        location = ujoin(app.base_url, location)
    else:
        # use default url
        location = user.url

    url = 'login'
    if next_url:
        if '//' not in next_url:
            next_url = ujoin(app.base_url, next_url, '')
        url = url_concat(url, dict(next=next_url))

    if running and not user.active:
        # ensure running
        yield user.spawn()
    elif user.active and not running:
        # ensure not running
        yield user.stop()
    r = yield get_page(url, app, cookies=cookies, allow_redirects=False)
    r.raise_for_status()
    assert r.status_code == 302
    assert location == r.headers['Location']
    def query(self, callback, query, *args, **kw):
        method = kw.get("method", "POST")
        result_format = kw.get("result_format", DEFAULT_FORMAT)
        content_type = DEFAULT_CONTENT_TYPE

        headers = {
            "Content-Type": content_type,
        }

        params = {
            "query": query,
            "format": result_format
        }

        url = self.endpoint_url

        if method == "GET":
            url = url_concat(url, params)
            body = None
        elif method == "POST":
            body = urllib.urlencode(params)

        request = HTTPRequest(url=url,
                              method=method,
                              headers=headers,
                              body=body,
                              auth_username=self.user,
                              auth_password=self.password,
                              auth_mode=self.auth_mode
                              )
        response = yield gen.Task(self.client.fetch, request)
        callback(response, *args, **kw)
Example #20
0
    def post(self):
        contract_id = self.get_argument('contract_id')
        agent_id = self.get_argument('agent_id')

        self.db.execute('update contract set deleted = 1 where id = %s', contract_id)

        self.redirect(url_concat(self.reverse_url('agent.contract'), {'agent_id': agent_id}))
Example #21
0
 def getData(self,url,method,data,cookie):
     try:
         client = HTTPClient()
         request = HTTPRequest(
                 url,
                 method=method,
                 headers={
                     'Cookie':cookie
                 }
             )
         if data and method=="GET":
             url = url_concat(url,data)
             url = url.replace("+","%20")
             request.url = url
         elif data and method=="POST":
             realData = {}
             for i in data:
                 realData[i[0]] = i[1]
             data = urllib.urlencode(realData)
             request.body = data
         response = client.fetch(request)
         return json.loads(response.body)
     except Exception,e:
         # print str(e)
         #traceback.print_exc()
         return str(e)
Example #22
0
 def get(self, name):
     current_user = self.get_current_user()
     if current_user and current_user.name == name:
         # logged in, spawn the server
         if current_user.spawner:
             if current_user.spawn_pending:
                 # spawn has started, but not finished
                 html = self.render_template("spawn_pending.html", user=current_user)
                 self.finish(html)
                 return
             
             # spawn has supposedly finished, check on the status
             status = yield current_user.spawner.poll()
             if status is not None:
                 if current_user.spawner.options_form:
                     self.redirect(url_path_join(self.hub.server.base_url, 'spawn'))
                     return
                 else:
                     yield self.spawn_single_user(current_user)
         # set login cookie anew
         self.set_login_cookie(current_user)
         without_prefix = self.request.uri[len(self.hub.server.base_url):]
         target = url_path_join(self.base_url, without_prefix)
         self.redirect(target)
     else:
         # not logged in to the right user,
         # clear any cookies and reload (will redirect to login)
         self.clear_login_cookie()
         self.redirect(url_concat(
             self.settings['login_url'],
             {'next': self.request.uri,
         }))
Example #23
0
    def watch(self, url_path, on_data, **kwargs):
        local_data = dict(buffer="")

        class WatchFuture(Future):

            def cancel(self):
                client.close()
                logging.debug("AsyncHTTPClient closed")

        def data_callback(data):
            split_data = data.split("\n")
            for index, fragment in enumerate(split_data):
                if index + 1 < len(split_data):
                    on_data(json.loads(local_data["buffer"] + fragment))
                    local_data["buffer"] = ""
                else:
                    local_data["buffer"] += fragment

        params = self.build_params(url_path, **kwargs)
        url = url_concat(self.build_url(url_path, **kwargs), params)

        request = HTTPRequest(
            url=url,
            method="GET",
            headers=self.build_headers(),
            request_timeout=3600,
            streaming_callback=data_callback)

        client = AsyncHTTPClient(force_instance=True)
        future = WatchFuture()

        chain_future(client.fetch(request), future)
        return future
Example #24
0
 async def get_submits(self):
     start, size = 0, 50
     while True:
         url = httputil.url_concat(self.status_url,
                                   gen_status_params(self.account.nickname, start, size))
         response = await self.fetch(url)
         res = json.loads(response.body.decode('utf-8'))
         status_data = res['aaData']
         if len(status_data) == 0:
             break
         status_list = []
         for row in status_data:
             run_time = row[5][:-3] if row[5] != '' else '-1'
             memory = row[6][:-3] if row[6] != '' else '-1'
             status = {
                 'type': DataType.Submit, 'account': self.account,
                 'status': submit.SubmitStatus.BROKEN,
                 'run_id': row[1], 'pro_id': row[2], 'result': row[3],
                 'lang': row[4], 'run_time': run_time, 'memory': memory,
                 'submit_time': row[8], 'code': None
             }
             status_list.append(status)
         logger.debug('{} {} Success to get {} new status'.format(
             self.TAG, self.account, len(status_list)))
         self.put_queue(status_list)
         start += size
Example #25
0
    def authorize_redirect(self, redirect_uri=None, client_id=None,
                           client_secret=None, extra_params=None,
                           callback=None, scope=None, response_type="code"):
        """Redirects the user to obtain OAuth authorization for this service.

        Some providers require that you register a redirect URL with
        your application instead of passing one via this method. You
        should call this method to log the user in, and then call
        ``get_authenticated_user`` in the handler for your
        redirect URL to complete the authorization process.

        .. versionchanged:: 3.1
           Returns a `.Future` and takes an optional callback.  These are
           not strictly necessary as this method is synchronous,
           but they are supplied for consistency with
           `OAuthMixin.authorize_redirect`.

        .. deprecated:: 5.1

           The ``callback`` argument and returned awaitable will be removed
           in Tornado 6.0; this will be an ordinary synchronous function.
        """
        args = {
            "redirect_uri": redirect_uri,
            "client_id": client_id,
            "response_type": response_type
        }
        if extra_params:
            args.update(extra_params)
        if scope:
            args['scope'] = ' '.join(scope)
        self.redirect(
            url_concat(self._OAUTH_AUTHORIZE_URL, args))
        callback()
Example #26
0
    def get(self):
        url, method = TOGGL_API.time_entries

        today = datetime.datetime.today()
        end_date = today + datetime.timedelta(days=1)
        start_date = datetime.datetime.today() - datetime.timedelta(days=5)

        start_date = tz.localize(
            datetime.datetime(start_date.year, start_date.month, start_date.day)
        ).isoformat()
        end_date = tz.localize(
            datetime.datetime(end_date.year, end_date.month, end_date.day)
        ).isoformat()

        params = {"start_date": start_date,
                  "end_date": end_date, }
        url = url_concat(url, params)

        res = yield tornado.httpclient.AsyncHTTPClient().fetch(
            request=url,
            method=method,
            auth_username=username,
            auth_password=password,
        )

        time_entries = tornado.escape.json_decode(res.body)
        time_entries.reverse()
        redis_db["time_entries"] = redis_encode(time_entries)
        self.redirect("/")

        logging.info("entries params = %s\nlen = %s" % (
            params, len(time_entries)))
Example #27
0
    def get(self):
        # we can append next to the redirect uri, so the user gets the
        # correct URL on login
        redirect_uri = url_concat(self.request.protocol
                                  + "://" + self.request.host
                                  + self.settings["github_callback_path"],
                                  {"next": self.get_argument('next', '/')})

        # if we have a code, we have been authorized so we can log in
        if self.get_argument("code", False):
            user = yield self.get_authenticated_user(
                redirect_uri=redirect_uri,
                client_id=self.settings["github_client_id"],
                client_secret=self.settings["github_client_secret"],
                code=self.get_argument("code"))
            if user:
                log.info('logged in user from github: ' + str(user))
                self.set_secure_cookie("user", json_encode(user))
            else:
                self.clear_cookie("user")
            self.redirect(self.get_argument("next","/"))
            return

        # otherwise we need to request an authorization code
        self.authorize_redirect(
            redirect_uri=redirect_uri,
            client_id=self.settings["github_client_id"],
            extra_params={"scope": self.settings['github_scope'], "foo":1})
Example #28
0
 def getData(self,url,method,data,cookie):
     try:
         client = HTTPClient()
         request = HTTPRequest(
                 url,
                 method=method,
                 headers={
                     'Cookie':cookie
                 }
             )
         if data and method=="GET":
             data = json.loads(data)
             url = url_concat(url,data)
             request.url = url
         elif data and method=="POST":
             data = json.loads(data)
             print data
             data = urllib.urlencode(data)
             request.body = data
         # print request.url
         response = client.fetch(request)
         return response.body
     except Exception,e:
         # print str(e)
         return None
Example #29
0
	def authorize_redirect(self, redirect_uri=None, client_id=None,
						   client_secret=None, extra_params=None,
						   callback=None):
		"""Redirects the user to obtain OAuth authorization for this service.

		Some providers require that you register a redirect URL with
		your application instead of passing one via this method. You
		should call this method to log the user in, and then call
		``get_authenticated_user`` in the handler for your
		redirect URL to complete the authorization process.

		.. versionchanged:: 3.1
		   Returns a `.Future` and takes an optional callback.  These are
		   not strictly necessary as this method is synchronous,
		   but they are supplied for consistency with
		   `OAuthMixin.authorize_redirect`.
		"""
		args = {
			"redirect_uri": redirect_uri,
			"client_id": client_id
		}
		if extra_params:
			args.update(extra_params)
		self.redirect(
			url_concat(self._OAUTH_AUTHORIZE_URL, args))
		callback()
Example #30
0
    def _generate_escaped_url(self, url, args):
        """Takes in a dictionary of arguments and returns a URL line.

        Sorts the arguments so that the returned string is predictable and in
        alphabetical order. Effectively wraps the tornado.httputil.url_concat
        method and properly strips out None values, as well as lowercases
        Bool values.

        Args:
            url: (Str) The URL to append the arguments to
            args: (Dict) Key/Value arguments. Values should be primitives.

        Returns:
            A URL encoded string like this: <url>?foo=bar&abc=xyz
        """

        # Remove keys from the arguments where the value is None
        args = dict((k, v) for k, v in args.iteritems() if v)

        # Convert all Bool values to lowercase strings
        for key, value in args.iteritems():
            if type(value) is bool:
                args[key] = str(value).lower()

        # Now generate the URL
        full_url = httputil.url_concat(url, sorted(args.items()))
        self.log.debug('Generated URL: %s' % full_url)

        return full_url
Example #31
0
    async def authenticate(self, handler, data=None):
        code = handler.get_argument(name="code")
        # TODO: Configure the curl_httpclient for tornado
        http_client = AsyncHTTPClient()

        params = dict(redirect_uri=self.get_callback_url(handler),
                      code=code,
                      grant_type='authorization_code')
        params.update(self.extra_params)

        if self.token_url:
            url = self.token_url
        else:
            raise ValueError(
                "Please set the OAUTH2_TOKEN_URL environment variable")

        headers = {"Accept": "application/json", "User-Agent": "JupyterHub"}

        if self.basic_auth:
            b64key = base64.b64encode(
                bytes("{}:{}".format(self.client_id, self.client_secret),
                      "utf8"))
            headers.update(
                {"Authorization": "Basic {}".format(b64key.decode("utf8"))})

        req = HTTPRequest(
            url,
            method="POST",
            headers=headers,
            validate_cert=self.tls_verify,
            body=urllib.parse.urlencode(
                params)  # Body is required for a POST...
        )

        resp = await http_client.fetch(req)

        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        access_token = resp_json['access_token']
        refresh_token = resp_json.get('refresh_token', None)
        token_type = resp_json['token_type']
        scope = resp_json.get('scope', '')
        if (isinstance(scope, str)):
            scope = scope.split(' ')

        # Determine who the logged in user is
        headers = {
            "Accept": "application/json",
            "User-Agent": "JupyterHub",
            "Authorization": "{} {}".format(token_type, access_token)
        }
        if self.userdata_url:
            url = url_concat(self.userdata_url, self.userdata_params)
        else:
            raise ValueError(
                "Please set the OAUTH2_USERDATA_URL environment variable")

        if self.userdata_token_method == "url":
            url = url_concat(self.userdata_url,
                             dict(access_token=access_token))

        req = HTTPRequest(
            url,
            method=self.userdata_method,
            headers=headers,
            validate_cert=self.tls_verify,
        )
        resp = await http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        if not resp_json.get(self.username_key):
            self.log.error("OAuth user contains no key %s: %s",
                           self.username_key, resp_json)
            return

        return {
            'name': resp_json.get(self.username_key),
            'auth_state': {
                'access_token': access_token,
                'refresh_token': refresh_token,
                'oauth_user': resp_json,
                'scope': scope,
            }
        }
Example #32
0
    def authenticate(self, handler, data=None):
        code = handler.get_argument("code")
        # TODO: Configure the curl_httpclient for tornado
        http_client = AsyncHTTPClient()

        # Exchange the OAuth code for a GitLab Access Token
        #
        # See: https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/oauth2.md

        # GitLab specifies a POST request yet requires URL parameters
        params = dict(
            client_id=self.client_id,
            client_secret=self.client_secret,
            code=code,
            grant_type="authorization_code",
            redirect_uri=self.get_callback_url(handler),
        )

        validate_server_cert = self.validate_server_cert

        url = url_concat("%s/oauth/token" % GITLAB_HOST, params)

        req = HTTPRequest(
            url,
            method="POST",
            headers={"Accept": "application/json"},
            validate_cert=validate_server_cert,
            body=''  # Body is required for a POST...
        )

        resp = yield http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        access_token = resp_json['access_token']

        # Determine who the logged in user is
        req = HTTPRequest("%s/user" % GITLAB_API,
                          method="GET",
                          validate_cert=validate_server_cert,
                          headers=_api_headers(access_token))
        resp = yield http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        username = resp_json["username"]
        user_id = resp_json["id"]
        is_admin = resp_json.get("is_admin", False)

        # Check if user is a member of any whitelisted organizations.
        # This check is performed here, as it requires `access_token`.
        if self.gitlab_group_whitelist:
            user_in_group = yield self._check_group_whitelist(
                username, user_id, is_admin, access_token)
            if not user_in_group:
                self.log.warning("%s not in group whitelist", username)
                return None
        return {
            'name': username,
            'auth_state': {
                'access_token': access_token,
                'gitlab_user': resp_json,
            }
        }
Example #33
0
    def github_api_request(self, api_url, etag=None):
        client = AsyncHTTPClient()
        if self.auth:
            # Add auth params. After logging!
            api_url = url_concat(api_url, self.auth)

        headers = {}
        if etag:
            headers['If-None-Match'] = etag
        req = HTTPRequest(api_url, headers=headers, user_agent="BinderHub")

        try:
            resp = yield client.fetch(req)
        except HTTPError as e:
            if e.code == 304:
                resp = e.response
            elif (e.code == 403 and e.response
                  and e.response.headers.get('x-ratelimit-remaining') == '0'):
                rate_limit = e.response.headers['x-ratelimit-limit']
                reset_timestamp = int(e.response.headers['x-ratelimit-reset'])
                reset_seconds = int(reset_timestamp - time.time())
                self.log.error(
                    "GitHub Rate limit ({limit}) exceeded. Reset in {delta}.".
                    format(
                        limit=rate_limit,
                        delta=timedelta(seconds=reset_seconds),
                    ))
                # round expiry up to nearest 5 minutes
                minutes_until_reset = 5 * (1 + (reset_seconds // 60 // 5))

                raise ValueError(
                    "GitHub rate limit exceeded. Try again in %i minutes." %
                    minutes_until_reset)
            # Status 422 is returned by the API when we try and resolve a non
            # existent reference
            elif e.code in (404, 422):
                return None
            else:
                raise

        # record and log github rate limit
        remaining = int(resp.headers['x-ratelimit-remaining'])
        rate_limit = int(resp.headers['x-ratelimit-limit'])
        reset_timestamp = int(resp.headers['x-ratelimit-reset'])

        # record with prometheus
        GITHUB_RATE_LIMIT.set(remaining)

        # log at different levels, depending on remaining fraction
        fraction = remaining / rate_limit
        if fraction < 0.2:
            log = self.log.warning
        elif fraction < 0.5:
            log = self.log.info
        else:
            log = self.log.debug

        # str(timedelta) looks like '00:32'
        delta = timedelta(seconds=int(reset_timestamp - time.time()))
        log("GitHub rate limit remaining {remaining}/{limit}. Reset in {delta}."
            .format(
                remaining=remaining,
                limit=rate_limit,
                delta=delta,
            ))
        return resp
Example #34
0
    def get(self, name, user_path):
        if not user_path:
            user_path = '/'
        current_user = self.get_current_user()

        if current_user and current_user.name == name:
            # if spawning fails for any reason, point users to /hub/home to retry
            self.extra_error_html = self.spawn_home_error

            # If people visit /user/:name directly on the Hub,
            # the redirects will just loop, because the proxy is bypassed.
            # Try to check for that and warn,
            # though the user-facing behavior is unchanged
            host_info = urlparse(self.request.full_url())
            port = host_info.port
            if not port:
                port = 443 if host_info.scheme == 'https' else 80
            if port != Server.from_url(
                    self.proxy.public_url
            ).connect_port and port == self.hub.connect_port:
                self.log.warning(
                    """
                    Detected possible direct connection to Hub's private ip: %s, bypassing proxy.
                    This will result in a redirect loop.
                    Make sure to connect to the proxied public URL %s
                    """, self.request.full_url(), self.proxy.public_url)

            # logged in as correct user, check for pending spawn
            spawner = current_user.spawner

            # First, check for previous failure.
            if (not spawner.active and spawner._spawn_future
                    and spawner._spawn_future.done()
                    and spawner._spawn_future.exception()):
                # Condition: spawner not active and _spawn_future exists and contains an Exception
                # Implicit spawn on /user/:name is not allowed if the user's last spawn failed.
                # We should point the user to Home if the most recent spawn failed.
                exc = spawner._spawn_future.exception()
                self.log.error(
                    "Preventing implicit spawn for %s because last spawn failed: %s",
                    spawner._log_name, exc)
                # raise a copy because each time an Exception object is re-raised, its traceback grows
                raise copy.copy(exc).with_traceback(exc.__traceback__)

            # check for pending spawn
            if spawner.pending and spawner._spawn_future:
                # wait on the pending spawn
                self.log.debug("Waiting for %s pending %s", spawner._log_name,
                               spawner.pending)
                try:
                    yield gen.with_timeout(
                        timedelta(seconds=self.slow_spawn_timeout),
                        spawner._spawn_future)
                except gen.TimeoutError:
                    self.log.info(
                        "Pending spawn for %s didn't finish in %.1f seconds",
                        spawner._log_name, self.slow_spawn_timeout)
                    pass

            # we may have waited above, check pending again:
            if spawner.pending:
                self.log.info("%s is pending %s", spawner._log_name,
                              spawner.pending)
                # spawn has started, but not finished
                self.statsd.incr('redirects.user_spawn_pending', 1)
                html = self.render_template("spawn_pending.html",
                                            user=current_user)
                self.finish(html)
                return

            # spawn has supposedly finished, check on the status
            if spawner.ready:
                status = yield spawner.poll()
            else:
                status = 0

            # server is not running, trigger spawn
            if status is not None:
                if spawner.options_form:
                    self.redirect(
                        url_concat(url_path_join(self.hub.base_url, 'spawn'),
                                   {'next': self.request.uri}))
                    return
                else:
                    yield self.spawn_single_user(current_user)

            # spawn didn't finish, show pending page
            if spawner.pending:
                self.log.info("%s is pending %s", spawner._log_name,
                              spawner.pending)
                # spawn has started, but not finished
                self.statsd.incr('redirects.user_spawn_pending', 1)
                html = self.render_template("spawn_pending.html",
                                            user=current_user)
                self.finish(html)
                return

            # We do exponential backoff here - since otherwise we can get stuck in a redirect loop!
            # This is important in many distributed proxy implementations - those are often eventually
            # consistent and can take upto a couple of seconds to actually apply throughout the cluster.
            try:
                redirects = int(self.get_argument('redirects', 0))
            except ValueError:
                self.log.warning("Invalid redirects argument %r",
                                 self.get_argument('redirects'))
                redirects = 0

            # check redirect limit to prevent browser-enforced limits.
            # In case of version mismatch, raise on only two redirects.
            if redirects >= self.settings.get('user_redirect_limit', 4) or (
                    redirects >= 2
                    and spawner._jupyterhub_version != __version__):
                # We stop if we've been redirected too many times.
                msg = "Redirect loop detected."
                if spawner._jupyterhub_version != __version__:
                    msg += (
                        " Notebook has jupyterhub version {singleuser}, but the Hub expects {hub}."
                        " Try installing jupyterhub=={hub} in the user environment"
                        " if you continue to have problems.").format(
                            singleuser=spawner._jupyterhub_version
                            or 'unknown (likely < 0.8)',
                            hub=__version__,
                        )
                raise web.HTTPError(500, msg)

            # set login cookie anew
            self.set_login_cookie(current_user)
            without_prefix = self.request.uri[len(self.hub.base_url):]
            target = url_path_join(self.base_url, without_prefix)
            if self.subdomain_host:
                target = current_user.host + target

            # record redirect count in query parameter
            if redirects:
                self.log.warning("Redirect loop detected on %s",
                                 self.request.uri)
                # add capped exponential backoff where cap is 10s
                yield gen.sleep(min(1 * (2**redirects), 10))
                # rewrite target url with new `redirects` query value
                url_parts = urlparse(target)
                query_parts = parse_qs(url_parts.query)
                query_parts['redirects'] = redirects + 1
                url_parts = url_parts._replace(query=urlencode(query_parts))
                target = urlunparse(url_parts)
            else:
                target = url_concat(target, {'redirects': 1})

            self.redirect(target)
            self.statsd.incr('redirects.user_after_login')
        elif current_user:
            # logged in as a different user, redirect
            self.statsd.incr('redirects.user_to_user', 1)
            target = url_path_join(current_user.url, user_path or '')
            self.redirect(target)
        else:
            # not logged in, clear any cookies and reload
            self.statsd.incr('redirects.user_to_login', 1)
            self.clear_login_cookie()
            self.redirect(
                url_concat(
                    self.settings['login_url'],
                    {'next': self.request.uri},
                ))
Example #35
0
    async def generate_url(
        self,
        user: str,
        role: str,
        region: str = "us-east-1",
        user_role: bool = False,
        account_id: str = None,
    ) -> str:
        """Generate URL will get temporary credentials and craft a URL with those credentials."""
        function = (
            f"{__name__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}"
        )
        log_data = {
            "function": function,
            "user": user,
            "role": role,
            "message": "Generating authenticated AWS console URL",
        }
        log.debug(log_data)
        credentials = await self.get_credentials(
            user,
            role,
            user_role=user_role,
            account_id=account_id,
            enforce_ip_restrictions=False,
        )

        credentials_d = {
            "sessionId": credentials.get("Credentials", {}).get("AccessKeyId"),
            "sessionKey": credentials.get("Credentials",
                                          {}).get("SecretAccessKey"),
            "sessionToken": credentials.get("Credentials",
                                            {}).get("SessionToken"),
        }

        req_params = {
            "Action": "getSigninToken",
            "Session": bleach.clean(json.dumps(credentials_d)),
            "DurationSeconds": config.get("aws.session_duration", 3600),
        }

        http_client = AsyncHTTPClient(force_instance=True)

        url_with_params: str = url_concat(
            config.get("aws.federation_url",
                       "https://signin.aws.amazon.com/federation"),
            req_params,
        )
        r = await http_client.fetch(url_with_params,
                                    ssl_options=ssl.SSLContext())
        token = json.loads(r.body)

        login_req_params = {
            "Action":
            "login",
            "Issuer":
            config.get("aws.issuer"),
            "Destination": ("{}".format(
                config.get(
                    "aws.console_url",
                    "https://{}.console.aws.amazon.com").format(region))),
            "SigninToken":
            bleach.clean(token.get("SigninToken")),
            "SessionDuration":
            config.get("aws.session_duration", 3600),
        }

        r2 = requests_sync.Request(
            "GET",
            config.get("aws.federation_url",
                       "https://signin.aws.amazon.com/federation"),
            params=login_req_params,
        )
        url = r2.prepare().url
        return url
Example #36
0
 def test_url_concat_multi_same_query_params(self):
     url = url_concat(
         "https://localhost/path?r=1&r=2",
         [('y', 'y')],
     )
     self.assertEqual(url, "https://localhost/path?r=1&r=2&y=y")
Example #37
0
 def test_url_concat_with_frag(self):
     url = url_concat(
         "https://localhost/path#tab",
         [('y', 'y')],
     )
     self.assertEqual(url, "https://localhost/path?y=y#tab")
Example #38
0
 def _login_url(self):
     return url_concat(self.oauth_authorization_url, {
         'client_id': self.oauth_client_id,
         'redirect_uri': self.oauth_redirect_uri,
         'response_type': 'code',
     })
Example #39
0
    def get(self, name, user_path):
        current_user = self.get_current_user()
        if current_user and current_user.name == name:
            # If people visit /user/:name directly on the Hub,
            # the redirects will just loop, because the proxy is bypassed.
            # Try to check for that and warn,
            # though the user-facing behavior is unchainged
            host_info = urlparse(self.request.full_url())
            port = host_info.port
            if not port:
                port = 443 if host_info.scheme == 'https' else 80
            if port != Server.from_url(
                    self.proxy.public_url).port and port == self.hub.port:
                self.log.warning(
                    """
                    Detected possible direct connection to Hub's private ip: %s, bypassing proxy.
                    This will result in a redirect loop.
                    Make sure to connect to the proxied public URL %s
                    """, self.request.full_url(), self.proxy.public_url)

            # logged in as correct user, spawn the server
            if current_user.spawner:
                if current_user.spawn_pending:
                    # spawn has started, but not finished
                    self.statsd.incr('redirects.user_spawn_pending', 1)
                    html = self.render_template("spawn_pending.html",
                                                user=current_user)
                    self.finish(html)
                    return

                # spawn has supposedly finished, check on the status
                status = yield current_user.spawner.poll()
                if status is not None:
                    if current_user.spawner.options_form:
                        self.redirect(
                            url_concat(
                                url_path_join(self.hub.base_url, 'spawn'),
                                {'next': self.request.uri}))
                        return
                    else:
                        yield self.spawn_single_user(current_user)
            # set login cookie anew
            self.set_login_cookie(current_user)
            without_prefix = self.request.uri[len(self.hub.base_url):]
            target = url_path_join(self.base_url, without_prefix)
            if self.subdomain_host:
                target = current_user.host + target
            self.redirect(target)
            self.statsd.incr('redirects.user_after_login')
        elif current_user:
            # logged in as a different user, redirect
            self.statsd.incr('redirects.user_to_user', 1)
            target = url_path_join(current_user.url, user_path or '')
            self.redirect(target)
        else:
            # not logged in, clear any cookies and reload
            self.statsd.incr('redirects.user_to_login', 1)
            self.clear_login_cookie()
            self.redirect(
                url_concat(
                    self.settings['login_url'],
                    {'next': self.request.uri},
                ))
Example #40
0
 def get_method_url(cls, method, params=None):
     url = 'https://api.telegram.org/bot' + cls.bot_key + '/' + method
     if params is not None:
         url = url_concat(url, params)
     return url
Example #41
0
def delete(url, params=None, callback=None, **kwargs):
    url = url_concat(url, params)
    return session("DELETE", url, callback=None, **kwargs)
Example #42
0
def get_messages_from_person(person_id, num):
    params = {"seed": person_id, "numMessages": num}
    return url_concat(ENDPOINT_URL_PREFIX + "get_messages_from_person", params)
Example #43
0
 def test_url_concat_trailing_q(self):
     url = url_concat(
         "https://localhost/path?",
         [('y', 'y'), ('z', 'z')],
     )
     self.assertEqual(url, "https://localhost/path?y=y&z=z")
Example #44
0
 def test_url_concat_no_query_params(self):
     url = url_concat(
         "https://localhost/path",
         [('y', 'y'), ('z', 'z')],
     )
     self.assertEqual(url, "https://localhost/path?y=y&z=z")
Example #45
0
 def test_url_concat_mult_params(self):
     url = url_concat(
         "https://localhost/path?a=1&b=2",
         [('y', 'y'), ('z', 'z')],
     )
     self.assertEqual(url, "https://localhost/path?a=1&b=2&y=y&z=z")
Example #46
0
    def authenticate(self, handler, data=None):
        """We set up auth_state based on additional GitHub info if we
        receive it.
        """
        code = handler.get_argument("code")
        # TODO: Configure the curl_httpclient for tornado
        http_client = AsyncHTTPClient()

        # Exchange the OAuth code for a GitHub Access Token
        #
        # See: https://developer.github.com/v3/oauth/

        # GitHub specifies a POST request yet requires URL parameters
        params = dict(
            client_id=self.client_id,
            client_secret=self.client_secret,
            code=code
        )

        url = url_concat("%s://%s/login/oauth/access_token" % (GITHUB_PROTOCOL, GITHUB_HOST),
                         params)

        req = HTTPRequest(url,
                          method="POST",
                          headers={"Accept": "application/json"},
                          body=''  # Body is required for a POST...
                          )

        resp = yield http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        if 'access_token' in resp_json:
            access_token = resp_json['access_token']
        elif 'error_description' in resp_json:
            raise HTTPError(403,
                "An access token was not returned: {}".format(
                    resp_json['error_description']))
        else:
            raise HTTPError(500,
                "Bad response: %s".format(resp))

        # Determine who the logged in user is
        req = HTTPRequest("%s://%s/user" % (GITHUB_PROTOCOL, GITHUB_API),
                          method="GET",
                          headers=_api_headers(access_token)
                          )
        resp = yield http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        username = resp_json["login"]
        # username is now the GitHub userid.
        if not username:
            return None
        # Check if user is a member of any whitelisted organizations.
        # This check is performed here, as it requires `access_token`.
        if self.github_organization_whitelist:
            for org in self.github_organization_whitelist:
                user_in_org = yield self._check_organization_whitelist(org, username, access_token)
                if user_in_org:
                    break
            else:  # User not found in member list for any organisation
                self.log.warning("User %s is not in org whitelist", username)
                return None
        userdict = {"name": username}
        # Now we set up auth_state
        userdict["auth_state"] = auth_state = {}
        # Save the access token and full GitHub reply (name, id, email) in auth state
        # These can be used for user provisioning in the Lab/Notebook environment.
        # e.g.
        #  1) stash the access token
        #  2) use the GitHub ID as the id
        #  3) set up name/email for .gitconfig
        auth_state['access_token'] = access_token
        # store the whole user model in auth_state.github_user
        auth_state['github_user'] = resp_json
        # A public email will return in the initial query (assuming default scope).
        # Private will not.

        return userdict
Example #47
0
 def test_url_concat_multi_same_params(self):
     url = url_concat(
         "https://localhost/path",
         [('y', 'y1'), ('y', 'y2')],
     )
     self.assertEqual(url, "https://localhost/path?y=y1&y=y2")
 def login_url(self, base_url):
     return url_concat(url_path_join(base_url, 'external-login'),
                       {'redirect-to': self.external_login_url})
Example #49
0
 def test_url_concat_dict_params(self):
     url = url_concat(
         "https://localhost/path",
         dict(y='y'),
     )
     self.assertEqual(url, "https://localhost/path?y=y")
Example #50
0
    def _paginate(self, data=None, data_generator=None, sort=None):
        arg_page = self._get_page()
        arg_limit = self._get_limit()

        headers = {
            'X-Pagination-Page': arg_page,
            'X-Pagination-Limit': arg_limit
        }

        first_page = arg_page if arg_page > 0 else 1
        previous_page = None if arg_page <= 1 else arg_page - 1
        if data_generator:
            results = list(data_generator())[:arg_limit]
            next_page = None if len(results) < arg_limit else arg_page + 1
            last_page = None
        else:
            arg_sort = self._get_sort(default=sort)
            start = (arg_page - 1) * arg_limit
            end = start + arg_limit
            results = data
            if arg_sort:
                # Compare to earliest datetime instead of None
                def safe_compare(field, results):
                    if field == 'airDate' and results[field] is None:
                        return text_type(datetime.min)
                    return results[field]

                try:
                    for field, reverse in reversed(arg_sort):
                        results = sorted(results,
                                         key=partial(safe_compare, field),
                                         reverse=reverse)
                except KeyError:
                    return self._bad_request('Invalid sort query parameter')

            count = len(results)
            headers['X-Pagination-Count'] = count
            results = results[start:end]
            next_page = None if end > count else arg_page + 1
            last_page = ((count - 1) // arg_limit) + 1
            headers['X-Pagination-Total'] = last_page
            if last_page <= arg_page:
                last_page = None

        # Reconstruct the query parameters
        query_params = []
        for arg, values in viewitems(self.request.query_arguments):
            if arg in ('page', 'limit'):
                continue
            if not isinstance(values, list):
                values = [values]
            query_params += [(arg, value) for value in values]

        bare_uri = url_concat(self.request.path, query_params)

        links = []
        for rel, page in (('next', next_page), ('last', last_page),
                          ('first', first_page), ('previous', previous_page)):
            if page is None:
                continue

            uri = url_concat(bare_uri, dict(page=page, limit=arg_limit))
            link = '<{uri}>; rel="{rel}"'.format(uri=uri, rel=rel)
            links.append(link)

        self.set_header('Link', ', '.join(links))

        return self._ok(data=results, headers=headers)
Example #51
0
    def get(self, name, user_path):
        current_user = self.get_current_user()

        if current_user and current_user.name == name:
            # If people visit /user/:name directly on the Hub,
            # the redirects will just loop, because the proxy is bypassed.
            # Try to check for that and warn,
            # though the user-facing behavior is unchainged
            host_info = urlparse(self.request.full_url())
            port = host_info.port
            if not port:
                port = 443 if host_info.scheme == 'https' else 80
            if port != Server.from_url(
                    self.proxy.public_url
            ).connect_port and port == self.hub.connect_port:
                self.log.warning(
                    """
                    Detected possible direct connection to Hub's private ip: %s, bypassing proxy.
                    This will result in a redirect loop.
                    Make sure to connect to the proxied public URL %s
                    """, self.request.full_url(), self.proxy.public_url)

            # logged in as correct user, spawn the server
            spawner = current_user.spawner
            if spawner._spawn_pending or spawner._proxy_pending:
                # spawn has started, but not finished
                self.statsd.incr('redirects.user_spawn_pending', 1)
                html = self.render_template("spawn_pending.html",
                                            user=current_user)
                self.finish(html)
                return

            # spawn has supposedly finished, check on the status
            status = yield spawner.poll()
            if status is not None:
                if spawner.options_form:
                    self.redirect(
                        url_concat(url_path_join(self.hub.base_url, 'spawn'),
                                   {'next': self.request.uri}))
                    return
                else:
                    yield self.spawn_single_user(current_user)

            # We do exponential backoff here - since otherwise we can get stuck in a redirect loop!
            # This is important in many distributed proxy implementations - those are often eventually
            # consistent and can take upto a couple of seconds to actually apply throughout the cluster.
            try:
                redirects = int(self.get_argument('redirects', 0))
            except ValueError:
                self.log.warning("Invalid redirects argument %r",
                                 self.get_argument('redirects'))
                redirects = 0

            if redirects >= self.settings.get('user_redirect_limit', 5):
                # We stop if we've been redirected too many times.
                raise web.HTTPError(500, "Redirect loop detected.")

            # set login cookie anew
            self.set_login_cookie(current_user)
            without_prefix = self.request.uri[len(self.hub.base_url):]
            target = url_path_join(self.base_url, without_prefix)
            if self.subdomain_host:
                target = current_user.host + target

            # record redirect count in query parameter
            if redirects:
                self.log.warning("Redirect loop detected on %s",
                                 self.request.uri)
                # add capped exponential backoff where cap is 10s
                yield gen.sleep(min(1 * (2**redirects), 10))
                # rewrite target url with new `redirects` query value
                url_parts = urlparse(target)
                query_parts = parse_qs(url_parts.query)
                query_parts['redirects'] = redirects + 1
                url_parts = url_parts._replace(query=urlencode(query_parts))
                target = urlunparse(url_parts)
            else:
                target = url_concat(target, {'redirects': 1})

            self.redirect(target)
            self.statsd.incr('redirects.user_after_login')
        elif current_user:
            # logged in as a different user, redirect
            self.statsd.incr('redirects.user_to_user', 1)
            target = url_path_join(current_user.url, user_path or '')
            self.redirect(target)
        else:
            # not logged in, clear any cookies and reload
            self.statsd.incr('redirects.user_to_login', 1)
            self.clear_login_cookie()
            self.redirect(
                url_concat(
                    self.settings['login_url'],
                    {'next': self.request.uri},
                ))
Example #52
0
 def test_url_concat_no_params(self):
     url = url_concat(
         "https://localhost/path?r=1&t=2",
         {},
     )
     self.assertEqual(url, "https://localhost/path?r=1&t=2")
Example #53
0
    def authenticate(self, handler, data=None):
        """We set up auth_state based on additional CILogon info if we
        receive it.
        """
        code = handler.get_argument("code")
        # TODO: Configure the curl_httpclient for tornado
        http_client = AsyncHTTPClient()

        # Exchange the OAuth code for a CILogon Access Token
        # See: http://www.cilogon.org/oidc
        headers = {
            "Accept": "application/json",
            "User-Agent": "JupyterHub",
        }

        params = dict(
            client_id=self.client_id,
            client_secret=self.client_secret,
            redirect_uri=self.oauth_callback_url,
            code=code,
            grant_type='authorization_code',
        )

        url = url_concat("https://%s/oauth2/token" % CILOGON_HOST, params)

        req = HTTPRequest(url,
                          headers=headers,
                          method="POST",
                          body=''
                          )

        resp = yield http_client.fetch(req)
        token_response = json.loads(resp.body.decode('utf8', 'replace'))
        access_token = token_response['access_token']
        self.log.info("Access token acquired.")
        # Determine who the logged in user is
        params = dict(access_token=access_token)
        req = HTTPRequest(url_concat("https://%s/oauth2/userinfo" %
                                     CILOGON_HOST, params),
                          headers=headers
                          )
        resp = yield http_client.fetch(req)
        resp_json = json.loads(resp.body.decode('utf8', 'replace'))

        self.log.info("Userinfo response JSON: %s" % resp_json)


        username = resp_json.get(self.username_claim)
        if not username:
            self.log.error("Username claim %s not found in the response: %s",
                           self.username_claim, sorted(resp_json.keys())
                           )
            raise web.HTTPError(500, "Failed to get username from CILogon")

        if self.idp_whitelist:
            gotten_name, gotten_idp = username.split('@')
            if gotten_idp not in self.idp_whitelist:
                self.log.error(
                    "Trying to login from not whitelisted domain %s", gotten_idp)
                raise web.HTTPError(
                    500, "Trying to login from not whitelisted domain")
            if len(self.idp_whitelist) == 1 and self.strip_idp_domain:
                username = gotten_name       
       
        if self.comanage_group_whitelist:
            self.log.debug("comanage_group_whitelist %s" % self.comanage_group_whitelist)
            gotten_groups = resp_json.get(self.ismemberof_claim)
            self.log.info("Gotten groups from response: %s type: %s" % (gotten_groups, type(gotten_groups)))
            if gotten_groups is None:
                gotten_groups = []
            
            allowed = False
            okgroup = None
            for goodgroup in self.comanage_group_whitelist:
                if goodgroup in gotten_groups:
                    okgroup = goodgroup
                    allowed = True
            if allowed:
                self.log.info("User authorized by membership in %s" % okgroup)
            else:
                raise web.HTTPError(
                    500, "User belongs to no authorized groups. Presented groups: %s" % gotten_groups) 
        else:
            raise web.HTTPError(
                    500, "No groups whitelisted in configuration! Why use COManage?") 
        
        userdict = {"name": username}
        # Now we set up auth_state
        userdict["auth_state"] = auth_state = {}
        # Save the token response and full CILogon reply in auth state
        # These can be used for user provisioning
        #  in the Lab/Notebook environment.
        auth_state['token_response'] = token_response
        # store the whole user model in auth_state.cilogon_user
        # keep access_token as well, in case anyone was relying on it
        auth_state['access_token'] = access_token
        auth_state['cilogon_user'] = resp_json
        return userdict
Example #54
0
 def gen_link(self, page):
     return url_concat(self.path, dict(self.args, page=page))
Example #55
0
 def get(self):
     # issue a fake auth code and redirect to redirect_uri
     code = 'fake-authorization-code'
     self.redirect(
         url_concat(self.get_argument('redirect_uri'), dict(code=code)))
Example #56
0
    async def authenticate(self, handler, data=None):
        """We set up auth_state based on additional CILogon info if we
        receive it.
        """
        code = handler.get_argument("code")

        # Exchange the OAuth code for a CILogon Access Token
        # See: http://www.cilogon.org/oidc
        headers = {"Accept": "application/json", "User-Agent": "JupyterHub"}

        params = dict(
            client_id=self.client_id,
            client_secret=self.client_secret,
            redirect_uri=self.oauth_callback_url,
            code=code,
            grant_type='authorization_code',
        )

        url = url_concat(self.token_url, params)

        req = HTTPRequest(url, headers=headers, method="POST", body='')

        token_response = await self.fetch(req)
        access_token = token_response['access_token']
        # Determine who the logged in user is
        params = dict(access_token=access_token)
        req = HTTPRequest(
            url_concat("https://%s/oauth2/userinfo" % self.cilogon_host,
                       params),
            headers=headers,
        )
        resp_json = await self.fetch(req)

        claimlist = [self.username_claim]
        if self.additional_username_claims:
            claimlist.extend(self.additional_username_claims)

        for claim in claimlist:
            username = resp_json.get(claim)
            if username:
                break
        if not username:
            if len(claimlist) < 2:
                self.log.error(
                    "Username claim %s not found in response: %s",
                    self.username_claim,
                    sorted(resp_json.keys()),
                )
            else:
                self.log.error(
                    "No username claim from %r in response: %s",
                    claimlist,
                    sorted(resp_json.keys()),
                )
            raise web.HTTPError(500, "Failed to get username from CILogon")

        if self.allowed_idps:
            gotten_name, gotten_idp = username.split('@')
            if gotten_idp not in self.allowed_idps:
                self.log.error("Trying to login from not allowed domain %s",
                               gotten_idp)
                raise web.HTTPError(
                    500, "Trying to login from a domain not allowed")
            if len(self.allowed_idps) == 1 and self.strip_idp_domain:
                username = gotten_name
        userdict = {"name": username}
        # Now we set up auth_state
        userdict["auth_state"] = auth_state = {}
        # Save the token response and full CILogon reply in auth state
        # These can be used for user provisioning
        #  in the Lab/Notebook environment.
        auth_state['token_response'] = token_response
        # store the whole user model in auth_state.cilogon_user
        # keep access_token as well, in case anyone was relying on it
        auth_state['access_token'] = access_token
        auth_state['cilogon_user'] = resp_json
        return userdict
Example #57
0
 def test_url_concat_encode_args(self):
     url = url_concat(
         "https://localhost/path",
         [('y', '/y'), ('z', 'z')],
     )
     self.assertEqual(url, "https://localhost/path?y=%2Fy&z=z")
Example #58
0
 def get(self, user, repo, urlpath=None):
     url = '/v2/gh/{user}/{repo}/master'.format(user=user, repo=repo)
     if urlpath is not None and urlpath.strip('/'):
         url = url_concat(url, dict(urlpath=urlpath))
     self.redirect(url)
Example #59
0
 def test_url_concat_q_with_no_trailing_amp(self):
     url = url_concat(
         "https://localhost/path?x",
         [('y', 'y'), ('z', 'z')],
     )
     self.assertEqual(url, "https://localhost/path?x=&y=y&z=z")
Example #60
0
def get(url, params=None, callback=None, **kwargs):
    url = url_concat(url, params)
    return session("GET", url, callback=None, **kwargs)