Changeset - 51362853ac3b
[Not reviewed]
default
0 3 4
Marcin Kuzminski - 15 years ago 2010-07-14 13:30:31
marcin@python-works.com
added settings rest controllers for admin, updated routes with easier submodule handling
7 files changed with 207 insertions and 6 deletions:
0 comments (0 inline, 0 general)
pylons_app/config/routing.py
Show inline comments
 
"""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/
 
"""
 
from routes import Mapper
 
from pylons_app.lib.utils import check_repo_fast as cr
 

	
 
def make_map(config):
 
    """Create, configure and return the routes Mapper"""
 
    map = Mapper(directory=config['pylons.paths']['controllers'],
 
                 always_scan=config['debug'])
 
    map.minimization = False
 
    map.explicit = False
 

	
 
    # The ErrorController route (handles 404/500 error pages); it should
 
    # likely stay at the top, ensuring it can always be resolved
 
    map.connect('/error/{action}', controller='error')
 
    map.connect('/error/{action}/{id}', controller='error')
 

	
 
    # CUSTOM ROUTES HERE
 
    map.connect('hg_home', '/', controller='hg', action='index')
 
    
 
    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')
 
        return not cr(repo_name, config['base_path'])
 
 
 
    #REST routes
 
    with map.submapper(path_prefix='/_admin', controller='pylons_app.controllers.admin.repos:ReposController') as m:
 
    with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
 
        m.connect("repos", "/repos",
 
             action="create", conditions=dict(method=["POST"]))
 
        m.connect("repos", "/repos",
 
             action="index", conditions=dict(method=["GET"]))
 
        m.connect("formatted_repos", "/repos.{format}",
 
             action="index",
 
            conditions=dict(method=["GET"]))
 
        m.connect("new_repo", "/repos/new",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("formatted_new_repo", "/repos/new.{format}",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("/repos/{repo_name:.*}",
 
             action="update", conditions=dict(method=["PUT"],
 
                                              function=check_repo))
 
        m.connect("/repos/{repo_name:.*}",
 
             action="delete", conditions=dict(method=["DELETE"],
 
                                              function=check_repo))
 
        m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("repo", "/repos/{repo_name:.*}",
 
             action="show", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
 
             action="show", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        #ajax delete repo perm user
 
        m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
 
             action="delete_perm_user", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 
        
 
    map.resource('user', 'users', controller='pylons_app.controllers.admin.users:UsersController', path_prefix='/_admin')
 
    map.resource('permission', 'permissions', controller='pylons_app.controllers.admin.permissions:PermissionsController', path_prefix='/_admin')
 
    map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
 
    map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
 
    map.resource('setting', 'settings', controller='admin/settings', path_prefix='/_admin', name_prefix='admin_')
 
    
 
    #ADMIN
 
    with map.submapper(path_prefix='/_admin', controller='pylons_app.controllers.admin.admin:AdminController') as m:
 
    with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
 
        m.connect('admin_home', '', action='index')#main page
 
        m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
 
                  action='add_repo')
 
    
 
    #FEEDS
 
    map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
 
                controller='feed', action='rss',
 
                conditions=dict(function=check_repo))
 
    map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
 
                controller='feed', action='atom',
 
                conditions=dict(function=check_repo))
 
    
 
    #LOGIN/LOGOUT
 
    map.connect('login_home', '/login', controller='login')
 
    map.connect('logout_home', '/logout', controller='login', action='logout')
 
    
 
    #OTHERS
 
    map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
 
                controller='changeset', revision='tip',
 
                conditions=dict(function=check_repo))
 
    map.connect('summary_home', '/{repo_name:.*}/summary',
 
                controller='summary', conditions=dict(function=check_repo))
 
    map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
 
                controller='shortlog', conditions=dict(function=check_repo))
 
    map.connect('branches_home', '/{repo_name:.*}/branches',
 
                controller='branches', conditions=dict(function=check_repo))
 
    map.connect('tags_home', '/{repo_name:.*}/tags',
 
                controller='tags', conditions=dict(function=check_repo))
 
    map.connect('changelog_home', '/{repo_name:.*}/changelog',
 
                controller='changelog', conditions=dict(function=check_repo))    
 
    map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
 
                controller='files', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
 
                controller='files', action='diff', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    map.connect('files_raw_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
 
                controller='files', action='rawfile', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
 
                controller='files', action='annotate', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))    
 
    map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
 
                controller='files', action='archivefile', revision='tip',
 
                conditions=dict(function=check_repo))
 
    map.connect('repo_settings_update', '/{repo_name:.*}/settings',
 
                controller='settings', action="update",
 
                conditions=dict(method=["PUT"], function=check_repo))
pylons_app/controllers/admin/settings.py
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# settings controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# 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 General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on July 14, 2010
 
settings controller for pylons
 
@author: marcink
 
