83 lines
1.5 KiB
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,
|
|
}
|
|
}
|