Esempio n. 1
0
    def login_url(self, next="/"):
        """ Overriding to produce a different redirect_uri """

        if not self.accessToken():

            request = current.request
            session = current.session

            if not request.vars.code:

                session.redirect_uri = self.args["redirect_uri"]

                data = {
                    "redirect_uri": session.redirect_uri,
                    "response_type": "code",
                    "client_id": self.client_id,
                }

                if self.args:
                    data.update(self.args)

                auth_request_url = "%s?%s" % (
                    self.auth_url,
                    urlencode(data),
                )
                raise HTTP(
                    307,
                    REDIRECT_MSG % auth_request_url,
                    Location=auth_request_url,
                )
            else:
                session.code = request.vars.code
                self.accessToken()

        return next
Esempio n. 2
0
        def geocode(self,
                    query,
                    *,
                    exactly_one=True,
                    timeout=DEFAULT_SENTINEL,
                    country=None,
                    country_bias=None):
            """
            Return a location point by address.

            :param str query: The address or query you wish to geocode.

            :param bool exactly_one: Return one result or a list of results, if
                available.

            :param int timeout: Time, in seconds, to wait for the geocoding service
                to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
                exception. Set this only if you wish to override, on this call
                only, the value set during the geocoder's initialization.

            :param country: Limit records to the specified countries.
                Two letter country code ISO-3166 (e.g. ``FR``). Might be
                a single string or a list of strings.
            :type country: str or list

            :param str country_bias: Records from the country_bias are listed first.
                Two letter country code ISO-3166.

            :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
                ``exactly_one=False``.
            """
            params = [
                ('name_startsWith', query),
            ]

            #if country_bias:
            #    params.append(('countryBias', country_bias))

            #if not country:
            #    country = []
            #if isinstance(country, str):
            #    country = [country]
            #for country_item in country:
            #    params.append(('country', country_item))

            if exactly_one:
                params.append(('maxRows', 1))
            url = "&".join((self.api, urlencode(params)))
            logger.debug("%s.geocode: %s", self.__class__.__name__, url)
            callback = partial(self._parse_json, exactly_one=exactly_one)
            return self._call_geocoder(url, callback, timeout=timeout)
Esempio n. 3
0
    def accessToken(self):
        """
            Return the access token generated by the authenticating server.

            If token is already in the session that one will be used.
            Otherwise the token is fetched from the auth server.
        """

        session = current.session

        token = session.token
        if token and "expires" in token:
            expires = token["expires"]
            # reuse token until expiration
            if expires == 0 or expires > time.time():
                return token["access_token"]

        code = session.code
        if code:
            data = {
                "client_id": self.client_id,
                "client_secret": self.client_secret,
                "redirect_uri": self.args["redirect_uri"],
                "code": code,
                "grant_type": "authorization_code",
                "scope": self.args["scope"],
            }

            open_url = None
            opener = self.__build_url_opener(self.token_url)
            try:
                open_url = opener.open(self.token_url, urlencode(data))
            except HTTPError as e:
                raise Exception(e.read())
            finally:
                del session.code  # throw it away

            if open_url:
                try:
                    token = json.loads(open_url.read())
                    token["expires"] = int(token["expires_in"]) + time.time()
                finally:
                    opener.close()
                session.token = token
                return token["access_token"]

        session.token = None
        return None
