Compare commits
24 Commits
R-2.10.4.b
...
R-2.10.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58533954dc | ||
|
|
236dc4b943 | ||
|
|
6612fd1cfe | ||
|
|
520950ba74 | ||
|
|
e943aa9c25 | ||
|
|
756aec7206 | ||
|
|
970e2ed35c | ||
|
|
1388c39636 | ||
|
|
6e84737924 | ||
|
|
0ad50630f2 | ||
|
|
f42ee15f5f | ||
|
|
2b0bfba649 | ||
|
|
9f1edf267d | ||
|
|
f3bda9ad02 | ||
|
|
f8afc76263 | ||
|
|
65b4aaf842 | ||
|
|
1b729cfbfc | ||
|
|
1aa5f30091 | ||
|
|
b17174c04c | ||
|
|
ac80adc9b4 | ||
|
|
888fa3dfc8 | ||
|
|
f3d815e84b | ||
|
|
9915fdf093 | ||
|
|
ef8f802df9 |
2
Makefile
2
Makefile
@@ -32,7 +32,7 @@ update:
|
||||
echo "remember that pymysql was tweaked"
|
||||
src:
|
||||
### Use semantic versioning
|
||||
echo 'Version 2.10.3-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
echo 'Version 2.10.4-beta+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
### rm -f all junk files
|
||||
make clean
|
||||
### clean up baisc apps
|
||||
|
||||
2
VERSION
2
VERSION
@@ -1 +1 @@
|
||||
Version 2.10.3-stable+timestamp.2015.04.02.16.28.49
|
||||
Version 2.10.4-stable+timestamp.2015.04.26.09.05.21
|
||||
|
||||
@@ -62,7 +62,7 @@ auth.define_tables(username=False, signature=False)
|
||||
|
||||
## configure email
|
||||
mail = auth.settings.mailer
|
||||
mail.settings.server = 'logging' if request.is_local else myconf.take('smtp.sender')
|
||||
mail.settings.server = 'logging' if request.is_local else myconf.take('smtp.server')
|
||||
mail.settings.sender = myconf.take('smtp.sender')
|
||||
mail.settings.login = myconf.take('smtp.login')
|
||||
|
||||
|
||||
46
examples/web.config
Normal file
46
examples/web.config
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- app configuration for web2py on IIS -->
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="WSGI_HANDLER" value="gluon.main.wsgibase" />
|
||||
<add key="WSGI_RESTART_FILE_REGEX" value=".*((routes\.py)|(\.config))$" />
|
||||
</appSettings>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<clear />
|
||||
<rule name="static" enabled="true" stopProcessing="true">
|
||||
<match url="^(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$" />
|
||||
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
|
||||
<action type="Rewrite" url="applications/{R:1}/static/{R:2}" logRewrittenUrl="false" />
|
||||
</rule>
|
||||
<rule name="web2py_app" enabled="true" stopProcessing="true">
|
||||
<match url="(.*)" ignoreCase="false" />
|
||||
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
|
||||
<action type="Rewrite" url="handler.web2py/{R:1}" appendQueryString="true" />
|
||||
</rule>
|
||||
</rules>
|
||||
<outboundRules>
|
||||
<rule name="static_version_cache_control" preCondition="static_version">
|
||||
<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
|
||||
<action type="Rewrite" value="max-age=315360000" />
|
||||
<conditions>
|
||||
</conditions>
|
||||
</rule>
|
||||
<rule name="static_version_Expires" preCondition="static_version">
|
||||
<match serverVariable="RESPONSE_Expires" pattern=".*" />
|
||||
<action type="Rewrite" value="Thu, 31 Dec 2037 23:59:59 GMT" />
|
||||
</rule>
|
||||
<preConditions>
|
||||
<preCondition name="static_version">
|
||||
<add input="{REQUEST_URI}" pattern="(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$" />
|
||||
</preCondition>
|
||||
</preConditions>
|
||||
</outboundRules>
|
||||
</rewrite>
|
||||
<handlers>
|
||||
<!-- replace SCRIPT_PROCESSOR with the configured handler for python -->
|
||||
<add name="Python_via_FastCGI" path="handler.web2py" verb="*" modules="FastCgiModule" scriptProcessor="SCRIPT_PROCESSOR" resourceType="Unspecified" requireAccess="Script" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -521,9 +521,19 @@ def ldap_auth(server='ldap', port=None,
|
||||
logging.error(
|
||||
'There is no username or email for %s!' % username)
|
||||
raise
|
||||
db_group_search = db((db.auth_membership.user_id == db_user_id) &
|
||||
(db.auth_user.id == db.auth_membership.user_id) &
|
||||
(db.auth_group.id == db.auth_membership.group_id))
|
||||
# if old pydal version, assume this is a relational database which can do joins
|
||||
db_can_join = db.can_join() if hasattr(db, 'can_join') else True
|
||||
if db_can_join:
|
||||
db_group_search = db(
|
||||
(db.auth_membership.user_id == db_user_id) &
|
||||
(db.auth_user.id == db.auth_membership.user_id) &
|
||||
(db.auth_group.id == db.auth_membership.group_id))
|
||||
else:
|
||||
# no joins on NoSQL databases, perform two queries
|
||||
db_group_search = db(db.auth_membership.user_id == db_user_id)
|
||||
group_ids = [x.group_id for x in db_group_search.select(
|
||||
db.auth_membership.group_id, distinct=True)]
|
||||
db_group_search = db(db.auth_group.id.belongs(group_ids))
|
||||
db_groups_of_the_user = list()
|
||||
db_group_id = dict()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
Takes care of adapting pyDAL to web2py's needs
|
||||
--------------------------------------------
|
||||
-----------------------------------------------
|
||||
"""
|
||||
|
||||
from pydal import DAL as DAL
|
||||
|
||||
Submodule gluon/packages/dal updated: 9272062bf1...62eb7767db
@@ -5362,7 +5362,7 @@ class Expose(object):
|
||||
if current.request.raw_args:
|
||||
self.args = [arg for arg in current.request.raw_args.split('/') if arg]
|
||||
else:
|
||||
self.args = [arg for arg in current.request.args if args]
|
||||
self.args = [arg for arg in current.request.args if arg]
|
||||
filename = os.path.join(base, *self.args)
|
||||
if not os.path.exists(filename):
|
||||
raise HTTP(404, "FILE NOT FOUND")
|
||||
|
||||
169
scripts/setup-web2py-ws2012r2.ps1
Normal file
169
scripts/setup-web2py-ws2012r2.ps1
Normal file
@@ -0,0 +1,169 @@
|
||||
"This script will work fine for a few cases 'by default':"
|
||||
" - completely CLEAN WS2012R2 host"
|
||||
" - python 2.7 installed in the default path"
|
||||
" - wfasctgi installed on the default path"
|
||||
"It'll install web2py under the default website "
|
||||
" You can use it as a boilerplate to automate your deployments"
|
||||
" but it still is released AS IT IS. "
|
||||
"BIG FAT WARNING: It will install a bunch of dependecies
|
||||
Inspect the source before executing it"
|
||||
""
|
||||
""
|
||||
$ErrorActionPreference = 'stop'
|
||||
|
||||
$REALLY_SURE = Read-Host "Do you want to start with web2py deployment? [y/N]"
|
||||
if (!@('y', 'Y') -contains $REALLY_SURE) {
|
||||
"Ok, Exiting without doing anything"
|
||||
exit 1
|
||||
}
|
||||
#setting root folder
|
||||
$rootfolder = $pwd
|
||||
|
||||
### utilities - start
|
||||
function ask_a_question($question) {
|
||||
$response = Read-Host "$question [Y/n]"
|
||||
if (@('Y', 'y', '', $null) -contains $response) {
|
||||
return $true
|
||||
} else {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function unzip_me {
|
||||
#Load the assembly
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
|
||||
#Unzip the file
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($pathToZip, $targetDir)
|
||||
}
|
||||
|
||||
|
||||
### utilities - end
|
||||
|
||||
#install 4.5 that is needed for a bunch of things anyway
|
||||
Install-WindowsFeature Net-Framework-45-Core
|
||||
|
||||
#fetch web2py
|
||||
$web2py_url = 'http://www.web2py.com/examples/static/web2py_src.zip'
|
||||
$web2py_file = "$pwd\web2py_src.zip"
|
||||
if (!(Test-Path $web2py_file)) {
|
||||
(new-object net.webclient).DownloadFile($web2py_url, $web2py_file)
|
||||
}
|
||||
#Load the assembly
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
|
||||
#Unzip the file
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($web2py_file, $pwd)
|
||||
|
||||
#features installation (IIS, needed modules, python, chocolatey, etc)
|
||||
$installfeatures = ask_a_question('Do you want to install needed features?')
|
||||
|
||||
if ($installfeatures) {
|
||||
Install-WindowsFeature Web-Server,Web-Default-Doc,Web-Static-Content,Web-Http-Redirect,Web-Http-Logging,Web-Request-Monitor,`
|
||||
Web-Http-Tracing,Web-Stat-Compression,Web-Dyn-Compression,Web-Filtering,Web-Basic-Auth,Web-Windows-Auth,Web-AppInit,`
|
||||
Web-CGI,Web-WebSockets,Web-Mgmt-Console,Web-Net-Ext45
|
||||
}
|
||||
|
||||
$copy_web2py = ask_a_question("Copy web2py to the default website root?")
|
||||
if ($copy_web2py) {
|
||||
Import-Module WebAdministration
|
||||
$available_websites = Get-Website
|
||||
if ($available_websites[0] -eq $null) {
|
||||
$default_one = $available_websites
|
||||
} else {
|
||||
$default_one = $available_websites[0]
|
||||
}
|
||||
$iis_root = [System.Environment]::ExpandEnvironmentVariables($default_one.PhysicalPath)
|
||||
Copy-Item "$rootfolder\web2py\*" $iis_root -Recurse
|
||||
$rootfolder = $iis_root
|
||||
$acl = (Get-Item $rootfolder).GetAccessControl('Access')
|
||||
$identity = "BUILTIN\IIS_IUSRS"
|
||||
$fileSystemRights = "Modify"
|
||||
$inheritanceFlags = "ContainerInherit, ObjectInherit"
|
||||
$propagationFlags = "None"
|
||||
$accessControlType = "Allow"
|
||||
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, $fileSystemRights, $inheritanceFlags, $propagationFlags, $accessControlType)
|
||||
$acl.SetAccessRule($rule)
|
||||
Set-Acl $rootfolder $acl
|
||||
}
|
||||
|
||||
$create_cert = ask_a_question("Do you want to create a self-signed SSL cert?")
|
||||
if ($create_cert) {
|
||||
$cert = New-SelfSignedCertificate -DnsName ("localtest.me","*.localtest.me") -CertStoreLocation cert:\LocalMachine\My
|
||||
$rootStore = Get-Item cert:\LocalMachine\Root
|
||||
$rootStore.Open("ReadWrite")
|
||||
$rootStore.Add($cert)
|
||||
$rootStore.Close();
|
||||
Import-Module WebAdministration
|
||||
Set-Location IIS:\SslBindings
|
||||
New-WebBinding -Name "Default Web Site" -IP "*" -Port 443 -Protocol https
|
||||
$cert | New-Item 0.0.0.0!443
|
||||
Set-Location $pwd
|
||||
}
|
||||
|
||||
"checking for chocolatey"
|
||||
if (Get-Command "choco.exe" -ErrorAction SilentlyContinue)
|
||||
{
|
||||
"chocolatey found"
|
||||
} else {
|
||||
"installing chocolatey"
|
||||
(new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1') | iex
|
||||
}
|
||||
"installing url-rewrite"
|
||||
choco install UrlRewrite
|
||||
$pythonexe = Read-Host 'Python.exe path [C:\Python27\python.exe]'
|
||||
if (($pythonexe -eq '') -or ($pythonexe -eq $null)) {
|
||||
$pythonexe = 'C:\Python27\python.exe'
|
||||
}
|
||||
if (!(Test-Path $pythonexe)) {
|
||||
"ERROR: python executable not found"
|
||||
$pythonwanted = ask_a_question("do you want to install it automatically?")
|
||||
|
||||
if ($pythonwanted) {
|
||||
choco install webpicmd
|
||||
WebpiCmd.exe /Install /Products:WFastCgi_21_279
|
||||
$pythonexe = 'C:\Python27\python.exe'
|
||||
}
|
||||
else {
|
||||
exit 1
|
||||
}
|
||||
|
||||
}
|
||||
$wfastcgipath = Read-Host 'wfastcgi.py path [C:\Python27\Scripts\wfastcgi.py]'
|
||||
if (($wfastcgipath -eq '') -or ($wfastcgipath -eq $null)) {
|
||||
$wfastcgipath = 'C:\Python27\Scripts\wfastcgi.py'
|
||||
}
|
||||
|
||||
if (-not (Test-Path $wfastcgipath)) {
|
||||
"ERROR: wfastcgi.py not found"
|
||||
|
||||
$wfastcgiwanted = ask_a_question("do you want to install it automatically?")
|
||||
if ($wfastcgiwanted) {
|
||||
choco install webpicmd
|
||||
WebpiCmd.exe /Install /Products:WFastCgi_21_279
|
||||
} else {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
$pythondir = Split-Path c:\python27\python.exe
|
||||
#installing dependencies
|
||||
$env:Path = $env:Path + ";$pythondir;$pythondir\Scripts"
|
||||
|
||||
pip install pypiwin32
|
||||
|
||||
$PW = Read-Host 'Web2py Admin Password'
|
||||
|
||||
$appcmdpath = "$env:windir\system32\inetsrv\appcmd.exe"
|
||||
|
||||
& $appcmdpath set config /section:system.webServer/fastCGI "/+[fullPath='$pythonexe', arguments='$wfastcgipath']"
|
||||
& $appcmdpath unlock config -section:system.webServer/handlers
|
||||
|
||||
& cd $rootfolder
|
||||
& $pythonexe -c "from gluon.main import save_password; save_password('$PW',443)"
|
||||
|
||||
$webconfig_template = Join-Path $rootfolder "examples\web.config"
|
||||
$destination = Join-Path $rootfolder "web.config"
|
||||
$scriptprocessor = 'scriptProcessor="{0}|{1}"' -f $pythonexe, $wfastcgipath
|
||||
|
||||
(Get-Content $webconfig_template) | Foreach-Object {$_ -replace 'scriptProcessor="SCRIPT_PROCESSOR"', $scriptprocessor} | where {$_ -ne ""} | Set-Content $destination
|
||||
""
|
||||
"Installation finished. Web2py is available either on http://localhost/ or at https://localtest.me/"
|
||||
""
|
||||
78
scripts/tickets2slack.py
Executable file
78
scripts/tickets2slack.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Post error tickets to slack on a 5 minute schedule.
|
||||
#
|
||||
# Proper use depends on having created a web-hook through Slack, and having set
|
||||
# that value in your app's model as the value of global_settings.slack_hook.
|
||||
# Details on creating web-hooks can be found at https://slack.com/integrations
|
||||
#
|
||||
# requires the Requests module for posting to slack, other requirements are
|
||||
# standard or provided by web2py
|
||||
#
|
||||
# Usage (on Unices), replace myapp with the name of your application and run:
|
||||
# nohup python web2py.py -S myapp -M -R scripts/tickets2slack.py &
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import pickle
|
||||
import json
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError as e:
|
||||
print "missing module 'Requests', aborting."
|
||||
sys.exit(1)
|
||||
|
||||
from gluon import URL
|
||||
from gluon.utils import md5_hash
|
||||
from gluon.restricted import RestrictedError
|
||||
from gluon.settings import global_settings
|
||||
|
||||
|
||||
path = os.path.join(request.folder, 'errors')
|
||||
sent_errors_file = os.path.join(path, 'slack_errors.pickle')
|
||||
hashes = {}
|
||||
if os.path.exists(sent_errors_file):
|
||||
try:
|
||||
with open(sent_errors_file, 'rb') as f:
|
||||
hashes = pickle.load(f)
|
||||
except Exception as _:
|
||||
pass
|
||||
|
||||
# ## CONFIGURE HERE
|
||||
SLEEP_MINUTES = 5
|
||||
ALLOW_DUPLICATES = False
|
||||
global_settings.slack_hook = global_settings.slack_hook or \
|
||||
'https://hooks.slack.com/services/your_service'
|
||||
# ## END CONFIGURATION
|
||||
|
||||
while 1:
|
||||
for file_name in os.listdir(path):
|
||||
if file_name == 'slack_errors.pickle':
|
||||
continue
|
||||
|
||||
if not ALLOW_DUPLICATES:
|
||||
key = md5_hash(file_name)
|
||||
if key in hashes:
|
||||
continue
|
||||
hashes[key] = 1
|
||||
|
||||
error = RestrictedError()
|
||||
|
||||
try:
|
||||
error.load(request, request.application, file_name)
|
||||
except Exception as _:
|
||||
continue # not an exception file?
|
||||
|
||||
url = URL(a='admin', f='ticket', args=[request.application, file],
|
||||
scheme=True)
|
||||
payload = json.dumps(dict(text="Error in %(app)s.\n%(url)s" %
|
||||
dict(app=request.application, url=url)))
|
||||
|
||||
requests.post(global_settings.slack_hook, data=dict(payload=payload))
|
||||
|
||||
with open(sent_errors_file, 'wb') as f:
|
||||
pickle.dump(hashes, f)
|
||||
time.sleep(SLEEP_MINUTES * 60)
|
||||
Reference in New Issue
Block a user