From a4bec7c9e08b8dd87c3170d97a2b1145e04d5515 Mon Sep 17 00:00:00 2001 From: Kevin Lyda <kevin@lyda.ie> Date: Wed, 21 May 2025 22:29:36 +0100 Subject: [PATCH] Fix CHANGE --- repl/messages.go | 84 +++++++++++++++++++++++- storage/messages.sql.go | 55 ++++++++++++++-- storage/migrations/1_create_table.up.sql | 1 + storage/models.go | 1 + storage/queries/messages.sql | 11 ++++ storage/standard.sql.go | 6 +- 6 files changed, 146 insertions(+), 12 deletions(-) diff --git a/repl/messages.go b/repl/messages.go index 1a7dde0..70f589a 100644 --- a/repl/messages.go +++ b/repl/messages.go @@ -194,8 +194,13 @@ func ActionBack(_ *dclish.Command) error { // an existing message. func ActionChange(cmd *dclish.Command) error { var err error + isAdmin := this.User.Admin == 1 + optAll := false if cmd.Flags["/ALL"].Value == "true" { + if !isAdmin { + return errors.New("Must be admin") + } optAll = true } @@ -220,6 +225,9 @@ func ActionChange(cmd *dclish.Command) error { return errors.New("Can only be used in the GENERAL folder") } if cmd.Flags["/GENERAL"].Value == "true" { + if !isAdmin { + return errors.New("Must be admin") + } optGeneral = true } if cmd.Flags["/GENERAL"].Set && !optGeneral { @@ -231,12 +239,15 @@ func ActionChange(cmd *dclish.Command) error { optNew = true } - optNumber := []int64{this.MsgID} + msgids := []int64{this.MsgID} + if cmd.Flags["/NUMBER"].Set && optAll { + return errors.New("Can't set /ALL and /NUMBER") + } if cmd.Flags["/NUMBER"].Set && cmd.Flags["/NUMBER"].Value == "" { return errors.New("Must supply message number(s) if /NUMBER is set") } if cmd.Flags["/NUMBER"].Value != "" { - optNumber, err = ParseNumberList(cmd.Flags["/NUMBER"].Value) + msgids, err = ParseNumberList(cmd.Flags["/NUMBER"].Value) if err != nil { return err } @@ -249,6 +260,9 @@ func ActionChange(cmd *dclish.Command) error { optShutdown := false if cmd.Flags["/SHUTDOWN"].Value == "true" { + if !isAdmin { + return errors.New("Must be admin") + } optShutdown = true } @@ -262,7 +276,7 @@ func ActionChange(cmd *dclish.Command) error { optSystem := false if cmd.Flags["/SYSTEM"].Set { - if this.User.Admin == 0 { + if !isAdmin { return errors.New("Must be admin") } if this.Folder.Name != "GENERAL" { @@ -285,6 +299,70 @@ func ActionChange(cmd *dclish.Command) error { if optSystem && optGeneral { return errors.New("Can't specify /SYSTEM and /GENERAL") } + if optNew && !optText { + return errors.New("Must specify /TEXT if you specify /NEW") + } + ctx := storage.Context() + if optAll { + if optText { + return errors.New("Can't specify /TEXT with /ALL") + } + msgids, err = this.Q.ListMessageIDs(ctx, this.Folder.Name) + if err != nil { + return err + } + } + + isFolderOwner := folders.IsFolderOwner(this.Folder.Name, this.User.Login) + for i := range msgids { + msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgids[i]) + if err != nil { + return err + } + if msg.ID == 0 { + return fmt.Errorf("Failed to retrieve message number %d", msgids[i]) + } + if !(isAdmin || isFolderOwner || msg.Author == this.User.Login) { + return errors.New("Only admin or folder owner or author can change message") + } + if optSystem { + msg.System = 1 + } else if optGeneral { + msg.System = 0 + } + if cmd.Flags["/EXPIRATION"].Set { + msg.Expiration = *optExpiration + } + if optPermanent { + msg.Permanent = 1 + } + if optShutdown { + msg.Shutdown = 1 + } + if cmd.Flags["/SUBJECT"].Set { + msg.Subject = optSubject + } + if optText { + if optNew { + msg.Message = "" + } + msg.Message, err = editor.Editor( + fmt.Sprintf("Enter message for '%s'...", msg.Subject), + "Edit message", + msg.Message) + } + err = this.Q.UpdateMessage(ctx, storage.UpdateMessageParams{ + System: msg.System, + Expiration: msg.Expiration, + Permanent: msg.Permanent, + Shutdown: msg.Shutdown, + Subject: msg.Subject, + Message: msg.Message, + }) + if err != nil { + return err + } + } fmt.Println("TODO: flags parsed, now need to do something.") return nil diff --git a/storage/messages.sql.go b/storage/messages.sql.go index 5a5fb40..3e46406 100644 --- a/storage/messages.sql.go +++ b/storage/messages.sql.go @@ -233,7 +233,7 @@ func (q *Queries) PrevMsgidIgnoringSeen(ctx context.Context, arg PrevMsgidIgnori } const readMessage = `-- name: ReadMessage :one -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages WHERE folder = ? AND id = ? +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE folder = ? AND id = ? ` type ReadMessageParams struct { @@ -251,6 +251,7 @@ func (q *Queries) ReadMessage(ctx context.Context, arg ReadMessageParams) (Messa &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -260,7 +261,7 @@ func (q *Queries) ReadMessage(ctx context.Context, arg ReadMessageParams) (Messa } const search = `-- name: Search :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE (message LIKE '%' || ?1 || '%' OR subject LIKE '%' || ?1 || '%') AND id >= ?2 @@ -289,6 +290,7 @@ func (q *Queries) Search(ctx context.Context, arg SearchParams) ([]Message, erro &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -308,7 +310,7 @@ func (q *Queries) Search(ctx context.Context, arg SearchParams) ([]Message, erro } const searchReply = `-- name: SearchReply :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE subject = ? AND id >= ? AND folder = ? @@ -336,6 +338,7 @@ func (q *Queries) SearchReply(ctx context.Context, arg SearchReplyParams) ([]Mes &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -355,7 +358,7 @@ func (q *Queries) SearchReply(ctx context.Context, arg SearchReplyParams) ([]Mes } const searchReplyReverse = `-- name: SearchReplyReverse :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE subject = ? AND id <= ? AND folder = ? @@ -384,6 +387,7 @@ func (q *Queries) SearchReplyReverse(ctx context.Context, arg SearchReplyReverse &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -403,7 +407,7 @@ func (q *Queries) SearchReplyReverse(ctx context.Context, arg SearchReplyReverse } const searchReverse = `-- name: SearchReverse :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE (message LIKE '%' || ?1 || '%' OR subject LIKE '%' || ?1 || '%') AND id <= ?2 @@ -433,6 +437,7 @@ func (q *Queries) SearchReverse(ctx context.Context, arg SearchReverseParams) ([ &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -452,7 +457,7 @@ func (q *Queries) SearchReverse(ctx context.Context, arg SearchReverseParams) ([ } const searchSubject = `-- name: SearchSubject :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE subject LIKE '%' || ? || '%' AND id >= ? AND folder = ? @@ -480,6 +485,7 @@ func (q *Queries) SearchSubject(ctx context.Context, arg SearchSubjectParams) ([ &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -499,7 +505,7 @@ func (q *Queries) SearchSubject(ctx context.Context, arg SearchSubjectParams) ([ } const searchSubjectReverse = `-- name: SearchSubjectReverse :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE subject LIKE '%' || ? || '%' AND id <= ? AND folder = ? @@ -528,6 +534,7 @@ func (q *Queries) SearchSubjectReverse(ctx context.Context, arg SearchSubjectRev &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -575,3 +582,37 @@ func (q *Queries) UnsetMessageSeen(ctx context.Context, arg UnsetMessageSeenPara _, err := q.db.ExecContext(ctx, unsetMessageSeen, arg.Login, arg.Folder, arg.Msgid) return err } + +const updateMessage = `-- name: UpdateMessage :exec +UPDATE messages SET + subject = ?, + message = ?, + permanent = ?, + system = ?, + shutdown = ?, + expiration = ? + WHERE id = ? +` + +type UpdateMessageParams struct { + Subject string + Message string + Permanent int64 + System int64 + Shutdown int64 + Expiration time.Time + ID int64 +} + +func (q *Queries) UpdateMessage(ctx context.Context, arg UpdateMessageParams) error { + _, err := q.db.ExecContext(ctx, updateMessage, + arg.Subject, + arg.Message, + arg.Permanent, + arg.System, + arg.Shutdown, + arg.Expiration, + arg.ID, + ) + return err +} diff --git a/storage/migrations/1_create_table.up.sql b/storage/migrations/1_create_table.up.sql index 2f066f8..690387f 100644 --- a/storage/migrations/1_create_table.up.sql +++ b/storage/migrations/1_create_table.up.sql @@ -111,6 +111,7 @@ CREATE TABLE messages ( subject VARCHAR(53) NOT NULL, message TEXT NOT NULL, permanent INT DEFAULT 0 NOT NULL, + system INT DEFAULT 0 NOT NULL, shutdown INT DEFAULT 0 NOT NULL, expiration TIMESTAMP NOT NULL, create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, diff --git a/storage/models.go b/storage/models.go index 1292885..98bbe36 100644 --- a/storage/models.go +++ b/storage/models.go @@ -55,6 +55,7 @@ type Message struct { Subject string Message string Permanent int64 + System int64 Shutdown int64 Expiration time.Time CreateAt time.Time diff --git a/storage/queries/messages.sql b/storage/queries/messages.sql index 901d71c..7d9abf3 100644 --- a/storage/queries/messages.sql +++ b/storage/queries/messages.sql @@ -95,3 +95,14 @@ SELECT * FROM messages AND id <= ? AND folder = ? ORDER BY DESC; + +-- name: UpdateMessage :exec +UPDATE messages SET + subject = ?, + message = ?, + permanent = ?, + system = ?, + shutdown = ?, + expiration = ? + WHERE id = ?; + diff --git a/storage/standard.sql.go b/storage/standard.sql.go index 01d0e14..be420e6 100644 --- a/storage/standard.sql.go +++ b/storage/standard.sql.go @@ -287,7 +287,7 @@ func (q *Queries) GetMark(ctx context.Context, arg GetMarkParams) (Mark, error) } const getMessage = `-- name: GetMessage :one -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages WHERE id = ? AND folder = ? +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE id = ? AND folder = ? ` type GetMessageParams struct { @@ -305,6 +305,7 @@ func (q *Queries) GetMessage(ctx context.Context, arg GetMessageParams) (Message &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, @@ -558,7 +559,7 @@ func (q *Queries) ListMessageIDs(ctx context.Context, folder string) ([]int64, e } const listMessages = `-- name: ListMessages :many -SELECT id, folder, author, subject, message, permanent, shutdown, expiration, create_at, update_at FROM messages WHERE folder = ? ORDER BY id +SELECT id, folder, author, subject, message, permanent, system, shutdown, expiration, create_at, update_at FROM messages WHERE folder = ? ORDER BY id ` func (q *Queries) ListMessages(ctx context.Context, folder string) ([]Message, error) { @@ -577,6 +578,7 @@ func (q *Queries) ListMessages(ctx context.Context, folder string) ([]Message, e &i.Subject, &i.Message, &i.Permanent, + &i.System, &i.Shutdown, &i.Expiration, &i.CreateAt, -- GitLab