Editorial Workflows

DropboxAuth

public workflow

Install Workflow...

This workflow contains at least one Python script. Only use it if you trust the person who shared this with you, and if you know exactly what it does.

I understand, install the workflow!

This is a workflow for Editorial, a Markdown and plain text editor for iOS. To download it, you need to view this page on a device that has the app installed.

Description: Manage Dropbox authentication keys and tokens for either app folder or full access to Dropbox. Useful when you want to interact with Dropbox beyond the folder synced with Editorial.

The workflow also includes two sample actions that demonstrate how to establish a client connection to Dropbox. One is a self-contained action and the other demonstrates the use of a custom module. These can be saved as preset actions for easier use in other workflows.

NOTE: You must create an App through the Dropbox website to generate the necessary keys and access the Dropbox API. See this page for more details: https://www.dropbox.com/developers/apps

Credit: This workflow is based on the original dropboxlogin.py module Ole Zorn provided for use with Pythonista.

Ed Gauthier
@edgauthier

Shared by: @edgauthier

Comments: Comment Feed (RSS)

There are no comments yet.

+ Add Comment

Workflow Preview
Set count (generate text with specified number of lines) ?
...and repeat (simulate 'while' loop) - Main menu ?
Repeat with
  • Every Line
  • Every Match of Regular Expression:
Match Group
0 (entire match)
Reverse
OFF
Load Dropbox settings ?
Run the block if
1
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
1
Get Dropbox access type... ?
Source Code
#coding: utf-8
import workflow, keychain

value = keychain.get_password('dropbox', 'access_type')
if not value:
	value = '<unset>'

workflow.set_output(value)
...and save ?
Variable Name
access_type
Value
Input
Get Dropbox App Key... ?
Source Code
#coding: utf-8
import workflow, keychain

PASSWD_CHAR = u'\u2731'

value = keychain.get_password('dropbox', 'app_key')
if not value:
	value = '<unset>'
else:
	value = PASSWD_CHAR * len(value)

workflow.set_output(value)
...and save ?
Variable Name
app_key
Value
Input
Get Dropbox App Secret... ?
Source Code
#coding: utf-8
import workflow, keychain

PASSWD_CHAR = u'\u2731'

value = keychain.get_password('dropbox', 'app_secret')
if not value:
	value = '<unset>'
else:
	value = PASSWD_CHAR * len(value)

workflow.set_output(value)
...and save ?
Variable Name
app_secret
Value
Input
Get Dropbox access token... ?
Source Code
#coding: utf-8
import workflow, keychain, pickle

PASSWD_CHAR = u'\u2731'

token_str = keychain.get_password('dropbox', 'access_token')
all_params = keychain.get_password('dropbox', 'all_params')
if not token_str or not all_params:
	value = '<unset>'
else:
	key, secret = pickle.loads(token_str)
	value = PASSWD_CHAR * len(key)
workflow.set_output(value)
...and save ?
Variable Name
access_token
Value
Input
Reset continue flag ?
Variable Name
continue
Value
false
…End If
Display menu ?
Title
Dropbox Authentication
List (Lines)
Access Type: access_type access_type App Key: app_key app_key App Secret: app_secret app_secret Access Token: access_token access_token Reset All Settings reset
Multiple Selection
OFF
Show in Popover
ON
If access type selected ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
access_type
Choose access type... ?
Title
Select Dropbox access type
List (Lines)
App folder app_folder Full access dropbox
Multiple Selection
OFF
Show in Popover
ON
Set keychain value ?
Continue workflow ?
Variable Name
continue
Value
true
…End If
If app key selected ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
app_key
Get current keychain value ?
Request app key... ?
Title
Enter App Key
Initial Text
Input
  • Single Line
  • Multiple Lines
Keyboard Options:
Set keychain value ?
Continue workflow ?
Variable Name
continue
Value
true
…End If
If app secret selected ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
app_secret
Get current keychain value ?
Request app secret... ?
Title
Enter App Secret
Initial Text
Input
  • Single Line
  • Multiple Lines
Keyboard Options:
Set keychain value ?
Continue workflow ?
Variable Name
continue
Value
true
…End If
If access token selected ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
access_token
Reset skip flag ?
Variable Name
set_token
Value
true
Validate token if already set ?
Run the block if
access_token
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
<unset>
Show HUD ?
HUD Text
Validating token...
Duration
  • 1 Second
  • 2 Seconds
  • 3 Seconds
