Loading repl/messages.go +81 −3 Original line number Diff line number Diff line Loading @@ -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 } Loading @@ -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 { Loading @@ -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 } Loading @@ -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 } Loading @@ -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" { Loading @@ -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 Loading storage/messages.sql.go +48 −7 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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, Loading @@ -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 Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading Loading @@ -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 } storage/migrations/1_create_table.up.sql +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading storage/models.go +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ type Message struct { Subject string Message string Permanent int64 System int64 Shutdown int64 Expiration time.Time CreateAt time.Time Loading storage/queries/messages.sql +11 −0 Original line number Diff line number Diff line Loading @@ -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 = ?; Loading
repl/messages.go +81 −3 Original line number Diff line number Diff line Loading @@ -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 } Loading @@ -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 { Loading @@ -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 } Loading @@ -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 } Loading @@ -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" { Loading @@ -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 Loading
storage/messages.sql.go +48 −7 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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, Loading @@ -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 Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading @@ -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 = ? Loading Loading @@ -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, Loading Loading @@ -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 }
storage/migrations/1_create_table.up.sql +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
storage/models.go +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ type Message struct { Subject string Message string Permanent int64 System int64 Shutdown int64 Expiration time.Time CreateAt time.Time Loading
storage/queries/messages.sql +11 −0 Original line number Diff line number Diff line Loading @@ -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 = ?;