Emails
+-
+ % for elem in sorted(c.email_types.keys()):
+
- + ${elem} + | + plain rendered + + % endfor +
diff --git a/rhodecode/apps/debug_style/__init__.py b/rhodecode/apps/debug_style/__init__.py --- a/rhodecode/apps/debug_style/__init__.py +++ b/rhodecode/apps/debug_style/__init__.py @@ -43,6 +43,14 @@ def includeme(config): pattern=ADMIN_PREFIX + '/debug_style', debug_style=True) config.add_route( + name='debug_style_email', + pattern=ADMIN_PREFIX + '/debug_style/email/{email_id}', + debug_style=True) + config.add_route( + name='debug_style_email_plain_rendered', + pattern=ADMIN_PREFIX + '/debug_style/email-rendered/{email_id}', + debug_style=True) + config.add_route( name='debug_style_template', pattern=ADMIN_PREFIX + '/debug_style/t/{t_path}', debug_style=True) diff --git a/rhodecode/apps/debug_style/views.py b/rhodecode/apps/debug_style/views.py --- a/rhodecode/apps/debug_style/views.py +++ b/rhodecode/apps/debug_style/views.py @@ -20,10 +20,15 @@ import os import logging +import datetime from pyramid.view import view_config from pyramid.renderers import render_to_response from rhodecode.apps._base import BaseAppView +from rhodecode.lib.celerylib import run_task, tasks +from rhodecode.lib.utils2 import AttributeDict +from rhodecode.model.db import User +from rhodecode.model.notification import EmailNotificationModel log = logging.getLogger(__name__) @@ -46,6 +51,271 @@ class DebugStyleView(BaseAppView): request=self.request) @view_config( + route_name='debug_style_email', request_method='GET', + renderer=None) + @view_config( + route_name='debug_style_email_plain_rendered', request_method='GET', + renderer=None) + def render_email(self): + c = self.load_default_context() + email_id = self.request.matchdict['email_id'] + c.active = 'emails' + + pr = AttributeDict( + pull_request_id=123, + title='digital_ocean: fix redis, elastic search start on boot, ' + 'fix fd limits on supervisor, set postgres 11 version', + description=''' +Check if we should use full-topic or mini-topic. + +- full topic produces some problems with merge states etc +- server-mini-topic needs probably tweeks. + ''', + repo_name='foobar', + source_ref_parts=AttributeDict(type='branch', name='fix-ticket-2000'), + target_ref_parts=AttributeDict(type='branch', name='master'), + ) + target_repo = AttributeDict(repo_name='repo_group/target_repo') + source_repo = AttributeDict(repo_name='repo_group/source_repo') + user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user + + email_kwargs = { + 'test': {}, + 'message': { + 'body': 'message body !' + }, + 'email_test': { + 'user': user, + 'date': datetime.datetime.now(), + 'rhodecode_version': c.rhodecode_version + }, + 'password_reset': { + 'password_reset_url': 'http://example.com/reset-rhodecode-password/token', + + 'user': user, + 'date': datetime.datetime.now(), + 'email': 'test@rhodecode.com', + 'first_admin_email': User.get_first_super_admin().email + }, + 'password_reset_confirmation': { + 'new_password': 'new-password-example', + 'user': user, + 'date': datetime.datetime.now(), + 'email': 'test@rhodecode.com', + 'first_admin_email': User.get_first_super_admin().email + }, + 'registration': { + 'user': user, + 'date': datetime.datetime.now(), + }, + + 'pull_request_comment': { + 'user': user, + + 'status_change': None, + 'status_change_type': None, + + 'pull_request': pr, + 'pull_request_commits': [], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://localhost/pr1', + 'pr_comment_url': 'http://comment-url', + + 'comment_file': None, + 'comment_line': None, + 'comment_type': 'note', + 'comment_body': 'This is my comment body. *I like !*', + + 'renderer_type': 'markdown', + 'mention': True, + + }, + 'pull_request_comment+status': { + 'user': user, + + 'status_change': 'approved', + 'status_change_type': 'approved', + + 'pull_request': pr, + 'pull_request_commits': [], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://localhost/pr1', + 'pr_comment_url': 'http://comment-url', + + 'comment_type': 'todo', + 'comment_file': None, + 'comment_line': None, + 'comment_body': ''' +I think something like this would be better + +```py + +def db(): + global connection + return connection + +``` + + ''', + + 'renderer_type': 'markdown', + 'mention': True, + + }, + 'pull_request_comment+file': { + 'user': user, + + 'status_change': None, + 'status_change_type': None, + + 'pull_request': pr, + 'pull_request_commits': [], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://localhost/pr1', + + 'pr_comment_url': 'http://comment-url', + + 'comment_file': 'rhodecode/model/db.py', + 'comment_line': 'o1210', + 'comment_type': 'todo', + 'comment_body': ''' +I like this ! + +But please check this code:: + + def main(): + print 'ok' + +This should work better ! + ''', + + 'renderer_type': 'rst', + 'mention': True, + + }, + + 'cs_comment': { + 'user': user, + 'commit': AttributeDict(idx=123, raw_id='a'*40, message='Commit message'), + 'status_change': None, + 'status_change_type': None, + + 'commit_target_repo_url': 'http://foo.example.com/#comment1', + 'repo_name': 'test-repo', + 'comment_type': 'note', + 'comment_file': None, + 'comment_line': None, + 'commit_comment_url': 'http://comment-url', + 'comment_body': 'This is my comment body. *I like !*', + 'renderer_type': 'markdown', + 'mention': True, + }, + 'cs_comment+status': { + 'user': user, + 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'), + 'status_change': 'approved', + 'status_change_type': 'approved', + + 'commit_target_repo_url': 'http://foo.example.com/#comment1', + 'repo_name': 'test-repo', + 'comment_type': 'note', + 'comment_file': None, + 'comment_line': None, + 'commit_comment_url': 'http://comment-url', + 'comment_body': ''' +Hello **world** + +This is a multiline comment :) + +- list +- list2 + ''', + 'renderer_type': 'markdown', + 'mention': True, + }, + 'cs_comment+file': { + 'user': user, + 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'), + 'status_change': None, + 'status_change_type': None, + + 'commit_target_repo_url': 'http://foo.example.com/#comment1', + 'repo_name': 'test-repo', + + 'comment_type': 'note', + 'comment_file': 'test-file.py', + 'comment_line': 'n100', + + 'commit_comment_url': 'http://comment-url', + 'comment_body': 'This is my comment body. *I like !*', + 'renderer_type': 'markdown', + 'mention': True, + }, + + 'pull_request': { + 'user': user, + 'pull_request': pr, + 'pull_request_commits': [ + ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\ +my-account: moved email closer to profile as it's similar data just moved outside. + '''), + ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\ +users: description edit fixes + +- tests +- added metatags info + '''), + ], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123', + } + + } + + template_type = email_id.split('+')[0] + (c.subject, c.headers, c.email_body, + c.email_body_plaintext) = EmailNotificationModel().render_email( + template_type, **email_kwargs.get(email_id, {})) + + test_email = self.request.GET.get('email') + if test_email: + recipients = [test_email] + run_task(tasks.send_email, recipients, c.subject, + c.email_body_plaintext, c.email_body) + + if self.request.matched_route.name == 'debug_style_email_plain_rendered': + template = 'debug_style/email_plain_rendered.mako' + else: + template = 'debug_style/email.mako' + return render_to_response( + template, self._get_template_context(c), + request=self.request) + + @view_config( route_name='debug_style_template', request_method='GET', renderer=None) def template(self): @@ -53,7 +323,16 @@ class DebugStyleView(BaseAppView): c = self.load_default_context() c.active = os.path.splitext(t_path)[0] c.came_from = '' + c.email_types = { + 'cs_comment+file': {}, + 'cs_comment+status': {}, + + 'pull_request_comment+file': {}, + 'pull_request_comment+status': {}, + } + c.email_types.update(EmailNotificationModel.email_types) return render_to_response( 'debug_style/' + t_path, self._get_template_context(c), - request=self.request) \ No newline at end of file + request=self.request) + diff --git a/rhodecode/apps/repository/tests/test_repo_commit_comments.py b/rhodecode/apps/repository/tests/test_repo_commit_comments.py --- a/rhodecode/apps/repository/tests/test_repo_commit_comments.py +++ b/rhodecode/apps/repository/tests/test_repo_commit_comments.py @@ -98,7 +98,7 @@ class TestRepoCommitCommentsView(TestCon assert notification.type_ == Notification.TYPE_CHANGESET_COMMENT author = notification.created_by_user.username_and_name - sbj = '{0} left a {1} on commit `{2}` in the {3} repository'.format( + sbj = '@{0} left a {1} on commit `{2}` in the `{3}` repository'.format( author, comment_type, h.show_id(commit), backend.repo_name) assert sbj == notification.subject @@ -159,7 +159,7 @@ class TestRepoCommitCommentsView(TestCon assert comment.revision == commit_id author = notification.created_by_user.username_and_name - sbj = '{0} left a {1} on file `{2}` in commit `{3}` in the {4} repository'.format( + sbj = '@{0} left a {1} on file `{2}` in commit `{3}` in the `{4}` repository'.format( author, comment_type, f_path, h.show_id(commit), backend.repo_name) assert sbj == notification.subject @@ -230,7 +230,7 @@ class TestRepoCommitCommentsView(TestCon assert notification.type_ == Notification.TYPE_CHANGESET_COMMENT author = notification.created_by_user.username_and_name - sbj = '[status: Approved] {0} left a note on commit `{1}` in the {2} repository'.format( + sbj = '[status: Approved] @{0} left a note on commit `{1}` in the `{2}` repository'.format( author, h.show_id(commit), backend.repo_name) assert sbj == notification.subject diff --git a/rhodecode/apps/repository/tests/test_repo_pullrequests.py b/rhodecode/apps/repository/tests/test_repo_pullrequests.py --- a/rhodecode/apps/repository/tests/test_repo_pullrequests.py +++ b/rhodecode/apps/repository/tests/test_repo_pullrequests.py @@ -467,7 +467,7 @@ class TestPullrequestsView(object): .filter(Notification.created_by == pull_request.author.user_id, Notification.type_ == Notification.TYPE_PULL_REQUEST, Notification.subject.contains( - "wants you to review pull request #%s" % pull_request_id)) + "requested a pull request review. !%s" % pull_request_id)) assert len(notifications.all()) == 1 # Change reviewers and check that a notification was made @@ -549,11 +549,10 @@ class TestPullrequestsView(object): pull_request_id = pull_request.pull_request_id repo_name = pull_request.target_repo.scm_instance().name, - response = self.app.post( - route_path('pullrequest_merge', - repo_name=str(repo_name[0]), - pull_request_id=pull_request_id), - params={'csrf_token': csrf_token}).follow() + url = route_path('pullrequest_merge', + repo_name=str(repo_name[0]), + pull_request_id=pull_request_id) + response = self.app.post(url, params={'csrf_token': csrf_token}).follow() pull_request = PullRequest.get(pull_request_id) @@ -735,12 +734,12 @@ class TestPullrequestsView(object): backend.pull_heads(source, heads=['change-rebased']) # update PR - self.app.post( - route_path('pullrequest_update', - repo_name=target.repo_name, - pull_request_id=pull_request_id), - params={'update_commits': 'true', 'csrf_token': csrf_token}, - status=200) + url = route_path('pullrequest_update', + repo_name=target.repo_name, + pull_request_id=pull_request_id) + self.app.post(url, + params={'update_commits': 'true', 'csrf_token': csrf_token}, + status=200) # check that we have now both revisions pull_request = PullRequest.get(pull_request_id) @@ -801,12 +800,12 @@ class TestPullrequestsView(object): vcsrepo.run_git_command(['reset', '--soft', 'HEAD~2']) # update PR - self.app.post( - route_path('pullrequest_update', - repo_name=target.repo_name, - pull_request_id=pull_request_id), - params={'update_commits': 'true', 'csrf_token': csrf_token}, - status=200) + url = route_path('pullrequest_update', + repo_name=target.repo_name, + pull_request_id=pull_request_id) + self.app.post(url, + params={'update_commits': 'true', 'csrf_token': csrf_token}, + status=200) response = self.app.get(route_path('pullrequest_new', repo_name=target.repo_name)) assert response.status_int == 200 @@ -961,12 +960,12 @@ class TestPullrequestsView(object): else: vcs.strip(pr_util.commit_ids['new-feature']) - response = self.app.post( - route_path('pullrequest_update', - repo_name=pull_request.target_repo.repo_name, - pull_request_id=pull_request.pull_request_id), - params={'update_commits': 'true', - 'csrf_token': csrf_token}) + url = route_path('pullrequest_update', + repo_name=pull_request.target_repo.repo_name, + pull_request_id=pull_request.pull_request_id) + response = self.app.post(url, + params={'update_commits': 'true', + 'csrf_token': csrf_token}) assert response.status_int == 200 assert response.body == 'true' @@ -1208,14 +1207,11 @@ class TestPullrequestsControllerDelete(o def assert_pull_request_status(pull_request, expected_status): - status = ChangesetStatusModel().calculated_review_status( - pull_request=pull_request) + status = ChangesetStatusModel().calculated_review_status(pull_request=pull_request) assert status == expected_status @pytest.mark.parametrize('route', ['pullrequest_new', 'pullrequest_create']) @pytest.mark.usefixtures("autologin_user") def test_forbidde_to_repo_summary_for_svn_repositories(backend_svn, app, route): - response = app.get( - route_path(route, repo_name=backend_svn.repo_name), status=404) - + app.get(route_path(route, repo_name=backend_svn.repo_name), status=404) diff --git a/rhodecode/model/comment.py b/rhodecode/model/comment.py --- a/rhodecode/model/comment.py +++ b/rhodecode/model/comment.py @@ -359,7 +359,7 @@ class CommentsModel(BaseModel): kwargs.update({ 'commit': commit_obj, 'commit_message': commit_obj.message, - 'commit_target_repo': target_repo_url, + 'commit_target_repo_url': target_repo_url, 'commit_comment_url': commit_comment_url, }) @@ -382,6 +382,11 @@ class CommentsModel(BaseModel): pull_request_id=pull_request_obj.pull_request_id, _anchor='comment-%s' % comment.comment_id) + pr_url = h.route_url( + 'pullrequest_show', + repo_name=pr_target_repo.repo_name, + pull_request_id=pull_request_obj.pull_request_id, ) + # set some variables for email notification pr_target_repo_url = h.route_url( 'repo_summary', repo_name=pr_target_repo.repo_name) @@ -393,10 +398,11 @@ class CommentsModel(BaseModel): kwargs.update({ 'pull_request': pull_request_obj, 'pr_id': pull_request_obj.pull_request_id, - 'pr_target_repo': pr_target_repo, - 'pr_target_repo_url': pr_target_repo_url, - 'pr_source_repo': pr_source_repo, - 'pr_source_repo_url': pr_source_repo_url, + 'pull_request_url': pr_url, + 'pull_request_target_repo': pr_target_repo, + 'pull_request_target_repo_url': pr_target_repo_url, + 'pull_request_source_repo': pr_source_repo, + 'pull_request_source_repo_url': pr_source_repo_url, 'pr_comment_url': pr_comment_url, 'pr_closing': closing_pr, }) diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -1110,8 +1110,8 @@ class PullRequestModel(BaseModel): pr_target_repo = pull_request_obj.target_repo pr_url = h.route_url('pullrequest_show', - repo_name=pr_target_repo.repo_name, - pull_request_id=pull_request_obj.pull_request_id,) + repo_name=pr_target_repo.repo_name, + pull_request_id=pull_request_obj.pull_request_id,) # set some variables for email notification pr_target_repo_url = h.route_url( diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -612,7 +612,8 @@ class UserModel(BaseModel): 'password_reset_url': pwd_reset_url, 'user': user, 'email': user_email, - 'date': datetime.datetime.now() + 'date': datetime.datetime.now(), + 'first_admin_email': User.get_first_super_admin().email } (subject, headers, email_body, @@ -670,7 +671,8 @@ class UserModel(BaseModel): 'new_password': new_passwd, 'user': user, 'email': user_email, - 'date': datetime.datetime.now() + 'date': datetime.datetime.now(), + 'first_admin_email': User.get_first_super_admin().email } (subject, headers, email_body, diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -342,6 +342,8 @@ function registerRCRoutes() { pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']); pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']); pyroutes.register('debug_style_home', '/_admin/debug_style', []); + pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']); + pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']); pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']); pyroutes.register('apiv2', '/_admin/api', []); pyroutes.register('admin_settings_license', '/_admin/settings/license', []); diff --git a/rhodecode/templates/debug_style/email.mako b/rhodecode/templates/debug_style/email.mako new file mode 100644 --- /dev/null +++ b/rhodecode/templates/debug_style/email.mako @@ -0,0 +1,29 @@ + + + +
+ + + +SUBJECT: +${c.subject}+ +HEADERS: +
+${c.headers} ++ +PLAINTEXT: +
+${c.email_body_plaintext|n} ++ + + +