Hi, I would like to create a tool or a template that could list and (re)generate key for the user you want if you are login as an admin. I found the api_keys function in the user controller but I don't know how to use it. It seems that the decorators before the function checked if you are login as the good user... I also found the mako template that used this api_keys function but it is still unclear for me. Here is my sql function (FULL OUTER JOIN compatibility for MySQL) that list every keys even if they are empty : SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` LEFT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id` UNION SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` RIGHT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id` I know how to do that in PHP but it won't use python framework sqlalchemy (= only for mysql or pgsql...) ! Morevoer I don't know how do you generate your api_keys. Is it a md5 sum based on username / password ? Or is it just a random key with fix length ? Any help would be gracefull, Regards, Remy
Ok, so I answer to myself. I created 2 template and 1 controller. You need tu put the controller in [galaxy_install_dir]/lib/galaxy/webapps/galaxy/controllers/userskeys.py """ Contains the user interface in the Universe class """ import glob import logging import os import socket import string import random import pprint from galaxy import web from galaxy import util, model from galaxy.model.orm import and_ from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname from galaxy.util.json import from_json_string, to_json_string from galaxy.web import url_for from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids from inspect import getmembers log = logging.getLogger( __name__ ) require_login_template = """ <p> This %s has been configured such that only users who are logged in may use it.%s </p> <p/> """ class UserOpenIDGrid( grids.Grid ): use_panels = False title = "OpenIDs linked to your account" model_class = model.UserOpenID template = '/user/openid_manage.mako' default_filter = { "openid" : "All" } default_sort_key = "-create_time" columns = [ grids.TextColumn( "OpenID URL", key="openid", link=( lambda x: dict( action='openid_auth', login_button="Login", openid_url=x.openid if not x.provider else '', openid_provider=x.provider, auto_associate=True ) ) ), grids.GridColumn( "Created", key="create_time", format=time_ago ), ] operations = [ grids.GridOperation( "Delete", async_compatible=True ), ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id ) class User( BaseUIController, UsesFormDefinitionsMixin ): user_openid_grid = UserOpenIDGrid() installed_len_files = None @web.expose @web.require_login() def api_keys( self, trans, cntrller, uid, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) uid = params.get('uid', uid) pprint.pprint(uid) if params.get( 'new_api_key_button', False ): new_key = trans.app.model.APIKeys() new_key.user_id = uid new_key.key = trans.app.security.get_new_guid() trans.sa_session.add( new_key ) trans.sa_session.flush() message = "Generated a new web API key" status = "done" return trans.fill_template( 'webapps/galaxy/user/ok_admin_api_keys.mako', cntrller=cntrller, message=message, status=status ) @web.expose @web.require_login() def all_users( self, trans, cntrller, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) users = [] for user in trans.sa_session.query( trans.app.model.User ) \ .filter( trans.app.model.User.table.c.deleted==False ) \ .order_by( trans.app.model.User.table.c.email ): uid = int(user.id) userkey = "" for api_user in trans.sa_session.query(trans.app.model.APIKeys) \ .filter( trans.app.model.APIKeys.user_id == uid): userkey = api_user.key users.append({'uid':uid, 'email':user.email, 'key':userkey}) return trans.fill_template( 'webapps/galaxy/user/list_users.mako', cntrller=cntrller, users=users, message=message, status=status ) Then the 2 templates [galaxy_install_dir]/templates/webapps/galaxy/user/ The first one listing all the users with their keys cat templates/webapps/galaxy/user/list_users.mako <%inherit file="/base.mako"/> %if message: ${render_msg( message, status )} %endif %if users: <div class="toolForm"> <div class="toolFormTitle">Users informations</div> <table> <thead><th>UID</th><th>email</th></thead> <tbody> %for user in users: <tr> <td>${user['uid']}</td> <td>${user['email']}</td> <td>${user['key']}</td> <td> <form action="${h.url_for( controller='userskeys', action='api_keys', cntrller=cntrller )}" method="POST"> <input type="hidden" name="uid" value=${user['uid']} /> <input type="submit" name="new_api_key_button" value="Generate a new key now" /> </form> </td> </tr> %endfor </tbody> </table> <div style="clear: both"></div> </div> %else: <div>No informations available</div> %endif <p/> The second one is just an information template : cat templates/webapps/galaxy/user/ok_admin_api_keys.mako <%inherit file="/base.mako"/> <%namespace file="/message.mako" import="render_msg" /> <br/><br/> <ul class="manage-table-actions"> <li> <a class="action-button" href="${h.url_for( controller='userskeys', action='all_users', cntrller=cntrller )}">List users API keys</a> </li> </ul> %if message: ${render_msg( message, status )} %endif <div> <div style="clear: both;"> SUCCESS. A new API key has been generated. </div> <div style="clear: both;"> An API key will allow you to access Galaxy via its web API (documentation forthcoming). Please note that <strong>this key acts as an alternate means to access your account, and should be treated with the same care as your login password</strong>. </div> </div> Then, you can go to http:// [galaxy_address]/userskeys/all_users?cntrller=userskeys I think it needs some control to check if you are an admin. Hope this help. Regards, Remy 2013/2/25 Rémy Dernat <remy.d1@gmail.com>
Hi,
I would like to create a tool or a template that could list and (re)generate key for the user you want if you are login as an admin. I found the api_keys function in the user controller but I don't know how to use it. It seems that the decorators before the function checked if you are login as the good user... I also found the mako template that used this api_keys function but it is still unclear for me.
Here is my sql function (FULL OUTER JOIN compatibility for MySQL) that list every keys even if they are empty :
SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` LEFT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id` UNION SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` RIGHT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id`
I know how to do that in PHP but it won't use python framework sqlalchemy (= only for mysql or pgsql...) !
Morevoer I don't know how do you generate your api_keys. Is it a md5 sum based on username / password ? Or is it just a random key with fix length ?
Any help would be gracefull,
Regards,
Remy
Hello, For people interested in this API management through galaxy GUI, I created a simple wrapper to use display.py : hg clone http://remy-d1@testtoolshed.g2.bx.psu.edu/repos/remy-d1/api_tools I think it should be better to use display.py API in a controller/template way, like I did before for key management, because $__app__.config would be depracated soon. To add the previous templates to admin panel, just change the controller like this : cat lib/galaxy/webapps/galaxy/controllers/userskeys.py """ Contains the user interface in the Universe class """ import glob import logging import os import socket import string import random import pprint from galaxy import web from galaxy import util, model from galaxy.model.orm import and_ from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname from galaxy.util.json import from_json_string, to_json_string from galaxy.web import url_for from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids from inspect import getmembers log = logging.getLogger( __name__ ) require_login_template = """ <p> This %s has been configured such that only users who are logged in may use it.%s </p> <p/> """ class UserOpenIDGrid( grids.Grid ): use_panels = False title = "OpenIDs linked to your account" model_class = model.UserOpenID template = '/user/openid_manage.mako' default_filter = { "openid" : "All" } default_sort_key = "-create_time" columns = [ grids.TextColumn( "OpenID URL", key="openid", link=( lambda x: dict( action='openid_auth', login_button="Login", openid_url=x.openid if not x.provider else '', openid_provider=x.provider, auto_associate=True ) ) ), grids.GridColumn( "Created", key="create_time", format=time_ago ), ] operations = [ grids.GridOperation( "Delete", async_compatible=True ), ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id ) class User( BaseUIController, UsesFormDefinitionsMixin ): user_openid_grid = UserOpenIDGrid() installed_len_files = None @web.expose @web.require_login() @web.require_admin def index( self, trans, cntrller, **kwd ): return trans.fill_template( 'webapps/galaxy/user/list_users.mako', action='all_users', cntrller=cntrller ) @web.expose @web.require_login() @web.require_admin def api_keys( self, trans, cntrller, uid, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) uid = params.get('uid', uid) pprint.pprint(uid) if params.get( 'new_api_key_button', False ): new_key = trans.app.model.APIKeys() new_key.user_id = uid new_key.key = trans.app.security.get_new_guid() trans.sa_session.add( new_key ) trans.sa_session.flush() message = "Generated a new web API key" status = "done" return trans.fill_template( 'webapps/galaxy/user/ok_admin_api_keys.mako', cntrller=cntrller, message=message, status=status ) @web.expose @web.require_login() @web.require_admin def all_users( self, trans, cntrller="userskeys", **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) users = [] for user in trans.sa_session.query( trans.app.model.User ) \ .filter( trans.app.model.User.table.c.deleted==False ) \ .order_by( trans.app.model.User.table.c.email ): uid = int(user.id) userkey = "" for api_user in trans.sa_session.query(trans.app.model.APIKeys) \ .filter( trans.app.model.APIKeys.user_id == uid): userkey = api_user.key users.append({'uid':uid, 'email':user.email, 'key':userkey}) return trans.fill_template( 'webapps/galaxy/user/list_users.mako', cntrller=cntrller, users=users, message=message, status=status ) Then, add an entry in templates/webapps/galaxy/admin/index.mako : nl templates/webapps/galaxy/admin/index.mako |grep userskeys 39 <div class="toolTitle"><a href="${h.url_for( controller='userskeys', action='all_users' )}" target="galaxy_main">Manage users API keys</a></div> (39 is the line number retrieve by "nl" command). I think that more tools for API available through GUI could be usefull. Regards, Remy 2013/2/28 Rémy Dernat <remy.d1@gmail.com>
Ok, so I answer to myself. I created 2 template and 1 controller.
You need tu put the controller in [galaxy_install_dir]/lib/galaxy/webapps/galaxy/controllers/userskeys.py
""" Contains the user interface in the Universe class """
import glob import logging import os import socket import string import random import pprint
from galaxy import web from galaxy import util, model from galaxy.model.orm import and_ from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname from galaxy.util.json import from_json_string, to_json_string from galaxy.web import url_for from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids
from inspect import getmembers
log = logging.getLogger( __name__ )
require_login_template = """ <p> This %s has been configured such that only users who are logged in may use it.%s </p> <p/> """
class UserOpenIDGrid( grids.Grid ): use_panels = False title = "OpenIDs linked to your account" model_class = model.UserOpenID template = '/user/openid_manage.mako' default_filter = { "openid" : "All" } default_sort_key = "-create_time" columns = [ grids.TextColumn( "OpenID URL", key="openid", link=( lambda x: dict( action='openid_auth', login_button="Login", openid_url=x.openid if not x.provider else '', openid_provider=x.provider, auto_associate=True ) ) ), grids.GridColumn( "Created", key="create_time", format=time_ago ), ] operations = [ grids.GridOperation( "Delete", async_compatible=True ), ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id )
class User( BaseUIController, UsesFormDefinitionsMixin ): user_openid_grid = UserOpenIDGrid() installed_len_files = None
@web.expose @web.require_login() def api_keys( self, trans, cntrller, uid, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) uid = params.get('uid', uid) pprint.pprint(uid) if params.get( 'new_api_key_button', False ): new_key = trans.app.model.APIKeys() new_key.user_id = uid new_key.key = trans.app.security.get_new_guid() trans.sa_session.add( new_key ) trans.sa_session.flush() message = "Generated a new web API key" status = "done" return trans.fill_template( 'webapps/galaxy/user/ok_admin_api_keys.mako', cntrller=cntrller, message=message, status=status )
@web.expose @web.require_login() def all_users( self, trans, cntrller, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) users = [] for user in trans.sa_session.query( trans.app.model.User ) \ .filter( trans.app.model.User.table.c.deleted==False ) \ .order_by( trans.app.model.User.table.c.email ): uid = int(user.id) userkey = "" for api_user in trans.sa_session.query(trans.app.model.APIKeys) \ .filter( trans.app.model.APIKeys.user_id == uid): userkey = api_user.key users.append({'uid':uid, 'email':user.email, 'key':userkey}) return trans.fill_template( 'webapps/galaxy/user/list_users.mako', cntrller=cntrller, users=users, message=message, status=status )
Then the 2 templates [galaxy_install_dir]/templates/webapps/galaxy/user/
The first one listing all the users with their keys cat templates/webapps/galaxy/user/list_users.mako
<%inherit file="/base.mako"/>
%if message: ${render_msg( message, status )} %endif
%if users: <div class="toolForm"> <div class="toolFormTitle">Users informations</div> <table> <thead><th>UID</th><th>email</th></thead> <tbody> %for user in users: <tr> <td>${user['uid']}</td> <td>${user['email']}</td> <td>${user['key']}</td> <td> <form action="${h.url_for( controller='userskeys', action='api_keys', cntrller=cntrller )}" method="POST"> <input type="hidden" name="uid" value=${user['uid']} /> <input type="submit" name="new_api_key_button" value="Generate a new key now" /> </form> </td> </tr> %endfor </tbody> </table> <div style="clear: both"></div> </div> %else: <div>No informations available</div> %endif
<p/>
The second one is just an information template :
cat templates/webapps/galaxy/user/ok_admin_api_keys.mako
<%inherit file="/base.mako"/> <%namespace file="/message.mako" import="render_msg" />
<br/><br/> <ul class="manage-table-actions"> <li> <a class="action-button" href="${h.url_for( controller='userskeys', action='all_users', cntrller=cntrller )}">List users API keys</a> </li> </ul>
%if message: ${render_msg( message, status )} %endif
<div> <div style="clear: both;"> SUCCESS. A new API key has been generated. </div>
<div style="clear: both;"> An API key will allow you to access Galaxy via its web API (documentation forthcoming). Please note that <strong>this key acts as an alternate means to access your account, and should be treated with the same care as your login password</strong>. </div> </div>
Then, you can go to http:// [galaxy_address]/userskeys/all_users?cntrller=userskeys
I think it needs some control to check if you are an admin.
Hope this help.
Regards, Remy
2013/2/25 Rémy Dernat <remy.d1@gmail.com>
Hi,
I would like to create a tool or a template that could list and (re)generate key for the user you want if you are login as an admin. I found the api_keys function in the user controller but I don't know how to use it. It seems that the decorators before the function checked if you are login as the good user... I also found the mako template that used this api_keys function but it is still unclear for me.
Here is my sql function (FULL OUTER JOIN compatibility for MySQL) that list every keys even if they are empty :
SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` LEFT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id` UNION SELECT `galaxy_user`.`id`, `api_keys`.`user_id`, `api_keys`.`key`, `galaxy_user`.`email`, `galaxy_user`.`username` FROM `galaxy_user` RIGHT JOIN `api_keys` on `api_keys`.`user_id` = `galaxy_user`.`id`
I know how to do that in PHP but it won't use python framework sqlalchemy (= only for mysql or pgsql...) !
Morevoer I don't know how do you generate your api_keys. Is it a md5 sum based on username / password ? Or is it just a random key with fix length ?
Any help would be gracefull,
Regards,
Remy
participants (1)
-
Rémy Dernat