From 54e6832bcfe9a7e10c3636735c77e2acd2157efe Mon Sep 17 00:00:00 2001
From: Kevin Lyda <kevin@lyda.ie>
Date: Fri, 16 May 2025 07:33:26 +0100
Subject: [PATCH] Some initial work on SHOW USER

---
 repl/command.go                          |  5 ++---
 repl/show.go                             | 19 ++++++++++++++++++-
 storage/migrations/1_create_table.up.sql | 10 ++++++++++
 storage/models.go                        |  7 ++++---
 storage/standard.sql.go                  | 18 ++++++++++++++----
 5 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/repl/command.go b/repl/command.go
index e048e30..074fdcf 100644
--- a/repl/command.go
+++ b/repl/command.go
@@ -1647,9 +1647,8 @@ have done this.`,
 						Description: `/FOLDER=[foldername]
 
   Specifies to display  the latest message that was read  by the user(s)
-  for the  specified foldername. A  newsgroup can be specified,  but the
-  info can only be shown if the user has subscribed to the newsgroup. If
-  the foldername is not specified, the selected folder will be used.`,
+  for the specified foldername.  If the foldername is not specified, the
+	selected folder will be used.`,
 					},
 					"/SINCE": {
 						Description: `/SINCE=[date]
diff --git a/repl/show.go b/repl/show.go
index 9448f78..f800729 100644
--- a/repl/show.go
+++ b/repl/show.go
@@ -115,8 +115,25 @@ func ActionShowPrivileges(_ *dclish.Command) error {
 }
 
 // ActionShowUser handles the `SHOW USER` command.
-func ActionShowUser(_ *dclish.Command) error {
+func ActionShowUser(cmd *dclish.Command) error {
+	showAll := false
+	if cmd.Flags["/ALL"].Value == "true" {
+		// TODO: Check permissions.
+		showAll = true
+	}
+	showLogin := false
+	if cmd.Flags["/LOGIN"].Value == "true" {
+		// TODO: Check permissions.
+		showLogin = true
+	}
+	folder := this.Folder
+	if cmd.Flags["/FOLDER"].Value != "" {
+		// TODO: Check permissions.
+		folder = folders.FindFolder(cmd.Flags["/FOLDER"].Value)
+	}
+	since := cmd.Flags["/FOLDER"].Value
 	fmt.Println("TODO: implement ActionShowUser.")
+	fmt.Printf("TODO: %t %t %s %s.\n", showAll, showLogin, folder.Name, since)
 	return nil
 }
 
diff --git a/storage/migrations/1_create_table.up.sql b/storage/migrations/1_create_table.up.sql
index 863515c..b2de88b 100644
--- a/storage/migrations/1_create_table.up.sql
+++ b/storage/migrations/1_create_table.up.sql
@@ -121,12 +121,22 @@ CREATE TABLE messages (
 CREATE INDEX messages_idx_shutdown ON messages(shutdown);
 CREATE INDEX messages_idx_expiration ON messages(expiration);
 
+CREATE TRIGGER messages_after_update_update_at
+  AFTER UPDATE ON messages FOR EACH ROW
+    WHEN NEW.update_at = OLD.update_at    --- avoid infinite loop
+BEGIN
+  UPDATE messages SET update_at=CURRENT_TIMESTAMP
+    WHERE folder=NEW.folder AND id=NEW.id;
+END;
+
 CREATE TABLE seen (
   login       VARCHAR(25) REFERENCES users(login)
               ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
   folder      VARCHAR(25) REFERENCES folders(name)
               ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
   msgid       INT     NOT NULL,
+  create_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  --- Nothing to update in this table.
   PRIMARY KEY (folder, login, msgid),
   CONSTRAINT read_fk_id_folder
     FOREIGN KEY (msgid, folder)
diff --git a/storage/models.go b/storage/models.go
index ea5558c..d0089ad 100644
--- a/storage/models.go
+++ b/storage/models.go
@@ -62,9 +62,10 @@ type Owner struct {
 }
 
 type Seen struct {
-	Login  string
-	Folder string
-	Msgid  int64
+	Login    string
+	Folder   string
+	Msgid    int64
+	CreateAt time.Time
 }
 
 type System struct {
diff --git a/storage/standard.sql.go b/storage/standard.sql.go
index ffe19b2..b192647 100644
--- a/storage/standard.sql.go
+++ b/storage/standard.sql.go
@@ -376,7 +376,7 @@ func (q *Queries) GetOwners(ctx context.Context, folder string) ([]Owner, error)
 }
 
 const getSeen = `-- name: GetSeen :one
-SELECT login, folder, msgid FROM seen WHERE folder = ? AND login = ? AND msgid = ?
+SELECT login, folder, msgid, create_at FROM seen WHERE folder = ? AND login = ? AND msgid = ?
 `
 
 type GetSeenParams struct {
@@ -388,7 +388,12 @@ type GetSeenParams struct {
 func (q *Queries) GetSeen(ctx context.Context, arg GetSeenParams) (Seen, error) {
 	row := q.db.QueryRowContext(ctx, getSeen, arg.Folder, arg.Login, arg.Msgid)
 	var i Seen
-	err := row.Scan(&i.Login, &i.Folder, &i.Msgid)
+	err := row.Scan(
+		&i.Login,
+		&i.Folder,
+		&i.Msgid,
+		&i.CreateAt,
+	)
 	return i, err
 }
 
@@ -600,7 +605,7 @@ func (q *Queries) ListOwners(ctx context.Context) ([]Owner, error) {
 }
 
 const listSeen = `-- name: ListSeen :many
-SELECT login, folder, msgid FROM seen
+SELECT login, folder, msgid, create_at FROM seen
 `
 
 func (q *Queries) ListSeen(ctx context.Context) ([]Seen, error) {
@@ -612,7 +617,12 @@ func (q *Queries) ListSeen(ctx context.Context) ([]Seen, error) {
 	var items []Seen
 	for rows.Next() {
 		var i Seen
-		if err := rows.Scan(&i.Login, &i.Folder, &i.Msgid); err != nil {
+		if err := rows.Scan(
+			&i.Login,
+			&i.Folder,
+			&i.Msgid,
+			&i.CreateAt,
+		); err != nil {
 			return nil, err
 		}
 		items = append(items, i)
-- 
GitLab