Changeset - 3fe3285868d1
[Not reviewed]
beta
0 6 1
Marcin Kuzminski - 15 years ago 2011-02-25 18:47:09
marcin@python-works.com
implemented public journal for anonymous users, admin can control which repositories
are visible in such journal in admin panel
7 files changed with 184 insertions and 44 deletions:
0 comments (0 inline, 0 general)
rhodecode/config/routing.py
Show inline comments
 
@@ -86,6 +86,9 @@ def make_map(config):
 
        m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
 
             action="repo_cache", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 
        m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
 
             action="repo_public_journal", conditions=dict(method=["PUT"],
 
                                                        function=check_repo))
 

	
 
    #ADMIN USER REST ROUTES
 
    routes_map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
 
@@ -145,6 +148,8 @@ def make_map(config):
 

	
 
    #USER JOURNAL
 
    routes_map.connect('journal', '/_admin/journal', controller='journal',)
 
    routes_map.connect('public_journal', '/_admin/public_journal', controller='journal',
 
                       action="public_journal")
 
    routes_map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
 
                action='toggle_following', conditions=dict(method=["POST"]))
 

	
rhodecode/controllers/admin/repos.py
Show inline comments
 
@@ -41,7 +41,8 @@ from rhodecode.lib.auth import LoginRequ
 
    HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
 
from rhodecode.model.db import User
 
from rhodecode.lib.helpers import get_token
 
from rhodecode.model.db import User, Repository, UserFollowing
 
from rhodecode.model.forms import RepoForm
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.repo import RepoModel
 
@@ -50,7 +51,8 @@ from rhodecode.model.repo import RepoMod
 
log = logging.getLogger(__name__)
 

	
 
class ReposController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    """
 
    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('repo', 'repos')
 
@@ -72,7 +74,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        """
 
        POST /repos: Create a new item"""
 
        # url('repos')
 
        repo_model = RepoModel()
 
        _form = RepoForm()()
 
@@ -124,7 +127,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def update(self, repo_name):
 
        """PUT /repos/repo_name: Update an existing item"""
 
        """
 
        PUT /repos/repo_name: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
@@ -156,6 +160,11 @@ class ReposController(BaseController):
 
            repo, dbrepo = ScmModel().get(repo_name, retval='repo')
 
            c.repo_last_rev = repo.count() if repo.revisions else 0
 

	
 
            c.default_user_id = User.by_username('default').user_id
 
            c.in_public_journal = self.sa.query(UserFollowing)\
 
                .filter(UserFollowing.user_id == c.default_user_id)\
 
                .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
            if last_rev == 0:
 
                c.stats_percentage = 0
 
            else:
 
@@ -182,7 +191,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete(self, repo_name):
 
        """DELETE /repos/repo_name: Delete an existing item"""
 
        """
 
        DELETE /repos/repo_name: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
@@ -216,7 +226,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_perm_user(self, repo_name):
 
        """DELETE an existing repository permission user
 
        """
 
        DELETE an existing repository permission user
 
        
 
        :param repo_name:
 
        """
 
@@ -231,7 +242,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_perm_users_group(self, repo_name):
 
        """DELETE an existing repository permission users group
 
        """
 
        DELETE an existing repository permission users group
 
        
 
        :param repo_name:
 
        """
 
@@ -246,7 +258,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_stats(self, repo_name):
 
        """DELETE an existing repository statistics
 
        """
 
        DELETE an existing repository statistics
 
        
 
        :param repo_name:
 
        """
 
