Changeset - 3bcf9529d221
[Not reviewed]
default
0 5 0
Marcin Kuzminski - 15 years ago 2010-08-05 22:31:23
marcin@python-works.com
Added new application settings,Push ssl and repositories path
5 files changed with 140 insertions and 12 deletions:
0 comments (0 inline, 0 general)
pylons_app/config/environment.py
Show inline comments
 
@@ -52,22 +52,23 @@ def load_environment(global_conf, app_co
 
    
 
    #MULTIPLE DB configs
 
    # Setup the SQLAlchemy database engine
 
    if config['debug']:
 
        #use query time debugging.
 
        from pylons_app.lib.timerproxy import TimerProxy
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
 
                                                            proxy=TimerProxy())
 
    else:
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
 

	
 
    init_model(sa_engine_db1)
 
    #init baseui
 
    config['pylons.app_globals'].baseui = make_ui('db')
 
    
 
    repo2db_mapper(_get_repos_cached_initial(config['pylons.app_globals'], initial))
 
    set_available_permissions(config)
 
    set_base_path(config)
 
    set_hg_app_config(config)
 
    # CONFIGURATION OPTIONS HERE (note: all config options will override
 
    # any Pylons config options)
 
    
 
    return config
pylons_app/controllers/admin/settings.py
Show inline comments
 
@@ -23,27 +23,28 @@ settings controller for pylons
 
@author: marcink
 
"""
 
from formencode import htmlfill
 
from pylons import request, session, tmpl_context as c, url, app_globals as g, \
 
    config
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 
from pylons_app.lib import helpers as h
 
from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.utils import repo2db_mapper, invalidate_cache, \
 
    set_hg_app_config, get_hg_settings
 
from pylons_app.model.db import User, UserLog, HgAppSettings
 
from pylons_app.model.forms import UserForm, ApplicationSettingsForm
 
    set_hg_app_config, get_hg_settings, get_hg_ui_settings, make_ui
 
from pylons_app.model.db import User, UserLog, HgAppSettings, HgAppUi
 
from pylons_app.model.forms import UserForm, ApplicationSettingsForm, \
 
    ApplicationUiSettingsForm
 
from pylons_app.model.hg_model import HgModel
 
from pylons_app.model.user_model import UserModel
 
import formencode
 
import logging
 
import traceback
 
 
 
log = logging.getLogger(__name__)
 

	
 

	
 
class SettingsController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
@@ -56,25 +57,25 @@ class SettingsController(BaseController)
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(SettingsController, self).__before__()
 
    
 
    
 
    @HasPermissionAllDecorator('hg.admin')    
 
    def index(self, format='html'):
 
        """GET /admin/settings: All items in the collection"""
 
        # url('admin_settings')
 

	
 
        defaults = get_hg_settings()
 

	
 
        defaults.update(get_hg_ui_settings())
 
        return htmlfill.render(
 
            render('admin/settings/settings.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )  
 
    
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create(self):
 
        """POST /admin/settings: Create a new item"""
 
        # url('admin_settings')
 
    
 
@@ -99,28 +100,30 @@ class SettingsController(BaseController)
 
            initial = HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
 
            repo2db_mapper(initial, rm_obsolete)
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('Repositories sucessfully rescanned'), category='success')            
 
        
 
        if setting_id == 'global':
 
            
 
            application_form = ApplicationSettingsForm()()
 
            try:
 
                form_result = application_form.to_python(dict(request.POST))
 
            
 
                try:
 
                    hgsettings1 = self.sa.query(HgAppSettings).filter(HgAppSettings.app_settings_name == 'title').one()
 
                    hgsettings1 = self.sa.query(HgAppSettings)\
 
                    .filter(HgAppSettings.app_settings_name == 'title').one()
 
                    hgsettings1.app_settings_value = form_result['hg_app_title'] 
 
                    
 
                    hgsettings2 = self.sa.query(HgAppSettings).filter(HgAppSettings.app_settings_name == 'realm').one()
 
                    hgsettings2 = self.sa.query(HgAppSettings)\
 
                    .filter(HgAppSettings.app_settings_name == 'realm').one()
 
                    hgsettings2.app_settings_value = form_result['hg_app_realm'] 
 
                    
 
                    
 
                    self.sa.add(hgsettings1)
 
                    self.sa.add(hgsettings2)
 
                    self.sa.commit()
 
                    set_hg_app_config(config)
 
                    h.flash(_('Updated application settings'),
 
                            category='success')
 
                                    
 
                except:
 
                    log.error(traceback.format_exc())
 
@@ -129,24 +132,64 @@ class SettingsController(BaseController)
 
                                
 
                    self.sa.rollback()
 
                    
 

	
 
            except formencode.Invalid as errors:
 
                return htmlfill.render(
 
                     render('admin/settings/settings.html'),
 
                     defaults=errors.value,
 
                     errors=errors.error_dict or {},
 
                     prefix_error=False,
 
                     encoding="UTF-8") 
 
                        
 
        if setting_id == 'mercurial':
 
            application_form = ApplicationUiSettingsForm()()
 
            try:
 
                form_result = application_form.to_python(dict(request.POST))
 
            
 
                try:
 
                    
 
                    hgsettings1 = self.sa.query(HgAppUi)\
 
                    .filter(HgAppUi.ui_key == 'push_ssl').one()
 
                    hgsettings1.ui_value = form_result['web_push_ssl']
 
                    
 
                    hgsettings2 = self.sa.query(HgAppUi)\
 
                    .filter(HgAppUi.ui_key == '/').one()
 
                    hgsettings2.ui_value = form_result['paths_root_path']                    
 
                    
 
                    self.sa.add(hgsettings1)
 
                    self.sa.add(hgsettings2)
 
                    self.sa.commit()
 
                    
 
                    h.flash(_('Updated application settings'),
 
                            category='success')
 
                                    
 
                except:
 
                    log.error(traceback.format_exc())
 
                    h.flash(_('error occured during updating application settings'),
 
                            category='error')
 
                                
 
                    self.sa.rollback()
 
                    
 

	
 
            except formencode.Invalid as errors:
 
                return htmlfill.render(
 
                     render('admin/settings/settings.html'),
 
                     defaults=errors.value,
 
                     errors=errors.error_dict or {},
 
                     prefix_error=False,
 
                     encoding="UTF-8") 
 
                
 
                
 
                        
 
        return redirect(url('admin_settings'))
 
    
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete(self, setting_id):
 
        """DELETE /admin/settings/setting_id: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
        #    h.form(url('admin_setting', setting_id=ID),
 
        #           method='delete')
 
        # url('admin_setting', setting_id=ID)
 
    
