diff --git a/folders/folders.go b/folders/folders.go
index 436e71c8c5e795efc65b6d285eb5e4a240b10f94..2f9cdf6e513f2551d2f7b5a9814c036f6806b0a4 100644
--- a/folders/folders.go
+++ b/folders/folders.go
@@ -2,6 +2,7 @@
package folders
import (
+ "database/sql"
"errors"
"strings"
@@ -63,7 +64,10 @@ func FindFolder(name string) storage.Folder {
if folder.Name != "" {
return folder
}
- folder, _ = this.Q.FindFolderPrefix(ctx, name)
+ folder, _ = this.Q.FindFolderPrefix(ctx, sql.NullString{
+ String: name,
+ Valid: true,
+ })
return folder
}
diff --git a/folders/messages.go b/folders/messages.go
index fd762401e1e428a60026be8fa0c50b9f9e061caa..055ec887514a944439b554699cceaa96f8492764 100644
--- a/folders/messages.go
+++ b/folders/messages.go
@@ -2,7 +2,6 @@ package folders
import (
"errors"
- "fmt"
"time"
"git.lyda.ie/kevin/bulletin/storage"
@@ -39,10 +38,9 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown
return err
}
-// ReadMessage reads a message for a user.
-func ReadMessage(login, folder string, msgid int64) (*storage.Message, error) {
+// GetMessage reads a message for a user.
+func GetMessage(login, folder string, msgid int64) (*storage.Message, error) {
ctx := storage.Context()
- fmt.Printf("TODO(ReadMessage): Make sure %s can read this message.\n", login)
msg, err := this.Q.ReadMessage(ctx, storage.ReadMessageParams{
Folder: folder,
ID: msgid,
diff --git a/key/key.go b/key/key.go
index 77f267b4d7d4f96ec1f5aacbe54cdd50e300f80d..46a6ceee691b96a2b18aaac406b1a13540a64447 100644
--- a/key/key.go
+++ b/key/key.go
@@ -212,7 +212,7 @@ func Fetch(login, nickname, username string) string {
keys := 0
for scanner.Scan() {
keyline := string(bytes.TrimSpace(scanner.Bytes()))
- Add(login, keyline)
+ Add(strings.ToUpper(login), keyline)
keys++
}
switch keys {
diff --git a/main.go b/main.go
index 8d48d462829cbb4f8f43f47ec646a499c8a608c9..ce9562b2be82f1fa585d7d13242427bba45f5ad8 100644
--- a/main.go
+++ b/main.go
@@ -6,6 +6,7 @@ import (
"context"
"fmt"
"os"
+ "strings"
"git.lyda.ie/kevin/bulletin/batch"
"git.lyda.ie/kevin/bulletin/repl"
@@ -33,7 +34,7 @@ func main() {
},
},
Action: func(_ context.Context, cmd *cli.Command) error {
- user := cmd.String("user")
+ user := strings.ToUpper(cmd.String("user"))
batchFlag := cmd.String("batch")
if batchFlag != "" {
diff --git a/repl/messages.go b/repl/messages.go
index 03b926872355f63da4456b2efc20f945565645f7..83b387bd729eed7c978d2d4df7fe70a84bfb49f6 100644
--- a/repl/messages.go
+++ b/repl/messages.go
@@ -58,6 +58,8 @@ func ActionDirectory(cmd *dclish.Command) error {
// ActionAdd handles the `ADD` command. This adds a message to a folder.
func ActionAdd(cmd *dclish.Command) error {
+ ctx := storage.Context()
+
optAll := 0
optBell := 0
optBroadcast := 0
@@ -74,15 +76,19 @@ func ActionAdd(cmd *dclish.Command) error {
if cmd.Flags["/ALL"].Value == "true" {
optAll = 1
+ fmt.Printf("TODO: optAll is not yet implemented - you set it to %d\n", optAll)
}
if cmd.Flags["/BELL"].Value == "true" {
optBell = 1
+ fmt.Printf("TODO: optBell is not yet implemented - you set it to %d\n", optBell)
}
if cmd.Flags["/BROADCAST"].Value == "true" {
optBroadcast = 1
+ fmt.Printf("TODO: optBroadcast is not yet implemented - you set it to %d\n", optBroadcast)
}
if cmd.Flags["/EDIT"].Value == "true" {
optEdit = 1
+ fmt.Printf("TODO: optEdit is not yet implemented - you set it to %d\n", optEdit)
}
if cmd.Flags["/EXPIRATION"].Value != "" {
// dd-mmm-yyyy, or delta time: dddd
@@ -100,12 +106,14 @@ func ActionAdd(cmd *dclish.Command) error {
}
if cmd.Flags["/EXTRACT"].Value == "true" {
optExtract = 1
+ fmt.Printf("TODO: optExtract is not yet implemented - you set it to %d\n", optExtract)
}
if cmd.Flags["/FOLDER"].Value != "" {
optFolder = strings.Split(cmd.Flags["/FOLDER"].Value, ",")
}
if cmd.Flags["/INDENT"].Value == "true" {
optIndent = 1
+ fmt.Printf("TODO: optIndent is not yet implemented - you set it to %d\n", optIndent)
}
if cmd.Flags["/PERMANENT"].Value == "true" {
optPermanent = 1
@@ -115,34 +123,38 @@ func ActionAdd(cmd *dclish.Command) error {
}
if cmd.Flags["/SIGNATURE"].Value == "true" {
optSignature = 1
+ fmt.Printf("TODO: optSignature is not yet implemented - you set it to %d\n", optSignature)
}
if cmd.Flags["/SUBJECT"].Value != "" {
optSubject = cmd.Flags["/SUBJECT"].Value
}
if cmd.Flags["/SYSTEM"].Value == "true" {
optSystem = 1
+ fmt.Printf("TODO: optSystem is not yet implemented - you set it to %d\n", optSystem)
}
- fmt.Printf("TODO: optAll is not yet implemented - you set it to %d\n", optAll)
- fmt.Printf("TODO: optBell is not yet implemented - you set it to %d\n", optBell)
- fmt.Printf("TODO: optBroadcast is not yet implemented - you set it to %d\n", optBroadcast)
- fmt.Printf("TODO: optEdit is not yet implemented - you set it to %d\n", optEdit)
- fmt.Printf("TODO: optExtract is not yet implemented - you set it to %d\n", optExtract)
- fmt.Printf("TODO: optIndent is not yet implemented - you set it to %d\n", optIndent)
- fmt.Printf("TODO: optSignature is not yet implemented - you set it to %d\n", optSignature)
- fmt.Printf("TODO: optSystem is not yet implemented - you set it to %d\n", optSystem)
-
if len(optFolder) == 0 {
optFolder = []string{this.Folder.Name}
}
- // TODO: check if folders exist.
+ for i := range optFolder {
+ f, _ := this.Q.FindFolderExact(ctx, optFolder[i])
+ if f.Name == "" {
+ return fmt.Errorf("Folder '%s' does not exist", optFolder[i])
+ }
+ if f.Visibility != 0 && this.User.Admin == 0 && this.User.Login != f.Owner {
+ return fmt.Errorf("Folder '%s' is not accessible", optFolder[i])
+ }
+ }
+
if optSubject == "" {
optSubject, _ = ask.GetLine("Enter subject of message: ")
if optSubject == "" {
return errors.New("Must enter a subject")
}
}
- // TODO: check we have permission for shutdown and permanent
+ if optShutdown == 1 && this.User.Admin == 0 {
+ return errors.New("Must be an admin to set shutdown")
+ }
message, err := editor.Editor(
fmt.Sprintf("Enter message for '%s'...", optSubject),
@@ -160,7 +172,7 @@ func ActionAdd(cmd *dclish.Command) error {
// ActionCurrent handles the `CURRENT` command.
func ActionCurrent(_ *dclish.Command) error {
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, this.MsgID)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, this.MsgID)
if err != nil {
return err
}
@@ -179,7 +191,7 @@ func ActionBack(_ *dclish.Command) error {
fmt.Println("No previous messages")
return nil
}
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
return err
}
@@ -315,7 +327,7 @@ func ActionChange(cmd *dclish.Command) error {
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])
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgids[i])
if err != nil {
return err
}
@@ -376,7 +388,7 @@ func ActionFirst(_ *dclish.Command) error {
return nil
}
this.MsgID = msgid
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
return err
}
@@ -394,7 +406,7 @@ func ActionLast(_ *dclish.Command) error {
return nil
}
this.MsgID = msgid
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
return err
}
@@ -411,7 +423,7 @@ func ActionNext(_ *dclish.Command) error {
fmt.Println("No next messages")
return nil
}
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
return err
}
@@ -446,7 +458,7 @@ func ActionPrint(cmd *dclish.Command) error {
}
print("\033[5i")
for _, msgid := range msgids {
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
fmt.Printf("Message %d not found.\n", msgid)
} else {
@@ -476,7 +488,7 @@ func ActionRead(cmd *dclish.Command) error {
}
}
this.MsgID = msgid
- msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+ msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
if err != nil {
return err
}
@@ -496,7 +508,7 @@ func ActionReply(cmd *dclish.Command) error {
if cmd.Flags["/INDENT"].Value == "false" {
indent = false
}
- original, err := folders.ReadMessage(this.User.Login, this.Folder.Name, this.MsgID)
+ original, err := folders.GetMessage(this.User.Login, this.Folder.Name, this.MsgID)
origMsg := ""
if extract {
if indent {
diff --git a/storage/folders.sql.go b/storage/folders.sql.go
index 98722dabe26e97740d2f1099af6e3960542b74fd..b479c9efd98fd7f98bd6f672a8d4f56142064b5f 100644
--- a/storage/folders.sql.go
+++ b/storage/folders.sql.go
@@ -7,6 +7,7 @@ package storage
import (
"context"
+ "database/sql"
)
const createFolder = `-- name: CreateFolder :exec
@@ -64,12 +65,12 @@ func (q *Queries) FindFolderExact(ctx context.Context, name string) (Folder, err
}
const findFolderPrefix = `-- name: FindFolderPrefix :one
-SELECT name, "always", alert, description, owner, system, expire, visibility, create_at, update_at FROM folders where name LIKE ?
+SELECT name, "always", alert, description, owner, system, expire, visibility, create_at, update_at FROM folders where name LIKE ?1 || '%'
ORDER BY name
LIMIT 1
`
-func (q *Queries) FindFolderPrefix(ctx context.Context, name string) (Folder, error) {
+func (q *Queries) FindFolderPrefix(ctx context.Context, name sql.NullString) (Folder, error) {
row := q.db.QueryRowContext(ctx, findFolderPrefix, name)
var i Folder
err := row.Scan(
diff --git a/storage/queries/folders.sql b/storage/queries/folders.sql
index 7f965c5a67d3710bbbe92ee6e775b508b253dd1a..6c8aba995606f32ae9a45b343e877fa506370ce7 100644
--- a/storage/queries/folders.sql
+++ b/storage/queries/folders.sql
@@ -20,7 +20,7 @@ ORDER BY f.name;
SELECT * FROM folders where name = ?;
-- name: FindFolderPrefix :one
-SELECT * FROM folders where name LIKE ?
+SELECT * FROM folders where name LIKE sqlc.arg(name) || '%'
ORDER BY name
LIMIT 1;