package server import ( "crypto/rand" "encoding/hex" "net/http" "sync" "time" "yoresee_dropbox/internal/store" "yoresee_dropbox/web" ) type Server struct { store *store.Store accessToken string sessions map[string]int64 shareSessions map[string]string loginAttempts map[string]int loginLockout map[string]time.Time shareAttempts map[string]int shareLockout map[string]time.Time mu sync.Mutex workspace string } func New(store *store.Store, accessToken string, workspace string) *Server { return &Server{ store: store, accessToken: accessToken, sessions: make(map[string]int64), shareSessions: make(map[string]string), loginAttempts: make(map[string]int), loginLockout: make(map[string]time.Time), shareAttempts: make(map[string]int), shareLockout: make(map[string]time.Time), workspace: workspace, } } func generateUUID() string { b := make([]byte, 16) rand.Read(b) return hex.EncodeToString(b) } func (s *Server) Handler() http.Handler { mux := http.NewServeMux() mux.HandleFunc("POST /api/login", s.handleLogin) mux.HandleFunc("POST /api/logout", s.requireAuth(s.handleLogout)) mux.HandleFunc("POST /api/upload", s.requireAuth(s.handleUpload)) mux.HandleFunc("GET /api/files", s.requireAuth(s.handleListFiles)) mux.HandleFunc("GET /api/files/{id}/download", s.requireAuth(s.handleDownload)) mux.HandleFunc("DELETE /api/files/{id}", s.requireAuth(s.handleDeleteFile)) mux.HandleFunc("POST /api/files/{id}/share", s.requireAuth(s.handleCreateShare)) mux.HandleFunc("GET /api/shares", s.requireAuth(s.handleListShares)) mux.HandleFunc("DELETE /api/shares/{id}", s.requireAuth(s.handleDeleteShare)) mux.HandleFunc("GET /s/{token}", s.handleShareAccess) mux.HandleFunc("POST /s/{token}", s.handleSharePassword) mux.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { data, _ := web.FS.ReadFile("login.html") w.Write(data) }) mux.HandleFunc("GET /{$}", s.requireAuthPage(func(w http.ResponseWriter, r *http.Request) { data, _ := web.FS.ReadFile("index.html") w.Write(data) })) static := http.FileServerFS(web.FS) mux.Handle("GET /components/", static) mux.Handle("GET /styles/", static) mux.Handle("GET /version.js", static) mux.Handle("GET /alpine.min.js", static) return mux }