def post(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) if pull_request.is_closed(): raise HTTPForbidden() assert pull_request.other_repo.repo_name == repo_name #only owner or admin can update it owner = pull_request.author.user_id == c.authuser.user_id repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name) if not (h.HasPermissionAny('hg.admin') or repo_admin or owner): raise HTTPForbidden() _form = PullRequestPostForm()().to_python(request.POST) reviewers_ids = [int(s) for s in _form['review_members']] if _form['updaterev']: return self.create_update(pull_request, _form['updaterev'], _form['pullrequest_title'], _form['pullrequest_desc'], reviewers_ids) old_description = pull_request.description pull_request.title = _form['pullrequest_title'] pull_request.description = _form['pullrequest_desc'].strip() or _( 'No description') PullRequestModel().mention_from_description(pull_request, old_description) PullRequestModel().update_reviewers(pull_request_id, reviewers_ids) Session().commit() h.flash(_('Pull request updated'), category='success') return redirect(pull_request.url())
def post(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) if pull_request.is_closed(): raise HTTPForbidden() assert pull_request.other_repo.repo_name == repo_name # only owner or admin can update it owner = pull_request.owner_id == request.authuser.user_id repo_admin = h.HasRepoPermissionLevel('admin')(c.repo_name) if not (h.HasPermissionAny('hg.admin')() or repo_admin or owner): raise HTTPForbidden() _form = PullRequestPostForm()().to_python(request.POST) cur_reviewers = set(pull_request.get_reviewer_users()) new_reviewers = set(_get_reviewer(s) for s in _form['review_members']) old_reviewers = set( _get_reviewer(s) for s in _form['org_review_members']) other_added = cur_reviewers - old_reviewers other_removed = old_reviewers - cur_reviewers if other_added: h.flash( _('Meanwhile, the following reviewers have been added: %s') % (', '.join(u.username for u in other_added)), category='warning') if other_removed: h.flash( _('Meanwhile, the following reviewers have been removed: %s') % (', '.join(u.username for u in other_removed)), category='warning') if _form['updaterev']: return self.create_new_iteration(pull_request, _form['updaterev'], _form['pullrequest_title'], _form['pullrequest_desc'], new_reviewers) added_reviewers = new_reviewers - old_reviewers - cur_reviewers removed_reviewers = (old_reviewers - new_reviewers) & cur_reviewers old_description = pull_request.description pull_request.title = _form['pullrequest_title'] pull_request.description = _form['pullrequest_desc'].strip() or _( 'No description') pull_request.owner = User.get_by_username(_form['owner']) user = User.get(request.authuser.user_id) PullRequestModel().mention_from_description(user, pull_request, old_description) PullRequestModel().add_reviewers(user, pull_request, added_reviewers) PullRequestModel().remove_reviewers(user, pull_request, removed_reviewers) Session().commit() h.flash(_('Pull request updated'), category='success') raise HTTPFound(location=pull_request.url())
def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) if not co: raise HTTPBadRequest() owner = co.author.user_id == c.authuser.user_id repo_admin = h.HasRepoPermissionAny('repository.admin') if h.HasPermissionAny('hg.admin')() or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True else: raise HTTPForbidden()
def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get_or_404(comment_id) if co.repo.repo_name != repo_name: raise HTTPNotFound() owner = co.author_id == request.authuser.user_id repo_admin = h.HasRepoPermissionLevel('admin')(repo_name) if h.HasPermissionAny('hg.admin')() or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True else: raise HTTPForbidden()
def delete(self, gist_id): gist = GistModel().get_gist(gist_id) owner = gist.owner_id == request.authuser.user_id if h.HasPermissionAny('hg.admin')() or owner: GistModel().delete(gist) Session().commit() h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success') else: raise HTTPForbidden() raise HTTPFound(location=url('gists'))
def update(self, notification_id): try: no = Notification.get(notification_id) owner = all(un.user_id == request.authuser.user_id for un in no.notifications_to_users) if h.HasPermissionAny('hg.admin')() or owner: # deletes only notification2user NotificationModel().mark_read(request.authuser.user_id, no) Session().commit() return 'ok' except Exception: Session().rollback() log.error(traceback.format_exc()) raise HTTPBadRequest()
def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) if co.pull_request.is_closed(): #don't allow deleting comments on closed pull request raise HTTPForbidden() owner = co.author_id == request.authuser.user_id repo_admin = h.HasRepoPermissionLevel('admin')(c.repo_name) if h.HasPermissionAny('hg.admin')() or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True else: raise HTTPForbidden()
def is_user_authorized(old_pull_request): """Performs authorization check with only the minimum amount of information needed for such a check, rather than a full command object. """ if h.HasPermissionAny('hg.admin')(): return True # Authorized to edit the old PR? if request.authuser.user_id != old_pull_request.owner_id: return False # Authorized to create a new PR? if not CreatePullRequestAction.is_user_authorized(old_pull_request.org_repo, old_pull_request.other_repo): return False return True
def delete_cs_pr_comment(repo_name, comment_id): """Delete a comment from a changeset or pull request""" co = ChangesetComment.get_or_404(comment_id) if co.repo.repo_name != repo_name: raise HTTPNotFound() if co.pull_request and co.pull_request.is_closed(): # don't allow deleting comments on closed pull request raise HTTPForbidden() owner = co.author_id == request.authuser.user_id repo_admin = h.HasRepoPermissionLevel('admin')(repo_name) if h.HasPermissionAny('hg.admin')() or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True else: raise HTTPForbidden()
def delete(self, gist_id): """DELETE /admin/gists/gist_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('gist', gist_id=ID), # method='delete') # url('gist', gist_id=ID) gist = GistModel().get_gist(gist_id) owner = gist.gist_owner == c.authuser.user_id if h.HasPermissionAny('hg.admin')() or owner: GistModel().delete(gist) Session().commit() h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success') else: raise HTTPForbidden() return redirect(url('gists'))
def delete(self, notification_id): """DELETE /_admin/notifications/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('notification', notification_id=ID), # method='delete') # url('notification', notification_id=ID) try: no = Notification.get(notification_id) owner = any(un.user.user_id == c.authuser.user_id for un in no.notifications_to_users) if h.HasPermissionAny('hg.admin')() or owner: # deletes only notification2user NotificationModel().delete(c.authuser.user_id, no) Session().commit() return 'ok' except Exception: Session().rollback() log.error(traceback.format_exc()) raise HTTPBadRequest()
def show(self, notification_id, format='html'): """GET /_admin/notifications/id: Show a specific item""" # url('notification', notification_id=ID) c.user = self.authuser no = Notification.get(notification_id) owner = any(un.user.user_id == c.authuser.user_id for un in no.notifications_to_users) repo_admin = h.HasRepoPermissionAny('repository.admin') if no and (h.HasPermissionAny('hg.admin')() or repo_admin or owner): unotification = NotificationModel()\ .get_user_notification(c.user.user_id, no) # if this association to user is not valid, we don't want to show # this message if unotification: if not unotification.read: unotification.mark_as_read() Session().commit() c.notification = no return render('admin/notifications/show_notification.html') return abort(403)
def create_cs_pr_comment(repo_name, revision=None, pull_request=None, allowed_to_change_status=True): """ Add a comment to the specified changeset or pull request, using POST values from the request. Comments can be inline (when a file path and line number is specified in POST) or general comments. A comment can be accompanied by a review status change (accepted, rejected, etc.). Pull requests can be closed or deleted. Parameter 'allowed_to_change_status' is used for both status changes and closing of pull requests. For deleting of pull requests, more specific checks are done. """ assert request.environ.get('HTTP_X_PARTIAL_XHR') if pull_request: pull_request_id = pull_request.pull_request_id else: pull_request_id = None status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') delete = request.POST.get('save_delete') f_path = request.POST.get('f_path') line_no = request.POST.get('line') if (status or close_pr or delete) and (f_path or line_no): # status votes and closing is only possible in general comments raise HTTPBadRequest() if not allowed_to_change_status: if status or close_pr: h.flash(_('No permission to change status'), 'error') raise HTTPForbidden() if pull_request and delete == "delete": if (pull_request.owner_id == request.authuser.user_id or h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionLevel('admin')( pull_request.org_repo.repo_name) or h.HasRepoPermissionLevel('admin')( pull_request.other_repo.repo_name) ) and not pull_request.is_closed(): PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request %s') % pull_request_id, category='success') return { 'location': h.url('my_pullrequests'), # or repo pr list? } raise HTTPForbidden() text = request.POST.get('text', '').strip() comment = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, author=request.authuser.user_id, revision=revision, pull_request=pull_request_id, f_path=f_path or None, line_no=line_no or None, status_change=ChangesetStatus.get_status_lbl(status) if status else None, closing_pr=close_pr, ) if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, request.authuser.user_id, comment, revision=revision, pull_request=pull_request_id, ) if pull_request: action = 'user_commented_pull_request:%s' % pull_request_id else: action = 'user_commented_revision:%s' % revision action_logger(request.authuser, action, c.db_repo, request.ip_addr) if pull_request and close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(request.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) Session().commit() data = { 'target_id': h.safeid(request.POST.get('f_path')), } if comment is not None: c.comment = comment data.update(comment.get_dict()) data.update({ 'rendered_text': render('changeset/changeset_comment_block.html') }) return data
def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') delete = request.POST.get('save_delete') f_path = request.POST.get('f_path') line_no = request.POST.get('line') if (status or close_pr or delete) and (f_path or line_no): # status votes and closing is only possible in general comments raise HTTPBadRequest() allowed_to_change_status = self._get_is_allowed_change_status(pull_request) if not allowed_to_change_status: if status or close_pr: h.flash(_('No permission to change pull request status'), 'error') raise HTTPForbidden() if delete == "delete": if (pull_request.owner_id == request.authuser.user_id or h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionLevel('admin')(pull_request.org_repo.repo_name) or h.HasRepoPermissionLevel('admin')(pull_request.other_repo.repo_name) ) and not pull_request.is_closed(): PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request %s') % pull_request_id, category='success') return { 'location': url('my_pullrequests'), # or repo pr list? } raise HTTPFound(location=url('my_pullrequests')) # or repo pr list? raise HTTPForbidden() text = request.POST.get('text', '').strip() comment = create_comment( text, status, pull_request_id=pull_request_id, f_path=f_path, line_no=line_no, closing_pr=close_pr, ) action_logger(request.authuser, 'user_commented_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, request.authuser.user_id, comment, pull_request=pull_request_id ) if close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(request.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): raise HTTPFound(location=pull_request.url()) data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comment is not None: c.comment = comment data.update(comment.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data