Skip to content

Commit

Permalink
New web server for managing credentials and linking bank accounts (#10)
Browse files Browse the repository at this point in the history
* Check new web server into version control

* Log user sync before pushing to database

* Use `before_first_request` decorator to initialize db

* Run Flask app in `__main__`

* Rename `web-server` to `web_server` so it can be imported

* Add files necessary for gcloud app engine deployment

* Simplify module api to run new web server
  • Loading branch information
e13h authored Jul 15, 2022
1 parent f5c34f7 commit cbf250c
Show file tree
Hide file tree
Showing 27 changed files with 860 additions and 452 deletions.
3 changes: 0 additions & 3 deletions MANIFEST.in

This file was deleted.

21 changes: 2 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,19 @@ Create a Plaid developer account [here](https://dashboard.plaid.com/signup).
After you have created an account, go to Team Settings > Keys. You should see your `client_id`, as well as Development and Sandbox secrets.

#### Register the redirect URI in the Plaid Dashboard
Add the redirect URI to the [list of allowed redirect URIs in the Plaid Dashboard](https://dashboard.plaid.com/team/api). By default, the redirect URI is `https://localhost:8080/oauth`. In the next step (when you run the `init` command), you'll have the option to change the port number from the default to something else. If you change the port number, you **must** register the new redirect URI or else Plaid will reject your requests.

### Configure `gsheets_plaid`
To configure `gsheets_plaid` with all of these credentials we just created, run the following command:
```shell
python3 -m gsheets_plaid init
```
You will be given the opportunity to enter all the credentials necessary for syncing with Plaid and Google Sheets.
Note that you only need to supply the Plaid secret corresponding to the Plaid environment that `gsheets_plaid` runs in. In other words, you can just submit the Plaid sandbox secret and leave the development and production ones blank to start out. You can always come back and rerun `init` to update the config.

When it asks for the Google credentials JSON file, supply the absolute filepath to the JSON file we downloaded previously. Once you see that it is successfully saved, you can safely delete the copy of the credentials file from your downloads folder (or wherever you saved it).
Add the redirect URI to the [list of allowed redirect URIs in the Plaid Dashboard](https://dashboard.plaid.com/team/api). By default, the redirect URI is `https://localhost:8080/google-oauth-callback`.

### Link a bank account
We are finally getting to the exciting part!

If everything is configured correctly, running the following command will open a new browser tab with a small local web server you can use to connect a bank account.
```shell
python3 -m gsheets_plaid link
python3 -m gsheets_plaid
```
If you are using the `sandbox` environment, note that the credentials are provided at the bottom of the screen. If you are using the `development` environment, use your actual bank account credentials. Note that you are only given 5 tokens to use in the development environment, but if you submit a ticket on Plaid Dashboard, you can get it bumped up to 100 tokens, which should be more than plenty for personal usage.

Once you have added all the bank accounts you want, close the browser tab and enter `CTRL+C` in the terminal you started the `link` command in to kill the web server process.

### Sync transaction data with Google Sheets
To sync your transactions from the banks you signed in with, run this command in the terminal
```shell
python3 -m gsheets_plaid sync
```
If this is the first time you're running the command, you'll see a new browser tab open and be asked to give this developer application permission to use Google Sheets. You should only have to do this once. A new finance tracker spreadsheet will be created and the transaction data will be synced to `Sheet1`. Subsequent runs of this command will reuse the same spreadsheet.

That's it! Hopefully you're inspired to write some cool formulas and make neat charts using this raw transaction data.

---
Expand Down
79 changes: 12 additions & 67 deletions gsheets_plaid/__main__.py
Original file line number Diff line number Diff line change
@@ -1,72 +1,17 @@
import argparse
import sys
import os
import threading
import webbrowser
from time import sleep

from gsheets_plaid.data import (get_access_tokens, get_spreadsheet_id_from_file,
load_creds_from_file)
from gsheets_plaid.services import GOOGLE_SCOPES, generate_gsheets_service, generate_plaid_client
from gsheets_plaid.sync import get_spreadsheet_url
from dotenv import load_dotenv

# Main parser
description = 'Sync transaction data to Google Sheets using Plaid.'
parser = argparse.ArgumentParser(description=description, prog='gsheets_plaid')
parser.add_argument('-v', '--verbose', action='store_true', help='print verbose output')
subparsers = parser.add_subparsers(dest='action', required=True, metavar='sub-command')
from gsheets_plaid.web_server.main import run_web_server

load_dotenv(os.path.join(os.path.dirname(__file__), 'web_server/.env'))
t = threading.Thread(target=run_web_server, kwargs={'ssl_context': 'adhoc'})
t.start()
sleep(1) # Wait for the server to start

# Parser for the 'init' command
parser_init = subparsers.add_parser('init', help='initialize')


# Parser for the 'link' command
parser_link = subparsers.add_parser('link', help='link new accounts, manage existing accounts')
parser_link.add_argument(
'--env',
type=str,
choices=['sandbox', 'development', 'production'],
help='temporarily run with a different env type (does NOT change config)')


# Parser for the 'sync' command
parser_sync = subparsers.add_parser('sync', help='sync transactions from linked accounts')
parser_sync.add_argument('--days', type=int, default=30, help='number of days to sync')
parser_sync.add_argument(
'--env',
type=str,
choices=['sandbox', 'development', 'production'],
help='temporarily run with a different env type (does NOT change config)')

if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)


args = parser.parse_args()

from gsheets_plaid.initialization import CONFIG, is_initialized

if not is_initialized() and args.action != 'init':
parser.error('Please run "gsheets_plaid init" before running any other commands.')

if args.env:
CONFIG['PLAID_ENV'] = args.env

if args.action == 'init':
from gsheets_plaid.initialization import initialize
initialize()
elif args.action == 'link':
from gsheets_plaid.link import run_link_server
run_link_server(CONFIG['PLAID_LINK_PORT'])
elif args.action == 'sync':
from gsheets_plaid.sync import sync_transactions
plaid_env = CONFIG.get('PLAID_ENV')
plaid_secret = CONFIG.get(f'PLAID_SECRET_{plaid_env.upper()}', None)
if not plaid_secret:
raise ValueError(f'Either {plaid_env} is incorrect or PLAID_SECRET_{plaid_env.upper()} does not exist!')
gsheets_credentials = load_creds_from_file(GOOGLE_SCOPES)
gsheets_service = generate_gsheets_service(gsheets_credentials)
plaid_client = generate_plaid_client(plaid_env, CONFIG.get('PLAID_CLIENT_ID'), plaid_secret)
access_tokens = get_access_tokens()
spreadsheet_id = get_spreadsheet_id_from_file(gsheets_service, verbose=True)
sync_transactions(gsheets_service, plaid_client, access_tokens, spreadsheet_id, args.days)
webbrowser.open(get_spreadsheet_url(gsheets_service, spreadsheet_id), new=1, autoraise=True)
# Direct the user to Plaid Link
webbrowser.open('https://localhost:8080/', new=1, autoraise=True)
t.join()
85 changes: 0 additions & 85 deletions gsheets_plaid/data.py

This file was deleted.

98 changes: 0 additions & 98 deletions gsheets_plaid/initialization.py

This file was deleted.

21 changes: 0 additions & 21 deletions gsheets_plaid/link.py

This file was deleted.

Empty file.
11 changes: 0 additions & 11 deletions gsheets_plaid/resources/db/.env.example

This file was deleted.

Empty file.
Empty file.
Loading

0 comments on commit cbf250c

Please sign in to comment.