aboutsummaryrefslogtreecommitdiff
path: root/wqflask
diff options
context:
space:
mode:
Diffstat (limited to 'wqflask')
-rw-r--r--wqflask/base/trait.py8
-rw-r--r--wqflask/utility/hmac.py56
-rw-r--r--wqflask/wqflask/collect.py247
-rw-r--r--wqflask/wqflask/correlation/corr_scatter_plot.py9
-rw-r--r--wqflask/wqflask/gsearch.py4
-rw-r--r--wqflask/wqflask/search_results.py2
-rw-r--r--wqflask/wqflask/templates/base.html4
-rw-r--r--wqflask/wqflask/templates/collections/list.html24
-rw-r--r--wqflask/wqflask/templates/collections/view.html9
-rw-r--r--wqflask/wqflask/templates/new_security/login_user.html1
-rw-r--r--wqflask/wqflask/templates/show_trait_mapping_tools.html11
-rw-r--r--wqflask/wqflask/templates/show_trait_statistics.html6
-rw-r--r--wqflask/wqflask/user_login.py8
-rw-r--r--wqflask/wqflask/user_session.py551
-rw-r--r--wqflask/wqflask/views.py2
15 files changed, 375 insertions, 567 deletions
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index c9dfe780..8e779a11 100644
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -303,7 +303,7 @@ def jsonable_table_row(trait, dataset_name, index):
additive = "N/A"
else:
additive = "%.3f" % round(float(trait.additive), 2)
- return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.hmac_creation('{}:{}'.format(str(trait.name), dataset.name)) + '">',
+ return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.data_hmac('{}:{}'.format(str(trait.name), dataset.name)) + '">',
index,
'<a href="/show_trait?trait_id='+str(trait.name)+'&dataset='+dataset.name+'">'+str(trait.name)+'</a>',
trait.symbol,
@@ -319,7 +319,7 @@ def jsonable_table_row(trait, dataset_name, index):
else:
additive = "%.2f" % round(float(trait.additive), 2)
if trait.pubmed_id:
- return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.hmac_creation('{}:{}'.format(str(trait.name), dataset.name)) + '">',
+ return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.data_hmac('{}:{}'.format(str(trait.name), dataset.name)) + '">',
index,
'<a href="/show_trait?trait_id='+str(trait.name)+'&dataset='+dataset.name+'">'+str(trait.name)+'</a>',
trait.description_display,
@@ -329,7 +329,7 @@ def jsonable_table_row(trait, dataset_name, index):
trait.LRS_location_repr,
additive]
else:
- return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.hmac_creation('{}:{}'.format(str(trait.name), dataset.name)) + '">',
+ return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.data_hmac('{}:{}'.format(str(trait.name), dataset.name)) + '">',
index,
'<a href="/show_trait?trait_id='+str(trait.name)+'&dataset='+dataset.name+'">'+str(trait.name)+'</a>',
trait.description_display,
@@ -339,7 +339,7 @@ def jsonable_table_row(trait, dataset_name, index):
trait.LRS_location_repr,
additive]
elif dataset.type == "Geno":
- return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.hmac_creation('{}:{}'.format(str(trait.name), dataset.name)) + '">',
+ return ['<input type="checkbox" name="searchResult" class="checkbox trait_checkbox" value="' + hmac.data_hmac('{}:{}'.format(str(trait.name), dataset.name)) + '">',
index,
'<a href="/show_trait?trait_id='+str(trait.name)+'&dataset='+dataset.name+'">'+str(trait.name)+'</a>',
trait.location_repr]
diff --git a/wqflask/utility/hmac.py b/wqflask/utility/hmac.py
index 47001e54..d8a0eace 100644
--- a/wqflask/utility/hmac.py
+++ b/wqflask/utility/hmac.py
@@ -1,18 +1,38 @@
-from __future__ import print_function, division, absolute_import
-
-import hmac
-
-from wqflask import app
-
-def hmac_creation(stringy):
- """Helper function to create the actual hmac"""
-
- secret = app.config['SECRET_HMAC_CODE']
-
- hmaced = hmac.new(secret, stringy, hashlib.sha1)
- hm = hmaced.hexdigest()
- # ZS: Leaving the below comment here to ask Pjotr about
- # "Conventional wisdom is that you don't lose much in terms of security if you throw away up to half of the output."
- # http://www.w3.org/QA/2009/07/hmac_truncation_in_xml_signatu.html
- hm = hm[:20]
- return hm \ No newline at end of file
+from __future__ import print_function, division, absolute_import
+
+import hmac
+import hashlib
+
+from wqflask import app
+
+def hmac_creation(stringy):
+ """Helper function to create the actual hmac"""
+
+ secret = app.config['SECRET_HMAC_CODE']
+
+ hmaced = hmac.new(secret, stringy, hashlib.sha1)
+ hm = hmaced.hexdigest()
+ # ZS: Leaving the below comment here to ask Pjotr about
+ # "Conventional wisdom is that you don't lose much in terms of security if you throw away up to half of the output."
+ # http://www.w3.org/QA/2009/07/hmac_truncation_in_xml_signatu.html
+ hm = hm[:20]
+ return hm
+
+def data_hmac(stringy):
+ """Takes arbitray data string and appends :hmac so we know data hasn't been tampered with"""
+ return stringy + ":" + hmac_creation(stringy)
+
+def url_for_hmac(endpoint, **values):
+ """Like url_for but adds an hmac at the end to insure the url hasn't been tampered with"""
+
+ url = url_for(endpoint, **values)
+
+ hm = hmac_creation(url)
+ if '?' in url:
+ combiner = "&"
+ else:
+ combiner = "?"
+ return url + combiner + "hm=" + hm
+
+app.jinja_env.globals.update(url_for_hmac=url_for_hmac,
+ data_hmac=data_hmac) \ No newline at end of file
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index c273af59..e5c24873 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -8,7 +8,6 @@ import time
import uuid
import hashlib
-import hmac
import base64
import urlparse
@@ -28,9 +27,8 @@ from pprint import pformat as pf
from wqflask.database import db_session
from wqflask import model
-from wqflask import user_manager
-from utility import Bunch, Struct
+from utility import Bunch, Struct, hmac
from utility.formatting import numify
from base import trait
@@ -40,119 +38,15 @@ import logging
from utility.logger import getLogger
logger = getLogger(__name__)
-
-class AnonCollection(object):
- """User is not logged in"""
- def __init__(self, collection_name):
- anon_user = user_manager.AnonUser()
- self.key = anon_user.key
- self.name = collection_name
- self.id = None
- self.created_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
- self.changed_timestamp = self.created_timestamp #ZS: will be updated when changes are made
-
- #ZS: Find id and set it if the collection doesn't already exist
- if Redis.get(self.key) == "None" or Redis.get(self.key) == None:
- Redis.set(self.key, "None") #ZS: For some reason I get the error "Operation against a key holding the wrong kind of value" if I don't do this
- else:
- collections_list = json.loads(Redis.get(self.key))
- collection_position = 0 #ZS: Position of collection in collection_list, if it exists
- collection_exists = False
- for i, collection in enumerate(collections_list):
- if collection['name'] == self.name:
- collection_position = i
- collection_exists = True
- self.id = collection['id']
- break
-
- if self.id == None:
- self.id = str(uuid.uuid4())
-
- def get_members(self):
- traits = []
- collections_list = json.loads(Redis.get(self.key))
- for collection in collections_list:
- if collection['id'] == self.id:
- traits = collection['members']
- return traits
-
- @property
- def num_members(self):
- num_members = 0
- collections_list = json.loads(Redis.get(self.key))
- for collection in collections_list:
- if collection['id'] == self.id:
- num_members = collection['num_members']
- return num_members
-
- def add_traits(self, unprocessed_traits):
- #assert collection_name == "Default", "Unexpected collection name for anonymous user"
- self.traits = list(process_traits(unprocessed_traits))
- existing_collections = Redis.get(self.key)
- logger.debug("existing_collections:", existing_collections)
- if existing_collections != None and existing_collections != "None":
- collections_list = json.loads(existing_collections)
- collection_position = 0 #ZS: Position of collection in collection_list, if it exists
- collection_exists = False
- for i, collection in enumerate(collections_list):
- if collection['id'] == self.id:
- collection_position = i
- collection_exists = True
- break
- if collection_exists:
- collections_list[collection_position]['members'] += list(set(self.traits) - set(collections_list[collection_position]['members']))
- collections_list[collection_position]['num_members'] = len(collections_list[collection_position]['members'])
- collections_list[collection_position]['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
- else:
- collection_dict = {"id" : self.id,
- "name" : self.name,
- "created_timestamp" : self.created_timestamp,
- "changed_timestamp" : self.changed_timestamp,
- "num_members" : len(self.traits),
- "members" : self.traits}
- collections_list.append(collection_dict)
- else:
- collections_list = []
- collection_dict = {"id" : self.id,
- "name" : self.name,
- "created_timestamp" : self.created_timestamp,
- "changed_timestamp" : self.changed_timestamp,
- "num_members" : len(self.traits),
- "members" : self.traits}
- collections_list.append(collection_dict)
-
- Redis.set(self.key, json.dumps(collections_list))
-
- def remove_traits(self, params):
- traits_to_remove = [(":").join(trait.split(":")[:2]) for trait in params.getlist('traits[]')]
- existing_collections = Redis.get(self.key)
- collection_position = 0
- collections_list = json.loads(existing_collections)
- for i, collection in enumerate(collections_list):
- if collection['id'] == self.id:
- collection_position = i
- collection_exists = True
- break
- collections_list[collection_position]['members'] = [trait for trait in collections_list[collection_position]['members'] if trait not in traits_to_remove]
- collections_list[collection_position]['num_members'] = len(collections_list[collection_position]['members'])
- collections_list[collection_position]['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
- len_now = collections_list[collection_position]['num_members']
- Redis.set(self.key, json.dumps(collections_list))
-
- # We need to return something so we'll return this...maybe in the future
- # we can use it to check the results
- return str(len_now)
-
def process_traits(unprocessed_traits):
if isinstance(unprocessed_traits, basestring):
unprocessed_traits = unprocessed_traits.split(",")
traits = set()
for trait in unprocessed_traits:
- #print("trait is:", trait)
data, _separator, hmac = trait.rpartition(':')
data = data.strip()
if g.user_session.logged_in:
- assert hmac==user_manager.actual_hmac_creation(data), "Data tampering?"
+ assert hmac == hmac.data_hmac(data), "Data tampering?"
traits.add(str(data))
return traits
@@ -160,8 +54,6 @@ def process_traits(unprocessed_traits):
def report_change(len_before, len_now):
new_length = len_now - len_before
if new_length:
- logger.debug("We've added {} to your collection.".format(
- numify(new_length, 'new trait', 'new traits')))
flash("We've added {} to your collection.".format(
numify(new_length, 'new trait', 'new traits')))
else:
@@ -180,18 +72,14 @@ def store_traits_list():
@app.route("/collections/add")
def collections_add():
- if g.user_session.logged_in:
+
+ collections = g.user_session.user_collections
+ if len(collections) < 1:
+ collection_name = "Default Collection"
+ uc_id = g.user_session.add_collection(collection_name, set())
collections = g.user_session.user_collections
- if len(collections) < 1:
- collection_name = "Default Collection"
- uc_id = g.user_session.add_collection(collection_name, set())
- collections = g.user_session.user_collections
- else:
- anon_collections = user_manager.AnonUser().get_collections()
- collections = []
- for collection in anon_collections:
- collections.append({'id':collection['id'], 'name':collection['name']})
+ #ZS: One of these might be unnecessary
if 'traits' in request.args:
traits=request.args['traits']
return render_template("collections/add.html",
@@ -212,19 +100,13 @@ def collections_new():
if "sign_in" in params:
return redirect(url_for('login'))
if "create_new" in params:
- logger.debug("in create_new")
collection_name = params['new_collection']
if collection_name.strip() == "":
collection_name = datetime.datetime.utcnow().strftime('Collection_%b_%d_%H:%M')
return create_new(collection_name)
elif "add_to_existing" in params:
- logger.debug("in add to existing")
if 'existing_collection' not in params:
- default_collection_exists = False
- if g.user_session.logged_in:
- collections = g.user_session.user_collections
- else:
- collections = user_manager.AnonUser().get_collections()
+ collections = g.user_session.user_collections
for collection in collections:
if collection["name"] == "Default Collection":
collection_id = collection["id"]
@@ -235,22 +117,14 @@ def collections_new():
else:
collection_id = params['existing_collection'].split(":")[0]
collection_name = params['existing_collection'].split(":")[1]
- if g.user_session.logged_in:
- if "hash" in params:
- unprocessed_traits = Redis.get(params['hash'])
- else:
- unprocessed_traits = params['traits']
- traits = list(process_traits(unprocessed_traits))
- g.user_session.add_traits_to_collection(collection_id, traits)
- return redirect(url_for('view_collection', uc_id=collection_id))
+
+ if "hash" in params:
+ unprocessed_traits = Redis.get(params['hash'])
else:
- ac = AnonCollection(collection_name)
- if "hash" in params:
- unprocessed_traits = Redis.get(params['hash'])
- else:
- unprocessed_traits = params['traits']
- ac.add_traits(unprocessed_traits)
- return redirect(url_for('view_collection', collection_id=ac.id))
+ unprocessed_traits = params['traits']
+ traits = list(process_traits(unprocessed_traits))
+ g.user_session.add_traits_to_collection(collection_id, traits)
+ return redirect(url_for('view_collection', uc_id=collection_id))
else:
CauseAnError
@@ -265,50 +139,30 @@ def create_new(collection_name):
traits = process_traits(unprocessed_traits)
- if g.user_session.logged_in:
- uc_id = g.user_session.add_collection(collection_name, traits)
+ uc_id = g.user_session.add_collection(collection_name, traits)
- return redirect(url_for('view_collection', uc_id=uc_id))
- else:
- ac = AnonCollection(collection_name)
- ac.changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
- ac.add_traits(unprocessed_traits)
- return redirect(url_for('view_collection', collection_id=ac.id))
+ return redirect(url_for('view_collection', uc_id=uc_id))
@app.route("/collections/list")
def list_collections():
params = request.args
- if g.user_session.logged_in:
- user_collections = list(g.user_session.user_collections)
- #logger.debug("user_collections are:", user_collections)
- return render_template("collections/list.html",
- params = params,
- collections = user_collections,
- )
- else:
- anon_collections = user_manager.AnonUser().get_collections()
- #logger.debug("anon_collections are:", anon_collections)
- return render_template("collections/list.html",
- params = params,
- collections = anon_collections)
-
+ user_collections = list(g.user_session.user_collections)
+ return render_template("collections/list.html",
+ params = params,
+ collections = user_collections,
+ )
@app.route("/collections/remove", methods=('POST',))
def remove_traits():
params = request.form
- if "uc_id" in params:
- uc_id = params['uc_id']
- traits_to_remove = params.getlist('traits[]')
- traits_to_remove = process_traits(traits_to_remove)
- logger.debug("\n\n after processing, traits_to_remove:", traits_to_remove)
-
- members_now = g.user_session.remove_traits_from_collection(uc_id, traits_to_remove)
- else:
- collection_name = params['collection_name']
- members_now = AnonCollection(collection_name).remove_traits(params)
+ uc_id = params['uc_id']
+ traits_to_remove = params.getlist('traits[]')
+ traits_to_remove = process_traits(traits_to_remove)
+ logger.debug("\n\n after processing, traits_to_remove:", traits_to_remove)
+ members_now = g.user_session.remove_traits_from_collection(uc_id, traits_to_remove)
# We need to return something so we'll return this...maybe in the future
# we can use it to check the results
@@ -319,21 +173,13 @@ def remove_traits():
def delete_collection():
params = request.form
uc_id = ""
- if g.user_session.logged_in:
- uc_id = params['uc_id']
- if len(uc_id.split(":")) > 1:
- for this_uc_id in uc_id.split(":"):
- collection_name = g.user_session.delete_collection(this_uc_id)
- else:
- collection_name = g.user_session.delete_collection(uc_id)
+
+ uc_id = params['uc_id']
+ if len(uc_id.split(":")) > 1:
+ for this_uc_id in uc_id.split(":"):
+ collection_name = g.user_session.delete_collection(this_uc_id)
else:
- if "collection_name" in params:
- collection_name = params['collection_name']
- user_manager.AnonUser().delete_collection(collection_name)
- else:
- uc_id = params['uc_id']
- for this_collection in uc_id.split(":"):
- user_manager.AnonUser().delete_collection(this_collection)
+ collection_name = g.user_session.delete_collection(uc_id)
if uc_id != "":
if len(uc_id.split(":")) > 1:
@@ -350,19 +196,9 @@ def delete_collection():
def view_collection():
params = request.args
- if g.user_session.logged_in and "uc_id" in params:
- uc_id = params['uc_id']
- uc = (collection for collection in g.user_session.user_collections if collection["id"] == uc_id).next()
- traits = uc["members"]
- else:
- user_collections = json.loads(Redis.get(user_manager.AnonUser().key))
- this_collection = {}
- for collection in user_collections:
- if collection['id'] == params['collection_id']:
- this_collection = collection
- break
-
- traits = this_collection['members']
+ uc_id = params['uc_id']
+ uc = (collection for collection in g.user_session.user_collections if collection["id"] == uc_id).next()
+ traits = uc["members"]
trait_obs = []
json_version = []
@@ -381,12 +217,9 @@ def view_collection():
json_version.append(trait.jsonable(trait_ob))
- if "uc_id" in params:
- collection_info = dict(trait_obs=trait_obs,
- uc = uc)
- else:
- collection_info = dict(trait_obs=trait_obs,
- collection_name=this_collection['name'])
+ collection_info = dict(trait_obs=trait_obs,
+ uc = uc)
+
if "json" in params:
return json.dumps(json_version)
else:
diff --git a/wqflask/wqflask/correlation/corr_scatter_plot.py b/wqflask/wqflask/correlation/corr_scatter_plot.py
index f8eca386..dfb81c54 100644
--- a/wqflask/wqflask/correlation/corr_scatter_plot.py
+++ b/wqflask/wqflask/correlation/corr_scatter_plot.py
@@ -71,15 +71,8 @@ class CorrScatterPlot(object):
sr_intercept_coords = get_intercept_coords(srslope, srintercept, sr_range, sr_range)
- #vals_3 = []
- #for sample in self.trait_3.data:
- # vals_3.append(self.trait_3.data[sample].value)
-
self.collections_exist = "False"
- if g.user_session.logged_in:
- if g.user_session.num_collections > 0:
- self.collections_exist = "True"
- elif g.cookie_session.display_num_collections() != "":
+ if g.user_session.num_collections > 0:
self.collections_exist = "True"
self.js_data = dict(
diff --git a/wqflask/wqflask/gsearch.py b/wqflask/wqflask/gsearch.py
index ed3b74b8..12813e9a 100644
--- a/wqflask/wqflask/gsearch.py
+++ b/wqflask/wqflask/gsearch.py
@@ -70,7 +70,7 @@ class GSearch(object):
this_trait['name'] = line[5]
this_trait['dataset'] = line[3]
this_trait['dataset_fullname'] = line[4]
- this_trait['hmac'] = hmac.hmac_creation('{}:{}'.format(line[5], line[3]))
+ this_trait['hmac'] = hmac.data_hmac('{}:{}'.format(line[5], line[3]))
this_trait['species'] = line[0]
this_trait['group'] = line[1]
this_trait['tissue'] = line[2]
@@ -174,7 +174,7 @@ class GSearch(object):
this_trait['display_name'] = this_trait['name']
this_trait['dataset'] = line[2]
this_trait['dataset_fullname'] = line[3]
- this_trait['hmac'] = hmac.hmac_creation('{}:{}'.format(line[4], line[2]))
+ this_trait['hmac'] = hmac.data_hmac('{}:{}'.format(line[4], line[2]))
this_trait['species'] = line[0]
this_trait['group'] = line[1]
if line[9] != None and line[6] != None:
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index 902317a4..34c647f4 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -120,7 +120,7 @@ views.py).
else:
trait_dict['display_name'] = this_trait.name
trait_dict['dataset'] = this_trait.dataset.name
- trait_dict['hmac'] = hmac.hmac_creation('{}:{}'.format(this_trait.name, this_trait.dataset.name))
+ trait_dict['hmac'] = hmac.data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name))
if this_trait.dataset.type == "ProbeSet":
trait_dict['symbol'] = this_trait.symbol
trait_dict['description'] = this_trait.description_display.decode('utf-8', 'replace')
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 04cf718a..2c95bf5e 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -73,11 +73,7 @@
</li>
<li class="">
<a href="/collections/list">Collections
- {% if g.user_session.logged_in %}
<span class="badge badge-info">{{ g.user_session.num_collections }}</span>
- {% else %}
- <span class="badge badge-info">{{ g.cookie_session.display_num_collections() }}</span>
- {% endif %}
</a>
</li>
<li class="">
diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html
index 19aec8ae..eb3fc061 100644
--- a/wqflask/wqflask/templates/collections/list.html
+++ b/wqflask/wqflask/templates/collections/list.html
@@ -15,17 +15,6 @@
<h1>Your Collections</h1>
{% endif %}
- <!-- <hr style="height: 1px; background-color: #A9A9A9;">-->
-
- <!--
- <div class="page-header">
- {% if g.user_session.logged_in %}
- <h1>Collections owned by {{ g.user_session.user_name }}</h1>
- {% else %}
- <h1>Your Collections</h1>
- {% endif %}
- </div>
- -->
<div>
<form id="collections_form" action="/delete" method="post">
<input type="hidden" name="uc_id" id="uc_id" value="" />
@@ -55,24 +44,11 @@
<tbody>
{% for uc in collections %}
<tr class="collection_line">
- {% if g.user_session.logged_in %}
<td align="center" style="padding: 0px;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.id }}"></td>
- {% else %}
- <td align="center" style="padding: 0px;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.name }}"></td>
- {% endif %}
<td align="right">{{ loop.index }}
- {% if g.user_session.logged_in %}
<td><a class="collection_name" href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td>
- {% else %}
- <td><a class="collection_name" href="{{ url_for('view_collection', collection_id=uc.id) }}">{{ uc.name }}</a></td>
- {% endif %}
- {% if g.user_session.logged_in %}
<td>{{ uc.created_timestamp }}</td>
<td>{{ uc.changed_timestamp }}</td>
- {% else %}
- <td>{{ timeago(uc.created_timestamp.isoformat() + "Z") }}</td>
- <td>{{ timeago(uc.changed_timestamp.isoformat() + "Z") }}</td>
- {% endif %}
<td align="right">{{ uc.num_members }}</td>
</tr>
{% endfor %}
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index 640eb561..fd0025d9 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -9,20 +9,15 @@
<!-- Start of body -->
<div class="container" style="min-width: 1250px;">
- {% if uc %}
- <h1>{{ uc.name }}</h1>
- {% else %}
- <h1>{{ collection_name }}</h1>
- {% endif %}
+ <h1><input type="text" id="change_collection_name" style="display: none; width: 500px;" class="form-control" placeholder="{{ uc.name }}"></h1>
+ <h1>{{ uc.name }} <!--<button class="btn btn-default" style="margin-bottom: 5px;" id="change_collection_name">Change Collection Name</button>--></h1>
<h3>This collection has {{ '{}'.format(numify(trait_obs|count, "record", "records")) }}</h3>
<!--<hr style="height: 1px; background-color: #A9A9A9;">-->
<div>
<form id="collection_form" action="/delete" method="post">
- {% if uc %}
<input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" />
- {% endif %}
<input type="hidden" name="collection_name" id="collection_name" value="{{ collection_name }}" />
<input type="hidden" name="tool_used" value="" />
<input type="hidden" name="form_url" value="" />
diff --git a/wqflask/wqflask/templates/new_security/login_user.html b/wqflask/wqflask/templates/new_security/login_user.html
index 9df0e16a..80fed82a 100644
--- a/wqflask/wqflask/templates/new_security/login_user.html
+++ b/wqflask/wqflask/templates/new_security/login_user.html
@@ -10,6 +10,7 @@
{% if redis_is_available: %}
<form class="form-horizontal" action="/n/login" method="POST" name="login_user_form" id="loginUserForm">
+ <input name="anon_id" type="hidden" value="{{ g.user_session.user_id }}">
<fieldset>
<div class="form-group">
<label style="text-align:left;" class="col-xs-1 control-label" for="email_address">Email&nbsp;Address</label>
diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html
index 841d6ad5..a806a8b3 100644
--- a/wqflask/wqflask/templates/show_trait_mapping_tools.html
+++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html
@@ -81,7 +81,6 @@
<font size="2">Select covariate(s) from a collection</font>
</div>
<div style="margin-left:20px;" class="col-xs-7">
- {% if g.user_session.logged_in %}
{% if g.user_session.num_collections < 1 %}
No collections available. Please add traits to a collection to use them as covariates.
{% else %}
@@ -91,16 +90,6 @@
</div>
<textarea rows="3" cols="50" readonly placeholder="No covariates selected" style="overflow-y: scroll; resize: none; width: 200px;" class="selected_covariates"></textarea>
{% endif %}
- {% elif g.cookie_session.display_num_collections() == "" %}
- No collections available. Please add traits to a collection to use them as covariates.
- {% else %}
- <div style="margin-bottom: 10px;" class="btn-group" role="group">
- <button type="button" id="select_covariates" class="btn btn-default">Select</button>
- <button type="button" id="remove_covariates" class="btn btn-default">Remove</button>
- </div>
- <br>
- <textarea rows="3" cols="30" readonly placeholder="No covariates selected" style="overflow-y: scroll; resize: none;" class="selected_covariates"></textarea>
- {% endif %}
</div>
</div>
<div class="mapping_method_fields form-group">
diff --git a/wqflask/wqflask/templates/show_trait_statistics.html b/wqflask/wqflask/templates/show_trait_statistics.html
index 4653b398..974081d3 100644
--- a/wqflask/wqflask/templates/show_trait_statistics.html
+++ b/wqflask/wqflask/templates/show_trait_statistics.html
@@ -21,11 +21,9 @@
<li>
<a href="#violin_plot_tab" class="violin_plot_tab" data-toggle="tab">Violin Plot</a>
</li>
- {% if g.user_session.logged_in %}
<li>
<a href="#scatterplot_matrix" data-toggle="tab">Scatterplot Matrix</a>
</li>
- {% endif %}
</ul>
<div class="tab-content">
@@ -78,13 +76,11 @@
<i class="icon-signal"></i> Sort By Value
</button>
</div>
- {% if g.user_session.logged_in %}
<div class="btn-group">
<button type="button" class="btn btn-default" id="color_by_trait">
<i class="icon-tint"></i> Color by Trait
</button>
</div>
- {% endif %}
<div id="bar_chart_container">
<div id="bar_chart"></div>
</div>
@@ -126,7 +122,6 @@
<div id="violin_plot"></div>
</div>
</div>
- {% if g.user_session.logged_in %}
<div class="tab-pane" id="scatterplot_matrix">
<div style="margin-bottom:40px;" class="btn-group">
@@ -141,7 +136,6 @@
<div id="comparison_scatterplot" class="qtlcharts"></div>
</div>
</div>
- {% endif %}
</div>
</div>
<!--</div>-->
diff --git a/wqflask/wqflask/user_login.py b/wqflask/wqflask/user_login.py
index 05885e2c..da3cc504 100644
--- a/wqflask/wqflask/user_login.py
+++ b/wqflask/wqflask/user_login.py
@@ -21,9 +21,9 @@ from flask import (Flask, g, render_template, url_for, request, make_response,
from wqflask import app
from wqflask import pbkdf2
-from wqflask.hmac_func import hmac_creation
from wqflask.user_session import UserSession
+from utility import hmac
from utility.redis_tools import is_redis_available, get_user_id, get_user_by_unique_column, set_user_attribute, save_user, save_verification_code, check_verification_code, get_user_collections, save_collections
from utility.logger import getLogger
@@ -83,7 +83,7 @@ def encrypt_password(unencrypted_password, pwfields):
def get_signed_session_id(user):
session_id = str(uuid.uuid4())
- session_id_signature = hmac_creation(session_id)
+ session_id_signature = hmac.hmac_creation(session_id)
session_id_signed = session_id + ":" + session_id_signature
#ZS: Need to check if this is ever actually used or exists
@@ -197,12 +197,14 @@ def login():
if password_match: # If password correct
if user_details['confirmed']: # If account confirmed
import_col = "false"
+ anon_id = ""
if 'import_collections' in params:
import_col = "true"
+ anon_id = params['anon_id']
session_id_signed = get_signed_session_id(user_details)
flash("Thank you for logging in {}.".format(user_details['full_name']), "alert-success")
- response = make_response(redirect(url_for('index_page', import_collections = import_col)))
+ response = make_response(redirect(url_for('index_page', import_collections = import_col, anon_id = anon_id)))
response.set_cookie(UserSession.user_cookie_name, session_id_signed, max_age=None)
return response
else:
diff --git a/wqflask/wqflask/user_session.py b/wqflask/wqflask/user_session.py
index 1f3e6558..e19ec9df 100644
--- a/wqflask/wqflask/user_session.py
+++ b/wqflask/wqflask/user_session.py
@@ -1,272 +1,281 @@
-from __future__ import print_function, division, absolute_import
-
-import datetime
-import time
-import uuid
-
-import simplejson as json
-
-import redis # used for collections
-Redis = redis.StrictRedis()
-
-from flask import (Flask, g, render_template, url_for, request, make_response,
- redirect, flash, abort)
-
-from wqflask import app
-from wqflask.hmac_func import hmac_creation
-
-#from utility.elasticsearch_tools import get_elasticsearch_connection
-from utility.redis_tools import get_user_id, get_user_by_unique_column, get_user_collections, save_collections
-
-from utility.logger import getLogger
-logger = getLogger(__name__)
-
-THREE_DAYS = 60 * 60 * 24 * 3
-THIRTY_DAYS = 60 * 60 * 24 * 30
-
-def verify_cookie(cookie):
- the_uuid, separator, the_signature = cookie.partition(':')
- assert len(the_uuid) == 36, "Is session_id a uuid?"
- assert separator == ":", "Expected a : here"
- assert the_signature == hmac_creation(the_uuid), "Uh-oh, someone tampering with the cookie?"
- return the_uuid
-
-def create_signed_cookie():
- the_uuid = str(uuid.uuid4())
- signature = hmac_creation(the_uuid)
- uuid_signed = the_uuid + ":" + signature
- logger.debug("uuid_signed:", uuid_signed)
- return the_uuid, uuid_signed
-
-class UserSession(object):
- """Logged in user handling"""
-
- user_cookie_name = 'session_id_v1'
- anon_cookie_name = 'anon_user_v1'
-
- def __init__(self):
- user_cookie = request.cookies.get(self.user_cookie_name)
- if not user_cookie:
- self.logged_in = False
- anon_cookie = request.cookies.get(self.anon_cookie_name)
- self.cookie_name = self.anon_cookie_name
- if anon_cookie:
- self.cookie = anon_cookie
- session_id = verify_cookie(self.cookie)
- else:
- session_id, self.cookie = create_signed_cookie()
- else:
- self.cookie_name = self.user_cookie_name
- self.cookie = user_cookie
- session_id = verify_cookie(self.cookie)
-
- self.redis_key = self.cookie_name + ":" + session_id
- self.session_id = session_id
- self.record = Redis.hgetall(self.redis_key)
-
- #ZS: If user correctled logged in but their session expired
- #ZS: Need to test this by setting the time-out to be really short or something
- if not self.record:
- if user_cookie:
- self.logged_in = False
-
- ########### Grrr...this won't work because of the way flask handles cookies
- # Delete the cookie
- response = make_response(redirect(url_for('login')))
- #response.set_cookie(self.cookie_name, '', expires=0)
- flash("Due to inactivity your session has expired. If you'd like please login again.")
- return response
- #return
- else:
- self.record = dict(login_time = time.time(),
- user_type = "anon",
- user_id = str(uuid.uuid4()))
-
- Redis.hmset(self.redis_key, self.record)
- Redis.expire(self.redis_key, THIRTY_DAYS)
- else:
- if user_cookie:
- self.logged_in = True
-
- if user_cookie:
- session_time = THREE_DAYS
- else:
- session_time = THIRTY_DAYS
-
- if Redis.ttl(self.redis_key) < session_time:
- # (Almost) everytime the user does something we extend the session_id in Redis...
- logger.debug("Extending ttl...")
- Redis.expire(self.redis_key, session_time)
-
- @property
- def user_id(self):
- """Shortcut to the user_id"""
- if 'user_id' in self.record:
- return self.record['user_id']
- else:
- return ''
-
- @property
- def redis_user_id(self):
- """User id from Redis (need to check if this is the same as the id stored in self.records)"""
-
- #ZS: This part is a bit weird. Some accounts used to not have saved user ids, and in the process of testing I think I created some duplicate accounts for myself.
- #ZS: Accounts should automatically generate user_ids if they don't already have one now, so this might not be necessary for anything other than my account's collections
-
- if 'user_email_address' in self.record:
- user_email = self.record['user_email_address']
-
- #ZS: Get user's collections if they exist
- user_id = None
- user_id = get_user_id("email_address", user_email)
- elif 'user_id' in self.record:
- user_id = self.record['user_id']
- elif 'github_id' in self.record:
- user_github_id = self.record['github_id']
- user_id = None
- user_id = get_user_id("github_id", user_github_id)
- else: #ZS: Anonymous user
- return None
-
- return user_id
-
- @property
- def user_name(self):
- """Shortcut to the user_name"""
- if 'user_name' in self.record:
- return self.record['user_name']
- else:
- return ''
-
- @property
- def user_collections(self):
- """List of user's collections"""
-
- #ZS: Get user's collections if they exist
- collections = get_user_collections(self.redis_user_id)
- return collections
-
- @property
- def num_collections(self):
- """Number of user's collections"""
-
- return len(self.user_collections)
-
- def add_collection(self, collection_name, traits):
- """Add collection into ElasticSearch"""
-
- collection_dict = {'id': unicode(uuid.uuid4()),
- 'name': collection_name,
- 'created_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
- 'changed_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
- 'num_members': len(traits),
- 'members': list(traits) }
-
- current_collections = self.user_collections
- current_collections.append(collection_dict)
- self.update_collections(current_collections)
-
- return collection_dict['id']
-
- def change_collection_name(self, collection_id, new_name):
- for collection in self.user_collections:
- if collection['id'] == collection_id:
- collection['name'] = new_name
- break
-
- return new_name
-
- def delete_collection(self, collection_id):
- """Remove collection with given ID"""
-
- updated_collections = []
- for collection in self.user_collections:
- if collection['id'] == collection_id:
- continue
- else:
- updated_collections.append(collection)
-
- self.update_collections(updated_collections)
-
- return collection['name']
-
- def add_traits_to_collection(self, collection_id, traits_to_add):
- """Add specified traits to a collection"""
-
- this_collection = self.get_collection_by_id(collection_id)
-
- updated_collection = this_collection
- updated_traits = this_collection['members'] + traits_to_add
-
- updated_collection['members'] = updated_traits
- updated_collection['num_members'] = len(updated_traits)
- updated_collection['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
-
- updated_collections = []
- for collection in self.user_collections:
- if collection['id'] == collection_id:
- updated_collections.append(updated_collection)
- else:
- updated_collections.append(collection)
-
- self.update_collections(updated_collections)
-
- def remove_traits_from_collection(self, collection_id, traits_to_remove):
- """Remove specified traits from a collection"""
-
- this_collection = self.get_collection_by_id(collection_id)
-
- updated_collection = this_collection
- updated_traits = []
- for trait in this_collection['members']:
- if trait in traits_to_remove:
- continue
- else:
- updated_traits.append(trait)
-
- updated_collection['members'] = updated_traits
- updated_collection['num_members'] = len(updated_traits)
- updated_collection['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
-
- updated_collections = []
- for collection in self.user_collections:
- if collection['id'] == collection_id:
- updated_collections.append(updated_collection)
- else:
- updated_collections.append(collection)
-
- self.update_collections(updated_collections)
-
- return updated_traits
-
- def get_collection_by_id(self, collection_id):
- for collection in self.user_collections:
- if collection['id'] == collection_id:
- return collection
-
- def get_collection_by_name(self, collection_name):
- for collection in self.user_collections:
- if collection['name'] == collection_name:
- return collection
-
- return None
-
- def update_collections(self, updated_collections):
- collection_body = json.dumps(updated_collections)
-
- save_collections(self.redis_user_id, collection_body)
-
- def delete_session(self):
- # And more importantly delete the redis record
- Redis.delete(self.redis_key)
- self.logged_in = False
-
-@app.before_request
-def before_request():
- g.user_session = UserSession()
-
-@app.after_request
-def set_cookie(response):
- if not request.cookies.get(g.user_session.cookie_name):
- response.set_cookie(g.user_session.cookie_name, g.user_session.cookie)
+from __future__ import print_function, division, absolute_import
+
+import datetime
+import time
+import uuid
+
+import simplejson as json
+
+import redis # used for collections
+Redis = redis.StrictRedis()
+
+from flask import (Flask, g, render_template, url_for, request, make_response,
+ redirect, flash, abort)
+
+from wqflask import app
+from utility import hmac
+
+#from utility.elasticsearch_tools import get_elasticsearch_connection
+from utility.redis_tools import get_user_id, get_user_by_unique_column, get_user_collections, save_collections
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+THREE_DAYS = 60 * 60 * 24 * 3
+THIRTY_DAYS = 60 * 60 * 24 * 30
+
+def verify_cookie(cookie):
+ the_uuid, separator, the_signature = cookie.partition(':')
+ assert len(the_uuid) == 36, "Is session_id a uuid?"
+ assert separator == ":", "Expected a : here"
+ assert the_signature == hmac.hmac_creation(the_uuid), "Uh-oh, someone tampering with the cookie?"
+ return the_uuid
+
+def create_signed_cookie():
+ the_uuid = str(uuid.uuid4())
+ signature = hmac.hmac_creation(the_uuid)
+ uuid_signed = the_uuid + ":" + signature
+ logger.debug("uuid_signed:", uuid_signed)
+ return the_uuid, uuid_signed
+
+class UserSession(object):
+ """Logged in user handling"""
+
+ user_cookie_name = 'session_id_v1'
+ anon_cookie_name = 'anon_user_v1'
+
+ def __init__(self):
+ user_cookie = request.cookies.get(self.user_cookie_name)
+ if not user_cookie:
+ self.logged_in = False
+ anon_cookie = request.cookies.get(self.anon_cookie_name)
+ self.cookie_name = self.anon_cookie_name
+ if anon_cookie:
+ self.cookie = anon_cookie
+ session_id = verify_cookie(self.cookie)
+ else:
+ session_id, self.cookie = create_signed_cookie()
+ else:
+ self.cookie_name = self.user_cookie_name
+ self.cookie = user_cookie
+ session_id = verify_cookie(self.cookie)
+
+ self.redis_key = self.cookie_name + ":" + session_id
+ self.session_id = session_id
+ self.record = Redis.hgetall(self.redis_key)
+
+ #ZS: If user correctled logged in but their session expired
+ #ZS: Need to test this by setting the time-out to be really short or something
+ if not self.record:
+ if user_cookie:
+ self.logged_in = False
+
+ ########### Grrr...this won't work because of the way flask handles cookies
+ # Delete the cookie
+ response = make_response(redirect(url_for('login')))
+ #response.set_cookie(self.cookie_name, '', expires=0)
+ flash("Due to inactivity your session has expired. If you'd like please login again.")
+ return response
+ #return
+ else:
+ self.record = dict(login_time = time.time(),
+ user_type = "anon",
+ user_id = str(uuid.uuid4()))
+
+ Redis.hmset(self.redis_key, self.record)
+ Redis.expire(self.redis_key, THIRTY_DAYS)
+ else:
+ if user_cookie:
+ self.logged_in = True
+
+ if user_cookie:
+ session_time = THREE_DAYS
+ else:
+ session_time = THIRTY_DAYS
+
+ if Redis.ttl(self.redis_key) < session_time:
+ # (Almost) everytime the user does something we extend the session_id in Redis...
+ logger.debug("Extending ttl...")
+ Redis.expire(self.redis_key, session_time)
+
+ @property
+ def user_id(self):
+ """Shortcut to the user_id"""
+ if 'user_id' in self.record:
+ return self.record['user_id']
+ else:
+ return ''
+
+ @property
+ def redis_user_id(self):
+ """User id from Redis (need to check if this is the same as the id stored in self.records)"""
+
+ #ZS: This part is a bit weird. Some accounts used to not have saved user ids, and in the process of testing I think I created some duplicate accounts for myself.
+ #ZS: Accounts should automatically generate user_ids if they don't already have one now, so this might not be necessary for anything other than my account's collections
+
+ if 'user_email_address' in self.record:
+ user_email = self.record['user_email_address']
+
+ #ZS: Get user's collections if they exist
+ user_id = None
+ user_id = get_user_id("email_address", user_email)
+ elif 'user_id' in self.record:
+ user_id = self.record['user_id']
+ elif 'github_id' in self.record:
+ user_github_id = self.record['github_id']
+ user_id = None
+ user_id = get_user_id("github_id", user_github_id)
+ else: #ZS: Anonymous user
+ return None
+
+ return user_id
+
+ @property
+ def user_name(self):
+ """Shortcut to the user_name"""
+ if 'user_name' in self.record:
+ return self.record['user_name']
+ else:
+ return ''
+
+ @property
+ def user_collections(self):
+ """List of user's collections"""
+
+ #ZS: Get user's collections if they exist
+ collections = get_user_collections(self.redis_user_id)
+ return collections
+
+ @property
+ def num_collections(self):
+ """Number of user's collections"""
+
+ return len(self.user_collections)
+
+ def add_collection(self, collection_name, traits):
+ """Add collection into Redis"""
+
+ collection_dict = {'id': unicode(uuid.uuid4()),
+ 'name': collection_name,
+ 'created_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
+ 'changed_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
+ 'num_members': len(traits),
+ 'members': list(traits) }
+
+ current_collections = self.user_collections
+ current_collections.append(collection_dict)
+ self.update_collections(current_collections)
+
+ return collection_dict['id']
+
+ def change_collection_name(self, collection_id, new_name):
+ for collection in self.user_collections:
+ if collection['id'] == collection_id:
+ collection['name'] = new_name
+ break
+
+ return new_name
+
+ def delete_collection(self, collection_id):
+ """Remove collection with given ID"""
+
+ updated_collections = []
+ for collection in self.user_collections:
+ if collection['id'] == collection_id:
+ continue
+ else:
+ updated_collections.append(collection)
+
+ self.update_collections(updated_collections)
+
+ return collection['name']
+
+ def add_traits_to_collection(self, collection_id, traits_to_add):
+ """Add specified traits to a collection"""
+
+ this_collection = self.get_collection_by_id(collection_id)
+
+ updated_collection = this_collection
+ updated_traits = this_collection['members'] + traits_to_add
+
+ updated_collection['members'] = updated_traits
+ updated_collection['num_members'] = len(updated_traits)
+ updated_collection['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+
+ updated_collections = []
+ for collection in self.user_collections:
+ if collection['id'] == collection_id:
+ updated_collections.append(updated_collection)
+ else:
+ updated_collections.append(collection)
+
+ self.update_collections(updated_collections)
+
+ def remove_traits_from_collection(self, collection_id, traits_to_remove):
+ """Remove specified traits from a collection"""
+
+ this_collection = self.get_collection_by_id(collection_id)
+
+ updated_collection = this_collection
+ updated_traits = []
+ for trait in this_collection['members']:
+ if trait in traits_to_remove:
+ continue
+ else:
+ updated_traits.append(trait)
+
+ updated_collection['members'] = updated_traits
+ updated_collection['num_members'] = len(updated_traits)
+ updated_collection['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+
+ updated_collections = []
+ for collection in self.user_collections:
+ if collection['id'] == collection_id:
+ updated_collections.append(updated_collection)
+ else:
+ updated_collections.append(collection)
+
+ self.update_collections(updated_collections)
+
+ return updated_traits
+
+ def get_collection_by_id(self, collection_id):
+ for collection in self.user_collections:
+ if collection['id'] == collection_id:
+ return collection
+
+ def get_collection_by_name(self, collection_name):
+ for collection in self.user_collections:
+ if collection['name'] == collection_name:
+ return collection
+
+ return None
+
+ def update_collections(self, updated_collections):
+ collection_body = json.dumps(updated_collections)
+
+ save_collections(self.redis_user_id, collection_body)
+
+ def import_traits_to_user(self, anon_id):
+ collections = get_user_collections(anon_id)
+ for collection in collections:
+ collection_exists = self.get_collection_by_name(collection['name'])
+ if collection_exists:
+ continue
+ else:
+ self.add_collection(collection['name'], collection['members'])
+
+ def delete_session(self):
+ # And more importantly delete the redis record
+ Redis.delete(self.redis_key)
+ self.logged_in = False
+
+@app.before_request
+def before_request():
+ g.user_session = UserSession()
+
+@app.after_request
+def set_cookie(response):
+ if not request.cookies.get(g.user_session.cookie_name):
+ response.set_cookie(g.user_session.cookie_name, g.user_session.cookie)
return response \ No newline at end of file
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 436ebc91..8a80c26c 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -126,7 +126,7 @@ def index_page():
if 'import_collections' in params:
import_collections = params['import_collections']
if import_collections == "true":
- g.cookie_session.import_traits_to_user()
+ g.user_session.import_traits_to_user(params['anon_id'])
#if USE_GN_SERVER:
# # The menu is generated using GN_SERVER
# return render_template("index_page.html", gn_server_url = GN_SERVER_URL, version=GN_VERSION)