Esempio n. 4
0
File: base.py Progetto: nursix/drkcm
    def http(
        self,
        method="GET",
        path=None,
        args=None,
        data=None,
        headers=None,
        auth=False,
        encode="json",
        decode="json",
    ):
        """
            Send a HTTP request to the REST API

            @param method: the HTTP method
            @param path: the path relative to the base URL of the service
            @param args: dict of URL parameters
            @param data: data to send (JSON-serializable object)
            @param auth: False - do not send an Auth header
                         "Basic" - send an Auth header with username+password
                         "Token" - send an Auth header with access token
            @param encode: encode the request data as "json"|"text"|"bytes"
            @param decode: decode the response as "json"|"text"|"bytes"
        """

        base_url = self.base_url
        if not base_url:
            return None, None, "No base URL set"

        url = base_url.rstrip("/")
        if path:
            url = "/".join((url, path.lstrip("/")))
        if args:
            url = "?".join((url, urlencode(args)))

        # Generate the Request
        if PY2:
            req = urllib2.Request(url)
            req.get_method = lambda: method
        else:
            req = urllib2.Request(url=url, method=method)

        # Request data
        if method == "GET":
            request_data = None
        elif data:
            if encode == "json":
                request_data = json.dumps(data).encode("utf-8")
                req.add_header("Content-Type", "application/json")
            elif encode == "text":
                request_data = s3_str(data).encode("utf-8")
                req.add_header("Content-Type", "text/plain; charset=UTF-8")
            else:
                request_data = s3_str(data).encode("utf-8")
                req.add_header("Content-Type", "application/octet-stream")
        else:
            request_data = None

        # Acceptable response type
        if decode == "json":
            req.add_header("Accept", "application/json")
        else:
            req.add_header("Accept", "*/*")

        # Run the request
        output = status = error = None

        opener = self._http_opener(req, headers=headers, auth=auth)
        try:
            f = opener.open(req, data=request_data)
        except HTTPError as e:
            # HTTP error status
            status = e.code
            error = s3_str(e.read())
        except URLError as e:
            # Network Error
            error = e.reason
            if not error:
                error = "Unknown network error"
        except Exception:
            # Other Error
            error = sys.exc_info()[1]
        else:
            status = f.code

            # Decode the response
            if decode == "json":
                try:
                    output = json.load(f)
                except JSONERRORS:
                    error = sys.exc_info()[1]
            elif decode == "text":
                output = s3_str(f.read())
            else:
                # return the stream as-is
                output = f

        return output, status, error
Esempio n. 5
0
    def _send_request(self, method="GET", **args):

        repository = self.repository
        config = repository.config

        # Authentication
        args = Storage(args)
        if hasattr(self, "PHPSESSID") and self.PHPSESSID:
            args["PHPSESSID"] = self.PHPSESSID
        if hasattr(self, "api_key") and self.api_key:
            args["api_key"] = self.api_key
        if repository.site_key:
            args["key"] = repository.site_key

        # Create the request
        url = repository.url + "?" + urlencode(args)
        req = urllib2.Request(url=url)
        handlers = []

        # Proxy handling
        proxy = repository.proxy or config.proxy or None
        if proxy:
            # Figure out the protocol from the URL
            url_split = url.split("://", 1)
            if len(url_split) == 2:
                protocol = url_split[0]
            else:
                protocol = "http"
            current.log.debug("using proxy=%s", proxy)
            proxy_handler = urllib2.ProxyHandler({protocol: proxy})
            handlers.append(proxy_handler)

        # Install all handlers
        if handlers:
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        # Execute the request
        response = None
        message = None

        try:
            if method == "POST":
                f = urlopen(req, data="")
            else:
                f = urlopen(req)
        except HTTPError as e:
            message = "HTTP %s: %s" % (e.code, e.reason)
        else:
            # Parse the response
            tree = current.xml.parse(f)
            root = tree.getroot()
            is_error = root.xpath("//ResultSet[1]/Result[1]/is_error")
            if len(is_error) and int(is_error[0].text):
                error = root.xpath("//ResultSet[1]/Result[1]/error_message")
                if len(error):
                    message = error[0].text
                else:
                    message = "Unknown error"
            else:
                response = tree

        return response, message