"""
 
from formencode import htmlfill
 
from pylons import request, session, tmpl_context as c, url
 
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
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.db import User, UserLog
 
from pylons_app.model.forms import UserForm
 
from pylons_app.model.user_model import UserModel
 
import formencode
 
import logging
 

	
 
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
 
    # file has a resource setup:
 
    #     map.resource('setting', 'settings', controller='admin/settings', 
 
    #         path_prefix='/admin', name_prefix='admin_')
 

	
 

	
 
    @LoginRequired()
 
    #@HasPermissionAllDecorator('hg.admin')
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(SettingsController, self).__before__()
 
        
 
    def index(self, format='html'):
 
        """GET /admin/settings: All items in the collection"""
 
        # url('admin_settings')
 
        return render('admin/settings/settings.html')
 
    
 
    def create(self):
 
        """POST /admin/settings: Create a new item"""
 
        # url('admin_settings')
 

	
 
    def new(self, format='html'):
 
        """GET /admin/settings/new: Form to create a new item"""
 
        # url('admin_new_setting')
 

	
 
    def update(self, id):
 
        """PUT /admin/settings/id: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
        #    h.form(url('admin_setting', id=ID),
 
        #           method='put')
 
        # url('admin_setting', id=ID)
 

	
 
    def delete(self, id):
 
        """DELETE /admin/settings/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', id=ID),
 
        #           method='delete')
 
        # url('admin_setting', id=ID)
 

	
 
    def show(self, id, format='html'):
 
        """GET /admin/settings/id: Show a specific item"""
 
        # url('admin_setting', id=ID)
 

	
 
    def edit(self, id, format='html'):
 
        """GET /admin/settings/id/edit: Form to edit an existing item"""
 
        # url('admin_edit_setting', id=ID)
pylons_app/templates/admin/settings/settings.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Settings administration')}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${h.link_to(u'Admin',h.url('admin_home'))}
 
	 /  
 
	 ${_('Settings')}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('admin')}
 
	${self.submenu('settings')}
 
</%def>
 
<%def name="main()">
 
	<div>
 
	<h2>${_('Settings administration')}</h2>
 
	
 
    </div>
 
</%def>    
pylons_app/templates/admin/users/users.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Users administration')}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${h.link_to(u'Admin',h.url('admin_home'))}
 
	 /  
 
	 ${_('Users')}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('admin')}
 
	${self.submenu('users')}
 
</%def>
 
<%def name="main()">
 
	<div>
 
        <h2>${_('Mercurial users')}</h2>
 
        <h2>${_('Users administration')}</h2>
 
        <table class="table_disp">
 
         <tr class="header">
 
            <td>${_('username')}</td>
 
            <td>${_('name')}</td>
 
            <td>${_('lastname')}</td>
 
            <td>${_('active')}</td>
 
            <td>${_('admin')}</td>
 
            <td>${_('action')}</td>
 
         </tr>
 
            %for user in c.users_list:
 
                <tr>
 
                    <td>${h.link_to(user.username,h.url('edit_user', id=user.user_id))}</td>
 
                    <td>${user.name}</td>
 
                    <td>${user.lastname}</td>
 
                    <td>${user.active}</td>
 
                    <td>${user.admin}</td>
 
                    <td>
 
	                    ${h.form(url('user', id=user.user_id),method='delete')}
 
	                    	${h.submit('remove','delete',class_="delete_icon action_button")}
 
	                    ${h.end_form()}
 
        			</td>
 
                </tr>
 
            %endfor
 
        </table>
 
        <span class="add_icon">${h.link_to(u'add user',h.url('new_user'))}</span>        
 
    </div>
 
</%def>
pylons_app/templates/base/base.html
Show inline comments
 
@@ -89,76 +89,76 @@ def is_current(selected):
 
				})
 
	           });
 
	       	</script>       	
 
	        <ul class="page-nav">
 
				<li>
 
					<a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
 
					<div id="switch_repos" style="display:none;position: absolute;height: 25px">
 
						<select id="repos_list" size="=10" style="min-width: 150px">
 
						%for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
 
							<option value="${repo}">${repo}</option>
 
						%endfor
 
						</select>
 
					</div>			
 
				</li>
 
	            <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
 
				<li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>            
 
	            <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
 
				%if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
					<li ${is_current('settings')}>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name))}</li>
 
				%endif					        
 
	        </ul>
 
		%else:
 
		##Root menu
 
			<ul class="page-nav">
 
				<li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
 
				%if h.HasPermissionAll('hg.admin')('access admin main page'):
 
					<li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
 
				%endif
 
				<li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
 
			</ul>
 
		%endif    
 
		</div>
 
</%def>
 
<%def name="submenu(current=None)">
 
	<% 
 
	def is_current(selected):
 
		if selected == current:
 
			return "class='current_submenu'"
 
	%>
 
	%if current != None:
 
	<div>
 
    <ul class="submenu">
 
        <li ${is_current('repos')}>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
 
        <li ${is_current('users')}>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
 
        ##commented<li ${is_current('permissions')}>${h.link_to(_('permissions'),h.url('permissions'),class_='permissions')}</li>
 
		##commented<li ${is_current('settings')}>${h.link_to(_('settings'),h.url('hgapp_settings'),class_='settings')}</li>        
 
		<li ${is_current('settings')}>${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>        
 
    </ul>
 
    </div>
 
    %endif
 
</%def>
 

	
 

	
 
<%def name="css()">
 
<link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
 
</%def>
 

	
 
<%def name="js()">
 
<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
 
<script type="text/javascript" src="/js/yui/container/container-min.js"></script>
 
<script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
 
<script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
 
</%def>
 

	
 
<!-- DEFINITION OF FORM ERROR FETCHER -->
 
<%def name="get_form_error(element)">
 
	%if hasattr(c,'form_errors') and type(c.form_errors) == dict:
 
        %if c.form_errors.get(element,False):
 
            <span class="error-message">
 
                ${c.form_errors.get(element,'')}
 
            </span>
 
        %endif
 
	%endif           
 
</%def>
 
\ No newline at end of file
pylons_app/tests/functional/test_admin_settings.py
Show inline comments
 
new file 100644
 
from pylons_app.tests import *
 

	
 
class TestSettingsController(TestController):
 

	
 
    def test_index(self):
 
        response = self.app.get(url('admin_settings'))
 
        # Test response...
 

	
 
    def test_index_as_xml(self):
 
        response = self.app.get(url('formatted_admin_settings', format='xml'))
 

	
 
    def test_create(self):
 
        response = self.app.post(url('admin_settings'))
 

	
 
    def test_new(self):
 
        response = self.app.get(url('admin_new_setting'))
 

	
 
    def test_new_as_xml(self):
 
        response = self.app.get(url('formatted_admin_new_setting', format='xml'))
 

	
 
    def test_update(self):
 
        response = self.app.put(url('admin_setting', id=1))
 

	
 
    def test_update_browser_fakeout(self):
 
        response = self.app.post(url('admin_setting', id=1), params=dict(_method='put'))
 

	
 
    def test_delete(self):
 
        response = self.app.delete(url('admin_setting', id=1))
 

	
 
    def test_delete_browser_fakeout(self):
 
        response = self.app.post(url('admin_setting', id=1), params=dict(_method='delete'))
 

	
 
    def test_show(self):
 
        response = self.app.get(url('admin_setting', id=1))
 

	
 
    def test_show_as_xml(self):
 
        response = self.app.get(url('formatted_admin_setting', id=1, format='xml'))
 

	
 
    def test_edit(self):
 
        response = self.app.get(url('admin_edit_setting', id=1))
 

	
 
    def test_edit_as_xml(self):
 
        response = self.app.get(url('formatted_admin_edit_setting', id=1, format='xml'))
pylons_app/tests/functional/test_admin_settings_hg.py
Show inline comments
 
new file 100644
 
from pylons_app.tests import *
 

	
 
class TestSettingsHgController(TestController):
 

	
 
    def test_index(self):
 
        response = self.app.get(url('admin_settings_hg'))
 
        # Test response...
 

	
 
    def test_index_as_xml(self):
 
        response = self.app.get(url('formatted_admin_settings_hg', format='xml'))
 

	
 
    def test_create(self):
 
        response = self.app.post(url('admin_settings_hg'))
 

	
 
    def test_new(self):
 
        response = self.app.get(url('admin_new_setting_hg'))
 

	
 
    def test_new_as_xml(self):
 
        response = self.app.get(url('formatted_admin_new_setting_hg', format='xml'))
 

	
 
    def test_update(self):
 
        response = self.app.put(url('admin_setting_hg', id=1))
 

	
 
    def test_update_browser_fakeout(self):
 
        response = self.app.post(url('admin_setting_hg', id=1), params=dict(_method='put'))
 

	
 
    def test_delete(self):
 
        response = self.app.delete(url('admin_setting_hg', id=1))
 

	
 
    def test_delete_browser_fakeout(self):
 
        response = self.app.post(url('admin_setting_hg', id=1), params=dict(_method='delete'))
 

	
 
    def test_show(self):
 
        response = self.app.get(url('admin_setting_hg', id=1))
 

	
 
    def test_show_as_xml(self):
 
        response = self.app.get(url('formatted_admin_setting_hg', id=1, format='xml'))
 

	
 
    def test_edit(self):
 
        response = self.app.get(url('admin_edit_setting_hg', id=1))
 

	
 
    def test_edit_as_xml(self):
 
        response = self.app.get(url('formatted_admin_edit_setting_hg', id=1, format='xml'))
0 comments (0 inline, 0 general)