Add support for creating and listing OFXAccounts

This makes it so that we can add new accounts and show the accounts that
we already have. We don't do anything with them yet, but that's okay it
was interesting figuring out how to get them set up at all. I'm
currently storing the passwords as unencrypted, which I intend to
change, but it's going to take some time to research exactly how to
encrypt them so that the data is not retrievable by a bad actor with
access to the database.
This commit is contained in:
Eli Ribble 2016-06-21 07:51:36 -06:00
parent 91f89d2cbd
commit 104289418b
5 changed files with 113 additions and 16 deletions

View File

@ -1,7 +1,42 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block main_content %} {% block main_content %}
<h1>Accounts</h1> <h1>Accounts</h1>
{% if not accounts %} {% if accounts %}
<p>You don't have any accounts yet. Let's create some</p> <table class="table">
<tr><th>Name</th><th>Type</th><th>Institution</th></tr>
{% for account in accounts %}
<tr>
<td>{{ account.name }}</td>
<td>{{ account.type }}</td>
<td>{{ account.institution }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>You don't have any accounts yet. Let's create some</p>
{% endif %} {% endif %}
<h1>Add new account</h1>
<form method="POST" action="/account/">
<div class="form-group">
<label for="name">Name</label>
<input id="name" type="text" name="name" class="form-control" placeholder="My OFX account"></input>
<label for="institution">Institution</label>
<input id="institution" type="text" name="institution" class="form-control" list="institutions"></input>
<label for="userid">User ID</label>
<input id="userid" type="text" name="userid" class="form-control" placeholder="123456"></input>
<label for="password">Password</label>
<input id="password" type="password" name="password" class="form-control" placeholder="1234"></input>
<label for="type">Account Type</label>
<select id="account_type" value="checking" name="account_type" class="form-control">
<option value="checking">Checking</option>
<option value="checking">Savings</option>
</select>
<input class="btn btn-primary form-control" type="submit" value="Create Account"></input>
<datalist id="institutions">
{% for source in sources %}
<option value="{{ source.name }}">{{ source.name }}</option>
{% endfor %}
</datalist>
</div>
</form>
{% endblock %} {% endblock %}

View File

@ -8,6 +8,7 @@
<input id="username" type="text" name="username" class="form-control"></input> <input id="username" type="text" name="username" class="form-control"></input>
<label for="password">password</label> <label for="password">password</label>
<input id="password" type="password" name="password" class="form-control"></input> <input id="password" type="password" name="password" class="form-control"></input>
<input class="btn btn-primary" type="submit" value="Log in" class="form-control"></input> <input class="btn btn-primary form-control" type="submit" value="Log in"></input>
</div>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -1,8 +1,24 @@
import flask import flask
import vanth.platform.ofxaccount
import vanth.platform.ofxsource
blueprint = flask.Blueprint('accounts', __name__) blueprint = flask.Blueprint('accounts', __name__)
@blueprint.route('/accounts/') @blueprint.route('/accounts/', methods=['GET'])
def accounts(): def get_accounts():
my_accounts = [] my_accounts = vanth.platform.ofxaccount.get(flask.session['user_id'])
return flask.render_template('accounts.html', accounts=my_accounts) sources = vanth.platform.ofxsource.get()
return flask.render_template('accounts.html', accounts=my_accounts, sources=sources)
@blueprint.route('/account/', methods=['POST'])
def post_account():
account_type = flask.request.form.get('account_type')
institution = flask.request.form.get('institution')
name = flask.request.form.get('name')
password = flask.request.form.get('password')
userid = flask.request.form.get('userid')
vanth.platform.ofxaccount.create(flask.session['user_id'], name, account_type, institution, password, userid)
return flask.redirect('/accounts/')

View File

@ -0,0 +1,52 @@
import uuid
import chryso.connection
import sqlalchemy
import vanth.platform.ofxsource
import vanth.tables
def get(user_id):
engine = chryso.connection.get()
query = sqlalchemy.select([
vanth.tables.OFXSource.c.name.label('institution'),
vanth.tables.OFXAccount.c.name,
vanth.tables.OFXAccount.c.source,
vanth.tables.OFXAccount.c.type,
vanth.tables.OFXAccount.c.user_id,
vanth.tables.OFXAccount.c.uuid,
]).where(
vanth.tables.OFXAccount.c.source == vanth.tables.OFXSource.c.uuid
).where(
vanth.tables.OFXAccount.c.owner == user_id
)
results = engine.execute(query)
return [{
'institution' : result[vanth.tables.OFXSource.c.name.label('institution')],
'name' : result[vanth.tables.OFXAccount.c.name],
'source' : result[vanth.tables.OFXAccount.c.source],
'type' : result[vanth.tables.OFXAccount.c.type],
'user_id' : result[vanth.tables.OFXAccount.c.user_id],
'uuid' : result[vanth.tables.OFXAccount.c.uuid],
} for result in results]
def create(user_id, name, account_type, institution, password, account_user):
engine = chryso.connection.get()
source_name = sqlalchemy.select([
vanth.tables.OFXSource.c.uuid
]).where(vanth.tables.OFXSource.c.name == institution)
_uuid = uuid.uuid4()
statement = vanth.tables.OFXAccount.insert().values( # pylint: disable=no-value-for-parameter
uuid = _uuid,
name = name,
user_id = account_user,
password = password,
type = account_type,
source = source_name,
owner = user_id,
)
engine.execute(statement)
return _uuid

View File

@ -1,20 +1,13 @@
import logging import logging
import chryso.connection import chryso.connection
import sepiida.routing
import vanth.tables import vanth.tables
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
def by_filter(filters): def get():
engine = chryso.connection.get() engine = chryso.connection.get()
LOGGER.debug("Getting ofxsources by filter %s", filters)
query = vanth.tables.OFXSource.select() query = vanth.tables.OFXSource.select()
results = engine.execute(query).fetchall() results = engine.execute(query).fetchall()
return [{ return [dict(result) for result in results]
'name' : result[vanth.tables.OFXSource.c.name],
'fid' : result[vanth.tables.OFXSource.c.fid],
'bankid' : result[vanth.tables.OFXSource.c.bankid],
'uri' : sepiida.routing.uri('ofxsource', result[vanth.tables.OFXSource.c.uuid]),
} for result in results]