diff options
author | zsloan | 2020-06-17 14:49:40 -0500 |
---|---|---|
committer | zsloan | 2020-06-17 14:49:40 -0500 |
commit | ea47eb228b1224ea83e3f50a056bf715b3bf5ec6 (patch) | |
tree | e6ff6824d2e1960e7b84342c7d09771d4783ae97 | |
parent | 7438f3c45122f02c25155b42ede703ad2845649c (diff) | |
download | genenetwork2-ea47eb228b1224ea83e3f50a056bf715b3bf5ec6.tar.gz |
Adding all the authentication stuff
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 |