@@ -261,7 +274,8 @@ class ReposController(BaseController):
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_cache(self, repo_name):
 
        """INVALIDATE existing repository cache
 
        """
 
        INVALIDATE existing repository cache
 
        
 
        :param repo_name:
 
        """
 
@@ -274,6 +288,35 @@ class ReposController(BaseController):
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_public_journal(self, repo_name):
 
        """
 
        Set's this repository to be visible in public journal,
 
        in other words assing default user to follow this repo
 
        
 
        :param repo_name:
 
        """
 

	
 
        cur_token = request.POST.get('auth_token')
 
        token = get_token()
 
        if cur_token == token:
 
            try:
 
                repo_id = Repository.by_repo_name(repo_name).repo_id
 
                user_id = User.by_username('default').user_id
 
                self.scm_model.toggle_following_repo(repo_id, user_id)
 
                h.flash(_('Updated repository visibility in public journal'),
 
                        category='success')
 
            except:
 
                h.flash(_('An error occurred during setting this'
 
                          ' repository in public journal'),
 
                        category='error')
 

	
 
        else:
 
            h.flash(_('Token mismatch'), category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 

	
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def show(self, repo_name, format='html'):
 
        """GET /repos/repo_name: Show a specific item"""
 
        # url('repo', repo_name=ID)
 
@@ -296,6 +339,11 @@ class ReposController(BaseController):
 

	
 
            return redirect(url('repos'))
 

	
 
        c.default_user_id = User.by_username('default').user_id
 
        c.in_public_journal = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.default_user_id)\
 
            .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
        if c.repo_info.stats:
 
            last_rev = c.repo_info.stats.stat_on_revision
 
        else:
rhodecode/controllers/journal.py
Show inline comments
 
@@ -45,42 +45,20 @@ class JournalController(BaseController):
 

	
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def __before__(self):
 
        super(JournalController, self).__before__()
 

	
 
    @NotAnonymous()
 
    def index(self):
 
        # Return a rendered template
 
        p = int(request.params.get('page', 1))
 

	
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 

	
 
        repo_ids = [x.follows_repository.repo_id for x in c.following
 
                    if x.follows_repository is not None]
 
        user_ids = [x.follows_user.user_id for x in c.following
 
                    if x.follows_user is not None]
 

	
 
        filtering_criterion = None
 

	
 
        if repo_ids and user_ids:
 
            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
 
                        UserLog.user_id.in_(user_ids))
 
        if repo_ids and not user_ids:
 
            filtering_criterion = UserLog.repository_id.in_(repo_ids)
 
        if not repo_ids and user_ids:
 
            filtering_criterion = UserLog.user_id.in_(user_ids)
 
        if filtering_criterion is not None:
 
            journal = self.sa.query(UserLog)\
 
                .options(joinedload(UserLog.user))\
 
                .options(joinedload(UserLog.repository))\
 
                .filter(filtering_criterion)\
 
                .order_by(UserLog.action_date.desc())
 
        else:
 
            journal = []
 
        p = int(request.params.get('page', 1))
 
        journal = self._get_journal_data(c.following)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20)
 

	
 
@@ -105,6 +83,34 @@ class JournalController(BaseController):
 
        return groups
 

	
 

	
 
    def _get_journal_data(self, following_repos):
 
        repo_ids = [x.follows_repository.repo_id for x in following_repos
 
                    if x.follows_repository is not None]
 
        user_ids = [x.follows_user.user_id for x in following_repos
 
                    if x.follows_user is not None]
 

	
 
        filtering_criterion = None
 

	
 
        if repo_ids and user_ids:
 
            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
 
                        UserLog.user_id.in_(user_ids))
 
        if repo_ids and not user_ids:
 
            filtering_criterion = UserLog.repository_id.in_(repo_ids)
 
        if not repo_ids and user_ids:
 
            filtering_criterion = UserLog.user_id.in_(user_ids)
 
        if filtering_criterion is not None:
 
            journal = self.sa.query(UserLog)\
 
                .options(joinedload(UserLog.user))\
 
                .options(joinedload(UserLog.repository))\
 
                .filter(filtering_criterion)\
 
                .order_by(UserLog.action_date.desc())
 
        else:
 
            journal = []
 

	
 

	
 
        return journal
 

	
 
    @NotAnonymous()
 
    def toggle_following(self):
 
        cur_token = request.POST.get('auth_token')
 
        token = get_token()
 
@@ -131,3 +137,26 @@ class JournalController(BaseController):
 

	
 
        log.debug('token mismatch %s vs %s', cur_token, token)
 
        raise HTTPInternalServerError()
 

	
 

	
 

	
 

	
 
    def public_journal(self):
 
        # Return a rendered template
 
        p = int(request.params.get('page', 1))
 

	
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        journal = self._get_journal_data(c.following)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20)
 

	
 
        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
 

	
 
        c.journal_data = render('journal/journal_data.html')
 
        if request.params.get('partial'):
 
            return c.journal_data
 
        return render('journal/public_journal.html')
rhodecode/public/css/style.css
Show inline comments
 
@@ -1987,6 +1987,20 @@ padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
.start_following_icon {
 
background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
.stop_following_icon {
 
background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
 
.action_button {
 
border:0;
rhodecode/templates/admin/repos/repo_edit.html
Show inline comments
 
@@ -302,7 +302,6 @@
 
        <div class="form">
 
           <div class="fields">
 
               ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('Confirm to remove current statistics');")}
 
               
 
               <div class="field">
 
               <ul>
 
                    <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
 
@@ -323,6 +322,19 @@
 
        </div>                    
 
        ${h.end_form()}
 
        
 
        <h3>${_('Public journal')}</h3>
 
        ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
 
        <div class="form">
 
            <div class="fields">
 
                ${h.hidden('auth_token',str(h.get_token()))}
 
                %if c.in_public_journal:
 
                    ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")}
 
                %else:
 
		            ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")}
 
		        %endif
 
	         </div>        
 
        </div>
 
        ${h.end_form()}
 
        
 
        <h3>${_('Delete')}</h3>
 
        ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
rhodecode/templates/base/base.html
Show inline comments
 
@@ -38,12 +38,7 @@
 
	                </div>
 
		            <div class="account">
 
		            %if c.rhodecode_user.username == 'default':
 
                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')(): 
 
                            ${h.link_to('anonymous',h.url('register'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
                        %else:
 
                            ${h.link_to('anonymous',h.url('#'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
                        %endif		            
 
                        
 
		                <a href="${h.url('public_journal')}">${_('Public journal')}</a>   
 
                    %else:                        		            
 
		            	${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
		            %endif
 
@@ -373,20 +368,26 @@ function onSuccess(target){
 
    }
 
}
 

	
 
function toggleFollowingUser(fallows_user_id,token){
 
function toggleFollowingUser(target,fallows_user_id,token,user_id){
 
    args = 'follows_user_id='+fallows_user_id;
 
    args+= '&amp;auth_token='+token;
 
    if(user_id != undefined){
 
    	args+="&amp;user_id="+user_id;
 
    }
 
    YUC.asyncRequest('POST',base_url,{
 
        success:function(o){
 
        	onSuccess();
 
        	onSuccess(target);
 
        }
 
    },args); return false;
 
}
 

	
 
function toggleFollowingRepo(target,fallows_repo_id,token){
 
function toggleFollowingRepo(target,fallows_repo_id,token,user_id){
 

	
 
    args = 'follows_repo_id='+fallows_repo_id;
 
    args+= '&amp;auth_token='+token;
 
    if(user_id != undefined){
 
        args+="&amp;user_id="+user_id;
 
    }    
 
    YUC.asyncRequest('POST',base_url,{
 
        success:function(o){
 
        	onSuccess(target);
rhodecode/templates/journal/public_journal.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 
<%def name="title()">
 
    ${_('Journal')} - ${c.rhodecode_name}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${c.rhodecode_name}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('home')}
 
</%def>
 
<%def name="main()">
 
	
 
    <div class="box">
 
	    <!-- box / title -->
 
	    <div class="title">
 
	        <h5>${_('Public Journal')}</h5>
 
	    </div>
 
		<script type="text/javascript">
 
		function show_more_event(){
 
		YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
 
		    var el = e.target;
 
		    YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
 
		    YUD.setStyle(el.parentNode,'display','none');
 
		});
 
		}
 
		</script> 	    
 
	    <div id="journal">${c.journal_data}</div>
 
    </div>
 
     
 
</%def>    
0 comments (0 inline, 0 general)