about summary refs log tree commit diff
path: root/wqflask
diff options
context:
space:
mode:
Diffstat (limited to 'wqflask')
-rw-r--r--wqflask/base/data_set.py36
-rw-r--r--wqflask/base/trait.py5
-rw-r--r--wqflask/maintenance/set_resource_defaults.py307
-rw-r--r--wqflask/utility/authentication_tools.py132
-rw-r--r--wqflask/utility/redis_tools.py67
-rw-r--r--wqflask/wqflask/docs.py4
-rw-r--r--wqflask/wqflask/group_manager.py220
-rw-r--r--wqflask/wqflask/resource_manager.py204
-rw-r--r--wqflask/wqflask/static/new/javascript/group_manager.js74
-rw-r--r--wqflask/wqflask/static/new/javascript/search_results.js1
-rw-r--r--wqflask/wqflask/templates/admin/change_resource_owner.html116
-rw-r--r--wqflask/wqflask/templates/admin/create_group.html178
-rw-r--r--wqflask/wqflask/templates/admin/group_manager.html18
-rw-r--r--wqflask/wqflask/templates/admin/manage_resource.html200
-rw-r--r--wqflask/wqflask/templates/admin/search_for_groups.html198
-rw-r--r--wqflask/wqflask/templates/admin/select_group_to_add.html54
-rw-r--r--wqflask/wqflask/templates/admin/set_group_privileges.html102
-rw-r--r--wqflask/wqflask/templates/admin/view_group.html238
-rw-r--r--wqflask/wqflask/templates/base.html5
-rw-r--r--wqflask/wqflask/templates/set_group_privileges.html77
-rw-r--r--wqflask/wqflask/templates/show_trait_details.html4
-rw-r--r--wqflask/wqflask/views.py2
22 files changed, 1516 insertions, 726 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 1457ba8d..92dc8615 100644
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -486,25 +486,18 @@ class DatasetGroup(object):
 
 def datasets(group_name, this_group = None):
     key = "group_dataset_menu:v2:" + group_name
-    logger.debug("key is2:", key)
     dataset_menu = []