Esempio n. 6
0
    def _send_request(self,
                      method="GET",
                      path=None,
                      args=None,
                      data=None,
                      auth=False):
        """
            Send a request to the Wrike API

            @param method: the HTTP method
            @param path: the path relative to the repository URL
            @param data: the data to send
            @param auth: this is an authorization request
        """

        repository = self.repository

        # Request URL
        api = "oauth2/token" if auth else "api/v3"
        url = "/".join((repository.url.rstrip("/"), api))
        if path:
            url = "/".join((url, path.lstrip("/")))
        if args:
            url = "?".join((url, urlencode(args)))

        # Create the request
        req = urllib2.Request(url=url)
        handlers = []

        if not auth:
            # Install access token header
            access_token = self.access_token
            if not access_token:
                message = "Authorization failed: no access token"
                current.log.error(message)
                return None, message
            req.add_header("Authorization",
                           "%s %s" % (self.token_type, access_token))
            # JSONify request data
            request_data = json.dumps(data) if data else ""
            if request_data:
                req.add_header("Content-Type", "application/json")
        else:
            # URL-encode request data for auth
            request_data = urlencode(data) if data else ""

        # Indicate that we expect JSON response
        req.add_header("Accept", "application/json")

        # Proxy handling
        config = repository.config
        proxy = repository.proxy or config.proxy or None
        if proxy:
            current.log.debug("using proxy=%s" % proxy)
            proxy_handler = urllib2.ProxyHandler({"https": proxy})
            handlers.append(proxy_handler)

        # Install all handlers
        if handlers:
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        # Execute the request
        response = None
        message = None
        try:
            if method == "POST":
                f = urlopen(req, data=request_data)
            else:
                f = urlopen(req)
        except HTTPError as e:
            message = "HTTP %s: %s" % (e.code, e.reason)
        else:
            # Parse the response
            try:
                response = json.load(f)
            except ValueError as e:
                message = sys.exc_info()[1]

        return response, message
Esempio n. 7
0
    def _send_request(self,
                      method="GET",
                      path=None,
                      args=None,
                      data=None,
                      auth=False):
        """
            Send a request to the CommandBridge API

            @param method: the HTTP method
            @param path: the path relative to the repository URL
            @param data: the data to send
            @param auth: this is an authorization request
        """

        xml = current.xml
        repository = self.repository

        # Request URL
        url = repository.url.rstrip("/")
        if path:
            url = "/".join((url, path.lstrip("/")))
        if args:
            url = "?".join((url, urlencode(args)))

        # Create the request
        req = urllib2.Request(url=url)
        handlers = []

        site_key = repository.site_key
        if not site_key:
            message = "CommandBridge Authorization failed: no access token (site key)"
            current.log.error(message)
            return None, message
        req.add_header("Authorization-Token", "%s" % site_key)

        # Request Data
        request_data = data if data is not None else ""
        if request_data:
            req.add_header("Content-Type", "application/xml")

        # Indicate that we expect XML response
        req.add_header("Accept", "application/xml")

        # Proxy handling
        config = repository.config
        proxy = repository.proxy or config.proxy or None
        if proxy:
            current.log.debug("using proxy=%s" % proxy)
            proxy_handler = urllib2.ProxyHandler({"https": proxy})
            handlers.append(proxy_handler)

        # Install all handlers
        if handlers:
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        # Execute the request
        response = None
        message = None
        try:
            if method == "POST":
                f = urlopen(req, data=request_data)
            else:
                f = urlopen(req)
        except HTTPError as e:
            message = "HTTP %s: %s" % (e.code, e.reason)
            # More details may be in the response body
            error_response = xml.parse(e)
            if error_response:
                error_messages = error_response.findall("Message")
                details = " / ".join(item.text for item in error_messages)
                message = "%s (%s)" % (message, details)
        else:
            response = xml.parse(f)
            if response is None:
                if method == "POST":
                    response = True
                elif xml.error:
                    message = xml.error

        return response, message
