Example #1
0
    def get_latest_version(self) -> Optional[str]:
        # Do a version check to see if updates are available. If the user is logged
        # into the registry, also send the user ID for metrics.
        # The user can opt out by setting "SG_UPDATE_FREQUENCY" to 0 or opt out of
        # sending user ID by setting SG_UPDATE_ANONYMOUS to true.

        config = create_config_dict()
        frequency = int(get_singleton(config, "SG_UPDATE_FREQUENCY"))

        if frequency == 0:
            return None

        last_check = int(get_singleton(config, "SG_UPDATE_LAST"))
        now = int(time.time())

        if last_check + frequency > now:
            return None

        headers = get_headers()
        if get_singleton(config, "SG_UPDATE_ANONYMOUS").lower() == "false":
            try:
                headers.update(
                    {"Authorization": "Bearer " + self.access_token})
            except AuthAPIError:
                pass

        try:
            logging.debug("Running update check")
            response = requests.post(
                self.endpoint + "/update_check",
                verify=self.verify,
                headers=headers,
            )
            response.raise_for_status()
            latest_version = str(response.json()["latest_version"])
        except requests.RequestException as e:
            logging.debug("Error running the update check", exc_info=e)
            return None
        except KeyError:
            logging.debug("Malformed response from the update service")
            return None

        try:
            patch_and_save_config(config, {"SG_UPDATE_LAST": str(now)})
        except Exception as e:
            logging.debug("Error patching the config", exc_info=e)
            return latest_version

        return latest_version
Example #2
0
def login_api_c(api_key, api_secret, remote, skip_inject):
    """Log into a Splitgraph registry using existing API keys.

    This will inject the API keys for the registry into the configuration file
    and generate a new access token.
    """
    from splitgraph.cloud import AuthAPIClient, get_token_claim, DEFAULT_REMOTES
    from splitgraph.config import CONFIG
    from splitgraph.config.config import get_all_in_subsection

    client = AuthAPIClient(remote)
    access = client.get_access_token_from_api(api_key, api_secret)

    namespace = get_token_claim(access, "username")

    click.echo("Logged into %s as %s" % (remote, namespace))
    remote_params = (copy(DEFAULT_REMOTES.get(remote, {}))
                     if not get_all_in_subsection(CONFIG, "remotes", remote)
                     else {})
    remote_params.update({
        "SG_NAMESPACE": namespace,
        "SG_CLOUD_ACCESS_TOKEN": access,
        "SG_ENGINE_USER": api_key,
        "SG_ENGINE_PWD": api_secret,
    })
    config_patch = {
        "SG_REPO_LOOKUP": _update_repo_lookup(CONFIG, remote),
        "remotes": {
            remote: remote_params
        },
    }
    config_path = patch_and_save_config(CONFIG, config_patch)

    if not skip_inject:
        inject_config_into_engines(CONFIG["SG_ENGINE_PREFIX"], config_path)
Example #3
0
def register_c(username, password, email, remote, accept_tos, skip_inject):
    """
    Register the user on a Splitgraph registry.

    By default, this registers the user on data.splitgraph.com,
    obtains a set of machine (API) credentials for the client to communicate
    with the registry and configures the data.splitgraph.com engine.
    """
    from splitgraph.cloud import AuthAPIClient, DEFAULT_REMOTES
    from splitgraph.config import CONFIG
    from splitgraph.config.config import get_all_in_subsection

    client = AuthAPIClient(remote)
    tos = client.tos()

    if tos and not accept_tos:
        click.echo("%s says: %s" % (client.endpoint, tos))
        click.confirm("Do you accept the Terms of Service?",
                      default=False,
                      abort=True)
    click.echo("Registering the user...")

    uuid, access, refresh = client.register(username,
                                            password,
                                            email,
                                            accept_tos=True)
    click.echo("Registration successful. UUID %s" % uuid)

    key, secret = client.create_machine_credentials(access, password)
    click.echo("Acquired refresh token and API keys")

    repo_lookup = _update_repo_lookup(CONFIG, remote)

    # If remote isn't in the config (is one of the default ones), add the default parameters
    # to the new config -- otherwise only overwrite the new fields in the existing config.
    remote_params = (copy(DEFAULT_REMOTES.get(remote, {}))
                     if not get_all_in_subsection(CONFIG, "remotes", remote)
                     else {})
    remote_params.update({
        "SG_ENGINE_USER": key,
        "SG_ENGINE_PWD": secret,
        "SG_NAMESPACE": username,
        "SG_CLOUD_REFRESH_TOKEN": refresh,
        "SG_CLOUD_ACCESS_TOKEN": access,
        "SG_IS_REGISTRY": "true",
    })

    config_patch = {
        "SG_REPO_LOOKUP": repo_lookup,
        "remotes": {
            remote: remote_params
        },
    }
    config_path = patch_and_save_config(CONFIG, config_patch)

    if not skip_inject:
        inject_config_into_engines(CONFIG["SG_ENGINE_PREFIX"], config_path)

    click.echo("Done.")
Example #4
0
def login_c(username, password, remote, overwrite, skip_inject):
    """Log into a Splitgraph registry with username/password.

    This will generate a new refresh token (to use the Splitgraph query API)
    and API keys to let sgr access the registry (if they don't already exist
    in the configuration file or if the actual username has changed).

    Note that if you already have generated an API key pair but it's not
    in the configuration file, this will generate a new pair instead of
    restoring the existing one, as the API secret is only stored in the configuration file.

    If you want to log in using an existing API key pair, use `sgr cloud login-api` instead.
    """
    from splitgraph.config import CONFIG
    from splitgraph.config.config import get_all_in_subsection
    from splitgraph.cloud import AuthAPIClient, get_token_claim, DEFAULT_REMOTES

    client = AuthAPIClient(remote)

    if not password:
        profile_url = _construct_user_profile_url(client.endpoint)
        password = click.prompt(
            text="Password (visit %s if you don't have it)" % profile_url,
            confirmation_prompt=False,
            hide_input=True,
        )

    access, refresh = client.get_refresh_token(username, password)

    # Extract namespace from the access token since we might have logged in with an e-mail.
    namespace = get_token_claim(access, "username")

    click.echo("Logged into %s as %s" % (remote, namespace))

    config_remote_params = get_all_in_subsection(CONFIG, "remotes", remote)

    remote_params = copy(DEFAULT_REMOTES.get(
        remote, {})) if not config_remote_params else {}
    remote_params.update({
        "SG_NAMESPACE": namespace,
        "SG_CLOUD_REFRESH_TOKEN": refresh,
        "SG_CLOUD_ACCESS_TOKEN": access,
    })

    config_patch = {
        "SG_REPO_LOOKUP": _update_repo_lookup(CONFIG, remote),
        "remotes": {
            remote: remote_params
        },
    }

    # Get new tokens in any case if we're logging in under a different username.
    try:
        username_changed = namespace != CONFIG["remotes"][remote][
            "SG_NAMESPACE"]
    except KeyError:
        username_changed = False

    if ("SG_ENGINE_USER" not in config_remote_params
            or "SG_ENGINE_PWD" not in config_remote_params or overwrite
            or username_changed):
        key, secret = client.create_machine_credentials(access, password)
        config_patch["remotes"][remote]["SG_ENGINE_USER"] = key
        config_patch["remotes"][remote]["SG_ENGINE_PWD"] = secret
        click.echo("Acquired new API keys")

    config_path = patch_and_save_config(CONFIG, config_patch)

    if not skip_inject:
        inject_config_into_engines(CONFIG["SG_ENGINE_PREFIX"], config_path)