From 11c9ec92422ac3a573ac72560520c572e90bac23 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Mon, 17 Jun 2024 19:25:10 -0500 Subject: [PATCH] Docs and CORS --- internal/backend/darkstorm.go | 25 +++++++++++++++++++++++ internal/backend/embed/robots.txt | 2 ++ internal/blog/main.go | 12 +++++++++++ main.go | 33 +++++++++++++++++++++++-------- 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 internal/backend/embed/robots.txt diff --git a/internal/backend/darkstorm.go b/internal/backend/darkstorm.go index d5e86d8..0a264e8 100644 --- a/internal/backend/darkstorm.go +++ b/internal/backend/darkstorm.go @@ -2,6 +2,7 @@ package backend import ( "crypto/ed25519" + "embed" "encoding/json" "errors" "log" @@ -10,17 +11,23 @@ import ( "time" ) +//go:embed embed/* +var robotEmbed embed.FS + +// A simple backend that handles user authentication, user count, and crash reports. type Backend struct { userTable Table[User] keyTable Table[ApiKey] m *http.ServeMux apps map[string]App managementKeyID string + corsAddr string jwtPriv ed25519.PrivateKey jwtPub ed25519.PublicKey userMutex sync.RWMutex } +// Create a new Backend with the given apps. keyTable must be specified. func NewBackend(keyTable Table[ApiKey], apps ...App) (*Backend, error) { b := &Backend{ keyTable: keyTable, @@ -28,6 +35,7 @@ func NewBackend(keyTable Table[ApiKey], apps ...App) (*Backend, error) { apps: make(map[string]App), userMutex: sync.RWMutex{}, } + b.m.Handle("GET /robots.txt", http.FileServerFS(robotEmbed)) var hasLog, hasCrash bool for i := range apps { _, has := b.apps[apps[i].AppID()] @@ -76,7 +84,21 @@ func (b *Backend) cleanupLoop() { } } +// Enable CORS for with the given cors address +func (b *Backend) AddCorsAddress(corsAddr string) { + b.corsAddr = corsAddr +} + +// http.Handler func (b *Backend) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if b.corsAddr != "" { + w.Header().Set("Access-Control-Allow-Origin", b.corsAddr) + if r.Method == http.MethodOptions { + w.Header().Set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT") + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers") + } + } b.m.ServeHTTP(w, r) } @@ -84,6 +106,7 @@ func getDate(t time.Time) int { return (t.Year() * 10000) + (int(t.Month()) * 100) + t.Day() } +// Enables the use of a management API key for crash and count. func (b *Backend) EnableManagementKey(managementID string) { b.managementKeyID = managementID b.m.HandleFunc("DELETE /{appID}/crash/{crashID}", b.managementDeleteCrash) @@ -91,6 +114,7 @@ func (b *Backend) EnableManagementKey(managementID string) { b.m.HandleFunc("GET /{appID}/count", b.getCount) } +// Enables user creation and authentication. func (b *Backend) AddUserAuth(userTable Table[User], privKey, pubKey []byte) { b.userTable = userTable b.jwtPriv = privKey @@ -113,6 +137,7 @@ type retError struct { ErrorMsg string `json:"errorMsg"` } +// Return an error response with the given status code, code, and message. func ReturnError(w http.ResponseWriter, status int, code, msg string) { w.WriteHeader(status) json.NewEncoder(w).Encode(retError{ diff --git a/internal/backend/embed/robots.txt b/internal/backend/embed/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/internal/backend/embed/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/internal/blog/main.go b/internal/blog/main.go index 68b5494..75556dc 100644 --- a/internal/blog/main.go +++ b/internal/blog/main.go @@ -28,3 +28,15 @@ func NewBlogApp(b *backend.Backend, db *mongo.Database, mux *http.ServeMux) *Blo //TODO return out } + +func (b *BlogApp) AppID() string { + return "blog" +} + +func (b *BlogApp) CountTable() backend.CountTable { + return nil +} + +func (b *BlogApp) CrashTable() backend.CrashTable { + return nil +} diff --git a/main.go b/main.go index 660fd99..d0b4abc 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,8 @@ import ( "net/http" "path/filepath" + "github.com/CalebQ42/darkstorm-server/internal/backend" + "github.com/CalebQ42/darkstorm-server/internal/backend/db" "github.com/CalebQ42/darkstorm-server/internal/blog" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -15,6 +17,7 @@ import ( var ( mongoClient *mongo.Client + back *backend.Backend blogApp *blog.BlogApp ) @@ -28,28 +31,42 @@ func main() { if *mongoURL == "" || *webRoot == "" { log.Fatal("SPECIFY MONGO AND WEB-ROOT OR I WILL DIE (Death noises).") } + go func() { + http.ListenAndServe(":80", http.RedirectHandler("https://darkstorm.tech", http.StatusPermanentRedirect)) + }() mux := http.NewServeMux() - mongoClient = setupMongo(*mongoURL) + setupMongo(*mongoURL) setupBackend(mux) setupWebsite(mux, *webRoot) - http.ListenAndServeTLS(":443", filepath.Join(flag.Arg(0), "cert.pem"), filepath.Join(flag.Arg(0), "key.pem"), mux) + serv := &http.Server{ + Addr: ":443", + Handler: mux, + } + err := serv.ListenAndServeTLS(filepath.Join(flag.Arg(0), "cert.pem"), filepath.Join(flag.Arg(0), "key.pem")) + log.Println("webserver closed:", err) } -func setupMongo(uri string) *mongo.Client { +func setupMongo(uri string) { mongoCert, err := tls.LoadX509KeyPair(filepath.Join(flag.Arg(0), "mongo.pem"), filepath.Join(flag.Arg(0)+"key.pem")) if err != nil { log.Fatal("error loading mongo keys:", err) } - client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri).SetTLSConfig(&tls.Config{ + mongoClient, err = mongo.Connect(context.Background(), options.Client().ApplyURI(uri).SetTLSConfig(&tls.Config{ Certificates: []tls.Certificate{mongoCert}, })) if err != nil { log.Fatal("error connecting to mongo:", err) } - return client +} + +func setupBackend(mux *http.ServeMux) { + blogApp = blog.NewBlogApp(back, mongoClient.Database("blog"), mux) + //TODO: SWAssistant and CDR backends + var err error + back, err = backend.NewBackend(db.NewMongoTable[backend.ApiKey](mongoClient.Database("darkstorm").Collection("keys")), blogApp) + if err != nil { + log.Fatal("error setting up backend:", err) + } } func setupWebsite(mux *http.ServeMux, root string) {} - -func setupBackend(mux *http.ServeMux) { -}