journal.py
319 lines
| 11.6 KiB
| text/x-python
|
PythonLexer
Bradley M. Kuhn
|
r4187 | # -*- coding: utf-8 -*- | ||
# 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, either version 3 of the License, or | ||||
# (at your option) any later version. | ||||
# | ||||
# 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, see <http://www.gnu.org/licenses/>. | ||||
""" | ||||
kallithea.controllers.journal | ||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
Thomas De Schampheleire
|
r6178 | Journal controller | ||
Bradley M. Kuhn
|
r4187 | |||
Bradley M. Kuhn
|
r4211 | This file was forked by the Kallithea project in July 2014. | ||
Original author and date, and relevant copyright and licensing information is below: | ||||
Bradley M. Kuhn
|
r4187 | :created_on: Nov 21, 2010 | ||
:author: marcink | ||||
Bradley M. Kuhn
|
r4211 | :copyright: (c) 2013 RhodeCode GmbH, and others. | ||
Bradley M. Kuhn
|
r4208 | :license: GPLv3, see LICENSE.md for more details. | ||
Bradley M. Kuhn
|
r4187 | |||
""" | ||||
import logging | ||||
Mads Kiilerich
|
r4733 | import traceback | ||
Bradley M. Kuhn
|
r4187 | from itertools import groupby | ||
from sqlalchemy import or_ | ||||
from sqlalchemy.orm import joinedload | ||||
from sqlalchemy.sql.expression import func | ||||
from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed | ||||
from webob.exc import HTTPBadRequest | ||||
Mads Kiilerich
|
r6508 | from tg import request, tmpl_context as c, response | ||
from tg.i18n import ugettext as _ | ||||
Bradley M. Kuhn
|
r4187 | |||
Thomas De Schampheleire
|
r6182 | from kallithea.config.routing import url | ||
Bradley M. Kuhn
|
r4187 | from kallithea.controllers.admin.admin import _journal_filter | ||
from kallithea.model.db import UserLog, UserFollowing, Repository, User | ||||
from kallithea.model.meta import Session | ||||
from kallithea.model.repo import RepoModel | ||||
import kallithea.lib.helpers as h | ||||
from kallithea.lib.auth import LoginRequired, NotAnonymous | ||||
from kallithea.lib.base import BaseController, render | ||||
Thomas De Schampheleire
|
r6215 | from kallithea.lib.page import Page | ||
Bradley M. Kuhn
|
r4187 | from kallithea.lib.utils2 import safe_int, AttributeDict | ||
log = logging.getLogger(__name__) | ||||
Mads Kiilerich
|
r6411 | language = 'en-us' | ||
ttl = "5" | ||||
feed_nr = 20 | ||||
Bradley M. Kuhn
|
r4187 | class JournalController(BaseController): | ||
Thomas De Schampheleire
|
r6513 | def _before(self, *args, **kwargs): | ||
super(JournalController, self)._before(*args, **kwargs) | ||||
Bradley M. Kuhn
|
r4187 | c.search_term = request.GET.get('filter') | ||
def _get_daily_aggregate(self, journal): | ||||
groups = [] | ||||
for k, g in groupby(journal, lambda x: x.action_as_day): | ||||
user_group = [] | ||||
Lars Kruse
|
r6789 | # groupby username if it's a present value, else fallback to journal username | ||
Mads Kiilerich
|
r4424 | for _unused, g2 in groupby(list(g), lambda x: x.user.username if x.user else x.username): | ||
Bradley M. Kuhn
|
r4187 | l = list(g2) | ||
user_group.append((l[0].user, l)) | ||||
groups.append((k, user_group,)) | ||||
return groups | ||||
def _get_journal_data(self, following_repos): | ||||
Søren Løvborg
|
r6281 | repo_ids = [x.follows_repository_id for x in following_repos | ||
if x.follows_repository_id is not None] | ||||
Søren Løvborg
|
r6197 | user_ids = [x.follows_user_id for x in following_repos | ||
if x.follows_user_id is not None] | ||||
Bradley M. Kuhn
|
r4187 | |||
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: | ||||
Søren Løvborg
|
r6483 | journal = UserLog.query() \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserLog.user)) \ | ||
Bradley M. Kuhn
|
r4187 | .options(joinedload(UserLog.repository)) | ||
Lars Kruse
|
r6789 | # filter | ||
Mads Kiilerich
|
r4733 | journal = _journal_filter(journal, c.search_term) | ||
Mads Kiilerich
|
r5585 | journal = journal.filter(filtering_criterion) \ | ||
Bradley M. Kuhn
|
r4187 | .order_by(UserLog.action_date.desc()) | ||
else: | ||||
journal = [] | ||||
return journal | ||||
def _atom_feed(self, repos, public=True): | ||||
journal = self._get_journal_data(repos) | ||||
if public: | ||||
Mads Kiilerich
|
r4445 | _link = h.canonical_url('public_journal_atom') | ||
Mads Kiilerich
|
r5127 | _desc = '%s %s %s' % (c.site_name, _('Public Journal'), | ||
Bradley M. Kuhn
|
r4187 | 'atom feed') | ||
else: | ||||
Mads Kiilerich
|
r4445 | _link = h.canonical_url('journal_atom') | ||
Mads Kiilerich
|
r5127 | _desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed') | ||
Bradley M. Kuhn
|
r4187 | |||
feed = Atom1Feed(title=_desc, | ||||
link=_link, | ||||
description=_desc, | ||||
Mads Kiilerich
|
r6411 | language=language, | ||
ttl=ttl) | ||||
Bradley M. Kuhn
|
r4187 | |||
Mads Kiilerich
|
r6411 | for entry in journal[:feed_nr]: | ||
Bradley M. Kuhn
|
r4187 | user = entry.user | ||
if user is None: | ||||
Lars Kruse
|
r6789 | # fix deleted users | ||
Bradley M. Kuhn
|
r4187 | user = AttributeDict({'short_contact': entry.username, | ||
'email': '', | ||||
'full_contact': ''}) | ||||
action, action_extra, ico = h.action_parser(entry, feed=True) | ||||
title = "%s - %s %s" % (user.short_contact, action(), | ||||
entry.repository.repo_name) | ||||
desc = action_extra() | ||||
_url = None | ||||
if entry.repository is not None: | ||||
Mads Kiilerich
|
r4445 | _url = h.canonical_url('changelog_home', | ||
repo_name=entry.repository.repo_name) | ||||
Bradley M. Kuhn
|
r4187 | |||
feed.add_item(title=title, | ||||
pubdate=entry.action_date, | ||||
Mads Kiilerich
|
r4445 | link=_url or h.canonical_url(''), | ||
Bradley M. Kuhn
|
r4187 | author_email=user.email, | ||
author_name=user.full_contact, | ||||
description=desc) | ||||
response.content_type = feed.mime_type | ||||
return feed.writeString('utf-8') | ||||
def _rss_feed(self, repos, public=True): | ||||
journal = self._get_journal_data(repos) | ||||
if public: | ||||
Mads Kiilerich
|
r4445 | _link = h.canonical_url('public_journal_atom') | ||
Mads Kiilerich
|
r5127 | _desc = '%s %s %s' % (c.site_name, _('Public Journal'), | ||
Bradley M. Kuhn
|
r4187 | 'rss feed') | ||
else: | ||||
Mads Kiilerich
|
r4445 | _link = h.canonical_url('journal_atom') | ||
Mads Kiilerich
|
r5127 | _desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed') | ||
Bradley M. Kuhn
|
r4187 | |||
feed = Rss201rev2Feed(title=_desc, | ||||
link=_link, | ||||
description=_desc, | ||||
Mads Kiilerich
|
r6411 | language=language, | ||
ttl=ttl) | ||||
Bradley M. Kuhn
|
r4187 | |||
Mads Kiilerich
|
r6411 | for entry in journal[:feed_nr]: | ||
Bradley M. Kuhn
|
r4187 | user = entry.user | ||
if user is None: | ||||
Lars Kruse
|
r6789 | # fix deleted users | ||
Bradley M. Kuhn
|
r4187 | user = AttributeDict({'short_contact': entry.username, | ||
'email': '', | ||||
'full_contact': ''}) | ||||
action, action_extra, ico = h.action_parser(entry, feed=True) | ||||
title = "%s - %s %s" % (user.short_contact, action(), | ||||
entry.repository.repo_name) | ||||
desc = action_extra() | ||||
_url = None | ||||
if entry.repository is not None: | ||||
Mads Kiilerich
|
r4445 | _url = h.canonical_url('changelog_home', | ||
repo_name=entry.repository.repo_name) | ||||
Bradley M. Kuhn
|
r4187 | |||
feed.add_item(title=title, | ||||
pubdate=entry.action_date, | ||||
Mads Kiilerich
|
r4445 | link=_url or h.canonical_url(''), | ||
Bradley M. Kuhn
|
r4187 | author_email=user.email, | ||
author_name=user.full_contact, | ||||
description=desc) | ||||
response.content_type = feed.mime_type | ||||
return feed.writeString('utf-8') | ||||
@LoginRequired() | ||||
@NotAnonymous() | ||||
def index(self): | ||||
# Return a rendered template | ||||
Mads Kiilerich
|
r5992 | p = safe_int(request.GET.get('page'), 1) | ||
Mads Kiilerich
|
r6412 | c.user = User.get(request.authuser.user_id) | ||
Søren Løvborg
|
r6483 | c.following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
journal = self._get_journal_data(c.following) | ||||
def url_generator(**kw): | ||||
return url.current(filter=c.search_term, **kw) | ||||
c.journal_pager = Page(journal, page=p, items_per_page=20, url=url_generator) | ||||
timeless@gmail.com
|
r5783 | c.journal_day_aggregate = self._get_daily_aggregate(c.journal_pager) | ||
Bradley M. Kuhn
|
r4187 | |||
if request.environ.get('HTTP_X_PARTIAL_XHR'): | ||||
Thomas De Schampheleire
|
r4850 | return render('journal/journal_data.html') | ||
Bradley M. Kuhn
|
r4187 | |||
Søren Løvborg
|
r6186 | repos_list = Repository.query(sorted=True) \ | ||
Mads Kiilerich
|
r6412 | .filter_by(owner_id=request.authuser.user_id).all() | ||
Bradley M. Kuhn
|
r4187 | |||
repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, | ||||
admin=True) | ||||
Lars Kruse
|
r6789 | # data used to render the grid | ||
Søren Løvborg
|
r6492 | c.data = repos_data | ||
Bradley M. Kuhn
|
r4187 | |||
return render('journal/journal.html') | ||||
@LoginRequired(api_access=True) | ||||
@NotAnonymous() | ||||
def journal_atom(self): | ||||
""" | ||||
Produce an atom-1.0 feed via feedgenerator module | ||||
""" | ||||
Søren Løvborg
|
r6483 | following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
return self._atom_feed(following, public=False) | ||||
@LoginRequired(api_access=True) | ||||
@NotAnonymous() | ||||
def journal_rss(self): | ||||
""" | ||||
Produce an rss feed via feedgenerator module | ||||
""" | ||||
Søren Løvborg
|
r6483 | following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
return self._rss_feed(following, public=False) | ||||
@LoginRequired() | ||||
@NotAnonymous() | ||||
def toggle_following(self): | ||||
Mads Kiilerich
|
r4990 | user_id = request.POST.get('follows_user_id') | ||
if user_id: | ||||
try: | ||||
self.scm_model.toggle_following_user(user_id, | ||||
Mads Kiilerich
|
r6412 | request.authuser.user_id) | ||
domruf
|
r6578 | Session().commit() | ||
Mads Kiilerich
|
r4990 | return 'ok' | ||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
raise HTTPBadRequest() | ||||
Bradley M. Kuhn
|
r4187 | |||
Søren Løvborg
|
r6281 | repo_id = request.POST.get('follows_repository_id') | ||
Mads Kiilerich
|
r4990 | if repo_id: | ||
try: | ||||
self.scm_model.toggle_following_repo(repo_id, | ||||
Mads Kiilerich
|
r6412 | request.authuser.user_id) | ||
domruf
|
r6578 | Session().commit() | ||
Mads Kiilerich
|
r4990 | return 'ok' | ||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
raise HTTPBadRequest() | ||||
Bradley M. Kuhn
|
r4187 | |||
raise HTTPBadRequest() | ||||
@LoginRequired() | ||||
def public_journal(self): | ||||
# Return a rendered template | ||||
Mads Kiilerich
|
r5992 | p = safe_int(request.GET.get('page'), 1) | ||
Bradley M. Kuhn
|
r4187 | |||
Søren Løvborg
|
r6483 | c.following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
journal = self._get_journal_data(c.following) | ||||
c.journal_pager = Page(journal, page=p, items_per_page=20) | ||||
timeless@gmail.com
|
r5783 | c.journal_day_aggregate = self._get_daily_aggregate(c.journal_pager) | ||
Bradley M. Kuhn
|
r4187 | |||
if request.environ.get('HTTP_X_PARTIAL_XHR'): | ||||
Thomas De Schampheleire
|
r4850 | return render('journal/journal_data.html') | ||
Bradley M. Kuhn
|
r4187 | return render('journal/public_journal.html') | ||
@LoginRequired(api_access=True) | ||||
def public_journal_atom(self): | ||||
""" | ||||
Produce an atom-1.0 feed via feedgenerator module | ||||
""" | ||||
Søren Løvborg
|
r6483 | c.following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
return self._atom_feed(c.following) | ||||
@LoginRequired(api_access=True) | ||||
def public_journal_rss(self): | ||||
""" | ||||
Produce an rss2 feed via feedgenerator module | ||||
""" | ||||
Søren Løvborg
|
r6483 | c.following = UserFollowing.query() \ | ||
Mads Kiilerich
|
r6412 | .filter(UserFollowing.user_id == request.authuser.user_id) \ | ||
Mads Kiilerich
|
r5585 | .options(joinedload(UserFollowing.follows_repository)) \ | ||
Bradley M. Kuhn
|
r4187 | .all() | ||
return self._rss_feed(c.following) | ||||