pylons_app/lib/utils.py
Show inline comments
 
@@ -103,65 +103,82 @@ def get_hg_settings():
 
        ret = sa.query(HgAppSettings).all()
 
    finally:
 
        meta.Session.remove()
 
        
 
    if not ret:
 
        raise Exception('Could not get application settings !')
 
    settings = {}
 
    for each in ret:
 
        settings['hg_app_' + each.app_settings_name] = each.app_settings_value    
 
    
 
    return settings
 

	
 
def get_hg_ui_settings():
 
    try:
 
        sa = meta.Session
 
        ret = sa.query(HgAppUi).all()
 
    finally:
 
        meta.Session.remove()
 
        
 
    if not ret:
 
        raise Exception('Could not get application ui settings !')
 
    settings = {}
 
    for each in ret:
 
        k = each.ui_key if each.ui_key != '/' else 'root_path'
 
        settings[each.ui_section + '_' + k] = each.ui_value    
 
    
 
    return settings
 

	
 
#propagated from mercurial documentation
 
ui_sections = ['alias', 'auth',
 
                'decode/encode', 'defaults',
 
                'diff', 'email',
 
                'extensions', 'format',
 
                'merge-patterns', 'merge-tools',
 
                'hooks', 'http_proxy',
 
                'smtp', 'patch',
 
                'paths', 'profiling',
 
                'server', 'trusted',
 
                'ui', 'web', ]
 
        
 
def make_ui(read_from='file', path=None, checkpaths=True):        
 
    """
 
    A function that will read python rc files or database
 
    and make an mercurial ui object from read options
 
    
 
    @param path: path to mercurial config file
 
    @param checkpaths: check the path
 
    @param read_from: read from 'file' or 'db'
 
    """
 
    #propagated from mercurial documentation
 

	
 
    baseui = ui.ui()
 

	
 
                
 
    if read_from == 'file':
 
        if not os.path.isfile(path):
 
            log.warning('Unable to read config file %s' % path)
 
            return False
 
        
 
        log.debug('reading hgrc from %s', path)
 
        cfg = config.config()
 
        cfg.read(path)
 
        for section in ui_sections:
 
            for k, v in cfg.items(section):
 
                baseui.setconfig(section, k, v)
 
                log.debug('settings ui from file[%s]%s:%s', section, k, v)
 
        if checkpaths:check_repo_dir(cfg.items('paths'))                
 
              
 
        
 
    elif read_from == 'db':
 
        hg_ui = get_hg_ui_cached()
 
        for ui_ in hg_ui:
 
            log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
 
            baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
 
        
 
    
 
    return baseui
 

	
 

	
 
def set_hg_app_config(config):
 
    hgsettings = get_hg_settings()
 
    
 
    for k, v in hgsettings.items():
 
        config[k] = v
 

	
pylons_app/model/forms.py
Show inline comments
 
@@ -16,33 +16,34 @@ ignore_key_missing      False     If Tru
 
<name> = formencode.validators.<name of validator>
 
<name> must equal form name
 
list=[1,2,3,4,5]
 
for SELECT use formencode.All(OneOf(list), Int())
 
    
 
