pylons: remove pylons as dependency

- dependencies: bumped:
 -setuptools-scm==1.15.6
 -celery==4.1.0
 -kombu==4.1.0
 -pytz==2017.3
 -Routes==2.4.1

Removed all pylons components. Refactored the code to use only pyramid
parts
This commit is contained in:
Marcin Kuzminski 2017-11-15 13:42:54 +01:00
parent 038bcc5f72
commit 5f9ae2ae11
145 changed files with 925 additions and 1891 deletions

View file

@ -1,12 +0,0 @@
diff -rup celery-2.2.10-orig/setup.py celery-2.2.10/setup.py
--- celery-2.2.10-orig/setup.py 2017-02-25 15:30:34.000000000 +0100
+++ celery-2.2.10/setup.py 2017-02-25 15:30:34.000000000 +0100
@@ -48,7 +48,7 @@ try:
except ImportError:
install_requires.append("importlib")
install_requires.extend([
- "python-dateutil>=1.5.0,<2.0.0",
+ "python-dateutil>=1.5.0,<2.2.0",
"anyjson>=0.3.1",
"kombu>=1.1.2,<2.0.0",
"pyparsing>=1.5.0,<2.0.0",

View file

@ -1,15 +0,0 @@
diff -rup kombu-1.5.1-orig/kombu/utils/__init__.py kombu-1.5.1/kombu/utils/__init__.py
--- kombu-1.5.1-orig/kombu/utils/__init__.py 2016-03-09 15:11:34.000000000 +0100
+++ kombu-1.5.1/kombu/utils/__init__.py 2016-03-09 15:15:52.000000000 +0100
@@ -11,7 +11,10 @@ Internal utilities.
import sys
from time import sleep
-from uuid import UUID, uuid4 as _uuid4, _uuid_generate_random
+from uuid import UUID, uuid4 as _uuid4
+
+# Fix for Python 2.7.11
+_uuid_generate_random = None
from kombu.utils.encoding import safe_repr as _safe_repr

View file

@ -61,23 +61,6 @@ self: super: {
];
});
celery = super.celery.override (attrs: {
# The current version of kombu needs some patching to work with the
# other libs. Should be removed once we update celery and kombu.
patches = [
./patch-celery-dateutil.diff
];
});
kombu = super.kombu.override (attrs: {
# The current version of kombu needs some patching to work with the
# other libs. Should be removed once we update celery and kombu.
patches = [
./patch-kombu-py-2-7-11.diff
./patch-kombu-msgpack.diff
];
});
lxml = super.lxml.override (attrs: {
# johbo: On 16.09 we need this to compile on darwin, otherwise compilation
# fails on Darwin.
@ -133,10 +116,6 @@ self: super: {
};
});
Pylons = super.Pylons.override (attrs: {
name = "Pylons-1.0.2.rhodecode-patch1";
});
pyramid = super.pyramid.override (attrs: {
postFixup = ''
wrapPythonPrograms

View file

@ -184,30 +184,17 @@
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
Pylons = super.buildPythonPackage {
name = "Pylons-1.0.2.dev20171106";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [Routes WebHelpers Beaker Paste PasteDeploy PasteScript FormEncode simplejson decorator nose Mako WebError WebTest Tempita MarkupSafe WebOb];
src = fetchurl {
url = "https://code.rhodecode.com/upstream/pylons/archive/707354ee4261b9c10450404fc9852ccea4fd667d.tar.gz?md5=f26633726fa2cd3a340316ee6a5d218f";
md5 = "f26633726fa2cd3a340316ee6a5d218f";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
Routes = super.buildPythonPackage {
name = "Routes-1.13";
name = "Routes-2.4.1";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [repoze.lru];
propagatedBuildInputs = with self; [six repoze.lru];
src = fetchurl {
url = "https://pypi.python.org/packages/88/d3/259c3b3cde8837eb9441ab5f574a660e8a4acea8f54a078441d4d2acac1c/Routes-1.13.tar.gz";
md5 = "d527b0ab7dd9172b1275a41f97448783";
url = "https://pypi.python.org/packages/33/38/ea827837e68d9c7dde4cff7ec122a93c319f0effc08ce92a17095576603f/Routes-2.4.1.tar.gz";
md5 = "c058dff6832941dec47e0d0052548ad8";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
license = [ pkgs.lib.licenses.mit ];
};
};
SQLAlchemy = super.buildPythonPackage {
@ -340,6 +327,19 @@
license = [ pkgs.lib.licenses.mit ];
};
};
amqp = super.buildPythonPackage {
name = "amqp-2.2.2";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [vine];
src = fetchurl {
url = "https://pypi.python.org/packages/e0/70/9ab9ccd8247fb7d2adb717e9f6a0ed358c9e1ab2c349048b0352f9e80ee2/amqp-2.2.2.tar.gz";
md5 = "0971a3fd2d635ded45c349cfc17106bd";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
amqplib = super.buildPythonPackage {
name = "amqplib-1.0.2";
buildInputs = with self; [];
@ -353,19 +353,6 @@
license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
};
};
anyjson = super.buildPythonPackage {
name = "anyjson-0.3.3";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/c3/4d/d4089e1a3dd25b46bebdb55a992b0797cff657b4477bc32ce28038fdecbc/anyjson-0.3.3.tar.gz";
md5 = "2ea28d6ec311aeeebaf993cb3008b27c";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
appenlight-client = super.buildPythonPackage {
name = "appenlight-client-0.6.22";
buildInputs = with self; [];
@ -418,6 +405,19 @@
license = [ pkgs.lib.licenses.mit ];
};
};
billiard = super.buildPythonPackage {
name = "billiard-3.5.0.3";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/39/ac/f5571210cca2e4f4532e38aaff242f26c8654c5e2436bee966c230647ccc/billiard-3.5.0.3.tar.gz";
md5 = "113ba481e48400adbf6fbbf59a2f8554";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
bleach = super.buildPythonPackage {
name = "bleach-1.5.0";
buildInputs = with self; [];
@ -458,13 +458,13 @@
};
};
celery = super.buildPythonPackage {
name = "celery-2.2.10";
name = "celery-4.1.0";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [python-dateutil anyjson kombu pyparsing];
propagatedBuildInputs = with self; [pytz billiard kombu];
src = fetchurl {
url = "https://pypi.python.org/packages/b1/64/860fd50e45844c83442e7953effcddeff66b2851d90b2d784f7201c111b8/celery-2.2.10.tar.gz";
md5 = "898bc87e54f278055b561316ba73e222";
url = "https://pypi.python.org/packages/07/65/88a2a45fc80f487872c93121a701a53bbbc3d3d832016876fac84fc8d46a/celery-4.1.0.tar.gz";
md5 = "db91e1d26936381127f01e150fe3054a";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
@ -1004,13 +1004,13 @@
};
};
kombu = super.buildPythonPackage {
name = "kombu-1.5.1";
name = "kombu-4.1.0";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [anyjson amqplib];
propagatedBuildInputs = with self; [amqp];
src = fetchurl {
url = "https://pypi.python.org/packages/19/53/74bf2a624644b45f0850a638752514fc10a8e1cbd738f10804951a6df3f5/kombu-1.5.1.tar.gz";
md5 = "50662f3c7e9395b3d0721fb75d100b63";
url = "https://pypi.python.org/packages/03/5e/1a47d1e543d4943d65330af4e4406049f443878818fb65bfdc651bb93a96/kombu-4.1.0.tar.gz";
md5 = "2fb2be9fec0e6514231bba23a3779439";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
@ -1094,19 +1094,6 @@
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
nose = super.buildPythonPackage {
name = "nose-1.3.6";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/70/c7/469e68148d17a0d3db5ed49150242fd70a74a8147b8f3f8b87776e028d99/nose-1.3.6.tar.gz";
md5 = "0ca546d81ca8309080fc80cb389e7a16";
};
meta = {
license = [ { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "GNU LGPL"; } ];
};
};
objgraph = super.buildPythonPackage {
name = "objgraph-3.1.1";
buildInputs = with self; [];
@ -1173,13 +1160,13 @@
};
};
pexpect = super.buildPythonPackage {
name = "pexpect-4.2.1";
name = "pexpect-4.3.0";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [ptyprocess];
src = fetchurl {
url = "https://pypi.python.org/packages/e8/13/d0b0599099d6cd23663043a2a0bb7c61e58c6ba359b2656e6fb000ef5b98/pexpect-4.2.1.tar.gz";
md5 = "3694410001a99dff83f0b500a1ca1c95";
url = "https://pypi.python.org/packages/f8/44/5466c30e49762bb92e442bbdf4472d6904608d211258eb3198a11f0309a4/pexpect-4.3.0.tar.gz";
md5 = "047a486dcd26134b74f2e67046bb61a0";
};
meta = {
license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
@ -1550,16 +1537,16 @@
};
};
python-dateutil = super.buildPythonPackage {
name = "python-dateutil-2.1";
name = "python-dateutil-2.6.1";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [six];
src = fetchurl {
url = "https://pypi.python.org/packages/65/52/9c18dac21f174ad31b65e22d24297864a954e6fe65876eba3f5773d2da43/python-dateutil-2.1.tar.gz";
md5 = "1534bb15cf311f07afaa3aacba1c028b";
url = "https://pypi.python.org/packages/54/bb/f1db86504f7a49e1d9b9301531181b00a1c7325dc85a29160ee3eaa73a54/python-dateutil-2.6.1.tar.gz";
md5 = "db38f6b4511cefd76014745bb0cc45a4";
};
meta = {
license = [ { fullName = "Simplified BSD"; } ];
license = [ pkgs.lib.licenses.bsdOriginal { fullName = "Simplified BSD"; } ];
};
};
python-editor = super.buildPythonPackage {
@ -1615,13 +1602,13 @@
};
};
pytz = super.buildPythonPackage {
name = "pytz-2015.4";
name = "pytz-2017.3";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/7e/1a/f43b5c92df7b156822030fed151327ea096bcf417e45acc23bd1df43472f/pytz-2015.4.zip";
md5 = "233f2a2b370d03f9b5911700cc9ebf3c";
url = "https://pypi.python.org/packages/60/88/d3152c234da4b2a1f7a989f89609ea488225eaea015bc16fbde2b3fdfefa/pytz-2017.3.zip";
md5 = "7006b56c0d68a162d9fe57d4249c3171";
};
meta = {
license = [ pkgs.lib.licenses.mit ];
@ -1696,7 +1683,7 @@
name = "rhodecode-enterprise-ce-4.11.0";
buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage configobj];
doCheck = true;
propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments pygments-markdown-lexer Pylons Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic cssselect celery channelstream colander decorator deform docutils gevent gunicorn infrae.cache ipython iso8601 kombu lxml msgpack-python nbconvert packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client redis repoze.lru requests simplejson sshpubkeys subprocess32 waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt];
propagatedBuildInputs = with self; [setuptools-scm amqplib amqp authomatic Babel Beaker celery Chameleon channelstream click colander configobj cssselect decorator deform docutils dogpile.cache dogpile.core ecdsa FormEncode future futures gnureadline infrae.cache iso8601 itsdangerous Jinja2 billiard kombu lxml Mako Markdown MarkupSafe msgpack-python MySQL-python objgraph packaging Paste PasteDeploy PasteScript pathlib2 peppercorn psutil psycopg2 py-bcrypt pycrypto pycurl pyflakes pygments-markdown-lexer Pygments pyparsing pyramid-beaker pyramid-debugtoolbar pyramid-jinja2 pyramid-mako pyramid pysqlite python-dateutil python-ldap python-memcached python-pam pytz pyzmq py-gfm recaptcha-client redis repoze.lru requests Routes setproctitle simplejson six SQLAlchemy sshpubkeys subprocess32 Tempita translationstring trollius urllib3 URLObject venusian WebError WebHelpers2 WebHelpers WebOb Whoosh wsgiref zope.cachedescriptors zope.deprecation zope.event zope.interface nbconvert bleach nbformat jupyter-client alembic invoke bumpversion transifex-client gevent greenlet gunicorn waitress uWSGI ipdb ipython CProfileV bottle rhodecode-tools appenlight-client pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage];
src = ./.;
meta = {
license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
@ -1755,13 +1742,13 @@
};
};
setuptools-scm = super.buildPythonPackage {
name = "setuptools-scm-1.15.0";
name = "setuptools-scm-1.15.6";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/80/b7/31b6ae5fcb188e37f7e31abe75f9be90490a5456a72860fa6e643f8a3cbc/setuptools_scm-1.15.0.tar.gz";
md5 = "b6916c78ed6253d6602444fad4279c5b";
url = "https://pypi.python.org/packages/03/6d/aafdd01edd227ee879b691455bf19895091872af7e48192bea1758c82032/setuptools_scm-1.15.6.tar.gz";
md5 = "f17493d53f0d842bb0152f214775640b";
};
meta = {
license = [ pkgs.lib.licenses.mit ];
@ -1949,6 +1936,19 @@
license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
};
};
vine = super.buildPythonPackage {
name = "vine-1.1.4";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/32/23/36284986e011f3c130d802c3c66abd8f1aef371eae110ddf80c5ae22e1ff/vine-1.1.4.tar.gz";
md5 = "9fdb971e7fd15b181b84f3bfcf20d11c";
};
meta = {
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
waitress = super.buildPythonPackage {
name = "waitress-1.1.0";
buildInputs = with self; [];

View file

@ -1,13 +1,13 @@
## core
setuptools==30.1.0
setuptools-scm==1.15.0
setuptools-scm==1.15.6
amqplib==1.0.2
anyjson==0.3.3
amqp==2.2.2
authomatic==0.1.0.post1
Babel==1.3
Beaker==1.9.0
celery==2.2.10
celery==4.1.0
Chameleon==2.24
channelstream==0.5.2
click==6.6
@ -28,7 +28,8 @@ infrae.cache==1.0.1
iso8601==0.1.12
itsdangerous==0.24
Jinja2==2.9.6
kombu==1.5.1
billiard==3.5.0.3
kombu==4.1.0
lxml==3.7.3
Mako==1.0.7
Markdown==2.6.9
@ -57,18 +58,18 @@ pyramid-jinja2==2.7
pyramid-mako==1.0.2
pyramid==1.9.1
pysqlite==2.8.3
python-dateutil==2.1
python-dateutil
python-ldap==2.4.45
python-memcached==1.58
python-pam==1.8.2
pytz==2015.4
pytz==2017.3
pyzmq==14.6.0
py-gfm==0.1.3
recaptcha-client==1.0.6
redis==2.10.6
repoze.lru==0.7
requests==2.9.1
Routes==1.13
Routes==2.4.1
setproctitle==1.1.10
simplejson==3.11.1
six==1.11.0
@ -92,10 +93,6 @@ zope.deprecation==4.1.2
zope.event==4.0.3
zope.interface==4.1.3
## customized/patched libs
# our patched version of Pylons==1.0.2
https://code.rhodecode.com/upstream/pylons/archive/707354ee4261b9c10450404fc9852ccea4fd667d.tar.gz?md5=f26633726fa2cd3a340316ee6a5d218f#egg=Pylons==1.0.2.rhodecode-patch-1
# IPYTHON RENDERING
# entrypoints backport, pypi version doesn't support egg installs

View file

@ -27,7 +27,7 @@ from rhodecode.tests import TEST_USER_ADMIN_LOGIN
@pytest.fixture(scope="class")
def testuser_api(request, pylonsapp):
def testuser_api(request, baseapp):
cls = request.cls
# ADMIN USER

View file

@ -159,32 +159,14 @@ class BaseAppView(object):
return c
def _register_global_c(self, tmpl_args):
"""
Registers attributes to pylons global `c`
"""
# TODO(marcink): remove once pyramid migration is finished
from pylons import tmpl_context as c
try:
for k, v in tmpl_args.items():
setattr(c, k, v)
except TypeError:
log.exception('Failed to register pylons C')
pass
def _get_template_context(self, tmpl_args):
self._register_global_c(tmpl_args)
def _get_template_context(self, tmpl_args, **kwargs):
local_tmpl_args = {
'defaults': {},
'errors': {},
# register a fake 'c' to be used in templates instead of global
# pylons c, after migration to pyramid we should rename it to 'c'
# make sure we replace usage of _c in templates too
'_c': tmpl_args
'c': tmpl_args
}
local_tmpl_args.update(tmpl_args)
local_tmpl_args.update(kwargs)
return local_tmpl_args
def load_default_context(self):
@ -194,7 +176,7 @@ class BaseAppView(object):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.custom_var = 'foobar'
self._register_global_c(c)
return c
"""
raise NotImplementedError('Needs implementation in view class')
@ -213,7 +195,7 @@ class RepoAppView(BaseAppView):
'Requirements are missing for repository %s: %s',
self.db_repo_name, error.message)
def _get_local_tmpl_context(self, include_app_defaults=False):
def _get_local_tmpl_context(self, include_app_defaults=True):
_ = self.request.translate
c = super(RepoAppView, self)._get_local_tmpl_context(
include_app_defaults=include_app_defaults)
@ -336,7 +318,7 @@ class BaseReferencesView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
def load_refs_context(self, ref_items, partials_template):

View file

@ -25,7 +25,6 @@ import collections
from zope.interface import implementer
from rhodecode.apps.admin.interfaces import IAdminNavigationRegistry
from rhodecode.lib.utils import get_registry
from rhodecode.lib.utils2 import str2bool
from rhodecode.translation import _
@ -116,7 +115,7 @@ def navigation_registry(request, registry=None):
"""
Helper that returns the admin navigation registry.
"""
pyramid_registry = registry or get_registry(request)
pyramid_registry = registry or request.registry
nav_registry = pyramid_registry.queryUtility(IAdminNavigationRegistry)
return nav_registry

View file

@ -46,10 +46,11 @@ def route_path(name, params=None, **kwargs):
return base_url
class TestAdminController(TestController):
@pytest.mark.usefixtures('app')
class TestAdminController(object):
@pytest.fixture(scope='class', autouse=True)
def prepare(self, request, pylonsapp):
def prepare(self, request, baseapp):
UserLog.query().delete()
Session().commit()
@ -84,104 +85,87 @@ class TestAdminController(TestController):
UserLog.query().delete()
Session().commit()
def test_index(self):
self.log_user()
def test_index(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs'))
response.mustcontain('Admin audit logs')
def test_filter_all_entries(self):
self.log_user()
def test_filter_all_entries(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs'))
all_count = UserLog.query().count()
response.mustcontain('%s entries' % all_count)
def test_filter_journal_filter_exact_match_on_repository(self):
self.log_user()
def test_filter_journal_filter_exact_match_on_repository(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:rhodecode')))
response.mustcontain('3 entries')
def test_filter_journal_filter_exact_match_on_repository_CamelCase(self):
self.log_user()
def test_filter_journal_filter_exact_match_on_repository_CamelCase(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:RhodeCode')))
response.mustcontain('3 entries')
def test_filter_journal_filter_wildcard_on_repository(self):
self.log_user()
def test_filter_journal_filter_wildcard_on_repository(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:*test*')))
response.mustcontain('862 entries')
def test_filter_journal_filter_prefix_on_repository(self):
self.log_user()
def test_filter_journal_filter_prefix_on_repository(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:test*')))
response.mustcontain('257 entries')
def test_filter_journal_filter_prefix_on_repository_CamelCase(self):
self.log_user()
def test_filter_journal_filter_prefix_on_repository_CamelCase(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:Test*')))
response.mustcontain('257 entries')
def test_filter_journal_filter_prefix_on_repository_and_user(self):
self.log_user()
def test_filter_journal_filter_prefix_on_repository_and_user(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:test* AND username:demo')))
response.mustcontain('130 entries')
def test_filter_journal_filter_prefix_on_repository_or_target_repo(self):
self.log_user()
def test_filter_journal_filter_prefix_on_repository_or_target_repo(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='repository:test* OR repository:rhodecode')))
response.mustcontain('260 entries') # 257 + 3
def test_filter_journal_filter_exact_match_on_username(self):
self.log_user()
def test_filter_journal_filter_exact_match_on_username(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='username:demo')))
response.mustcontain('1087 entries')
def test_filter_journal_filter_exact_match_on_username_camelCase(self):
self.log_user()
def test_filter_journal_filter_exact_match_on_username_camelCase(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='username:DemO')))
response.mustcontain('1087 entries')
def test_filter_journal_filter_wildcard_on_username(self):
self.log_user()
def test_filter_journal_filter_wildcard_on_username(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='username:*test*')))
entries_count = UserLog.query().filter(UserLog.username.ilike('%test%')).count()
response.mustcontain('{} entries'.format(entries_count))
def test_filter_journal_filter_prefix_on_username(self):
self.log_user()
def test_filter_journal_filter_prefix_on_username(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='username:demo*')))
response.mustcontain('1101 entries')
def test_filter_journal_filter_prefix_on_user_or_other_user(self):
self.log_user()
def test_filter_journal_filter_prefix_on_user_or_other_user(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='username:demo OR username:volcan')))
response.mustcontain('1095 entries') # 1087 + 8
def test_filter_journal_filter_wildcard_on_action(self):
self.log_user()
def test_filter_journal_filter_wildcard_on_action(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='action:*pull_request*')))
response.mustcontain('187 entries')
def test_filter_journal_filter_on_date(self):
self.log_user()
def test_filter_journal_filter_on_date(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='date:20121010')))
response.mustcontain('47 entries')
def test_filter_journal_filter_on_date_2(self):
self.log_user()
def test_filter_journal_filter_on_date_2(self, autologin_user):
response = self.app.get(route_path('admin_audit_logs',
params=dict(filter='date:20121020')))
response.mustcontain('17 entries')

View file

@ -429,7 +429,7 @@ class TestAdminSettingsVcs(object):
# TODO: johbo: What we really want is to checkpoint before a test run and
# reset the session afterwards.
@pytest.fixture(scope='class', autouse=True)
def cleanup_settings(self, request, pylonsapp):
def cleanup_settings(self, request, baseapp):
ui_id = RhodeCodeUi.ui_id
original_ids = list(
r.ui_id for r in RhodeCodeUi.query().values(ui_id))

View file

@ -23,7 +23,6 @@ from sqlalchemy.orm.exc import NoResultFound
from rhodecode.lib import auth
from rhodecode.lib import helpers as h
from rhodecode.model import validators
from rhodecode.model.db import User, UserApiKeys, UserEmailMap, Repository
from rhodecode.model.meta import Session
from rhodecode.model.user import UserModel
@ -386,8 +385,7 @@ class TestAdminUsersView(TestController):
'csrf_token': self.csrf_token,
})
msg = validators.ValidUsername(
False, {})._messages['system_invalid_username']
msg = '???'
msg = h.html_escape(msg % {'username': 'new_user'})
response.mustcontain('<span class="error-message">%s</span>' % msg)
response.mustcontain(

View file

@ -36,7 +36,6 @@ log = logging.getLogger(__name__)
class AdminAuditLogsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -44,7 +44,7 @@ class AdminDefaultSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -79,7 +79,7 @@ class AdminDefaultSettingsView(BaseAppView):
_ = self.request.translate
c = self.load_default_context()
c.active = 'repositories'
form = DefaultsForm()()
form = DefaultsForm(self.request.translate)()
try:
form_result = form.to_python(dict(self.request.POST))

View file

@ -35,7 +35,7 @@ class OpenSourceLicensesAdminSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -54,7 +54,7 @@ class AdminPermissionsView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
PermissionModel().set_global_permission_choices(
c, gettext_translator=self.request.translate)
return c
@ -100,6 +100,7 @@ class AdminPermissionsView(BaseAppView, DataGridAppView):
c.active = 'application'
_form = ApplicationPermissionsForm(
self.request.translate,
[x[0] for x in c.register_choices],
[x[0] for x in c.password_reset_choices],
[x[0] for x in c.extern_activate_choices])()
@ -180,6 +181,7 @@ class AdminPermissionsView(BaseAppView, DataGridAppView):
c.active = 'objects'
_form = ObjectPermissionsForm(
self.request.translate,
[x[0] for x in c.repo_perms_choices],
[x[0] for x in c.group_perms_choices],
[x[0] for x in c.user_group_perms_choices])()
@ -251,6 +253,7 @@ class AdminPermissionsView(BaseAppView, DataGridAppView):
c.active = 'global'
_form = UserPermissionsForm(
self.request.translate,
[x[0] for x in c.repo_create_choices],
[x[0] for x in c.repo_create_on_write_choices],
[x[0] for x in c.repo_group_create_choices],
@ -395,6 +398,7 @@ class AdminPermissionsView(BaseAppView, DataGridAppView):
renderer='json_ext', xhr=True)
def ssh_keys_data(self):
_ = self.request.translate
self.load_default_context()
column_map = {
'fingerprint': 'ssh_key_fingerprint',
'username': User.username

View file

@ -35,7 +35,7 @@ log = logging.getLogger(__name__)
class AdminProcessManagementView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -47,7 +47,7 @@ class AdminRepoGroupsView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
def _load_form_data(self, c):
@ -150,8 +150,9 @@ class AdminRepoGroupsView(BaseAppView, DataGridAppView):
# permissions for can create group based on parent_id are checked
# here in the Form
available_groups = map(lambda k: safe_unicode(k[0]), c.repo_groups)
repo_group_form = RepoGroupForm(available_groups=available_groups,
can_create_in_root=can_create)()
repo_group_form = RepoGroupForm(
self.request.translate, available_groups=available_groups,
can_create_in_root=can_create)()
repo_group_name = self.request.POST.get('group_name')
try:

View file

@ -49,7 +49,7 @@ class AdminReposView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
def _load_form_data(self, c):
@ -148,9 +148,10 @@ class AdminReposView(BaseAppView, DataGridAppView):
try:
# CanWriteToGroup validators checks permissions of this POST
form_result = RepoForm(repo_groups=c.repo_groups_choices,
landing_revs=c.landing_revs_choices)()\
.to_python(dict(self.request.POST))
form = RepoForm(
self.request.translate, repo_groups=c.repo_groups_choices,
landing_revs=c.landing_revs_choices)()
form_results = form.to_python(dict(self.request.POST))
# create is done sometimes async on celery, db transaction
# management is handled there.

View file

@ -39,7 +39,7 @@ class AdminSessionSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -67,7 +67,7 @@ class AdminSettingsView(BaseAppView):
c.labs_active = str2bool(
rhodecode.CONFIG.get('labs_settings_active', 'true'))
c.navlist = navigation_list(self.request)
self._register_global_c(c)
return c
@classmethod
@ -153,7 +153,7 @@ class AdminSettingsView(BaseAppView):
settings = self.request.registry.settings
c.svn_proxy_generate_config = settings[generate_config]
application_form = ApplicationUiSettingsForm()()
application_form = ApplicationUiSettingsForm(self.request.translate)()
try:
form_result = application_form.to_python(dict(self.request.POST))
@ -310,7 +310,7 @@ class AdminSettingsView(BaseAppView):
c.active = 'global'
c.personal_repo_group_default_pattern = RepoGroupModel()\
.get_personal_group_name_pattern()
application_form = ApplicationSettingsForm()()
application_form = ApplicationSettingsForm(self.request.translate)()
try:
form_result = application_form.to_python(dict(self.request.POST))
except formencode.Invalid as errors:
@ -382,7 +382,7 @@ class AdminSettingsView(BaseAppView):
_ = self.request.translate
c = self.load_default_context()
c.active = 'visual'
application_form = ApplicationVisualisationForm()()
application_form = ApplicationVisualisationForm(self.request.translate)()
try:
form_result = application_form.to_python(dict(self.request.POST))
except formencode.Invalid as errors:
@ -482,7 +482,7 @@ class AdminSettingsView(BaseAppView):
settings_model = IssueTrackerSettingsModel()
try:
form = IssueTrackerPatternsForm()().to_python(self.request.POST)
form = IssueTrackerPatternsForm(self.request.translate)().to_python(self.request.POST)
except formencode.Invalid as errors:
log.exception('Failed to add new pattern')
error = errors
@ -698,7 +698,7 @@ class AdminSettingsView(BaseAppView):
c = self.load_default_context()
c.active = 'labs'
application_form = LabsSettingsForm()()
application_form = LabsSettingsForm(self.request.translate)()
try:
form_result = application_form.to_python(dict(self.request.POST))
except formencode.Invalid as errors:

View file

@ -40,7 +40,7 @@ log = logging.getLogger(__name__)
class AdminSystemInfoSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@staticmethod

View file

@ -53,7 +53,7 @@ class AdminUserGroupsView(BaseAppView, DataGridAppView):
PermissionModel().set_global_permission_choices(
c, gettext_translator=self.request.translate)
self._register_global_c(c)
return c
# permission check in data loading of
@ -196,7 +196,7 @@ class AdminUserGroupsView(BaseAppView, DataGridAppView):
def user_groups_create(self):
_ = self.request.translate
c = self.load_default_context()
users_group_form = UserGroupForm()()
users_group_form = UserGroupForm(self.request.translate)()
user_group_name = self.request.POST.get('users_group_name')
try:

View file

@ -44,7 +44,8 @@ from rhodecode.lib import helpers as h
from rhodecode.lib.utils2 import safe_int, safe_unicode, AttributeDict
from rhodecode.model.auth_token import AuthTokenModel
from rhodecode.model.forms import (
UserForm, UserIndividualPermissionsForm, UserPermissionsForm)
UserForm, UserIndividualPermissionsForm, UserPermissionsForm,
UserExtraEmailForm, UserExtraIpForm)
from rhodecode.model.permission import PermissionModel
from rhodecode.model.repo_group import RepoGroupModel
from rhodecode.model.ssh_key import SshKeyModel
@ -62,7 +63,6 @@ class AdminUsersView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -191,7 +191,7 @@ class AdminUsersView(BaseAppView, DataGridAppView):
c = self.load_default_context()
c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
user_model = UserModel()
user_form = UserForm()()
user_form = UserForm(self.request.translate)()
try:
form_result = user_form.to_python(dict(self.request.POST))
user = user_model.create(form_result)
@ -259,7 +259,7 @@ class UsersView(UserAppView):
PermissionModel().set_global_permission_choices(
c, gettext_translator=req.translate)
self._register_global_c(c)
return c
@LoginRequired()
@ -280,7 +280,8 @@ class UsersView(UserAppView):
c.extern_name = c.user.extern_name
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
available_languages = [x[0] for x in c.allowed_languages]
_form = UserForm(edit=True, available_languages=available_languages,
_form = UserForm(self.request.translate, edit=True,
available_languages=available_languages,
old_data={'user_id': user_id,
'email': c.user.email})()
form_result = {}
@ -538,7 +539,7 @@ class UsersView(UserAppView):
c.active = 'global_perms'
try:
# first stage that verifies the checkbox
_form = UserIndividualPermissionsForm()
_form = UserIndividualPermissionsForm(self.request.translate)
form_result = _form.to_python(dict(self.request.POST))
inherit_perms = form_result['inherit_default_permissions']
c.user.inherit_default_permissions = inherit_perms
@ -547,6 +548,7 @@ class UsersView(UserAppView):
if not inherit_perms:
# only update the individual ones if we un check the flag
_form = UserPermissionsForm(
self.request.translate,
[x[0] for x in c.repo_create_choices],
[x[0] for x in c.repo_create_on_write_choices],
[x[0] for x in c.repo_group_create_choices],
@ -914,6 +916,11 @@ class UsersView(UserAppView):
email = self.request.POST.get('new_email')
user_data = c.user.get_api_data()
try:
form = UserExtraEmailForm(self.request.translate)()
data = form.to_python({'email': email})
email = data['email']
UserModel().add_extra_email(c.user.user_id, email)
audit_logger.store_web(
'user.edit.email.add',
@ -1009,6 +1016,10 @@ class UsersView(UserAppView):
user_data = c.user.get_api_data()
for ip in ip_list:
try:
form = UserExtraIpForm(self.request.translate)()
data = form.to_python({'ip': ip})
ip = data['ip']
user_model.add_extra_ip(c.user.user_id, ip, desc)
audit_logger.store_web(
'user.edit.ip.add',

View file

@ -24,6 +24,7 @@ import uuid
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPBadRequest, HTTPForbidden, HTTPBadGateway
from rhodecode.apps._base import BaseAppView
from rhodecode.lib.channelstream import (
channelstream_request,
ChannelstreamConnectionException,
@ -34,28 +35,28 @@ from rhodecode.lib.channelstream import (
parse_channels_info,
update_history_from_logs,
STATE_PUBLIC_KEYS)
from rhodecode.lib.auth import NotAnonymous
log = logging.getLogger(__name__)
class ChannelstreamView(object):
def __init__(self, context, request):
self.context = context
self.request = request
class ChannelstreamView(BaseAppView):
# Some of the decorators rely on this attribute to be present
# on the class of the decorated method.
self._rhodecode_user = request.user
registry = request.registry
self.channelstream_config = registry.rhodecode_plugins['channelstream']
def load_default_context(self):
c = self._get_local_tmpl_context()
self.channelstream_config = \
self.request.registry.rhodecode_plugins['channelstream']
if not self.channelstream_config.get('enabled'):
log.error('Channelstream plugin is disabled')
raise HTTPBadRequest()
return c
@NotAnonymous()
@view_config(route_name='channelstream_connect', renderer='json')
@view_config(route_name='channelstream_connect', renderer='json_ext')
def connect(self):
self.load_default_context()
""" handle authorization of users trying to connect """
try:
json_body = self.request.json_body
@ -122,9 +123,10 @@ class ChannelstreamView(object):
return connect_result
@NotAnonymous()
@view_config(route_name='channelstream_subscribe', renderer='json')
@view_config(route_name='channelstream_subscribe', renderer='json_ext')
def subscribe(self):
""" can be used to subscribe specific connection to other channels """
self.load_default_context()
try:
json_body = self.request.json_body
except Exception:

View file

@ -31,7 +31,7 @@ log = logging.getLogger(__name__)
class DebugStyleView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@view_config(

View file

@ -67,7 +67,7 @@ class GistView(BaseAppView):
(Gist.ACL_LEVEL_PUBLIC, _("Can be accessed by anonymous users"))
]
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -66,7 +66,7 @@ class TestGotoSwitcherData(TestController):
]
@pytest.fixture(autouse=True, scope='class')
def prepare(self, request, pylonsapp):
def prepare(self, request, baseapp):
for repo_and_group in self.required_repos_with_groups:
# create structure of groups and return the last group

View file

@ -46,7 +46,7 @@ class HomeView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.user = c.auth_user.get_instance()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -47,7 +47,7 @@ class JournalView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context(include_app_defaults=True)
self._register_global_c(c)
self._load_defaults(c.rhodecode_name)
# TODO(marcink): what is this, why we need a global register ?
@ -146,7 +146,8 @@ class JournalView(BaseAppView):
user = AttributeDict({'short_contact': entry.username,
'email': '',
'full_contact': ''})
action, action_extra, ico = h.action_parser(entry, feed=True)
action, action_extra, ico = h.action_parser(
self.request, entry, feed=True)
title = "%s - %s %s" % (user.short_contact, action(),
entry.repository.repo_name)
desc = action_extra()
@ -191,7 +192,8 @@ class JournalView(BaseAppView):
user = AttributeDict({'short_contact': entry.username,
'email': '',
'full_contact': ''})
action, action_extra, ico = h.action_parser(entry, feed=True)
action, action_extra, ico = h.action_parser(
self.request, entry, feed=True)
title = "%s - %s %s" % (user.short_contact, action(),
entry.repository.repo_name)
desc = action_extra()

View file

@ -30,7 +30,6 @@ from rhodecode.tests.fixture import Fixture
from rhodecode.lib.auth import check_password
from rhodecode.lib import helpers as h
from rhodecode.model.auth_token import AuthTokenModel
from rhodecode.model import validators
from rhodecode.model.db import User, Notification, UserApiKeys
from rhodecode.model.meta import Session
@ -234,7 +233,7 @@ class TestLoginController(object):
)
assertr = response.assert_response()
msg = validators.ValidUsername()._messages['username_exists']
msg = '???'
msg = msg % {'username': uname}
assertr.element_contains('#username+.error-message', msg)
@ -252,7 +251,7 @@ class TestLoginController(object):
)
assertr = response.assert_response()
msg = validators.UniqSystemEmail()()._messages['email_taken']
msg = '???'
assertr.element_contains('#email+.error-message', msg)
def test_register_err_same_email_case_sensitive(self):
@ -268,7 +267,7 @@ class TestLoginController(object):
}
)
assertr = response.assert_response()
msg = validators.UniqSystemEmail()()._messages['email_taken']
msg = '???'
assertr.element_contains('#email+.error-message', msg)
def test_register_err_wrong_data(self):
@ -322,7 +321,7 @@ class TestLoginController(object):
)
assertr = response.assert_response()
msg = validators.ValidUsername()._messages['username_exists']
msg = '???'
msg = msg % {'username': usr}
assertr.element_contains('#username+.error-message', msg)
@ -339,7 +338,7 @@ class TestLoginController(object):
}
)
msg = validators.ValidPassword()._messages['invalid_password']
msg = '???'
response.mustcontain(msg)
def test_register_password_mismatch(self):
@ -354,7 +353,7 @@ class TestLoginController(object):
'lastname': 'test'
}
)
msg = validators.ValidPasswordsMatch()._messages['password_mismatch']
msg = '???'
response.mustcontain(msg)
def test_register_ok(self):

View file

@ -113,7 +113,7 @@ class LoginView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.came_from = get_came_from(self.request)
self._register_global_c(c)
return c
def _get_captcha_data(self):
@ -157,7 +157,7 @@ class LoginView(BaseAppView):
def login_post(self):
c = self.load_default_context()
login_form = LoginForm()()
login_form = LoginForm(self.request.translate)()
try:
self.session.invalidate()
@ -182,11 +182,10 @@ class LoginView(BaseAppView):
defaults = errors.value
# remove password from filling in form again
defaults.pop('password', None)
render_ctx = self._get_template_context(c)
render_ctx.update({
render_ctx = {
'errors': errors.error_dict,
'defaults': defaults,
})
}
audit_user = audit_logger.UserWrap(
username=self.request.POST.get('username'),
@ -195,7 +194,7 @@ class LoginView(BaseAppView):
audit_logger.store_web(
'user.login.failure', action_data=action_data,
user=audit_user, commit=True)
return render_ctx
return self._get_template_context(c, **render_ctx)
except UserCreationError as e:
# headers auth or other auth functions that create users on
@ -255,7 +254,7 @@ class LoginView(BaseAppView):
auto_active = 'hg.register.auto_activate' in User.get_default_user()\
.AuthUser().permissions['global']
register_form = RegisterForm()()
register_form = RegisterForm(self.request.translate)()
try:
form_result = register_form.to_python(self.request.POST)
@ -324,7 +323,7 @@ class LoginView(BaseAppView):
queue='error')
return HTTPFound(self.request.route_path('reset_password'))
password_reset_form = PasswordResetForm()()
password_reset_form = PasswordResetForm(self.request.translate)()
try:
form_result = password_reset_form.to_python(
self.request.POST)

View file

@ -198,8 +198,6 @@ class TestMyAccountEdit(TestController):
params=params)
response.mustcontain('An email address must contain a single @')
from rhodecode.model import validators
msg = validators.ValidUsername(
edit=False, old_data={})._messages['username_exists']
msg = '???'
msg = h.html_escape(msg % {'username': 'test_admin'})
response.mustcontain(u"%s" % msg)

View file

@ -42,7 +42,7 @@ from rhodecode.model.comment import CommentsModel
from rhodecode.model.db import (
Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload,
PullRequest)
from rhodecode.model.forms import UserForm
from rhodecode.model.forms import UserForm, UserExtraEmailForm
from rhodecode.model.meta import Session
from rhodecode.model.pull_request import PullRequestModel
from rhodecode.model.scm import RepoList
@ -64,7 +64,7 @@ class MyAccountView(BaseAppView, DataGridAppView):
c = self._get_local_tmpl_context()
c.user = c.auth_user.get_instance()
c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
self._register_global_c(c)
return c
@LoginRequired()
@ -245,6 +245,10 @@ class MyAccountView(BaseAppView, DataGridAppView):
email = self.request.POST.get('new_email')
try:
form = UserExtraEmailForm(self.request.translate)()
data = form.to_python({'email': email})
email = data['email']
UserModel().add_extra_email(c.user.user_id, email)
audit_logger.store_web(
'user.edit.email.add', action_data={
@ -442,7 +446,7 @@ class MyAccountView(BaseAppView, DataGridAppView):
c.extern_type = c.user.extern_type
c.extern_name = c.user.extern_name
_form = UserForm(edit=True,
_form = UserForm(self.request.translate, edit=True,
old_data={'user_id': self._rhodecode_user.user_id,
'email': self._rhodecode_user.email})()
form_result = {}

View file

@ -43,7 +43,7 @@ class MyAccountNotificationsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.user = c.auth_user.get_instance()
self._register_global_c(c)
return c
def _has_permissions(self, notification):

View file

@ -44,7 +44,7 @@ class MyAccountSshKeysView(BaseAppView, DataGridAppView):
c.ssh_enabled = self.request.registry.settings.get(
'ssh.generate_authorized_keyfile')
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -36,7 +36,7 @@ def admin_routes(config):
def includeme(config):
config.include(admin_routes, route_prefix=ADMIN_PREFIX + '/ops')
# make OLD entries from pylons work
# make OLD entries from <4.10.0 work
config.add_route(
name='ops_ping_legacy', pattern=ADMIN_PREFIX + '/ping')
config.add_route(

View file

@ -35,7 +35,7 @@ class OpsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.user = c.auth_user.get_instance()
self._register_global_c(c)
return c
@view_config(

View file

@ -37,7 +37,7 @@ log = logging.getLogger(__name__)
class RepoGroupSettingsView(RepoGroupAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -38,7 +38,7 @@ log = logging.getLogger(__name__)
class RepoGroupPermissionsView(RepoGroupAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -65,7 +65,7 @@ class RepoGroupPermissionsView(RepoGroupAppView):
c.repo_group = self.db_repo_group
valid_recursive_choices = ['none', 'repos', 'groups', 'all']
form = RepoGroupPermsForm(valid_recursive_choices)()\
form = RepoGroupPermsForm(self.request.translate, valid_recursive_choices)()\
.to_python(self.request.POST)
if not c.rhodecode_user.is_admin:

View file

@ -73,7 +73,7 @@ class RepoGroupSettingsView(RepoGroupAppView):
c.repo_groups_choices.append(parent_group.group_id)
c.repo_groups.append(RepoGroup._generate_choice(parent_group))
self._register_global_c(c)
return c
def _can_create_repo_group(self, parent_group_id=None):

View file

@ -47,7 +47,7 @@ def route_path(name, params=None, **kwargs):
class TestRepoCommitCommentsView(TestController):
@pytest.fixture(autouse=True)
def prepare(self, request, pylonsapp):
def prepare(self, request, baseapp):
for x in ChangesetComment.query().all():
Session().delete(x)
Session().commit()

View file

@ -34,7 +34,7 @@ class AuditLogsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -37,7 +37,7 @@ class RepoCachesView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -159,7 +159,7 @@ class RepoChangelogView(RepoAppView):
c = self._get_local_tmpl_context(include_app_defaults=True)
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
def _get_preload_attrs(self):

View file

@ -34,7 +34,7 @@ log = logging.getLogger(__name__)
class RepoChecksView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@NotAnonymous()

View file

@ -150,7 +150,6 @@ class RepoCommitsView(RepoAppView):
c = self._get_local_tmpl_context(include_app_defaults=True)
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
def _commit(self, commit_id_range, method):

View file

@ -47,7 +47,7 @@ class RepoCompareView(RepoAppView):
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
def _get_commit_or_redirect(

View file

@ -42,7 +42,7 @@ class RepoFeedView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
self._load_defaults()
return c

View file

@ -83,7 +83,7 @@ class RepoFilesView(RepoAppView):
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
def _ensure_not_locked(self):

View file

@ -57,7 +57,7 @@ class RepoForksView(RepoAppView, DataGridAppView):
c.landing_revs_choices = choices
c.personal_repo_group = c.rhodecode_user.personal_repo_group
self._register_global_c(c)
return c
@LoginRequired()
@ -209,7 +209,7 @@ class RepoForksView(RepoAppView, DataGridAppView):
_ = self.request.translate
c = self.load_default_context()
_form = RepoForkForm(old_data={'repo_type': self.db_repo.repo_type},
_form = RepoForkForm(self.request.translate, old_data={'repo_type': self.db_repo.repo_type},
repo_groups=c.repo_groups_choices,
landing_revs=c.landing_revs_choices)()
post_data = dict(self.request.POST)

View file

@ -33,7 +33,7 @@ class RepoMaintenanceView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -40,7 +40,7 @@ class RepoSettingsPermissionsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -68,7 +68,7 @@ class RepoSettingsPermissionsView(RepoAppView):
# default user permissions, prevents submission of FAKE post data
# into the form for private repos
data['repo_private'] = self.db_repo.private
form = RepoPermsForm()().to_python(data)
form = RepoPermsForm(self.request.translate)().to_python(data)
changes = RepoModel().update_permissions(
self.db_repo_name, form['perm_additions'], form['perm_updates'],
form['perm_deletions'])

View file

@ -60,7 +60,7 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
c = self._get_local_tmpl_context(include_app_defaults=True)
c.REVIEW_STATUS_APPROVED = ChangesetStatus.STATUS_APPROVED
c.REVIEW_STATUS_REJECTED = ChangesetStatus.STATUS_REJECTED
self._register_global_c(c)
return c
def _get_pull_requests_list(
@ -749,7 +749,9 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
controls = peppercorn.parse(self.request.POST.items())
try:
_form = PullRequestForm(self.db_repo.repo_id)().to_python(controls)
form = PullRequestForm(
self.request.translate, self.db_repo.repo_id)()
_form = form.to_python(controls)
except formencode.Invalid as errors:
if errors.error_dict.get('revisions'):
msg = 'Revisions: %s' % errors.error_dict['revisions']

View file

@ -32,8 +32,6 @@ log = logging.getLogger(__name__)
class RepoReviewRulesView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -54,6 +52,7 @@ class RepoReviewRulesView(RepoAppView):
route_name='repo_default_reviewers_data', request_method='GET',
renderer='json_ext')
def repo_default_reviewers_data(self):
self.load_default_context()
review_data = get_default_reviewers_data(
self.db_repo.user, None, None, None, None)
return review_data

View file

@ -71,7 +71,7 @@ class RepoSettingsView(RepoAppView):
c.repo_fields = RepositoryField.query()\
.filter(RepositoryField.repository == self.db_repo).all()
self._register_global_c(c)
return c
def _get_schema(self, c, old_values=None):

View file

@ -44,7 +44,7 @@ class RepoSettingsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -43,7 +43,7 @@ class RepoSettingsFieldsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -70,7 +70,8 @@ class RepoSettingsFieldsView(RepoAppView):
_ = self.request.translate
try:
form_result = RepoFieldForm()().to_python(dict(self.request.POST))
form = RepoFieldForm(self.request.translate)()
form_result = form.to_python(dict(self.request.POST))
RepoModel().add_repo_field(
self.db_repo_name,
form_result['new_field_key'],

View file

@ -40,7 +40,7 @@ class RepoSettingsIssueTrackersView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -118,7 +118,7 @@ class RepoSettingsIssueTrackersView(RepoAppView):
Session().commit()
try:
form = IssueTrackerPatternsForm()().to_python(self.request.POST)
form = IssueTrackerPatternsForm(self.request.translate)().to_python(self.request.POST)
except formencode.Invalid as errors:
log.exception('Failed to add new pattern')
error = errors

View file

@ -36,7 +36,7 @@ class RepoSettingsRemoteView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -43,7 +43,7 @@ class RepoSettingsVcsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
def _vcs_form_defaults(self, repo_name):
@ -117,7 +117,7 @@ class RepoSettingsVcsView(RepoAppView):
defaults = self._vcs_form_defaults(self.db_repo_name)
c.inherit_global_settings = defaults['inherit_global_settings']
application_form = RepoVcsSettingsForm(self.db_repo_name)()
application_form = RepoVcsSettingsForm(self.request.translate, self.db_repo_name)()
try:
form_result = application_form.to_python(dict(self.request.POST))
except formencode.Invalid as errors:

View file

@ -35,7 +35,7 @@ class StripView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -53,7 +53,7 @@ class RepoSummaryView(RepoAppView):
if not c.repository_requirements_missing:
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
def _get_readme_data(self, db_repo, default_renderer):

View file

@ -103,7 +103,7 @@ def search(request, tmpl_context, repo_name):
class SearchView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@ -119,7 +119,7 @@ class SearchView(BaseAppView):
class SearchRepoView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -56,7 +56,7 @@ class UserGroupsView(UserGroupAppView):
PermissionModel().set_global_permission_choices(
c, gettext_translator=self.request.translate)
self._register_global_c(c)
return c
def _get_perms_summary(self, user_group_id):
@ -94,6 +94,7 @@ class UserGroupsView(UserGroupAppView):
"""
Return members of given user group
"""
self.load_default_context()
user_group = self.db_user_group
group_members_obj = sorted((x.user for x in user_group.members),
key=lambda u: u.username.lower())
@ -173,7 +174,8 @@ class UserGroupsView(UserGroupAppView):
c.active = 'settings'
users_group_form = UserGroupForm(
edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
self.request.translate, edit=True,
old_data=c.user_group.get_dict(), allow_disabled=True)()
old_values = c.user_group.get_api_data()
user_group_name = self.request.POST.get('users_group_name')
@ -346,7 +348,7 @@ class UserGroupsView(UserGroupAppView):
user_group_id = user_group.users_group_id
c = self.load_default_context()
c.user_group = user_group
form = UserGroupPermsForm()().to_python(self.request.POST)
form = UserGroupPermsForm(self.request.translate)().to_python(self.request.POST)
if not self._rhodecode_user.is_admin:
if self._revoke_perms_on_yourself(form):
@ -435,6 +437,7 @@ class UserGroupsView(UserGroupAppView):
if not inherit_perms:
# only update the individual ones if we un check the flag
_form = UserPermissionsForm(
self.request.translate,
[x[0] for x in c.repo_create_choices],
[x[0] for x in c.repo_create_on_write_choices],
[x[0] for x in c.repo_group_create_choices],

View file

@ -252,29 +252,6 @@ class RhodeCodeAuthPluginBase(object):
del settings_copy[k]
return settings_copy
@property
def validators(self):
"""
Exposes RhodeCode validators modules
"""
# this is a hack to overcome issues with pylons threadlocals and
# translator object _() not being registered properly.
class LazyCaller(object):
def __init__(self, name):
self.validator_name = name
def __call__(self, *args, **kwargs):
from rhodecode.model import validators as v
obj = getattr(v, self.validator_name)
# log.debug('Initializing lazy formencode object: %s', obj)
return LazyFormencode(obj, *args, **kwargs)
class ProxyGet(object):
def __getattribute__(self, name):
return LazyCaller(name)
return ProxyGet()
@hybrid_property
def name(self):
"""

View file

@ -26,25 +26,24 @@ from pyramid.httpexceptions import HTTPFound
from pyramid.renderers import render
from pyramid.response import Response
from rhodecode.apps._base import BaseAppView
from rhodecode.authentication.base import (
get_auth_cache_manager, get_perms_cache_manager, get_authn_registry)
from rhodecode.lib import auth
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
from rhodecode.lib.auth import (
LoginRequired, HasPermissionAllDecorator, CSRFRequired)
from rhodecode.model.forms import AuthSettingsForm
from rhodecode.model.meta import Session
from rhodecode.model.settings import SettingsModel
from rhodecode.translation import _
log = logging.getLogger(__name__)
class AuthnPluginViewBase(object):
class AuthnPluginViewBase(BaseAppView):
def __init__(self, context, request):
self.request = request
self.context = context
self.plugin = context.plugin
self._rhodecode_user = request.user
def load_default_context(self):
c = self._get_local_tmpl_context()
self.plugin = self.context.plugin
return c
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@ -52,6 +51,7 @@ class AuthnPluginViewBase(object):
"""
View that displays the plugin settings as a form.
"""
c = self.load_default_context()
defaults = defaults or {}
errors = errors or {}
schema = self.plugin.get_settings_schema()
@ -70,15 +70,17 @@ class AuthnPluginViewBase(object):
'resource': self.context,
}
return template_context
return self._get_template_context(c, **template_context)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@auth.CSRFRequired()
@CSRFRequired()
def settings_post(self):
"""
View that validates and stores the plugin settings.
"""
_ = self.request.translate
self.load_default_context()
schema = self.plugin.get_settings_schema()
data = self.request.params
@ -107,23 +109,16 @@ class AuthnPluginViewBase(object):
return HTTPFound(redirect_to)
# TODO: Ongoing migration in these views.
# - Maybe we should also use a colander schema for these views.
class AuthSettingsView(object):
def __init__(self, context, request):
self.context = context
self.request = request
# TODO: Move this into a utility function. It is needed in all view
# classes during migration. Maybe a mixin?
# Some of the decorators rely on this attribute to be present on the
# class of the decorated method.
self._rhodecode_user = request.user
class AuthSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
return c
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def index(self, defaults=None, errors=None, prefix_error=False):
c = self.load_default_context()
defaults = defaults or {}
authn_registry = get_authn_registry(self.request.registry)
enabled_plugins = SettingsModel().get_auth_plugins()
@ -135,8 +130,8 @@ class AuthSettingsView(object):
'enabled_plugins': enabled_plugins,
}
html = render('rhodecode:templates/admin/auth/auth_settings.mako',
template_context,
request=self.request)
self._get_template_context(c, **template_context),
self.request)
# Create form default values and fill the form.
form_defaults = {
@ -155,11 +150,12 @@ class AuthSettingsView(object):
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@auth.CSRFRequired()
@CSRFRequired()
def auth_settings(self):
_ = self.request.translate
try:
form = AuthSettingsForm()()
form_result = form.to_python(self.request.params)
form = AuthSettingsForm(self.request.translate)()
form_result = form.to_python(self.request.POST)
plugins = ','.join(form_result['auth_plugins'])
setting = SettingsModel().create_or_update_setting(
'auth_plugins', plugins)

View file

@ -18,127 +18,49 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
Pylons environment configuration
"""
import os
import logging
import rhodecode
from mako.lookup import TemplateLookup
from pyramid.settings import asbool
# ------------------------------------------------------------------------------
# CELERY magic until refactor - issue #4163 - import order matters here:
from rhodecode.lib import celerypylons # this must be first, celerypylons
#from rhodecode.lib import celerypylons # this must be first, celerypylons
# sets config settings upon import
import rhodecode.integrations # any modules using celery task
# decorators should be added afterwards:
# ------------------------------------------------------------------------------
from rhodecode.lib import app_globals
from rhodecode.config import utils
from rhodecode.config.routing import make_map
from rhodecode.lib import helpers
from rhodecode.lib.utils import (
make_db_config, set_rhodecode_config, load_rcextensions)
from rhodecode.lib.utils2 import str2bool, aslist
from rhodecode.lib.utils import load_rcextensions
from rhodecode.lib.utils2 import str2bool
from rhodecode.lib.vcs import connect_vcs, start_vcs_server
log = logging.getLogger(__name__)
def load_environment(global_conf, app_conf, initial=False,
test_env=None, test_index=None):
"""
Configure the Pylons environment via the ``pylons.config``
object
"""
from pylons.configuration import PylonsConfig
from pylons.error import handle_mako_error
config = PylonsConfig()
# Pylons paths
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
paths = {
'root': root,
'controllers': os.path.join(root, 'controllers'),
'static_files': os.path.join(root, 'public'),
'templates': [os.path.join(root, 'templates')],
}
# Initialize config with the basic options
config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
# store some globals into rhodecode
rhodecode.CELERY_ENABLED = str2bool(config['app_conf'].get('use_celery'))
rhodecode.CELERY_EAGER = str2bool(
config['app_conf'].get('celery.always.eager'))
config['routes.map'] = make_map(config)
config['pylons.app_globals'] = app_globals.Globals(config)
config['pylons.h'] = helpers
rhodecode.CONFIG = config
load_rcextensions(root_path=config['here'])
# Setup cache object as early as possible
import pylons
pylons.cache._push_object(config['pylons.app_globals'].cache)
# Create the Mako TemplateLookup, with the default auto-escaping
config['pylons.app_globals'].mako_lookup = TemplateLookup(
directories=paths['templates'],
error_handler=handle_mako_error,
module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
input_encoding='utf-8', default_filters=['escape'],
imports=['from webhelpers.html import escape'])
# sets the c attribute access when don't existing attribute are accessed
config['pylons.strict_tmpl_context'] = True
# configure channelstream
config['channelstream_config'] = {
'enabled': asbool(config.get('channelstream.enabled', False)),
'server': config.get('channelstream.server'),
'secret': config.get('channelstream.secret')
}
db_cfg = make_db_config(clear_session=True)
repos_path = list(db_cfg.items('paths'))[0][1]
config['base_path'] = repos_path
# store db config also in main global CONFIG
set_rhodecode_config(config)
# configure instance id
utils.set_instance_id(config)
# CONFIGURATION OPTIONS HERE (note: all config options will override
# any Pylons config options)
# store config reference into our module to skip import magic of pylons
rhodecode.CONFIG.update(config)
return config
def load_pyramid_environment(global_config, settings):
# Some parts of the code expect a merge of global and app settings.
settings_merged = global_config.copy()
settings_merged.update(settings)
# Store the settings to make them available to other modules.
rhodecode.PYRAMID_SETTINGS = settings_merged
# NOTE(marcink): needs to be enabled after full port to pyramid
# rhodecode.CONFIG = config
# TODO(marcink): probably not required anymore
# configure channelstream,
settings_merged['channelstream_config'] = {
'enabled': str2bool(settings_merged.get('channelstream.enabled', False)),
'server': settings_merged.get('channelstream.server'),
'secret': settings_merged.get('channelstream.secret')
}
# TODO(marcink): celery
# # store some globals into rhodecode
# rhodecode.CELERY_ENABLED = str2bool(config['app_conf'].get('use_celery'))
# rhodecode.CELERY_EAGER = str2bool(
# config['app_conf'].get('celery.always.eager'))
# If this is a test run we prepare the test environment like
# creating a test database, test search index and test repositories.
@ -152,6 +74,11 @@ def load_pyramid_environment(global_config, settings):
# Initialize the database connection.
utils.initialize_database(settings_merged)
# TODO(marcink): base_path handling ?
# repos_path = list(db_cfg.items('paths'))[0][1]
load_rcextensions(root_path=settings_merged['here'])
# Limit backends to `vcs.backends` from configuration
for alias in rhodecode.BACKENDS.keys():
if alias not in settings['vcs.backends']:
@ -173,5 +100,10 @@ def load_pyramid_environment(global_config, settings):
utils.configure_vcs(settings)
# Store the settings to make them available to other modules.
rhodecode.PYRAMID_SETTINGS = settings_merged
rhodecode.CONFIG = settings_merged
if vcs_server_enabled:
connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(settings))

View file

@ -43,10 +43,7 @@
},
"python2.7-Pygments-2.2.0": {
"BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
},
"python2.7-Pylons-1.0.2.rhodecode-patch1": {
"BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
},
},
"python2.7-Routes-1.13": {
"BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
},
@ -80,10 +77,7 @@
},
"python2.7-amqplib-1.0.2": {
"GNU Lesser General Public License v3.0 only": "http://spdx.org/licenses/LGPL-3.0"
},
"python2.7-anyjson-0.3.3": {
"BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
},
},
"python2.7-appenlight-client-0.6.14": {
"BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
},
@ -327,7 +321,7 @@
"Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0",
"Zope Public License 2.0": "http://spdx.org/licenses/ZPL-2.0"
},
"python2.7-setuptools-scm-1.15.0": {
"python2.7-setuptools-scm-1.15.6": {
"MIT License": "http://spdx.org/licenses/MIT"
},
"python2.7-simplegeneric-0.8.1": {

View file

@ -22,33 +22,26 @@ import logging
import traceback
import collections
from paste.registry import RegistryManager
from paste.gzipper import make_gzip_middleware
from pyramid.wsgi import wsgiapp
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.config import Configurator
from pyramid.settings import asbool, aslist
from pyramid.wsgi import wsgiapp
from pyramid.httpexceptions import (
HTTPException, HTTPError, HTTPInternalServerError, HTTPFound)
HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
from pyramid.events import ApplicationCreated
from pyramid.renderers import render_to_response
from routes.middleware import RoutesMiddleware
import rhodecode
from rhodecode.model import meta
from rhodecode.config import patches
from rhodecode.config import utils as config_utils
from rhodecode.config.routing import STATIC_FILE_PREFIX
from rhodecode.config.environment import (
load_environment, load_pyramid_environment)
from rhodecode.config.environment import load_pyramid_environment
from rhodecode.lib.middleware.vcs import VCSMiddleware
from rhodecode.lib.vcs import VCSCommunicationError
from rhodecode.lib.exceptions import VCSServerUnavailable
from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
from rhodecode.lib.middleware.error_handling import (
PylonsErrorHandlingMiddleware)
from rhodecode.lib.middleware.https_fixup import HttpsFixup
from rhodecode.lib.middleware.vcs import VCSMiddleware
from rhodecode.lib.plugins.utils import register_rhodecode_plugin
from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
from rhodecode.subscribers import (
@ -59,76 +52,17 @@ from rhodecode.subscribers import (
log = logging.getLogger(__name__)
# this is used to avoid avoid the route lookup overhead in routesmiddleware
# for certain routes which won't go to pylons to - eg. static files, debugger
# it is only needed for the pylons migration and can be removed once complete
class SkippableRoutesMiddleware(RoutesMiddleware):
""" Routes middleware that allows you to skip prefixes """
def __init__(self, *args, **kw):
self.skip_prefixes = kw.pop('skip_prefixes', [])
super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
def __call__(self, environ, start_response):
for prefix in self.skip_prefixes:
if environ['PATH_INFO'].startswith(prefix):
# added to avoid the case when a missing /_static route falls
# through to pylons and causes an exception as pylons is
# expecting wsgiorg.routingargs to be set in the environ
# by RoutesMiddleware.
if 'wsgiorg.routing_args' not in environ:
environ['wsgiorg.routing_args'] = (None, {})
return self.app(environ, start_response)
return super(SkippableRoutesMiddleware, self).__call__(
environ, start_response)
def make_app(global_conf, static_files=True, **app_conf):
"""Create a Pylons WSGI application and return it
``global_conf``
The inherited configuration for this application. Normally from
the [DEFAULT] section of the Paste ini file.
``app_conf``
The application's local configuration. Normally specified in
the [app:<name>] section of the Paste ini file (where <name>
defaults to main).
"""
from pylons.wsgiapp import PylonsApp
# Apply compatibility patches
patches.kombu_1_5_1_python_2_7_11()
patches.inspect_getargspec()
# Configure the Pylons environment
config = load_environment(global_conf, app_conf)
# The Pylons WSGI app
app = PylonsApp(config=config)
# Establish the Registry for this application
app = RegistryManager(app)
app.config = config
return app
def is_http_error(response):
# error which should have traceback
return response.status_code > 499
def make_pyramid_app(global_config, **settings):
"""
Constructs the WSGI application based on Pyramid and wraps the Pylons based
application.
Constructs the WSGI application based on Pyramid.
Specials:
* We migrate from Pylons to Pyramid. While doing this, we keep both
frameworks functional. This involves moving some WSGI middlewares around
and providing access to some data internals, so that the old code is
still functional.
* The application can also be integrated like a plugin via the call to
`includeme`. This is accompanied with the other utility functions which
are called. Changing this should be done with great care to not break
@ -138,9 +72,11 @@ def make_pyramid_app(global_config, **settings):
sanitize_settings_and_apply_defaults(settings)
config = Configurator(settings=settings)
load_pyramid_environment(global_config, settings)
add_pylons_compat_data(config.registry, global_config, settings.copy())
# Apply compatibility patches
patches.inspect_getargspec()
load_pyramid_environment(global_config, settings)
# Static file view comes first
includeme_first(config)
@ -157,54 +93,24 @@ def make_pyramid_app(global_config, **settings):
return pyramid_app
def make_not_found_view(config):
def not_found_view(request):
"""
This creates the view which should be registered as not-found-view to
pyramid. Basically it contains of the old pylons app, converted to a view.
Additionally it is wrapped by some other middlewares.
pyramid.
"""
settings = config.registry.settings
vcs_server_enabled = settings['vcs.server.enable']
# Make pylons app from unprepared settings.
pylons_app = make_app(
config.registry._pylons_compat_global_config,
**config.registry._pylons_compat_settings)
config.registry._pylons_compat_config = pylons_app.config
if not getattr(request, 'vcs_call', None):
# handle like regular case with our error_handler
return error_handler(HTTPNotFound(), request)
# Appenlight monitoring.
pylons_app, appenlight_client = wrap_in_appenlight_if_enabled(
pylons_app, settings)
# handle not found view as a vcs call
settings = request.registry.settings
ae_client = getattr(request, 'ae_client', None)
vcs_app = VCSMiddleware(
HTTPNotFound(), request.registry, settings,
appenlight_client=ae_client)
# The pylons app is executed inside of the pyramid 404 exception handler.
# Exceptions which are raised inside of it are not handled by pyramid
# again. Therefore we add a middleware that invokes the error handler in
# case of an exception or error response. This way we return proper error
# HTML pages in case of an error.
reraise = (settings.get('debugtoolbar.enabled', False) or
rhodecode.disable_error_handler)
pylons_app = PylonsErrorHandlingMiddleware(
pylons_app, error_handler, reraise)
# The VCSMiddleware shall operate like a fallback if pyramid doesn't find a
# view to handle the request. Therefore it is wrapped around the pylons
# app. It has to be outside of the error handling otherwise error responses
# from the vcsserver are converted to HTML error pages. This confuses the
# command line tools and the user won't get a meaningful error message.
if vcs_server_enabled:
pylons_app = VCSMiddleware(
pylons_app, settings, appenlight_client, registry=config.registry)
# Convert WSGI app to pyramid view and return it.
return wsgiapp(pylons_app)
def add_pylons_compat_data(registry, global_config, settings):
"""
Attach data to the registry to support the Pylons integration.
"""
registry._pylons_compat_global_config = global_config
registry._pylons_compat_settings = settings
return wsgiapp(vcs_app)(None, request)
def error_handler(exception, request):
@ -220,10 +126,6 @@ def error_handler(exception, request):
elif isinstance(exception, VCSCommunicationError):
base_response = VCSServerUnavailable()
def is_http_error(response):
# error which should have traceback
return response.status_code > 499
if is_http_error(base_response):
log.exception(
'error occurred handling this request for path: %s', request.path)
@ -366,43 +268,29 @@ def includeme(config):
for inc in includes:
config.include(inc)
# This is the glue which allows us to migrate in chunks. By registering the
# pylons based application as the "Not Found" view in Pyramid, we will
# fallback to the old application each time the new one does not yet know
# how to handle a request.
config.add_notfound_view(make_not_found_view(config))
# custom not found view, if our pyramid app doesn't know how to handle
# the request pass it to potential VCS handling ap
config.add_notfound_view(not_found_view)
if not settings.get('debugtoolbar.enabled', False):
# disabled debugtoolbar handle all exceptions via the error_handlers
config.add_view(error_handler, context=Exception)
# all errors including 403/404/50X
config.add_view(error_handler, context=HTTPError)
def wrap_app_in_wsgi_middlewares(pyramid_app, config):
"""
Apply outer WSGI middlewares around the application.
Part of this has been moved up from the Pylons layer, so that the
data is also available if old Pylons code is hit through an already ported
view.
"""
settings = config.registry.settings
# enable https redirects based on HTTP_X_URL_SCHEME set by proxy
pyramid_app = HttpsFixup(pyramid_app, settings)
# Add RoutesMiddleware to support the pylons compatibility tween during
# migration to pyramid.
# TODO(marcink): remove after migration to pyramid
if hasattr(config.registry, '_pylons_compat_config'):
routes_map = config.registry._pylons_compat_config['routes.map']
pyramid_app = SkippableRoutesMiddleware(
pyramid_app, routes_map,
skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
pyramid_app, _ = wrap_in_appenlight_if_enabled(pyramid_app, settings)
pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
pyramid_app, settings)
config.registry.ae_client = _ae_client
if settings['gzip_responses']:
pyramid_app = make_gzip_middleware(
@ -518,10 +406,10 @@ def _int_setting(settings, name, default):
def _bool_setting(settings, name, default):
input = settings.get(name, default)
if isinstance(input, unicode):
input = input.encode('utf8')
settings[name] = asbool(input)
input_val = settings.get(name, default)
if isinstance(input_val, unicode):
input_val = input_val.encode('utf8')
settings[name] = asbool(input_val)
def _list_setting(settings, name, default):

View file

@ -32,26 +32,10 @@ Please keep the following principles in mind:
"""
def kombu_1_5_1_python_2_7_11():
"""
Kombu 1.5.1 relies on a private method which got removed in Python 2.7.11.
This patch adds the symbol to the module :mod:`uuid` and assigns the value
``None`` to it. This causes kombu to fall back to the public API of
:mod:`uuid`.
This patch can most probably be removed once celery and kombu are updated
to more recent versions.
"""
import uuid
if not hasattr(uuid, '_uuid_generate_random'):
uuid._uuid_generate_random = None
def inspect_getargspec():
"""
Pyramid and Pylons rely on inspect.getargspec to lookup the signature of
Pyramid rely on inspect.getargspec to lookup the signature of
view functions. This is not compatible with cython, therefore we replace
getargspec with a custom version.
Code is inspired by the inspect module from Python-3.4

View file

@ -1,184 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
Routes configuration
The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
and _route_name variable which uses some of stored naming here to do redirects.
"""
import os
import re
from routes import Mapper
# prefix for non repository related links needs to be prefixed with `/`
ADMIN_PREFIX = '/_admin'
STATIC_FILE_PREFIX = '/_static'
# Default requirements for URL parts
URL_NAME_REQUIREMENTS = {
# group name can have a slash in them, but they must not end with a slash
'group_name': r'.*?[^/]',
'repo_group_name': r'.*?[^/]',
# repo names can have a slash in them, but they must not end with a slash
'repo_name': r'.*?[^/]',
# file path eats up everything at the end
'f_path': r'.*',
# reference types
'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
}
class JSRoutesMapper(Mapper):
"""
Wrapper for routes.Mapper to make pyroutes compatible url definitions
"""
_named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
_argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
def __init__(self, *args, **kw):
super(JSRoutesMapper, self).__init__(*args, **kw)
self._jsroutes = []
def connect(self, *args, **kw):
"""
Wrapper for connect to take an extra argument jsroute=True
:param jsroute: boolean, if True will add the route to the pyroutes list
"""
if kw.pop('jsroute', False):
if not self._named_route_regex.match(args[0]):
raise Exception('only named routes can be added to pyroutes')
self._jsroutes.append(args[0])
super(JSRoutesMapper, self).connect(*args, **kw)
def _extract_route_information(self, route):
"""
Convert a route into tuple(name, path, args), eg:
('show_user', '/profile/%(username)s', ['username'])
"""
routepath = route.routepath
def replace(matchobj):
if matchobj.group(1):
return "%%(%s)s" % matchobj.group(1).split(':')[0]
else:
return "%%(%s)s" % matchobj.group(2)
routepath = self._argument_prog.sub(replace, routepath)
return (
route.name,
routepath,
[(arg[0].split(':')[0] if arg[0] != '' else arg[1])
for arg in self._argument_prog.findall(route.routepath)]
)
def jsroutes(self):
"""
Return a list of pyroutes.js compatible routes
"""
for route_name in self._jsroutes:
yield self._extract_route_information(self._routenames[route_name])
def make_map(config):
"""Create, configure and return the routes Mapper"""
rmap = JSRoutesMapper(
directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
rmap.minimization = False
rmap.explicit = False
from rhodecode.lib.utils2 import str2bool
from rhodecode.model import repo, repo_group
def check_repo(environ, match_dict):
"""
check for valid repository for proper 404 handling
:param environ:
:param match_dict:
"""
repo_name = match_dict.get('repo_name')
if match_dict.get('f_path'):
# fix for multiple initial slashes that causes errors
match_dict['f_path'] = match_dict['f_path'].lstrip('/')
repo_model = repo.RepoModel()
by_name_match = repo_model.get_by_repo_name(repo_name)
# if we match quickly from database, short circuit the operation,
# and validate repo based on the type.
if by_name_match:
return True
by_id_match = repo_model.get_repo_by_id(repo_name)
if by_id_match:
repo_name = by_id_match.repo_name
match_dict['repo_name'] = repo_name
return True
return False
def check_group(environ, match_dict):
"""
check for valid repository group path for proper 404 handling
:param environ:
:param match_dict:
"""
repo_group_name = match_dict.get('group_name')
repo_group_model = repo_group.RepoGroupModel()
by_name_match = repo_group_model.get_by_group_name(repo_group_name)
if by_name_match:
return True
return False
def check_user_group(environ, match_dict):
"""
check for valid user group for proper 404 handling
:param environ:
:param match_dict:
"""
return True
def check_int(environ, match_dict):
return match_dict.get('id').isdigit()
#==========================================================================
# CUSTOM ROUTES HERE
#==========================================================================
# ADMIN MY ACCOUNT
with rmap.submapper(path_prefix=ADMIN_PREFIX,
controller='admin/my_account') as m:
# NOTE(marcink): this needs to be kept for password force flag to be
# handled in pylons controllers, remove after full migration to pyramid
m.connect('my_account_password', '/my_account/password',
action='my_account_password', conditions={'method': ['GET']})
return rmap

View file

@ -110,7 +110,7 @@ class IntegrationSettingsViewBase(BaseAppView):
return False
def _get_local_tmpl_context(self, include_app_defaults=False):
def _get_local_tmpl_context(self, include_app_defaults=True):
_ = self.request.translate
c = super(IntegrationSettingsViewBase, self)._get_local_tmpl_context(
include_app_defaults=include_app_defaults)
@ -366,7 +366,7 @@ class GlobalIntegrationsView(IntegrationSettingsViewBase):
c.repo = self.repo
c.repo_group = self.repo_group
c.navlist = navigation_list(self.request)
self._register_global_c(c)
return c
@LoginRequired()
@ -403,7 +403,7 @@ class RepoIntegrationsView(IntegrationSettingsViewBase):
c.repo_name = self.db_repo.repo_name
c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
self._register_global_c(c)
return c
@LoginRequired()
@ -434,7 +434,7 @@ class RepoGroupIntegrationsView(IntegrationSettingsViewBase):
c.repo = self.repo
c.repo_group = self.repo_group
c.navlist = navigation_list(self.request)
self._register_global_c(c)
return c
@LoginRequired()

View file

@ -20,7 +20,6 @@
import logging
from pylons.i18n.translation import _
from webhelpers.html.builder import literal
from webhelpers.html.tags import link_to
@ -32,7 +31,7 @@ from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
log = logging.getLogger(__name__)
def action_parser(user_log, feed=False, parse_cs=False):
def action_parser(request, user_log, feed=False, parse_cs=False):
"""
This helper will action_map the specified string action into translated
fancy names with icons and links
@ -42,11 +41,11 @@ def action_parser(user_log, feed=False, parse_cs=False):
:param parse_cs: parse Changesets into VCS instances
"""
if user_log.version == 'v2':
ap = AuditLogParser(user_log)
ap = AuditLogParser(request, user_log)
return ap.callbacks()
else:
# old style
ap = ActionParser(user_log, feed=False, parse_commits=False)
ap = ActionParser(request, user_log, feed=False, parse_commits=False)
return ap.callbacks()
@ -55,10 +54,11 @@ class ActionParser(object):
commits_limit = 3 # display this amount always
commits_top_limit = 50 # show up to this amount of commits hidden
def __init__(self, user_log, feed=False, parse_commits=False):
def __init__(self, request, user_log, feed=False, parse_commits=False):
self.user_log = user_log
self.feed = feed
self.parse_commits = parse_commits
self.request = request
self.action = user_log.action
self.action_params = ' '
@ -86,7 +86,7 @@ class ActionParser(object):
@property
def action_map(self):
_ = self.request.translate
# action : translated str, callback(extractor), icon
action_map = {
'user_deleted_repo': (
@ -166,6 +166,7 @@ class ActionParser(object):
def get_fork_name(self):
from rhodecode.lib import helpers as h
_ = self.request.translate
repo_name = self.action_params
_url = h.route_path('repo_summary', repo_name=repo_name)
return _('fork name %s') % link_to(self.action_params, _url)
@ -180,6 +181,7 @@ class ActionParser(object):
def get_pull_request(self):
from rhodecode.lib import helpers as h
_ = self.request.translate
pull_request_id = self.action_params
if self.is_deleted():
repo_name = self.user_log.repository_name
@ -201,6 +203,7 @@ class ActionParser(object):
def get_cs_links(self):
from rhodecode.lib import helpers as h
_ = self.request.translate
if self.is_deleted():
return self.action_params
@ -277,7 +280,9 @@ class ActionParser(object):
def lnk(self, commit_or_id, repo_name):
from rhodecode.lib.helpers import tooltip
from rhodecode.lib import helpers as h
_ = self.request.translate
title = ''
lazy_cs = True
if isinstance(commit_or_id, (BaseCommit, AttributeDict)):
lazy_cs = True
if (getattr(commit_or_id, 'op', None) and
@ -312,8 +317,9 @@ class ActionParser(object):
class AuditLogParser(object):
def __init__(self, audit_log_entry):
def __init__(self, request, audit_log_entry):
self.audit_log_entry = audit_log_entry
self.request = request
def get_icon(self, action):
return 'icon-rhodecode'

View file

@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
The application's Globals object
"""
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
class Globals(object):
"""
Globals acts as a container for objects available throughout the
life of the application
"""
def __init__(self, config):
"""One instance of Globals is created during application
initialization and is available during requests via the
'app_globals' variable
"""
self.cache = CacheManager(**parse_cache_config_options(config))
self.available_permissions = None # propagated after init_model

View file

@ -34,7 +34,7 @@ import traceback
from functools import wraps
import ipaddress
from beaker.cache import cache_region
from pyramid.httpexceptions import HTTPForbidden, HTTPFound, HTTPNotFound
from sqlalchemy.orm.exc import ObjectDeletedError
from sqlalchemy.orm import joinedload

View file

@ -52,42 +52,9 @@ from rhodecode.model.notification import NotificationModel
from rhodecode.model.scm import ScmModel
from rhodecode.model.settings import VcsSettingsModel, SettingsModel
# NOTE(marcink): remove after base controller is no longer required
from pylons.controllers import WSGIController
from pylons.i18n import translation
log = logging.getLogger(__name__)
# hack to make the migration to pyramid easier
def render(template_name, extra_vars=None, cache_key=None,
cache_type=None, cache_expire=None):
"""Render a template with Mako
Accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire``.
"""
from pylons.templating import literal
from pylons.templating import cached_template, pylons_globals
# Create a render callable for the cache function
def render_template():
# Pull in extra vars if needed
globs = extra_vars or {}
# Second, get the globals
globs.update(pylons_globals())
globs['_ungettext'] = globs['ungettext']
# Grab a template reference
template = globs['app_globals'].mako_lookup.get_template(template_name)
return literal(template.render_unicode(**globs))
return cached_template(template_name, render_template, cache_key=cache_key,
cache_type=cache_type, cache_expire=cache_expire)
def _filter_proxy(ip):
"""
Passed in IP addresses in HEADERS can be in a special format of multiple
@ -310,14 +277,10 @@ def get_current_lang(request):
def attach_context_attributes(context, request, user_id):
"""
Attach variables into template context called `c`, please note that
request could be pylons or pyramid request in here.
Attach variables into template context called `c`.
"""
# NOTE(marcink): remove check after pyramid migration
if hasattr(request, 'registry'):
config = request.registry.settings
else:
from pylons import config
config = request.registry.settings
rc_config = SettingsModel().get_all_settings(cache=True)
@ -418,10 +381,6 @@ def attach_context_attributes(context, request, user_id):
}
# END CONFIG VARS
# TODO: This dosn't work when called from pylons compatibility tween.
# Fix this and remove it from base controller.
# context.repo_name = get_repo_slug(request) # can be empty
diffmode = 'sideside'
if request.GET.get('diffmode'):
if request.GET['diffmode'] == 'unified':
@ -439,20 +398,15 @@ def attach_context_attributes(context, request, user_id):
context.backends.sort()
context.unread_notifications = NotificationModel().get_unread_cnt_for_user(user_id)
# NOTE(marcink): when migrated to pyramid we don't need to set this anymore,
# given request will ALWAYS be pyramid one
pyramid_request = pyramid.threadlocal.get_current_request()
context.pyramid_request = pyramid_request
# web case
if hasattr(pyramid_request, 'user'):
context.auth_user = pyramid_request.user
context.rhodecode_user = pyramid_request.user
if hasattr(request, 'user'):
context.auth_user = request.user
context.rhodecode_user = request.user
# api case
if hasattr(pyramid_request, 'rpc_user'):
context.auth_user = pyramid_request.rpc_user
context.rhodecode_user = pyramid_request.rpc_user
if hasattr(request, 'rpc_user'):
context.auth_user = request.rpc_user
context.rhodecode_user = request.rpc_user
# attach the whole call context to the request
request.call_context = context
@ -500,82 +454,6 @@ def get_auth_user(request):
return auth_user
class BaseController(WSGIController):
def __before__(self):
"""
__before__ is called before controller methods and after __call__
"""
# on each call propagate settings calls into global settings.
from pylons import config
from pylons import tmpl_context as c, request, url
set_rhodecode_config(config)
attach_context_attributes(c, request, self._rhodecode_user.user_id)
# TODO: Remove this when fixed in attach_context_attributes()
c.repo_name = get_repo_slug(request) # can be empty
self.cut_off_limit_diff = safe_int(config.get('cut_off_limit_diff'))
self.cut_off_limit_file = safe_int(config.get('cut_off_limit_file'))
self.sa = meta.Session
self.scm_model = ScmModel(self.sa)
# set user language
user_lang = getattr(c.pyramid_request, '_LOCALE_', None)
if user_lang:
translation.set_lang(user_lang)
log.debug('set language to %s for user %s',
user_lang, self._rhodecode_user)
def _dispatch_redirect(self, with_url, environ, start_response):
from webob.exc import HTTPFound
resp = HTTPFound(with_url)
environ['SCRIPT_NAME'] = '' # handle prefix middleware
environ['PATH_INFO'] = with_url
return resp(environ, start_response)
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
from rhodecode.lib import helpers as h
from pylons import tmpl_context as c, request, url
# Provide the Pylons context to Pyramid's debugtoolbar if it asks
if environ.get('debugtoolbar.wants_pylons_context', False):
environ['debugtoolbar.pylons_context'] = c._current_obj()
_route_name = '.'.join([environ['pylons.routes_dict']['controller'],
environ['pylons.routes_dict']['action']])
self.rc_config = SettingsModel().get_all_settings(cache=True)
self.ip_addr = get_ip_addr(environ)
# The rhodecode auth user is looked up and passed through the
# environ by the pylons compatibility tween in pyramid.
# So we can just grab it from there.
auth_user = environ['rc_auth_user']
# set globals for auth user
request.user = auth_user
self._rhodecode_user = auth_user
log.info('IP: %s User: %s accessed %s [%s]' % (
self.ip_addr, auth_user, safe_unicode(get_access_path(environ)),
_route_name)
)
user_obj = auth_user.get_instance()
if user_obj and user_obj.user_data.get('force_password_change'):
h.flash('You are required to change your password', 'warning',
ignore_duplicate=True)
return self._dispatch_redirect(
url('my_account_password'), environ, start_response)
return WSGIController.__call__(self, environ, start_response)
def h_filter(s):
"""
Custom filter for Mako templates. Mako by standard uses `markupsafe.escape`
@ -623,6 +501,7 @@ def bootstrap_config(request):
# allow pyramid lookup in testing
config.include('pyramid_mako')
config.include('pyramid_beaker')
add_events_routes(config)

View file

@ -28,7 +28,6 @@ import os
import logging
from celery.task import task
from pylons import config
import rhodecode
from rhodecode.lib import audit_logger
@ -42,9 +41,6 @@ from rhodecode.lib.utils2 import safe_int, str2bool
from rhodecode.model.db import Repository, User
add_cache(config) # pragma: no cover
def get_logger(cls):
if rhodecode.CELERY_ENABLED:
try:

View file

@ -36,7 +36,7 @@ class PylonsSettingsProxy(object):
"""
def __getattr__(self, key):
pylons_key = to_pylons(key)
proxy_config = rhodecode.PYRAMID_SETTINGS or pylons.config
proxy_config = rhodecode.PYRAMID_SETTINGS
try:
value = proxy_config[pylons_key]
if key in LIST_PARAMS:
@ -59,7 +59,7 @@ class PylonsSettingsProxy(object):
def __setattr__(self, key, value):
pylons_key = to_pylons(key)
proxy_config = rhodecode.PYRAMID_SETTINGS or pylons.config
proxy_config = rhodecode.PYRAMID_SETTINGS
proxy_config[pylons_key] = value
def __setitem__(self, key, value):

View file

@ -30,7 +30,7 @@ import logging
from itertools import tee, imap
from pylons.i18n.translation import _
from rhodecode.translation import temp_translation_factory as _
from rhodecode.lib.vcs.exceptions import VCSError
from rhodecode.lib.vcs.nodes import FileNode, SubModuleNode

View file

@ -7,9 +7,9 @@ import simplejson as json
from rhodecode.lib.datelib import is_aware
try:
import pylons
import rhodecode.translation
except ImportError:
pylons = None
rhodecode = None
__all__ = ['json']
@ -51,7 +51,7 @@ def _obj_dump(obj):
return str(obj)
elif isinstance(obj, complex):
return [obj.real, obj.imag]
elif pylons and isinstance(obj, pylons.i18n.translation.LazyString):
elif rhodecode and isinstance(obj, rhodecode.translation.LazyString):
return obj.eval()
else:
raise TypeError(repr(obj) + " is not JSON serializable")

View file

@ -91,11 +91,6 @@ DEFAULT_USER = User.DEFAULT_USER
DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
def url(*args, **kw):
from pylons import url as pylons_url
return pylons_url(*args, **kw)
def asset(path, ver=None, **kwargs):
"""
Helper to generate a static asset file path for rhodecode assets
@ -1287,15 +1282,8 @@ def initials_gravatar(email_address, first_name, last_name, size=30):
def gravatar_url(email_address, size=30, request=None):
request = get_current_request()
if request and hasattr(request, 'call_context'):
_use_gravatar = request.call_context.visual.use_gravatar
_gravatar_url = request.call_context.visual.gravatar_url
else:
# doh, we need to re-import those to mock it later
from pylons import tmpl_context as c
_use_gravatar = c.visual.use_gravatar
_gravatar_url = c.visual.gravatar_url
_use_gravatar = request.call_context.visual.use_gravatar
_gravatar_url = request.call_context.visual.gravatar_url
_gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
@ -1745,8 +1733,6 @@ def urlify_commit_message(commit_text, repository=None):
:param commit_text:
:param repository:
"""
from pylons import url # doh, we need to re-import url to mock it later
def escaper(string):
return string.replace('<', '&lt;').replace('>', '&gt;')
@ -2006,8 +1992,6 @@ def get_last_path_part(file_node):
def route_url(*args, **kwargs):
"""
Wrapper around pyramids `route_url` (fully qualified url) function.
It is used to generate URLs from within pylons views or templates.
This will be removed when pyramid migration if finished.
"""
req = get_current_request()
return req.route_url(*args, **kwargs)
@ -2015,9 +1999,7 @@ def route_url(*args, **kwargs):
def route_path(*args, **kwargs):
"""
Wrapper around pyramids `route_path` function. It is used to generate
URLs from within pylons views or templates. This will be removed when
pyramid migration if finished.
Wrapper around pyramids `route_path` function.
"""
req = get_current_request()
return req.route_path(*args, **kwargs)
@ -2036,26 +2018,6 @@ def current_route_path(request, **kw):
return request.current_route_path(_query=new_args)
def static_url(*args, **kwds):
"""
Wrapper around pyramids `route_path` function. It is used to generate
URLs from within pylons views or templates. This will be removed when
pyramid migration if finished.
"""
req = get_current_request()
return req.static_url(*args, **kwds)
def resource_path(*args, **kwds):
"""
Wrapper around pyramids `route_path` function. It is used to generate
URLs from within pylons views or templates. This will be removed when
pyramid migration if finished.
"""
req = get_current_request()
return req.resource_path(*args, **kwds)
def api_call_example(method, args):
"""
Generates an API call example via CURL

View file

@ -18,8 +18,8 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import pylons
import webob
from pyramid.threadlocal import get_current_request
from rhodecode import events
from rhodecode.lib import hooks_base
@ -31,12 +31,15 @@ def _get_rc_scm_extras(username, repo_name, repo_alias, action):
from rhodecode.lib.base import vcs_operation_context
check_locking = action in ('pull', 'push')
request = get_current_request()
# default
dummy_environ = webob.Request.blank('').environ
try:
environ = pylons.request.environ
environ = request.environ or dummy_environ
except TypeError:
# we might use this outside of request context, let's fake the
# environ data
environ = webob.Request.blank('').environ
# we might use this outside of request context
environ = dummy_environ
extras = vcs_operation_context(
environ, repo_name, username, action, repo_alias, check_locking)

View file

@ -27,7 +27,7 @@ import logging
import os
import re
from pylons.i18n.translation import _
from rhodecode.translation import temp_translation_factory as _
from whoosh import query as query_lib, sorting
from whoosh.highlight import HtmlFormatter, ContextFragmenter

View file

@ -1,108 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import logging
from pyramid import httpexceptions
from pyramid.httpexceptions import (
HTTPRedirection, HTTPError, HTTPInternalServerError)
from pyramid.threadlocal import get_current_request
from rhodecode.lib.exceptions import VCSServerUnavailable
from rhodecode.lib.vcs.exceptions import VCSCommunicationError
log = logging.getLogger(__name__)
class PylonsErrorHandlingMiddleware(object):
"""
This middleware is wrapped around the old pylons application to catch
errors and invoke our error handling view to return a proper error page.
"""
def __init__(self, app, error_view, reraise=False):
self.app = app
self.error_view = error_view
self._reraise = reraise
def __call__(self, environ, start_response):
# We need to use the pyramid request here instead of creating a custom
# instance from the environ because this request maybe passed to the
# error handler view which is a pyramid view and expects a pyramid
# request which has been processed by the pyramid router.
request = get_current_request()
response = self.handle_request(request)
return response(environ, start_response)
def is_http_error(self, response):
# webob type error responses
return 400 <= response.status_int <= 599
def reraise(self):
return self._reraise
def handle_request(self, request):
"""
Calls the underlying WSGI app (typically the old RhodeCode pylons app)
and returns the response if no error happened. In case of an error it
invokes the error handling view to return a proper error page as
response.
- old webob type exceptions get converted to pyramid exceptions
- pyramid exceptions are passed to the error handler view
"""
try:
response = request.get_response(self.app)
if self.is_http_error(response):
response = webob_to_pyramid_http_response(response)
return self.error_view(response, request)
except HTTPRedirection as e:
# pyramid type redirection, with status codes in the 300s
log.debug('Handling pyramid HTTPRedirection: %s', e)
return e
except HTTPError as e:
# pyramid type exceptions, with status codes in the 400s and 500s
log.debug('Handling pyramid HTTPError: %s', e)
return self.error_view(e, request)
except Exception as e:
log.debug('Handling general error: %s', e)
if self.reraise():
raise
if isinstance(e, VCSCommunicationError):
return self.error_view(VCSServerUnavailable(), request)
return self.error_view(HTTPInternalServerError(), request)
return response
def webob_to_pyramid_http_response(webob_response):
log.debug('response is webob http error[%s], handling now...',
webob_response.status_int)
ResponseClass = httpexceptions.status_map[webob_response.status_int]
pyramid_response = ResponseClass(webob_response.status)
pyramid_response.status = webob_response.status
pyramid_response.headers.update(webob_response.headers)
if pyramid_response.headers['content-type'] == 'text/html':
pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
return pyramid_response

View file

@ -23,7 +23,7 @@ import time
import logging
from rhodecode.lib.base import get_ip_addr, get_access_path
from rhodecode.lib.base import get_ip_addr, get_access_path, get_user_agent
from rhodecode.lib.utils2 import safe_str
@ -43,10 +43,11 @@ class RequestWrapperTween(object):
response = self.handler(request)
finally:
end = time.time()
log.info('IP: %s Request to %s time: %.3fs' % (
total = end - start
log.info('IP: %s Request to %s time: %.3fs [%s]' % (
get_ip_addr(request.environ),
safe_str(get_access_path(request.environ)), end - start)
safe_str(get_access_path(request.environ)), total,
get_user_agent(request. environ),)
)
return response

View file

@ -134,11 +134,11 @@ class SimpleSvn(simplevcs.SimpleVCS):
# SVN includes the whole path in it's requests, including
# subdirectories inside the repo. Therefore we have to search for
# the repo root directory.
if not is_valid_repo(repo_name, self.basepath, self.SCM):
if not is_valid_repo(repo_name, self.base_path, self.SCM):
current_path = ''
for component in repo_name.split('/'):
current_path += component
if is_valid_repo(current_path, self.basepath, self.SCM):
if is_valid_repo(current_path, self.base_path, self.SCM):
return current_path
current_path += '/'

View file

@ -31,7 +31,8 @@ from functools import wraps
import time
from paste.httpheaders import REMOTE_USER, AUTH_TYPE
from webob.exc import (
# TODO(marcink): check if we should use webob.exc here ?
from pyramid.httpexceptions import (
HTTPNotFound, HTTPForbidden, HTTPNotAcceptable, HTTPInternalServerError)
import rhodecode
@ -55,7 +56,7 @@ from rhodecode.model import meta
from rhodecode.model.db import User, Repository, PullRequest
from rhodecode.model.scm import ScmModel
from rhodecode.model.pull_request import PullRequestModel
from rhodecode.model.settings import SettingsModel
from rhodecode.model.settings import SettingsModel, VcsSettingsModel
log = logging.getLogger(__name__)
@ -103,14 +104,13 @@ class SimpleVCS(object):
'repository$' # shadow repo
.format(slug_pat=SLUG_RE.pattern))
def __init__(self, application, config, registry):
def __init__(self, config, registry):
self.registry = registry
self.application = application
self.config = config
# re-populated by specialized middleware
self.repo_vcs_config = base.Config()
self.rhodecode_settings = SettingsModel().get_all_settings(cache=True)
self.basepath = rhodecode.CONFIG['base_path']
registry.rhodecode_settings = self.rhodecode_settings
# authenticate this VCS request using authfunc
auth_ret_code_detection = \
@ -120,6 +120,10 @@ class SimpleVCS(object):
auth_ret_code_detection)
self.ip_addr = '0.0.0.0'
@property
def base_path(self):
return self.repo_vcs_config.get(*VcsSettingsModel.PATH_SETTING)
def set_repo_names(self, environ):
"""
This will populate the attributes acl_repo_name, url_repo_name,
@ -381,6 +385,8 @@ class SimpleVCS(object):
# Check if the shadow repo actually exists, in case someone refers
# to it, and it has been deleted because of successful merge.
if self.is_shadow_repo and not self.is_shadow_repo_dir:
log.debug('Shadow repo detected, and shadow repo dir `%s` is missing',
self.is_shadow_repo_dir)
return HTTPNotFound()(environ, start_response)
# ======================================================================
@ -493,7 +499,7 @@ class SimpleVCS(object):
# REQUEST HANDLING
# ======================================================================
repo_path = os.path.join(
safe_str(self.basepath), safe_str(self.vcs_repo_name))
safe_str(self.base_path), safe_str(self.vcs_repo_name))
log.debug('Repository path is %s', repo_path)
fix_PATH()

View file

@ -168,11 +168,11 @@ def detect_vcs_request(environ, backends):
class VCSMiddleware(object):
def __init__(self, app, config, appenlight_client, registry):
def __init__(self, app, registry, config, appenlight_client):
self.application = app
self.registry = registry
self.config = config
self.appenlight_client = appenlight_client
self.registry = registry
self.use_gzip = True
# order in which we check the middlewares, based on vcs.backends config
self.check_middlewares = config['vcs.backends']
@ -193,7 +193,7 @@ class VCSMiddleware(object):
log.debug('VCSMiddleware: detecting vcs type.')
handler = detect_vcs_request(environ, self.check_middlewares)
if handler:
app = handler(self.application, self.config, self.registry)
app = handler(self.config, self.registry)
return app
@ -212,7 +212,7 @@ class VCSMiddleware(object):
# check for type, presence in database and on filesystem
if not vcs_handler.is_valid_and_existing_repo(
vcs_handler.acl_repo_name,
vcs_handler.basepath,
vcs_handler.base_path,
vcs_handler.SCM):
return HTTPNotFound()(environ, start_response)

View file

@ -578,9 +578,6 @@ def rhodecode_config():
blacklist = [
'rhodecode_license_key',
'routes.map',
'pylons.h',
'pylons.app_globals',
'pylons.environ_config',
'sqlalchemy.db1.url',
'channelstream.secret',
'beaker.session.secret',

View file

@ -97,18 +97,14 @@ def repo_name_slug(value):
#==============================================================================
def get_repo_slug(request):
_repo = ''
if isinstance(request, Request):
if hasattr(request, 'db_repo'):
# if our requests has set db reference use it for name, this
# translates the example.com/_<id> into proper repo names
_repo = request.db_repo.repo_name
elif getattr(request, 'matchdict', None):
# pyramid
_repo = request.matchdict.get('repo_name')
# TODO(marcink): remove after pylons migration...
if not _repo:
_repo = request.environ['pylons.routes_dict'].get('repo_name')
if hasattr(request, 'db_repo'):
# if our requests has set db reference use it for name, this
# translates the example.com/_<id> into proper repo names
_repo = request.db_repo.repo_name
elif getattr(request, 'matchdict', None):
# pyramid
_repo = request.matchdict.get('repo_name')
if _repo:
_repo = _repo.rstrip('/')
@ -117,18 +113,14 @@ def get_repo_slug(request):
def get_repo_group_slug(request):
_group = ''
if isinstance(request, Request):
if hasattr(request, 'db_repo_group'):
# if our requests has set db reference use it for name, this
# translates the example.com/_<id> into proper repo group names
_group = request.db_repo_group.group_name
elif getattr(request, 'matchdict', None):
# pyramid
_group = request.matchdict.get('repo_group_name')
if hasattr(request, 'db_repo_group'):
# if our requests has set db reference use it for name, this
# translates the example.com/_<id> into proper repo group names
_group = request.db_repo_group.group_name
elif getattr(request, 'matchdict', None):
# pyramid
_group = request.matchdict.get('repo_group_name')
# TODO(marcink): remove after pylons migration...
if not _group:
_group = request.environ['pylons.routes_dict'].get('group_name')
if _group:
_group = _group.rstrip('/')
@ -137,26 +129,21 @@ def get_repo_group_slug(request):
def get_user_group_slug(request):
_user_group = ''
if isinstance(request, Request):
if hasattr(request, 'db_user_group'):
_user_group = request.db_user_group.users_group_name
elif getattr(request, 'matchdict', None):
# pyramid
_user_group = request.matchdict.get('user_group_id')
if hasattr(request, 'db_user_group'):
_user_group = request.db_user_group.users_group_name
elif getattr(request, 'matchdict', None):
# pyramid
_user_group = request.matchdict.get('user_group_id')
try:
_user_group = UserGroup.get(_user_group)
if _user_group:
_user_group = _user_group.users_group_name
except Exception:
log.exception('Failed to get user group by id')
# catch all failures here
return None
# TODO(marcink): remove after pylons migration...
if not _user_group:
_user_group = request.environ['pylons.routes_dict'].get('user_group_id')
try:
_user_group = UserGroup.get(_user_group)
if _user_group:
_user_group = _user_group.users_group_name
except Exception:
log.exception('Failed to get user group by id')
# catch all failures here
return None
return _user_group
@ -438,7 +425,7 @@ def get_enabled_hook_classes(ui_settings):
def set_rhodecode_config(config):
"""
Updates pylons config with new settings from database
Updates pyramid config with new settings from database
:param config:
"""
@ -881,19 +868,6 @@ def read_opensource_licenses():
return _license_cache
def get_registry(request):
"""
Utility to get the pyramid registry from a request. During migration to
pyramid we sometimes want to use the pyramid registry from pylons context.
Therefore this utility returns `request.registry` for pyramid requests and
uses `get_current_registry()` for pylons requests.
"""
try:
return request.registry
except AttributeError:
return get_current_registry()
def generate_platform_uuid():
"""
Generates platform UUID based on it's name

View file

@ -18,27 +18,6 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
The application's model objects
:example:
.. code-block:: python
from paste.deploy import appconfig
from pylons import config
from sqlalchemy import engine_from_config
from rhodecode.config.environment import load_environment
conf = appconfig('config:development.ini', relative_to = './../../')
load_environment(conf.global_conf, conf.local_conf)
engine = engine_from_config(config, 'sqlalchemy.')
init_model(engine)
# RUN YOUR CODE HERE
"""
import logging

View file

@ -26,7 +26,6 @@ import logging
import traceback
import collections
from pylons.i18n.translation import _
from pyramid.threadlocal import get_current_registry, get_current_request
from sqlalchemy.sql.expression import null
from sqlalchemy.sql.functions import coalesce
@ -68,8 +67,8 @@ class CommentsModel(BaseModel):
user_objects.append(user_obj)
return user_objects
def _get_renderer(self, global_renderer='rst'):
request = get_current_request()
def _get_renderer(self, global_renderer='rst', request=None):
request = request or get_current_request()
try:
global_renderer = request.call_context.visual.default_renderer
@ -194,9 +193,11 @@ class CommentsModel(BaseModel):
if not text:
log.warning('Missing text for comment, skipping...')
return
request = get_current_request()
_ = request.translate
if not renderer:
renderer = self._get_renderer()
renderer = self._get_renderer(request=request)
repo = self._get_repo(repo)
user = self._get_user(user)
@ -268,7 +269,7 @@ class CommentsModel(BaseModel):
cs_author = repo.user
recipients += [cs_author]
commit_comment_url = self.get_url(comment)
commit_comment_url = self.get_url(comment, request=request)
target_repo_url = h.link_to(
repo.repo_name,

View file

@ -48,7 +48,7 @@ import formencode
from pkg_resources import resource_filename
from formencode import All, Pipe
from pylons.i18n.translation import _
from rhodecode.translation import temp_translation_factory as _
from pyramid.threadlocal import get_current_request
from rhodecode import BACKENDS
@ -75,7 +75,9 @@ form_renderer = RhodecodeFormZPTRendererFactory(search_path)
deform.Form.set_default_renderer(form_renderer)
def LoginForm():
def LoginForm(localizer):
_ = localizer
class _LoginForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -101,33 +103,37 @@ def LoginForm():
remember = v.StringBoolean(if_missing=False)
chained_validators = [v.ValidAuth()]
chained_validators = [v.ValidAuth(localizer)]
return _LoginForm
def UserForm(edit=False, available_languages=[], old_data={}):
def UserForm(localizer, edit=False, available_languages=None, old_data=None):
old_data = old_data or {}
available_languages = available_languages or []
_ = localizer
class _UserForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
v.ValidUsername(edit, old_data))
v.ValidUsername(localizer, edit, old_data))
if edit:
new_password = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
)
password_confirmation = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=False),
)
admin = v.StringBoolean(if_missing=False)
else:
password = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
)
password_confirmation = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
)
@ -137,17 +143,18 @@ def UserForm(edit=False, available_languages=[], old_data={}):
active = v.StringBoolean(if_missing=False)
firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
email = All(v.Email(not_empty=True), v.UniqSystemEmail(localizer, old_data))
extern_name = v.UnicodeString(strip=True)
extern_type = v.UnicodeString(strip=True)
language = v.OneOf(available_languages, hideList=False,
testValueList=True, if_missing=None)
chained_validators = [v.ValidPasswordsMatch()]
chained_validators = [v.ValidPasswordsMatch(localizer)]
return _UserForm
def UserGroupForm(edit=False, old_data=None, allow_disabled=False):
def UserGroupForm(localizer, edit=False, old_data=None, allow_disabled=False):
old_data = old_data or {}
_ = localizer
class _UserGroupForm(formencode.Schema):
allow_extra_fields = True
@ -155,7 +162,7 @@ def UserGroupForm(edit=False, old_data=None, allow_disabled=False):
users_group_name = All(
v.UnicodeString(strip=True, min=1, not_empty=True),
v.ValidUserGroup(edit, old_data)
v.ValidUserGroup(localizer, edit, old_data)
)
user_group_description = v.UnicodeString(strip=True, min=1,
not_empty=False)
@ -166,12 +173,13 @@ def UserGroupForm(edit=False, old_data=None, allow_disabled=False):
# this is user group owner
user = All(
v.UnicodeString(not_empty=True),
v.ValidRepoUser(allow_disabled))
v.ValidRepoUser(localizer, allow_disabled))
return _UserGroupForm
def RepoGroupForm(edit=False, old_data=None, available_groups=None,
can_create_in_root=False, allow_disabled=False):
def RepoGroupForm(localizer, edit=False, old_data=None, available_groups=None,
can_create_in_root=False, allow_disabled=False):
_ = localizer
old_data = old_data or {}
available_groups = available_groups or []
@ -180,7 +188,7 @@ def RepoGroupForm(edit=False, old_data=None, available_groups=None,
filter_extra_fields = False
group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
v.SlugifyName(),)
v.SlugifyName(localizer),)
group_description = v.UnicodeString(strip=True, min=1,
not_empty=False)
group_copy_permissions = v.StringBoolean(if_missing=False)
@ -189,53 +197,57 @@ def RepoGroupForm(edit=False, old_data=None, available_groups=None,
testValueList=True, not_empty=True)
enable_locking = v.StringBoolean(if_missing=False)
chained_validators = [
v.ValidRepoGroup(edit, old_data, can_create_in_root)]
v.ValidRepoGroup(localizer, edit, old_data, can_create_in_root)]
if edit:
# this is repo group owner
user = All(
v.UnicodeString(not_empty=True),
v.ValidRepoUser(allow_disabled))
v.ValidRepoUser(localizer, allow_disabled))
return _RepoGroupForm
def RegisterForm(edit=False, old_data={}):
def RegisterForm(localizer, edit=False, old_data=None):
_ = localizer
old_data = old_data or {}
class _RegisterForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
username = All(
v.ValidUsername(edit, old_data),
v.ValidUsername(localizer, edit, old_data),
v.UnicodeString(strip=True, min=1, not_empty=True)
)
password = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
)
password_confirmation = All(
v.ValidPassword(),
v.ValidPassword(localizer),
v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
)
active = v.StringBoolean(if_missing=False)
firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
chained_validators = [v.ValidPasswordsMatch()]
email = All(v.Email(not_empty=True), v.UniqSystemEmail(localizer, old_data))
chained_validators = [v.ValidPasswordsMatch(localizer)]
return _RegisterForm
def PasswordResetForm():
def PasswordResetForm(localizer):
_ = localizer
class _PasswordResetForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
email = All(v.ValidSystemEmail(localizer), v.Email(not_empty=True))
return _PasswordResetForm
def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None,
allow_disabled=False):
def RepoForm(localizer, edit=False, old_data=None, repo_groups=None,
landing_revs=None, allow_disabled=False):
_ = localizer
old_data = old_data or {}
repo_groups = repo_groups or []
landing_revs = landing_revs or []
@ -245,8 +257,8 @@ def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None,
allow_extra_fields = True
filter_extra_fields = False
repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
v.SlugifyName(), v.CannotHaveGitSuffix())
repo_group = All(v.CanWriteGroup(old_data),
v.SlugifyName(localizer), v.CannotHaveGitSuffix(localizer))
repo_group = All(v.CanWriteGroup(localizer, old_data),
v.OneOf(repo_groups, hideList=True))
repo_type = v.OneOf(supported_backends, required=False,
if_missing=old_data.get('repo_type'))
@ -264,77 +276,91 @@ def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None,
# this is repo owner
user = All(
v.UnicodeString(not_empty=True),
v.ValidRepoUser(allow_disabled))
v.ValidRepoUser(localizer, allow_disabled))
clone_uri_change = v.UnicodeString(
not_empty=False, if_missing=v.Missing)
chained_validators = [v.ValidCloneUri(),
v.ValidRepoName(edit, old_data)]
chained_validators = [v.ValidCloneUri(localizer),
v.ValidRepoName(localizer, edit, old_data)]
return _RepoForm
def RepoPermsForm():
def RepoPermsForm(localizer):
_ = localizer
class _RepoPermsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
chained_validators = [v.ValidPerms(type_='repo')]
chained_validators = [v.ValidPerms(localizer, type_='repo')]
return _RepoPermsForm
def RepoGroupPermsForm(valid_recursive_choices):
def RepoGroupPermsForm(localizer, valid_recursive_choices):
_ = localizer
class _RepoGroupPermsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
recursive = v.OneOf(valid_recursive_choices)
chained_validators = [v.ValidPerms(type_='repo_group')]
chained_validators = [v.ValidPerms(localizer, type_='repo_group')]
return _RepoGroupPermsForm
def UserGroupPermsForm():
def UserGroupPermsForm(localizer):
_ = localizer
class _UserPermsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
chained_validators = [v.ValidPerms(type_='user_group')]
chained_validators = [v.ValidPerms(localizer, type_='user_group')]
return _UserPermsForm
def RepoFieldForm():
def RepoFieldForm(localizer):
_ = localizer
class _RepoFieldForm(formencode.Schema):
filter_extra_fields = True
allow_extra_fields = True
new_field_key = All(v.FieldKey(),
new_field_key = All(v.FieldKey(localizer),
v.UnicodeString(strip=True, min=3, not_empty=True))
new_field_value = v.UnicodeString(not_empty=False, if_missing=u'')
new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
if_missing='str')
new_field_label = v.UnicodeString(not_empty=False)
new_field_desc = v.UnicodeString(not_empty=False)
return _RepoFieldForm
def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
repo_groups=[], landing_revs=[]):
def RepoForkForm(localizer, edit=False, old_data=None,
supported_backends=BACKENDS.keys(), repo_groups=None,
landing_revs=None):
_ = localizer
old_data = old_data or {}
repo_groups = repo_groups or []
landing_revs = landing_revs or []
class _RepoForkForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
v.SlugifyName())
repo_group = All(v.CanWriteGroup(),
v.SlugifyName(localizer))
repo_group = All(v.CanWriteGroup(localizer, ),
v.OneOf(repo_groups, hideList=True))
repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
repo_type = All(v.ValidForkType(localizer, old_data), v.OneOf(supported_backends))
description = v.UnicodeString(strip=True, min=1, not_empty=True)
private = v.StringBoolean(if_missing=False)
copy_permissions = v.StringBoolean(if_missing=False)
fork_parent_id = v.UnicodeString()
chained_validators = [v.ValidForkName(edit, old_data)]
chained_validators = [v.ValidForkName(localizer, edit, old_data)]
landing_rev = v.OneOf(landing_revs, hideList=True)
return _RepoForkForm
def ApplicationSettingsForm():
def ApplicationSettingsForm(localizer):
_ = localizer
class _ApplicationSettingsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
@ -346,11 +372,12 @@ def ApplicationSettingsForm():
rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
return _ApplicationSettingsForm
def ApplicationVisualisationForm():
def ApplicationVisualisationForm(localizer):
_ = localizer
class _ApplicationVisualisationForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
@ -370,11 +397,11 @@ def ApplicationVisualisationForm():
rhodecode_support_url = v.UnicodeString()
rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
return _ApplicationVisualisationForm
class _BaseVcsSettingsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
@ -403,48 +430,54 @@ class _BaseVcsSettingsForm(formencode.Schema):
vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
def ApplicationUiSettingsForm():
def ApplicationUiSettingsForm(localizer):
_ = localizer
class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
web_push_ssl = v.StringBoolean(if_missing=False)
paths_root_path = All(
v.ValidPath(),
v.ValidPath(localizer),
v.UnicodeString(strip=True, min=1, not_empty=True)
)
largefiles_usercache = All(
v.ValidPath(),
v.ValidPath(localizer),
v.UnicodeString(strip=True, min=2, not_empty=True))
vcs_git_lfs_store_location = All(
v.ValidPath(),
v.ValidPath(localizer),
v.UnicodeString(strip=True, min=2, not_empty=True))
extensions_hgsubversion = v.StringBoolean(if_missing=False)
extensions_hggit = v.StringBoolean(if_missing=False)
new_svn_branch = v.ValidSvnPattern(section='vcs_svn_branch')
new_svn_tag = v.ValidSvnPattern(section='vcs_svn_tag')
new_svn_branch = v.ValidSvnPattern(localizer, section='vcs_svn_branch')
new_svn_tag = v.ValidSvnPattern(localizer, section='vcs_svn_tag')
return _ApplicationUiSettingsForm
def RepoVcsSettingsForm(repo_name):
def RepoVcsSettingsForm(localizer, repo_name):
_ = localizer
class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
inherit_global_settings = v.StringBoolean(if_missing=False)
new_svn_branch = v.ValidSvnPattern(
new_svn_branch = v.ValidSvnPattern(localizer,
section='vcs_svn_branch', repo_name=repo_name)
new_svn_tag = v.ValidSvnPattern(
new_svn_tag = v.ValidSvnPattern(localizer,
section='vcs_svn_tag', repo_name=repo_name)
return _RepoVcsSettingsForm
def LabsSettingsForm():
def LabsSettingsForm(localizer):
_ = localizer
class _LabSettingsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
return _LabSettingsForm
def ApplicationPermissionsForm(
register_choices, password_reset_choices, extern_activate_choices):
localizer, register_choices, password_reset_choices,
extern_activate_choices):
_ = localizer
class _DefaultPermissionsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -454,12 +487,13 @@ def ApplicationPermissionsForm(
default_register_message = v.UnicodeString()
default_password_reset = v.OneOf(password_reset_choices)
default_extern_activate = v.OneOf(extern_activate_choices)
return _DefaultPermissionsForm
def ObjectPermissionsForm(repo_perms_choices, group_perms_choices,
def ObjectPermissionsForm(localizer, repo_perms_choices, group_perms_choices,
user_group_perms_choices):
_ = localizer
class _ObjectPermissionsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -469,13 +503,14 @@ def ObjectPermissionsForm(repo_perms_choices, group_perms_choices,
default_repo_perm = v.OneOf(repo_perms_choices)
default_group_perm = v.OneOf(group_perms_choices)
default_user_group_perm = v.OneOf(user_group_perms_choices)
return _ObjectPermissionsForm
def UserPermissionsForm(create_choices, create_on_write_choices,
def UserPermissionsForm(localizer, create_choices, create_on_write_choices,
repo_group_create_choices, user_group_create_choices,
fork_choices, inherit_default_permissions_choices):
_ = localizer
class _DefaultPermissionsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -488,21 +523,24 @@ def UserPermissionsForm(create_choices, create_on_write_choices,
default_repo_group_create = v.OneOf(repo_group_create_choices)
default_fork_create = v.OneOf(fork_choices)
default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
return _DefaultPermissionsForm
def UserIndividualPermissionsForm():
def UserIndividualPermissionsForm(localizer):
_ = localizer
class _DefaultPermissionsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
inherit_default_permissions = v.StringBoolean(if_missing=False)
return _DefaultPermissionsForm
def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
def DefaultsForm(localizer, edit=False, old_data=None, supported_backends=BACKENDS.keys()):
_ = localizer
old_data = old_data or {}
class _DefaultsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -511,34 +549,39 @@ def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
default_repo_enable_statistics = v.StringBoolean(if_missing=False)
default_repo_enable_downloads = v.StringBoolean(if_missing=False)
default_repo_enable_locking = v.StringBoolean(if_missing=False)
return _DefaultsForm
def AuthSettingsForm():
def AuthSettingsForm(localizer):
_ = localizer
class _AuthSettingsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
auth_plugins = All(v.ValidAuthPlugins(),
v.UniqueListFromString()(not_empty=True))
auth_plugins = All(v.ValidAuthPlugins(localizer),
v.UniqueListFromString(localizer)(not_empty=True))
return _AuthSettingsForm
def UserExtraEmailForm():
def UserExtraEmailForm(localizer):
_ = localizer
class _UserExtraEmailForm(formencode.Schema):
email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
email = All(v.UniqSystemEmail(localizer), v.Email(not_empty=True))
return _UserExtraEmailForm
def UserExtraIpForm():
def UserExtraIpForm(localizer):
_ = localizer
class _UserExtraIpForm(formencode.Schema):
ip = v.ValidIp()(not_empty=True)
ip = v.ValidIp(localizer)(not_empty=True)
return _UserExtraIpForm
def PullRequestForm(localizer, repo_id):
_ = localizer
def PullRequestForm(repo_id):
class ReviewerForm(formencode.Schema):
user_id = v.Int(not_empty=True)
reasons = All()
@ -553,8 +596,8 @@ def PullRequestForm(repo_id):
source_ref = v.UnicodeString(strip=True, required=True)
target_repo = v.UnicodeString(strip=True, required=True)
target_ref = v.UnicodeString(strip=True, required=True)
revisions = All(#v.NotReviewedRevisions(repo_id)(),
v.UniqueList()(not_empty=True))
revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
v.UniqueList(localizer)(not_empty=True))
review_members = formencode.ForEach(ReviewerForm())
pullrequest_title = v.UnicodeString(strip=True, required=True)
pullrequest_desc = v.UnicodeString(strip=True, required=False)
@ -562,9 +605,11 @@ def PullRequestForm(repo_id):
return _PullRequestForm
def IssueTrackerPatternsForm():
def IssueTrackerPatternsForm(localizer):
_ = localizer
class _IssueTrackerPatternsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = False
chained_validators = [v.ValidPattern()]
chained_validators = [v.ValidPattern(localizer)]
return _IssueTrackerPatternsForm

View file

@ -30,7 +30,7 @@ import logging
import cStringIO
import pkg_resources
from pylons.i18n.translation import _
from rhodecode.translation import temp_translation_factory as _
from sqlalchemy import func
from zope.cachedescriptors.property import Lazy as LazyProperty

View file

@ -26,7 +26,7 @@ import logging
import traceback
import datetime
from pylons.i18n.translation import _
from rhodecode.translation import temp_translation_factory as _
import ipaddress
from sqlalchemy.exc import DatabaseError
@ -754,14 +754,12 @@ class UserModel(BaseModel):
:param user:
:param email:
"""
from rhodecode.model import forms
form = forms.UserExtraEmailForm()()
data = form.to_python({'email': email})
user = self._get_user(user)
obj = UserEmailMap()
obj.user = user
obj.email = data['email']
obj.email = email
self.sa.add(obj)
return obj
@ -811,14 +809,11 @@ class UserModel(BaseModel):
:param user:
:param ip:
"""
from rhodecode.model import forms
form = forms.UserExtraIpForm()()
data = form.to_python({'ip': ip})
user = self._get_user(user)
user = self._get_user(user)
obj = UserIpMap()
obj.user = user
obj.ip_addr = data['ip']
obj.ip_addr = ip
obj.description = description
self.sa.add(obj)
return obj

View file

@ -22,10 +22,11 @@
Set of generic validators
"""
import logging
import os
import re
from collections import defaultdict
import logging
import collections
import formencode
import ipaddress
@ -33,7 +34,7 @@ from formencode.validators import (
UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
NotEmpty, IPAddress, CIDR, String, FancyValidator
)
from pylons.i18n.translation import _
from sqlalchemy.sql.expression import true
from sqlalchemy.util import OrderedSet
from webhelpers.pylonslib.secure_form import authentication_token
@ -62,17 +63,11 @@ log = logging.getLogger(__name__)
class _Missing(object):
pass
Missing = _Missing()
class StateObj(object):
"""
this is needed to translate the messages using _() in validators
"""
_ = staticmethod(_)
def M(self, key, state=None, **kwargs):
def M(self, key, state, **kwargs):
"""
returns string from self.message based on given key,
passed kw params are used to substitute %(named)s params inside
@ -81,16 +76,16 @@ def M(self, key, state=None, **kwargs):
:param msg:
:param state:
"""
if state is None:
state = StateObj()
else:
state._ = staticmethod(_)
#state._ = staticmethod(_)
# inject validator into state object
return self.message(key, state, **kwargs)
def UniqueList(convert=None):
class _UniqueList(formencode.FancyValidator):
def UniqueList(localizer, convert=None):
_ = localizer
class _validator(formencode.FancyValidator):
"""
Unique List !
"""
@ -123,20 +118,23 @@ def UniqueList(convert=None):
def empty_value(self, value):
return []
return _UniqueList
return _validator
def UniqueListFromString():
class _UniqueListFromString(UniqueList()):
def UniqueListFromString(localizer):
_ = localizer
class _validator(UniqueList(localizer)):
def _to_python(self, value, state):
if isinstance(value, basestring):
value = aslist(value, ',')
return super(_UniqueListFromString, self)._to_python(value, state)
return _UniqueListFromString
return super(_validator, self)._to_python(value, state)
return _validator
def ValidSvnPattern(section, repo_name=None):
def ValidSvnPattern(localizer, section, repo_name=None):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'pattern_exists': _(u'Pattern already exists'),
@ -154,7 +152,10 @@ def ValidSvnPattern(section, repo_name=None):
return _validator
def ValidUsername(edit=False, old_data={}):
def ValidUsername(localizer, edit=False, old_data=None):
_ = localizer
old_data = old_data or {}
class _validator(formencode.validators.FancyValidator):
messages = {
'username_exists': _(u'Username "%(username)s" already exists'),
@ -187,13 +188,9 @@ def ValidUsername(edit=False, old_data={}):
return _validator
def ValidRegex(msg=None):
class _validator(formencode.validators.Regex):
messages = {'invalid': msg or _(u'The input is not valid')}
return _validator
def ValidRepoUser(localizer, allow_disabled=False):
_ = localizer
def ValidRepoUser(allow_disabled=False):
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_username': _(u'Username %(username)s is not valid'),
@ -213,11 +210,13 @@ def ValidRepoUser(allow_disabled=False):
raise formencode.Invalid(
msg, value, state, error_dict={'username': msg}
)
return _validator
def ValidUserGroup(edit=False, old_data={}):
def ValidUserGroup(localizer, edit=False, old_data=None):
_ = localizer
old_data = old_data or {}
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_group': _(u'Invalid user group name'),
@ -254,11 +253,13 @@ def ValidUserGroup(edit=False, old_data={}):
raise formencode.Invalid(
msg, value, state, error_dict={'users_group_name': msg}
)
return _validator
def ValidRepoGroup(edit=False, old_data={}, can_create_in_root=False):
def ValidRepoGroup(localizer, edit=False, old_data=None, can_create_in_root=False):
_ = localizer
old_data = old_data or {}
class _validator(formencode.validators.FancyValidator):
messages = {
'group_parent_id': _(u'Cannot assign this group as parent'),
@ -375,11 +376,12 @@ def ValidRepoGroup(edit=False, old_data={}, can_create_in_root=False):
msg = M(self, 'repo_exists', state, group_name=group_name)
raise formencode.Invalid(
msg, value, state, error_dict={'group_name': msg})
return _validator
def ValidPassword():
def ValidPassword(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_password':
@ -395,24 +397,11 @@ def ValidPassword():
return _validator
def ValidOldPassword(username):
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_password': _(u'Invalid old password')
}
def validate_python(self, value, state):
from rhodecode.authentication.base import authenticate, HTTP_TYPE
if not authenticate(username, value, '', HTTP_TYPE):
msg = M(self, 'invalid_password', state)
raise formencode.Invalid(
msg, value, state, error_dict={'current_password': msg}
)
return _validator
def ValidPasswordsMatch(
passwd='new_password', passwd_confirmation='password_confirmation'):
localizer, passwd='new_password',
passwd_confirmation='password_confirmation'):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'password_mismatch': _(u'Passwords do not match'),
@ -430,7 +419,9 @@ def ValidPasswordsMatch(
return _validator
def ValidAuth():
def ValidAuth(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_password': _(u'invalid password'),
@ -464,7 +455,9 @@ def ValidAuth():
return _validator
def ValidAuthToken():
def ValidAuthToken(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_token': _(u'Token mismatch')
@ -477,7 +470,10 @@ def ValidAuthToken():
return _validator
def ValidRepoName(edit=False, old_data={}):
def ValidRepoName(localizer, edit=False, old_data=None):
old_data = old_data or {}
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_repo_name':
@ -558,11 +554,15 @@ def ValidRepoName(edit=False, old_data={}):
return _validator
def ValidForkName(*args, **kwargs):
return ValidRepoName(*args, **kwargs)
def ValidForkName(localizer, *args, **kwargs):
_ = localizer
return ValidRepoName(localizer, *args, **kwargs)
def SlugifyName():
def SlugifyName(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
def _to_python(self, value, state):
@ -570,11 +570,12 @@ def SlugifyName():
def validate_python(self, value, state):
pass
return _validator
def CannotHaveGitSuffix():
def CannotHaveGitSuffix(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'has_git_suffix':
@ -590,11 +591,12 @@ def CannotHaveGitSuffix():
self, 'has_git_suffix', state)
raise formencode.Invalid(
msg, value, state, error_dict={'repo_name': msg})
return _validator
def ValidCloneUri():
def ValidCloneUri(localizer):
_ = localizer
class InvalidCloneUrl(Exception):
allowed_prefixes = ()
@ -652,19 +654,22 @@ def ValidCloneUri():
url_handler(repo_type, url)
except InvalidCloneUrl as e:
log.warning(e)
msg = M(self, 'invalid_clone_uri', rtype=repo_type,
msg = M(self, 'invalid_clone_uri', state, rtype=repo_type,
allowed_prefixes=','.join(e.allowed_prefixes))
raise formencode.Invalid(msg, value, state,
error_dict={'clone_uri': msg})
except Exception:
log.exception('Url validation failed')
msg = M(self, 'clone_uri', rtype=repo_type)
msg = M(self, 'clone_uri', state, rtype=repo_type)
raise formencode.Invalid(msg, value, state,
error_dict={'clone_uri': msg})
return _validator
def ValidForkType(old_data={}):
def ValidForkType(localizer, old_data=None):
_ = localizer
old_data = old_data or {}
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_fork_type': _(u'Fork have to be the same type as parent')
@ -679,7 +684,9 @@ def ValidForkType(old_data={}):
return _validator
def CanWriteGroup(old_data=None):
def CanWriteGroup(localizer, old_data=None):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'permission_denied': _(
@ -730,11 +737,11 @@ def CanWriteGroup(old_data=None):
raise formencode.Invalid(
msg, value, state, error_dict={'repo_type': msg}
)
return _validator
def ValidPerms(type_='repo'):
def ValidPerms(localizer, type_='repo'):
_ = localizer
if type_ == 'repo_group':
EMPTY_PERM = 'group.none'
elif type_ == 'repo':
@ -756,8 +763,8 @@ def ValidPerms(type_='repo'):
# Read the perm_new_member/perm_del_member attributes and group
# them by they IDs
new_perms_group = defaultdict(dict)
del_perms_group = defaultdict(dict)
new_perms_group = collections.defaultdict(dict)
del_perms_group = collections.defaultdict(dict)
for k, v in value.copy().iteritems():
if k.startswith('perm_del_member'):
# delete from org storage so we don't process that later
@ -851,29 +858,9 @@ def ValidPerms(type_='repo'):
return _validator
def ValidSettings():
class _validator(formencode.validators.FancyValidator):
def _to_python(self, value, state):
# settings form for users that are not admin
# can't edit certain parameters, it's extra backup if they mangle
# with forms
def ValidPath(localizer):
_ = localizer
forbidden_params = [
'user', 'repo_type', 'repo_enable_locking',
'repo_enable_downloads', 'repo_enable_statistics'
]
for param in forbidden_params:
if param in value:
del value[param]
return value
def validate_python(self, value, state):
pass
return _validator
def ValidPath():
class _validator(formencode.validators.FancyValidator):
messages = {
'invalid_path': _(u'This is not a valid path')
@ -888,7 +875,10 @@ def ValidPath():
return _validator
def UniqSystemEmail(old_data={}):
def UniqSystemEmail(localizer, old_data=None):
_ = localizer
old_data = old_data or {}
class _validator(formencode.validators.FancyValidator):
messages = {
'email_taken': _(u'This e-mail address is already taken')
@ -908,7 +898,9 @@ def UniqSystemEmail(old_data={}):
return _validator
def ValidSystemEmail():
def ValidSystemEmail(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
@ -924,11 +916,11 @@ def ValidSystemEmail():
raise formencode.Invalid(
msg, value, state, error_dict={'email': msg}
)
return _validator
def NotReviewedRevisions(repo_id):
def NotReviewedRevisions(localizer, repo_id):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'rev_already_reviewed':
@ -960,7 +952,9 @@ def NotReviewedRevisions(repo_id):
return _validator
def ValidIp():
def ValidIp(localizer):
_ = localizer
class _validator(CIDR):
messages = {
'badFormat': _(u'Please enter a valid IPv4 or IpV6 address'),
@ -984,11 +978,12 @@ def ValidIp():
except ValueError:
raise formencode.Invalid(self.message('badFormat', state),
value, state)
return _validator
def FieldKey():
def FieldKey(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'badFormat': _(
@ -1003,7 +998,9 @@ def FieldKey():
return _validator
def ValidAuthPlugins():
def ValidAuthPlugins(localizer):
_ = localizer
class _validator(formencode.validators.FancyValidator):
messages = {
'import_duplicate': _(
@ -1033,11 +1030,11 @@ def ValidAuthPlugins():
log.exception(
'Exception during import of auth legacy plugin "{}"'
.format(plugin_id))
msg = M(self, 'import_error', plugin_id=plugin_id)
msg = M(self, 'import_error', state, plugin_id=plugin_id)
raise formencode.Invalid(msg, value, state)
if not hasattr(plugin, 'includeme'):
msg = M(self, 'missing_includeme', plugin_id=plugin_id)
msg = M(self, 'missing_includeme', state, plugin_id=plugin_id)
raise formencode.Invalid(msg, value, state)
return plugin
@ -1051,7 +1048,7 @@ def ValidAuthPlugins():
plugin = loadplugin(plugin_id)
if plugin is None:
msg = M(self, 'no_plugin', plugin_id=plugin_id)
msg = M(self, 'no_plugin', state, plugin_id=plugin_id)
raise formencode.Invalid(msg, value, state)
return plugin
@ -1074,13 +1071,13 @@ def ValidAuthPlugins():
next_to_load=plugin)
raise formencode.Invalid(msg, value, state)
unique_names[plugin.name] = plugin
return _validator
def ValidPattern():
def ValidPattern(localizer):
_ = localizer
class _Validator(formencode.validators.FancyValidator):
class _validator(formencode.validators.FancyValidator):
messages = {
'bad_format': _(u'Url must start with http or /'),
}
@ -1129,4 +1126,4 @@ def ValidPattern():
delete_patterns = [delete_patterns]
value['delete_patterns'] = delete_patterns
return value
return _Validator
return _validator

View file

@ -21,7 +21,6 @@ import io
import re
import datetime
import logging
import pylons
import Queue
import subprocess32
import os
@ -36,14 +35,11 @@ from threading import Thread
from rhodecode.translation import _ as tsf
from rhodecode.config.jsroutes import generate_jsroutes_content
from rhodecode.lib import auth
from rhodecode.lib.base import get_auth_user
import rhodecode
from pylons.i18n.translation import _get_translator
from pylons.util import ContextObj
from routes.util import URLGenerator
from rhodecode.lib.base import attach_context_attributes, get_auth_user
log = logging.getLogger(__name__)
@ -51,11 +47,6 @@ log = logging.getLogger(__name__)
def add_renderer_globals(event):
from rhodecode.lib import helpers
# NOTE(marcink):
# Put pylons stuff into the context. This will be removed as soon as
# migration to pyramid is finished.
event['c'] = pylons.tmpl_context
# TODO: When executed in pyramid view context the request is not available
# in the event. Find a better solution to get the request.
request = event['request'] or get_current_request()
@ -68,12 +59,11 @@ def add_renderer_globals(event):
def add_localizer(event):
request = event.request
localizer = get_localizer(request)
localizer = request.localizer
def auto_translate(*args, **kwargs):
return localizer.translate(tsf(*args, **kwargs))
request.localizer = localizer
request.translate = auto_translate
request.plularize = localizer.pluralize
@ -108,39 +98,6 @@ def add_request_user_context(event):
request.environ['rc_auth_user'] = auth_user
def add_pylons_context(event):
request = event.request
config = rhodecode.CONFIG
environ = request.environ
session = request.session
if hasattr(request, 'vcs_call'):
# skip vcs calls
return
# Setup pylons globals.
pylons.config._push_object(config)
pylons.request._push_object(request)
pylons.session._push_object(session)
pylons.translator._push_object(_get_translator(config.get('lang')))
pylons.url._push_object(URLGenerator(config['routes.map'], environ))
session_key = (
config['pylons.environ_config'].get('session', 'beaker.session'))
environ[session_key] = session
if hasattr(request, 'rpc_method'):
# skip api calls
return
# Setup the pylons context object ('c')
context = ContextObj()
context.rhodecode_user = request.user
attach_context_attributes(context, request, request.user.user_id)
pylons.tmpl_context._push_object(context)
def inject_app_settings(event):
settings = event.app.registry.settings
# inject info about available permissions

View file

@ -61,14 +61,14 @@
</td>
<td>
% if c.audit_log_entry.version == c.audit_log_entry.VERSION_1:
${h.action_parser(l)[0]()}
${h.action_parser(request, l)[0]()}
% else:
${h.literal(c.audit_log_entry.action)}
% endif
<div class="journal_action_params">
% if c.audit_log_entry.version == c.audit_log_entry.VERSION_1:
${h.literal(h.action_parser(l)[1]())}
${h.literal(h.action_parser(request, l)[1]())}
% endif
</div>
</td>

View file

@ -14,7 +14,7 @@
<input type='submit' value="${_('filter')}" class="btn" />
${_('Audit logs')} - ${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)}
${h.end_form()}
<p class="tooltip filterexample" title="${h.tooltip(h.journal_filter_help(c.pyramid_request))}">${_('Example Queries')}</p>
<p class="tooltip filterexample" title="${h.tooltip(h.journal_filter_help(request))}">${_('Example Queries')}</p>
</%def>
<%def name="menu_bar_nav()">

View file

@ -26,14 +26,14 @@
</td>
<td class="td-journalaction">
% if l.version == l.VERSION_1:
${h.action_parser(l)[0]()}
${h.action_parser(request, l)[0]()}
% else:
${h.literal(l.action)}
% endif
<div class="journal_action_params">
% if l.version == l.VERSION_1:
${h.literal(h.action_parser(l)[1]())}
${h.literal(h.action_parser(request, l)[1]())}
% endif
</div>
</td>

Some files were not shown because too many files have changed in this diff Show more