Skip to content

Commit

Permalink
Merge pull request #167 from /issues/155
Browse files Browse the repository at this point in the history
Fixes #155 - ofxgetter shouldn't try importing settings when running remote
  • Loading branch information
jantman authored Jan 7, 2018
2 parents f5ee376 + 0740502 commit cee477e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Unreleased Changes
* `Issue #163 <https://github.com/jantman/biweeklybudget/issues/163>`_ - Include next payment amount on Credit Payoffs view.
* `Issue #84 <https://github.com/jantman/biweeklybudget/issues/84>`_ - Remove vendored-in ``ofxparse`` package now that `my PR #127 <https://github.com/jseutter/ofxparse/pull/127>`_ has been merged and released on PyPI. **Important note:** The version of ofxparse is changed in this release. If you are using ``ofxgetter -r`` (remote API mode), the versions of ofxparse (and therefore biweeklybudget/ofxgetter) must match between the client and server.
* `Issue #165 <https://github.com/jantman/biweeklybudget/issues/165>`_ - Remove vendored-in ``wishlist`` package now that `my PR #8 <https://github.com/Jaymon/wishlist/pull/8>`_ has been merged and released on PyPI.
* `Issue #155 <https://github.com/jantman/biweeklybudget/issues/155>`_ - Refactor ofxgetter to fix bug where ``SETTINGS_MODULE`` was still required even if running remotely.

0.6.0 (2017-11-11)
------------------
Expand Down
21 changes: 18 additions & 3 deletions biweeklybudget/backfill_ofx.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
from ofxparse import OfxParser
from sqlalchemy.exc import InvalidRequestError, IntegrityError

from biweeklybudget import settings
from biweeklybudget.cliutils import set_log_debug, set_log_info
from biweeklybudget.ofxapi import apiclient
from biweeklybudget.ofxapi.exceptions import DuplicateFileException
Expand Down Expand Up @@ -79,7 +78,7 @@ def run(self):
logger.debug('Checking for Accounts with statement directories')
accounts = self._client.get_accounts()
for acctname in sorted(accounts.keys()):
p = os.path.join(settings.STATEMENTS_SAVE_PATH, acctname)
p = os.path.join(self.savedir, acctname)
data = accounts[acctname]
if not os.path.isdir(p):
logger.info('No statement directory for Account %d (%s)',
Expand Down Expand Up @@ -160,6 +159,10 @@ def parse_args():
default=None,
help='biweeklybudget API URL to use instead of direct DB '
'access')
p.add_argument('-s', '--save-path', dest='save_path', action='store',
type=str, default=None,
help='Statement save path; must be specified when running '
'in remote (-r) mode.')
p.add_argument('--ca-bundle', dest='ca_bundle', action='store', type=str,
default=None,
help='Path to CA certificate bundle file or directory to '
Expand Down Expand Up @@ -197,8 +200,20 @@ def main():
api_url=args.remote, ca_bundle=args.ca_bundle,
client_cert=args.client_cert, client_key=args.client_key
)
cls = OfxBackfiller(client, settings.STATEMENTS_SAVE_PATH)

if args.remote is None:
from biweeklybudget import settings
save_path = settings.STATEMENTS_SAVE_PATH
else:
if args.save_path is None:
logger.error('ERROR: -s|--save-path must be specified when running '
'in remote mode.')
raise SystemExit(1)
save_path = os.path.abspath(args.save_path)

cls = OfxBackfiller(client, save_path)
cls.run()


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion biweeklybudget/ofxapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"""
import logging

from biweeklybudget.ofxapi.local import OfxApiLocal
from biweeklybudget.ofxapi.remote import OfxApiRemote

logger = logging.getLogger(__name__)
Expand All @@ -49,6 +48,7 @@ def apiclient(api_url=None, ca_bundle=None, client_cert=None, client_key=None):
from biweeklybudget.db import init_db, cleanup_db, db_session
atexit.register(cleanup_db)
init_db()
from biweeklybudget.ofxapi.local import OfxApiLocal
return OfxApiLocal(db_session)
logger.info('Using OfxApiRemote with base_url %s', api_url)
return OfxApiRemote(
Expand Down
19 changes: 16 additions & 3 deletions biweeklybudget/ofxgetter.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
from biweeklybudget.vendored.ofxclient.account \
import Account as OfxClientAccount

from biweeklybudget.utils import Vault
from biweeklybudget import settings
from biweeklybudget.vault import Vault
from biweeklybudget.cliutils import set_log_debug, set_log_info
from biweeklybudget.ofxapi import apiclient

Expand Down Expand Up @@ -258,6 +257,10 @@ def parse_args():
type=str, default=None,
help='path to unencrypted client key to use for SSL client '
'cert auth, if key is not contained in the cert file')
p.add_argument('-s', '--save-path', dest='save_path', action='store',
type=str, default=None,
help='Statement save path; must be specified when running '
'in remote (-r) mode.')
p.add_argument('ACCOUNT_NAME', type=str, action='store', default=None,
nargs='?',
help='Account name; omit to download all accounts')
Expand Down Expand Up @@ -294,7 +297,17 @@ def main():
print(k)
raise SystemExit(0)

getter = OfxGetter(client, settings.STATEMENTS_SAVE_PATH)
if args.remote is None:
from biweeklybudget import settings
save_path = settings.STATEMENTS_SAVE_PATH
else:
if args.save_path is None:
logger.error('ERROR: -s|--save-path must be specified when running '
'in remote mode.')
raise SystemExit(1)
save_path = os.path.abspath(args.save_path)

getter = OfxGetter(client, save_path)
if args.ACCOUNT_NAME is not None:
getter.get_ofx(args.ACCOUNT_NAME)
raise SystemExit(0)
Expand Down
49 changes: 0 additions & 49 deletions biweeklybudget/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"""