-    logger.debug("[tape4] webqtlConfig.PUBLICTHRESH:", webqtlConfig.PUBLICTHRESH)
-    logger.debug("[tape4] type webqtlConfig.PUBLICTHRESH:", type(webqtlConfig.PUBLICTHRESH))
     the_results = fetchall('''
          (SELECT '#PublishFreeze',PublishFreeze.FullName,PublishFreeze.Name
           FROM PublishFreeze,InbredSet
           WHERE PublishFreeze.InbredSetId = InbredSet.Id
             and InbredSet.Name = '%s'
-            and PublishFreeze.public > %s
-            and PublishFreeze.confidentiality < 1
           ORDER BY PublishFreeze.Id ASC)
          UNION
          (SELECT '#GenoFreeze',GenoFreeze.FullName,GenoFreeze.Name
           FROM GenoFreeze, InbredSet
           WHERE GenoFreeze.InbredSetId = InbredSet.Id
-            and InbredSet.Name = '%s'
-            and GenoFreeze.public > %s
-            and GenoFreeze.confidentiality < 1)
+            and InbredSet.Name = '%s')
          UNION
          (SELECT Tissue.Name, ProbeSetFreeze.FullName,ProbeSetFreeze.Name
           FROM ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue
@@ -512,12 +505,10 @@ def datasets(group_name, this_group = None):
             and ProbeFreeze.TissueId = Tissue.Id
             and ProbeFreeze.InbredSetId = InbredSet.Id
             and InbredSet.Name like %s
-            and ProbeSetFreeze.public > %s
-            and ProbeSetFreeze.confidentiality < 1
           ORDER BY Tissue.Name, ProbeSetFreeze.OrderList DESC)
-        ''' % (group_name, webqtlConfig.PUBLICTHRESH,
-              group_name, webqtlConfig.PUBLICTHRESH,
-              "'" + group_name + "'", webqtlConfig.PUBLICTHRESH))
+        ''' % (group_name,
+              group_name,
+              "'" + group_name + "'"))
 
     sorted_results = sorted(the_results, key=lambda kv: kv[0])
 
@@ -637,29 +628,25 @@ class DataSet(object):
 
         """
 
-
         try:
             if self.type == "ProbeSet":
                 query_args = tuple(escape(x) for x in (
-                    str(webqtlConfig.PUBLICTHRESH),
                     self.name,
                     self.name,
                     self.name))
 
                 self.id, self.name, self.fullname, self.shortname, self.data_scale, self.tissue = fetch1("""
-SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.FullName, ProbeSetFreeze.ShortName, ProbeSetFreeze.DataScale, Tissue.Name
-FROM ProbeSetFreeze, ProbeFreeze, Tissue
-WHERE ProbeSetFreeze.public > %s
-AND ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
-AND ProbeFreeze.TissueId = Tissue.Id
-AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFreeze.ShortName = '%s')
+    SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.FullName, ProbeSetFreeze.ShortName, ProbeSetFreeze.DataScale, Tissue.Name
+    FROM ProbeSetFreeze, ProbeFreeze, Tissue
+    WHERE ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
+    AND ProbeFreeze.TissueId = Tissue.Id
+    AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFreeze.ShortName = '%s')
                 """ % (query_args),"/dataset/"+self.name+".json",
             lambda r: (r["id"],r["name"],r["full_name"],r["short_name"],r["data_scale"],r["tissue"])
                 )
             else:
                 query_args = tuple(escape(x) for x in (
                     (self.type + "Freeze"),
-                    str(webqtlConfig.PUBLICTHRESH),
                     self.name,
                     self.name,
                     self.name))
@@ -668,9 +655,8 @@ AND (ProbeSetFreeze.Name = '%s' OR ProbeSetFreeze.FullName = '%s' OR ProbeSetFre
                 self.id, self.name, self.fullname, self.shortname = fetchone("""
                         SELECT Id, Name, FullName, ShortName
                         FROM %s
-                        WHERE public > %s AND
-                             (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
-                  """ % (query_args))
+                        WHERE (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
+                    """ % (query_args))
 
         except TypeError:
             logger.debug("Dataset {} is not yet available in GeneNetwork.".format(self.name))
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 2a945588..7700ecd5 100644
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -46,9 +46,10 @@ def create_trait(**kw):
             else:
                 permitted = check_resource_availability(dataset)
 
-    if permitted:
+    if permitted != "no-access":
         the_trait = GeneralTrait(**kw)
         if the_trait.dataset.type != "Temp":
+
             the_trait = retrieve_trait_info(the_trait, the_trait.dataset, get_qtl_info=kw.get('get_qtl_info'))
         return the_trait
     else:
@@ -383,7 +384,6 @@ def retrieve_trait_info(trait, dataset, get_qtl_info=False):
     if dataset.type == 'Publish':
         the_url = "http://localhost:8080/run-action?resource={}&user={}&branch=data&action=view".format(resource_id, g.user_session.user_id)
     else:
-
         the_url = "http://localhost:8080/run-action?resource={}&user={}&branch=data&action=view&trait={}".format(resource_id, g.user_session.user_id, trait.name)
 
     try:
@@ -424,7 +424,6 @@ def retrieve_trait_info(trait, dataset, get_qtl_info=False):
             logger.sql(query)
             trait_info = g.db.execute(query).fetchone()
 
-
         #XZ, 05/08/2009: Xiaodong add this block to use ProbeSet.Id to find the probeset instead of just using ProbeSet.Name
         #XZ, 05/08/2009: to avoid the problem of same probeset name from different platforms.
         elif dataset.type == 'ProbeSet':
diff --git a/wqflask/maintenance/set_resource_defaults.py b/wqflask/maintenance/set_resource_defaults.py
index ba102d9c..344e6a23 100644
--- a/wqflask/maintenance/set_resource_defaults.py
+++ b/wqflask/maintenance/set_resource_defaults.py
@@ -1,155 +1,154 @@
-"""

-

-Script that sets default resource access masks for use with the DB proxy

-

-Defaults will be:

-Owner - omni_gn

-Mask  - Public/non-confidential: { data: "view",

-                                   metadata: "view",

-                                   admin: "not-admin" }

-        Private/confidentia:     { data: "no-access",

-                                   metadata: "no-access",

-                                   admin: "not-admin" }

-

-To run:

-./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py

-

-"""

-

-from __future__ import print_function, division

-

-import sys

-import json

-

-# NEW: Note we prepend the current path - otherwise a guix instance of GN2 may be used instead

-sys.path.insert(0,'./')

-

-# NEW: import app to avoid a circular dependency on utility.tools

-from wqflask import app

-

-from utility.tools import SQL_URI

-from utility.redis_tools import get_redis_conn, get_user_id, add_resource, get_resources

-Redis = get_redis_conn()

-

-import MySQLdb

-

-import urlparse

-

-from utility.logger import getLogger

-logger = getLogger(__name__)

-

-def parse_db_uri():

-    """Converts a database URI to the db name, host name, user name, and password"""

-

-    parsed_uri = urlparse.urlparse(SQL_URI)

-

-    db_conn_info = dict(

-                        db = parsed_uri.path[1:],

-                        host = parsed_uri.hostname,

-                        user = parsed_uri.username,

-                        passwd = parsed_uri.password)

-

-    print(db_conn_info)

-    return db_conn_info

-

-def insert_probeset_resources(default_owner_id):

-    current_resources = Redis.hgetall("resources")

-    Cursor.execute("""  SELECT 

-                            ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.confidentiality, ProbeSetFreeze.public

-                        FROM 

-                            ProbeSetFreeze""")

-

-    resource_results = Cursor.fetchall()

-    for i, resource in enumerate(resource_results):

-        if i % 20 == 0:

-            print(i)

-        resource_ob = {}

-        resource_ob['name'] = resource[1]

-        resource_ob['owner_id'] = default_owner_id

-        resource_ob['data'] = { "dataset" : str(resource[0])}

-        resource_ob['type'] = "dataset-probeset"

-        if resource[2] < 1 and resource[3] > 0:

-            resource_ob['default_mask'] = { "data": ["no-access", "view"] }

-        else:

-            resource_ob['default_mask'] = { "data": ["no-access"] }

-        resource_ob['group_masks'] = {}

-

-        add_resource(resource_ob)

-

-def insert_publish_resources(default_owner_id):

-    current_resources = Redis.hgetall("resources")

-    Cursor.execute("""  SELECT 

-                            PublishXRef.Id, PublishFreeze.Id, InbredSet.InbredSetCode

-                        FROM

-                            PublishXRef, PublishFreeze, InbredSet, Publication

-                        WHERE

-                            PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND

-                            InbredSet.Id = PublishXRef.InbredSetId AND

-                            Publication.Id = PublishXRef.PublicationId""")

-

-    resource_results = Cursor.fetchall()

-    for resource in resource_results:

-        if resource[2]:

-            resource_ob = {}

-            if resource[2]:

-                resource_ob['name'] = resource[2] + "_" + str(resource[0])

-            else:

-                resource_ob['name'] = str(resource[0])

-            resource_ob['owner_id'] = default_owner_id

-            resource_ob['data'] = { "dataset" : str(resource[1]) ,

-                                    "trait"   : str(resource[0])}

-            resource_ob['type'] = "dataset-publish"

-            resource_ob['default_mask'] = { "data": "view" }

-

-            resource_ob['group_masks'] = {}

-

-            add_resource(resource_ob)

-        else:

-            continue

-

-def insert_geno_resources(default_owner_id):

-    current_resources = Redis.hgetall("resources")

-    Cursor.execute("""  SELECT 

-                            GenoFreeze.Id, GenoFreeze.ShortName, GenoFreeze.confidentiality

-                        FROM 

-                            GenoFreeze""")

-

-    resource_results = Cursor.fetchall()

-    for i, resource in enumerate(resource_results):

-        if i % 20 == 0:

-            print(i)

-        resource_ob = {}

-        resource_ob['name'] = resource[1]

-        resource_ob['owner_id'] = default_owner_id

-        resource_ob['data'] = { "dataset" : str(resource[0]) }

-        resource_ob['type'] = "dataset-geno"

-        if resource[2] < 1:

-            resource_ob['default_mask'] = { "data": "view" }

-        else:

-            resource_ob['default_mask'] = { "data": "no-access" }

-        resource_ob['group_masks'] = {}

-

-        add_resource(resource_ob)

-

-def insert_resources(default_owner_id):

-    current_resources = get_resources()

-    print("START")

-    insert_publish_resources(default_owner_id)

-    print("AFTER PUBLISH")

-    insert_geno_resources(default_owner_id)

-    print("AFTER GENO")

-    insert_probeset_resources(default_owner_id)

-    print("AFTER PROBESET")

-

-def main():

-    """Generates and outputs (as json file) the data for the main dropdown menus on the home page"""

-

-    Redis.delete("resources")

-

-    owner_id = get_user_id("email_address", "zachary.a.sloan@gmail.com")

-    insert_resources(owner_id)

-

-if __name__ == '__main__':

-    Conn = MySQLdb.Connect(**parse_db_uri())

-    Cursor = Conn.cursor()

+"""
+
+Script that sets default resource access masks for use with the DB proxy
+
+Defaults will be:
+Owner - omni_gn
+Mask  - Public/non-confidential: { data: "view",
+                                   metadata: "view",
+                                   admin: "not-admin" }
+        Private/confidentia:     { data: "no-access",
+                                   metadata: "no-access",
+                                   admin: "not-admin" }
+
+To run:
+./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py
+
+"""
+
+from __future__ import print_function, division
+
+import sys
+import json
+
+# NEW: Note we prepend the current path - otherwise a guix instance of GN2 may be used instead
+sys.path.insert(0,'./')
+
+# NEW: import app to avoid a circular dependency on utility.tools
+from wqflask import app
+
+from utility.tools import SQL_URI
+from utility.redis_tools import get_redis_conn, get_user_id, add_resource, get_resources
+Redis = get_redis_conn()
+
+import MySQLdb
+
+import urlparse
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+def parse_db_uri():
+    """Converts a database URI to the db name, host name, user name, and password"""
+
+    parsed_uri = urlparse.urlparse(SQL_URI)
+
+    db_conn_info = dict(
+                        db = parsed_uri.path[1:],
+                        host = parsed_uri.hostname,
+                        user = parsed_uri.username,
+                        passwd = parsed_uri.password)
+
+    print(db_conn_info)
+    return db_conn_info
+
+def insert_probeset_resources(default_owner_id):
+    current_resources = Redis.hgetall("resources")
+    Cursor.execute("""  SELECT
+                            ProbeSetFreeze.Id, ProbeSetFreeze.Name, ProbeSetFreeze.confidentiality, ProbeSetFreeze.public
+                        FROM
+                            ProbeSetFreeze""")
+
+    resource_results = Cursor.fetchall()
+    for i, resource in enumerate(resource_results):
+        resource_ob = {}
+        resource_ob['name'] = resource[1]
+        resource_ob['owner_id'] = default_owner_id
+        resource_ob['data'] = { "dataset" : str(resource[0])}
+        resource_ob['type'] = "dataset-probeset"
+        if resource[2] < 1 and resource[3] > 0:
+            resource_ob['default_mask'] = { "data": "view" }
+        else:
+            resource_ob['default_mask'] = { "data": "no-access" }
+        resource_ob['group_masks'] = {}
+
+        add_resource(resource_ob)
+
+def insert_publish_resources(default_owner_id):
+    current_resources = Redis.hgetall("resources")
+    Cursor.execute("""  SELECT 
+                            PublishXRef.Id, PublishFreeze.Id, InbredSet.InbredSetCode
+                        FROM
+                            PublishXRef, PublishFreeze, InbredSet, Publication
+                        WHERE
+                            PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
+                            InbredSet.Id = PublishXRef.InbredSetId AND
+                            Publication.Id = PublishXRef.PublicationId""")
+
+    resource_results = Cursor.fetchall()
+    for resource in resource_results:
+        if resource[2]:
+            resource_ob = {}
+            if resource[2]:
+                resource_ob['name'] = resource[2] + "_" + str(resource[0])
+            else:
+                resource_ob['name'] = str(resource[0])
+            resource_ob['owner_id'] = default_owner_id
+            resource_ob['data'] = { "dataset" : str(resource[1]) ,
+                                    "trait"   : str(resource[0])}
+            resource_ob['type'] = "dataset-publish"
+            resource_ob['default_mask'] = { "data": "view" }
+
+            resource_ob['group_masks'] = {}
+
+            add_resource(resource_ob)
+        else:
+            continue
+
+def insert_geno_resources(default_owner_id):
+    current_resources = Redis.hgetall("resources")
+    Cursor.execute("""  SELECT
+                            GenoFreeze.Id, GenoFreeze.ShortName, GenoFreeze.confidentiality
+                        FROM
+                            GenoFreeze""")
+
+    resource_results = Cursor.fetchall()
+    for i, resource in enumerate(resource_results):
+        resource_ob = {}
+        resource_ob['name'] = resource[1]
+        if resource[1] == "HET3-ITPGeno":
+            resource_ob['owner_id'] = "73a3f093-ca13-4ae0-a179-9a446f709f6e"
+        else:
+            resource_ob['owner_id'] = default_owner_id
+        resource_ob['data'] = { "dataset" : str(resource[0]) }
+        resource_ob['type'] = "dataset-geno"
+        if resource[2] < 1:
+            resource_ob['default_mask'] = { "data": "view" }
+        else:
+            resource_ob['default_mask'] = { "data": "no-access" }
+        resource_ob['group_masks'] = {}
+
+        add_resource(resource_ob)
+
+def insert_resources(default_owner_id):
+    current_resources = get_resources()
+    print("START")
+    insert_publish_resources(default_owner_id)
+    print("AFTER PUBLISH")
+    insert_geno_resources(default_owner_id)
+    print("AFTER GENO")
+    insert_probeset_resources(default_owner_id)
+    print("AFTER PROBESET")
+
+def main():
+    """Generates and outputs (as json file) the data for the main dropdown menus on the home page"""
+
+    Redis.delete("resources")
+
+    owner_id = get_user_id("email_address", "zachary.a.sloan@gmail.com")
+    insert_resources(owner_id)
+
+if __name__ == '__main__':
+    Conn = MySQLdb.Connect(**parse_db_uri())
+    Cursor = Conn.cursor()
     main()
\ No newline at end of file
diff --git a/wqflask/utility/authentication_tools.py b/wqflask/utility/authentication_tools.py
index 537881a5..07ceacc0 100644
--- a/wqflask/utility/authentication_tools.py
+++ b/wqflask/utility/authentication_tools.py
@@ -1,46 +1,86 @@
-from __future__ import absolute_import, print_function, division

-

-import json

-import requests

-

-from base import data_set

-

-from utility import hmac

-from utility.redis_tools import get_redis_conn, get_resource_info, get_resource_id

-

-from flask import Flask, g, redirect, url_for

-

-import logging

-logger = logging.getLogger(__name__ )

-

-def check_resource_availability(dataset, trait_id=None):

-    resource_id = get_resource_id(dataset, trait_id)

-

-    if resource_id:

-        the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)

-        try:

-            response = json.loads(requests.get(the_url).content)['data']

-        except:

-            resource_info = get_resource_info(resource_id)

-            response = resource_info['default_mask']['data']

-

-        if 'view' in response:

-            return True

-        else:

-            return redirect(url_for("no_access_page"))

-

-    return True

-

-def check_owner(dataset=None, trait_id=None, resource_id=None):

-    if resource_id:

-        resource_info = get_resource_info(resource_id)

-        if g.user_session.user_id == resource_info['owner_id']:

-            return resource_id

-    else:

-        resource_id = get_resource_id(dataset, trait_id)

-        if resource_id:

-            resource_info = get_resource_info(resource_id)

-            if g.user_session.user_id == resource_info['owner_id']:

-                return resource_id

-

-    return False
\ No newline at end of file
+from __future__ import absolute_import, print_function, division
+
+import json
+import requests
+
+from base import data_set
+
+from utility import hmac
+from utility.redis_tools import get_redis_conn, get_resource_info, get_resource_id
+
+from flask import Flask, g, redirect, url_for
+
+import logging
+logger = logging.getLogger(__name__ )
+
+def check_resource_availability(dataset, trait_id=None):
+    resource_id = get_resource_id(dataset, trait_id)
+
+    response = None
+    if resource_id:
+        resource_info = get_resource_info(resource_id)
+
+        the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)
+        try:
+            response = json.loads(requests.get(the_url).content)['data']
+        except:
+            response = resource_info['default_mask']['data']
+
+        if 'edit' in response:
+            return "edit"
+        elif 'view' in response:
+            return "view"
+        else:
+            return "no-access"
+
+    return False
+
+def check_admin(resource_id=None):
+
+    return "not-admin"
+
+    # ZS: commented out until proxy can return this
+    # the_url = "http://localhost:8080/available?resource={}&user={}".format(resource_id, g.user_session.user_id)
+    # try:
+    #     response = json.loads(requests.get(the_url).content)
+    # except:
+    #     response = resource_info['default_mask']['admin']
+
+    # if 'edit-admins' in response:
+    #     return "edit-admins"
+    # elif 'edit-access' in response:
+    #     return "edit-access"
+    # else:
+    #     return "not-admin"
+
+def check_owner(dataset=None, trait_id=None, resource_id=None):
+    if resource_id:
+        resource_info = get_resource_info(resource_id)
+        if g.user_session.user_id == resource_info['owner_id']:
+            return resource_id
+    else:
+        resource_id = get_resource_id(dataset, trait_id)
+        if resource_id:
+            resource_info = get_resource_info(resource_id)
+            if g.user_session.user_id == resource_info['owner_id']:
+                return resource_id
+
+    return False
+
+def check_owner_or_admin(dataset=None, trait_id=None, resource_id=None):
+    if resource_id:
+        resource_info = get_resource_info(resource_id)
+        if g.user_session.user_id == resource_info['owner_id']:
+            return [resource_id, "owner"]
+        else:
+            return [resource_id, check_admin(resource_id)]
+    else:
+        resource_id = get_resource_id(dataset, trait_id)
+        if resource_id:
+            resource_info = get_resource_info(resource_id)
+            if g.user_session.user_id == resource_info['owner_id']:
+                return [resource_id, "owner"]
+            else:
+                return [resource_id, check_admin(resource_id)]
+
+    return [resource_id, "not-admin"]
\ No newline at end of file
diff --git a/wqflask/utility/redis_tools.py b/wqflask/utility/redis_tools.py
index bc30a0af..c6d221ff 100644
--- a/wqflask/utility/redis_tools.py
+++ b/wqflask/utility/redis_tools.py
@@ -16,7 +16,7 @@ from utility.logger import getLogger
 logger = getLogger(__name__)
 
 def get_redis_conn():
-    Redis = redis.StrictRedis(port=6380)
+    Redis = redis.StrictRedis(port=6379)
     return Redis
 
 Redis = get_redis_conn()
@@ -51,6 +51,27 @@ def get_user_by_unique_column(column_name, column_value):
 
     return item_details
 
+def get_users_like_unique_column(column_name, column_value):
+    """
+    Like previous function, but this only checks if the input is a subset of a field and can return multiple results
+    """
+    matched_users = []
+
+    if column_value != "":
+        user_list = Redis.hgetall("users")
+        if column_name != "user_id":
+            for key in user_list:
+                user_ob = json.loads(user_list[key])
+                if column_name in user_ob:
+                    if column_value in user_ob[column_name]:
+                        matched_users.append(user_ob)
+        else:
+            matched_users.append(json.loads(user_list[column_value]))
+
+    return matched_users
+
+# def search_users_by_unique_column(column_name, column_value):
+
 def set_user_attribute(user_id, column_name, column_value):
     user_info = json.loads(Redis.hget("users", user_id))
     user_info[column_name] = column_value
@@ -142,6 +163,28 @@ def get_group_by_unique_column(column_name, column_value):
 
     return matched_groups
 
+def get_groups_like_unique_column(column_name, column_value):
+    """
+    Like previous function, but this only checks if the input is a subset of a field and can return multiple results
+    """
+    matched_groups = []
+
+    if column_value != "":
+        group_list = Redis.hgetall("groups")
+        if column_name != "group_id":
+            for key in group_list:
+                group_info = json.loads(group_list[key])
+                if column_name == "admins" or column_name == "members": #ZS: Since these fields are lists, search in the list
+                    if column_value in group_info[column_name]:
+                        matched_groups.append(group_info)
+                else:
+                    if column_name in group_info:
+                        if column_value in group_info[column_name]:
+                            matched_groups.append(group_info)
+        else:
+            matched_groups.append(json.loads(group_list[column_value]))
+
+    return matched_groups
 
 def create_group(admin_user_ids, member_user_ids = [], group_name = "Default Group Name"):
     group_id = str(uuid.uuid4())
@@ -192,9 +235,13 @@ def add_users_to_group(user_id, group_id, user_emails = [], admins = False): #ZS
 
 def remove_users_from_group(user_id, users_to_remove_ids, group_id, user_type = "members"): #ZS: User type is because I assume admins can remove other admins
     group_info = get_group_info(group_id)
+
     if user_id in group_info["admins"]:
+        users_to_remove_set = set(users_to_remove_ids)
+        if user_type == "admins" and user_id in users_to_remove_set: #ZS: Make sure an admin can't remove themselves from a group, since I imagine we don't want groups to be able to become admin-less
+            users_to_remove_set.remove(user_id)
         group_users = set(group_info[user_type])
-        group_users -= set(users_to_remove_ids)
+        group_users -= users_to_remove_set
         group_info[user_type] = list(group_users)
         group_info["changed_timestamp"] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
         Redis.hset("groups", group_id, json.dumps(group_info))
@@ -232,7 +279,6 @@ def get_resource_info(resource_id):
     return json.loads(resource_info)
 
 def add_resource(resource_info):
-
     if 'trait' in resource_info['data']:
         resource_id = hmac.hmac_creation('{}:{}:{}'.format(str(resource_info['type']), str(resource_info['data']['dataset']), str(resource_info['data']['trait'])))
     else:
@@ -241,3 +287,18 @@ def add_resource(resource_info):
     Redis.hset("resources", resource_id, json.dumps(resource_info))
 
     return resource_info
+
+def add_access_mask(resource_id, group_id, access_mask):
+    the_resource = get_resource_info(resource_id)
+    the_resource['group_masks'][group_id] = access_mask
+
+    Redis.hset("resources", resource_id, json.dumps(the_resource))
+
+    return the_resource
+
+def change_resource_owner(resource_id, new_owner_id):
+    the_resource= get_resource_info(resource_id)
+    the_resource['owner_id'] = new_owner_id
+
+    Redis.delete("resource")
+    Redis.hset("resources", resource_id, json.dumps(the_resource))
\ No newline at end of file
diff --git a/wqflask/wqflask/docs.py b/wqflask/wqflask/docs.py
index 0187f32e..78407e22 100644
--- a/wqflask/wqflask/docs.py
+++ b/wqflask/wqflask/docs.py
@@ -1,5 +1,7 @@
 from __future__ import absolute_import, print_function, division
 
+import codecs
+
 from flask import g
 
 from utility.logger import getLogger
@@ -20,7 +22,7 @@ class Docs(object):
             self.content = ""
         else:
             self.title = result[0]
-            self.content = result[1]
+            self.content = result[1].encode("latin1")
 
         self.editable = "false"
         # ZS: Removing option to edit to see if text still gets vandalized
diff --git a/wqflask/wqflask/group_manager.py b/wqflask/wqflask/group_manager.py
index f41ae56d..9afc016b 100644
--- a/wqflask/wqflask/group_manager.py
+++ b/wqflask/wqflask/group_manager.py
@@ -1,77 +1,145 @@
-

-from __future__ import print_function, division, absolute_import

-

-from flask import (Flask, g, render_template, url_for, request, make_response,

-                   redirect, flash)

-

-from wqflask import app

-from wqflask.user_login import send_verification_email

-

-from utility.redis_tools import get_user_groups, get_group_info, create_group, delete_group, add_users_to_group, remove_users_from_group, \

-                                change_group_name, save_verification_code, check_verification_code, get_user_by_unique_column

-

-from utility.logger import getLogger

-logger = getLogger(__name__)

-

-@app.route("/groups/manage", methods=('GET', 'POST'))

-def manage_groups():

-   params = request.form if request.form else request.args

-   if "add_new_group" in params:

-      return redirect(url_for('add_group'))

-   else:

-      admin_groups, user_groups = get_user_groups(g.user_session.user_id)

-      return render_template("admin/group_manager.html", admin_groups=admin_groups, user_groups=user_groups)

-

-@app.route("/groups/remove", methods=('POST',))

-def remove_groups():

-   group_ids_to_remove = request.form['selected_group_ids']

-   for group_id in group_ids_to_remove.split(":"):

-      delete_group(g.user_session.user_id, group_id)

-

-   return redirect(url_for('manage_groups'))

-

-@app.route("/groups/create", methods=('GET', 'POST'))

-def add_group():

-   params = request.form if request.form else request.args

-   if "group_name" in params:

-      member_user_ids = set()

-      admin_user_ids = set()

-      admin_user_ids.add(g.user_session.user_id) #ZS: Always add the user creating the group as an admin

-      if "admin_emails" in params:

-         admin_emails = params['admin_emails_to_add'].split(",")

-         for email in admin_emails:

-            user_details = get_user_by_unique_column("email_address", email)

-            if user_details:

-               admin_user_ids.add(user_details['user_id'])

-         #send_group_invites(params['group_id'], user_email_list = admin_emails, user_type="admins")

-      if "user_emails" in params:

-         member_emails = params['member_emails_to_add'].split(",")

-         for email in member_emails:

-            user_details = get_user_by_unique_column("email_address", email)

-            if user_details:

-               member_user_ids.add(user_details['user_id'])

-         #send_group_invites(params['group_id'], user_email_list = user_emails, user_type="members")

-

-      create_group(list(admin_user_ids), list(member_user_ids), params['group_name'])

-      return redirect(url_for('manage_groups'))

-   else:

-      return render_template("admin/create_group.html")

-

-#ZS: Will integrate this later, for now just letting users be added directly

-def send_group_invites(group_id, user_email_list = [], user_type="members"):

-   for user_email in user_email_list:

-      user_details = get_user_by_unique_column("email_address", user_email)

-      if user_details:

-         group_info = get_group_info(group_id)

-         #ZS: Probably not necessary since the group should normally always exist if group_id is being passed here,

-         #    but it's technically possible to hit it if Redis is cleared out before submitting the new users or something

-         if group_info:

-            #ZS: Don't add user if they're already an admin or if they're being added a regular user and are already a regular user,

-            #    but do add them if they're a regular user and are added as an admin

-            if (user_details['user_id'] in group_info['admins']) or \

-               ((user_type == "members") and (user_details['user_id'] in group_info['members'])):

-               continue

-            else:

-               send_verification_email(user_details, template_name = "email/group_verification.txt", key_prefix = "verification_code", subject = "You've been invited to join a GeneNetwork user group")

-

+
+from __future__ import print_function, division, absolute_import
+
+from flask import (Flask, g, render_template, url_for, request, make_response,
+                   redirect, flash)
+
+from wqflask import app
+from wqflask.user_login import send_verification_email
+
+from utility.redis_tools import get_user_groups, get_group_info, create_group, delete_group, add_users_to_group, remove_users_from_group, \
+                                change_group_name, save_verification_code, check_verification_code, get_user_by_unique_column, get_resources, get_resource_info
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+@app.route("/groups/manage", methods=('GET', 'POST'))
+def manage_groups():
+   params = request.form if request.form else request.args
+   if "add_new_group" in params:
+      return redirect(url_for('add_group'))
+   else:
+      admin_groups, user_groups = get_user_groups(g.user_session.user_id)
+      return render_template("admin/group_manager.html", admin_groups=admin_groups, user_groups=user_groups)
+
+@app.route("/groups/view", methods=('GET', 'POST'))
+def view_group():
+   params = request.form if request.form else request.args
+   group_id = params['id']
+   group_info = get_group_info(group_id)
+   admins_info = []
+   user_is_admin = False
+   if g.user_session.user_id in group_info['admins']:
+      user_is_admin = True
+   for user_id in group_info['admins']:
+      if user_id:
+         user_info = get_user_by_unique_column("user_id", user_id)
+         admins_info.append(user_info)
+   members_info = []
+   for user_id in group_info['members']:
+      if user_id:
+         user_info = get_user_by_unique_column("user_id", user_id)
+         members_info.append(user_info)
+
+   #ZS: This whole part might not scale well with many resources
+   resources_info  = []
+   all_resources = get_resources()
+   for resource_id in all_resources:
+      resource_info = get_resource_info(resource_id)
+      group_masks = resource_info['group_masks']
+      if group_id in group_masks:
+         this_resource = {}
+         privileges = group_masks[group_id]
+         this_resource['id'] = resource_id
+         this_resource['name'] = resource_info['name']
+         this_resource['data'] = privileges['data']
+         this_resource['metadata'] = privileges['metadata']
+         this_resource['admin'] = privileges['admin']
+         resources_info.append(this_resource)
+
+   return render_template("admin/view_group.html", group_info=group_info, admins=admins_info, members=members_info, user_is_admin=user_is_admin, resources=resources_info)
+
+@app.route("/groups/remove", methods=('POST',))
+def remove_groups():
+   group_ids_to_remove = request.form['selected_group_ids']
+   for group_id in group_ids_to_remove.split(":"):
+      delete_group(g.user_session.user_id, group_id)
+
+   return redirect(url_for('manage_groups'))
+
+@app.route("/groups/remove_users", methods=('POST',))
+def remove_users():
+   group_id = request.form['group_id']
+   admin_ids_to_remove = request.form['selected_admin_ids']
+   member_ids_to_remove = request.form['selected_member_ids']
+
+   remove_users_from_group(g.user_session.user_id, admin_ids_to_remove.split(":"), group_id, user_type="admins")
+   remove_users_from_group(g.user_session.user_id, member_ids_to_remove.split(":"), group_id, user_type="members")
+
+   return redirect(url_for('view_group', id=group_id))
+
+@app.route("/groups/add_<path:user_type>", methods=('POST',))
+def add_users(user_type='members'):
+   group_id = request.form['group_id']
+   if user_type == "admins":
+      user_emails = request.form['admin_emails_to_add'].split(",")
+      add_users_to_group(g.user_session.user_id, group_id, user_emails, admins = True)
+   elif user_type == "members":
+      user_emails = request.form['member_emails_to_add'].split(",")
+      add_users_to_group(g.user_session.user_id, group_id, user_emails, admins = False)
+
+   return redirect(url_for('view_group', id=group_id))
+
+@app.route("/groups/change_name", methods=('POST',))
+def change_name():
+   group_id = request.form['group_id']
+   new_name = request.form['new_name']
+   group_info = change_group_name(g.user_session.user_id, group_id, new_name)
+
+   return new_name
+
+@app.route("/groups/create", methods=('GET', 'POST'))
+def add_or_edit_group():
+   params = request.form if request.form else request.args
+   if "group_name" in params:
+      member_user_ids = set()
+      admin_user_ids = set()
+      admin_user_ids.add(g.user_session.user_id) #ZS: Always add the user creating the group as an admin
+      if "admin_emails_to_add" in params:
+         admin_emails = params['admin_emails_to_add'].split(",")
+         for email in admin_emails:
+            user_details = get_user_by_unique_column("email_address", email)
+            if user_details:
+               admin_user_ids.add(user_details['user_id'])
+         #send_group_invites(params['group_id'], user_email_list = admin_emails, user_type="admins")
+      if "member_emails_to_add" in params:
+         member_emails = params['member_emails_to_add'].split(",")
+         for email in member_emails:
+            user_details = get_user_by_unique_column("email_address", email)
+            if user_details:
+               member_user_ids.add(user_details['user_id'])
+         #send_group_invites(params['group_id'], user_email_list = user_emails, user_type="members")
+
+      create_group(list(admin_user_ids), list(member_user_ids), params['group_name'])
+      return redirect(url_for('manage_groups'))
+   else:
+      return render_template("admin/create_group.html")
+
+#ZS: Will integrate this later, for now just letting users be added directly
+def send_group_invites(group_id, user_email_list = [], user_type="members"):
+   for user_email in user_email_list:
+      user_details = get_user_by_unique_column("email_address", user_email)
+      if user_details:
+         group_info = get_group_info(group_id)
+         #ZS: Probably not necessary since the group should normally always exist if group_id is being passed here,
+         #    but it's technically possible to hit it if Redis is cleared out before submitting the new users or something
+         if group_info:
+            #ZS: Don't add user if they're already an admin or if they're being added a regular user and are already a regular user,
+            #    but do add them if they're a regular user and are added as an admin
+            if (user_details['user_id'] in group_info['admins']) or \
+               ((user_type == "members") and (user_details['user_id'] in group_info['members'])):
+               continue
+            else:
+               send_verification_email(user_details, template_name = "email/group_verification.txt", key_prefix = "verification_code", subject = "You've been invited to join a GeneNetwork user group")
+
 #@app.route()
\ No newline at end of file
diff --git a/wqflask/wqflask/resource_manager.py b/wqflask/wqflask/resource_manager.py
index 7d88b8ed..0f9f5c9d 100644
--- a/wqflask/wqflask/resource_manager.py
+++ b/wqflask/wqflask/resource_manager.py
@@ -1,72 +1,134 @@
-from __future__ import print_function, division, absolute_import

-

-from flask import (Flask, g, render_template, url_for, request, make_response,

-                   redirect, flash)

-

-from wqflask import app

-

-from utility.authentication_tools import check_owner

-from utility.redis_tools import get_resource_info, get_group_info, get_group_by_unique_column, get_user_id

-

-from utility.logger import getLogger

-logger = getLogger(__name__)

-

-@app.route("/resources/manage", methods=('GET', 'POST'))

-def view_resource():

-    params = request.form if request.form else request.args

-    if 'resource_id' in request.args:

-        resource_id = request.args['resource_id']

-        if check_owner(resource_id=resource_id):

-            resource_info = get_resource_info(resource_id)

-            group_masks = resource_info['group_masks']

-            group_masks_with_names = get_group_names(group_masks)

-            default_mask = resource_info['default_mask']['data']

-            return render_template("admin/manage_resource.html", resource_id = resource_id, resource_info=resource_info, default_mask=default_mask, group_masks=group_masks_with_names)

-        else:

-            return redirect(url_for("no_access_page"))

-        

-@app.route("/resources/add_group", methods=('POST',))

-def add_group_to_resource():

-    resource_id = request.form['resource_id']

-    if check_owner(resource_id=resource_id):

-        if all(key in request.form for key in ('group_id', 'group_name', 'user_name', 'user_email')):

-            group_list = []

-            if request.form['group_id'] != "":

-                the_group = get_group_info(request.form['group_id'])

-                if the_group:

-                    group_list.append(the_group)

-            if request.form['group_name'] != "":

-                matched_groups = get_group_by_unique_column("name", request.form['group_name'])

-                for group in matched_groups:

-                    group_list.append(group)

-            if request.form['user_name'] != "":

-                user_id = get_user_id("user_name", request.form['user_name'])

-                if user_id:

-                    matched_groups = get_group_by_unique_column("admins", user_id)

-                    matched_groups += get_group_by_unique_column("members", user_id)

-                    for group in matched_groups:

-                        group_list.append(group)

-            if request.form['user_email'] != "":

-                user_id = get_user_id("email_address", request.form['user_email'])

-                if user_id:

-                    matched_groups = get_group_by_unique_column("admins", user_id)

-                    matched_groups += get_group_by_unique_column("members", user_id)

-                    for group in matched_groups:

-                        group_list.append(group)

-            return render_template("admin/select_group_to_add.html", group_list=group_list, resource_id = resource_id)

-        elif 'selected_group' in request.form:

-            group_id = request.form['selected_group']

-            return render_template("admin/set_group_privileges.html", resource_id = resource_id, group_id = group_id)

-        else:

-            return render_template("admin/search_for_groups.html", resource_id = resource_id)

-    else:

-        return redirect(url_for("no_access_page"))

-

-def get_group_names(group_masks):

-    group_masks_with_names = {}

-    for group_id, group_mask in group_masks.iteritems():

-        this_mask = group_mask

-        group_name = get_group_info(group_id)['name']

-        this_mask['name'] = group_name

-    

+from __future__ import print_function, division, absolute_import
+
+import json
+
+from flask import (Flask, g, render_template, url_for, request, make_response,
+                   redirect, flash)
+
+from wqflask import app
+
+from utility.authentication_tools import check_owner_or_admin
+from utility.redis_tools import get_resource_info, get_group_info, get_groups_like_unique_column, get_user_id, get_user_by_unique_column, get_users_like_unique_column, add_access_mask, add_resource, change_resource_owner
+
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
+@app.route("/resources/manage", methods=('GET', 'POST'))
+def manage_resource():
+    params = request.form if request.form else request.args
+    if 'resource_id' in request.args:
+        resource_id = request.args['resource_id']
+        admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+
+        resource_info = get_resource_info(resource_id)
+        group_masks = resource_info['group_masks']
+        group_masks_with_names = get_group_names(group_masks)
+        default_mask = resource_info['default_mask']['data']
+        owner_id = resource_info['owner_id']
+        owner_info = get_user_by_unique_column("user_id", owner_id)
+
+        if 'name' in owner_info:
+            owner_display_name = owner_info['full_name']
+        elif 'user_name' in owner_info:
+            owner_display_name = owner_info['user_name']
+        elif 'email_address' in owner_info:
+            owner_display_name = owner_info['email_address']
+        else:
+            owner_display_name = None
+
+        return render_template("admin/manage_resource.html", owner_name = owner_display_name, resource_id = resource_id, resource_info=resource_info, default_mask=default_mask, group_masks=group_masks_with_names, admin_status=admin_status)
+
+@app.route("/search_for_users", methods=('POST',))
+def search_for_user():
+    params = request.form
+    user_list = []
+    user_list += get_users_like_unique_column("full_name", params['user_name'])
+    user_list += get_users_like_unique_column("email_address", params['user_email'])
+
+    return json.dumps(user_list)
+
+@app.route("/search_for_groups", methods=('POST',))
+def search_for_groups():
+    params = request.form
+    group_list = []
+    group_list += get_groups_like_unique_column("id", params['group_id'])
+    group_list += get_groups_like_unique_column("name", params['group_name'])
+
+    user_list = []
+    user_list += get_users_like_unique_column("full_name", params['user_name'])
+    user_list += get_users_like_unique_column("email_address", params['user_email'])
+    for user in user_list:
+        group_list += get_groups_like_unique_column("admins", user['user_id'])
+        group_list += get_groups_like_unique_column("members", user['user_id'])
+
+    return json.dumps(group_list)
+
+@app.route("/resources/change_owner", methods=('POST',))
+def change_owner():
+    resource_id = request.form['resource_id']
+    if 'new_owner' in request.form:
+        admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+        if admin_status == "owner":
+            new_owner_id = request.form['new_owner']
+            change_resource_owner(resource_id, new_owner_id)
+            flash("The resource's owner has beeen changed.", "alert-info")
+            return redirect(url_for("manage_resource", resource_id=resource_id))
+        else:
+            flash("You lack the permissions to make this change.", "error")
+            return redirect(url_for("manage_resource", resource_id=resource_id))
+    else:
+        return render_template("admin/change_resource_owner.html", resource_id = resource_id)
+
+@app.route("/resources/change_default_privileges", methods=('POST',))
+def change_default_privileges():
+    resource_id = request.form['resource_id']
+    admin_status = check_owner_or_admin(resource_id=resource_id)
+    if admin_status == "owner" or admin_status == "edit-admins":
+        resource_info = get_resource_info(resource_id)
+        default_mask = resource_info['default_mask']
+        if request.form['open_to_public'] == "True":
+            default_mask['data'] = 'view'
+        else:
+            default_mask['data'] = 'no-access'
+        resource_info['default_mask'] = default_mask
+        add_resource(resource_info)
+        flash("Your changes have been saved.", "alert-info")
+        return redirect(url_for("manage_resource", resource_id=resource_id))
+    else:
+        return redirect(url_for("no_access_page"))
+
+@app.route("/resources/add_group", methods=('POST',))
+def add_group_to_resource():
+    resource_id = request.form['resource_id']
+    admin_status = check_owner_or_admin(resource_id=resource_id)[1]
+    if admin_status == "owner" or admin_status == "edit-admins" or admin_status == "edit-access":
+        if 'selected_group' in request.form:
+            group_id = request.form['selected_group']
+            resource_info = get_resource_info(resource_id)
+            default_privileges = resource_info['default_mask']
+            return render_template("admin/set_group_privileges.html", resource_id = resource_id, group_id = group_id, default_privileges = default_privileges)
+        elif all(key in request.form for key in ('data_privilege', 'metadata_privilege', 'admin_privilege')):
+            group_id = request.form['group_id']
+            group_name = get_group_info(group_id)['name']
+            access_mask = {
+                'data': request.form['data_privilege'],
+                'metadata': request.form['metadata_privilege'],
+                'admin': request.form['admin_privilege']
+            }
+            add_access_mask(resource_id, group_id, access_mask)
+            flash("Privileges have been added for group {}.".format(group_name), "alert-info")
+            return redirect(url_for("manage_resource", resource_id=resource_id))
+        else:
+            return render_template("admin/search_for_groups.html", resource_id = resource_id)
+    else:
+        return redirect(url_for("no_access_page"))
+
+def get_group_names(group_masks):
+    group_masks_with_names = {}
+    for group_id, group_mask in group_masks.iteritems():
+        this_mask = group_mask
+        group_name = get_group_info(group_id)['name']
+        this_mask['name'] = group_name
+        group_masks_with_names[group_id] = this_mask
+    
     return group_masks_with_names
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/group_manager.js b/wqflask/wqflask/static/new/javascript/group_manager.js
index 5e82d104..4c172cbf 100644
--- a/wqflask/wqflask/static/new/javascript/group_manager.js
+++ b/wqflask/wqflask/static/new/javascript/group_manager.js
@@ -1,38 +1,38 @@
-$('#add_to_admins').click(function() {

-    add_emails('admin')

-})

-

-$('#add_to_members').click(function() {

-    add_emails('member')

-})

-

-$('#clear_admins').click(function(){

-    clear_emails('admin')

-})

-

-$('#clear_members').click(function(){

-    clear_emails('member')

-})

-

-

-function add_emails(user_type){

-    var email_address = $('input[name=user_email]').val();

-    var email_list_string = $('input[name=' + user_type + '_emails_to_add]').val()

-    console.log(email_list_string)

-    if (email_list_string == ""){

-        var email_set = new Set();

-    } else {

-        var email_set = new Set(email_list_string.split(","))

-    }

-    email_set.add(email_address)

-

-    $('input[name=' + user_type + '_emails_to_add]').val(Array.from(email_set).join(','))

-

-    var emails_display_string = Array.from(email_set).join('\n')

-    $('.added_' + user_type + 's').val(emails_display_string)

-}

-

-function clear_emails(user_type){

-    $('input[name=' + user_type + '_emails_to_add]').val("")

-    $('.added_' + user_type + 's').val("")

+$('#add_to_admins').click(function() {
+    add_emails('admin')
+})
+
+$('#add_to_members').click(function() {
+    add_emails('member')
+})
+
+$('#clear_admins').click(function(){
+    clear_emails('admin')
+})
+
+$('#clear_members').click(function(){
+    clear_emails('member')
+})
+
+
+function add_emails(user_type){
+    var email_address = $('input[name=user_email]').val();
+    var email_list_string = $('input[name=' + user_type + '_emails_to_add]').val().trim()
+    console.log(email_list_string)
+    if (email_list_string == ""){
+        var email_set = new Set();
+    } else {
+        var email_set = new Set(email_list_string.split(","))
+    }
+    email_set.add(email_address)
+
+    $('input[name=' + user_type + '_emails_to_add]').val(Array.from(email_set).join(','))
+
+    var emails_display_string = Array.from(email_set).join('\n')
+    $('.added_' + user_type + 's').val(emails_display_string)
+}
+
+function clear_emails(user_type){
+    $('input[name=' + user_type + '_emails_to_add]').val("")
+    $('.added_' + user_type + 's').val("")
 }
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 8fa698b4..115dac13 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -296,7 +296,6 @@ $(function() {
   $("#deselect_all").click(deselect_all);
   $("#invert").click(invert);
   $("#add").click(add);
-  $("#remove").click(remove);
   $("#submit_bnw").click(submit_bnw);
   $("#export_traits").click(export_traits);
   $('.trait_checkbox, .btn').click(change_buttons);
diff --git a/wqflask/wqflask/templates/admin/change_resource_owner.html b/wqflask/wqflask/templates/admin/change_resource_owner.html
new file mode 100644
index 00000000..ae9409b0
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/change_resource_owner.html
@@ -0,0 +1,116 @@
+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        <div class="page-header">
+            <h1>Search for user to assign ownership to:</h1>
+        </div>
+        <form id="change_owner_form" action="/resources/change_owner" method="POST">
+            <input type="hidden" name="resource_id" value="{{ resource_id }}">
+            <div style="min-width: 600px; max-width: 800px;">
+                <fieldset>
+                    <div class="form-horizontal" style="width: 900px;">
+                        <div style="margin-bottom: 30px;">
+                            <h2>Search for user by either name or e-mail:</h2>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User's Name:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="user_name" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User's E-mail:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="user_email" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <button type="button" id="find_users" class="btn btn-primary">Search</button>
+                                <button style="margin-left: 20px; display: none;" type="submit" id="submit_new_owner" class="btn btn-success">Assign Ownership to Selected User</button>
+                            </div>
+                        </div>
+                    </div>
+                </fieldset>
+                <hr>
+                <div id="user_results">
+                </div>
+            </div>
+        </form>
+    </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+    <script language="javascript">
+        $('#find_users').click(function() {
+            $.ajax({
+                method: "POST",
+                url: "/search_for_users",
+                data: {
+                    user_name: $('input[name=user_name]').val(),
+                    user_email: $('input[name=user_email]').val()
+                },
+                success: populate_users
+            });
+        })
+
+        populate_users = function(json_user_list){
+            var user_list = JSON.parse(json_user_list)
+
+            var the_html = ""
+            if (user_list.length > 0){
+                the_html += "<table id='users_table' style='padding-top: 10px; width: 100%;' class='table-hover table-striped cell-border'>";
+                the_html += "<thead><tr><th></th><th>Index</th><th>Name</th><th>E-mail Address</th><th>Organization</th></tr></thead>";
+                the_html += "<tbody>";
+                for (_i = 0, _len = user_list.length; _i < _len; _i++) {
+                    this_user = user_list[_i]
+                    the_html += "<tr>";
+                    the_html += "<td align='center' class='select_user'><input type='radio' name='new_owner' value='" + this_user.user_id + "'></td>";
+                    the_html += "<td>" + (_i + 1).toString() + "</td>"
+                    if ("full_name" in this_user) {
+                        the_html += "<td>" + this_user.full_name + "</td>";
+                    } else {
+                        the_html += "<td>N/A</td>"
+                    }
+                    if ("email_address" in this_user) {
+                        the_html += "<td>" + this_user.email_address + "</td>";
+                    } else {
+                        the_html += "<td>N/A</td>"
+                    }
+                    if ("organization" in this_user) {
+                        the_html += "<td>" + this_user.organization + "</td>";
+                    } else {
+                        the_html += "<td>N/A</td>"
+                    }
+                    the_html += "</tr>"
+                }
+                the_html += "</tbody>";
+                the_html += "</table>";
+            } else {
+                the_html = "<span>No users were found matching the entered criteria.</span>"
+            }
+
+            $('#user_results').html(the_html)
+            if (user_list.length > 0){
+                $('#users_table').dataTable({
+                    'order': [[1, "asc" ]],
+                    'sDom': 'tr'
+                });
+                $('input[name=select_user]:eq(0)').prop("checked", true)
+                $('#submit_new_owner').css("display", "inline-block")
+            }
+        }
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/create_group.html b/wqflask/wqflask/templates/admin/create_group.html
index 55c3fa0b..5a6929fb 100644
--- a/wqflask/wqflask/templates/admin/create_group.html
+++ b/wqflask/wqflask/templates/admin/create_group.html
@@ -1,89 +1,89 @@
-{% extends "base.html" %}

-{% block title %}Group Manager{% endblock %}

-{% block content %}

-<!-- Start of body -->

-    <div class="container">

-        <div class="page-header">

-            <h1>Create Group</h1>

-        </div>

-        <form action="/groups/create" method="POST">

-            <input type="hidden" name="admin_emails_to_add" value="">

-            <input type="hidden" name="member_emails_to_add" value="">

-            <fieldset>

-                <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-12">

-                                <input name="group_name" type="text" style="width:100%;"></input>

-                            </div>

-                        </div>

-                    </div>

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Add User Email:</label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-12">

-                                <input name="user_email" type="text" style="width:100%;"></input>

-                            </div>

-                        </div>

-                    </div>

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label class="col-xs-3"></label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-6">

-                                <button type="button" id="add_to_admins" class="btn btn-default">Add to Admins</button>

-                            </div>

-                            <div class="col-xs-6">

-                                <button type="button" id="add_to_members" class="btn btn-default">Add to Members</button>

-                            </div>

-                        </div>

-                    </div>

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label class="col-xs-3" style="font-size: 18px;">Members to be added:</label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-6">

-                                <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_admins"></textarea>

-                            </div>

-                            <div class="col-xs-6">

-                                <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_members"></textarea>

-                            </div>

-                        </div>

-                    </div>

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label class="col-xs-3"></label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-6">

-                                <button type="button" id="clear_admins" class="btn btn-default">Clear</button>

-                            </div>

-                            <div class="col-xs-6">

-                                <button type="button" id="clear_members" class="btn btn-default">Clear</button>

-                            </div>

-                        </div>

-                    </div>

-                    <div class="form-group" style="padding-left: 20px;">

-                        <label for="create_group" class="col-xs-3" style="float: left; font-size: 18px;"></label>

-                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                            <div class="col-xs-6">

-                                <button type="button" id="create_group" class="btn btn-primary">Create Group</button>

-                            </div>

-                        </div>

-                    </div>

-                </div>

-            </fieldset>

-        </form>

-    </div>

-

-

-

-<!-- End of body -->

-

-{% endblock %}

-

-{% block js %}

-    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>

-

-    <script type="text/javascript" charset="utf-8">

-    </script>

-{% endblock %}

+{% extends "base.html" %}
+{% block title %}Group Manager{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        <div class="page-header">
+            <h1>Create Group</h1>
+        </div>
+        <form action="/groups/create" method="POST">
+            <input type="hidden" name="admin_emails_to_add" value="">
+            <input type="hidden" name="member_emails_to_add" value="">
+            <fieldset>
+                <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-12">
+                                <input name="group_name" type="text" style="width:100%;"></input>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Add User Email:</label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-12">
+                                <input name="user_email" type="text" style="width:100%;"></input>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label class="col-xs-3"></label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-6">
+                                <button type="button" id="add_to_admins" class="btn btn-default">Add to Admins</button>
+                            </div>
+                            <div class="col-xs-6">
+                                <button type="button" id="add_to_members" class="btn btn-default">Add to Members</button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label class="col-xs-3" style="font-size: 18px;">Members to be added:</label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-6">
+                                <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_admins"></textarea>
+                            </div>
+                            <div class="col-xs-6">
+                                <textarea rows="8" cols="60" readonly placeholder="No users added" style="overflow-y: scroll; resize: none; width: 200px;" class="added_members"></textarea>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label class="col-xs-3"></label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-6">
+                                <button type="button" id="clear_admins" class="btn btn-default">Clear</button>
+                            </div>
+                            <div class="col-xs-6">
+                                <button type="button" id="clear_members" class="btn btn-default">Clear</button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group" style="padding-left: 20px;">
+                        <label for="create_group" class="col-xs-3" style="float: left; font-size: 18px;"></label>
+                        <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                            <div class="col-xs-6">
+                                <button type="submit" id="create_group" class="btn btn-primary">Create Group</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </fieldset>
+        </form>
+    </div>
+
+
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
+
+    <script type="text/javascript" charset="utf-8">
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/group_manager.html b/wqflask/wqflask/templates/admin/group_manager.html
index 23d8205a..70d55684 100644
--- a/wqflask/wqflask/templates/admin/group_manager.html
+++ b/wqflask/wqflask/templates/admin/group_manager.html
@@ -23,7 +23,7 @@
                 <br>
                 <button type="submit" name="add_new_group" class="btn btn-primary">Create a new group</button>
                 {% else %}
-                <div><h3>Admin Groups</h3></div>
+                <div style="margin-top: 20px;"><h2>Admin Groups</h2></div>
                 <hr>
                 {% if admin_groups|length == 0 %}
                 <h4>You currently aren't the administrator of any groups.</h4>
@@ -45,8 +45,8 @@
                         <tr>
                             <td><input type="checkbox" name="group_id" value="{{ group.id }}"></td>
                             <td align="right">{{ loop.index }}</td>
-                            <td>{{ group.name }}</td>
-                            <td align="right">{{ group.admins|length + group.users|length }}</td>
+                            <td><a href="/groups/view?id={{ group.id }}">{{ group.name }}</a></td>
+                            <td align="right">{{ group.admins|length + group.members|length }}</td>
                             <td>{{ group.created_timestamp }}</td>
                             <td>{{ group.changed_timestamp }}</td>
                             <td>{{ group.id }}</td>
@@ -58,7 +58,7 @@
             </div>
             <hr>
             <div style="min-width: 800px; max-width: 1000px;">
-                <div><h3>User Groups</h3></div>
+                <div><h2>User Groups</h2></div>
                 <hr>
                 {% if user_groups|length == 0 %}
                 <h4>You currently aren't a member of any groups.</h4>
@@ -80,7 +80,7 @@
                             <td><input type="checkbox" name="read" value="{{ group.id }}"></td>
                             <td>{{ loop.index }}</td>
                             <td>{{ group.name }}</td>
-                            <td>{{ group.admins|length + group.users|length }}</td>
+                            <td>{{ group.admins|length + group.members|length }}</td>
                             <td>{{ group.created_timestamp }}</td>
                             <td>{{ group.changed_timestamp }}</td>
                         </tr>
@@ -103,10 +103,14 @@
     <script type="text/javascript" charset="utf-8">
         $(document).ready( function () {
             {% if admin_groups|length != 0 %}
-            $('#admin_groups').dataTable();
+            $('#admin_groups').dataTable({
+                'sDom': 'tr'
+            });
             {% endif %}
             {% if user_groups|length != 0 %}
-            $('#user_groups').dataTable();
+            $('#user_groups').dataTable({
+                'sDom': 'tr'
+            });
             {% endif %}
             submit_special = function(url) {
                 $("#groups_form").attr("action", url);
diff --git a/wqflask/wqflask/templates/admin/manage_resource.html b/wqflask/wqflask/templates/admin/manage_resource.html
index a47f47ad..0b12eaae 100644
--- a/wqflask/wqflask/templates/admin/manage_resource.html
+++ b/wqflask/wqflask/templates/admin/manage_resource.html
@@ -1,92 +1,108 @@
-{% extends "base.html" %}

-{% block title %}Resource Manager{% endblock %}

-{% block content %}

-<!-- Start of body -->

-    <div class="container">

-        <div class="page-header">

-            <h1>Resource Manager</h1>

-        </div>

-        <form id="manage_resource" action="/resources/manage" method="POST">

-            <input type="hidden" name="resource_id" value="{{ resource_id }}">

-            <div class="col-xs-6" style="min-width: 600px; max-width: 800px;">

-                <fieldset>

-                    <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Resource Name:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                {{ resource_info.name }}

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Open to Public:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <label class="radio-inline">

-                                    <input type="radio" name="default_mask" value="True" checked="">

-                                    Yes

-                                </label>

-                                <label class="radio-inline">

-                                    <input type="radio" name="default_mask" value="False">

-                                    No

-                            </label>

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label class="col-xs-3" style="float: left; font-size: 18px;"></label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <button id="save_changes" class="btn btn-primary">Save Changes</button>

-                            </div>

-                        </div>

-                    </div>

-                </fieldset>

-            </div>

-            <div class="col-xs-6" style="min-width: 600px; max-width: 800px;">

-                <button id="add_group_to_resource" class="btn btn-primary" style="margin-bottom: 30px;" data-url="/resources/add_group">Add Group</button>

-                <br>

-                {% if group_masks|length > 0 %}

-                <h3>Current Group Permissions</h3>

-                <table>

-                    <thead>

-                        <tr>

-                            <th>Name</th>

-                            <th>Data</th>

-                            <th>Metadata</th>

-                            <th>Admin</th>

-                        </tr>

-                    </thead>

-                    <tbody>

-                        {% for key, value in group_masks.iteritems() %}

-                        <tr>

-                            <td>{{ value.name }}</td>

-                            <td>{{ value.data }}</td>

-                            <td>{{ value.metadata }}</td>

-                            <td>{{ value.admin }}</td>

-                        </tr>

-                        {% endfor %}

-                    </tbody>

-                </table>

-                {% else %}

-                <h3>No groups are currently added to this resource.</h3>

-                {% endif %}

-            </div>

-        </form>

-    </div>

-

-

-

-<!-- End of body -->

-

-{% endblock %}

-

-{% block js %}

-    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>

-

-    <script type="text/javascript" charset="utf-8">

-        $('#add_group_to_resource').click(function(){

-            url = $(this).data("url");

-            $('#manage_resource').attr("action", url)

-            $('#manage_resource').submit()

-        })

-    </script>

-{% endblock %}

+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        {{ flash_me() }}
+        <div class="page-header" style="display: inline-block;">
+            <h1>Resource Manager</h1>
+            <h3>{% if owner_name is not none %}Current Owner: {{ owner_name }}{% endif %} {% if admin_status == "owner" %}<button id="change_owner" class="btn btn-danger" data-url="/resources/change_owner" style="margin-left: 20px;">Change Owner</button>{% endif %}</h3>
+        </div>
+        <form id="manage_resource" action="/resources/manage" method="POST">
+            <input type="hidden" name="resource_id" value="{{ resource_id }}">
+            <div style="min-width: 600px; max-width: 800px;">
+                <fieldset>
+                    <div class="form-horizontal" style="width: 900px; margin-bottom: 50px;">
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Resource Name:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                {{ resource_info.name }}
+                            </div>
+                        </div>
+                        {% if admin_status == "owner" %}
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">Open to Public:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <label class="radio-inline">
+                                    <input type="radio" name="open_to_public" value="True" {% if default_mask != 'no-access' %}checked{% endif %}>
+                                    Yes
+                                </label>
+                                <label class="radio-inline">
+                                    <input type="radio" name="open_to_public" value="False" {% if default_mask == 'no-access' %}checked{% endif %}>
+                                    No
+                            </label>
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <button id="save_changes" class="btn btn-primary" data-url="/resources/change_default_privileges">Save Changes</button>
+                            </div>
+                        </div>
+                        {% endif %}
+                    </div>
+                </fieldset>
+            </div>
+            {% if admin_status == "owner" or admin_status == "edit-admins" or admin_status == "edit-access" %}
+            <div style="min-width: 600px; max-width: 800px;">
+                <hr>
+                <button id="add_group_to_resource" class="btn btn-primary" style="margin-bottom: 30px;" data-url="/resources/add_group">Add Group</button>
+                <br>
+                {% if group_masks|length > 0 %}
+                <h2>Current Group Permissions</h2>
+                <hr>
+                <table id="groups_table" class="table-hover table-striped cell-border">
+                    <thead>
+                        <tr>
+                            <th>Name</th>
+                            <th>Data</th>
+                            <th>Metadata</th>
+                            <th>Admin</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {% for key, value in group_masks.iteritems() %}
+                        <tr>
+                            <td>{{ value.name }}</td>
+                            <td>{{ value.data }}</td>
+                            <td>{{ value.metadata }}</td>
+                            <td>{{ value.admin }}</td>
+                        </tr>
+                        {% endfor %}
+                    </tbody>
+                </table>
+                {% else %}
+                <h3>No groups are currently added to this resource.</h3>
+                {% endif %}
+            </div>
+            {% endif %}
+        </form>
+    </div>
+
+
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+    <script type="text/javascript" charset="utf-8">
+        $('#add_group_to_resource, #save_changes, #change_owner').click(function(){
+            url = $(this).data("url");
+            $('#manage_resource').attr("action", url)
+            $('#manage_resource').submit()
+        })
+
+        {% if group_masks|length > 0 %}
+        $('#groups_table').dataTable({
+            'sDom': 'tr',
+        });
+        {% endif %}
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/search_for_groups.html b/wqflask/wqflask/templates/admin/search_for_groups.html
index 89eb11dd..f304a172 100644
--- a/wqflask/wqflask/templates/admin/search_for_groups.html
+++ b/wqflask/wqflask/templates/admin/search_for_groups.html
@@ -1,64 +1,134 @@
-{% extends "base.html" %}

-{% block title %}Resource Manager{% endblock %}

-{% block content %}

-<!-- Start of body -->

-    <div class="container">

-        <div class="page-header">

-            <h1>Find Groups</h1>

-        </div>

-        <form id="find_groups" action="/resources/add_group" method="POST">

-            <input type="hidden" name="resource_id" value="{{ resource_id }}">

-            <div style="min-width: 600px; max-width: 800px;">

-                <fieldset>

-                    <div class="form-horizontal" style="width: 900px;">

-                        <div style="margin-bottom: 30px;">

-                            <h2>Search by:</h2>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group ID:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <input name="group_id" type="text" value="">

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <input name="group_name" type="text" value="">

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User Name:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <input name="user_name" type="text" value="">

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User E-mail:</label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <input name="user_email" type="text" value="">

-                            </div>

-                        </div>

-                        <div class="form-group" style="padding-left: 20px;">

-                            <label class="col-xs-3" style="float: left; font-size: 18px;"></label>

-                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">

-                                <button type="submit" id="find_groups" class="btn btn-primary">Search</button>

-                            </div>

-                        </div>

-                    </div>

-                </fieldset>

-            </div>

-        </form>

-    </div>

-

-<!-- End of body -->

-

-{% endblock %}

-

-{% block js %}

-    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>

-    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>

-

-    <script type="text/javascript" charset="utf-8">

-    </script>

-{% endblock %}

+{% extends "base.html" %}
+{% block title %}Resource Manager{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        <div class="page-header">
+            <h1>Find Groups</h1>
+        </div>
+        <form id="add_group" action="/resources/add_group" method="POST">
+            <input type="hidden" name="resource_id" value="{{ resource_id }}">
+            <div style="min-width: 600px; max-width: 800px;">
+                <fieldset>
+                    <div class="form-horizontal" style="width: 900px;">
+                        <div style="margin-bottom: 30px;">
+                            <h2>Search by:</h2>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group ID:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="group_id" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="group_name" class="col-xs-3" style="float: left; font-size: 18px;">Group Name:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="group_name" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="user_name" class="col-xs-3" style="float: left; font-size: 18px;">User Name:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="user_name" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label for="user_email" class="col-xs-3" style="float: left; font-size: 18px;">User E-mail:</label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <input name="user_email" type="text" value="">
+                            </div>
+                        </div>
+                        <div class="form-group" style="padding-left: 20px;">
+                            <label class="col-xs-3" style="float: left; font-size: 18px;"></label>
+                            <div class="controls input-append col-xs-9" style="display: flex; padding-left: 20px; float: left;">
+                                <button type="button" id="find_groups" class="btn btn-primary">Search</button>
+                                <button style="margin-left: 20px; display: none;" type="submit" id="submit_group" class="btn btn-success">Add Privileges for Selected Group</button>
+                            </div>
+                        </div>
+                    </div>
+                </fieldset>
+                <hr>
+                <div id="group_results">
+                </div>
+            </div>
+        </form>
+    </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/javascript/group_manager.js"></script>
+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+    <script type="text/javascript" charset="utf-8">
+
+        $('#find_groups').click(function() {
+            $.ajax({
+                method: "POST",
+                url: "/search_for_groups",
+                data: {
+                    group_id: $('input[name=group_id]').val(),
+                    group_name: $('input[name=group_name]').val(),
+                    user_name: $('input[name=user_name]').val(),
+                    user_email: $('input[name=user_email]').val()
+                },
+                success: populate_groups
+            });
+        })
+
+        populate_groups = function(json_group_list){
+            console.log(json_group_list)
+            var group_list = JSON.parse(json_group_list)
+
+            var the_html = ""
+            if (group_list.length > 0){
+                the_html += "<table id='groups_table' style='padding-top: 10px; width: 100%;' class='table-hover table-striped cell-border'>";
+                the_html += "<thead><tr><th></th><th>Index</th><th>Name</th><th># Admins</th><th># Members</th></tr></thead>";
+                the_html += "<tbody>";
+                for (_i = 0, _len = group_list.length; _i < _len; _i++) {
+                    this_group = group_list[_i]
+                    the_html += "<tr>";
+                    the_html += "<td align='center' class='select_group'><input type='radio' name='selected_group' value='" + this_group.id + "'></td>";
+                    the_html += "<td>" + (_i + 1).toString() + "</td>"
+                    if ("name" in this_group) {
+                        the_html += "<td>" + this_group.name + "</td>";
+                    } else {
+                        the_html += "<td>N/A</td>"
+                    }
+                    if ("admins" in this_group) {
+                        the_html += "<td>" + this_group.admins.length + "</td>";
+                    } else {
+                        the_html += "<td>0</td>"
+                    }
+                    if ("members" in this_group) {
+                        the_html += "<td>" + this_group.members.length + "</td>";
+                    } else {
+                        the_html += "<td>0</td>"
+                    }
+                    the_html += "</tr>"
+                }
+                the_html += "</tbody>";
+                the_html += "</table>";
+            } else {
+                the_html = "<span>No groups were found matching the entered criteria.</span>"
+            }
+
+            $('#group_results').html(the_html)
+            if (group_list.length > 0){
+                $('#groups_table').dataTable({
+                    'order': [[1, "asc" ]],
+                    'sDom': 'tr'
+                });
+                $('input[name=selected_group]:eq(0)').prop("checked", true)
+                $('#submit_group').css("display", "inline-block")
+            }
+        }
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/select_group_to_add.html b/wqflask/wqflask/templates/admin/select_group_to_add.html
deleted file mode 100644
index df70fb2f..00000000
--- a/wqflask/wqflask/templates/admin/select_group_to_add.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% extends "base.html" %}

-{% block title %}Matched Groups{% endblock %}

-{% block css %}

-    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />

-    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">

-    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />

-{% endblock %}

-{% block content %}

-<!-- Start of body -->

-    <div class="container">

-        <h1>The following groups were found:</h1>

-        <br>

-        <form id="add_groups">

-            <input type="hidden" name="resource_id" value="{{ resource_id }}">

-            <div id="groups_list" style="min-width: 600px; max-width: 800px;">

-                {% if group_list|length > 0 %}

-                <button type="submit" class="btn btn-primary" style="margin-bottom: 40px;">Add Selected Group</button>

-                <table id="groups_table" class="table-hover table-striped cell-border" style="float: left;">

-                    <thead>

-                        <tr>

-                            <th></th>

-                            <th>Name</th>

-                            <th>Created</th>

-                            <th>Last Changed</th>

-                        </tr>

-                    </thead>

-                    <tbody>

-                    {% for group in group_list %}

-                        <tr>

-                            <td align="center" style="padding: 0px;"><input type="radio" name="selected_group" VALUE="{{ group.id }}"></td>

-                            <td>{% if 'name' in group %}{{ group.name }}{% else %}N/A{% endif %}</td>

-                            <td>{% if 'created_timestamp' in group %}{{ group.created_timestamp }}{% else %}N/A{% endif %}</td>

-                            <td>{% if 'changed_timestamp' in group %}{{ group.changed_timestamp }}{% else %}N/A{% endif %}</td>

-                        </tr>

-                    {% endfor %}

-                    </tbody>

-                </table>

-                {% else %}

-                <h2>No matching groups were found.</h2>

-                {% endif %}

-            </div>

-        </form>

-    </div>

-

-<!-- End of body -->

-

-{% endblock %}

-

-{% block js %}

-    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>

-    <script>

-        $('#groups_table').dataTable();

-    </script>

-{% endblock %}

diff --git a/wqflask/wqflask/templates/admin/set_group_privileges.html b/wqflask/wqflask/templates/admin/set_group_privileges.html
new file mode 100644
index 00000000..bc52788f
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/set_group_privileges.html
@@ -0,0 +1,102 @@
+{% extends "base.html" %}
+{% block title %}Set Group Privileges{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        <h1>Group Privileges</h1>
+        <br>
+        <form id="set_group_privileges" action="/resources/add_group" method="POST">
+            <input type="hidden" name="resource_id" value="{{ resource_id }}">
+            <input type="hidden" name="group_id" value="{{ group_id }}">
+            <div style="min-width: 600px; max-width: 800px;">
+                <button type="submit" class="btn btn-primary" style="margin-bottom: 10px;">Add Group</button>
+                <hr>
+                <h2>Data and Metadata Privileges</h2>
+                <table id="data_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+                    <thead>
+                        <tr>
+                            <th></th>
+                            <th>No-Access</th>
+                            <th>View</th>
+                            <th>Edit</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <tr>
+                            <td>Data:</td>
+                            {% if 'data' in default_privileges %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" {% if default_privileges.data == "no-access" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view" {% if default_privileges.data == "view" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit" {% if default_privileges.data == "edit" %}checked{% endif %}></td>
+                            {% else %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" checked></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view"></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit"></td>
+                            {% endif %}
+                        </tr>
+                        <tr>
+                            <td>Metadata:</td>
+                            {% if 'metadata' in default_privileges %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" {% if default_privileges.metadata == "no-access" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view" {% if default_privileges.metadata == "view" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit" {% if default_privileges.metadata[-1] == "edit" %}checked{% endif %}></td>
+                            {% else %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" checked></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view"></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit"></td>
+                            {% endif %}
+                        </tr>
+                    </tbody>
+                </table>
+                <hr>
+                <h2>Admin Privileges</h2>
+                <table id="admin_privileges_table" class="table-hover table-striped cell-border" style="float: left;">
+                    <thead>
+                        <tr>
+                            <th></th>
+                            <th>Not Admin</th>
+                            <th>Edit Access</th>
+                            <th>Edit Admins</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <tr>
+                            <td>Admin:</td>
+                            {% if 'admin' in default_privileges %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" {% if default_privileges.admin == "not-admin" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access" {% if default_privileges.admin == "edit-access" %}checked{% endif %}></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins" {% if default_privileges.admin == "edit-admins" %}checked{% endif %}></td>
+                            {% else %}
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" checked></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access"></td>
+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins"></td>
+                            {% endif %}
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </form>
+    </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+    <script>
+        $('#data_privileges_table').dataTable({
+            'sDom': 'tr',
+            'bSort': false
+        });
+        $('#admin_privileges_table').dataTable({
+            'sDom': 'tr',
+            'bSort': false
+        });
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/admin/view_group.html b/wqflask/wqflask/templates/admin/view_group.html
new file mode 100644
index 00000000..b797cd70
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/view_group.html
@@ -0,0 +1,238 @@
+{% extends "base.html" %}
+{% block title %}View and Edit Group{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
+    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">
+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+{% endblock %}
+{% block content %}
+<!-- Start of body -->
+    <div class="container">
+        <div class="page-header">
+            <h1>
+                <span id="group_name">{{ group_info.name }}</span>
+                <input type="text" name="new_group_name" style="font-size: 20px; display: none; width: 500px;" class="form-control" placeholder="{{ group_info.name }}"> 
+                <button class="btn btn-default" style="display: inline;" id="change_group_name">Change Group Name</button>
+            </h1>
+            {% if user_is_admin == true %}
+            <div style="display: inline;">
+                <button type="button" id="remove_users" class="btn btn-danger" data-url="/groups/remove_users">Remove Selected Users from Group</button>
+            </div>
+            {% endif %}
+        </div>
+        <form id="group_form" action="/groups/view" method="POST">
+            <input type="hidden" name="group_id" value="{{ group_info.id }}">
+            <input type="hidden" name="selected_admin_ids" value="">
+            <input type="hidden" name="selected_member_ids" value="">
+            <div class="row">
+            <div id="groups_div" class="col-xs-6" style="margin-right: 30px; min-width: 600px; max-width: 800px;">
+                <div>
+                    <div style="margin-top: 20px;"><h2>Admins</h2></div>
+                    <hr>
+                    <table id="group_admins" class="table-hover table-striped cell-border" style="float: left;">
+                        <thead>
+                            <tr>
+                                <th></th>
+                                <th>Index</th>
+                                <th>Name</th>
+                                <th>Email Address</th>
+                                <th>Organization</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            {% for admin in admins %}
+                            <tr>
+                                <td style="text-align: center; padding: 0px 10px 2px 10px;"><input type="checkbox" name="admin_id" value="{{ admin.user_id }}"></td>
+                                <td align="right">{{ loop.index }}</td>
+                                <td>{% if 'full_name' in admin %}{{ admin.full_name }}{% else %}N/A{% endif %}</td>
+                                <td>{% if 'email_address' in admin %}{{ admin.email_address }}{% else %}N/A{% endif %}</td>
+                                <td>{% if 'organization' in admin %}{{ admin.organization }}{% else %}N/A{% endif %}</td>
+                            </tr>
+                            {% endfor %}
+                        </tbody>
+                    </table>
+                    {% if user_is_admin == true %}
+                    <div style="margin-top: 20px;">
+                            <span>E-mail of user to add to admins (multiple e-mails can be added separated by commas):</span>
+                            <input type="text" size="60" name="admin_emails_to_add" placeholder="Enter E-mail(s)" value="">
+                    </div>
+                    <div style="margin-bottom: 30px; margin-top: 20px;">
+                        <button type="button" id="add_admins" class="btn btn-primary" data-usertype="admin" data-url="/groups/add_admins">Add Admin(s)</button>
+                    </div>
+                    {% endif %}
+                </div>
+                <hr>
+                <div>
+                    {% if members|length > 0 %}
+                    <div><h2>Members</h2></div>
+                    <hr>
+                    <table id="group_members" class="table-hover table-striped cell-border" style="float: left;">
+                        <thead>
+                            <tr>
+                                <th></th>
+                                <th>Index</th>
+                                <th>Name</th>
+                                <th>Email Address</th>
+                                <th>Organization</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            {% for member in members %}
+                            <tr>
+                                <td style="text-align: center; padding: 0px 10px 2px 10px;"><input type="checkbox" name="member_id" value="{{ member.user_id }}"></td>
+                                <td align="right">{{ loop.index }}</td>
+                                <td>{% if 'full_name' in member %}{{ member.full_name }}{% else %}N/A{% endif %}</td>
+                                <td>{% if 'email_address' in member %}{{ member.email_address }}{% else %}N/A{% endif %}</td>
+                                <td>{% if 'organization' in member %}{{ member.organization }}{% else %}N/A{% endif %}</td>
+                            </tr>
+                            {% endfor %}
+                        </tbody>
+                    </table>
+                    {% if user_is_admin == true %}
+                    <div style="margin-top: 20px;">
+                            <span>E-mail of user to add to members (multiple e-mails can be added separated by commas):</span>
+                            <input type="text" size="60" name="member_emails_to_add" placeholder="Enter E-mail(s)" value="">
+                    </div>
+                    <div style="margin-bottom: 30px; margin-top: 20px;">
+                        <button type="button" id="add_members" class="btn btn-primary" data-usertype="member" data-url="/groups/add_members">Add Member(s)</button>
+                    </div>
+                    {% endif %}
+                    {% else %}
+                    There are currently no members in this group.
+                    {% endif %}
+                </div>
+            </div>
+            <div id="resources_div" class="col-xs-6" style="border-left: 1px solid #eee; margin-right: 30px; min-width: 600px; max-width: 800px;">
+                <div style="margin-top: 20px;"><h2>Resources</h2></div>
+                <hr>
+                {% if resources|length > 0 %}
+                <table id="resources" class="table-hover table-striped cell-border" style="float: left;">
+                    <thead>
+                        <tr>
+                            <th>Index</th>
+                            <th>Name</th>
+                            <th>Data</th>
+                            <th>Metadata</th>
+                            <th>Admin</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {% for resource in resources %}
+                        <tr>
+                            <td align="right">{{ loop.index }}</td>
+                            <td>{% if 'name' in resource %}<a href="/resources/manage?resource_id={{ resource.id }}">{{ resource.name }}</a>{% else %}N/A{% endif %}</td>
+                            <td>{% if 'data' in resource %}{{ resource.data }}{% else %}N/A{% endif %}</td>
+                            <td>{% if 'metadata' in resource %}{{ resource.metadata }}{% else %}N/A{% endif %}</td>
+                            <td>{% if 'admin' in resource %}{{ resource.admin }}{% else %}N/A{% endif %}</td>
+                        </tr>
+                        {% endfor %}
+                    </tbody>
+                </table>
+                {% else %}
+                There are currently no resources associated with this group.
+                {% endif %}
+            </div>
+            </div>
+        </form>
+    </div>
+
+<!-- End of body -->
+
+{% endblock %}
+
+{% block js %}
+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+
+    <script type="text/javascript" charset="utf-8">
+        $(document).ready( function () {
+            $('#group_admins').dataTable({
+                'order': [[1, "asc" ]],
+                'columns': [
+                    { "type": "natural", "width": "25px"},
+                    { "type": "natural", "width": "30px" },
+                    { "type": "natural", "width": "150px" },
+                    { "type": "natural" },
+                    { "type": "natural" }
+                ],
+                'sDom': 'tr'
+            });
+            {% if members|length > 0 %}
+            $('#group_members').dataTable({
+                'order': [[1, "asc" ]],
+                'columns': [
+                    { "type": "natural", "width": "25px"},
+                    { "type": "natural", "width": "30px" },
+                    { "type": "natural", "width": "150px" },
+                    { "type": "natural" },
+                    { "type": "natural" }
+                ],
+                'sDom': 'tr'
+            });
+            {% endif %}
+            {% if resources|length > 0 %}
+            $('#resources').dataTable({
+                'order': [[0, "asc" ]],
+                'columns': [
+                    { "type": "natural", "width": "30px" },
+                    { "type": "natural", "width": "150px" },
+                    { "type": "natural" },
+                    { "type": "natural" },
+                    { "type": "natural" }
+                ],
+                'sDom': 'tr'
+            });
+            {% endif %}
+
+            $('#resources_div').css('height', $('#groups_div').css('height'))
+
+            submit_special = function(url) {
+                $("#group_form").attr("action", url);
+                return $("#group_form").submit();
+            };
+
+            $("#remove_users").on("click", function() {
+                url = $(this).data("url");
+                admins = [];
+                $("input[name=admin_id]:checked").each(function() {
+                    admins.push($(this).val());
+                });
+                admins_string = admins.join(":")
+                $("input[name=selected_admin_ids]").val(admins_string)
+
+                members = [];
+                $("input[name=member_id]:checked").each(function() {
+                    members.push($(this).val());
+                });
+                members_string = members.join(":")
+                $("input[name=selected_member_ids]").val(members_string)
+                return submit_special(url)
+            });
+
+            $("#add_admins, #add_members").on("click", function() {
+                url = $(this).data("url");
+                return submit_special(url)
+            });
+
+            $("#change_group_name").on("click", function() {
+                if ($('input[name=new_group_name]').css('display') == 'none') {
+                    $('input[name=new_group_name]').css('display', 'inline');
+                    $('#group_name').css('display', 'none');
+                } else {
+                    new_name = $('input[name=new_group_name]').val()
+                    $.ajax({
+                        type: "POST",
+                        url: "/groups/change_name",
+                        data: {
+                            group_id: $('input[name=group_id]').val(),
+                            new_name: new_name
+                        }
+                    });
+                    $('input[name=new_group_name]').css('display', 'none');
+                    $('input[name=group_name]').val(new_name);
+                    $('#group_name').text(new_name)
+                    $('#group_name').css('display', 'inline');
+                }
+            });
+        });
+    </script>
+{% endblock %}
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 07c1b48e..262d9ee5 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -94,6 +94,11 @@
                             <a id="login_in" href="/n/login">Sign in</a>
                             {% endif %}
                         </li>
+                        {% if g.user_session.logged_in %}
+                        <li class="">
+                            <a id="manage_groups" title="Manage Groups" href="/groups/manage">Manage Groups</a>
+                        </li>
+                        {% endif %}
                         {% endif %}
                         <!--
                         <li style="margin-left: 20px;">
diff --git a/wqflask/wqflask/templates/set_group_privileges.html b/wqflask/wqflask/templates/set_group_privileges.html
new file mode 100644
index 00000000..98b0cc12
--- /dev/null
+++ b/wqflask/wqflask/templates/set_group_privileges.html
@@ -0,0 +1,77 @@
+{% extends "base.html" %}

+{% block title %}Set Group Privileges{% endblock %}

+{% block css %}

+    <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />

+    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.dataTables.css">

+    <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />

+{% endblock %}

+{% block content %}

+<!-- Start of body -->

+    <div class="container">

+        <h1>Group Privileges</h1>

+        <br>

+        <form id="set_group_privileges">

+            <input type="hidden" name="resource_id" value="{{ resource_id }}">

+            <div style="min-width: 600px; max-width: 800px;">

+                <button type="submit" class="btn btn-primary" style="margin-bottom: 40px;">Add Group</button>

+                <hr>

+                <h2>Data and Metadata Privileges</h2>

+                <table id="data_privileges_table" class="table-hover table-striped cell-border" style="float: left;">

+                    <thead>

+                        <tr>

+                            <th></th>

+                            <th>No-Access</th>

+                            <th>View</th>

+                            <th>Edit</th>

+                        </tr>

+                    </thead>

+                    <tbody>

+                        <tr>

+                            <td>Data:</td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="no-access" checked></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="view"></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="data_privilege" VALUE="edit"></td>

+                        </tr>

+                        <tr>

+                            <td>Metadata:</td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="no-access" checked></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="view"></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="metadata_privilege" VALUE="edit"></td>

+                        </tr>

+                    </tbody>

+                </table>

+                <hr>

+                <h2>Admin Privileges</h2>

+                <table id="admin_privileges_table" class="table-hover table-striped cell-border" style="float: left;">

+                    <thead>

+                        <tr>

+                            <th></th>

+                            <th>Not Admin</th>

+                            <th>Edit Access</th>

+                            <th>Edit Admins</th>

+                        </tr>

+                    </thead>

+                    <tbody>

+                        <tr>

+                            <td>Admin:</td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="not-admin" checked></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-access"></td>

+                            <td align="center" style="padding: 0px;"><input type="radio" name="admin_privilege" VALUE="edit-admins"></td>

+                        </tr>

+                    </tbody>

+                </table>

+            </div>

+        </form>

+    </div>

+

+<!-- End of body -->

+

+{% endblock %}

+

+{% block js %}

+    <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>

+    <script>

+        $('#data_privileges_table').dataTable();

+        $('#admin_privileges_table').dataTable();

+    </script>

+{% endblock %}

diff --git a/wqflask/wqflask/templates/show_trait_details.html b/wqflask/wqflask/templates/show_trait_details.html
index 5c315878..5e0bae79 100644
--- a/wqflask/wqflask/templates/show_trait_details.html
+++ b/wqflask/wqflask/templates/show_trait_details.html
@@ -248,8 +248,8 @@
         <a target="_blank" href="http://gn1.genenetwork.org/webqtl/main.py?cmd=show&db={{ this_trait.dataset.name }}&probeset={{ this_trait.name }}">
         <button type="button" id="view_in_gn1" class="btn btn-primary" title="View Trait in GN1">View in GN1</button>
         </a>
-        {% if resource_id %}
-        <a target="_blank" href="./resources/manage?resource_id={{ resource_id }}">
+        {% if admin_status[1] == "owner" or admin_status[1] == "edit-admins" or admin_status[1] == "edit-access" %}
+        <a target="_blank" href="./resources/manage?resource_id={{ admin_status[0] }}">
             <button type="button" id="edit_resource" class="btn btn-success" title="Edit Resource">Edit</button>
         </a>
         {% endif %}
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index ee827ba3..dc431aa9 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -102,7 +102,7 @@ def check_access_permissions():
             else:
                 available = check_resource_availability(dataset)
 
-            if not available:
+            if available == "no-access":
                 return redirect(url_for("no_access_page"))
 
 @app.teardown_appcontext