aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzsloan2020-06-17 14:49:40 -0500
committerzsloan2020-06-17 14:49:40 -0500
commitea47eb228b1224ea83e3f50a056bf715b3bf5ec6 (patch)
treee6ff6824d2e1960e7b84342c7d09771d4783ae97
parent7438f3c45122f02c25155b42ede703ad2845649c (diff)
downloadgenenetwork2-ea47eb228b1224ea83e3f50a056bf715b3bf5ec6.tar.gz
Adding all the authentication stuff
-rw-r--r--wqflask/base/data_set.py36
-rw-r--r--wqflask/base/trait.py5
-rw-r--r--wqflask/maintenance/set_resource_defaults.py307
-rw-r--r--wqflask/utility/authentication_tools.py132
-rw-r--r--wqflask/utility/redis_tools.py67
-rw-r--r--wqflask/wqflask/docs.py4
-rw-r--r--wqflask/wqflask/group_manager.py220
-rw-r--r--wqflask/wqflask/resource_manager.py204
-rw-r--r--wqflask/wqflask/static/new/javascript/group_manager.js74
-rw-r--r--wqflask/wqflask/static/new/javascript/search_results.js1
-rw-r--r--wqflask/wqflask/templates/admin/change_resource_owner.html116
-rw-r--r--wqflask/wqflask/templates/admin/create_group.html178
-rw-r--r--wqflask/wqflask/templates/admin/group_manager.html18
-rw-r--r--wqflask/wqflask/templates/admin/manage_resource.html200
-rw-r--r--wqflask/wqflask/templates/admin/search_for_groups.html198
-rw-r--r--wqflask/wqflask/templates/admin/select_group_to_add.html54
-rw-r--r--wqflask/wqflask/templates/admin/set_group_privileges.html102
-rw-r--r--wqflask/wqflask/templates/admin/view_group.html238
-rw-r--r--wqflask/wqflask/templates/base.html5
-rw-r--r--wqflask/wqflask/templates/set_group_privileges.html77
-rw-r--r--wqflask/wqflask/templates/show_trait_details.html4
-rw-r--r--wqflask/wqflask/views.py2
22 files changed, 1516 insertions, 726 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 1457ba8d..92dc8615 100644
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -486,25 +486,18 @@ class DatasetGroup(object):
def datasets(group_name, this_group = None):
key = "group_dataset_menu:v2:" + group_name
- logger.debug("key is2:", key)
dataset_menu = []
- logger.debug("[tape4] webqtlConfig.PUBLICTHRESH:", webqtlConfig.PUBLICTHRESH)
- logger.debug("[tape4] type webqtlConfig.PUBLICTHRESH:", type(webqtlConfig.PUBLICTHRESH))
the_results = fetchall('''
(SELECT '#PublishFreeze',PublishFreeze.FullName,PublishFreeze.Name
FROM PublishFreeze,InbredSet
WHERE PublishFreeze.InbredSetId = InbredSet.Id
and InbredSet.Name = '%s'
- and PublishFreeze.public > %s
- and PublishFreeze.confidentiality < 1
ORDER BY PublishFreeze.Id ASC)
UNION
(SELECT '#GenoFreeze',GenoFreeze.FullName,GenoFreeze.Name
FROM GenoFreeze, InbredSet
WHERE GenoFreeze.InbredSetId = InbredSet.Id
- and InbredSet.Name = '%s'
- and GenoFreeze.public > %s
- and GenoFreeze.confidentiality < 1)
+ and InbredSet.Name = '%s')
UNION
(SELECT Tissue.Name, ProbeSetFreeze.FullName,ProbeSetFreeze.Name
FROM ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue
@@ -512,12 +505,10 @@ def datasets(group_name, this_group = None):
and ProbeFreeze.TissueId = Tissue.Id
and ProbeFreeze.InbredSetId = InbredSet.Id
and InbredSet.Name like %s
- and ProbeSetFreeze.public > %s
- and ProbeSetFreeze.confidentiality < 1
ORDER BY Tissue.Name, ProbeSetFreeze.OrderList DESC)
- ''' % (group_name, webqtlConfig.PUBLICTHRESH,
- group_name, webqtlConfig.PUBLICTHRESH,
- "'" + group_name + "'", webqtlConfig.PUBLICTHRESH))
+ ''' % (group_name,
+ group_name,
+ "'" + group_name + "'"))
sorted_results = sorted(the_results, key=lambda kv: kv[0])
@@ -637,29 +628,25 @@ class DataSet(object):
"""
-
try:
if self.type == "ProbeSet":
query_args = tuple(escape(x) for x in (
- str(webqtlConfig.PUBLICTHRESH),
self.name,
self.name,
self.name))
self.id, self.name, self.fullname, self.shortname, self.data_scale, self.tissue = fetch1("""
-SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.FullName, ProbeSetFreeze.ShortName, ProbeSetFreeze.DataScale, Tissue.Name
-FROM ProbeSetFreeze, ProbeFreeze, Tissue
-WHERE ProbeSetFreeze.public > %s
-AND ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
-AND ProbeFreeze.TissueId = Tissue.Id
-AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFreeze.ShortName = '%s')
+ SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.FullName, ProbeSetFreeze.ShortName, ProbeSetFreeze.DataScale, Tissue.Name
+ FROM ProbeSetFreeze, ProbeFreeze, Tissue
+ WHERE ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
+ AND ProbeFreeze.TissueId = Tissue.Id
+ AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFreeze.ShortName = '%s')
""" % (query_args),"/dataset/"+self.name+".json",
lambda r: (r["id"],r["name"],r["full_name"],r["short_name"],r["data_scale"],r["tissue"])
)
else:
query_args = tuple(escape(x) for x in (
(self.type + "Freeze"),
- str(webqtlConfig.PUBLICTHRESH),
self.name,
self.name,
self.name))
@@ -668,9 +655,8 @@ AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFre
self.id, self.name, self.fullname, self.shortname = fetchone("""
SELECT Id, Name, FullName, ShortName
FROM %s
- WHERE public > %s AND
- (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
- """ % (query_args))
+ WHERE (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
+ """ % (query_args))
except TypeError:
logger.debug("Dataset {} is not yet available in GeneNetwork.".format(self.name))
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 2a945588..7700ecd5 100644
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -46,9 +46,10 @@ def create_trait(**kw):
else:
permitted = check_resource_availability(dataset)
- if permitted:
+ if permitted != "no-access":
the_trait = GeneralTrait(**kw)
if the_trait.dataset.type != "Temp":
+
the_trait = retrieve_trait_info(the_trait, the_trait.dataset, get_qtl_info=kw.get('get_qtl_info'))
return the_trait
else:
@@ -383,7 +384,6 @@ def retrieve_trait_info(trait, dataset, get_qtl_info=False):
if dataset.type == 'Publish':
the_url = "http://localhost:8080/run-action?resource={}&user={}&branch=data&action=view".format(resource_id, g.user_session.user_id)
else:
-
the_url = "http://localhost:8080/run-action?resource={}&user={}&branch=data&action=view&trait={}".format(resource_id, g.user_session.user_id, trait.name)
try:
@@ -424,7 +424,6 @@ def retrieve_trait_info(trait, dataset, get_qtl_info=False):
logger.sql(query)
trait_info = g.db.execute(query).fetchone()
-
#XZ, 05/08/2009: Xiaodong add this block to use ProbeSet.Id to find the probeset instead of just using ProbeSet.Name
#XZ, 05/08/2009: to avoid the problem of same probeset name from different platforms.
elif dataset.type == 'ProbeSet':
diff --git a/wqflask/maintenance/set_resource_defaults.py b/wqflask/maintenance/set_resource_defaults.py
index ba102d9c..344e6a23 100644
--- a/wqflask/maintenance/set_resource_defaults.py
+++ b/wqflask/maintenance/set_resource_defaults.py
@@ -1,155 +1,154 @@
-"""
-
-Script that sets default resource access masks for use with the DB proxy
-
-Defaults will be:
-Owner - omni_gn
-Mask - Public/non-confidential: { data: "view",
- metadata: "view",
- admin: "not-admin" }
- Private/confidentia: { data: "no-access",
- metadata: "no-access",
- admin: "not-admin" }
-
-To run:
-./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py
-
-"""
-
-from __future__ import print_function, division
-
-import sys
-import json
-
-# NEW: Note we prepend the current path - otherwise a guix instance of GN2 may be used instead
-sys.path.insert(0,'./')
-
-# NEW: import app to avoid a circular dependency on utility.tools
-from wqflask import app
-
-from utility.tools import SQL_URI
-from utility.redis_tools import get_redis_conn, get_user_id, add_resource, get_resources
-Redis = get_redis_conn()
-
-import MySQLdb
-
-import urlparse
-
-from utility.logger import getLogger
-logger = getLogger(__name__)
-
-def parse_db_uri():
- """Converts a database URI to the db name, host name, user name, and password"""
-
- parsed_uri = urlparse.urlparse(SQL_URI)
-
- db_conn_info = dict(
- db = parsed_uri.path[1:],
- host = parsed_uri.hostname,
- user = parsed_uri.username,
- passwd = parsed_uri.password)
-
- print(db_conn_info)
- return db_conn_info
-
-def insert_probeset_resources(default_owner_id):
- current_resources = Redis.hgetall("resources")
- Cursor.execute(""" SELECT
- ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.confidentiality, ProbeSetFreeze.public
- FROM
- ProbeSetFreeze""")
-
- resource_results = Cursor.fetchall()
- for i, resource in enumerate(resource_results):
- if i % 20 == 0:
- print(i)
- resource_ob = {}
- resource_ob['name'] = resource[1]
- resource_ob['owner_id'] = default_owner_id
- resource_ob['data'] = { "dataset" : str(resource[0])}
- resource_ob['type'] = "dataset-probeset"
- if resource[2] < 1 and resource[3] > 0:
- resource_ob['default_mask'] = { "data": ["no-access", "view"] }
- else:
- resource_ob['default_mask'] = { "data": ["no-access"] }
- resource_ob['group_masks'] = {}
-
- add_resource(resource_ob)
-
-def insert_publish_resources(default_owner_id):
- current_resources = Redis.hgetall("resources")
- Cursor.execute(""" SELECT
- PublishXRef.Id, PublishFreeze.Id, InbredSet.InbredSetCode
- FROM
- PublishXRef, PublishFreeze, InbredSet, Publication
- WHERE
- PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
- InbredSet.Id = PublishXRef.InbredSetId AND
- Publication.Id = PublishXRef.PublicationId""")
-
- resource_results = Cursor.fetchall()
- for resource in resource_results:
- if resource[2]:
- resource_ob = {}
- if resource[2]:
- resource_ob['name'] = resource[2] + "_" + str(resource[0])
- else:
- resource_ob['name'] = str(resource[0])
- resource_ob['owner_id'] = default_owner_id
- resource_ob['data'] = { "dataset" : str(resource[1]) ,
- "trait" : str(resource[0])}
- resource_ob['type'] = "dataset-publish"
- resource_ob['default_mask'] = { "data": "view" }
-
- resource_ob['group_masks'] = {}
-
- add_resource(resource_ob)
- else:
- continue
-
-def insert_geno_resources(default_owner_id):
- current_resources = Redis.hgetall("resources")
- Cursor.execute(""" SELECT
- GenoFreeze.Id, GenoFreeze.ShortName, GenoFreeze.confidentiality
- FROM
- GenoFreeze""")
-
- resource_results = Cursor.fetchall()
- for i, resource in enumerate(resource_results):
- if i % 20 == 0:
- print(i)
- resource_ob = {}
- resource_ob['name'] = resource[1]
- resource_ob['owner_id'] = default_owner_id
- resource_ob['data'] = { "dataset" : str(resource[0]) }
- resource_ob['type'] = "dataset-geno"
- if resource[2] < 1:
- resource_ob['default_mask'] = { "data": "view" }
- else:
- resource_ob['default_mask'] = { "data": "no-access" }
- resource_ob['group_masks'] = {}
-
- add_resource(resource_ob)
-
-def insert_resources(default_owner_id):
- current_resources = get_resources()
- print("START")
- insert_publish_resources(default_owner_id)
- print("AFTER PUBLISH")
- insert_geno_resources(default_owner_id)
- print("AFTER GENO")
- insert_probeset_resources(default_owner_id)
- print("AFTER PROBESET")
-
-def main():
- """Generates and outputs (as json file) the data for the main dropdown menus on the home page"""
-
- Redis.delete("resources")
-
- owner_id = get_user_id("email_address", "zachary.a.sloan@gmail.com")
- insert_resources(owner_id)
-
-if __name__ == '__main__':
- Conn = MySQLdb.Connect(**parse_db_uri())
- Cursor = Conn.cursor()
+"""
+
+Script that sets default resource access masks for use with the DB proxy
+
+Defaults will be:
+Owner - omni_gn
+Mask - Public/non-confidential: { data: "view",
+ metadata: "view",
+ admin: "not-admin" }
+ Private/confidentia: { data: "no-access",
+ metadata: "no-access",
+ admin: "not-admin" }
+
+To run:
+./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py
+
+"""
+
+from __future__ import print_function, division
+
+import sys
+import json
+
+# NEW: Note we prepend the current path - otherwise a guix instance of GN2 may be used instead
+sys.path.insert(0,'./')
+
+# NEW: import app to avoid a circular dependency on utility.tools
+from wqflask import app
+
+from utility.tools import SQL_URI
+from utility.redis_tools import get_redis_conn, get_user_id, add_resource, get_resources
+Redis = get_redis_conn()
+
+import MySQLdb
+
+import urlparse
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+def parse_db_uri():
+ """Converts a database URI to the db name, host name, user name, and password"""
+
+ parsed_uri = urlparse.urlparse(SQL_URI)
+
+ db_conn_info = dict(
+ db = parsed_uri.path[1:],
+ host = parsed_uri.hostname,
+ user = parsed_uri.username,
+ passwd = parsed_uri.password)
+
+ print(db_conn_info)
+ return db_conn_info
+
+def insert_probeset_resources(default_owner_id):
+ current_resources = Redis.hgetall("resources")
+ Cursor.execute(""" SELECT
+ ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.confidentiality, ProbeSetFreeze.public
+ FROM
+ ProbeSetFreeze""")
+
+ resource_results = Cursor.fetchall()
+ for i, resource in enumerate(resource_results):
+ resource_ob = {}
+ resource_ob['name'] = resource[1]
+ resource_ob['owner_id'] = default_owner_id
+ resource_ob['data'] = { "dataset" : str(resource[0])}
+ resource_ob['type'] = "dataset-probeset"
+ if resource[2] < 1 and resource[3] > 0:
+ resource_ob['default_mask'] = { "data": "view" }
+ else:
+ resource_ob['default_mask'] = { "data": "no-access" }
+ resource_ob['group_masks'] = {}
+
+ add_resource(resource_ob)
+
+def insert_publish_resources(default_owner_id):
+ current_resources = Redis.hgetall("resources")
+ Cursor.execute(""" SELECT
+ PublishXRef.Id, PublishFreeze.Id, InbredSet.InbredSetCode
+ FROM
+ PublishXRef, PublishFreeze, InbredSet, Publication
+ WHERE
+ PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
+ InbredSet.Id = PublishXRef.InbredSetId AND
+ Publication.Id = PublishXRef.PublicationId""")
+
+ resource_results = Cursor.fetchall()
+ for resource in resource_results:
+ if resource[2]:
+ resource_ob = {}
+ if resource[2]:
+ resource_ob['name'] = resource[2] + "_" + str(resource[0])
+ else:
+ resource_ob['name'] = str(resource[0])
+ resource_ob['owner_id'] = default_owner_id
+ resource_ob['data'] = { "dataset" : str(resource[1]) ,
+ "trait" : str(resource[0])}
+ resource_ob['type'] = "dataset-publish"
+ resource_ob['default_mask'] = { "data": "view" }
+
+ resource_ob['group_masks'] = {}
+
+ add_resource(resource_ob)
+ else:
+ continue
+
+def insert_geno_resources(default_owner_id):
+ current_resources = Redis.hgetall("resources")
+ Cursor.execute(""" SELECT
+ GenoFreeze.Id, GenoFreeze.ShortName, GenoFreeze.confidentiality
+ FROM
+ GenoFreeze""")
+
+ resource_results = Cursor.fetchall()
+ for i, resource in enumerate(resource_results):
+ resource_ob = {}
+ resource_ob['name'] = resource[1]
+ if resource[1] == "HET3-ITPGeno":
+ resource_ob['owner_id'] = "73a3f093-ca13-4ae0-a179-9a446f709f6e"
+ else:
+ resource_ob['owner_id'] = default_owner_id
+ resource_ob['data'] = { "dataset" : str(resource[0]) }
+ resource_ob['type'] = "dataset-geno"
+ if resource[2] < 1:
+ resource_ob['default_mask'] = { "data": "view" }
+ else:
+ resource_ob['default_mask'] = { "data": "no-access" }
+ resource_ob['group_masks'] = {}
+
+ add_resource(resource_ob)
+
+def insert_resources(default_owner_id):
+ current_resources = get_resources()
+ print("START")
+ insert_publish_resources(default_owner_id)
+ print("AFTER PUBLISH")
+ insert_geno_resources(default_owner_id)
+ print("AFTER GENO")
+ insert_probeset_resources(default_owner_id)
+ print("AFTER PROBESET")
+
+def main():
+ """Generates and outputs (as json file) the data for the main dropdown menus on the home page"""
+
+ Redis.delete("resources")
+
+ owner_id = get_user_id("email_address", "zachary.a.sloan@gmail.com")
+ insert_resources(owner_id)
+
+if __name__ == '__main__':
+ Conn = MySQLdb.Connect(**parse_db_uri())
+ Cursor = Conn.cursor()
main() \ No newline at end of file
diff --git a/wqflask/utility/authentication_tools.py b/wqflask/utility/authentication_tools.py
index 537881a5..07ceacc0 100644
--- a/wqflask/utility/authentication_tools.py
+++ b/wqflask/utility/authentication_tools.py
@@ -1,46 +1,86 @@
-from __future__ import absolute_import, print_function, division
-
-import json
-import requests
-
-from base import data_set
-
-from utility import hmac
-from utility.redis_tools import get_redis_conn, get_resource_info, get_resource_id
-
-from flask import Flask, g, redirect, url_for
-
-import logging
-logger = logging.getLogger(__name__ )
-
-def check_resource_availability(dataset, trait_id=None):
- resource_id = get_resource_id(dataset, trait_id)
-
- if resource_id:
- the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)
- try:
- response = json.loads(requests.get(the_url).content)['data']
- except:
- resource_info = get_resource_info(resource_id)
- response = resource_info['default_mask']['data']
-
- if 'view' in response:
- return True
- else:
- return redirect(url_for("no_access_page"))
-
- return True
-
-def check_owner(dataset=None, trait_id=None, resource_id=None):
- if resource_id:
- resource_info = get_resource_info(resource_id)
- if g.user_session.user_id == resource_info['owner_id']:
- return resource_id
- else:
- resource_id = get_resource_id(dataset, trait_id)
- if resource_id:
- resource_info = get_resource_info(resource_id)
- if g.user_session.user_id == resource_info['owner_id']:
- return resource_id
-
- return False \ No newline at end of file
+from __future__ import absolute_import, print_function, division
+
+import json
+import requests
+
+from base import data_set
+
+from utility import hmac
+from utility.redis_tools import get_redis_conn, get_resource_info, get_resource_id
+
+from flask import Flask, g, redirect, url_for
+
+import logging
+logger = logging.getLogger(__name__ )
+
+def check_resource_availability(dataset, trait_id=None):
+ resource_id = get_resource_id(dataset, trait_id)
+
+ response = None
+ if resource_id:
+ resource_info = get_resource_info(resource_id)
+
+ the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)
+ try:
+ response = json.loads(requests.get(the_url).content)['data']
+ except:
+ response = resource_info['default_mask']['data']
+
+ if 'edit' in response:
+ return "edit"
+ elif 'view' in response:
+ return "view"
+ else:
+ return "no-access"
+
+ return False
+
+def check_admin(resource_id=None):
+
+ return "not-admin"
+
+ # ZS: commented out until proxy can return this
+ # the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)
+ # try:
+ # response = json.loads(requests.get(the_url).content)
+ # except:
+ # response = resource_info['default_mask']['admin']
+
+ # if 'edit-admins' in response:
+ # return "edit-admins"
+ # elif 'edit-access' in response:
+ # return "edit-access"
+ # else:
+ # return "not-admin"
+
+def check_owner(dataset=None, trait_id=None, resource_id=None):
+ if resource_id:
+ resource_info = get_resource_info(resource_id)
+ if g.user_session.user_id == resource_info['owner_id']:
+ return resource_id
+ else:
+ resource_id = get_resource_id(dataset, trait_id)
+ if resource_id:
+ resource_info = get_resource_info(resource_id)
+ if g.user_session.user_id == resource_info['owner_id']:
+ return resource_id
+
+ return False
+
+def check_owner_or_admin(dataset=None, trait_id=None, resource_id=None):
+ if resource_id:
+ resource_info = get_resource_info(resource_id)
+ if g.user_session.user_id == resource_info['owner_id']:
+ return [resource_id, "owner"]
+ else:
+ return [resource_id, check_admin(resource_id)]
+ else:
+ resource_id = get_resource_id(dataset, trait_id)
+ if resource_id:
+ resource_info = get_resource_info(resource_id)
+ if g.user_session.user_id == resource_info['owner_id']:
+ return [resource_id, "owner"]
+ else:
+ return [resource_id, check_admin(resource_id)]
+
+ return [resource_id, "not-admin"] \ No newline at end of file
diff --git a/wqflask/utility/redis_tools.py b/wqflask/utility/redis_tools.py
index bc30a0af..c6d221ff 100644
--- a/wqflask/utility/redis_tools.py
+++ b/wqflask/utility/redis_tools.py
@@ -16,7 +16,7 @@ from utility.logger import getLogger
logger = getLogger(__name__)
def get_redis_conn():
- Redis = redis.StrictRedis(port=6380)
+ Redis = redis.StrictRedis(port=6379)
return Redis
Redis = get_redis_conn()
@@ -51,6 +51,27 @@ def get_user_by_unique_column(column_name, column_value):
return item_details
+def get_users_like_unique_column(column_name, column_value):
+ """
+ Like previous function, but this only checks if the input is a subset of a field and can return multiple results
+ """
+ matched_users = []
+
+ if column_value != "":
+ user_list = Redis.hgetall("users")
+ if column_name != "user_id":
+ for key in user_list:
+ user_ob = json.loads(user_list[key])
+ if column_name in user_ob:
+ if column_value in user_ob[column_name]:
+ matched_users.append(user_ob)
+ else:
+ matched_users.append(json.loads(user_list[column_value]))
+
+ return matched_users
+
+# def search_users_by_unique_column(column_name, column_value):
+
def set_user_attribute(user_id, column_name, column_value):
user_info = json.loads(Redis.hget("users", user_id))
user_info[column_name] = column_value
@@ -142,6 +163,28 @@ def get_group_by_unique_column(column_name, column_value):
return matched_groups
+def get_groups_like_unique_column(column_name, column_value):
+ """
+ Like previous function, but this only checks if the input is a subset of a field and can return multiple results
+ """
+ matched_groups = []
+
+ if column_value != "":
+ group_list = Redis.hgetall("groups")
+ if column_name != "group_id":
+ for key in group_list:
+ group_info = json.loads(group_list[key])
+ if column_name == "admins" or column_name == "members": #ZS: Since these fields are lists, search in the list
+ if column_value in group_info[column_name]:
+ matched_groups.append(group_info)
+ else:
+ if column_name in group_info:
+ if column_value in group_info[column_name]:
+ matched_groups.append(group_info)
+ else:
+ matched_groups.append(json.loads(group_list[column_value]))
+
+ return matched_groups
def create_group(admin_user_ids, member_user_ids = [], group_name = "Default Group Name"):
group_id = str(uuid.uuid4())
@@ -192,9 +235,13 @@ def add_users_to_group(user_id, group_id, user_emails = [], admins = False): #ZS
def remove_users_from_group(user_id, users_to_remove_ids, group_id, user_type = "members"): #ZS: User type is because I assume admins can remove other admins
group_info = get_group_info(group_id)
+
if user_id in group_info["admins"]:
+ users_to_remove_set = set(users_to_remove_ids)
+ if user_type == "admins" and user_id in users_to_remove_set: #ZS: Make sure an admin can't remove themselves from a group, since I imagine we don't want groups to be able to become admin-less
+ users_to_remove_set.remove(user_id)
group_users = set(group_info[user_type])
- group_users -= set(users_to_remove_ids)
+ group_users -= users_to_remove_set
group_info[user_type] = list(group_users)
group_info["changed_timestamp"] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
Redis.hset("groups", group_id, json.dumps(group_info))
@@ -232,7 +279,6 @@ def get_resource_info(resource_id):
return json.loads(resource_info)
def add_resource(resource_info):
-
if 'trait' in resource_info['data']:
resource_id = hmac.hmac_creation('{}:{}:{}'.format(str(resource_info['type']), str(resource_info['data']['dataset']), str(resource_info['data']['trait'])))
else:
@@ -241,3 +287,18 @@ def add_resource(resource_info):
Redis.hset("resources", resource_id, json.dumps(resource_info))
return resource_info
+
+def add_access_mask(resource_id, group_id, access_mask):
+ the_resource = get_resource_info(resource_id)
+ the_resource['group_masks'][group_id] = access_mask
+
+ Redis.hset("resources", resource_id, json.dumps(the_resource))
+
+ return the_resource
+
+def change_resource_owner(resource_id, new_owner_id):
+ the_resource= get_resource_info(resource_id)
+ the_resource['owner_id'] = new_owner_id
+
+ Redis.delete("resource")
+ Redis.hset("resources", resource_id, json.dumps(the_resource)) \ No newline at end of file
diff --git a/wqflask/wqflask/docs.py b/wqflask/wqflask/docs.py
index 0187f32e..78407e22 100644
--- a/wqflask/wqflask/docs.py
+++ b/wqflask/wqflask/docs.py
@@ -1,5 +1,7 @@
from __future__ import absolute_import, print_function, division
+import codecs
+
from flask import g
from utility.logger import getLogger
@@ -20,7 +22,7 @@ class Docs(object):
self.content = ""
else:
self.title = result[0]
- self.content = result[1]
+ self.content = result[1].encode("latin1")
self.editable = "false"
# ZS: Removing option to edit to see if text still gets vandalized
diff --git a/wqflask/wqflask/group_manager.py b/wqflask/wqflask/group_manager.py
index f41ae56d..9afc016b 100644
--- a/wqflask/wqflask/group_manager.py
+++ b/wqflask/wqflask/group_manager.py
@@ -1,77 +1,145 @@
-
-from __future__ import print_function, division, absolute_import
-
-from flask import (Flask, g, render_template, url_for, request, make_response,
- redirect, flash)
-
-from wqflask import app
-from wqflask.user_login import send_verification_email
-
-from utility.redis_tools import get_user_groups, get_group_info, create_group, delete_group, add_users_to_group, remove_users_from_group, \
- change_group_name, save_verification_code, check_verification_code, get_user_by_unique_column
-
-from utility.logger import getLogger
-logger = getLogger(__name__)
-
-@app.route("/groups/manage", methods=('GET', 'POST'))
-def manage_groups():
- params = request.form if request.form else request.args
- if "add_new_group" in params:
- return redirect(url_for('add_group'))
- else:
- admin_groups, user_groups = get_user_groups(g.user_session.user_id)
- return render_template("admin/group_manager.html", admin_groups=admin_groups, user_groups=user_groups)
-
-@app.route("/groups/remove", methods=('POST',))
-def remove_groups():
- group_ids_to_remove = request.form['selected_group_ids']
- for group_id in group_ids_to_remove.split(":"):
- delete_group(g.user_session.user_id, group_id)
-
- return redirect(url_for('manage_groups'))
-
-@app.route("/groups/create", methods=('GET', 'POST'))
-def add_group():
- params = request.form if request.form else request.args
- if "group_name" in params:
- member_user_ids = set()
- admin_user_ids = set()
- admin_user_ids.add(g.user_session.user_id) #ZS: Always add the user creating the group as an admin
- if "admin_emails" in params:
- admin_emails = params['admin_emails_to_add'].split(",")
- for email in admin_emails:
- user_details = get_user_by_unique_column("email_address", email)
- if user_details:
- admin_user_ids.add(user_details['user_id'])
- #send_group_invites(params['group_id'], user_email_list = admin_emails, user_type="admins")
- if "user_emails" in params:
- member_emails = params['member_emails_to_add'].split(",")
- for email in member_emails:
- user_details = get_user_by_unique_column("email_address", email)
- if user_details:
- member_user_ids.add(user_details['user_id'])
- #send_group_invites(params['group_id'], user_email_list = user_emails, user_type="members")
-
- create_group(list(admin_user_ids), list(member_user_ids), params['group_name'])
- return redirect(url_for('manage_groups'))
- else:
- return render_template("admin/create_group.html")
-
-#ZS: Will integrate this later, for now just letting users be added directly
-def send_group_invites(group_id, user_email_list = [], user_type="members"):
- for user_email in user_email_list:
- user_details = get_user_by_unique_column("email_address", user_email)
- if user_details:
- group_info = get_group_info(group_id)
- #ZS: Probably not necessary since the group should normally always exist if group_id is being passed here,
- # but it's technically possible to hit it if Redis is cleared out before submitting the new users or something
- if group_info:
- #ZS: Don't add user if they're already an admin or if they're being added a regular user and are already a regular user,
- # but do add them if they're a regular user and are added as an admin
- if (user_details['user_id'] in group_info['admins']) or \
- ((user_type == "members") and (user_details['user_id'] in group_info['members'])):
- continue
- else:
- send_verification_email(user_details, template_name = "email/group_verification.txt", key_prefix = "verification_code", subject = "You've been invited to join a GeneNetwork user group")
-
+
+from __future__ import print_function, division, absolute_import
+
+from flask import (Flask, g, render_template, url_for, request, make_response,
+ redirect, flash)
+
+from wqflask import app
+from wqflask.user_login import send_verification_email
+
+from utility.redis_tools import get_user_groups, get_group_info, create_group, delete_group, add_users_to_group, remove_users_from_group, \
+ change_group_name, save_verification_code, check_verification_code, get_user_by_unique_column, get_resources, get_resource_info
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+@app.route("/groups/manage", methods=('GET', 'POST'))
+def manage_groups():
+ params = request.form if request.form else request.args
+ if "add_new_group" in params:
+ return redirect(url_for('add_group'))
+ else:
+ admin_groups, user_groups = get_user_groups(g.user_session.user_id)
+ return render_template("admin/group_manager.html", admin_groups=admin_groups, user_groups=user_groups)
+
+@app.route("/groups/view", methods=('GET', 'POST'))
+def view_group():
+ params = request.form if request.form else request.args
+ group_id = params['id']
+ group_info = get_group_info(group_id)
+ admins_info = []
+ user_is_admin = False
+ if g.user_session.user_id in group_info['admins']:
+ user_is_admin = True
+ for user_id in group_info['admins']:
+ if user_id:
+ user_info = get_user_by_unique_column("user_id", user_id)
+ admins_info.append(user_info)
+ members_info = []
+ for user_id in group_info['members']:
+ if user_id:
+ user_info = get_user_by_unique_column("user_id", user_id)
+ members_info.append(user_info)
+
+ #ZS: This whole part might not scale well with many resources
+ resources_info = []
+ all_resources = get_resources()
+ for resource_id in all_resources:
+ resource_info = get_resource_info(resource_id)
+ group_masks = resource_info['group_masks']
+ if group_id in group_masks:
+ this_resource = {}
+ privileges = group_masks[group_id]
+ this_resource['id'] = resource_id
+ this_resource['name'] = resource_info['name']
+ this_resource['data'] = privileges['data']
+ this_resource['metadata'] = privileges['metadata']
+ this_resource['admin'] = privileges['admin']
+ resources_info.append(this_resource)
+
+ return render_template("admin/view_group.html", group_info=group_info, admins=admins_info, members=members_info, user_is_admin=user_is_admin, resources=resources_info)
+
+@app.route("/groups/remove", methods=('POST',))
+def remove_groups():
+ group_ids_to_remove = request.form['selected_group_ids']
+ for group_id in group_ids_to_remove.split(":"):
+ delete_group(g.user_session.user_id, group_id)
+
+ return redirect(url_for('manage_groups'))
+
+@app.route("/groups/remove_users", methods=('POST',))
+def remove_users():
+ group_id = request.form['group_id']
+ admin_ids_to_remove = request.form['selected_admin_ids']
+ member_ids_to_remove = request.form['selected_member_ids']
+
+ remove_users_from_group(g.user_session.user_id, admin_ids_to_remove.split(":"), group_id, user_type="admins")
+ remove_users_from_group(g.user_session.user_id, member_ids_to_remove.split(":"), group_id, user_type="members")
+
+ return redirect(url_for('view_group', id=group_id))
+
+@app.route("/groups/add_<path:user_type>", methods=('POST',))
+def add_users(user_type='members'):
+ group_id = request.form['group_id']
+ if user_type == "admins":
+ user_emails = request.form['admin_emails_to_add'].split(",")
+ add_users_to_group(g.user_session.user_id, group_id, user_emails, admins = True)
+ elif user_type == "members":
+ user_emails = request.form['member_emails_to_add'].split(",")
+ add_users_to_group(g.user_session.user_id, group_id, user_emails, admins = False)
+
+ return redirect(url_for('view_group', id=group_id))
+
+@app.route("/groups/change_name", methods=('POST',))
+def change_name():
+ group_id = request.form['group_id']
+ new_name = request.form['new_name']
+ group_info = change_group_name(g.user_session.user_id, group_id, new_name)
+
+ return new_name
+
+@app.route("/groups/create", methods=('GET', 'POST'))
+def add_or_edit_group():
+ params = request.form if request.form else request.args
+ if "group_name" in params:
+ member_user_ids = set()
+ admin_user_ids = set()
+ admin_user_ids.add(g.user_session.user_id) #ZS: Always add the user creating the group as an admin
+ if "admin_emails_to_add" in params:
+ admin_emails = params['admin_emails_to_add'].split(",")
+ for email in admin_emails:
+ user_details = get_user_by_unique_column("email_address", email)
+ if user_details:
+ admin_user_ids.add(user_details['user_id'])
+ #send_group_invites(params['group_id'], user_email_list = admin_emails, user_type="admins")
+ if "member_emails_to_add" in params:
+ member_emails = params['member_emails_to_add'].split(",")
+ for email in member_emails:
+ user_details = get_user_by_unique_column("email_address", email)
+ if user_details:
+ member_user_ids.add(user_details['user_id'])
+ #send_group_invites(params['group_id'], user_email_list = user_emails, user_type="members")
+
+ create_group(list(admin_user_ids), list(member_user_ids), params['group_name'])
+ return redirect(url_for('manage_groups'))
+ else:
+ return render_template("admin/create_group.html")
+
+#ZS: Will integrate this later, for now just letting users be added directly
+def send_group_invites(group_id, user_email_list = [], user_type="members"):
+ for user_email in user_email_list:
+ user_details = get_user_by_unique_column("email_address", user_email)
+ if user_details:
+ group_info = get_group_info(group_id)
+ #ZS: Probably not necessary since the group should normally always exist if group_id is being passed here,
+ # but it's technically possible to hit it if Redis is cleared out before submitting the new users or something
+ if group_info:
+ #ZS: Don't add user if they're already an admin or if they're being added a regular user and are already a regular user,
+ # but do add them if they're a regular user and are added as an admin
+ if (user_details['user_id'] in group_info['admins']) or \
+ ((user_type == "members") and (user_details['user_id'] in group_info['members'])):
+ continue
+ else:
+ send_verification_email(user_details, template_name = "email/group_verification.txt", key_prefix = "verification_code", subject = "You've been invited to join a GeneNetwork user group")
+
#@app.route() \ No newline at end of file
diff --git a/wqflask/wqflask/resource_manager.py b/wqflask/wqflask/resource_manager.py
index 7d88b8ed..0f9f5c9d 100644
--- a/wqflask/wqflask/resource_manager.py
+++ b/wqflask/wqflask/resource_manager.py
@@ -1,72 +1,134 @@
-from __future__ import print_function, division, absolute_import
-
-from flask import (Flask, g, render_template, url_for, request, make_response,
- redirect, flash)
-
-from wqflask import app
-
-from utility.authentication_tools import check_owner
-from utility.redis_tools import get_resource_info, get_group_info, get_group_by_unique_column, get_user_id
-
-from utility.logger import getLogger
-logger = getLogger(__name__)
-
-@app.route("/resources/manage", methods=('GET', 'POST'))
-def view_resource():
- params = request.form if request.form else request.args
- if 'resource_id' in request.args:
- resource_id = request.args['resource_id']
- if check_owner(resource_id=resource_id):
- resource_info = get_resource_info(resource_id)
- group_masks = resource_info['group_masks']
- group_masks_with_names = get_group_names(group_masks)
- default_mask = resource_info['default_mask']['data']
- return render_template("admin/manage_resource.html", resource_id = resource_id, resource_info=resource_info, default_mask=default_mask, group_masks=group_masks_with_names)
- else:
- return redirect(url_for("no_access_page"))
-
-@app.route("/resources/add_group", methods=('POST',))
-def add_group_to_resource():
- resource_id = request.form['resource_id']
- if check_owner(resource_id=resource_id):
- if all(key in request.form for key in ('group_id', 'group_name', 'user_name', 'user_email')):
- group_list = []
- if request.form['group_id'] != "":
- the_group = get_group_info(request.form['group_id'])
- if the_group:
- group_list.append(the_group)
- if request.form['group_name'] != "":
- matched_groups = get_group_by_unique_column("name", request.form['group_name'])
- for group in matched_groups:
- group_list.append(group)
- if request.form['user_name'] != "":
- user_id = get_user_id("user_name", request.form['user_name'])
- if user_id:
- matched_groups = get_group_by_unique_column("admins", user_id)
- matched_groups += get_group_by_unique_column("members", user_id)
- for group in matched_groups:
- group_list.append(group)
- if request.form['user_email'] != "":
- user_id = get_user_id("email_address", request.form['user_email'])
- if user_id:
- matched_groups = get_group_by_unique_column("admins", user_id)
- matched_groups += get_group_by_unique_column("members", user_id)
- for group in matched_groups:
- group_list.append(group)
- return render_template("admin/select_group_to_add.html", group_list=group_list, resource_id = resource_id)
- elif 'selected_group' in request.form:
- group_id = request.form['selected_group']
- return render_template("admin/set_group_privileges.html", resource_id = resource_id, group_id = group_id)
- else:
- return render_template("admin/search_for_groups.html", resource_id = resource_id)
- else:
- return redirect(url_for("no_access_page"))
-
-def get_group_names(group_masks):
- group_masks_with_names = {}
- for group_id, group_mask in group_masks.iteritems():
- this_mask = group_mask
- group_name = get_group_info(group_id)['name']
- this_mask['name'] = group_name
-
+from __future__ import print_function, division, absolute_import
+
+import json
+
+from flask import (Flask, g, render_template, url_for, request, make_response,
+ redirect, flash)
+
+from wqflask import app
+
+from utility.authentication_tools import check_owner_or_admin
+from utility.redis_tools import get_resource_info, get_group_info, get_groups_like_unique_column, get_user_id, get_user_by_unique_column, get_users_like_unique_column, add_access_mask, add_resource, change_resource_owner
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+@app.route("/resources/manage", methods=('GET', 'POST'))
+def manage_resource():
+ params = request.form if request.form else request.args
+ if 'resource_id' in request.args:
+ resource_id = request.args['resource_id']
+ admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+
+ resource_info = get_resource_info(resource_id)
+ group_masks = resource_info['group_masks']
+ group_masks_with_names = get_group_names(group_masks)
+ default_mask = resource_info['default_mask']['data']
+ owner_id = resource_info['owner_id']
+ owner_info = get_user_by_unique_column("user_id", owner_id)
+
+ if 'name' in owner_info:
+ owner_display_name = owner_info['full_name']
+ elif 'user_name' in owner_info:
+ owner_display_name = owner_info['user_name']
+ elif 'email_address' in owner_info:
+ owner_display_name = owner_info['email_address']
+ else:
+ owner_display_name = None
+
+ return render_template("admin/manage_resource.html", owner_name = owner_display_name, resource_id = resource_id, resource_info=resource_info, default_mask=default_mask, group_masks=group_masks_with_names, admin_status=admin_status)
+
+@app.route("/search_for_users", methods=('POST',))
+def search_for_user():
+ params = request.form
+ user_list = []
+ user_list += get_users_like_unique_column("full_name", params['user_name'])
+ user_list += get_users_like_unique_column("email_address", params['user_email'])
+
+ return json.dumps(user_list)
+
+@app.route("/search_for_groups", methods=('POST',))
+def search_for_groups():
+ params = request.form
+ group_list = []
+ group_list += get_groups_like_unique_column("id", params['group_id'])
+ group_list += get_groups_like_unique_column("name", params['group_name'])
+
+ user_list = []
+ user_list += get_users_like_unique_column("full_name", params['user_name'])
+ user_list += get_users_like_unique_column("email_address", params['user_email'])
+ for user in user_list:
+ group_list += get_groups_like_unique_column("admins", user['user_id'])
+ group_list += get_groups_like_unique_column("members", user['user_id'])
+
+ return json.dumps(group_list)
+
+@app.route("/resources/change_owner", methods=('POST',))
+def change_owner():
+ resource_id = request.form['resource_id']
+ if 'new_owner' in request.form:
+ admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+ if admin_status == "owner":
+ new_owner_id = request.form['new_owner']
+ change_resource_owner(resource_id, new_owner_id)
+ flash("The resource's owner has beeen changed.", "alert-info")
+ return redirect(url_for("manage_resource", resource_id=resource_id))
+ else:
+ flash("You lack the permissions to make this change.", "error")
+ return redirect(url_for("manage_resource", resource_id=resource_id))
+ else:
+ return render_template("admin/change_resource_owner.html", resource_id = resource_id)
+
+@app.route("/resources/change_default_privileges", methods=('POST',))
+def change_default_privileges():
+ resource_id = request.form['resource_id']
+ admin_status = check_owner_or_admin(resource_id=resource_id)
+ if admin_status == "owner" or admin_status == "edit-admins":
+ resource_info = get_resource_info(resource_id)
+ default_mask = resource_info['default_mask']
+ if request.form['open_to_public'] == "True":
+ default_mask['data'] = 'view'
+ else:
+ default_mask['data'] = 'no-access'
+ resource_info['default_mask'] = default_mask
+ add_resource(resource_info)
+ flash("Your changes have been saved.", "alert-info")
+ return redirect(url_for("manage_resource", resource_id=resource_id))
+ else:
+ return redirect(url_for("no_access_page"))
+
+@app.route("/resources/add_group", methods=('POST',))
+def add_group_to_resource():
+ resource_id = request.form['resource_id']
+ admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+ if admin_status == "owner" or admin_status == "edit-admins" or admin_status == "edit-access":
+ if 'selected_group' in request.form:
+ group_id = request.form['selected_group']
+ resource_info = get_resource_info(resource_id)
+ default_privileges = resource_info['default_mask']
+ return render_template("admin/set_group_privileges.html", resource_id = resource_id, group_id = group_id, default_privileges = default_privileges)
+ elif all(key in request.form for key in ('data_privilege', 'metadata_privilege', 'admin_privilege')):
+ group_id = request.form['group_id']
+ group_name = get_group_info(group_id)['name']
+ access_mask = {
+ 'data': request.form['data_privilege'],
+ 'metadata': request.form['metadata_privilege'],
+ 'admin': request.form['admin_privilege']
+ }
+ add_access_mask(resource_id, group_id, access_mask)
+ flash("Privileges have been added for group {}.".format(group_name), "alert-info")
+ return redirect(url_for("manage_resource", resource_id=resource_id))
+ else:
+ return render_template("admin/search_for_groups.html", resource_id = resource_id)
+ else:
+ return redirect(url_for("no_access_page"))
+
+def get_group_names(group_masks):
+ group_masks_with_names = {}
+ for group_id, group_mask in group_masks.iteritems():
+ this_mask = group_mask
+ group_name = get_group_info(group_id)['name']
+ this_mask['name'] = group_name
+ group_masks_with_names[group_id] = this_mask
+
return group_masks_with_names \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/group_manager.js b/wqflask/wqflask/static/new/javascript/group_manager.js
index 5e82d104..4c172cbf 100644
--- a/wqflask/wqflask/static/new/javascript/group_manager.js
+++ b/wqflask/wqflask/static/new/javascript/group_manager.js
@@ -1,38 +1,38 @@
-$('#add_to_admins').click(function() {
- add_emails('admin')
-})
-
-$('#add_to_members').click(function() {
- add_emails('member')
-})
-
-$('#clear_admins').click(function(){
- clear_emails('admin')
-})
-
-$('#clear_members').click(function(){
- clear_emails('member')
-})
-
-
-function add_emails(user_type){
- var email_address = $('input[name=user_email]').val();
- var email_list_string = $('input[name=' + user_type + '_emails_to_add]').val()
- console.log(email_list_string)
- if (email_list_string == ""){
- var email_set = new Set();
- } else {
- var email_set = new Set(email_list_string.split(","))
- }
- email_set.add(email_address)
-
- $('input[name=' + user_type + '_emails_to_add]').val(Array.from(email_set).join(','))
-
- var emails_display_string = Array.from(email_set).join('\n')
- $('.added_' + user_type + 's').val(emails_display_string)
-}
-
-function clear_emails(user_type){
- $('input[name=' + user_type + '_emails_to_add]').val("")
- $('.added_' + user_type + 's').val("")
+$('#add_to_admins').click(function() {
+ add_emails('admin')
+})
+
+$('#add_to_members').click(function() {
+ add_emails('member')
+})
+
+$('#clear_admins').click(function(){
+ clear_emails('admin')
+})
+
+$('#clear_members').click(function(){
+ clear_emails('member')
+})
+
+
+function add_emails(user_type){
+ var email_address = $('input[name=user_email]').val();
+ var email_list_string = $('input[name=' + user_type + '_emails_to_add]').val().trim()
+ console.log(email_list_string)
+ if (email_list_string == ""){
+ var email_set = new Set();
+ } else {
+ var email_set = new Set(email_list_string.split(","))
+ }
+ email_set.add(email_address)
+
+ $('input[name=' + user_type + '_emails_to_add]').val(Array.from(email_set).join(','))
+
+ var emails_display_string = Array.from(email_set).join('\n')
+ $('.added_' + user_type + 's').val(emails_display_string)
+}
+
+function clear_emails(user_type){
+ $('input[name=' + user_type + '_emails_to_add]').val("")
+ $('.added_' + user_type + 's').val("")
} \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 8fa698b4..115dac13 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -296,7 +296,6 @@ $(function() {
$("#deselect_all").click(deselect_all);
$("#invert").click(invert);
$("#add").click(add);
- $("#remove").click(remove);
$("#submit_bnw").click(submit_bnw);
$("#export_traits").click(export_traits);
$('.trait_checkbox, .btn').click(change_buttons);
diff --git a/wqflask/wqflask/templates/admin/change_resource_owner.html b/wqflask/wqflask/templates/admin/change_resource_owner.html
new file mode 100644
index 00000000..ae9409b0
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/change_resource_owner.html
@@ -0,0 +1,116 @@
+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <div class="page-header">
+ <h1>Search for user to assign ownership to:</h1>
+ </div>
+ <form id="change_owner_form" action="/resources/change_owner" method="POST">
+ <input type="hidden" name="resource_id" value="{{ resource_id }}">
+ <div style="min-width: 600px; max-width: 800px;">
+ <fieldset>
+ <div class="form-horizontal" style="width: 900px;">
+ <div style="margin-bottom: 30px;">
+ <h2>Search for user by either name or e-mail:</h2>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User's Name:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="user_name" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User's E-mail:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="user_email" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <button type="button" id="find_users" class="btn btn-primary">Search</button>
+ <button style="margin-left: 20px; display: none;" type="submit" id="submit_new_owner" class="btn btn-success">Assign Ownership to Selected User</button>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ <hr>
+ <div id="user_results">
+ </div>
+ </div>
+ </form>
+ </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+ <script language="javascript">
+ $('#find_users').click(function() {
+ $.ajax({
+ method: "POST",
+ url: "/search_for_users",
+ data: {
+ user_name: $('input[name=user_name]').val(),
+ user_email: $('input[name=user_email]').val()
+ },
+ success: populate_users
+ });
+ })
+
+ populate_users = function(json_user_list){
+ var user_list = JSON.parse(json_user_list)
+
+ var the_html = ""
+ if (user_list.length > 0){
+ the_html += "<table id='users_table' style='padding-top: 10px; width: 100%;' class='table-hover table-striped cell-border'>";
+ the_html += "<thead><tr><th></th><th>Index</th><th>Name</th><th>E-mail Address</th><th>Organization</th></tr></thead>";
+ the_html += "<tbody>";
+ for (_i = 0, _len = user_list.length; _i < _len; _i++) {
+ this_user = user_list[_i]
+ the_html += "<tr>";
+ the_html += "<td align='center' class='select_user'><input type='radio' name='new_owner' value='" + this_user.user_id + "'></td>";
+ the_html += "<td>" + (_i + 1).toString() + "</td>"
+ if ("full_name" in this_user) {
+ the_html += "<td>" + this_user.full_name + "</td>";
+ } else {
+ the_html += "<td>N/A</td>"
+ }
+ if ("email_address" in this_user) {
+ the_html += "<td>" + this_user.email_address + "</td>";
+ } else {
+ the_html += "<td>N/A</td>"
+ }
+ if ("organization" in this_user) {
+ the_html += "<td>" + this_user.organization + "</td>";
+ } else {
+ the_html += "<td>N/A</td>"
+ }
+ the_html += "</tr>"
+ }
+ the_html += "</tbody>";
+ the_html += "</table>";
+ } else {
+ the_html = "<span>No users were found matching the entered criteria.</span>"
+ }
+
+ $('#user_results').html(the_html)
+ if (user_list.length > 0){
+ $('#users_table').dataTable({
+ 'order': [[1, "asc" ]],
+ 'sDom': 'tr'
+ });
+ $('input[name=select_user]:eq(0)').prop("checked", true)
+ $('#submit_new_owner').css("display", "inline-block")
+ }
+ }
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/create_group.html b/wqflask/wqflask/templates/admin/create_group.html
index 55c3fa0b..5a6929fb 100644
--- a/wqflask/wqflask/templates/admin/create_group.html
+++ b/wqflask/wqflask/templates/admin/create_group.html
@@ -1,89 +1,89 @@
-{% extends "base.html" %}
-{% block title %}Group Manager{% endblock %}
-{% block content %}
-<!-- Start of body -->
- <div class="container">
- <div class="page-header">
- <h1>Create Group</h1>
- </div>
- <form action="/groups/create" method="POST">
- <input type="hidden" name="admin_emails_to_add" value="">
- <input type="hidden" name="member_emails_to_add" value="">
- <fieldset>
- <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
- <div class="form-group" style="padding-left: 20px;">
- <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-12">
- <input name="group_name" type="text" style="width:100%;"></input>
- </div>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Add User Email:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-12">
- <input name="user_email" type="text" style="width:100%;"></input>
- </div>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label class="col-xs-3"></label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-6">
- <button type="button" id="add_to_admins" class="btn btn-default">Add to Admins</button>
- </div>
- <div class="col-xs-6">
- <button type="button" id="add_to_members" class="btn btn-default">Add to Members</button>
- </div>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label class="col-xs-3" style="font-size: 18px;">Members to be added:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-6">
- <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_admins"></textarea>
- </div>
- <div class="col-xs-6">
- <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_members"></textarea>
- </div>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label class="col-xs-3"></label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-6">
- <button type="button" id="clear_admins" class="btn btn-default">Clear</button>
- </div>
- <div class="col-xs-6">
- <button type="button" id="clear_members" class="btn btn-default">Clear</button>
- </div>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="create_group" class="col-xs-3" style="float: left; font-size: 18px;"></label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <div class="col-xs-6">
- <button type="button" id="create_group" class="btn btn-primary">Create Group</button>
- </div>
- </div>
- </div>
- </div>
- </fieldset>
- </form>
- </div>
-
-
-
-<!-- End of body -->
-
-{% endblock %}
-
-{% block js %}
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
-
- <script type="text/javascript" charset="utf-8">
- </script>
-{% endblock %}
+{% extends "base.html" %}
+{% block title %}Group Manager{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <div class="page-header">
+ <h1>Create Group</h1>
+ </div>
+ <form action="/groups/create" method="POST">
+ <input type="hidden" name="admin_emails_to_add" value="">
+ <input type="hidden" name="member_emails_to_add" value="">
+ <fieldset>
+ <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-12">
+ <input name="group_name" type="text" style="width:100%;"></input>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Add User Email:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-12">
+ <input name="user_email" type="text" style="width:100%;"></input>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-6">
+ <button type="button" id="add_to_admins" class="btn btn-default">Add to Admins</button>
+ </div>
+ <div class="col-xs-6">
+ <button type="button" id="add_to_members" class="btn btn-default">Add to Members</button>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3" style="font-size: 18px;">Members to be added:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-6">
+ <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_admins"></textarea>
+ </div>
+ <div class="col-xs-6">
+ <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_members"></textarea>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-6">
+ <button type="button" id="clear_admins" class="btn btn-default">Clear</button>
+ </div>
+ <div class="col-xs-6">
+ <button type="button" id="clear_members" class="btn btn-default">Clear</button>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="create_group" class="col-xs-3" style="float: left; font-size: 18px;"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <div class="col-xs-6">
+ <button type="submit" id="create_group" class="btn btn-primary">Create Group</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+
+
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
+
+ <script type="text/javascript" charset="utf-8">
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/group_manager.html b/wqflask/wqflask/templates/admin/group_manager.html
index 23d8205a..70d55684 100644
--- a/wqflask/wqflask/templates/admin/group_manager.html
+++ b/wqflask/wqflask/templates/admin/group_manager.html
@@ -23,7 +23,7 @@
<br>
<button type="submit" name="add_new_group" class="btn btn-primary">Create a new group</button>
{% else %}
- <div><h3>Admin Groups</h3></div>
+ <div style="margin-top: 20px;"><h2>Admin Groups</h2></div>
<hr>
{% if admin_groups|length == 0 %}
<h4>You currently aren't the administrator of any groups.</h4>
@@ -45,8 +45,8 @@
<tr>
<td><input type="checkbox" name="group_id" value="{{ group.id }}"></td>
<td align="right">{{ loop.index }}</td>
- <td>{{ group.name }}</td>
- <td align="right">{{ group.admins|length + group.users|length }}</td>
+ <td><a href="/groups/view?id={{ group.id }}">{{ group.name }}</a></td>
+ <td align="right">{{ group.admins|length + group.members|length }}</td>
<td>{{ group.created_timestamp }}</td>
<td>{{ group.changed_timestamp }}</td>
<td>{{ group.id }}</td>
@@ -58,7 +58,7 @@
</div>
<hr>
<div style="min-width: 800px; max-width: 1000px;">
- <div><h3>User Groups</h3></div>
+ <div><h2>User Groups</h2></div>
<hr>
{% if user_groups|length == 0 %}
<h4>You currently aren't a member of any groups.</h4>
@@ -80,7 +80,7 @@
<td><input type="checkbox" name="read" value="{{ group.id }}"></td>
<td>{{ loop.index }}</td>
<td>{{ group.name }}</td>
- <td>{{ group.admins|length + group.users|length }}</td>
+ <td>{{ group.admins|length + group.members|length }}</td>
<td>{{ group.created_timestamp }}</td>
<td>{{ group.changed_timestamp }}</td>
</tr>
@@ -103,10 +103,14 @@
<script type="text/javascript" charset="utf-8">
$(document).ready( function () {
{% if admin_groups|length != 0 %}
- $('#admin_groups').dataTable();
+ $('#admin_groups').dataTable({
+ 'sDom': 'tr'
+ });
{% endif %}
{% if user_groups|length != 0 %}
- $('#user_groups').dataTable();
+ $('#user_groups').dataTable({
+ 'sDom': 'tr'
+ });
{% endif %}
submit_special = function(url) {
$("#groups_form").attr("action", url);
diff --git a/wqflask/wqflask/templates/admin/manage_resource.html b/wqflask/wqflask/templates/admin/manage_resource.html
index a47f47ad..0b12eaae 100644
--- a/wqflask/wqflask/templates/admin/manage_resource.html
+++ b/wqflask/wqflask/templates/admin/manage_resource.html
@@ -1,92 +1,108 @@
-{% extends "base.html" %}
-{% block title %}Resource Manager{% endblock %}
-{% block content %}
-<!-- Start of body -->
- <div class="container">
- <div class="page-header">
- <h1>Resource Manager</h1>
- </div>
- <form id="manage_resource" action="/resources/manage" method="POST">
- <input type="hidden" name="resource_id" value="{{ resource_id }}">
- <div class="col-xs-6" style="min-width: 600px; max-width: 800px;">
- <fieldset>
- <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
- <div class="form-group" style="padding-left: 20px;">
- <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Resource Name:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- {{ resource_info.name }}
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Open to Public:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <label class="radio-inline">
- <input type="radio" name="default_mask" value="True" checked="">
- Yes
- </label>
- <label class="radio-inline">
- <input type="radio" name="default_mask" value="False">
- No
- </label>
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <button id="save_changes" class="btn btn-primary">Save Changes</button>
- </div>
- </div>
- </div>
- </fieldset>
- </div>
- <div class="col-xs-6" style="min-width: 600px; max-width: 800px;">
- <button id="add_group_to_resource" class="btn btn-primary" style="margin-bottom: 30px;" data-url="/resources/add_group">Add Group</button>
- <br>
- {% if group_masks|length > 0 %}
- <h3>Current Group Permissions</h3>
- <table>
- <thead>
- <tr>
- <th>Name</th>
- <th>Data</th>
- <th>Metadata</th>
- <th>Admin</th>
- </tr>
- </thead>
- <tbody>
- {% for key, value in group_masks.iteritems() %}
- <tr>
- <td>{{ value.name }}</td>
- <td>{{ value.data }}</td>
- <td>{{ value.metadata }}</td>
- <td>{{ value.admin }}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% else %}
- <h3>No groups are currently added to this resource.</h3>
- {% endif %}
- </div>
- </form>
- </div>
-
-
-
-<!-- End of body -->
-
-{% endblock %}
-
-{% block js %}
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
-
- <script type="text/javascript" charset="utf-8">
- $('#add_group_to_resource').click(function(){
- url = $(this).data("url");
- $('#manage_resource').attr("action", url)
- $('#manage_resource').submit()
- })
- </script>
-{% endblock %}
+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ {{ flash_me() }}
+ <div class="page-header" style="display: inline-block;">
+ <h1>Resource Manager</h1>
+ <h3>{% if owner_name is not none %}Current Owner: {{ owner_name }}{% endif %} {% if admin_status == "owner" %}<button id="change_owner" class="btn btn-danger" data-url="/resources/change_owner" style="margin-left: 20px;">Change Owner</button>{% endif %}</h3>
+ </div>
+ <form id="manage_resource" action="/resources/manage" method="POST">
+ <input type="hidden" name="resource_id" value="{{ resource_id }}">
+ <div style="min-width: 600px; max-width: 800px;">
+ <fieldset>
+ <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Resource Name:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ {{ resource_info.name }}
+ </div>
+ </div>
+ {% if admin_status == "owner" %}
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Open to Public:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <label class="radio-inline">
+ <input type="radio" name="open_to_public" value="True" {% if default_mask != 'no-access' %}checked{% endif %}>
+ Yes
+ </label>
+ <label class="radio-inline">
+ <input type="radio" name="open_to_public" value="False" {% if default_mask == 'no-access' %}checked{% endif %}>
+ No
+ </label>
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <button id="save_changes" class="btn btn-primary" data-url="/resources/change_default_privileges">Save Changes</button>
+ </div>
+ </div>
+ {% endif %}
+ </div>
+ </fieldset>
+ </div>
+ {% if admin_status == "owner" or admin_status == "edit-admins" or admin_status == "edit-access" %}
+ <div style="min-width: 600px; max-width: 800px;">
+ <hr>
+ <button id="add_group_to_resource" class="btn btn-primary" style="margin-bottom: 30px;" data-url="/resources/add_group">Add Group</button>
+ <br>
+ {% if group_masks|length > 0 %}
+ <h2>Current Group Permissions</h2>
+ <hr>
+ <table id="groups_table" class="table-hover table-striped cell-border">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Data</th>
+ <th>Metadata</th>
+ <th>Admin</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for key, value in group_masks.iteritems() %}
+ <tr>
+ <td>{{ value.name }}</td>
+ <td>{{ value.data }}</td>
+ <td>{{ value.metadata }}</td>
+ <td>{{ value.admin }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ <h3>No groups are currently added to this resource.</h3>
+ {% endif %}
+ </div>
+ {% endif %}
+ </form>
+ </div>
+
+
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+ <script type="text/javascript" charset="utf-8">
+ $('#add_group_to_resource, #save_changes, #change_owner').click(function(){
+ url = $(this).data("url");
+ $('#manage_resource').attr("action", url)
+ $('#manage_resource').submit()
+ })
+
+ {% if group_masks|length > 0 %}
+ $('#groups_table').dataTable({
+ 'sDom': 'tr',
+ });
+ {% endif %}
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/search_for_groups.html b/wqflask/wqflask/templates/admin/search_for_groups.html
index 89eb11dd..f304a172 100644
--- a/wqflask/wqflask/templates/admin/search_for_groups.html
+++ b/wqflask/wqflask/templates/admin/search_for_groups.html
@@ -1,64 +1,134 @@
-{% extends "base.html" %}
-{% block title %}Resource Manager{% endblock %}
-{% block content %}
-<!-- Start of body -->
- <div class="container">
- <div class="page-header">
- <h1>Find Groups</h1>
- </div>
- <form id="find_groups" action="/resources/add_group" method="POST">
- <input type="hidden" name="resource_id" value="{{ resource_id }}">
- <div style="min-width: 600px; max-width: 800px;">
- <fieldset>
- <div class="form-horizontal" style="width: 900px;">
- <div style="margin-bottom: 30px;">
- <h2>Search by:</h2>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group ID:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <input name="group_id" type="text" value="">
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <input name="group_name" type="text" value="">
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User Name:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <input name="user_name" type="text" value="">
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User E-mail:</label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <input name="user_email" type="text" value="">
- </div>
- </div>
- <div class="form-group" style="padding-left: 20px;">
- <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
- <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
- <button type="submit" id="find_groups" class="btn btn-primary">Search</button>
- </div>
- </div>
- </div>
- </fieldset>
- </div>
- </form>
- </div>
-
-<!-- End of body -->
-
-{% endblock %}
-
-{% block js %}
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
-
- <script type="text/javascript" charset="utf-8">
- </script>
-{% endblock %}
+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <div class="page-header">
+ <h1>Find Groups</h1>
+ </div>
+ <form id="add_group" action="/resources/add_group" method="POST">
+ <input type="hidden" name="resource_id" value="{{ resource_id }}">
+ <div style="min-width: 600px; max-width: 800px;">
+ <fieldset>
+ <div class="form-horizontal" style="width: 900px;">
+ <div style="margin-bottom: 30px;">
+ <h2>Search by:</h2>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group ID:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="group_id" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="group_name" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User Name:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="user_name" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User E-mail:</label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <input name="user_email" type="text" value="">
+ </div>
+ </div>
+ <div class="form-group" style="padding-left: 20px;">
+ <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+ <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+ <button type="button" id="find_groups" class="btn btn-primary">Search</button>
+ <button style="margin-left: 20px; display: none;" type="submit" id="submit_group" class="btn btn-success">Add Privileges for Selected Group</button>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ <hr>
+ <div id="group_results">
+ </div>
+ </div>
+ </form>
+ </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+ <script type="text/javascript" charset="utf-8">
+
+ $('#find_groups').click(function() {
+ $.ajax({
+ method: "POST",
+ url: "/search_for_groups",
+ data: {
+ group_id: $('input[name=group_id]').val(),
+ group_name: $('input[name=group_name]').val(),
+ user_name: $('input[name=user_name]').val(),
+ user_email: $('input[name=user_email]').val()
+ },
+ success: populate_groups
+ });
+ })
+
+ populate_groups = function(json_group_list){
+ console.log(json_group_list)
+ var group_list = JSON.parse(json_group_list)
+
+ var the_html = ""
+ if (group_list.length > 0){
+ the_html += "<table id='groups_table' style='padding-top: 10px; width: 100%;' class='table-hover table-striped cell-border'>";
+ the_html += "<thead><tr><th></th><th>Index</th><th>Name</th><th># Admins</th><th># Members</th></tr></thead>";
+ the_html += "<tbody>";
+ for (_i = 0, _len = group_list.length; _i < _len; _i++) {
+ this_group = group_list[_i]
+ the_html += "<tr>";
+ the_html += "<td align='center' class='select_group'><input type='radio' name='selected_group' value='" + this_group.id + "'></td>";
+ the_html += "<td>" + (_i + 1).toString() + "</td>"
+ if ("name" in this_group) {
+ the_html += "<td>" + this_group.name + "</td>";
+ } else {
+ the_html += "<td>N/A</td>"
+ }
+ if ("admins" in this_group) {
+ the_html += "<td>" + this_group.admins.length + "</td>";
+ } else {
+ the_html += "<td>0</td>"
+ }
+ if ("members" in this_group) {
+ the_html += "<td>" + this_group.members.length + "</td>";
+ } else {
+ the_html += "<td>0</td>"
+ }
+ the_html += "</tr>"
+ }
+ the_html += "</tbody>";
+ the_html += "</table>";
+ } else {
+ the_html = "<span>No groups were found matching the entered criteria.</span>"
+ }
+
+ $('#group_results').html(the_html)
+ if (group_list.length > 0){
+ $('#groups_table').dataTable({
+ 'order': [[1, "asc" ]],
+ 'sDom': 'tr'
+ });
+ $('input[name=selected_group]:eq(0)').prop("checked", true)
+ $('#submit_group').css("display", "inline-block")
+ }
+ }
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/select_group_to_add.html b/wqflask/wqflask/templates/admin/select_group_to_add.html
deleted file mode 100644
index df70fb2f..00000000
--- a/wqflask/wqflask/templates/admin/select_group_to_add.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% extends "base.html" %}
-{% block title %}Matched Groups{% endblock %}
-{% block css %}
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
- <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
- <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
-{% endblock %}
-{% block content %}
-<!-- Start of body -->
- <div class="container">
- <h1>The following groups were found:</h1>
- <br>
- <form id="add_groups">
- <input type="hidden" name="resource_id" value="{{ resource_id }}">
- <div id="groups_list" style="min-width: 600px; max-width: 800px;">
- {% if group_list|length > 0 %}
- <button type="submit" class="btn btn-primary" style="margin-bottom: 40px;">Add Selected Group</button>
- <table id="groups_table" class="table-hover table-striped cell-border" style="float: left;">
- <thead>
- <tr>
- <th></th>
- <th>Name</th>
- <th>Created</th>
- <th>Last Changed</th>
- </tr>
- </thead>
- <tbody>
- {% for group in group_list %}
- <tr>
- <td align="center" style="padding: 0px;"><input type="radio" name="selected_group" VALUE="{{ group.id }}"></td>
- <td>{% if 'name' in group %}{{ group.name }}{% else %}N/A{% endif %}</td>
- <td>{% if 'created_timestamp' in group %}{{ group.created_timestamp }}{% else %}N/A{% endif %}</td>
- <td>{% if 'changed_timestamp' in group %}{{ group.changed_timestamp }}{% else %}N/A{% endif %}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% else %}
- <h2>No matching groups were found.</h2>
- {% endif %}
- </div>
- </form>
- </div>
-
-<!-- End of body -->
-
-{% endblock %}
-
-{% block js %}
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
- <script>
- $('#groups_table').dataTable();
- </script>
-{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/set_group_privileges.html b/wqflask/wqflask/templates/admin/set_group_privileges.html
new file mode 100644
index 00000000..bc52788f
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/set_group_privileges.html
@@ -0,0 +1,102 @@
+{% extends "base.html" %}
+{% block title %}Set Group Privileges{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <h1>Group Privileges</h1>
+ <br>
+ <form id="set_group_privileges" action="/resources/add_group" method="POST">
+ <input type="hidden" name="resource_id" value="{{ resource_id }}">
+ <input type="hidden" name="group_id" value="{{ group_id }}">
+ <div style="min-width: 600px; max-width: 800px;">
+ <button type="submit" class="btn btn-primary" style="margin-bottom: 10px;">Add Group</button>
+ <hr>
+ <h2>Data and Metadata Privileges</h2>
+ <table id="data_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>No-Access</th>
+ <th>View</th>
+ <th>Edit</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Data:</td>
+ {% if 'data' in default_privileges %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" {% if default_privileges.data == "no-access" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view" {% if default_privileges.data == "view" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit" {% if default_privileges.data == "edit" %}checked{% endif %}></td>
+ {% else %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit"></td>
+ {% endif %}
+ </tr>
+ <tr>
+ <td>Metadata:</td>
+ {% if 'metadata' in default_privileges %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" {% if default_privileges.metadata == "no-access" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view" {% if default_privileges.metadata == "view" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit" {% if default_privileges.metadata[-1] == "edit" %}checked{% endif %}></td>
+ {% else %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit"></td>
+ {% endif %}
+ </tr>
+ </tbody>
+ </table>
+ <hr>
+ <h2>Admin Privileges</h2>
+ <table id="admin_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Not Admin</th>
+ <th>Edit Access</th>
+ <th>Edit Admins</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Admin:</td>
+ {% if 'admin' in default_privileges %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" {% if default_privileges.admin == "not-admin" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access" {% if default_privileges.admin == "edit-access" %}checked{% endif %}></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins" {% if default_privileges.admin == "edit-admins" %}checked{% endif %}></td>
+ {% else %}
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins"></td>
+ {% endif %}
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </form>
+ </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+ <script>
+ $('#data_privileges_table').dataTable({
+ 'sDom': 'tr',
+ 'bSort': false
+ });
+ $('#admin_privileges_table').dataTable({
+ 'sDom': 'tr',
+ 'bSort': false
+ });
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/view_group.html b/wqflask/wqflask/templates/admin/view_group.html
new file mode 100644
index 00000000..b797cd70
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/view_group.html
@@ -0,0 +1,238 @@
+{% extends "base.html" %}
+{% block title %}View and Edit Group{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <div class="page-header">
+ <h1>
+ <span id="group_name">{{ group_info.name }}</span>
+ <input type="text" name="new_group_name" style="font-size: 20px; display: none; width: 500px;" class="form-control" placeholder="{{ group_info.name }}">
+ <button class="btn btn-default" style="display: inline;" id="change_group_name">Change Group Name</button>
+ </h1>
+ {% if user_is_admin == true %}
+ <div style="display: inline;">
+ <button type="button" id="remove_users" class="btn btn-danger" data-url="/groups/remove_users">Remove Selected Users from Group</button>
+ </div>
+ {% endif %}
+ </div>
+ <form id="group_form" action="/groups/view" method="POST">
+ <input type="hidden" name="group_id" value="{{ group_info.id }}">
+ <input type="hidden" name="selected_admin_ids" value="">
+ <input type="hidden" name="selected_member_ids" value="">
+ <div class="row">
+ <div id="groups_div" class="col-xs-6" style="margin-right: 30px; min-width: 600px; max-width: 800px;">
+ <div>
+ <div style="margin-top: 20px;"><h2>Admins</h2></div>
+ <hr>
+ <table id="group_admins" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Index</th>
+ <th>Name</th>
+ <th>Email Address</th>
+ <th>Organization</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for admin in admins %}
+ <tr>
+ <td style="text-align: center; padding: 0px 10px 2px 10px;"><input type="checkbox" name="admin_id" value="{{ admin.user_id }}"></td>
+ <td align="right">{{ loop.index }}</td>
+ <td>{% if 'full_name' in admin %}{{ admin.full_name }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'email_address' in admin %}{{ admin.email_address }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'organization' in admin %}{{ admin.organization }}{% else %}N/A{% endif %}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% if user_is_admin == true %}
+ <div style="margin-top: 20px;">
+ <span>E-mail of user to add to admins (multiple e-mails can be added separated by commas):</span>
+ <input type="text" size="60" name="admin_emails_to_add" placeholder="Enter E-mail(s)" value="">
+ </div>
+ <div style="margin-bottom: 30px; margin-top: 20px;">
+ <button type="button" id="add_admins" class="btn btn-primary" data-usertype="admin" data-url="/groups/add_admins">Add Admin(s)</button>
+ </div>
+ {% endif %}
+ </div>
+ <hr>
+ <div>
+ {% if members|length > 0 %}
+ <div><h2>Members</h2></div>
+ <hr>
+ <table id="group_members" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Index</th>
+ <th>Name</th>
+ <th>Email Address</th>
+ <th>Organization</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for member in members %}
+ <tr>
+ <td style="text-align: center; padding: 0px 10px 2px 10px;"><input type="checkbox" name="member_id" value="{{ member.user_id }}"></td>
+ <td align="right">{{ loop.index }}</td>
+ <td>{% if 'full_name' in member %}{{ member.full_name }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'email_address' in member %}{{ member.email_address }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'organization' in member %}{{ member.organization }}{% else %}N/A{% endif %}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% if user_is_admin == true %}
+ <div style="margin-top: 20px;">
+ <span>E-mail of user to add to members (multiple e-mails can be added separated by commas):</span>
+ <input type="text" size="60" name="member_emails_to_add" placeholder="Enter E-mail(s)" value="">
+ </div>
+ <div style="margin-bottom: 30px; margin-top: 20px;">
+ <button type="button" id="add_members" class="btn btn-primary" data-usertype="member" data-url="/groups/add_members">Add Member(s)</button>
+ </div>
+ {% endif %}
+ {% else %}
+ There are currently no members in this group.
+ {% endif %}
+ </div>
+ </div>
+ <div id="resources_div" class="col-xs-6" style="border-left: 1px solid #eee; margin-right: 30px; min-width: 600px; max-width: 800px;">
+ <div style="margin-top: 20px;"><h2>Resources</h2></div>
+ <hr>
+ {% if resources|length > 0 %}
+ <table id="resources" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th>Index</th>
+ <th>Name</th>
+ <th>Data</th>
+ <th>Metadata</th>
+ <th>Admin</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for resource in resources %}
+ <tr>
+ <td align="right">{{ loop.index }}</td>
+ <td>{% if 'name' in resource %}<a href="/resources/manage?resource_id={{ resource.id }}">{{ resource.name }}</a>{% else %}N/A{% endif %}</td>
+ <td>{% if 'data' in resource %}{{ resource.data }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'metadata' in resource %}{{ resource.metadata }}{% else %}N/A{% endif %}</td>
+ <td>{% if 'admin' in resource %}{{ resource.admin }}{% else %}N/A{% endif %}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ There are currently no resources associated with this group.
+ {% endif %}
+ </div>
+ </div>
+ </form>
+ </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+ <script type="text/javascript" charset="utf-8">
+ $(document).ready( function () {
+ $('#group_admins').dataTable({
+ 'order': [[1, "asc" ]],
+ 'columns': [
+ { "type": "natural", "width": "25px"},
+ { "type": "natural", "width": "30px" },
+ { "type": "natural", "width": "150px" },
+ { "type": "natural" },
+ { "type": "natural" }
+ ],
+ 'sDom': 'tr'
+ });
+ {% if members|length > 0 %}
+ $('#group_members').dataTable({
+ 'order': [[1, "asc" ]],
+ 'columns': [
+ { "type": "natural", "width": "25px"},
+ { "type": "natural", "width": "30px" },
+ { "type": "natural", "width": "150px" },
+ { "type": "natural" },
+ { "type": "natural" }
+ ],
+ 'sDom': 'tr'
+ });
+ {% endif %}
+ {% if resources|length > 0 %}
+ $('#resources').dataTable({
+ 'order': [[0, "asc" ]],
+ 'columns': [
+ { "type": "natural", "width": "30px" },
+ { "type": "natural", "width": "150px" },
+ { "type": "natural" },
+ { "type": "natural" },
+ { "type": "natural" }
+ ],
+ 'sDom': 'tr'
+ });
+ {% endif %}
+
+ $('#resources_div').css('height', $('#groups_div').css('height'))
+
+ submit_special = function(url) {
+ $("#group_form").attr("action", url);
+ return $("#group_form").submit();
+ };
+
+ $("#remove_users").on("click", function() {
+ url = $(this).data("url");
+ admins = [];
+ $("input[name=admin_id]:checked").each(function() {
+ admins.push($(this).val());
+ });
+ admins_string = admins.join(":")
+ $("input[name=selected_admin_ids]").val(admins_string)
+
+ members = [];
+ $("input[name=member_id]:checked").each(function() {
+ members.push($(this).val());
+ });
+ members_string = members.join(":")
+ $("input[name=selected_member_ids]").val(members_string)
+ return submit_special(url)
+ });
+
+ $("#add_admins, #add_members").on("click", function() {
+ url = $(this).data("url");
+ return submit_special(url)
+ });
+
+ $("#change_group_name").on("click", function() {
+ if ($('input[name=new_group_name]').css('display') == 'none') {
+ $('input[name=new_group_name]').css('display', 'inline');
+ $('#group_name').css('display', 'none');
+ } else {
+ new_name = $('input[name=new_group_name]').val()
+ $.ajax({
+ type: "POST",
+ url: "/groups/change_name",
+ data: {
+ group_id: $('input[name=group_id]').val(),
+ new_name: new_name
+ }
+ });
+ $('input[name=new_group_name]').css('display', 'none');
+ $('input[name=group_name]').val(new_name);
+ $('#group_name').text(new_name)
+ $('#group_name').css('display', 'inline');
+ }
+ });
+ });
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 07c1b48e..262d9ee5 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -94,6 +94,11 @@
<a id="login_in" href="/n/login">Sign in</a>
{% endif %}
</li>
+ {% if g.user_session.logged_in %}
+ <li class="">
+ <a id="manage_groups" title="Manage Groups" href="/groups/manage">Manage Groups</a>
+ </li>
+ {% endif %}
{% endif %}
<!--
<li style="margin-left: 20px;">
diff --git a/wqflask/wqflask/templates/set_group_privileges.html b/wqflask/wqflask/templates/set_group_privileges.html
new file mode 100644
index 00000000..98b0cc12
--- /dev/null
+++ b/wqflask/wqflask/templates/set_group_privileges.html
@@ -0,0 +1,77 @@
+{% extends "base.html" %}
+{% block title %}Set Group Privileges{% endblock %}
+{% block css %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
+ <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ <div class="container">
+ <h1>Group Privileges</h1>
+ <br>
+ <form id="set_group_privileges">
+ <input type="hidden" name="resource_id" value="{{ resource_id }}">
+ <div style="min-width: 600px; max-width: 800px;">
+ <button type="submit" class="btn btn-primary" style="margin-bottom: 40px;">Add Group</button>
+ <hr>
+ <h2>Data and Metadata Privileges</h2>
+ <table id="data_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>No-Access</th>
+ <th>View</th>
+ <th>Edit</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Data:</td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit"></td>
+ </tr>
+ <tr>
+ <td>Metadata:</td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit"></td>
+ </tr>
+ </tbody>
+ </table>
+ <hr>
+ <h2>Admin Privileges</h2>
+ <table id="admin_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Not Admin</th>
+ <th>Edit Access</th>
+ <th>Edit Admins</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Admin:</td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" checked></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access"></td>
+ <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </form>
+ </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+ <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+ <script>
+ $('#data_privileges_table').dataTable();
+ $('#admin_privileges_table').dataTable();
+ </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/show_trait_details.html b/wqflask/wqflask/templates/show_trait_details.html
index 5c315878..5e0bae79 100644
--- a/wqflask/wqflask/templates/show_trait_details.html
+++ b/wqflask/wqflask/templates/show_trait_details.html
@@ -248,8 +248,8 @@
<a target="_blank" href="http://gn1.genenetwork.org/webqtl/main.py?cmd=show&db={{ this_trait.dataset.name }}&probeset={{ this_trait.name }}">
<button type="button" id="view_in_gn1" class="btn btn-primary" title="View Trait in GN1">View in GN1</button>
</a>
- {% if resource_id %}
- <a target="_blank" href="./resources/manage?resource_id={{ resource_id }}">
+ {% if admin_status[1] == "owner" or admin_status[1] == "edit-admins" or admin_status[1] == "edit-access" %}
+ <a target="_blank" href="./resources/manage?resource_id={{ admin_status[0] }}">
<button type="button" id="edit_resource" class="btn btn-success" title="Edit Resource">Edit</button>
</a>
{% endif %}
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index ee827ba3..dc431aa9 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -102,7 +102,7 @@ def check_access_permissions():
else:
available = check_resource_availability(dataset)
- if not available:
+ if available == "no-access":
return redirect(url_for("no_access_page"))
@app.teardown_appcontext