Icon
  • "Success"
  • "Error"
Validate Dropbox access token ?
Source Code
#coding: utf-8
import workflow, console, keychain
from dropbox import session, client
import pickle

console.show_activity()

dropbox_params_str = keychain.get_password('dropbox', 'all_params')
dropbox_params = pickle.loads(dropbox_params_str)

sess = session.DropboxSession(**dropbox_params['session'])
sess.set_token(**dropbox_params['token'])
dropbox_client = client.DropboxClient(sess)

try:
	account_info = dropbox_client.account_info()
	account_name = '{0} ({1})'.format(account_info['display_name'],account_info['email'])
	workflow.set_output(account_name)
except Exception as e:
		workflow.set_output('Invalid\n' + str(e))
Show token validation results ?
Title
Dropbox Token
Message
Token: Input
Button 1
Change
Output Value
change
Button 2
Cancel
Output Value
Button 3
(don't show)
Output Value
Show Cancel Button
OFF
If user doesn't want to change the token ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
change
Skip setting token ?
Variable Name
set_token
Value
false
…End If
…End If
If changing/setting token ?
Run the block if
set_token
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
true
Abort if access type not set ?
Run the block if
access_type
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
<unset>
Show HUD ?
HUD Text
Access type not set!
Duration
  • 1 Second
  • 2 Seconds
  • 3 Seconds
Icon
  • "Success"
  • "Error"
…End If
Abort if app key not set ?
Run the block if
app_key
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
<unset>
Show HUD ?
HUD Text
App Key not set!
Duration
  • 1 Second
  • 2 Seconds
  • 3 Seconds
Icon
  • "Success"
  • "Error"
…End If
Abort if app secret not set ?
Run the block if
app_secret
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
<unset>
Show HUD ?
HUD Text
App Secret not set!
Duration
  • 1 Second
  • 2 Seconds
  • 3 Seconds
Icon
  • "Success"
  • "Error"
…End If
Generate access token ?
Source Code
#coding: utf-8
import workflow, keychain
from dropbox import session
import pickle

access_type = keychain.get_password('dropbox', 'access_type')
app_key = keychain.get_password('dropbox', 'app_key')
app_secret = keychain.get_password('dropbox', 'app_secret')

sess = session.DropboxSession(app_key, app_secret, access_type)
request_token = sess.obtain_request_token()
url = sess.build_authorize_url(request_token)
token_str = pickle.dumps((request_token.key, request_token.secret))

workflow.set_variable('request_token', token_str)
workflow.set_output(url)
Open Dropbox in browser to authorize ?
Open in
  • In-App Browser
  • Default App / Safari
URL
Input
Tab
  • Last-used Tab
  • New Tab
  • Tab with ID:
Unique identifier
Wait until Loaded
OFF
Reveal Browser Automatically
ON
Display continuation message ?
Title
Dropbox Authorization
Message
Click the blue play/pause button on the right to continue after authorizing access via the Dropbox website.
Button 1
Proceed
Output Value
proceed
Button 2
(don't show)
Output Value
Button 3
(don't show)
Output Value
Show Cancel Button
OFF
Save access token ?
Source Code
#coding: utf-8
import workflow, keychain, console
from dropbox import session
import pickle

console.hide_output()

access_type = keychain.get_password('dropbox', 'access_type')
app_key = keychain.get_password('dropbox', 'app_key')
app_secret = keychain.get_password('dropbox', 'app_secret')
request_token_str = workflow.get_variable('request_token')
request_token_key, request_token_secret = pickle.loads(request_token_str)
request_token = session.OAuthToken(request_token_key, request_token_secret)

sess = session.DropboxSession(app_key, app_secret, access_type)
access_token = sess.obtain_access_token(request_token)

token_str = pickle.dumps((access_token.key, access_token.secret))
keychain.set_password('dropbox', 'access_token', token_str)

# Also store all the dropbox params in a single keychain item to 
# simplify process of establishing client sessions in the future.
# Use names that match arguments for Dropbox calls.
dropbox_params = {'session':{'access_type':access_type,
                             'consumer_key':app_key,
                             'consumer_secret':app_secret},
                  'token':{'access_token':access_token.key,
                           'access_token_secret':access_token.secret}}
dropbox_params_str = pickle.dumps(dropbox_params)
keychain.set_password('dropbox', 'all_params', dropbox_params_str)
…End If
Continue workflow ?
Variable Name
continue
Value
true
…End If
If reset selected ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
reset
Confirm reset of Dropbox settings ?
Title
Reset Dropbox Settings
Message
Are you sure you want to reset all Dropbox settings?
Button 1
Reset
Output Value
yes
Button 2
Cancel
Output Value
no
Button 3
(don't show)
Output Value
Show Cancel Button
OFF
If confirmed ?
Run the block if
Input
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
yes
Reset Dropbox settings ?
Source Code
#coding: utf-8
import keychain

keychain.delete_password('dropbox', 'access_type')	
keychain.delete_password('dropbox', 'app_key')
keychain.delete_password('dropbox', 'app_secret')
keychain.delete_password('dropbox', 'access_token')	
keychain.delete_password('dropbox', 'all_params')
…End If
Continue workflow ?
Variable Name
continue
Value
true
…End If
If not continuing, stop workflowk ?
Run the block if
continue
  • is Equal to
  • is Not Equal to
  • Contains
  • Doesn't Contain
  • Matches Regular Expression
true
Stop ?
Stop
  • This Workflow
  • Repeat Block
Show HUD Alert
OFF
Message
Stopped
…End If
…End Repeat
Stop if we make it this far (we shouldn't) ?
Stop
  • This Workflow
  • Repeat Block
Show HUD Alert
OFF
Message
Stopped
Sample Dropbox Action - All code within action ?
Source Code
#coding: utf-8
import workflow, keychain, pickle
from dropbox import session, client

dropbox_params_str = keychain.get_password('dropbox', 'all_params')
dropbox_params = pickle.loads(dropbox_params_str)

sess = session.DropboxSession(**dropbox_params['session'])
sess.set_token(**dropbox_params['token'])
dropbox_client = client.DropboxClient(sess)

# The code below puts the action input into the specified file path
file_path = 'Inbox/Sample.txt'
dropbox_client.put_file(file_path, workflow.get_input())
Sample Dropbox Action - Separate helper module ?
Source Code
#coding: utf-8

##############################################################

# This alternative action relies on loading a seprate module 
# with the code to estalish the Dropbox client connection. 
# This means you need to include a bit less boilerplate code
# in your actions that use Dropbox, and also have a module in
# place to include other helper functions as needed. 

# To do this, we need to modify the include path to find our
# module. The code immediately following is the sample action 
# code (with some additional comments) and further down is the 
# simple module code with instructions.

##############################################################

import sys, os

# Option 1 - A lib folder under Dropbox
sys.path += [os.path.join(os.getenv('HOME'), 'Library','Application Support','Dropbox', 'lib')]
# Option 2 - A lib folder in the local storage
# sys.path += [os.path.join(os.getenv('HOME'), 'Documents', 'lib')]

import dropbox_helper
dropbox_client = dropbox_helper.get_client()

# The code below puts the action input into the specified file path
file_path = 'Inbox/Sample.txt'
dropbox_client.put_file(file_path, workflow.get_input())

######################################################################

# The code below should be placed in a file named dropbox_helper.py
# and placed in a lib folder under either Dropbox or local storage, 
# which should match your selection above for the path modification.

# I recommed the Dropbox option (1) as that will allow you to edit 
# the file outside of Editorial (which isn't as friendly when editing
# python in the main editing interface) and have the file synced back
# to pick up changes. Note that while testing, you may need to reload
# the module to force python to pick up your changes: 
# i.e. enter 'reload(dropbox_helper)' at the console.

######################################################################

import workflow, keychain, pickle
from dropbox import session, client

def get_client():
	dropbox_params_str = keychain.get_password('dropbox', 'all_params')
	dropbox_params = pickle.loads(dropbox_params_str)

	sess = session.DropboxSession(**dropbox_params['session'])
	sess.set_token(**dropbox_params['token'])
	dropbox_client = client.DropboxClient(sess)
	
	return dropbox_client