Basic Auth with tabs - jordy33/turbogears_tutorial GitHub Wiki
From this link Include this directories to the public folder
Update setup.py with the following ti ebavke urllib3:
install_requires = [
"TurboGears2 >= 2.3.12",
"Beaker >= 1.8.0",
"Kajiki >= 0.6.3",
"Mako",
"zope.sqlalchemy >= 0.4",
"sqlalchemy",
"alembic",
"repoze.who",
"tw2.forms",
"tgext.admin >= 0.6.1",
"WebHelpers2",
"urllib3==1.22"
]
Update app_globals with the following:
# -*- coding: utf-8 -*-
"""The application's Globals object"""
__all__ = ['Globals']
import os
import urllib3
class Globals(object):
"""Container for objects available throughout the life of the application.
One instance of Globals is created during application initialization and
is available during requests via the 'app_globals' variable.
"""
def __init__(self):
"""Do nothing, by default."""
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Server parameters
self.host_secure = os.getenv('MYPROJECT_SECURE')
if self.host_secure is None:
self.host_secure="False"
if self.host_secure=="False":
host_prefix="http://"
else:
host_prefix="https://"
self.host_prefix=host_prefix
host_port=os.getenv('MYPROJECT_PORT')
if host_port is None:
host_port=""
if len(host_port)>0:
self.host_port=":"+host_port
else:
self.host_port=""
self.host=os.getenv('MYPROJECT_HOST')
if self.host is None:
self.host=host_prefix+"localhost:8080"
else:
self.host=host_prefix+self.host
self.app_dir = os.getenv('MYPROJECT_DIR')
if self.app_dir is None:
self.app_dir=os.getcwd()
# STOMP parameters
self.stomp_secure=os.getenv('STOMP_SECURE')
if self.stomp_secure is None:
self.stomp_secure="True"
if self.stomp_secure=="False":
stomp_prefix="ws://"
else:
stomp_prefix="wss://"
stomp_port=os.getenv('STOMP_PORT')
if stomp_port is None:
stomp_port=""
if len(stomp_port)>1:
self.stomp_port=":"+stomp_port
else:
self.stomp_port=""
self.stompHost = os.getenv('STOMP_HOST')
if self.stompHost is None:
self.stompHost = "stomp.dudewhereismy.mx"
self.stompUserName = os.getenv('STOMP_MASTER_USER')
if self.stompUserName is None:
self.stompUserName = "dwim"
self.stompPassword = os.getenv('STOMP_MASTER_PASS')
if self.stompPassword is None:
self.stompPassword = "gpscontrol1"
self.stompServer=stomp_prefix+self.stompHost+':15671'+'/ws'
# Telefonica Test parameters
cert_file_path = self.app_dir + "/telefonica.cer"
key_file_path = self.app_dir + "/telefonica.key"
self.cert = (cert_file_path, key_file_path)
self.apiUser="customer-DUDE_WHERE_IS_MY156320dc8168LfDu"
if os.getenv('SUN_SECURE')=="True":
self.domainsun="https://"+os.getenv('SUN_HOST')
else:
self.domainsun = "http://" + os.getenv('SUN_HOST')
if os.getenv('PLUTO_SECURE') == "True":
self.domainpluto="https://"+os.getenv('PLUTO_HOST')
else:
self.domainpluto = "http://" + os.getenv('PLUTO_HOST')
self.sunUsers = os.getenv('SUN_USERS')
if self.sunUsers is None:
self.sunUsers=self.domainsun+"/services/users"
self.sunGroups = os.getenv('SUN_GROUPS')
if self.sunGroups is None:
self.sunGroups = self.domainsun+"/services/groups"
self.sunApplications=self.domainsun+"/services/applications?internal_id=2"
self.sunapps = self.domainsun + "/services/apps"
self.telefonicaPosition="https://m2m-api.telefonica.com:8010/services/REST/GlobalM2M/Inventory/v5/r12/sim/icc:"
self.opencell="http://opencellid.org/cell/get"
self.opencellkey="2a87df53b26d3e"
Update helpers.py
# -*- coding: utf-8 -*-
"""Template Helpers used in myprojectname."""
import logging
from markupsafe import Markup
from datetime import datetime
from tg import request
from myprojectname.model import DBSession,User, Permission
from tg import app_globals
log = logging.getLogger(__name__)
def current_year():
now = datetime.now()
return now.strftime('%Y')
def today():
now = datetime.now()
return now.strftime('%d / %m / %y')
def icon(icon_name):
return Markup('<i class="glyphicon glyphicon-%s"></i>' % icon_name)
def badge():
if request.identity is None:
counter = 0
else:
identity = request.identity['repoze.who.userid']
user = DBSession.query(User).filter_by(user_name=identity).first()
counter = 0
return '' if counter == 0 else str(counter)
def whoami():
try:
ret=request.identity["repoze.who.userid"]
except:
return ""
else:
return ret
def password():
return 'gpscontrol1'
def perm(name):
identity = request.identity['repoze.who.userid']
user = DBSession.query(User).filter_by(user_name=identity).first()
perm = Permission.exist(u''+name+'',user.groups)
if perm == "si":
return True
else:
return False
# def url():
# return app_globals.host
def url():
return app_globals.host
#"https://dispatch.dudewhereismy.mx"
def stompServer():
return app_globals.stompServer
def stompUser():
return app_globals.stompUserName
def stompPassword():
return app_globals.stompPassword
# Import commonly used helpers from WebHelpers2 and TG
from tg.util.html import script_json_encode
try:
from webhelpers2 import date, html, number, misc, text
except SyntaxError:
log.error("WebHelpers2 helpers not available with this Python Version")
Update master.mak
<!DOCTYPE html>
<html>
<head>
${self.meta()}
<title>${self.title()}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/ecmascript" src="${tg.url('/lib/js/jquery-1.11.0.js')}"></script>
<script src="${tg.url('/lib/js/bootstrap.min.js')}"></script>
<script type="text/ecmascript" src="${tg.url('/lib/js/grid.locale-es.js')}"></script>
<!-- This is the Javascript file of jqGrid -->
<script type="text/ecmascript" src="${tg.url('/lib/js/jquery.jqgrid.src.js')}"></script>
<script type="text/ecmascript" src="${tg.url('/lib/js/jquery-ui.min.js')}"></script>
<link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/lib/css/jquery-ui.css')}" />
<!-- The link to the CSS that the grid needs -->
<link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/lib/css/ui.jqgrid.css')}" />
<link href="${tg.url('/lib/fonts/font-awesome.min.css')}" rel="stylesheet" />
<meta charset="utf-8" />
<title>MyProjectName</title>
<link href="${tg.url('/lib/css/bootstrap.min.css')}" rel="stylesheet">
<script src="${tg.url('/lib/stomp/stomp.js')}"></script>
<script src="${tg.url('/lib/moment/moment.js')}"></script>
<script src="${tg.url('/lib/js/alert.js')}"></script>
<script src="${tg.url('/lib/justgage/raphael-2.1.4.min.js')}"></script>
<script src="${tg.url('/lib/justgage/justgage.js')}"></script>
<script src="${tg.url('/lib/jqueryrotate/jQueryRotate.js')}"></script>
<script src="${tg.url('/lib/jquery-validation-1.17.0/dist/jquery.validate.js')}"></script>
<script src="${tg.url('/lib/timepicker/jquery-ui-timepicker-addon.js')}"></script>
<style type="text/css">
input { box-shadow: 0 0 3px #CC0000; margin: 10px }
.dropdown {
background: rgba(255, 255, 255, 0.1);
float: left;
margin: 10px 8px;
padding: 0px;
border-radius: 4px;
list-style-type: none;}
.dropdown a.dropdown-toggle {
height: 40px;
width: 40px;
padding-top: 11px;
padding-left: 9px; }
.dropdown:hover {
color: #fff;
background: rgba(255, 255, 255, 0.2); }
.dropdown .label {
top: -4px;
left: 22px;
padding-top: 4px;
padding-bottom: 4px;
position: absolute;
border-radius: 9999px; }
.profile-sidebar {
padding: 10px 0;
border-bottom: 1px solid #e9ecf2; }
.label-success {
background-color: #8ad919; }
.label-danger {
background-color: #f9243f; }
.profile-userpic img {
float: left;
margin: 10px 0px 0px 15px;
width: 50px;
height: 50px;
border-radius: 9999px !important; }
.profile-usertitle {
float: left;
text-align: left;
margin: 10px 0 0 12px; }
.profile-usertitle-name {
font-size: 15px;
margin-bottom: 0px; }
.profile-usertitle-status {
text-transform: uppercase;
color: #AAA;
font-size: 10px;
font-weight: 600;
margin-bottom: 15px; }
.indicator {
width: 10px;
height: 10px;
display: inline-block;
border-radius: 9999px;
margin-right: 5px; }
.error { color: #F00; background-color: #f1f4f3; }
div.dialog-hidden { display:none}
html, body { margin: 0; padding: 0;}
</style>
<!-- Global JavaScript -->
<script type="text/javascript">
function logout() {
var i = document.childNodes.length - 1;
while (i >= 0) {
console.log(document.childNodes[i]);
document.removeChild(document.childNodes[i--]);
}
jQuery.ajax({
type: "GET",
url: "/secc",
username: "logmeout",
password: "123456",
headers: { "Authorization": "Basic xxx" }
})
.done(function(){
// If we don't get an error, we actually got an error as we expect an 401!
})
.fail(function(){
// We expect to get an 401 Unauthorized error! In this case we are successfully
// logged out and we redirect the user.
window.location = "/";
});
return false;
}
var username = 'manager';
var password = 'managepass';
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
}
function doAjax(pageName,id) {
$.ajax({
url:pageName ,
error: function () {
alert("Error de credenciales con otro planeta");
},
beforeSend: function(xhr){
xhr.setRequestHeader("Content-Type","application/json");
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader( "Authorization", make_base_auth(username,password));
},
dataType: 'html',
data: { user: "${h.whoami()}", id:id } ,
success: function (data, rq) {
$("#loader"+id).html('');
$("#"+id).html(data);
},
error: function (data, rq) {
$("#"+id).html("<p>Error</p>");
},
type: 'GET'
});
}
function openTab(text,url) {
var num_tabs = $("div#tabs ul.main1 li.main1").length + 1;
var mytext= text;
var id = "frame"+num_tabs;
doAjax(url,id);
$("div#tabs ul.main1").append(
"<li class='main1'><a href='#tab"+num_tabs+"'>"+mytext+"</a><span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>"
);
$("div#tabs").append(
"<div id='tab"+num_tabs+"'> <div class='row'><div class='col-lg-12'><div id='"+id+"' style='margin:10px'></div><div id='loader"+id+"' class='cygnus'><span style='float:left;width: 20%;'><p>Cargando ...</p></span><span style='float:right;width: 80%;'><img src=${tg.url('/img/ajax-loader.gif')}></span></div></div></div></div>"
);
var $head = $("#"+id).contents().find("head");
var ur="${tg.url('/css/theme/jquery-ui1.css')}";
$head.append($("<link/>",
{ rel: "stylesheet", href:ur, type: "text/css" }
));
$("div#tabs").tabs("refresh").tabs('option', 'active', num_tabs - 1);
}
$(document).ready(function() {
$("div#tabs").tabs();
$( "#tabs" ).tabs().on( "click", "span.ui-icon-close", function() {
var num_tabs = $("div#tabs ul li").length + 1;
var panelId = $( this ).closest( "li" ).remove().attr( "aria-controls" );
$( "#" + panelId ).remove();
$("div#tabs").tabs("refresh").tabs('option', 'active', num_tabs - 1);
});
});
</script>
${self.head_content()}
</head>
% if tg.auth_stack_enabled:
% if not request.identity:
<meta http-equiv="refresh" content="0; url=${tg.url('/main')}" />
% else:
<body class="${self.body_class()}">
${self.main_menu()}
${self.footer()}
<!-- Insert nice scrool -->
${self.bottom_scripts()}
% endif
% endif
<%def name="meta()">
<meta charset="${response.charset}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Bootstrap 3 App">
<meta name="author" content="Jorge Macias & Maria Lacayo">
<meta name="keyword" content="Sun">
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
</%def>
<%def name="title()"> </%def>
<%def name="head_content()"></%def>
<%def name="body_class()"></%def>
<%def name="main_menu()">
<!-- INSERT MAIN MENU -->
<nav>
<table style="width: 100%" class=" ui-tabs-panel ui-corner-bottom ui-widget-content">
<td style="width: 5%">
<table>
<tr>
<td colspan="2">
<div align="center" >
<a class="navbar-brand" style="color:#a61a15" href="#"><span>${_('Administration')}</span> <br><div>System</div></a>
</div>
</td>
</tr>
<tr>
<td>
<table>
<td>
<li class="dropdown">
<a style="color:#a61a15" class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
<em class="fa fa-bell"></em><span class="label label-info" id="numeric_badge">${h.badge()}</span>
</a>
<ul class="dropdown-menu dropdown-alerts">
</ul>
</li>
</td>
<td>
<div class="profile-usertitle">
<div class="profile-usertitle-name">${h.whoami()}</div>
<div id="online" class="dialog-hidden">
<div class="profile-usertitle-status"><span class="indicator label-success"></span>Online</div>
</div>
<div id="offline" class="dialog-hidden">
<div class="profile-usertitle-status"><span class="indicator label-danger"></span>Offline</div>
</div>
</div>
</td>
</table>
</td>
</tr>
</table>
</td>
<td>
<ul class="nav nav-tabs ui-widget-header">
<li class=active><a href="#pl11" aria-expanded="true">MyProjectName</a></li>
<li><a href="#" onclick="logout()" style="color:#666"><em class="fa fa-power-off"> </em>Logout</a></li>
</ul>
<div class="tab-content ui-tabs-panel ui-corner-bottom ui-widget-content">
<div class="tab-pane fade in active" id="pl11" style="height:70px;padding: 10px">
<button onclick="openTab('JQgrid','${h.url()}/secc/test')" title="home of dispatch">Jqgrid</button>
</div>
</div>
</td>
</table>
</nav>
<div id="tabs">
<ul class="nav nav-tabs ui-widget-header main1">
<li class="main1"><a href="#tabs-1" >Inicio</a></li>
</ul>
<div id="tabs-1" align="right">
${self.content_wrapper()}
</div>
</div>
<!-- End MENU -->
</%def>
<%def name="content_wrapper()">
<%
flash=tg.flash_obj.render('flash', use_js=False)
%>
% if flash:
<script>$.alert("${str(tg.flash_obj.pop_payload()['message'])}" ,{autoclose:false,type:'info',title:false});</script>
% endif
${self.body()}
</%def>
<%def name="footer()">
<!-- INSERT FOOTER -->
<div class="text-right">
<div class="credits">
<p>Copyright © Madd Systems ${h.current_year()} </p>
</div>
</div>
</%def>
<%def name="bottom_scripts()">
<script type="text/javascript">
</script>
</%def>
Create test.mak inside templates:
<div style="margin-left:20px">
<table id="jqGrid"></table>
<div id="jqGridPager"></div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#jqGrid").jqGrid({
url: 'http://trirand.com/blog/phpjqgrid/examples/jsonp/getjsonp.php?callback=?&qwery=longorders',
mtype: "GET",
styleUI : 'Bootstrap',
datatype: "jsonp",
colModel: [
{ label: 'OrderID', name: 'OrderID', key: true, width: 75 },
{ label: 'Customer ID', name: 'CustomerID', width: 150 },
{ label: 'Order Date', name: 'OrderDate', width: 150 },
{ label: 'Freight', name: 'Freight', width: 150 },
{ label:'Ship Name', name: 'ShipName', width: 150 }
],
viewrecords: true,
height: 250,
rowNum: 20,
pager: "#jqGridPager"
});
});
</script>
Update secure.py controller:
# -*- coding: utf-8 -*-
"""Sample controller with all its actions protected."""
from tg import expose, flash
from tg.i18n import ugettext as _, lazy_ugettext as l_
from tg import predicates
from myprojectname.lib.base import BaseController
__all__ = ['SecureController']
class SecureController(BaseController):
"""Sample controller-wide authorization"""
# The predicate that must be met for all the actions in this controller:
# allow_only = has_permission(
# 'manage',
# msg=l_('Only for people with the "manage" permission')
# )
allow_only = predicates.not_anonymous()
@expose('myprojectname.templates.index')
def root(self):
"""Let the user know that's visiting a protected controller."""
#flash(_("Secure Controller here"))
return dict(page='index')
@expose('myprojectname.templates.test')
def test(self):
return dict()
Create a Service:
Add in controllers services.py with the following:
# -*- coding: utf-8 -*-
"""Sample controller with all its actions protected."""
from tg import expose
from myprojectname.lib.base import BaseController
__all__ = ['ServicesController']
class ServicesController(BaseController):
"""Sample controller-wide authorization"""
@expose('json')
def listjson(self, **kw):
lista = []
#http://localhost:8080/secc/test/?user=manager&app_name=Deployment&internal_id=1&application_id=1
#http://localhost:8080/services/listjson
lista.append({'id': 400,
'name': ('JqGrid Exmaple'),
'rows':1,
'cols':1,
'observations': ('Administración JqGrid'),
'perm': 'Admin JqGrid',
'open': 'Menu',
'url': '',
'sons' :[{
'id': 401,
'name': 'Listado de Clientes',
'url': '/sec/test',
'perm': 'Administrar Clientes',
'observations': ('Customers admin'),
'open': 'openTab',
'sons': '',
'icon': '<span class="glyphicon glyphicon-file"></span>'
}
]
})
return dict(list=lista, error="ok", planet_name="dmyprojectname")
Add to root controller at the top:
from myprojectname.controllers.services import ServicesController
Add inside the RootController class:
services = ServicesController()
Test service:
http://localhost:8080/services/listjson