# HG changeset patch # User Marcin Kuzminski # Date 2013-04-14 22:46:34 # Node ID b950b884ab87d386868c1b4e013b374a82f51de4 # Parent 9d743ca9cedebb14bec6d577dcaa91c6a3dc2aa5 auth decorators are not used anymore on __before__ - this will allow to create a whitelist of API enabled controller functions - moved around functions with _ to beginning of the files to make it cleaner diff --git a/rhodecode/controllers/bookmarks.py b/rhodecode/controllers/bookmarks.py --- a/rhodecode/controllers/bookmarks.py +++ b/rhodecode/controllers/bookmarks.py @@ -36,12 +36,12 @@ log = logging.getLogger(__name__) class BookmarksController(BaseRepoController): + def __before__(self): + super(BookmarksController, self).__before__() + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def __before__(self): - super(BookmarksController, self).__before__() - def index(self): if c.rhodecode_repo.alias != 'hg': raise HTTPNotFound() diff --git a/rhodecode/controllers/branches.py b/rhodecode/controllers/branches.py --- a/rhodecode/controllers/branches.py +++ b/rhodecode/controllers/branches.py @@ -38,12 +38,12 @@ log = logging.getLogger(__name__) class BranchesController(BaseRepoController): + def __before__(self): + super(BranchesController, self).__before__() + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def __before__(self): - super(BranchesController, self).__before__() - def index(self): def _branchtags(localrepo): @@ -72,5 +72,4 @@ class BranchesController(BaseRepoControl key=lambda ctx: ctx[0], reverse=False)) - return render('branches/branches.html') diff --git a/rhodecode/controllers/changelog.py b/rhodecode/controllers/changelog.py --- a/rhodecode/controllers/changelog.py +++ b/rhodecode/controllers/changelog.py @@ -44,13 +44,37 @@ log = logging.getLogger(__name__) class ChangelogController(BaseRepoController): - @LoginRequired() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') def __before__(self): super(ChangelogController, self).__before__() c.affected_files_cut_off = 60 + def _graph(self, repo, revs_int, repo_size, size, p): + """ + Generates a DAG graph for repo + + :param repo: + :param revs_int: + :param repo_size: + :param size: + :param p: + """ + if not revs_int: + c.jsdata = json.dumps([]) + return + + data = [] + revs = revs_int + + dag = _dagwalker(repo, revs, repo.alias) + dag = _colored(dag) + for (id, type, ctx, vtx, edges) in dag: + data.append(['', vtx, edges]) + + c.jsdata = json.dumps(data) + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def index(self): limit = 100 default = 20 @@ -89,31 +113,10 @@ class ChangelogController(BaseRepoContro return render('changelog/changelog.html') + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def changelog_details(self, cs): if request.environ.get('HTTP_X_PARTIAL_XHR'): c.cs = c.rhodecode_repo.get_changeset(cs) return render('changelog/changelog_details.html') - - def _graph(self, repo, revs_int, repo_size, size, p): - """ - Generates a DAG graph for repo - - :param repo: - :param revs_int: - :param repo_size: - :param size: - :param p: - """ - if not revs_int: - c.jsdata = json.dumps([]) - return - - data = [] - revs = revs_int - - dag = _dagwalker(repo, revs, repo.alias) - dag = _colored(dag) - for (id, type, ctx, vtx, edges) in dag: - data.append(['', vtx, edges]) - - c.jsdata = json.dumps(data) diff --git a/rhodecode/controllers/changeset.py b/rhodecode/controllers/changeset.py --- a/rhodecode/controllers/changeset.py +++ b/rhodecode/controllers/changeset.py @@ -170,9 +170,6 @@ def _context_url(GET, fileid=None): class ChangesetController(BaseRepoController): - @LoginRequired() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') def __before__(self): super(ChangesetController, self).__before__() c.affected_files_cut_off = 60 @@ -180,6 +177,9 @@ class ChangesetController(BaseRepoContro c.users_array = repo_model.get_users_js() c.users_groups_array = repo_model.get_users_groups_js() + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def index(self, revision, method='show'): c.anchor_url = anchor_url c.ignorews_url = _ignorews_url @@ -312,16 +312,28 @@ class ChangesetController(BaseRepoContro else: return render('changeset/changeset_range.html') + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def changeset_raw(self, revision): return self.index(revision, method='raw') + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def changeset_patch(self, revision): return self.index(revision, method='patch') + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def changeset_download(self, revision): return self.index(revision, method='download') + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def comment(self, repo_name, revision): status = request.POST.get('changeset_status') @@ -384,7 +396,10 @@ class ChangesetController(BaseRepoContro return data + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def preview_comment(self): if not request.environ.get('HTTP_X_PARTIAL_XHR'): raise HTTPBadRequest() @@ -393,7 +408,10 @@ class ChangesetController(BaseRepoContro return h.rst_w_mentions(text) return '' + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) @@ -405,6 +423,9 @@ class ChangesetController(BaseRepoContro else: raise HTTPForbidden() + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def changeset_info(self, repo_name, revision): if request.is_xhr: diff --git a/rhodecode/controllers/compare.py b/rhodecode/controllers/compare.py --- a/rhodecode/controllers/compare.py +++ b/rhodecode/controllers/compare.py @@ -51,9 +51,6 @@ log = logging.getLogger(__name__) class CompareController(BaseRepoController): - @LoginRequired() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') def __before__(self): super(CompareController, self).__before__() @@ -85,6 +82,82 @@ class CompareController(BaseRepoControll redirect(h.url('summary_home', repo_name=repo.repo_name)) raise HTTPBadRequest() + def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref, merge): + """ + Returns a list of changesets that can be merged from org_repo@org_ref + to other_repo@other_ref ... and the ancestor that would be used for merge + + :param org_repo: + :param org_ref: + :param other_repo: + :param other_ref: + :param tmp: + """ + + ancestor = None + + if alias == 'hg': + # lookup up the exact node id + _revset_predicates = { + 'branch': 'branch', + 'book': 'bookmark', + 'tag': 'tag', + 'rev': 'id', + } + + org_rev_spec = "max(%s('%s'))" % (_revset_predicates[org_ref[0]], + safe_str(org_ref[1])) + org_revs = scmutil.revrange(org_repo._repo, [org_rev_spec]) + org_rev = org_repo._repo[org_revs[-1] if org_revs else -1].hex() + + other_rev_spec = "max(%s('%s'))" % (_revset_predicates[other_ref[0]], + safe_str(other_ref[1])) + other_revs = scmutil.revrange(other_repo._repo, [other_rev_spec]) + other_rev = other_repo._repo[other_revs[-1] if other_revs else -1].hex() + + #case two independent repos + if org_repo != other_repo: + hgrepo = unionrepo.unionrepository(other_repo.baseui, + other_repo.path, + org_repo.path) + # all the changesets we are looking for will be in other_repo, + # so rev numbers from hgrepo can be used in other_repo + + #no remote compare do it on the same repository + else: + hgrepo = other_repo._repo + + if merge: + revs = ["ancestors(id('%s')) and not ancestors(id('%s')) and not id('%s')" % + (other_rev, org_rev, org_rev)] + + ancestors = scmutil.revrange(hgrepo, + ["ancestor(id('%s'), id('%s'))" % (org_rev, other_rev)]) + if ancestors: + # pick arbitrary ancestor - but there is usually only one + ancestor = hgrepo[ancestors[0]].hex() + else: + # TODO: have both + and - changesets + revs = ["id('%s') :: id('%s') - id('%s')" % + (org_rev, other_rev, org_rev)] + + changesets = [other_repo.get_changeset(cs) + for cs in scmutil.revrange(hgrepo, revs)] + + elif alias == 'git': + assert org_repo == other_repo, (org_repo, other_repo) # no git support for different repos + so, se = org_repo.run_git_command( + 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1], + other_ref[1]) + ) + changesets = [org_repo.get_changeset(cs) + for cs in re.findall(r'[0-9a-fA-F]{40}', so)] + + return changesets, ancestor + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def index(self, org_ref_type, org_ref, other_ref_type, other_ref): # org_ref will be evaluated in org_repo org_repo = c.rhodecode_db_repo.repo_name @@ -194,76 +267,3 @@ class CompareController(BaseRepoControll c.changes[fid] = [f['operation'], f['filename'], diff] return render('compare/compare_diff.html') - - def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref, merge): - """ - Returns a list of changesets that can be merged from org_repo@org_ref - to other_repo@other_ref ... and the ancestor that would be used for merge - - :param org_repo: - :param org_ref: - :param other_repo: - :param other_ref: - :param tmp: - """ - - ancestor = None - - if alias == 'hg': - # lookup up the exact node id - _revset_predicates = { - 'branch': 'branch', - 'book': 'bookmark', - 'tag': 'tag', - 'rev': 'id', - } - - org_rev_spec = "max(%s('%s'))" % (_revset_predicates[org_ref[0]], - safe_str(org_ref[1])) - org_revs = scmutil.revrange(org_repo._repo, [org_rev_spec]) - org_rev = org_repo._repo[org_revs[-1] if org_revs else -1].hex() - - other_rev_spec = "max(%s('%s'))" % (_revset_predicates[other_ref[0]], - safe_str(other_ref[1])) - other_revs = scmutil.revrange(other_repo._repo, [other_rev_spec]) - other_rev = other_repo._repo[other_revs[-1] if other_revs else -1].hex() - - #case two independent repos - if org_repo != other_repo: - hgrepo = unionrepo.unionrepository(other_repo.baseui, - other_repo.path, - org_repo.path) - # all the changesets we are looking for will be in other_repo, - # so rev numbers from hgrepo can be used in other_repo - - #no remote compare do it on the same repository - else: - hgrepo = other_repo._repo - - if merge: - revs = ["ancestors(id('%s')) and not ancestors(id('%s')) and not id('%s')" % - (other_rev, org_rev, org_rev)] - - ancestors = scmutil.revrange(hgrepo, - ["ancestor(id('%s'), id('%s'))" % (org_rev, other_rev)]) - if ancestors: - # pick arbitrary ancestor - but there is usually only one - ancestor = hgrepo[ancestors[0]].hex() - else: - # TODO: have both + and - changesets - revs = ["id('%s') :: id('%s') - id('%s')" % - (org_rev, other_rev, org_rev)] - - changesets = [other_repo.get_changeset(cs) - for cs in scmutil.revrange(hgrepo, revs)] - - elif alias == 'git': - assert org_repo == other_repo, (org_repo, other_repo) # no git support for different repos - so, se = org_repo.run_git_command( - 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1], - other_ref[1]) - ) - changesets = [org_repo.get_changeset(cs) - for cs in re.findall(r'[0-9a-fA-F]{40}', so)] - - return changesets, ancestor diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -182,6 +182,9 @@ class FilesController(BaseRepoController return render('files/files.html') + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def history(self, repo_name, revision, f_path, annotate=False): if request.environ.get('HTTP_X_PARTIAL_XHR'): c.changeset = self.__get_cs_or_redirect(revision, repo_name) diff --git a/rhodecode/controllers/followers.py b/rhodecode/controllers/followers.py --- a/rhodecode/controllers/followers.py +++ b/rhodecode/controllers/followers.py @@ -37,12 +37,12 @@ log = logging.getLogger(__name__) class FollowersController(BaseRepoController): + def __before__(self): + super(FollowersController, self).__before__() + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def __before__(self): - super(FollowersController, self).__before__() - def followers(self, repo_name): p = safe_int(request.GET.get('page', 1), 1) repo_id = c.rhodecode_db_repo.repo_id diff --git a/rhodecode/controllers/forks.py b/rhodecode/controllers/forks.py --- a/rhodecode/controllers/forks.py +++ b/rhodecode/controllers/forks.py @@ -50,7 +50,6 @@ log = logging.getLogger(__name__) class ForksController(BaseRepoController): - @LoginRequired() def __before__(self): super(ForksController, self).__before__() @@ -107,6 +106,7 @@ class ForksController(BaseRepoController return defaults + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def forks(self, repo_name): @@ -128,6 +128,7 @@ class ForksController(BaseRepoController return render('/forks/forks.html') + @LoginRequired() @NotAnonymous() @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', @@ -147,6 +148,7 @@ class ForksController(BaseRepoController force_defaults=False ) + @LoginRequired() @NotAnonymous() @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', diff --git a/rhodecode/controllers/home.py b/rhodecode/controllers/home.py --- a/rhodecode/controllers/home.py +++ b/rhodecode/controllers/home.py @@ -44,10 +44,10 @@ log = logging.getLogger(__name__) class HomeController(BaseController): - @LoginRequired() def __before__(self): super(HomeController, self).__before__() + @LoginRequired() def index(self): c.groups = self.scm_model.get_repos_groups() c.group = None @@ -68,6 +68,7 @@ class HomeController(BaseController): return render('/index.html') + @LoginRequired() def repo_switcher(self): if request.is_xhr: all_repos = Repository.query().order_by(Repository.repo_name).all() @@ -78,6 +79,7 @@ class HomeController(BaseController): else: raise HTTPBadRequest() + @LoginRequired() def branch_tag_switcher(self, repo_name): if request.is_xhr: c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) diff --git a/rhodecode/controllers/journal.py b/rhodecode/controllers/journal.py --- a/rhodecode/controllers/journal.py +++ b/rhodecode/controllers/journal.py @@ -58,6 +58,137 @@ class JournalController(BaseController): self.feed_nr = 20 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 = [] + #groupby username if it's a present value, else fallback to journal username + for _, g2 in groupby(list(g), lambda x: x.user.username if x.user else x.username): + l = list(g2) + user_group.append((l[0].user, l)) + + groups.append((k, user_group,)) + + 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 + try: + journal = _journal_filter(journal, c.search_term) + except Exception: + # we want this to crash for now + raise + journal = journal.filter(filtering_criterion)\ + .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: + _link = url('public_journal_atom', qualified=True) + _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), + 'atom feed') + else: + _link = url('journal_atom', qualified=True) + _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed') + + feed = Atom1Feed(title=_desc, + link=_link, + description=_desc, + language=self.language, + ttl=self.ttl) + + for entry in journal[:self.feed_nr]: + user = entry.user + if user is None: + #fix deleted users + 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: + _url = url('changelog_home', + repo_name=entry.repository.repo_name, + qualified=True) + + feed.add_item(title=title, + pubdate=entry.action_date, + link=_url or url('', qualified=True), + 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: + _link = url('public_journal_atom', qualified=True) + _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), + 'rss feed') + else: + _link = url('journal_atom', qualified=True) + _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed') + + feed = Rss201rev2Feed(title=_desc, + link=_link, + description=_desc, + language=self.language, + ttl=self.ttl) + + for entry in journal[:self.feed_nr]: + user = entry.user + if user is None: + #fix deleted users + 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: + _url = url('changelog_home', + repo_name=entry.repository.repo_name, + qualified=True) + + feed.add_item(title=title, + pubdate=entry.action_date, + link=_url or url('', qualified=True), + 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): @@ -172,51 +303,6 @@ class JournalController(BaseController): .all() return self._rss_feed(following, public=False) - def _get_daily_aggregate(self, journal): - groups = [] - for k, g in groupby(journal, lambda x: x.action_as_day): - user_group = [] - #groupby username if it's a present value, else fallback to journal username - for _, g2 in groupby(list(g), lambda x: x.user.username if x.user else x.username): - l = list(g2) - user_group.append((l[0].user, l)) - - groups.append((k, user_group,)) - - 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 - try: - journal = _journal_filter(journal, c.search_term) - except Exception: - # we want this to crash for now - raise - journal = journal.filter(filtering_criterion)\ - .order_by(UserLog.action_date.desc()) - else: - journal = [] - - return journal - @LoginRequired() @NotAnonymous() def toggle_following(self): @@ -268,92 +354,6 @@ class JournalController(BaseController): return c.journal_data return render('journal/public_journal.html') - def _atom_feed(self, repos, public=True): - journal = self._get_journal_data(repos) - if public: - _link = url('public_journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), - 'atom feed') - else: - _link = url('journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed') - - feed = Atom1Feed(title=_desc, - link=_link, - description=_desc, - language=self.language, - ttl=self.ttl) - - for entry in journal[:self.feed_nr]: - user = entry.user - if user is None: - #fix deleted users - 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: - _url = url('changelog_home', - repo_name=entry.repository.repo_name, - qualified=True) - - feed.add_item(title=title, - pubdate=entry.action_date, - link=_url or url('', qualified=True), - 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: - _link = url('public_journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), - 'rss feed') - else: - _link = url('journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed') - - feed = Rss201rev2Feed(title=_desc, - link=_link, - description=_desc, - language=self.language, - ttl=self.ttl) - - for entry in journal[:self.feed_nr]: - user = entry.user - if user is None: - #fix deleted users - 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: - _url = url('changelog_home', - repo_name=entry.repository.repo_name, - qualified=True) - - feed.add_item(title=title, - pubdate=entry.action_date, - link=_url or url('', qualified=True), - author_email=user.email, - author_name=user.full_contact, - description=desc) - - response.content_type = feed.mime_type - return feed.writeString('utf-8') - @LoginRequired(api_access=True) def public_journal_atom(self): """ diff --git a/rhodecode/controllers/pullrequests.py b/rhodecode/controllers/pullrequests.py --- a/rhodecode/controllers/pullrequests.py +++ b/rhodecode/controllers/pullrequests.py @@ -62,9 +62,6 @@ log = logging.getLogger(__name__) class PullrequestsController(BaseRepoController): - @LoginRequired() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') def __before__(self): super(PullrequestsController, self).__before__() repo_model = RepoModel() @@ -144,156 +141,6 @@ class PullrequestsController(BaseRepoCon pull_request.reviewers] return (self.rhodecode_user.admin or owner or reviewer) - def show_all(self, repo_name): - c.pull_requests = PullRequestModel().get_all(repo_name) - c.repo_name = repo_name - p = safe_int(request.GET.get('page', 1), 1) - - c.pullrequests_pager = Page(c.pull_requests, page=p, items_per_page=10) - - c.pullrequest_data = render('/pullrequests/pullrequest_data.html') - - if request.environ.get('HTTP_X_PARTIAL_XHR'): - return c.pullrequest_data - - return render('/pullrequests/pullrequest_show_all.html') - - @NotAnonymous() - def index(self): - org_repo = c.rhodecode_db_repo - - if org_repo.scm_instance.alias != 'hg': - log.error('Review not available for GIT REPOS') - raise HTTPNotFound - - try: - org_repo.scm_instance.get_changeset() - except EmptyRepositoryError, e: - h.flash(h.literal(_('There are no changesets yet')), - category='warning') - redirect(url('summary_home', repo_name=org_repo.repo_name)) - - org_rev = request.GET.get('rev_end') - # rev_start is not directly useful - its parent could however be used - # as default for other and thus give a simple compare view - #other_rev = request.POST.get('rev_start') - - c.org_repos = [] - c.org_repos.append((org_repo.repo_name, org_repo.repo_name)) - c.default_org_repo = org_repo.repo_name - c.org_refs, c.default_org_ref = self._get_repo_refs(org_repo.scm_instance, org_rev) - - c.other_repos = [] - other_repos_info = {} - - def add_other_repo(repo, branch_rev=None): - if repo.repo_name in other_repos_info: # shouldn't happen - return - c.other_repos.append((repo.repo_name, repo.repo_name)) - other_refs, selected_other_ref = self._get_repo_refs(repo.scm_instance, branch_rev=branch_rev) - other_repos_info[repo.repo_name] = { - 'user': dict(user_id=repo.user.user_id, - username=repo.user.username, - firstname=repo.user.firstname, - lastname=repo.user.lastname, - gravatar_link=h.gravatar_url(repo.user.email, 14)), - 'description': repo.description.split('\n', 1)[0], - 'revs': h.select('other_ref', selected_other_ref, other_refs, class_='refs') - } - - # add org repo to other so we can open pull request against peer branches on itself - add_other_repo(org_repo, branch_rev=org_rev) - c.default_other_repo = org_repo.repo_name - - # gather forks and add to this list ... even though it is rare to - # request forks to pull from their parent - for fork in org_repo.forks: - add_other_repo(fork) - - # add parents of this fork also, but only if it's not empty - if org_repo.parent and org_repo.parent.scm_instance.revisions: - add_other_repo(org_repo.parent) - c.default_other_repo = org_repo.parent.repo_name - - c.default_other_repo_info = other_repos_info[c.default_other_repo] - c.other_repos_info = json.dumps(other_repos_info) - - return render('/pullrequests/pullrequest.html') - - @NotAnonymous() - def create(self, repo_name): - repo = RepoModel()._get_repo(repo_name) - try: - _form = PullRequestForm(repo.repo_id)().to_python(request.POST) - except formencode.Invalid, errors: - log.error(traceback.format_exc()) - if errors.error_dict.get('revisions'): - msg = 'Revisions: %s' % errors.error_dict['revisions'] - elif errors.error_dict.get('pullrequest_title'): - msg = _('Pull request requires a title with min. 3 chars') - else: - msg = _('Error creating pull request') - - h.flash(msg, 'error') - return redirect(url('pullrequest_home', repo_name=repo_name)) - - org_repo = _form['org_repo'] - org_ref = 'rev:merge:%s' % _form['merge_rev'] - other_repo = _form['other_repo'] - other_ref = 'rev:ancestor:%s' % _form['ancestor_rev'] - revisions = reversed(_form['revisions']) - reviewers = _form['review_members'] - - title = _form['pullrequest_title'] - description = _form['pullrequest_desc'] - - try: - pull_request = PullRequestModel().create( - self.rhodecode_user.user_id, org_repo, org_ref, other_repo, - other_ref, revisions, reviewers, title, description - ) - Session().commit() - h.flash(_('Successfully opened new pull request'), - category='success') - except Exception: - h.flash(_('Error occurred during sending pull request'), - category='error') - log.error(traceback.format_exc()) - return redirect(url('pullrequest_home', repo_name=repo_name)) - - return redirect(url('pullrequest_show', repo_name=other_repo, - pull_request_id=pull_request.pull_request_id)) - - @NotAnonymous() - @jsonify - def update(self, repo_name, pull_request_id): - pull_request = PullRequest.get_or_404(pull_request_id) - if pull_request.is_closed(): - raise HTTPForbidden() - #only owner or admin can update it - owner = pull_request.author.user_id == c.rhodecode_user.user_id - if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: - reviewers_ids = map(int, filter(lambda v: v not in [None, ''], - request.POST.get('reviewers_ids', '').split(','))) - - PullRequestModel().update_reviewers(pull_request_id, reviewers_ids) - Session().commit() - return True - raise HTTPForbidden() - - @NotAnonymous() - @jsonify - def delete(self, repo_name, pull_request_id): - pull_request = PullRequest.get_or_404(pull_request_id) - #only owner can delete it ! - if pull_request.author.user_id == c.rhodecode_user.user_id: - PullRequestModel().delete(pull_request) - Session().commit() - h.flash(_('Successfully deleted pull request'), - category='success') - return redirect(url('admin_settings_my_account', anchor='pullrequests')) - raise HTTPForbidden() - def _load_compare_data(self, pull_request, enable_comments=True): """ Load context data needed for generating compare diff @@ -361,6 +208,174 @@ class PullrequestsController(BaseRepoCon parsed_lines=[f]) c.changes[fid] = [f['operation'], f['filename'], diff] + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def show_all(self, repo_name): + c.pull_requests = PullRequestModel().get_all(repo_name) + c.repo_name = repo_name + p = safe_int(request.GET.get('page', 1), 1) + + c.pullrequests_pager = Page(c.pull_requests, page=p, items_per_page=10) + + c.pullrequest_data = render('/pullrequests/pullrequest_data.html') + + if request.environ.get('HTTP_X_PARTIAL_XHR'): + return c.pullrequest_data + + return render('/pullrequests/pullrequest_show_all.html') + + @LoginRequired() + @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def index(self): + org_repo = c.rhodecode_db_repo + + if org_repo.scm_instance.alias != 'hg': + log.error('Review not available for GIT REPOS') + raise HTTPNotFound + + try: + org_repo.scm_instance.get_changeset() + except EmptyRepositoryError, e: + h.flash(h.literal(_('There are no changesets yet')), + category='warning') + redirect(url('summary_home', repo_name=org_repo.repo_name)) + + org_rev = request.GET.get('rev_end') + # rev_start is not directly useful - its parent could however be used + # as default for other and thus give a simple compare view + #other_rev = request.POST.get('rev_start') + + c.org_repos = [] + c.org_repos.append((org_repo.repo_name, org_repo.repo_name)) + c.default_org_repo = org_repo.repo_name + c.org_refs, c.default_org_ref = self._get_repo_refs(org_repo.scm_instance, org_rev) + + c.other_repos = [] + other_repos_info = {} + + def add_other_repo(repo, branch_rev=None): + if repo.repo_name in other_repos_info: # shouldn't happen + return + c.other_repos.append((repo.repo_name, repo.repo_name)) + other_refs, selected_other_ref = self._get_repo_refs(repo.scm_instance, branch_rev=branch_rev) + other_repos_info[repo.repo_name] = { + 'user': dict(user_id=repo.user.user_id, + username=repo.user.username, + firstname=repo.user.firstname, + lastname=repo.user.lastname, + gravatar_link=h.gravatar_url(repo.user.email, 14)), + 'description': repo.description.split('\n', 1)[0], + 'revs': h.select('other_ref', selected_other_ref, other_refs, class_='refs') + } + + # add org repo to other so we can open pull request against peer branches on itself + add_other_repo(org_repo, branch_rev=org_rev) + c.default_other_repo = org_repo.repo_name + + # gather forks and add to this list ... even though it is rare to + # request forks to pull from their parent + for fork in org_repo.forks: + add_other_repo(fork) + + # add parents of this fork also, but only if it's not empty + if org_repo.parent and org_repo.parent.scm_instance.revisions: + add_other_repo(org_repo.parent) + c.default_other_repo = org_repo.parent.repo_name + + c.default_other_repo_info = other_repos_info[c.default_other_repo] + c.other_repos_info = json.dumps(other_repos_info) + + return render('/pullrequests/pullrequest.html') + + @LoginRequired() + @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def create(self, repo_name): + repo = RepoModel()._get_repo(repo_name) + try: + _form = PullRequestForm(repo.repo_id)().to_python(request.POST) + except formencode.Invalid, errors: + log.error(traceback.format_exc()) + if errors.error_dict.get('revisions'): + msg = 'Revisions: %s' % errors.error_dict['revisions'] + elif errors.error_dict.get('pullrequest_title'): + msg = _('Pull request requires a title with min. 3 chars') + else: + msg = _('Error creating pull request') + + h.flash(msg, 'error') + return redirect(url('pullrequest_home', repo_name=repo_name)) + + org_repo = _form['org_repo'] + org_ref = 'rev:merge:%s' % _form['merge_rev'] + other_repo = _form['other_repo'] + other_ref = 'rev:ancestor:%s' % _form['ancestor_rev'] + revisions = reversed(_form['revisions']) + reviewers = _form['review_members'] + + title = _form['pullrequest_title'] + description = _form['pullrequest_desc'] + + try: + pull_request = PullRequestModel().create( + self.rhodecode_user.user_id, org_repo, org_ref, other_repo, + other_ref, revisions, reviewers, title, description + ) + Session().commit() + h.flash(_('Successfully opened new pull request'), + category='success') + except Exception: + h.flash(_('Error occurred during sending pull request'), + category='error') + log.error(traceback.format_exc()) + return redirect(url('pullrequest_home', repo_name=repo_name)) + + return redirect(url('pullrequest_show', repo_name=other_repo, + pull_request_id=pull_request.pull_request_id)) + + @LoginRequired() + @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def update(self, repo_name, pull_request_id): + pull_request = PullRequest.get_or_404(pull_request_id) + if pull_request.is_closed(): + raise HTTPForbidden() + #only owner or admin can update it + owner = pull_request.author.user_id == c.rhodecode_user.user_id + if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: + reviewers_ids = map(int, filter(lambda v: v not in [None, ''], + request.POST.get('reviewers_ids', '').split(','))) + + PullRequestModel().update_reviewers(pull_request_id, reviewers_ids) + Session().commit() + return True + raise HTTPForbidden() + + @LoginRequired() + @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def delete(self, repo_name, pull_request_id): + pull_request = PullRequest.get_or_404(pull_request_id) + #only owner can delete it ! + if pull_request.author.user_id == c.rhodecode_user.user_id: + PullRequestModel().delete(pull_request) + Session().commit() + h.flash(_('Successfully deleted pull request'), + category='success') + return redirect(url('admin_settings_my_account', anchor='pullrequests')) + raise HTTPForbidden() + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def show(self, repo_name, pull_request_id): repo_model = RepoModel() c.users_array = repo_model.get_users_js() @@ -429,7 +444,10 @@ class PullrequestsController(BaseRepoCon c.ancestor = None # there is one - but right here we don't know which return render('/pullrequests/pullrequest_show.html') + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) @@ -504,7 +522,10 @@ class PullrequestsController(BaseRepoCon return data + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) diff --git a/rhodecode/controllers/search.py b/rhodecode/controllers/search.py --- a/rhodecode/controllers/search.py +++ b/rhodecode/controllers/search.py @@ -48,10 +48,10 @@ log = logging.getLogger(__name__) class SearchController(BaseRepoController): - @LoginRequired() def __before__(self): super(SearchController, self).__before__() + @LoginRequired() def index(self, repo_name=None): c.repo_name = repo_name c.formated_results = [] diff --git a/rhodecode/controllers/shortlog.py b/rhodecode/controllers/shortlog.py --- a/rhodecode/controllers/shortlog.py +++ b/rhodecode/controllers/shortlog.py @@ -42,9 +42,6 @@ log = logging.getLogger(__name__) class ShortlogController(BaseRepoController): - @LoginRequired() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') def __before__(self): super(ShortlogController, self).__before__() @@ -63,6 +60,9 @@ class ShortlogController(BaseRepoControl h.flash(str(e), category='warning') redirect(h.url('shortlog_home', repo_name=repo_name)) + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def index(self, repo_name, revision=None, f_path=None): p = safe_int(request.GET.get('page', 1), 1) size = safe_int(request.GET.get('size', 20), 20) diff --git a/rhodecode/controllers/summary.py b/rhodecode/controllers/summary.py --- a/rhodecode/controllers/summary.py +++ b/rhodecode/controllers/summary.py @@ -65,12 +65,75 @@ README_FILES = [''.join([x[0][0], x[1][0 class SummaryController(BaseRepoController): + def __before__(self): + super(SummaryController, self).__before__() + + def _get_download_links(self, repo): + + download_l = [] + + branches_group = ([], _("Branches")) + tags_group = ([], _("Tags")) + + for name, chs in c.rhodecode_repo.branches.items(): + #chs = chs.split(':')[-1] + branches_group[0].append((chs, name),) + download_l.append(branches_group) + + for name, chs in c.rhodecode_repo.tags.items(): + #chs = chs.split(':')[-1] + tags_group[0].append((chs, name),) + download_l.append(tags_group) + + return download_l + + + def __get_readme_data(self, db_repo): + repo_name = db_repo.repo_name + + @cache_region('long_term') + def _get_readme_from_cache(key): + readme_data = None + readme_file = None + log.debug('Looking for README file') + try: + # get's the landing revision! or tip if fails + cs = db_repo.get_landing_changeset() + if isinstance(cs, EmptyChangeset): + raise EmptyRepositoryError() + renderer = MarkupRenderer() + for f in README_FILES: + try: + readme = cs.get_node(f) + if not isinstance(readme, FileNode): + continue + readme_file = f + log.debug('Found README file `%s` rendering...' % + readme_file) + readme_data = renderer.render(readme.content, f) + break + except NodeDoesNotExistError: + continue + except ChangesetError: + log.error(traceback.format_exc()) + pass + except EmptyRepositoryError: + pass + except Exception: + log.error(traceback.format_exc()) + + return readme_data, readme_file + + key = repo_name + '_README' + inv = CacheInvalidation.invalidate(key) + if inv is not None: + region_invalidate(_get_readme_from_cache, None, key) + CacheInvalidation.set_valid(inv.cache_key) + return _get_readme_from_cache(key) + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def __before__(self): - super(SummaryController, self).__before__() - def index(self, repo_name): c.dbrepo = dbrepo = c.rhodecode_db_repo @@ -189,72 +252,13 @@ class SummaryController(BaseRepoControll self.__get_readme_data(c.rhodecode_db_repo) return render('summary/summary.html') + @LoginRequired() @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') @jsonify def repo_size(self, repo_name): if request.is_xhr: return c.rhodecode_db_repo._repo_size() else: raise HTTPBadRequest() - - def __get_readme_data(self, db_repo): - repo_name = db_repo.repo_name - - @cache_region('long_term') - def _get_readme_from_cache(key): - readme_data = None - readme_file = None - log.debug('Looking for README file') - try: - # get's the landing revision! or tip if fails - cs = db_repo.get_landing_changeset() - if isinstance(cs, EmptyChangeset): - raise EmptyRepositoryError() - renderer = MarkupRenderer() - for f in README_FILES: - try: - readme = cs.get_node(f) - if not isinstance(readme, FileNode): - continue - readme_file = f - log.debug('Found README file `%s` rendering...' % - readme_file) - readme_data = renderer.render(readme.content, f) - break - except NodeDoesNotExistError: - continue - except ChangesetError: - log.error(traceback.format_exc()) - pass - except EmptyRepositoryError: - pass - except Exception: - log.error(traceback.format_exc()) - - return readme_data, readme_file - - key = repo_name + '_README' - inv = CacheInvalidation.invalidate(key) - if inv is not None: - region_invalidate(_get_readme_from_cache, None, key) - CacheInvalidation.set_valid(inv.cache_key) - return _get_readme_from_cache(key) - - def _get_download_links(self, repo): - - download_l = [] - - branches_group = ([], _("Branches")) - tags_group = ([], _("Tags")) - - for name, chs in c.rhodecode_repo.branches.items(): - #chs = chs.split(':')[-1] - branches_group[0].append((chs, name),) - download_l.append(branches_group) - - for name, chs in c.rhodecode_repo.tags.items(): - #chs = chs.split(':')[-1] - tags_group[0].append((chs, name),) - download_l.append(tags_group) - - return download_l diff --git a/rhodecode/controllers/tags.py b/rhodecode/controllers/tags.py --- a/rhodecode/controllers/tags.py +++ b/rhodecode/controllers/tags.py @@ -35,12 +35,12 @@ log = logging.getLogger(__name__) class TagsController(BaseRepoController): + def __before__(self): + super(TagsController, self).__before__() + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def __before__(self): - super(TagsController, self).__before__() - def index(self): c.repo_tags = OrderedDict()