diff options
author | zsloan | 2018-06-08 18:32:30 +0000 |
---|---|---|
committer | zsloan | 2018-06-08 18:32:30 +0000 |
commit | 59273293d3815066301a5fba0a096016a4d8ba44 (patch) | |
tree | c24b6617eb2db8776bdac3a10376e8e608bee51b | |
parent | 9bb60bb18ae5ac70fe480095554796b7c18f1b6c (diff) | |
download | genenetwork2-59273293d3815066301a5fba0a096016a4d8ba44.tar.gz |
User collections (now stored in ElasticSearch) are reimplemented now and should have their full functionality back (adding/removing collections, adding/removing traits, etc)
-rw-r--r-- | wqflask/wqflask/collect.py | 109 | ||||
-rw-r--r-- | wqflask/wqflask/templates/base.html | 6 | ||||
-rw-r--r-- | wqflask/wqflask/templates/collections/list.html | 15 | ||||
-rw-r--r-- | wqflask/wqflask/templates/show_trait_mapping_tools.html | 2 | ||||
-rw-r--r-- | wqflask/wqflask/templates/show_trait_statistics.html | 6 | ||||
-rw-r--r-- | wqflask/wqflask/user_manager.py | 319 |
6 files changed, 284 insertions, 173 deletions
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py index 2bd4b721..e1aceac8 100644 --- a/wqflask/wqflask/collect.py +++ b/wqflask/wqflask/collect.py @@ -88,7 +88,6 @@ class AnonCollection(object): def add_traits(self, params): #assert collection_name == "Default", "Unexpected collection name for anonymous user" self.traits = list(process_traits(params['traits'])) - #len_before = len(Redis.smembers(self.key)) existing_collections = Redis.get(self.key) logger.debug("existing_collections:", existing_collections) if existing_collections != None and existing_collections != "None": @@ -138,54 +137,12 @@ class AnonCollection(object): collections_list[collection_position]['num_members'] = len(collections_list[collection_position]['members']) collections_list[collection_position]['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p') len_now = collections_list[collection_position]['num_members'] - #print("before in redis:", json.loads(Redis.get(self.key))) Redis.set(self.key, json.dumps(collections_list)) - #print("currently in redis:", json.loads(Redis.get(self.key))) # We need to return something so we'll return this...maybe in the future # we can use it to check the results return str(len_now) - -class UserCollection(object): - """User is logged in""" - - def add_traits(self, params, collection_name): - logger.debug("---> params are:", params.keys()) - logger.debug(" type(params):", type(params)) - if collection_name=="Default": - uc = g.user_session.user_ob.get_collection_by_name("Default") - # Doesn't exist so we'll create it - if not uc: - return create_new("Default") - else: - uc = model.UserCollection.query.get(params['existing_collection'].split(":")[0]) - members = list(uc.members_as_set()) #set(json.loads(uc.members)) - len_before = len(members) - - traits = process_traits(params['traits']) - - members_now = members - for trait in traits: - if trait in members: - continue - else: - members_now.append(trait) - - #members_now = list(members | traits) - len_now = len(members_now) - uc.members = json.dumps(members_now) - - uc.changed_timestamp = datetime.datetime.utcnow() - - db_session.commit() - - logger.debug("added to existing, now set is:" + str(uc.members)) - report_change(len_before, len_now) - - # Probably have to change that - return redirect(url_for('view_collection', uc_id=uc.id)) - def process_traits(unprocessed_traits): #print("unprocessed_traits are:", unprocessed_traits) if isinstance(unprocessed_traits, basestring): @@ -216,9 +173,8 @@ def collections_add(): traits=request.args['traits'] if g.user_session.logged_in: - logger.debug("user_session",g.user_session) - user_collections = g.user_session.user_ob.user_collections - logger.debug("user_collections are:", user_collections) + user_collections = g.user_session.user_collections + #logger.debug("user_collections are:", user_collections) return render_template("collections/add.html", traits = traits, collections = user_collections, @@ -262,14 +218,9 @@ def create_new(collection_name): traits = process_traits(unprocessed_traits) if g.user_session.logged_in: - uc = model.UserCollection() - uc.name = collection_name - logger.debug("user_session:", g.user_session.__dict__) - uc.user = g.user_session.user_id - uc.members = json.dumps(list(traits)) - db_session.add(uc) - db_session.commit() - return redirect(url_for('view_collection', uc_id=uc.id)) + uc_id = g.user_session.add_collection(collection_name, traits) + + return redirect(url_for('view_collection', uc_id=uc_id)) else: ac = AnonCollection(collection_name) ac.changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p') @@ -279,17 +230,17 @@ def create_new(collection_name): @app.route("/collections/list") def list_collections(): params = request.args - logger.debug("PARAMS:", params) + #logger.debug("PARAMS:", params) if g.user_session.logged_in: - user_collections = list(g.user_session.user_ob.user_collections) - logger.debug("user_collections are:", user_collections) + user_collections = list(g.user_session.user_collections) + #logger.debug("user_collections are:", user_collections) return render_template("collections/list.html", params = params, collections = user_collections, ) else: anon_collections = user_manager.AnonUser().get_collections() - logger.debug("anon_collections are:", anon_collections) + #logger.debug("anon_collections are:", anon_collections) return render_template("collections/list.html", params = params, collections = anon_collections) @@ -298,20 +249,14 @@ def list_collections(): @app.route("/collections/remove", methods=('POST',)) def remove_traits(): params = request.form - logger.debug("params are:", params) if "uc_id" in params: uc_id = params['uc_id'] - uc = model.UserCollection.query.get(uc_id) traits_to_remove = params.getlist('traits[]') traits_to_remove = process_traits(traits_to_remove) logger.debug("\n\n after processing, traits_to_remove:", traits_to_remove) - all_traits = uc.members_as_set() - members_now = all_traits - traits_to_remove - logger.debug(" members_now:", members_now) - uc.members = json.dumps(list(members_now)) - uc.changed_timestamp = datetime.datetime.utcnow() - db_session.commit() + + members_now = g.user_session.remove_traits_from_collection(uc_id, traits_to_remove) else: collection_name = params['collection_name'] members_now = AnonCollection(collection_name).remove_traits(params) @@ -325,22 +270,13 @@ def remove_traits(): @app.route("/collections/delete", methods=('POST',)) def delete_collection(): params = request.form - logger.debug("params:", params) if g.user_session.logged_in: uc_id = params['uc_id'] if len(uc_id.split(":")) > 1: for this_uc_id in uc_id.split(":"): - uc = model.UserCollection.query.get(this_uc_id) - collection_name = uc.name - db_session.delete(uc) - db_session.commit() + collection_name = g.user_session.delete_collection(this_uc_id) else: - uc = model.UserCollection.query.get(uc_id) - # Todo: For now having the id is good enough since it's so unique - # But might want to check ownership in the future - collection_name = uc.name - db_session.delete(uc) - db_session.commit() + collection_name = g.user_session.delete_collection(uc_id) else: if "collection_name" in params: collection_name = params['collection_name'] @@ -348,7 +284,10 @@ def delete_collection(): for this_collection in params['uc_id'].split(":"): user_manager.AnonUser().delete_collection(this_collection) - flash("We've deleted the collection: {}.".format(collection_name), "alert-info") + if len(uc_id.split(":")) > 1: + flash("We've deleted the selected collections.", "alert-info") + else: + flash("We've deleted the collection: {}.".format(collection_name), "alert-info") return redirect(url_for('list_collections')) @@ -356,12 +295,11 @@ def delete_collection(): @app.route("/collections/view") def view_collection(): params = request.args - logger.debug("PARAMS in view collection:", params) - if "uc_id" in params: + if g.user_session.logged_in and "uc_id" in params: uc_id = params['uc_id'] - uc = model.UserCollection.query.get(uc_id) - traits = json.loads(uc.members) + uc = (collection for collection in g.user_session.user_collections if collection["id"] == uc_id).next() + traits = uc["members"] else: user_collections = json.loads(Redis.get(user_manager.AnonUser().key)) this_collection = {} @@ -369,10 +307,8 @@ def view_collection(): if collection['id'] == params['collection_id']: this_collection = collection break - #this_collection = user_collections[params['collection_id']] - traits = this_collection['members'] - logger.debug("in view_collection traits are:", traits) + traits = this_collection['members'] trait_obs = [] json_version = [] @@ -398,9 +334,8 @@ def view_collection(): collection_info = dict(trait_obs=trait_obs, collection_name=this_collection['name']) if "json" in params: - logger.debug("json_version:", json_version) return json.dumps(json_version) else: return render_template("collections/view.html", **collection_info - ) + )
\ No newline at end of file diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html index e8b51523..3df4c81a 100644 --- a/wqflask/wqflask/templates/base.html +++ b/wqflask/wqflask/templates/base.html @@ -44,8 +44,8 @@ </li> <li class=""> <a href="/collections/list">Collections - {% if g.user_session.user_ob %} - <span class="badge badge-info">{{ g.user_session.user_ob.display_num_collections() }}</span> + {% if g.user_session.logged_in %} + <span class="badge badge-info">{{ g.user_session.num_collections }}</span> {% else %} <span class="badge badge-info">{{ g.cookie_session.display_num_collections() }}</span> {% endif %} @@ -71,7 +71,7 @@ </li> <li class=""> {% if g.user_session.logged_in %} - <a id="login_out" title="Signed in as {{ g.user_session.user_ob.name_and_org }}." href="/n/logout">Sign out</a> + <a id="login_out" title="Signed in as {{ g.user_session.user_name }}" href="/n/logout">Sign out</a> {% else %} <a id="login_in" href="/n/login">Sign in</a> {% endif %} diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index e7f3229b..11c33673 100644 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -8,7 +8,7 @@ {% endblock %} {% block content %} <!-- Start of body --> - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} {{ header("Your Collections", 'You have {}.'.format(numify(collections|count, "collection", "collections"))) }} {% else %} @@ -19,8 +19,8 @@ <div class="container"> <div class="page-header"> - {% if g.user_session.user_ob %} - <h1>Collections owned by {{ g.user_session.user_ob.full_name }}</h1> + {% if g.user_session.logged_in %} + <h1>Collections owned by {{ g.user_session.user_name }}</h1> {% else %} <h1>Your Collections</h1> {% endif %} @@ -51,19 +51,24 @@ <tbody> {% for uc in collections %} <tr class="collection_line"> - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} <td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.id }}"></td> {% else %} <td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.name }}"></td> {% endif %} <td align="right">{{ loop.index }} - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} <td><a class="collection_name" href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td> {% else %} <td><a class="collection_name" href="{{ url_for('view_collection', collection_id=uc.id) }}">{{ uc.name }}</a></td> {% endif %} + {% if g.user_session.logged_in %} + <td>{{ uc.created_timestamp }}</td> + <td>{{ uc.changed_timestamp }}</td> + {% else %} <td>{{ timeago(uc.created_timestamp.isoformat() + "Z") }}</td> <td>{{ timeago(uc.changed_timestamp.isoformat() + "Z") }}</td> + {% endif %} <td align="right">{{ uc.num_members }}</td> </tr> {% endfor %} diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index 3d31797a..9c19028c 100644 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -71,7 +71,7 @@ <div class="mapping_method_fields form-group"> <label style="text-align: right;" class="col-xs-3 control-label">Covariates</label> <div style="margin-left:20px;" class="col-xs-7"> - {% if g.user_session.user_ob and (g.user_session.user_ob.display_num_collections() == "") %} + {% if g.user_session.logged_in and (g.user_session.num_collections > 0) %} No collections available. Please add traits to a collection to use them as covariates. {% elif g.cookie_session.display_num_collections() == "" %} No collections available. Please add traits to a collection to use them as covariates. diff --git a/wqflask/wqflask/templates/show_trait_statistics.html b/wqflask/wqflask/templates/show_trait_statistics.html index 09df3245..988c8047 100644 --- a/wqflask/wqflask/templates/show_trait_statistics.html +++ b/wqflask/wqflask/templates/show_trait_statistics.html @@ -13,7 +13,7 @@ <li> <a href="#probability_plot" data-toggle="tab">Probability Plot</a> </li> - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} <li> <a href="#scatterplot_matrix" data-toggle="tab">Scatterplot Matrix</a> </li> @@ -72,7 +72,7 @@ <i class="icon-signal"></i> Sort By Value </button> </div> - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} <div class="btn-group"> <button type="button" class="btn btn-default" id="color_by_trait"> <i class="icon-tint"></i> Color by Trait @@ -126,7 +126,7 @@ <div id="box_plot"></div> </div> </div> - {% if g.user_session.user_ob %} + {% if g.user_session.logged_in %} <div class="tab-pane" id="scatterplot_matrix"> <div style="margin-bottom:40px;" class="btn-group"> diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py index 132bae90..3772414c 100644 --- a/wqflask/wqflask/user_manager.py +++ b/wqflask/wqflask/user_manager.py @@ -54,11 +54,11 @@ class AnonUser(object): def __init__(self): self.cookie = request.cookies.get(self.cookie_name) if self.cookie: - logger.debug("already is cookie") + logger.debug("ANON COOKIE ALREADY EXISTS") self.anon_id = verify_cookie(self.cookie) else: - logger.debug("creating new cookie") + logger.debug("CREATING NEW ANON COOKIE") self.anon_id, self.cookie = create_signed_cookie() self.key = "anon_collection:v1:{}".format(self.anon_id) @@ -117,16 +117,11 @@ class AnonUser(object): result = Redis.get(self.key) collections_list = json.loads(result if result else "[]") for collection in collections_list: - uc = model.UserCollection() - uc.name = collection['name'] - collection_exists = g.user_session.user_ob.get_collection_by_name(uc.name) + collection_exists = g.user_session.get_collection_by_name(collection['name']) if collection_exists: continue else: - uc.user = g.user_session.user_id - uc.members = json.dumps(collection['members']) - db_session.add(uc) - db_session.commit() + g.user_session.add_collection(collection['name'], collection['members']) def display_num_collections(self): """ @@ -164,11 +159,12 @@ def create_signed_cookie(): class UserSession(object): """Logged in user handling""" - cookie_name = 'session_id_v2' + cookie_name = 'session_id_v1' def __init__(self): cookie = request.cookies.get(self.cookie_name) if not cookie: + logger.debug("NO USER COOKIE") self.logged_in = False return else: @@ -179,7 +175,6 @@ class UserSession(object): self.session_id = session_id self.record = Redis.hgetall(self.redis_key) - if not self.record: # This will occur, for example, when the browser has been left open over a long # weekend and the site hasn't been visited by the user @@ -211,21 +206,190 @@ class UserSession(object): return '' @property - def user_ob(self): - """Actual sqlalchemy record""" - # Only look it up once if needed, then store it - # raise "OBSOLETE: use ElasticSearch instead" - try: - if LOG_SQL_ALCHEMY: - logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG) + def es_user_id(self): + """User id from ElasticSearch (need to check if this is the same as the id stored in self.records)""" + + es = get_elasticsearch_connection() + user_email = self.record['user_email_address'] + + #ZS: Get user's collections if they exist + response = es.search( + index = "users", doc_type = "local", body = { + "query": { "match": { "email_address": user_email } } + }) - # Already did this before - return self.db_object - except AttributeError: - # Doesn't exist so we'll create it - self.db_object = model.User.query.get(self.user_id) - return self.db_object + user_id = response['hits']['hits'][0]['_id'] + return user_id + + @property + def user_name(self): + """Shortcut to the user_name""" + if 'user_name' in self.record: + return self.record['user_name'] + else: + return '' + + @property + def user_collections(self): + """List of user's collections""" + + es = get_elasticsearch_connection() + + user_email = self.record['user_email_address'] + + #ZS: Get user's collections if they exist + response = es.search( + index = "users", doc_type = "local", body = { + "query": { "match": { "email_address": user_email } } + }) + user_info = response['hits']['hits'][0]['_source'] + if 'collections' in user_info.keys(): + if len(user_info['collections']) > 0: + return json.loads(user_info['collections']) + else: + return [] + else: + return [] + + @property + def num_collections(self): + """Number of user's collections""" + + es = get_elasticsearch_connection() + + user_email = self.record['user_email_address'] + + #ZS: Get user's collections if they exist + response = es.search( + index = "users", doc_type = "local", body = { + "query": { "match": { "email_address": user_email } } + }) + + user_info = response['hits']['hits'][0]['_source'] + logger.debug("USER NUM COLL:", user_info) + if 'collections' in user_info.keys(): + if user_info['collections'] != "[]" and len(user_info['collections']) > 0: + collections_json = json.loads(user_info['collections']) + return len(collections_json) + else: + return 0 + else: + return 0 + +### +# ZS: This is currently not used, but I'm leaving it here commented out because the old "set superuser" code (at the bottom of this file) used it +### +# @property +# def user_ob(self): +# """Actual sqlalchemy record""" +# # Only look it up once if needed, then store it +# # raise "OBSOLETE: use ElasticSearch instead" +# try: +# if LOG_SQL_ALCHEMY: +# logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG) +# +# # Already did this before +# return self.db_object +# except AttributeError: +# # Doesn't exist so we'll create it +# self.db_object = model.User.query.get(self.user_id) +# return self.db_object + + def add_collection(self, collection_name, traits): + """Add collection into ElasticSearch""" + + collection_dict = {'id': unicode(uuid.uuid4()), + 'name': collection_name, + 'created_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'), + 'changed_timestamp': datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'), + 'num_members': len(traits), + 'members': list(traits) } + + es = get_elasticsearch_connection() + + user_email = self.record['user_email_address'] + response = es.search( + index = "users", doc_type = "local", body = { + "query": { "match": { "email_address": user_email } } + }) + + user_id = response['hits']['hits'][0]['_id'] + user_info = response['hits']['hits'][0]['_source'] + + if 'collections' in user_info.keys(): + if user_info['collections'] != [] and user_info['collections'] != "[]": + current_collections = json.loads(user_info['collections']) + current_collections.append(collection_dict) + collections_json = json.dumps(current_collections) + else: + collections_json = json.dumps([collection_dict]) + else: + collections_json = json.dumps([collection_dict]) + collection_body = {'doc': {'collections': collections_json}} + es.update(index='users', doc_type='local', id=user_id, refresh='wait_for', body=collection_body) + + return collection_dict['id'] + + def delete_collection(self, collection_id): + """Remove collection with given ID""" + + updated_collections = [] + for collection in self.user_collections: + if collection['id'] == collection_id: + continue + else: + updated_collections.append(collection) + + es = get_elasticsearch_connection() + + collection_body = {'doc': {'collections': json.dumps(updated_collections)}} + es.update(index='users', doc_type='local', id=self.es_user_id, refresh='wait_for', body=collection_body) + + return collection['name'] + + def remove_traits_from_collection(self, collection_id, traits_to_remove): + """Remove specified traits from a collection""" + + this_collection = self.get_collection_by_id(collection_id) + + updated_collection = this_collection + updated_traits = [] + for trait in this_collection['members']: + if trait in traits_to_remove: + continue + else: + updated_traits.append(trait) + + updated_collection['members'] = updated_traits + updated_collection['num_members'] = len(updated_traits) + updated_collection['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p') + + updated_collections = [] + for collection in self.user_collections: + if collection['id'] == collection_id: + updated_collections.append(updated_collection) + else: + updated_collections.append(collection) + + es = get_elasticsearch_connection() + + collection_body = {'doc': {'collections': json.dumps(updated_collections)}} + es.update(index='users', doc_type='local', id=self.es_user_id, refresh='wait_for', body=collection_body) + + return updated_traits + + def get_collection_by_id(self, collection_id): + for collection in self.user_collections: + if collection['id'] == collection_id: + return collection + + def get_collection_by_name(self, collection_name): + for collection in self.user_collections: + if collection['name'] == collection_name: + return collection + + return None def delete_session(self): # And more importantly delete the redis record @@ -602,6 +766,7 @@ class LoginUser(object): def __init__(self): self.remember_me = False + self.logged_in = False def oauth2_login(self, login_type, user_id): """Login via an OAuth2 provider""" @@ -672,6 +837,8 @@ class LoginUser(object): #g.cookie_session.import_traits_to_user() + self.logged_in = True + return self.actual_login(user, import_collections=import_col) else: @@ -691,6 +858,7 @@ class LoginUser(object): max_age = self.remember_time else: max_age = None + response.set_cookie(UserSession.cookie_name, session_id_signed, max_age=max_age) return response @@ -706,6 +874,7 @@ class LoginUser(object): session = dict(login_time = time.time(), user_id = user.id, + user_name = user.full_name, user_email_address = user.email_address) key = UserSession.cookie_name + ":" + login_rec.session_id @@ -716,6 +885,7 @@ class LoginUser(object): else: expire_time = THREE_DAYS Redis.expire(key, expire_time) + return session_id_signed def unsuccessful_login(self, user): @@ -767,56 +937,57 @@ def forgot_password_submit(): def unauthorized(error): return redirect(url_for('login')) -def super_only(): - try: - superuser = g.user_session.user_ob.superuser - except AttributeError: - superuser = False - if not superuser: - flash("You must be a superuser to access that page.", "alert-error") - abort(401) - - - -@app.route("/manage/users") -def manage_users(): - super_only() - template_vars = UsersManager() - return render_template("admin/user_manager.html", **template_vars.__dict__) - -@app.route("/manage/user") -def manage_user(): - super_only() - template_vars = UserManager(request.args) - return render_template("admin/ind_user_manager.html", **template_vars.__dict__) - -@app.route("/manage/groups") -def manage_groups(): - super_only() - template_vars = GroupsManager(request.args) - return render_template("admin/group_manager.html", **template_vars.__dict__) - -@app.route("/manage/make_superuser") -def make_superuser(): - super_only() - params = request.args - user_id = params['user_id'] - user = model.User.query.get(user_id) - superuser_info = basic_info() - superuser_info['crowned_by'] = g.user_session.user_id - user.superuser = json.dumps(superuser_info, sort_keys=True) - db_session.commit() - flash("We've made {} a superuser!".format(user.name_and_org)) - return redirect(url_for("manage_users")) - -@app.route("/manage/assume_identity") -def assume_identity(): - super_only() - params = request.args - user_id = params['user_id'] - user = model.User.query.get(user_id) - assumed_by = g.user_session.user_id - return LoginUser().actual_login(user, assumed_by=assumed_by) +### +# ZS: The following 6 functions require the old MySQL User accounts; I'm leaving them commented out just in case we decide to reimplement them using ElasticSearch +### +#def super_only(): +# try: +# superuser = g.user_session.user_ob.superuser +# except AttributeError: +# superuser = False +# if not superuser: +# flash("You must be a superuser to access that page.", "alert-error") +# abort(401) + +#@app.route("/manage/users") +#def manage_users(): +# super_only() +# template_vars = UsersManager() +# return render_template("admin/user_manager.html", **template_vars.__dict__) + +#@app.route("/manage/user") +#def manage_user(): +# super_only() +# template_vars = UserManager(request.args) +# return render_template("admin/ind_user_manager.html", **template_vars.__dict__) + +#@app.route("/manage/groups") +#def manage_groups(): +# super_only() +# template_vars = GroupsManager(request.args) +# return render_template("admin/group_manager.html", **template_vars.__dict__) + +#@app.route("/manage/make_superuser") +#def make_superuser(): +# super_only() +# params = request.args +# user_id = params['user_id'] +# user = model.User.query.get(user_id) +# superuser_info = basic_info() +# superuser_info['crowned_by'] = g.user_session.user_id +# user.superuser = json.dumps(superuser_info, sort_keys=True) +# db_session.commit() +# flash("We've made {} a superuser!".format(user.name_and_org)) +# return redirect(url_for("manage_users")) + +#@app.route("/manage/assume_identity") +#def assume_identity(): +# super_only() +# params = request.args +# user_id = params['user_id'] +# user = model.User.query.get(user_id) +# assumed_by = g.user_session.user_id +# return LoginUser().actual_login(user, assumed_by=assumed_by) @app.route("/n/register", methods=('GET', 'POST')) |