kittemail/user.go

143 lines
2.8 KiB
Go
Raw Normal View History

2024-12-10 19:54:22 +00:00
package main
import (
"errors"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/backend"
"github.com/google/uuid"
)
type User struct {
username string
sub uuid.UUID
openMessages map[*Message]struct{}
}
func (u *User) Username() string {
return u.username
}
func (u *User) ListMailboxes(subscribed bool) (mailboxes []backend.Mailbox, err error) {
mailboxQuery, err := Database.DB.Query("SELECT mailbox, subscribed FROM mailboxes")
if err != nil {
return nil, err
}
defer func() {
err := mailboxQuery.Close()
if err != nil {
log("Failed to close rows: "+err.Error()+", resource leaks may occur", 1)
}
}()
for mailboxQuery.Next() {
var name string
var subscribed bool
err := mailboxQuery.Scan(&name, &subscribed)
if err != nil {
return nil, err
}
mbox := &Mailbox{
name: name,
user: u,
}
mbox.Subscribed = subscribed
err = Database.DB.QueryRow("SELECT id FROM mailboxes WHERE mailbox = $1", name).Scan(&mbox.id)
if err != nil {
return nil, err
}
mailboxes = append(mailboxes, mbox)
}
return mailboxes, nil
}
func (u *User) GetRawMailbox(name string) (mailbox *Mailbox, err error) {
mailbox = &Mailbox{
name: name,
user: u,
}
err = Database.DB.QueryRow("SELECT id, subscribed FROM mailboxes WHERE mailbox = $1", name).Scan(&mailbox.id, &mailbox.Subscribed)
if err != nil {
return nil, err
}
return mailbox, nil
}
func (u *User) GetMailbox(name string) (mailbox backend.Mailbox, err error) {
return u.GetRawMailbox(name)
}
func (u *User) CreateMailbox(name string) error {
_, err := Database.DB.Exec("INSERT INTO mailboxes (mailbox, id, owner) VALUES ($1, $2, $3)", name, uuid.New(), u.sub[:])
if err != nil {
return err
}
return nil
}
func (u *User) DeleteMailbox(name string) error {
if name == "INBOX" {
return errors.New("cannot delete INBOX")
}
_, err := Database.DB.Exec("DELETE FROM mailboxes WHERE mailbox = $1", name)
if err != nil {
return err
}
return nil
}
func (u *User) RenameMailbox(existingName, newName string) error {
if existingName != "INBOX" {
_, err := Database.DB.Exec("UPDATE mailboxes SET mailbox = $1 WHERE mailbox = $2", newName, existingName)
if err != nil {
return err
}
} else {
// INBOX is a special case, we need to create a new mailbox and copy the contents
err := u.CreateMailbox(newName)
if err != nil {
return err
}
inbox, err := u.GetRawMailbox(newName)
if err != nil {
return err
}
set := new(imap.SeqSet)
set.AddRange(1, 4294967295) // uint32 maximum value, essentially means all messages
err = inbox.CopyMessages(true, set, newName)
if err != nil {
return err
}
err = inbox.Expunge()
if err != nil {
return err
}
}
return nil
}
func (u *User) Logout() error {
for msg := range u.openMessages {
err := msg.Close()
if err != nil {
return err
}
}
return nil
}