# HG changeset patch # User Mike Becker # Date 1736881945 -3600 # Node ID 7a515768c481927f96de1d63bede1fc7ef9a103f # Parent 7280393d1fa7f522a9b6c1c5936e8f6d6b34aad9 add author to issue history and RSS feed - fixes #463 diff -r 7280393d1fa7 -r 7a515768c481 setup/postgres/psql_create_tables.sql --- a/setup/postgres/psql_create_tables.sql Tue Jan 14 19:21:48 2025 +0100 +++ b/setup/postgres/psql_create_tables.sql Tue Jan 14 20:12:25 2025 +0100 @@ -113,6 +113,7 @@ ( eventid serial primary key, issueid integer not null references lpit_issue (issueid) on delete cascade, + userid integer null references lpit_user (userid) on delete set null, subject text not null, time timestamp with time zone not null default now(), type issue_history_event not null diff -r 7280393d1fa7 -r 7a515768c481 setup/postgres/psql_patch_1.5.0.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup/postgres/psql_patch_1.5.0.sql Tue Jan 14 20:12:25 2025 +0100 @@ -0,0 +1,4 @@ +-- apply this script to patch a version < 1.5.0 database to version 1.5.0 + +alter table lpit_issue_history_event + add userid integer null references lpit_user (userid) on delete set null; diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt --- a/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt Tue Jan 14 20:12:25 2025 +0100 @@ -118,8 +118,8 @@ fun getIssueRelationMap(includeDone: Boolean): IssueRelationMap fun getIssueRelationMap(project: Project, includeDone: Boolean): IssueRelationMap - fun insertHistoryEvent(issue: Issue, newId: Int = 0) - fun insertHistoryEvent(issue: Issue, issueComment: IssueComment, newId: Int = 0) + fun insertHistoryEvent(author: User?, issue: Issue, newId: Int = 0) + fun insertHistoryEvent(author: User?, issue: Issue, issueComment: IssueComment, newId: Int = 0) /** * Lists the issue history, optionally restricted to [project], for the past [days]. diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt --- a/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt Tue Jan 14 20:12:25 2025 +0100 @@ -631,15 +631,16 @@ } } - override fun insertHistoryEvent(issue: Issue, newId: Int) { + override fun insertHistoryEvent(author: User?, issue: Issue, newId: Int) { val type = if (newId > 0) IssueHistoryType.New else IssueHistoryType.Update val issueid = if (newId > 0) newId else issue.id val eventid = - withStatement("insert into lpit_issue_history_event(issueid, subject, type) values (?,?,?::issue_history_event) returning eventid") { + withStatement("insert into lpit_issue_history_event(issueid, subject, type, userid) values (?,?,?::issue_history_event,?) returning eventid") { setInt(1, issueid) setString(2, issue.subject) setEnum(3, type) + setIntOrNull(4, author?.id) querySingle { it.getInt(1) }!! } withStatement( @@ -797,15 +798,16 @@ } - override fun insertHistoryEvent(issue: Issue, issueComment: IssueComment, newId: Int) { + override fun insertHistoryEvent(author: User?, issue: Issue, issueComment: IssueComment, newId: Int) { val type = if (newId > 0) IssueHistoryType.NewComment else IssueHistoryType.UpdateComment val commentid = if (newId > 0) newId else issueComment.id val eventid = - withStatement("insert into lpit_issue_history_event(issueid, subject, type) values (?,?,?::issue_history_event) returning eventid") { + withStatement("insert into lpit_issue_history_event(issueid, subject, type, userid) values (?,?,?::issue_history_event,?) returning eventid") { setInt(1, issueComment.issueid) setString(2, issue.subject) setEnum(3, type) + setIntOrNull(4, author?.id) querySingle { it.getInt(1) }!! } withStatement("insert into lpit_issue_comment_history (commentid, eventid, comment) values (?,?,?)") { @@ -823,7 +825,7 @@ override fun listIssueHistory(project: Project?, days: Int) = withStatement( """ - select p.name as project_name, u.username as current_assignee, evt.*, evtdata.* + select evt.userid as authorid, p.name as project_name, u.username as current_assignee, evt.*, evtdata.* from lpit_issue_history_event evt join lpit_issue issue using (issueid) join lpit_project p on project = p.projectid @@ -840,6 +842,9 @@ queryAll { rs-> with(rs) { IssueHistoryEntry( + author = getInt("authorid").let { + if (it > 0) findUser(it) else null + }, project = getString("project_name"), subject = getString("subject"), time = getTimestamp("time"), @@ -862,7 +867,7 @@ override fun listIssueCommentHistory(project: Project?, days: Int) = withStatement( """ - select u.username as current_assignee, evt.*, evtdata.* + select evt.userid as authorid, u.username as current_assignee, evt.*, evtdata.* from lpit_issue_history_event evt join lpit_issue issue using (issueid) left join lpit_user u on u.userid = issue.assignee @@ -878,6 +883,9 @@ queryAll { rs-> with(rs) { IssueCommentHistoryEntry( + author = getInt("authorid").let { + if (it > 0) findUser(it) else null + }, subject = getString("subject"), time = getTimestamp("time"), type = getEnum("type"), diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/entities/IssueHistoryEntry.kt --- a/src/main/kotlin/de/uapcore/lightpit/entities/IssueHistoryEntry.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/entities/IssueHistoryEntry.kt Tue Jan 14 20:12:25 2025 +0100 @@ -32,6 +32,7 @@ import java.sql.Timestamp class IssueHistoryEntry( + val author: User?, val project: String, val subject: String, val time: Timestamp, @@ -52,6 +53,7 @@ ) class IssueCommentHistoryEntry( + val author: User?, val subject: String, val time: Timestamp, val type: IssueHistoryType, diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt --- a/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt Tue Jan 14 20:12:25 2025 +0100 @@ -56,18 +56,19 @@ } fun processIssueForm(issue: Issue, reference: Issue, http: HttpRequest, dao: DataAccessObject) { + val remoteUser = http.remoteUser?.let { dao.findUserByName(it) } if (issue.hasChanged(reference)) { dao.updateIssue(issue) - dao.insertHistoryEvent(issue) + dao.insertHistoryEvent(remoteUser, issue) } val newComment = http.param("comment") if (!newComment.isNullOrBlank()) { val comment = IssueComment(-1, issue.id).apply { - author = http.remoteUser?.let { dao.findUserByName(it) } + author = remoteUser comment = newComment } val commentid = dao.insertComment(comment) - dao.insertHistoryEvent(issue, comment, commentid) + dao.insertHistoryEvent(remoteUser, issue, comment, commentid) } } @@ -83,6 +84,7 @@ } fun processIssueComment(issue:Issue, http: HttpRequest, dao: DataAccessObject): Boolean { + val remoteUser = http.remoteUser?.let { dao.findUserByName(it) } val commentId = http.param("commentid")?.toIntOrNull() ?: -1 if (commentId > 0) { val comment = dao.findComment(commentId) @@ -90,13 +92,12 @@ http.response.sendError(404) return false } - val originalAuthor = comment.author?.username - if (originalAuthor != null && originalAuthor == http.remoteUser) { + if (comment.author != null && comment.author?.id == remoteUser?.id) { val newComment = http.param("comment") if (!newComment.isNullOrBlank()) { comment.comment = newComment dao.updateComment(comment) - dao.insertHistoryEvent(issue, comment) + dao.insertHistoryEvent(remoteUser, issue, comment) } } else { http.response.sendError(403) @@ -104,11 +105,11 @@ } } else { val comment = IssueComment(-1, issue.id).apply { - author = http.remoteUser?.let { dao.findUserByName(it) } + author = remoteUser comment = http.param("comment") ?: "" } val newId = dao.insertComment(comment) - dao.insertHistoryEvent(issue, comment, newId) + dao.insertHistoryEvent(remoteUser, issue, comment, newId) } return true } diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Tue Jan 14 20:12:25 2025 +0100 @@ -140,10 +140,11 @@ entries.groupBy { it.issueid }.mapValues { (_, history) -> history.zipWithNext().map { (cur, next) -> IssueFeedEntry( - cur.time, cur.type, issue = diffContent(http, cur, next) + cur.author, cur.time, cur.type, + issue = diffContent(http, cur, next) ) }.plus( - history.last().let { IssueFeedEntry(it.time, it.type, issue = fullContent(http, it)) } + history.last().let { IssueFeedEntry(it.author, it.time, it.type, issue = fullContent(http, it)) } ) }.flatMap { it.value } } @@ -155,10 +156,11 @@ entries.groupBy { it.commentid }.mapValues { (_, history) -> history.zipWithNext().map { (cur, next) -> IssueFeedEntry( - cur.time, cur.type, comment = diffContent(cur, next) + cur.author, cur.time, cur.type, + comment = diffContent(cur, next) ) }.plus( - history.last().let { IssueFeedEntry(it.time, it.type, comment = fullContent(it)) } + history.last().let { IssueFeedEntry(it.author, it.time, it.type, comment = fullContent(it)) } ) }.flatMap { it.value } } diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Tue Jan 14 20:12:25 2025 +0100 @@ -395,8 +395,9 @@ ).applyFormData(http, dao) val openId = if (issue.id < 0) { + val remoteUser = http.remoteUser?.let { dao.findUserByName(it) } val id = dao.insertIssue(issue) - dao.insertHistoryEvent(issue, id) + dao.insertHistoryEvent(remoteUser, issue, id) id } else { val reference = dao.findIssue(issue.id) diff -r 7280393d1fa7 -r 7a515768c481 src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt --- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt Tue Jan 14 20:12:25 2025 +0100 @@ -26,6 +26,7 @@ package de.uapcore.lightpit.viewmodel import de.uapcore.lightpit.entities.Project +import de.uapcore.lightpit.entities.User import de.uapcore.lightpit.types.IssueHistoryType import java.sql.Timestamp import java.time.Instant @@ -55,6 +56,7 @@ ) class IssueFeedEntry( + val author: User?, val time: Timestamp, val type: IssueHistoryType, val issue: IssueDiff? = null, diff -r 7280393d1fa7 -r 7a515768c481 src/main/webapp/WEB-INF/changelogs/changelog-de.jspf --- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Tue Jan 14 19:21:48 2025 +0100 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Tue Jan 14 20:12:25 2025 +0100 @@ -27,11 +27,13 @@

Version 1.5.0 (Vorschau)