Esempio n. 8
0
    def notify(cls, resource_id):
        """
            Asynchronous task to notify a subscriber about updates,
            runs a POST?format=msg request against the subscribed
            controller which extracts the data and renders and sends
            the notification message (see send()).

            @param resource_id: the pr_subscription_resource record ID
        """

        _debug = current.log.debug
        _debug("S3Notifications.notify(resource_id=%s)" % resource_id)

        db = current.db
        s3db = current.s3db

        stable = s3db.pr_subscription
        rtable = db.pr_subscription_resource
        ftable = s3db.pr_filter

        # Extract the subscription data
        join = stable.on(rtable.subscription_id == stable.id)
        left = ftable.on(ftable.id == stable.filter_id)

        # @todo: should not need rtable.resource here
        row = db(rtable.id == resource_id).select(stable.id,
                                                  stable.pe_id,
                                                  stable.frequency,
                                                  stable.notify_on,
                                                  stable.method,
                                                  stable.email_format,
                                                  stable.attachment,
                                                  rtable.id,
                                                  rtable.resource,
                                                  rtable.url,
                                                  rtable.last_check_time,
                                                  ftable.query,
                                                  join=join,
                                                  left=left).first()
        if not row:
            return True

        s = getattr(row, "pr_subscription")
        r = getattr(row, "pr_subscription_resource")
        f = getattr(row, "pr_filter")

        # Create a temporary token to authorize the lookup request
        auth_token = str(uuid4())

        # Store the auth_token in the subscription record
        r.update_record(auth_token=auth_token)
        db.commit()

        # Construct the send-URL
        public_url = current.deployment_settings.get_base_public_url()
        lookup_url = "%s/%s/%s" % (public_url,
                                   current.request.application,
                                   r.url.lstrip("/"))

        # Break up the URL into its components
        purl = list(urlparse.urlparse(lookup_url))

        # Subscription parameters
        # Date (must ensure we pass to REST as tz-aware)
        last_check_time = s3_encode_iso_datetime(r.last_check_time)
        query = {"subscription": auth_token, "format": "msg"}
        if "upd" in s.notify_on:
            query["~.modified_on__ge"] = "%sZ" % last_check_time
        else:
            query["~.created_on__ge"] = "%sZ" % last_check_time

        # Filters
        if f.query:
            from .s3filter import S3FilterString
            resource = s3db.resource(r.resource)
            fstring = S3FilterString(resource, f.query)
            for k, v in fstring.get_vars.items():
                if v is not None:
                    if k in query:
                        value = query[k]
                        if type(value) is list:
                            value.append(v)
                        else:
                            query[k] = [value, v]
                    else:
                        query[k] = v
            query_nice = s3_unicode(fstring.represent())
        else:
            query_nice = None

        # Add subscription parameters and filters to the URL query, and
        # put the URL back together
        query = urlencode(query)
        if purl[4]:
            query = "&".join((purl[4], query))
        page_url = urlparse.urlunparse([purl[0], # scheme
                                        purl[1], # netloc
                                        purl[2], # path
                                        purl[3], # params
                                        query,   # query
                                        purl[5], # fragment
                                        ])

        # Serialize data for send (avoid second lookup in send)
        data = json.dumps({"pe_id": s.pe_id,
                           "notify_on": s.notify_on,
                           "method": s.method,
                           "email_format": s.email_format,
                           "attachment": s.attachment,
                           "resource": r.resource,
                           "last_check_time": last_check_time,
                           "filter_query": query_nice,
                           "page_url": lookup_url,
                           "item_url": None,
                           })

        # Send the request
        _debug("Requesting %s" % page_url)
        req = urllib2.Request(page_url, data=data.encode("utf-8"))
        req.add_header("Content-Type", "application/json")
        success = False
        try:
            response = json.loads(urlopen(req).read())
            message = response["message"]
            if response["status"] == "success":
                success = True
        except HTTPError as e:
            message = ("HTTP %s: %s" % (e.code, e.read()))
        except:
            exc_info = sys.exc_info()[:2]
            message = ("%s: %s" % (exc_info[0].__name__, exc_info[1]))
        _debug(message)

        # Update time stamps and unlock, invalidate auth token
        intervals = s3db.pr_subscription_check_intervals
        interval = datetime.timedelta(minutes=intervals.get(s.frequency, 0))
        if success:
            last_check_time = datetime.datetime.utcnow()
            next_check_time = last_check_time + interval
            r.update_record(auth_token=None,
                            locked=False,
                            last_check_time=last_check_time,
                            next_check_time=next_check_time)
        else:
            r.update_record(auth_token=None,
                            locked=False)
        db.commit()

        # Done
        return message