"""
 
from formencode import All
 
from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
 
    Email, Bool, StringBoolean
 
from pylons import session
 
from pylons.i18n.translation import _
 
from pylons_app.lib.auth import get_crypt_password
 
import pylons_app.lib.helpers as h
 
from pylons_app.model import meta
 
from pylons_app.model.db import User, Repository
 
from sqlalchemy.exc import OperationalError
 
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 
from webhelpers.pylonslib.secure_form import authentication_token
 
import datetime
 
import formencode
 
import logging
 
import os
 
import pylons_app.lib.helpers as h
 
log = logging.getLogger(__name__)
 

	
 

	
 
#this is needed to translate the messages using _() in validators
 
class State_obj(object):
 
    _ = staticmethod(_)
 
    
 
#===============================================================================
 
# VALIDATORS
 
#===============================================================================
 
class ValidAuthToken(formencode.validators.FancyValidator):
 
    messages = {'invalid_token':_('Token mismatch')}
 
@@ -210,24 +211,38 @@ class ValidPerms(formencode.validators.F
 
                                     state=State_obj)
 
                raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})            
 
        return value
 
    
 
class ValidSettings(formencode.validators.FancyValidator):
 
    
 
    def to_python(self, value, state):
 
        #settings  form can't edit user
 
        if value.has_key('user'):
 
            del['value']['user']
 
        
 
        return value                
 
    
 
class ValidPath(formencode.validators.FancyValidator):
 
    def to_python(self, value, state):
 
        isdir = os.path.isdir(value.replace('*', ''))
 
        if (value.endswith('/*') or value.endswith('/**')) and isdir:
 
            return value
 
        elif not isdir:
 
            msg = _('This is not a valid path') 
 
        else:
 
            msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
 
        
 
        raise formencode.Invalid(msg, value, state,
 
                                     error_dict={'paths_root_path':msg})            
 
                       
 
#===============================================================================
 
# FORMS        
 
#===============================================================================
 
class LoginForm(formencode.Schema):
 
    allow_extra_fields = True
 
    filter_extra_fields = True
 
    username = UnicodeString(
 
                             strip=True,
 
                             min=3,
 
                             not_empty=True,
 
                             messages={
 
                                       'empty':_('Please enter a login'),
 
@@ -293,14 +308,21 @@ def RepoSettingsForm(edit=False, old_dat
 
    return _RepoForm
 

	
 

	
 
def ApplicationSettingsForm():
 
    class _ApplicationSettingsForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        hg_app_title = UnicodeString(strip=True, min=3, not_empty=True)
 
        hg_app_realm = UnicodeString(strip=True, min=3, not_empty=True)
 
        
 
    return _ApplicationSettingsForm
 
 
 
def ApplicationUiSettingsForm():
 
    class _ApplicationUiSettingsForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        web_push_ssl = OneOf(['true', 'false'], if_missing='false')
 
        paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=3, not_empty=True))
 

	
 
    return _ApplicationUiSettingsForm
 

	
pylons_app/templates/admin/settings/settings.html
Show inline comments
 
@@ -48,37 +48,82 @@
 
    </div>  
 
    ${h.end_form()}
 
     
 
    <h3>${_('Global application settings')}</h3> 
 
    ${h.form(url('admin_setting', setting_id='global'),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        
 
        <div class="fields">
 
             
 
             <div class="field">
 
                <div class="label">
 
                    <label for="input-small">${_('Application name')}:</label>
 
                    <label for="hg_app_title">${_('Application name')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('hg_app_title',size=30)}
 
                </div>
 
             </div>
 
                          
 
            <div class="field">
 
                <div class="label">
 
                    <label for="input-small">${_('Realm text')}:</label>
 
                    <label for="hg_app_realm">${_('Realm text')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('hg_app_realm',size=30)}
 
                </div>
 
            </div>
 
                                     
 
            <div class="buttons">
 
                ${h.submit('save','save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
 
           </div>                                                          
 
        </div>
 
    </div>      
 
    ${h.end_form()}
 
    
 
    <h3>${_('Mercurial settings')}</h3> 
 
    ${h.form(url('admin_setting', setting_id='mercurial'),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        
 
        <div class="fields">
 
             
 
             <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="web_push_ssl">${_('Push ssl')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
					<div class="checkbox">
 
						${h.checkbox('web_push_ssl','true')}
 
						<label for="web_push_ssl">${_('require ssl for pushing')}</label>
 
					</div>
 
				</div>
 
             </div>						
 
							                          
 
            <div class="field">
 
                <div class="label">
 
                    <label for="paths_root_path">${_('Repositories location')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('paths_root_path',size=30,disabled="disabled")}
 
					<span id="path_unlock" class="tooltip" tooltip_title="${h.tooltip(_('This a crucial application setting. If You really sure you need to change this, you must restart application in order to make this settings take effect. Click this label to unlock.'))}">
 
		                ${_('unlock')}</span>
 
                </div>
 
            </div>
 
                                     
 
            <div class="buttons">
 
                ${h.submit('save','save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
 
           </div>                                                          
 
        </div>
 
    </div>      
 
    ${h.end_form()}
 
    
 
    <script type="text/javascript">
 
        YAHOO.util.Event.onDOMReady(function(){
 
            YAHOO.util.Event.addListener('path_unlock','click',function(){
 
                YAHOO.util.Dom.get('paths_root_path').disabled=false;
 
            });
 
        });
 
    </script>
 
    
 
</div>
 
</%def>    
0 comments (0 inline, 0 general)