Ejemplo n.º 1
0
    def __authenticate(self):
        credentials_full_path = os.path.join(self._credentials_path,
                                             'credentials.json')
        token = os.path.join(self._credentials_path, 'credentials')

        gauth = GoogleAuth()
        gauth.LoadClientConfigFile(credentials_full_path)

        if os.path.exists(token):
            gauth.LoadCredentialsFile(token)

        cred = gauth.credentials
        if not cred or cred.invalid:
            if cred and cred.access_token_expired and cred.refresh_token:
                gauth.Refresh()
            else:
                gauth.LocalWebserverAuth()
            gauth.SaveCredentialsFile(token)
        return gauth
class GoogledrivebackupPlugin(octoprint.plugin.SettingsPlugin,
                              octoprint.plugin.AssetPlugin,
                              octoprint.plugin.TemplatePlugin,
                              octoprint.plugin.EventHandlerPlugin,
                              octoprint.plugin.SimpleApiPlugin):

    ##~~ SettingsPlugin mixin

    def __init__(self):
        self.gauth = None

    def get_settings_defaults(self):
        return dict(
            cert_saved=False,
            cert_authorized=False,
            installed_version=self._plugin_version,
        )

    ##~~ SimpleApiPlugin mixin

    def get_api_commands(self):
        return dict(gen_secret=["json_data"], authorize=["auth_code"])

    def on_api_command(self, command, data):
        from octoprint.server import user_permission
        import flask
        if not user_permission.can():
            return flask.make_response("Insufficient rights", 403)

        from pydrive2.auth import GoogleAuth
        config_file = "{}/client_secrets.json".format(
            self.get_plugin_data_folder())
        credentials_file = "{}/credentials.json".format(
            self.get_plugin_data_folder())
        if not self.gauth:
            self.gauth = GoogleAuth()

        if command == "gen_secret":
            import json
            # write out our client_secrets.json file
            with open(config_file, "w") as f:
                f.write(json.dumps(data["json_data"]))
            self._settings.set(["cert_saved"], True)
            self._settings.save()

            self.gauth.LoadClientConfigFile(config_file)
            self.gauth.GetFlow()
            self.gauth.flow.params.update({'access_type': 'offline'})
            self.gauth.flow.params.update({'approval_prompt': 'force'})
            auth_url = self.gauth.GetAuthUrl()
            return flask.jsonify(dict(cert_saved=True, url=auth_url))

        if command == "authorize":
            self._logger.info("Attempting to authorize Google App")
            if not self.gauth:
                return flask.jsonify(dict(authorized=False))
            # Try to load saved client credentials
            self.gauth.Auth(data["auth_code"])
            self.gauth.SaveCredentialsFile(credentials_file)
            self._settings.set(["cert_authorized"], True)
            self._settings.save()
            return flask.jsonify(dict(authorized=True))

        ##~~ AssetPlugin mixin

    def get_assets(self):
        # Define your plugin's asset files to automatically include in the
        # core UI here.
        return dict(js=["js/googledrivebackup.js"])

    ##~~ EventHandlerPlugin mixin

    def on_event(self, event, payload):
        if event == "plugin_backup_backup_created" and self._settings.get_boolean(
            ["cert_authorized"]):
            self._logger.info(
                "{} created, will now attempt to upload to Google Drive".
                format(payload["path"]))
            from pydrive2.drive import GoogleDrive
            from pydrive2.auth import GoogleAuth
            credentials_file = "{}/credentials.json".format(
                self.get_plugin_data_folder())
            gauth = GoogleAuth()
            gauth.LoadCredentialsFile(credentials_file)
            if gauth.credentials is None:
                self._logger.error("not authorized")
                self._settings.set(["cert_authorized"], False)
                self._settings.save()
                return
            elif gauth.access_token_expired:
                gauth.Refresh()
            else:
                gauth.Authorize()
            gauth.SaveCredentialsFile(credentials_file)
            drive = GoogleDrive(gauth)
            f = drive.CreateFile({'title': payload["name"]})
            f.SetContentFile(payload["path"])
            f.Upload()
            f = None

        ##~~ Softwareupdate hook

    def get_update_information(self):
        return dict(googledrivebackup=dict(
            displayName="Google Drive Backup",
            displayVersion=self._plugin_version,

            # version check: github repository
            type="github_release",
            user="******",
            repo="OctoPrint-GoogleDriveBackup",
            current=self._plugin_version,
            stable_branch=dict(
                name="Stable", branch="master", comittish=["master"]),
            prerelease_branches=[
                dict(name="Release Candidate",
                     branch="rc",
                     comittish=["rc", "master"])
            ],
            # update method: pip
            pip=
            "https://github.com/jneilliii/OctoPrint-GoogleDriveBackup/archive/{target_version}.zip"
        ))
