Browse Source

Store the user who closed a ticket in the database.

Fixes 3932

Signed-off-by: Clement Verna <cverna@tutanota.com>
Clement Verna 5 years ago
parent
commit
81c13058fc

+ 31 - 0
alembic/versions/1f24c9c8efa5_store_the_user_who_closed_an_issue_in_.py

@@ -0,0 +1,31 @@
+"""Store the user who closed an issue in the db
+
+Revision ID: 1f24c9c8efa5
+Revises: 6a3ed02ee160
+Create Date: 2018-12-04 13:02:57.101095
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "1f24c9c8efa5"
+down_revision = "6a3ed02ee160"
+
+
+def upgrade():
+
+    op.add_column(
+        "issues",
+        sa.Column(
+            "closed_by_id",
+            sa.Integer,
+            sa.ForeignKey("users.id", onupdate="CASCADE"),
+        ),
+    )
+
+
+def downgrade():
+    op.drop_column("issues", "closed_by_id")

+ 2 - 0
pagure/api/issue.py

@@ -249,6 +249,7 @@ def api_new_issue(repo, username=None, namespace=None):
             "blocks": [],
             "close_status": null,
             "closed_at": null,
+            "closed_by": null,
             "comments": [],
             "content": "This issue needs attention",
             "custom_fields": [],
@@ -465,6 +466,7 @@ def api_view_issues(repo, username=None, namespace=None):
               "blocks": ["1"],
               "close_status": null,
               "closed_at": null,
+              "closed_by": null,
               "comments": [],
               "content": "asd",
               "custom_fields": [],

+ 2 - 0
pagure/api/user.py

@@ -286,6 +286,7 @@ def api_view_user_issues(username):
               "blocks": [],
               "close_status": null,
               "closed_at": null,
+              "closed_by": null,
               "comments": [],
               "content": "Test Issue",
               "custom_fields": [],
@@ -314,6 +315,7 @@ def api_view_user_issues(username):
               "blocks": [],
               "close_status": null,
               "closed_at": null,
+              "closed_by": null,
               "comments": [],
               "content": "Test Issue",
               "custom_fields": [],

+ 15 - 0
pagure/lib/model.py

@@ -1244,6 +1244,11 @@ class Issue(BASE):
         sa.DateTime, nullable=False, default=datetime.datetime.utcnow
     )
     closed_at = sa.Column(sa.DateTime, nullable=True)
+    closed_by_id = sa.Column(
+        sa.Integer,
+        sa.ForeignKey("users.id", onupdate="CASCADE"),
+        nullable=True,
+    )
 
     project = relation(
         "Project",
@@ -1279,6 +1284,13 @@ class Issue(BASE):
         viewonly=True,
     )
 
+    closed_by = relation(
+        "User",
+        foreign_keys=[closed_by_id],
+        remote_side=[User.id],
+        backref="closed_issues",
+    )
+
     def __repr__(self):
         return "Issue(%s, project:%s, user:%s, title:%s)" % (
             self.id,
@@ -1436,6 +1448,9 @@ class Issue(BASE):
             "priority": self.priority,
             "milestone": self.milestone,
             "custom_fields": custom_fields,
+            "closed_by": self.closed_by.to_json(public=public)
+            if self.closed_by
+            else None,
         }
 
         comments = []

+ 1 - 0
pagure/lib/query.py

@@ -2026,6 +2026,7 @@ def edit_issue(
         issue.status = status
         if status.lower() != "open":
             issue.closed_at = datetime.datetime.utcnow()
+            issue.closed_by_id = user_obj.id
         elif issue.close_status:
             issue.close_status = None
             close_status = Unspecified

+ 3 - 1
pagure/templates/issue.html

@@ -90,8 +90,10 @@
                 {% endif %}
               </span> {{ issue.closed_at |humanize }}
             </span>
+            {% if issue.closed_by %}
             by
-            <span title="{{ issue.user.html_title }}">{{ issue.user.user }}.</span>
+            <span title="{{ issue.closed_by.html_title }}">{{ issue.closed_by.user }}.</span>
+            {% endif %}
             <span class="text-muted" data-toggle="tooltip" title="{{issue.date_created | format_datetime}}">
                 <span class="font-weight-bold">Opened</span> {{ issue.date_created |humanize }}
             </span>

+ 15 - 0
tests/test_pagure_flask_api_issue.py

@@ -40,6 +40,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "We should work on this",
     "custom_fields": [],
@@ -63,6 +64,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -86,6 +88,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -109,6 +112,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -132,6 +136,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -155,6 +160,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -178,6 +184,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -201,6 +208,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -224,6 +232,7 @@ FULL_ISSUE_LIST = [
     "blocks": [],
     "close_status": None,
     "closed_at": None,
+    "closed_by": None,
     "comments": [],
     "content": "This issue needs attention",
     "custom_fields": [],
@@ -251,6 +260,7 @@ LCL_ISSUES = [
     'blocks': [],
     'close_status': None,
     'closed_at': None,
+    "closed_by": None,
     'comments': [],
     'content': 'Description',
     'custom_fields': [],
@@ -271,6 +281,7 @@ LCL_ISSUES = [
     'blocks': [],
     'close_status': None,
     'closed_at': None,
+    "closed_by": None,
     'comments': [],
     'content': 'Description',
     'custom_fields': [],
@@ -2337,6 +2348,7 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
                 'blocks': [],
                 'close_status': None,
                 'closed_at': None,
+                'closed_by': None,
                 'comments': [],
                 'content': 'Description',
                 'custom_fields': [],
@@ -2410,6 +2422,7 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
               "date_created": "1431414800",
               "close_status": None,
               "closed_at": None,
+              "closed_by": None,
               "depends": [],
               "id": 1,
               "last_updated": "1431414800",
@@ -2508,6 +2521,7 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
               "date_created": "1431414800",
               "close_status": None,
               "closed_at": None,
+              "closed_by": None,
               "depends": [],
               "id": 2,
               "last_updated": "1431414800",
@@ -2541,6 +2555,7 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
               "date_created": "1431414800",
               "close_status": None,
               "closed_at": None,
+              "closed_by": None,
               "depends": [],
               "id": 2,
               "last_updated": "1431414800",

+ 3 - 0
tests/test_pagure_flask_api_issue_create.py

@@ -152,6 +152,7 @@ class PagureFlaskApiIssueCreatetests(tests.Modeltests):
                 "blocks": [],
                 "close_status": None,
                 "closed_at": None,
+                "closed_by": None,
                 "comments": [],
                 "content": "This issue needs attention",
                 "custom_fields": [],
@@ -206,6 +207,7 @@ class PagureFlaskApiIssueCreatetests(tests.Modeltests):
                 "blocks": [],
                 "close_status": None,
                 "closed_at": None,
+                "closed_by": None,
                 "comments": [],
                 "content": "This issue needs attention",
                 "custom_fields": [],
@@ -260,6 +262,7 @@ class PagureFlaskApiIssueCreatetests(tests.Modeltests):
                 "blocks": [],
                 "close_status": None,
                 "closed_at": None,
+                "closed_by": None,
                 "comments": [],
                 "content": "This issue needs attention",
                 "custom_fields": [],

+ 17 - 0
tests/test_pagure_flask_api_ui_private_repo.py

@@ -29,6 +29,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "We should work on this",
         "custom_fields": [],
@@ -52,6 +53,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -75,6 +77,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -98,6 +101,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -121,6 +125,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -144,6 +149,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -167,6 +173,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -190,6 +197,7 @@ FULL_ISSUE_LIST = [
         "blocks": [],
         "close_status": None,
         "closed_at": None,
+        "closed_by": None,
         "comments": [],
         "content": "This issue needs attention",
         "custom_fields": [],
@@ -2498,6 +2506,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                             "blocks": [],
                             "close_status": None,
                             "closed_at": None,
+                            "closed_by": None,
                             "comments": [],
                             "content": "This issue needs attention",
                             "custom_fields": [],
@@ -2577,6 +2586,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                             "blocks": [],
                             "close_status": None,
                             "closed_at": None,
+                            "closed_by": None,
                             "comments": [],
                             "content": "We should work on this",
                             "custom_fields": [],
@@ -2600,6 +2610,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                             "blocks": [],
                             "close_status": None,
                             "closed_at": None,
+                            "closed_by": None,
                             "comments": [],
                             "content": "This issue needs attention",
                             "custom_fields": [],
@@ -2672,6 +2683,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                         "blocks": [],
                         "close_status": None,
                         "closed_at": None,
+                        "closed_by": None,
                         "comments": [],
                         "content": "We should work on this",
                         "custom_fields": [],
@@ -2695,6 +2707,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                         "blocks": [],
                         "close_status": None,
                         "closed_at": None,
+                        "closed_by": None,
                         "comments": [],
                         "content": "This issue needs attention",
                         "custom_fields": [],
@@ -2835,6 +2848,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                         "blocks": [],
                         "close_status": None,
                         "closed_at": None,
+                        "closed_by": None,
                         "comments": [],
                         "content": "We should work on this",
                         "custom_fields": [],
@@ -2858,6 +2872,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                         "blocks": [],
                         "close_status": None,
                         "closed_at": None,
+                        "closed_by": None,
                         "comments": [],
                         "content": "This issue needs attention",
                         "custom_fields": [],
@@ -2948,6 +2963,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                     "blocks": [],
                     "close_status": None,
                     "closed_at": None,
+                    "closed_by": None,
                     "comments": [],
                     "content": "This issue needs attention",
                     "custom_fields": [],
@@ -2996,6 +3012,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                 "blocks": [],
                 "close_status": None,
                 "closed_at": None,
+                "closed_by": None,
                 "comments": [],
                 "content": "This issue needs attention",
                 "custom_fields": [],

+ 1 - 0
tests/test_pagure_flask_api_user.py

@@ -1225,6 +1225,7 @@ class PagureFlaskApiUsertestissues(tests.Modeltests):
                   "blocks": [],
                   "close_status": None,
                   "closed_at": None,
+                  "closed_by": None,
                   "comments": [],
                   "content": "We should work on this",
                   "custom_fields": [],

+ 10 - 1
tests/test_pagure_flask_ui_issues.py

@@ -3960,7 +3960,9 @@ class PagureFlaskIssuestests(tests.Modeltests):
         self.assertEqual(msg.title, 'Test issue')
 
         user = tests.FakeUser()
-        user.username = 'pingou'
+        user.username = 'foo'
+        msg = pagure.lib.query.add_user_to_project(self.session, repo, "foo", "pingou")
+        self.session.commit()
         with tests.user_set(self.app.application, user):
             output = self.app.get('/test/issue/1')
             self.assertEqual(output.status_code, 200)
@@ -4002,6 +4004,13 @@ class PagureFlaskIssuestests(tests.Modeltests):
             self.assertTrue(
                 '<option selected value="Fixed">Fixed</option>'
                 in output_text)
+            self.assertIn(
+                '                Closed: Fixed\n'
+                '              </span> just now\n'
+                '            </span>\n'
+                '            by\n'
+                '            <span title="foo bar (foo)">foo.</span>\n',
+                output_text)
 
     def _set_up_for_reaction_test(self, private=False):
         tests.create_projects(self.session)

+ 6 - 3
tests/test_pagure_lib_git.py

@@ -1437,7 +1437,7 @@ new file mode 100644
 index 0000000..60f7480
 --- /dev/null
 +++ b/456
-@@ -0,0 +1,28 @@
+@@ -0,0 +1,29 @@
 +{
 +    "assignee": null,
 +    "blocks": [],
@@ -1493,6 +1493,8 @@ index 0000000..60f7480
             elif 'closed_at' in row:
                 t = row.split(': ')[0]
                 row = '%s: null,' % t
+            elif 'closed_by' in row:
+                continue
             elif row.startswith('index 00'):
                 row = 'index 0000000..60f7480'
             elif row.startswith('+++ b/'):
@@ -1535,8 +1537,7 @@ diff --git a/123 b/456
 index 458821a..77674a8
 --- a/123
 +++ b/456
-@@ -3,13 +3,32 @@
-     "blocks": [],
+@@ -4,13 +4,32 @@
      "close_status": null,
      "closed_at": null,
 -    "comments": [],
@@ -1593,6 +1594,8 @@ index 458821a..77674a8
             elif 'closed_at' in row:
                 t = row.split(': ')[0]
                 row = '%s: null,' % t
+            elif 'closed_by' in row:
+                continue
             elif row.startswith('index'):
                 row = 'index 458821a..77674a8'
             elif row.startswith('--- a/'):