Commit 30110bed authored by Kevin Lyda's avatar Kevin Lyda
Browse files

Address code duplication

Addresses part of #18, but more to go.
parent aa5bb817
Loading
Loading
Loading
Loading
+11 −30
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ things about folders. The storage specific bits should go to [storage].
package folders

import (
	"context"
	"database/sql"
	"errors"
	"strings"
@@ -95,8 +96,7 @@ func FindFolder(name string) (storage.Folder, error) {
	return folder, nil
}

// IsFolderReadable checks if a user can read messages from a folder.
func IsFolderReadable(name, login string) (bool, error) {
func isFolderRWO(name, login string, check func(context.Context, string, string) (int64, error)) (bool, error) {
	ctx := storage.Context()
	admin, err := this.Q.IsUserAdmin(ctx, login)
	if err != nil {
@@ -105,45 +105,26 @@ func IsFolderReadable(name, login string) (bool, error) {
	if admin == 1 {
		return true, nil
	}
	found, err := this.Q.IsFolderReadable(ctx, name, login)
	found, err := check(ctx, name, login)
	if err != nil {
		return false, err
	}
	return found == 1, nil
}

// IsFolderWriteable checks if a user can write messages into a folder.
func IsFolderWriteable(name, login string) (bool, error) {
	ctx := storage.Context()
	admin, err := this.Q.IsUserAdmin(ctx, login)
	if err != nil {
		return false, err
	}
	if admin == 1 {
		return true, nil
	}
	found, err := this.Q.IsFolderWriteable(ctx, name, login)
	if err != nil {
		return false, err
// IsFolderReadable checks if a user can read messages from a folder.
func IsFolderReadable(folder, login string) (bool, error) {
	return isFolderRWO(folder, login, this.Q.IsFolderReadable)
}
	return found == 1, nil

// IsFolderWriteable checks if a user can write messages into a folder.
func IsFolderWriteable(folder, login string) (bool, error) {
	return isFolderRWO(folder, login, this.Q.IsFolderWriteable)
}

// IsFolderOwner checks if a user is a folder owner.
func IsFolderOwner(folder, login string) (bool, error) {
	ctx := storage.Context()
	admin, err := this.Q.IsUserAdmin(ctx, login)
	if err != nil {
		return false, err
	}
	if admin == 1 {
		return true, nil
	}
	found, err := this.Q.IsFolderOwner(ctx, folder, login)
	if err != nil {
		return false, err
	}
	return found == 1, nil
	return isFolderRWO(folder, login, this.Q.IsFolderOwner)
}

// DeleteFolder deletes a folder.
+11 −27
Original line number Diff line number Diff line
package folders

import (
	"context"
	"errors"
	"fmt"
	"time"
@@ -124,28 +125,25 @@ func GetMessage(login, folder string, msgid int64) (*storage.Message, error) {
	return &msg, nil
}

// MarkSeen marks a list of messages as seen.
func MarkSeen(msgids []int64) error {
func modifyMsgAttributes(msgids []int64, modify func(context.Context, string, string, int64) error) error {
	ctx := storage.Context()

	for _, msgid := range msgids {
		if err := this.Q.SetMessageSeen(ctx, this.User.Login, this.Folder.Name, msgid); err != nil {
		if err := modify(ctx, this.User.Login, this.Folder.Name, msgid); err != nil {
			return err
		}
	}
	return nil
}

// MarkSeen marks a list of messages as seen.
func MarkSeen(msgids []int64) error {
	return modifyMsgAttributes(msgids, this.Q.SetMessageSeen)
}

// MarkUnseen marks a list of messages as unseen.
func MarkUnseen(msgids []int64) error {
	ctx := storage.Context()

	for _, msgid := range msgids {
		if err := this.Q.UnsetMessageSeen(ctx, this.User.Login, this.Folder.Name, msgid); err != nil {
			return err
		}
	}
	return nil
	return modifyMsgAttributes(msgids, this.Q.UnsetMessageSeen)
}

// NextMsgid gets the next message id.
@@ -290,24 +288,10 @@ func DeleteAllMessages() error {

// SetMark sets a mark for message(s).
func SetMark(msgids []int64) error {
	ctx := storage.Context()

	for _, msgid := range msgids {
		if err := this.Q.AddMark(ctx, this.Folder.Name, this.User.Login, msgid); err != nil {
			return err
		}
	}
	return nil
	return modifyMsgAttributes(msgids, this.Q.AddMark)
}

// UnsetMark removes a mark for message(s).
func UnsetMark(msgids []int64) error {
	ctx := storage.Context()

	for _, msgid := range msgids {
		if err := this.Q.DeleteMark(ctx, this.Folder.Name, this.User.Login, msgid); err != nil {
			return err
		}
	}
	return nil
	return modifyMsgAttributes(msgids, this.Q.DeleteMark)
}
+11 −22
Original line number Diff line number Diff line
@@ -607,12 +607,8 @@ func ActionChange(cmd *dclish.Command) error {
	return nil
}

// ActionFirst handles the `FIRST` command.  Prints the first message in
// a folder.
//
// This originally existed as... not sure.
func ActionFirst(_ *dclish.Command) error {
	msgid := folders.FirstMessage(this.Folder.Name)
func msgExtreme(msgPos func(string) int64) error {
	msgid := msgPos(this.Folder.Name)
	if msgid == 0 {
		fmt.Println("No messages in folder")
		return nil
@@ -630,26 +626,19 @@ func ActionFirst(_ *dclish.Command) error {
	return nil
}

// ActionFirst handles the `FIRST` command.  Prints the first message in
// a folder.
//
// This originally existed as... not sure.
func ActionFirst(_ *dclish.Command) error {
	return msgExtreme(folders.FirstMessage)
}

// ActionLast handles the `LAST` command. Prints the last message.
//
// This originally existed as... not sure.
func ActionLast(_ *dclish.Command) error {
	msgid := folders.LastMessage(this.Folder.Name)
	if msgid == 0 {
		fmt.Println("No messages in folder")
		return nil
	}
	this.MsgID = msgid
	msg, err := folders.GetMessage(this.User.Login, this.Folder.Name, msgid)
	if err != nil {
		return err
	}
	if pager.Pager(msg.String()) {
		if err := folders.MarkSeen([]int64{msgid}); err != nil {
			return err
		}
	}
	return nil
	return msgExtreme(folders.LastMessage)
}

// ActionNext handles the `NEXT` command.  Shows the next message.
+17 −20
Original line number Diff line number Diff line
package repl

import (
	"context"
	"errors"
	"fmt"
	"strconv"
@@ -150,22 +151,22 @@ func ActionSetAccess(cmd *dclish.Command) error {
	return this.Q.UpdateFolderAccess(ctx, login, folder.Name, visibility)
}

// ActionSetAlways handles the `SET ALWAYS` command.
func ActionSetAlways(_ *dclish.Command) error {
func setAlways(always int64) error {
	if this.User.Admin == 0 && this.User.Login != this.Folder.Owner {
		return errors.New("no privileges to modify folder")
	}
	ctx := storage.Context()
	return this.Q.UpdateFolderAlways(ctx, 1, this.Folder.Name)
	return this.Q.UpdateFolderAlways(ctx, always, this.Folder.Name)
}

// ActionSetAlways handles the `SET ALWAYS` command.
func ActionSetAlways(_ *dclish.Command) error {
	return setAlways(1)
}

// ActionSetNoalways handles the `SET NOALWAYS` command.
func ActionSetNoalways(_ *dclish.Command) error {
	if this.User.Admin == 0 && this.User.Login != this.Folder.Owner {
		return errors.New("no privileges to modify folder")
	}
	ctx := storage.Context()
	return this.Q.UpdateFolderAlways(ctx, 0, this.Folder.Name)
	return setAlways(0)
}

// ActionSetBrief handles the `SET BRIEF` command.
@@ -178,8 +179,7 @@ func ActionSetNobrief(cmd *dclish.Command) error {
	return setAlert(cmd, storage.AlertNone)
}

// ActionSetDefaultExpire handles the `SET DEFAULT_EXPIRE` command.
func ActionSetDefaultExpire(cmd *dclish.Command) error {
func setExpire(cmd *dclish.Command, expire func(context.Context, int64) error) error {
	if this.User.Admin == 0 {
		return errors.New("privileges needed for changing defaults")
	}
@@ -188,20 +188,17 @@ func ActionSetDefaultExpire(cmd *dclish.Command) error {
		return err
	}
	ctx := storage.Context()
	return this.Q.UpdateDefaultExpire(ctx, value)
	return expire(ctx, value)
}

// ActionSetDefaultExpire handles the `SET DEFAULT_EXPIRE` command.
func ActionSetDefaultExpire(cmd *dclish.Command) error {
	return setExpire(cmd, this.Q.UpdateDefaultExpire)
}

// ActionSetExpireLimit handles the `SET EXPIRE_LIMIT` command.
func ActionSetExpireLimit(cmd *dclish.Command) error {
	if this.User.Admin == 0 {
		return errors.New("privileges needed for changing defaults")
	}
	value, err := strconv.ParseInt(cmd.Args[0], 10, 64)
	if err != nil {
		return err
	}
	ctx := storage.Context()
	return this.Q.UpdateExpireLimit(ctx, value)
	return setExpire(cmd, this.Q.UpdateExpireLimit)
}

// ActionSetPromptExpire handles the `SET PROMPT_EXPIRE` command.
+2 −2
Original line number Diff line number Diff line
@@ -38,11 +38,11 @@ DELETE FROM messages WHERE id = ? AND folder = ?;

-- AddMark mark a message id for a login in a folder.
-- name: AddMark :exec
INSERT INTO marks (folder, login, msgid) VALUES (?, ?, ?);
INSERT INTO marks (login, folder, msgid) VALUES (?, ?, ?);

-- DeleteMark unmark a message id for a login in a folder.
-- name: DeleteMark :exec
DELETE FROM marks WHERE folder = ? AND login = ? AND msgid = ?;
DELETE FROM marks WHERE login = ? AND folder = ? AND msgid = ?;

-- UpdateFolderAccess update folder visibility for a given login and
-- folder.
Loading