import os
import hvac
import logging
from biweeklybudget import settings
from datetime import datetime
Expand Down Expand Up @@ -132,51 +131,3 @@ def in_directory(path):
os.chdir(path)
yield os.path.abspath(path)
os.chdir(pwd)


class SecretMissingException(Exception):

def __init__(self, path):
self.path = path

def __str__(self):
return repr(self.path)


class Vault(object):
"""
Provides simpler access to Vault
"""

def __init__(self, addr=settings.VAULT_ADDR,
token_path=settings.TOKEN_PATH):
"""
Connect to Vault and maintain connection
:param addr: URL to connect to Vault at
:type addr: str
:param token_path: path to read Vault token from
:type token_path: str
"""
token_path = os.path.expanduser(token_path)
logger.debug('Connecting to Vault at %s with token from %s',
addr, token_path)
with open(token_path, 'r') as fh:
tkn = fh.read().strip()
self.conn = hvac.Client(url=addr, token=tkn)
assert self.conn.is_authenticated()
logger.debug('Connected to Vault')

def read(self, secret_path):
"""
Read and return a secret from Vault. Return only the data portion.
:param secret_path: path to read in Vault
:type secret_path: str
:return: secret data
:rtype: dict
"""
res = self.conn.read(secret_path)
if res is None:
raise SecretMissingException(secret_path)
return res['data']
109 changes: 109 additions & 0 deletions biweeklybudget/vault.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
The latest version of this package is available at:
<http://github.com/jantman/biweeklybudget>
################################################################################
Copyright 2016 Jason Antman <[email protected]> <http://www.jasonantman.com>
This file is part of biweeklybudget, also known as biweeklybudget.
biweeklybudget is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
biweeklybudget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with biweeklybudget. If not, see <http://www.gnu.org/licenses/>.
The Copyright and Authors attributions contained herein may not be removed or
otherwise altered, except to add the Author attribution of a contributor to
this work. (Additional Terms pursuant to Section 7b of the AGPL v3)
################################################################################
While not legally required, I sincerely request that anyone who finds
bugs please submit them at <https://github.com/jantman/biweeklybudget> or
to me via email, and that you send any contributions or improvements
either as a pull request on GitHub, or to me via email.
################################################################################
AUTHORS:
Jason Antman <[email protected]> <http://www.jasonantman.com>
################################################################################
"""

import os
import hvac
import logging

logger = logging.getLogger(__name__)


class SecretMissingException(Exception):

def __init__(self, path):
self.path = path

def __str__(self):
return repr(self.path)


class Vault(object):
"""
Provides simpler access to Vault
"""

def __init__(self, addr=None, token_path=None):
"""
Connect to Vault and maintain connection
:param addr: URL to connect to Vault at. If None, defaults to
:py:attr:`biweeklybudget.settings.VAULT_ADDR`.
:type addr: str
:param token_path: path to read Vault token from. If None, defaults to
:py:attr:`biweeklybudget.settings.TOKEN_PATH`.
:type token_path: str
"""
if addr is None and 'VAULT_ADDR' in os.environ:
addr = os.environ['VAULT_ADDR']
if token_path is None and 'TOKEN_PATH' in os.environ:
token_path = os.environ['TOKEN_PATH']
# if not in constructor or environment, use settings if possible
if addr is None or token_path is None:
try:
from biweeklybudget import settings
if addr is None:
addr = settings.VAULT_ADDR
if token_path is None:
token_path = settings.TOKEN_PATH
except Exception:
logger.error('ERROR: you must either set the SETTINGS_MODULE '
'environment variable to use a settings module, '
'or export VAULT_ADDR and TOKEN_PATH environment '
'variables.')
raise SystemExit(1)
token_path = os.path.expanduser(token_path)
logger.debug('Connecting to Vault at %s with token from %s',
addr, token_path)
with open(token_path, 'r') as fh:
tkn = fh.read().strip()
self.conn = hvac.Client(url=addr, token=tkn)
assert self.conn.is_authenticated()
logger.debug('Connected to Vault')

def read(self, secret_path):
"""
Read and return a secret from Vault. Return only the data portion.
:param secret_path: path to read in Vault
:type secret_path: str
:return: secret data
:rtype: dict
"""
res = self.conn.read(secret_path)
if res is None:
raise SecretMissingException(secret_path)
return res['data']

0 comments on commit cee477e

Please sign in to comment.