Ejemplo n.º 3
0
    def __init__(self, parsed_url):
        duplicity.backend.Backend.__init__(self, parsed_url)
        try:
            import httplib2
            from apiclient.discovery import build
        except ImportError as e:
            raise BackendException(u"""\
PyDrive backend requires PyDrive and Google API client installation.
Please read the manpage for setup details.
Exception: %s""" % str(e))

        # Shared Drive ID specified as a query parameter in the backend URL.
        # Example: pydrive://developer.gserviceaccount.com/target-folder/?driveID=<SHARED DRIVE ID>
        self.api_params = {}
        self.shared_drive_id = None
        if u'driveID' in parsed_url.query_args:
            self.shared_drive_id = parsed_url.query_args[u'driveID'][0]
            self.api_params = {
                u'corpora': u'teamDrive',
                u'teamDriveId': self.shared_drive_id,
                u'includeTeamDriveItems': True,
                u'supportsTeamDrives': True
            }

        try:
            from pydrive2.auth import GoogleAuth
            from pydrive2.drive import GoogleDrive
            from pydrive2.files import ApiRequestError, FileNotUploadedError
        except ImportError as e:
            try:
                from pydrive.auth import GoogleAuth
                from pydrive.drive import GoogleDrive
                from pydrive.files import ApiRequestError, FileNotUploadedError
            except ImportError as e:
                raise BackendException(u"""\
PyDrive backend requires PyDrive installation.  Please read the manpage for setup details.
Exception: %s""" % str(e))

        # let user get by with old client while he can
        try:
            from oauth2client.client import SignedJwtAssertionCredentials
            self.oldClient = True
        except:
            from oauth2client.service_account import ServiceAccountCredentials
            from oauth2client import crypt
            self.oldClient = False

        if u'GOOGLE_DRIVE_ACCOUNT_KEY' in os.environ:
            account_key = os.environ[u'GOOGLE_DRIVE_ACCOUNT_KEY']
            if self.oldClient:
                credentials = SignedJwtAssertionCredentials(
                    parsed_url.username + u'@' + parsed_url.hostname,
                    account_key,
                    scopes=u'https://www.googleapis.com/auth/drive')
            else:
                signer = crypt.Signer.from_string(account_key)
                credentials = ServiceAccountCredentials(
                    parsed_url.username + u'@' + parsed_url.hostname,
                    signer,
                    scopes=u'https://www.googleapis.com/auth/drive')
            credentials.authorize(httplib2.Http())
            gauth = GoogleAuth(http_timeout=60)
            gauth.credentials = credentials
        elif u'GOOGLE_DRIVE_SETTINGS' in os.environ:
            gauth = GoogleAuth(
                settings_file=os.environ[u'GOOGLE_DRIVE_SETTINGS'],
                http_timeout=60)
            gauth.CommandLineAuth()
        elif (u'GOOGLE_SECRETS_FILE' in os.environ
              and u'GOOGLE_CREDENTIALS_FILE' in os.environ):
            gauth = GoogleAuth(http_timeout=60)
            gauth.LoadClientConfigFile(os.environ[u'GOOGLE_SECRETS_FILE'])
            gauth.LoadCredentialsFile(os.environ[u'GOOGLE_CREDENTIALS_FILE'])
            if gauth.credentials is None:
                gauth.CommandLineAuth()
            elif gauth.access_token_expired:
                gauth.Refresh()
            else:
                gauth.Authorize()
            gauth.SaveCredentialsFile(os.environ[u'GOOGLE_CREDENTIALS_FILE'])
        else:
            raise BackendException(
                u'GOOGLE_DRIVE_ACCOUNT_KEY or GOOGLE_DRIVE_SETTINGS environment '
                u'variable not set. Please read the manpage to fix.')
        self.drive = GoogleDrive(gauth)

        if self.shared_drive_id:
            parent_folder_id = self.shared_drive_id
        else:
            # Dirty way to find root folder id
            file_list = self.drive.ListFile({
                u'q':
                u"'Root' in parents and trashed=false"
            }).GetList()
            if file_list:
                parent_folder_id = file_list[0][u'parents'][0][u'id']
            else:
                file_in_root = self.drive.CreateFile(
                    {u'title': u'i_am_in_root'})
                file_in_root.Upload()
                parent_folder_id = file_in_root[u'parents'][0][u'id']
                file_in_root.Delete()

        # Fetch destination folder entry and create hierarchy if required.
        folder_names = parsed_url.path.split(u'/')
        for folder_name in folder_names:
            if not folder_name:
                continue
            list_file_args = {
                u'q':
                u"'" + parent_folder_id + u"' in parents and trashed=false"
            }
            list_file_args.update(self.api_params)
            file_list = self.drive.ListFile(list_file_args).GetList()
            folder = next(
                (item
                 for item in file_list if item[u'title'] == folder_name and
                 item[u'mimeType'] == u'application/vnd.google-apps.folder'),
                None)
            if folder is None:
                create_file_args = {
                    u'title': folder_name,
                    u'mimeType': u"application/vnd.google-apps.folder",
                    u'parents': [{
                        u'id': parent_folder_id
                    }]
                }
                create_file_args[u'parents'][0].update(self.api_params)
                create_file_args.update(self.api_params)
                folder = self.drive.CreateFile(create_file_args)
                if self.shared_drive_id:
                    folder.Upload(param={u'supportsTeamDrives': True})
                else:
                    folder.Upload()
            parent_folder_id = folder[u'id']
        self.folder = parent_folder_id
        self.id_cache = {}