Compare commits

..
21 Commits
Author SHA1 Message Date
mdipierro edcc2e44dc R-2.12.3 2015-08-18 19:15:01 -05:00
mdipierro 2cf9f26b0d fixed pydal tracking again 2015-08-18 15:13:57 -05:00
mdipierro 4b99b6fdd7 adding debounced ajax calls 2015-08-18 14:16:10 -05:00
mdipierro 622430583f Merge pull request #1047 from web2py/revert-1046-master
Revert "added default HttpOnly cookies"
2015-08-18 13:59:07 -05:00
mdipierro 89cc5a5f70 Revert "added default HttpOnly cookies" 2015-08-18 13:57:44 -05:00
mdipierro 6899154fcd reverted DAL to v15.07 2015-08-18 13:46:38 -05:00
mdipierro 47c0e461f1 Merge pull request #1046 from ShySec/master
added default HttpOnly cookies
2015-08-18 11:53:54 -05:00
mdipierro 93237837ed Merge pull request #1042 from cassiobotaro/master
Allow change quality when RESIZE
2015-08-18 11:52:52 -05:00
kelson cf20ce5fae _js_cookies => not httponly_cookies 2015-08-18 12:25:13 -04:00
mdipierro 04c86f07ef Merge pull request #1032 from dsk7/allow_requires_login_to_be_determined_dynamically
Allow to specify a function for requires_login at auth decoration.
2015-08-18 11:03:37 -05:00
mdipierro 1a12c4011b Merge pull request #1031 from mmunz/master
Repair cache status page in appadmin for welcome, admin and examples …
2015-08-18 11:02:14 -05:00
mdipierro 85bbe15758 Merge pull request #1030 from josedesoto/issue/1028
fixed issue #1028, saml2 bug
2015-08-18 11:01:46 -05:00
mdipierro 5816481a44 Merge pull request #1029 from timnyborg/patch-3
simplejsonrpc: Fix TypeError when data is None
2015-08-18 11:01:19 -05:00
kelson 2675e9d229 added default HttpOnly cookies 2015-08-18 10:23:29 -04:00
mdipierro 41498917d5 Autocomplete(...at_beginning=False) 2015-08-16 15:22:45 -05:00
Cássio Botaro 8f7acd8154 Allow change quality when RESIZE 2015-08-13 02:12:49 -03:00
mdipierro 26865421b6 email change 2015-08-11 00:32:09 -05:00
dsk7 f94bc250eb Allow to specify a function for requires_login at auth decoration. 2015-08-02 13:21:20 +02:00
Manuel Munz 8078d4b0f3 Repair cache status page in appadmin for welcome, admin and examples apps.
This fixes how values are read. For cache.disk, we need to use the second value in the dict.
For cache.ram everything is already there in the object, no need trying to get the stats (which are not there) in the loop.
Also small fix for buttons that did not open the detailed statistics when clicked (class hidden has !important in bootstrap3).
2015-08-01 00:29:34 +02:00
Tim Nyborg 5ee8c9c930 simplejsonrpc: Fix TypeError when data is none 2015-07-27 12:07:26 +01:00
Jose de Soto 6659bc0793 fixed issue #1028, saml2 bug 2015-07-27 13:05:36 +02:00
14 changed files with 166 additions and 98 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ update:
echo "remember that pymysql was tweaked" echo "remember that pymysql was tweaked"
src: src:
### Use semantic versioning ### Use semantic versioning
echo 'Version 2.12.2-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION echo 'Version 2.12.3-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
### rm -f all junk files ### rm -f all junk files
make clean make clean
### clean up baisc apps ### clean up baisc apps
+1 -1
View File
@@ -1 +1 @@
Version 2.12.2-stable+timestamp.2015.08.09.09.27.09 Version 2.12.3-stable+timestamp.2015.08.18.19.14.07
+20 -19
View File
@@ -445,30 +445,31 @@ def ccache():
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
# get ram stats directly from the cache object
ram_stats = cache.ram.stats[request.application]
ram['hits'] = ram_stats['hit_total'] - ram_stats['misses']
ram['misses'] = ram_stats['misses']
try:
ram['ratio'] = ram['hits'] * 100 / ram_stats['hit_total']
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
for key, value in cache.ram.storage.iteritems(): for key, value in cache.ram.storage.iteritems():
if isinstance(value, dict): if hp:
ram['hits'] = value['hit_total'] - value['misses'] ram['bytes'] += hp.iso(value[1]).size
ram['misses'] = value['misses'] ram['objects'] += hp.iso(value[1]).count
try: ram['entries'] += 1
ram['ratio'] = ram['hits'] * 100 / value['hit_total'] if value[0] < ram['oldest']:
except (KeyError, ZeroDivisionError): ram['oldest'] = value[0]
ram['ratio'] = 0 ram['keys'].append((key, GetInHMS(time.time() - value[0])))
else:
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
ram['entries'] += 1
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage: for key in cache.disk.storage:
value = cache.disk.storage[key] value = cache.disk.storage[key]
if isinstance(value, dict): if isinstance(value[1], dict):
disk['hits'] = value['hit_total'] - value['misses'] disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value['misses'] disk['misses'] = value[1]['misses']
try: try:
disk['ratio'] = disk['hits'] * 100 / value['hit_total'] disk['ratio'] = disk['hits'] * 100 / value[1]['hit_total']
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
disk['ratio'] = 0 disk['ratio'] = 0
else: else:
+6 -6
View File
@@ -137,9 +137,9 @@
<h4>{{=T("Overview")}}</h4> <h4>{{=T("Overview")}}</h4>
<p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p> <p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p>
{{if total['entries'] > 0:}} {{if total['entries'] > 0:}}
<p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", <p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})",
dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} dict( ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}}
</p> </p>
<p> <p>
{{=T("Size of cache:")}} {{=T("Size of cache:")}}
{{if object_stats:}} {{if object_stats:}}
@@ -155,7 +155,7 @@
{{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}} dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}} {{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="all_keys"> <div class="hidden" id="all_keys">
{{=total['keys']}} {{=total['keys']}}
</div> </div>
@@ -183,7 +183,7 @@
{{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}} dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle();')}} {{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="ram_keys"> <div class="hidden" id="ram_keys">
{{=ram['keys']}} {{=ram['keys']}}
</div> </div>
@@ -212,7 +212,7 @@
{{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}} dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle();')}} {{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="disk_keys"> <div class="hidden" id="disk_keys">
{{=disk['keys']}} {{=disk['keys']}}
</div> </div>
+20 -19
View File
@@ -445,30 +445,31 @@ def ccache():
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
# get ram stats directly from the cache object
ram_stats = cache.ram.stats[request.application]
ram['hits'] = ram_stats['hit_total'] - ram_stats['misses']
ram['misses'] = ram_stats['misses']
try:
ram['ratio'] = ram['hits'] * 100 / ram_stats['hit_total']
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
for key, value in cache.ram.storage.iteritems(): for key, value in cache.ram.storage.iteritems():
if isinstance(value, dict): if hp:
ram['hits'] = value['hit_total'] - value['misses'] ram['bytes'] += hp.iso(value[1]).size
ram['misses'] = value['misses'] ram['objects'] += hp.iso(value[1]).count
try: ram['entries'] += 1
ram['ratio'] = ram['hits'] * 100 / value['hit_total'] if value[0] < ram['oldest']:
except (KeyError, ZeroDivisionError): ram['oldest'] = value[0]
ram['ratio'] = 0 ram['keys'].append((key, GetInHMS(time.time() - value[0])))
else:
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
ram['entries'] += 1
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage: for key in cache.disk.storage:
value = cache.disk.storage[key] value = cache.disk.storage[key]
if isinstance(value, dict): if isinstance(value[1], dict):
disk['hits'] = value['hit_total'] - value['misses'] disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value['misses'] disk['misses'] = value[1]['misses']
try: try:
disk['ratio'] = disk['hits'] * 100 / value['hit_total'] disk['ratio'] = disk['hits'] * 100 / value[1]['hit_total']
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
disk['ratio'] = 0 disk['ratio'] = 0
else: else:
+6 -6
View File
@@ -137,9 +137,9 @@
<h4>{{=T("Overview")}}</h4> <h4>{{=T("Overview")}}</h4>
<p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p> <p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p>
{{if total['entries'] > 0:}} {{if total['entries'] > 0:}}
<p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", <p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})",
dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} dict( ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}}
</p> </p>
<p> <p>
{{=T("Size of cache:")}} {{=T("Size of cache:")}}
{{if object_stats:}} {{if object_stats:}}
@@ -155,7 +155,7 @@
{{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}} dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}} {{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="all_keys"> <div class="hidden" id="all_keys">
{{=total['keys']}} {{=total['keys']}}
</div> </div>
@@ -183,7 +183,7 @@
{{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}} dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle();')}} {{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="ram_keys"> <div class="hidden" id="ram_keys">
{{=ram['keys']}} {{=ram['keys']}}
</div> </div>
@@ -212,7 +212,7 @@
{{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}} dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle();')}} {{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="disk_keys"> <div class="hidden" id="disk_keys">
{{=disk['keys']}} {{=disk['keys']}}
</div> </div>
+20 -19
View File
@@ -445,30 +445,31 @@ def ccache():
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
# get ram stats directly from the cache object
ram_stats = cache.ram.stats[request.application]
ram['hits'] = ram_stats['hit_total'] - ram_stats['misses']
ram['misses'] = ram_stats['misses']
try:
ram['ratio'] = ram['hits'] * 100 / ram_stats['hit_total']
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
for key, value in cache.ram.storage.iteritems(): for key, value in cache.ram.storage.iteritems():
if isinstance(value, dict): if hp:
ram['hits'] = value['hit_total'] - value['misses'] ram['bytes'] += hp.iso(value[1]).size
ram['misses'] = value['misses'] ram['objects'] += hp.iso(value[1]).count
try: ram['entries'] += 1
ram['ratio'] = ram['hits'] * 100 / value['hit_total'] if value[0] < ram['oldest']:
except (KeyError, ZeroDivisionError): ram['oldest'] = value[0]
ram['ratio'] = 0 ram['keys'].append((key, GetInHMS(time.time() - value[0])))
else:
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
ram['entries'] += 1
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage: for key in cache.disk.storage:
value = cache.disk.storage[key] value = cache.disk.storage[key]
if isinstance(value, dict): if isinstance(value[1], dict):
disk['hits'] = value['hit_total'] - value['misses'] disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value['misses'] disk['misses'] = value[1]['misses']
try: try:
disk['ratio'] = disk['hits'] * 100 / value['hit_total'] disk['ratio'] = disk['hits'] * 100 / value[1]['hit_total']
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
disk['ratio'] = 0 disk['ratio'] = 0
else: else:
+6 -6
View File
@@ -137,9 +137,9 @@
<h4>{{=T("Overview")}}</h4> <h4>{{=T("Overview")}}</h4>
<p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p> <p>{{=T.M("Number of entries: **%s**", total['entries'])}}</p>
{{if total['entries'] > 0:}} {{if total['entries'] > 0:}}
<p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", <p>{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})",
dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} dict( ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}}
</p> </p>
<p> <p>
{{=T("Size of cache:")}} {{=T("Size of cache:")}}
{{if object_stats:}} {{if object_stats:}}
@@ -155,7 +155,7 @@
{{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}} dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}} {{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="all_keys"> <div class="hidden" id="all_keys">
{{=total['keys']}} {{=total['keys']}}
</div> </div>
@@ -183,7 +183,7 @@
{{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}} dict(hours=ram['oldest'][0], min=ram['oldest'][1], sec=ram['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle();')}} {{=BUTTON(T('RAM Cache Keys'), _onclick='jQuery("#ram_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="ram_keys"> <div class="hidden" id="ram_keys">
{{=ram['keys']}} {{=ram['keys']}}
</div> </div>
@@ -212,7 +212,7 @@
{{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", {{=T.M("DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.",
dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}} dict(hours=disk['oldest'][0], min=disk['oldest'][1], sec=disk['oldest'][2]))}}
</p> </p>
{{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle();')}} {{=BUTTON(T('Disk Cache Keys'), _onclick='jQuery("#disk_keys").toggle().toggleClass( "hidden" );')}}
<div class="hidden" id="disk_keys"> <div class="hidden" id="disk_keys">
{{=disk['keys']}} {{=disk['keys']}}
</div> </div>
+12 -7
View File
@@ -6,15 +6,17 @@
# #
# Given the model # Given the model
# #
# db.define_table("table_name", Field("picture", "upload"), Field("thumbnail", "upload")) # db.define_table("table_name", Field("picture", "upload"),
# Field("thumbnail", "upload"))
# #
# # to resize the picture on upload # to resize the picture on upload
# #
# from images import RESIZE # from images import RESIZE
# #
# db.table_name.picture.requires = RESIZE(200, 200) # db.table_name.picture.requires = RESIZE(200, 200)
# #
# # to store original image in picture and create a thumbnail in 'thumbnail' field # to store original image in picture and create a thumbnail
# in 'thumbnail' field
# #
# from images import THUMB # from images import THUMB
# db.table_name.thumbnail.compute = lambda row: THUMB(row.picture, 200, 200) # db.table_name.thumbnail.compute = lambda row: THUMB(row.picture, 200, 200)
@@ -24,8 +26,11 @@ from gluon import current
class RESIZE(object): class RESIZE(object):
def __init__(self, nx=160, ny=80, error_message=' image resize'):
(self.nx, self.ny, self.error_message) = (nx, ny, error_message) def __init__(self, nx=160, ny=80, quality=100,
error_message=' image resize'):
(self.nx, self.ny, self.quality, self.error_message) = (
nx, ny, quality, error_message)
def __call__(self, value): def __call__(self, value):
if isinstance(value, str) and len(value) == 0: if isinstance(value, str) and len(value) == 0:
@@ -36,7 +41,7 @@ class RESIZE(object):
img = Image.open(value.file) img = Image.open(value.file)
img.thumbnail((self.nx, self.ny), Image.ANTIALIAS) img.thumbnail((self.nx, self.ny), Image.ANTIALIAS)
s = cStringIO.StringIO() s = cStringIO.StringIO()
img.save(s, 'JPEG', quality=100) img.save(s, 'JPEG', quality=self.quality)
s.seek(0) s.seek(0)
value.file = s value.file = s
except: except:
@@ -51,7 +56,7 @@ def THUMB(image, nx=120, ny=120, gae=False, name='thumb'):
request = current.request request = current.request
from PIL import Image from PIL import Image
import os import os
img = Image.open(os.path.join(request.folder,'uploads',image)) img = Image.open(os.path.join(request.folder, 'uploads', image))
img.thumbnail((nx, ny), Image.ANTIALIAS) img.thumbnail((nx, ny), Image.ANTIALIAS)
root, ext = os.path.splitext(image) root, ext = os.path.splitext(image)
thumb = '%s_%s%s' % (root, name, ext) thumb = '%s_%s%s' % (root, name, ext)
+57 -4
View File
@@ -13,6 +13,7 @@ Include in your model (eg db.py)::
auth.define_tables(username=True) auth.define_tables(username=True)
from gluon.contrib.login_methods.saml2_auth import Saml2Auth from gluon.contrib.login_methods.saml2_auth import Saml2Auth
import os
auth.settings.login_form=Saml2Auth( auth.settings.login_form=Saml2Auth(
config_file = os.path.join(request.folder,'private','sp_conf'), config_file = os.path.join(request.folder,'private','sp_conf'),
maps=dict( maps=dict(
@@ -20,10 +21,59 @@ Include in your model (eg db.py)::
email=lambda v: v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0], email=lambda v: v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0],
user_id=lambda v: v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0])) user_id=lambda v: v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0]))
you must have private/sp_conf.py, the pysaml2 sp configuration file you must have private/sp_conf.py, the pysaml2 sp configuration file. For example:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from saml2 import BINDING_HTTP_POST, BINDING_HTTP_REDIRECT
import os.path
import requests
import tempfile
BASEDIR = os.path.abspath(os.path.dirname(__file__))
# Web2py SP url and application name
HOST = 'http://127.0.0.1:8000'
APP = 'sp'
# To load the IDP metadata...
IDP_METADATA = 'http://127.0.0.1:8088/metadata'
def full_path(local_file):
return os.path.join(BASEDIR, local_file)
CONFIG = {
# your entity id, usually your subdomain plus the url to the metadata view.
'entityid': '%s/%s/default/metadata' % (HOST, APP),
'service': {
'sp' : {
'name': 'MYSP',
'endpoints': {
'assertion_consumer_service': [
('%s/%s/default/user/login' % (HOST, APP), BINDING_HTTP_REDIRECT),
('%s/%s/default/user/login' % (HOST, APP), BINDING_HTTP_POST),
],
},
},
},
# Your private and public key.
'key_file': full_path('pki/mykey.pem'),
'cert_file': full_path('pki/mycert.pem'),
# where the remote metadata is stored
'metadata': {
"remote": [{
"url": IDP_METADATA,
"cert":full_path('pki/mycert.pem')
}]
},
}
""" """
from saml2 import BINDING_HTTP_REDIRECT from saml2 import BINDING_HTTP_REDIRECT, BINDING_HTTP_POST
from saml2.client import Saml2Client from saml2.client import Saml2Client
from gluon.utils import web2py_uuid from gluon.utils import web2py_uuid
from gluon import current, redirect, URL from gluon import current, redirect, URL
@@ -59,10 +109,13 @@ def saml2_handler(session, request, config_filename = None):
client = Saml2Client(config_file = config_filename) client = Saml2Client(config_file = config_filename)
idps = client.metadata.with_descriptor("idpsso") idps = client.metadata.with_descriptor("idpsso")
entityid = idps.keys()[0] entityid = idps.keys()[0]
bindings = [BINDING_HTTP_REDIRECT] bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
binding, destination = client.pick_binding( binding, destination = client.pick_binding(
"single_sign_on_service", bindings, "idpsso", entity_id=entityid) "single_sign_on_service", bindings, "idpsso", entity_id=entityid)
binding = BINDING_HTTP_REDIRECT if request.env.request_method == 'GET':
binding = BINDING_HTTP_REDIRECT
elif request.env.request_method == 'POST':
binding = BINDING_HTTP_POST
if not request.vars.SAMLResponse: if not request.vars.SAMLResponse:
req_id, req = client.create_authn_request(destination, binding=binding) req_id, req = client.create_authn_request(destination, binding=binding)
relay_state = web2py_uuid().replace('-','') relay_state = web2py_uuid().replace('-','')
+1 -1
View File
@@ -34,7 +34,7 @@ except ImportError:
class JSONRPCError(RuntimeError): class JSONRPCError(RuntimeError):
"Error object for remote procedure call fail" "Error object for remote procedure call fail"
def __init__(self, code, message, data=None): def __init__(self, code, message, data=None):
value = "%s: %s\n%s" % (code, message, '\n'.join(data)) value = "%s: %s\n%s" % (code, message, '\n'.join(data or ''))
RuntimeError.__init__(self, value) RuntimeError.__init__(self, value)
self.code = code self.code = code
self.message = message self.message = message
+6 -4
View File
@@ -646,13 +646,12 @@ class AutocompleteWidget(object):
def __init__(self, request, field, id_field=None, db=None, def __init__(self, request, field, id_field=None, db=None,
orderby=None, limitby=(0, 10), distinct=False, orderby=None, limitby=(0, 10), distinct=False,
keyword='_autocomplete_%(tablename)s_%(fieldname)s', keyword='_autocomplete_%(tablename)s_%(fieldname)s',
min_length=2, help_fields=None, help_string=None): min_length=2, help_fields=None, help_string=None, at_beginning = True):
self.help_fields = help_fields or [] self.help_fields = help_fields or []
self.help_string = help_string self.help_string = help_string
if self.help_fields and not self.help_string: if self.help_fields and not self.help_string:
self.help_string = ' '.join('%%(%s)s' % f.name self.help_string = ' '.join('%%(%s)s' % f.name for f in self.help_fields)
for f in self.help_fields)
self.request = request self.request = request
self.keyword = keyword % dict(tablename=field.tablename, self.keyword = keyword % dict(tablename=field.tablename,
@@ -662,6 +661,7 @@ class AutocompleteWidget(object):
self.limitby = limitby self.limitby = limitby
self.distinct = distinct self.distinct = distinct
self.min_length = min_length self.min_length = min_length
self.at_beginning = at_beginning
self.fields = [field] self.fields = [field]
if id_field: if id_field:
self.is_reference = True self.is_reference = True
@@ -679,8 +679,10 @@ class AutocompleteWidget(object):
field = self.fields[0] field = self.fields[0]
if settings and settings.global_settings.web2py_runtime_gae: if settings and settings.global_settings.web2py_runtime_gae:
rows = self.db(field.__ge__(self.request.vars[self.keyword]) & field.__lt__(self.request.vars[self.keyword] + u'\ufffd')).select(orderby=self.orderby, limitby=self.limitby, *(self.fields+self.help_fields)) rows = self.db(field.__ge__(self.request.vars[self.keyword]) & field.__lt__(self.request.vars[self.keyword] + u'\ufffd')).select(orderby=self.orderby, limitby=self.limitby, *(self.fields+self.help_fields))
else: elif self.at_beginning:
rows = self.db(field.like(self.request.vars[self.keyword] + '%', case_sensitive=False)).select(orderby=self.orderby, limitby=self.limitby, distinct=self.distinct, *(self.fields+self.help_fields)) rows = self.db(field.like(self.request.vars[self.keyword] + '%', case_sensitive=False)).select(orderby=self.orderby, limitby=self.limitby, distinct=self.distinct, *(self.fields+self.help_fields))
else:
rows = self.db(field.contains(self.request.vars[self.keyword], case_sensitive=False)).select(orderby=self.orderby, limitby=self.limitby, distinct=self.distinct, *(self.fields+self.help_fields))
if rows: if rows:
if self.is_reference: if self.is_reference:
id_field = self.fields[1] id_field = self.fields[1]
+6 -1
View File
@@ -3739,7 +3739,12 @@ class Auth(object):
basic_allowed, basic_accepted, user = self.basic() basic_allowed, basic_accepted, user = self.basic()
user = user or self.user user = user or self.user
if requires_login:
login_required = requires_login
if callable(login_required):
login_required = login_required()
if login_required:
if not user: if not user:
if current.request.ajax: if current.request.ajax:
raise HTTP(401, self.messages.ajax_failed_authentication) raise HTTP(401, self.messages.ajax_failed_authentication)