kittemail/backend.go

83 lines
1.5 KiB
Go

package main
import (
"crypto/ed25519"
"errors"
"github.com/emersion/go-imap/v2/imapserver"
"github.com/google/uuid"
"sync"
)
// OAuthConfig is the configuration for OAuth.
type OAuthConfig struct {
HostName string
PublicKey ed25519.PublicKey
}
// Server is a server instance.
//
// A server contains a list of users.
type Server struct {
config OAuthConfig
userMutex sync.Mutex
users map[uuid.UUID]*User
}
// New creates a new server.
func New(config OAuthConfig) *Server {
return &Server{
config: config,
users: make(map[uuid.UUID]*User),
}
}
func (s *Server) userRaw(sub uuid.UUID) (*User, error) {
s.userMutex.Lock()
defer s.userMutex.Unlock()
user, ok := s.users[sub]
if !ok {
user = &User{
mailboxes: make(map[string]*Mailbox),
sessions: make(map[*UserSession]struct{}),
server: s,
sub: sub,
}
s.users[sub] = user
_, err := user.mailbox("INBOX")
if err != nil {
if errors.Is(err, ErrNoSuchMailbox) {
err := user.Create("INBOX", nil)
if err != nil {
return nil, err
}
} else {
return nil, err
}
}
}
return user, nil
}
func (s *Server) user(token string) (*User, error) {
sub, err := Authenticate(token, s.config)
if err != nil {
return nil, err
}
return s.userRaw(sub)
}
// NewSession creates a new IMAP session.
func (s *Server) NewSession() imapserver.Session {
return s.newSession()
}
func (s *Server) newSession() *EntryPoint {
return &EntryPoint{
Server: s,
}
}