Expirementing with building everthing from scratch.
1st steps
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
smtp "github.com/emersion/go-smtp"
|
||||
)
|
||||
|
||||
func startSMTPServer() {
|
||||
keyPath := flag.Arg(1)
|
||||
if keyPath == "" {
|
||||
log.Println("No argument given for key files. smtp signing off...")
|
||||
quitChan <- "smtp arg"
|
||||
return
|
||||
}
|
||||
tlsCert, err := tls.LoadX509KeyPair(keyPath+"/fullchain.pem", keyPath+"/key.pem")
|
||||
if err != nil {
|
||||
log.Println("Error while loading tls certificate:", err)
|
||||
quitChan <- "smtp err"
|
||||
return
|
||||
}
|
||||
cfg := &tls.Config{Certificates: []tls.Certificate{tlsCert}}
|
||||
serv := smtp.NewServer(&SMTPBackend{
|
||||
tlsConfig: cfg,
|
||||
})
|
||||
serv.Network = "tcp"
|
||||
serv.Addr = ":587"
|
||||
serv.TLSConfig = cfg
|
||||
serv.Domain = "darkstorm.tech"
|
||||
serv.WriteTimeout = 10 * time.Second
|
||||
serv.ReadTimeout = 10 * time.Second
|
||||
serv.MaxMessageBytes = 1024 * 1024
|
||||
serv.AllowInsecureAuth = true
|
||||
serv.MaxRecipients = 2
|
||||
err = serv.ListenAndServeTLS()
|
||||
log.Println("Error while serving smtp:", err)
|
||||
quitChan <- "smtp err"
|
||||
}
|
||||
|
||||
type SMTPBackend struct {
|
||||
tlsConfig *tls.Config
|
||||
}
|
||||
|
||||
func (b *SMTPBackend) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
||||
return NewSession(b.tlsConfig, c.Server().Addr)
|
||||
}
|
||||
|
||||
type SMTPSession struct {
|
||||
tlsConfig *tls.Config
|
||||
client *smtp.Client
|
||||
addr string
|
||||
}
|
||||
|
||||
func NewSession(tlsConfig *tls.Config, addr string) (*SMTPSession, error) {
|
||||
client, err := smtp.DialTLS(addr, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SMTPSession{
|
||||
tlsConfig: tlsConfig,
|
||||
client: client,
|
||||
addr: addr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SMTPSession) Reset() {
|
||||
var err error
|
||||
s.client, err = smtp.DialTLS(s.addr, s.tlsConfig)
|
||||
if err != nil {
|
||||
log.Println("Error while resetting smtp session:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SMTPSession) Logout() error {
|
||||
return s.client.Quit()
|
||||
}
|
||||
|
||||
func (s *SMTPSession) AuthPlain(username, password string) error {
|
||||
//TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SMTPSession) Mail(from string, opts *smtp.MailOptions) error {
|
||||
return s.client.Mail(from, opts)
|
||||
}
|
||||
|
||||
func (s *SMTPSession) Rcpt(to string, opts *smtp.RcptOptions) error {
|
||||
return s.client.Rcpt(to, opts)
|
||||
}
|
||||
|
||||
func (s *SMTPSession) Data(r io.Reader) error {
|
||||
wrt, err := s.client.Data()
|
||||
if err != nil {
|
||||
log.Println("Error while writing smtp data:", err)
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(wrt, r)
|
||||
if err != nil {
|
||||
log.Println("Error while writing smtp data:", err)
|
||||
return err
|
||||
}
|
||||
wrt.Close()
|
||||
return nil
|
||||
}
|
||||
@@ -1,32 +1,3 @@
|
||||
module github.com/CalebQ42/darkstorm-server
|
||||
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/1lann/udp-forward v0.0.0-20191015034046-6b774a53ea39
|
||||
github.com/CalebQ42/bbConvert v1.0.0
|
||||
github.com/CalebQ42/cdr-backend v0.1.1
|
||||
github.com/CalebQ42/stupid-backend/v2 v2.0.5
|
||||
github.com/CalebQ42/swassistant-backend v0.2.1
|
||||
go.mongodb.org/mongo-driver v1.15.0
|
||||
)
|
||||
|
||||
require github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||
|
||||
require (
|
||||
github.com/emersion/go-smtp v0.21.1
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/pascaldekloe/jwt v1.12.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
go 1.22.3
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
github.com/1lann/udp-forward v0.0.0-20191015034046-6b774a53ea39 h1:wAEqazqaAqb7wwijTl14KruBl7cvYytD3SkhXT9v5zs=
|
||||
github.com/1lann/udp-forward v0.0.0-20191015034046-6b774a53ea39/go.mod h1:zK6NTEHRcxPf9N4gcm0WXvE8RpsJfg/a8hMSW6dAQ0c=
|
||||
github.com/CalebQ42/bbConvert v1.0.0 h1:2WSAxVKhCCMReuU30r3ehLtL6m9aH8sY3wugp9yUdzg=
|
||||
github.com/CalebQ42/bbConvert v1.0.0/go.mod h1:QJevnlhzUdL3EJB5Lgqoi7rdgtzt/UEamn/QGNoVgkM=
|
||||
github.com/CalebQ42/cdr-backend v0.1.0 h1:9245aooAyLxAFO5gfXPgpqOHaYr6NAkMI75v2IlPOVA=
|
||||
github.com/CalebQ42/cdr-backend v0.1.0/go.mod h1:N7A+ia+4GDsDMZ3gb5IRZ6CY07gdFfJECtR9csKh5nI=
|
||||
github.com/CalebQ42/cdr-backend v0.1.1 h1:OwSVMODCPYMw3HpYTxqCAq9L1k0flLuPb5ICNv8qAn8=
|
||||
github.com/CalebQ42/cdr-backend v0.1.1/go.mod h1:A0YjZk5xKAFXBNPdJ3HhsUgH37kY8Cxjt6isSU0o+Ok=
|
||||
github.com/CalebQ42/stupid-backend/v2 v2.0.4 h1:ph75UDj5JevTiGyJbKgZsH3xyZZAGmXqfwSR6gLWoYQ=
|
||||
github.com/CalebQ42/stupid-backend/v2 v2.0.4/go.mod h1:skBYIF77NzxYcqZ34V1eSD2/MIZCAGyyINWIkCBrpx8=
|
||||
github.com/CalebQ42/stupid-backend/v2 v2.0.5 h1:l6lCzzAF0SCkGFLUiLMfWfBOP41uB/8Y3L50GuH2Npg=
|
||||
github.com/CalebQ42/stupid-backend/v2 v2.0.5/go.mod h1:skBYIF77NzxYcqZ34V1eSD2/MIZCAGyyINWIkCBrpx8=
|
||||
github.com/CalebQ42/swassistant-backend v0.2.0 h1:pXUG7+uHP5/lHaqqD6Hc64hOjfPzCGO8TkOpvtDB238=
|
||||
github.com/CalebQ42/swassistant-backend v0.2.0/go.mod h1:m67UAzh552+puEc0LngTHzOL3b/Y2B19NzbaVdVeabI=
|
||||
github.com/CalebQ42/swassistant-backend v0.2.1 h1:DqBx1pvPgMOE7LbzxvSoasH83FDgGLVv8JUhvA8CAZ0=
|
||||
github.com/CalebQ42/swassistant-backend v0.2.1/go.mod h1:WY+3UvzBcTUoZMtYCVhNWfFW/Cx3lBActCJfk+EUD0s=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4=
|
||||
github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-smtp v0.21.1 h1:VQeZSZAKk8ueYii1yR5Zalmy7jI287eWDUqSaJ68vRM=
|
||||
github.com/emersion/go-smtp v0.21.1/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
|
||||
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8=
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/pascaldekloe/jwt v1.12.0 h1:imQSkPOtAIBAXoKKjL9ZVJuF/rVqJ+ntiLGpLyeqMUQ=
|
||||
github.com/pascaldekloe/jwt v1.12.0/go.mod h1:LiIl7EwaglmH1hWThd/AmydNCnHf/mmfluBlNqHbk8U=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
|
||||
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# Darkstorm Backend
|
||||
|
||||
This is a purposefully "simple" application backend made specifically for _my_ apps. It's purpose is to collect minimal (only what's absolutely necessary) amounts of data while still fulfilling all my needs. I've found that other, off the shelf options such as Firebase are a bit heavy on the data collection. Plus I like to make things :P.
|
||||
|
||||
## Standard Header
|
||||
|
||||
Any request might or might not need these values. These values can be authenticated via the `TODO` function.
|
||||
|
||||
```json
|
||||
{
|
||||
X-API-Key: "{API Key}",
|
||||
Authorization: "Bearer {JWT Token}"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Response
|
||||
|
||||
If an error status code is returned then the body will be as follows.
|
||||
|
||||
```json
|
||||
{
|
||||
errorCode: "Error value for internal use",
|
||||
errorMsg: "User error message", //This message is meant to be displayed to the user. May be empty.
|
||||
}
|
||||
```
|
||||
|
||||
## Users
|
||||
|
||||
> TODO: Add the ability to create users and log-in through third-parties (such as Google).
|
||||
|
||||
All requsests pertaining to users requires the `X-API-Key` header.
|
||||
|
||||
### Create User
|
||||
|
||||
> TODO: Email user to confirm.
|
||||
> TODO: Screen username for offensive words and phrases.
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
email: "Email",
|
||||
}
|
||||
```
|
||||
|
||||
Return:
|
||||
|
||||
```json
|
||||
{
|
||||
username: "Username",
|
||||
token: "JWT Token"
|
||||
}
|
||||
```
|
||||
|
||||
If returned status is 401, the errorCode will be one of the following:
|
||||
|
||||
* username
|
||||
* Username is already taken
|
||||
* password
|
||||
* Password does not follow rules
|
||||
* email
|
||||
* Email is already linked to an account
|
||||
* disallowed
|
||||
* Username contains words/phases that are not allowed
|
||||
|
||||
### Login
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
}
|
||||
```
|
||||
|
||||
Return:
|
||||
|
||||
```json
|
||||
{
|
||||
token: "JWT Token",
|
||||
timeout: 0,
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
package darkstorm
|
||||
|
||||
type App interface{}
|
||||
@@ -0,0 +1,7 @@
|
||||
package darkstorm
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Backend struct {
|
||||
http.ServeMux
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
package darkstormtech
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/CalebQ42/bbConvert"
|
||||
"github.com/CalebQ42/stupid-backend/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type DarkstormTech struct {
|
||||
stupid.UnKeyedApp
|
||||
bb *bbConvert.HTMLConverter
|
||||
DB *mongo.Database
|
||||
filesFolder string
|
||||
}
|
||||
|
||||
func NewDarkstormTech(c *mongo.Client, filesFolder string) *DarkstormTech {
|
||||
bb := &bbConvert.HTMLConverter{}
|
||||
bb.ImplementDefaults()
|
||||
return &DarkstormTech{
|
||||
bb: bb,
|
||||
DB: c.Database("darkstormtech"),
|
||||
filesFolder: filesFolder,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) AlternateName() string {
|
||||
return "page"
|
||||
}
|
||||
|
||||
type pageOut struct {
|
||||
Content string `json:"content"`
|
||||
Title string `json:"title"`
|
||||
Favicon string `json:"favicon"`
|
||||
}
|
||||
|
||||
func notFoundPage() pageOut {
|
||||
return pageOut{
|
||||
Content: "404 Page Not Found 😥",
|
||||
Title: "Darkstorm.Tech",
|
||||
Favicon: "https://darkstorm.tech/favicon.png",
|
||||
}
|
||||
}
|
||||
|
||||
func pageWith(content string, title string) pageOut {
|
||||
if title == "" {
|
||||
title = "Darkstorm.Tech"
|
||||
}
|
||||
return pageOut{
|
||||
Content: content,
|
||||
Title: title,
|
||||
Favicon: "https://darkstorm.tech/favicon.png",
|
||||
}
|
||||
}
|
||||
|
||||
func (p pageOut) json() []byte {
|
||||
out, _ := json.Marshal(p)
|
||||
return out
|
||||
}
|
||||
|
||||
func (p *pageOut) addDefaults() {
|
||||
if p.Title == "" {
|
||||
p.Title = "Darkstorm.Tech"
|
||||
}
|
||||
if p.Favicon == "" {
|
||||
p.Favicon = "https://darkstorm.tech/favicon.png"
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) HandleReqest(req *stupid.Request) bool {
|
||||
if req.Path[0] != "page" {
|
||||
return false
|
||||
}
|
||||
if len(req.Path) == 1 {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
switch req.Path[1] {
|
||||
case "blog":
|
||||
return d.handleBlog(req)
|
||||
case "files":
|
||||
return d.handleFiles(req)
|
||||
case "portfolio":
|
||||
return d.handlePortfolio(req)
|
||||
case "default":
|
||||
b, err := d.getBlog(req)
|
||||
if err == mongo.ErrNoDocuments {
|
||||
req.Resp.Write(notFoundPage().json())
|
||||
req.Resp.WriteHeader(http.StatusNotFound)
|
||||
return true
|
||||
} else if err != nil {
|
||||
log.Println("Error while getting blog:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
out := pageOut{
|
||||
Content: d.bb.Convert(b.Content),
|
||||
}
|
||||
(&out).addDefaults()
|
||||
_, err = req.Resp.Write(out.json())
|
||||
if err != nil {
|
||||
log.Println("Error while writing response:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return true
|
||||
}
|
||||
res := d.DB.Collection("pages").FindOne(context.TODO(), bson.M{"_id": strings.Join(req.Path[1:], "/")}, options.FindOne().SetProjection(bson.M{"_id": 0}))
|
||||
if res.Err() == mongo.ErrNoDocuments {
|
||||
req.Resp.Write(notFoundPage().json())
|
||||
req.Resp.WriteHeader(http.StatusNotFound)
|
||||
return true
|
||||
} else if res.Err() != nil {
|
||||
log.Println("Error while getting page:", res.Err())
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
var pag pageOut
|
||||
err := res.Decode(&pag)
|
||||
if err != nil {
|
||||
log.Println("Error while decoding page:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
pag.Content = d.bb.Convert(pag.Content)
|
||||
(&pag).addDefaults()
|
||||
_, err = req.Resp.Write(pag.json())
|
||||
if err != nil {
|
||||
log.Println("Error while writing response:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type blog struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
Title string `bson:"title" json:"title"`
|
||||
Content string `bson:"content" json:"content"`
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) getBlog(req *stupid.Request) (*blog, error) {
|
||||
var res *mongo.SingleResult
|
||||
if len(req.Path) == 2 {
|
||||
res = d.DB.Collection("blog").FindOne(context.TODO(), bson.M{}, options.FindOne().SetSort(bson.M{"_id": -1}))
|
||||
} else {
|
||||
res = d.DB.Collection("blog").FindOne(context.TODO(), bson.M{"_id": req.Path[2]})
|
||||
}
|
||||
if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
}
|
||||
var b blog
|
||||
err := res.Decode(&b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) handleBlog(req *stupid.Request) bool {
|
||||
if req.Method == http.MethodPost {
|
||||
return d.addBlog(req)
|
||||
} else if req.Method != http.MethodGet {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
b, err := d.getBlog(req)
|
||||
if err == mongo.ErrNoDocuments {
|
||||
req.Resp.Write(notFoundPage().json())
|
||||
req.Resp.WriteHeader(http.StatusNotFound)
|
||||
return true
|
||||
} else if err != nil {
|
||||
log.Println("Error while getting blog:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
out := pageOut{
|
||||
Content: d.bb.Convert(b.Content),
|
||||
Title: b.Title,
|
||||
}
|
||||
(&out).addDefaults()
|
||||
_, err = req.Resp.Write(out.json())
|
||||
if err != nil {
|
||||
log.Println("Error while writing response:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) addBlog(req *stupid.Request) bool {
|
||||
if req.User == nil || req.User.Role != "admin" {
|
||||
req.Resp.WriteHeader(http.StatusUnauthorized)
|
||||
return true
|
||||
}
|
||||
if req.Body == nil {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
bod, err := io.ReadAll(req.Body)
|
||||
req.Body.Close()
|
||||
if err != nil {
|
||||
log.Println("Error while reading body:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
if len(bod) == 0 {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
var b blog
|
||||
err = json.Unmarshal(bod, &b)
|
||||
if err != nil {
|
||||
log.Println("Error while unmarshalling body:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
b.ID = strconv.Itoa(int(time.Now().Unix()))
|
||||
_, err = d.DB.Collection("blog").InsertOne(context.TODO(), b)
|
||||
if err != nil {
|
||||
log.Println("Error while inserting blog:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) handleFiles(req *stupid.Request) bool {
|
||||
if req.Method != http.MethodGet {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
foldPath := ""
|
||||
if len(req.Path) > 1 {
|
||||
foldPath = filepath.Join(req.Path[2:]...)
|
||||
}
|
||||
fils, err := os.ReadDir(filepath.Join(d.filesFolder, foldPath))
|
||||
if err != nil {
|
||||
log.Println("Error while getting files:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
out := ""
|
||||
var inf fs.FileInfo
|
||||
for _, f := range fils {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
inf, err = f.Info()
|
||||
if err != nil {
|
||||
log.Println("Error while getting FileInfo for", f.Name(), err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
out += "<p><a href='https://darkstorm.tech/files/" + f.Name() + "'>" + f.Name() + "</a> " + inf.ModTime().Round(time.Minute).String() + "</p>\n"
|
||||
}
|
||||
_, err = req.Resp.Write(pageWith(out, "Files").json())
|
||||
if err != nil {
|
||||
log.Println("Error while writing output:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type project struct {
|
||||
ID string `bson:"_id"`
|
||||
Repository string
|
||||
Description string
|
||||
Language []struct {
|
||||
Language string
|
||||
Dates string
|
||||
}
|
||||
}
|
||||
|
||||
func selectedString(selected bool) string {
|
||||
if !selected {
|
||||
return ""
|
||||
}
|
||||
return " selected"
|
||||
}
|
||||
|
||||
func (d *DarkstormTech) handlePortfolio(req *stupid.Request) bool {
|
||||
if req.Method != http.MethodGet {
|
||||
req.Resp.WriteHeader(http.StatusBadRequest)
|
||||
return true
|
||||
}
|
||||
filter := bson.M{}
|
||||
lang := ""
|
||||
if l, ok := req.Query["lang"]; ok && len(l) == 1 && l[0] != "" {
|
||||
lang = l[0]
|
||||
filter = bson.M{"language.language": l[0]}
|
||||
}
|
||||
projects := make([]project, 0)
|
||||
res, err := d.DB.Collection("projects").Find(context.TODO(), filter)
|
||||
if err != nil {
|
||||
log.Println("Error while getting projects:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
err = res.All(context.TODO(), &projects)
|
||||
if err != nil {
|
||||
log.Println("Error while decoding projects:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
return true
|
||||
}
|
||||
out := "<p>Language Filter: <select name='langSelect' id='langSelect'>"
|
||||
out += "<option value=''" + selectedString(lang == "") + ">All</option>"
|
||||
out += "<option value='Go'" + selectedString(lang == "Go") + ">Go</option>"
|
||||
out += "<option value='Dart'" + selectedString(lang == "Dart") + ">Dart (Flutter)</option>"
|
||||
out += "<option value='Java'" + selectedString(lang == "Java") + ">Java</option>"
|
||||
out += "</select></p>"
|
||||
for _, p := range projects {
|
||||
out += "<h1 style='margin-bottom:10px'>" + p.ID + "</h1>"
|
||||
out += "<p><a href='" + p.Repository + "'>" + p.Repository + "</a></p>"
|
||||
for _, l := range p.Language {
|
||||
lang := l.Language
|
||||
if lang == "Dart" {
|
||||
lang = "Dart (Flutter)"
|
||||
}
|
||||
out += "<p><b>" + lang + "</b>: " + l.Dates + "</p>"
|
||||
}
|
||||
out += "<p>" + p.Description + "</p>"
|
||||
}
|
||||
_, err = req.Resp.Write(pageWith(out, "Portfolio").json())
|
||||
if err != nil {
|
||||
log.Println("Error while writing output:", err)
|
||||
req.Resp.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package flexmls
|
||||
|
||||
import (
|
||||
"github.com/CalebQ42/stupid-backend/v2/defaultapp"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
type FlexMLS struct {
|
||||
*defaultapp.App
|
||||
}
|
||||
|
||||
func NewBackend(client *mongo.Client) *FlexMLS {
|
||||
return &FlexMLS{defaultapp.NewDefaultApp(client.Database("flexmls"))}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
forward "github.com/1lann/udp-forward"
|
||||
)
|
||||
|
||||
type link struct {
|
||||
addr string
|
||||
linkType string
|
||||
}
|
||||
|
||||
func (l link) isTCP() bool {
|
||||
return strings.HasPrefix(l.linkType, "tcp") || strings.HasPrefix(l.linkType, "unix")
|
||||
}
|
||||
|
||||
func (l link) isUDP() bool {
|
||||
return strings.HasPrefix(l.linkType, "udp")
|
||||
}
|
||||
|
||||
func linker() {
|
||||
links, err := parseConf()
|
||||
if err != nil {
|
||||
log.Println("Error while trying to parse config file:", err, "tcp linker signing off")
|
||||
quitChan <- "tcp conf"
|
||||
return
|
||||
} else if links == nil {
|
||||
log.Println("No values in config file or file not present (/etc/darkstorm-server.conf). tcp linker signing off")
|
||||
quitChan <- "tcp conf"
|
||||
return
|
||||
}
|
||||
fails := make(map[int]int) //logs how many fails per 5 seconds
|
||||
failChan := make(chan int, 20)
|
||||
open := make(map[int]bool)
|
||||
for port, addr := range links {
|
||||
open[port] = true
|
||||
go createLink(port, addr, failChan)
|
||||
}
|
||||
failWaiting:
|
||||
for portFail := <-failChan; ; portFail = <-failChan {
|
||||
if fails[portFail] == 0 {
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
fails[portFail] = 0
|
||||
}()
|
||||
} else if fails[portFail] == 4 {
|
||||
log.Println("Port", portFail, "has failed 5 time is as many seconds. Not restarting port...")
|
||||
open[portFail] = false
|
||||
for _, b := range open {
|
||||
if b {
|
||||
continue failWaiting
|
||||
}
|
||||
}
|
||||
log.Println("All ports dead. Attempting restart...")
|
||||
quitChan <- "tcp err"
|
||||
return
|
||||
}
|
||||
fails[portFail]++
|
||||
log.Println("Restarting linking for port", portFail)
|
||||
go createLink(portFail, links[portFail], failChan)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func createLink(port int, l link, failChan chan int) {
|
||||
log.Println("Linking", port, "to", l.addr, "with type", l.linkType)
|
||||
if l.isUDP() {
|
||||
_, err := forward.Forward(":"+strconv.Itoa(port), l.addr, forward.DefaultTimeout)
|
||||
if err != nil {
|
||||
log.Println("Error with udp forwarder on port", port, ":", err)
|
||||
failChan <- port
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
var tcpListen net.Listener
|
||||
var con net.Conn
|
||||
var err error
|
||||
if l.isTCP() {
|
||||
tcpListen, err = net.Listen(l.linkType, ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
log.Println("Error while trying to listen to port", port, ":", err)
|
||||
failChan <- port
|
||||
return
|
||||
}
|
||||
defer tcpListen.Close()
|
||||
}
|
||||
for {
|
||||
con, err = tcpListen.Accept()
|
||||
if err != nil {
|
||||
log.Println("Error while trying to accept connection to port ", port, ":", err)
|
||||
failChan <- port
|
||||
return
|
||||
}
|
||||
err = copyConn(con, l)
|
||||
if err != nil {
|
||||
log.Println("Error while trying copy data from port", port, "to address", l.addr, ":", err)
|
||||
failChan <- port
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseConf() (links map[int]link, err error) {
|
||||
conf, err := os.Open("/etc/darkstorm-server.conf")
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lineNum := 0
|
||||
links = make(map[int]link)
|
||||
rdr := bufio.NewReader(conf)
|
||||
multilineComment := false
|
||||
var line string
|
||||
for {
|
||||
if line == "" {
|
||||
lineNum++
|
||||
line, err = rdr.ReadString('\n')
|
||||
if err != nil && line == "" {
|
||||
break
|
||||
} else if line == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
startCom, endCom := strings.Index(line, "/*"), strings.Index(line, "*/")
|
||||
if multilineComment {
|
||||
if endCom != -1 {
|
||||
line = line[endCom:]
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if startCom != -1 {
|
||||
if endCom != -1 {
|
||||
line = line[:startCom] + line[endCom:]
|
||||
continue
|
||||
}
|
||||
line = line[:startCom]
|
||||
multilineComment = true
|
||||
}
|
||||
if strings.Contains(line, "//") {
|
||||
line = line[:strings.Index(line, "//")]
|
||||
}
|
||||
line = strings.ReplaceAll(line, "\t", " ")
|
||||
for strings.Contains(line, " ") {
|
||||
line = strings.Replace(line, " ", " ", -1)
|
||||
}
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
split := strings.Split(line, " ")
|
||||
if len(split) < 2 || len(split) > 3 {
|
||||
return nil, errors.New("invalid line #" + strconv.Itoa(lineNum))
|
||||
}
|
||||
var l link
|
||||
if len(split) == 3 {
|
||||
l.linkType = split[0]
|
||||
split = split[1:]
|
||||
} else {
|
||||
l.linkType = "tcp"
|
||||
}
|
||||
var i int
|
||||
i, err = strconv.Atoi(split[0])
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid line #" + strconv.Itoa(lineNum))
|
||||
}
|
||||
l.addr = split[1]
|
||||
links[i] = l
|
||||
line = ""
|
||||
}
|
||||
err = nil
|
||||
if len(links) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func copyConn(src net.Conn, l link) error {
|
||||
dst, err := net.Dial(l.linkType, l.addr)
|
||||
if err != nil {
|
||||
log.Println("Error while dialing", l.addr)
|
||||
return err
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer src.Close()
|
||||
defer dst.Close()
|
||||
io.Copy(dst, src)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer src.Close()
|
||||
defer dst.Close()
|
||||
io.Copy(src, dst)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
<-done
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
@@ -1,48 +1,4 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
var quitChan chan string = make(chan string)
|
||||
|
||||
func main() {
|
||||
mongoStr := flag.String("mongo", "", "MongoDB connection string for APIs")
|
||||
flag.Parse()
|
||||
go linker()
|
||||
go webserver(*mongoStr)
|
||||
go startSMTPServer()
|
||||
for failure := <-quitChan; ; failure = <-quitChan {
|
||||
switch failure {
|
||||
case "tcp conf":
|
||||
continue
|
||||
case "tcp err":
|
||||
go tcpLinkerRestart()
|
||||
case "web arg":
|
||||
continue
|
||||
case "web err":
|
||||
go websiteRestart(*mongoStr)
|
||||
case "smtp arg":
|
||||
continue
|
||||
case "smtp err":
|
||||
//TODO: restart smtp server
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tcpLinkerRestart() {
|
||||
log.Println("TCP linker failed. Restarting in 5 seconds...")
|
||||
time.Sleep(5 * time.Second)
|
||||
log.Println("Restarting tcp linker")
|
||||
linker()
|
||||
}
|
||||
|
||||
func websiteRestart(mongoStr string) {
|
||||
log.Println("Website failed. Restarting in 5 seconds...")
|
||||
time.Sleep(5 * time.Second)
|
||||
log.Println("Restarting website")
|
||||
webserver(mongoStr)
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/CalebQ42/cdr-backend"
|
||||
"github.com/CalebQ42/darkstorm-server/internal/darkstormtech"
|
||||
"github.com/CalebQ42/darkstorm-server/internal/flexmls"
|
||||
"github.com/CalebQ42/stupid-backend/v2"
|
||||
"github.com/CalebQ42/stupid-backend/v2/db"
|
||||
swassistantbackend "github.com/CalebQ42/swassistant-backend"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func setupStupid(keyPath, mongoStr string) error {
|
||||
tlsCert, err := tls.LoadX509KeyPair(keyPath+"/fullchain.pem", keyPath+"/key.pem")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := mongo.Connect(
|
||||
context.TODO(),
|
||||
options.Client().ApplyURI(mongoStr),
|
||||
options.Client().SetTLSConfig(&tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
}),
|
||||
)
|
||||
if err != nil {
|
||||
log.Println("Issues connecting to mongo:", err)
|
||||
return err
|
||||
}
|
||||
stupid := stupid.NewStupidBackend(db.NewMongoTable(client.Database("stupid").Collection("keys")), map[string]any{
|
||||
"swassistant": swassistantbackend.NewSWBackend(client),
|
||||
"cdr": cdr.NewBackend(client),
|
||||
"darkstormtech": darkstormtech.NewDarkstormTech(client, filepath.Join(flag.Arg(0), "files")),
|
||||
"flexmls": flexmls.NewBackend(client),
|
||||
}, "https://darkstorm.tech")
|
||||
users := true
|
||||
var pub, priv []byte
|
||||
stupidPubFil, err := os.Open(keyPath + "/stupid-pub.key")
|
||||
if err != nil {
|
||||
log.Println("Disabling API users:", err)
|
||||
users = false
|
||||
} else {
|
||||
pub, err = io.ReadAll(stupidPubFil)
|
||||
if err != nil {
|
||||
log.Println("Disabling API users:", err)
|
||||
users = false
|
||||
}
|
||||
}
|
||||
stupidPrivFil, err := os.Open(keyPath + "/stupid-pub.key")
|
||||
if err != nil {
|
||||
log.Println("Disabling API users:", err)
|
||||
users = false
|
||||
} else {
|
||||
priv, err = io.ReadAll(stupidPrivFil)
|
||||
if err != nil {
|
||||
log.Println("Disabling API users:", err)
|
||||
users = false
|
||||
}
|
||||
}
|
||||
if users {
|
||||
stupid.EnableUserAuth(db.NewMongoTable(client.Database("stupid").Collection("keys")), pub, priv)
|
||||
}
|
||||
http.Handle("api.darkstorm.tech/", stupid)
|
||||
return nil
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func webserver(mongoStr string) {
|
||||
path := flag.Arg(0)
|
||||
keyPath := flag.Arg(1)
|
||||
if path == "" {
|
||||
log.Println("No argument given for website file path. website signing off...")
|
||||
quitChan <- "web arg"
|
||||
return
|
||||
} else if keyPath == "" {
|
||||
log.Println("No argument given for key files. website signing off...")
|
||||
quitChan <- "web arg"
|
||||
return
|
||||
}
|
||||
var err error
|
||||
if mongoStr != "" {
|
||||
err = setupStupid(keyPath, mongoStr)
|
||||
if err != nil {
|
||||
quitChan <- "web err"
|
||||
return
|
||||
}
|
||||
}
|
||||
url, err := url.Parse("https://localhost:30000")
|
||||
if err != nil {
|
||||
log.Println("Can't parse foundry url:", err)
|
||||
quitChan <- "web err"
|
||||
return
|
||||
}
|
||||
// http.Handle("/", http.FileServer(http.Dir(path)))
|
||||
mainHandle := &fileOrIndexHandler{
|
||||
baseFolder: path,
|
||||
appFolders: []string{
|
||||
"SWAssistant",
|
||||
"CDR",
|
||||
},
|
||||
}
|
||||
http.Handle("/", mainHandle)
|
||||
// http.Handle("/SWAssistant/", swaHandler{})
|
||||
// http.Handle("/CDR/", cdrHandler{})
|
||||
http.Handle("rpg.darkstorm.tech/", httputil.NewSingleHostReverseProxy(url))
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
err = http.ListenAndServeTLS(":443", keyPath+"/fullchain.pem", keyPath+"/key.pem", nil)
|
||||
log.Println("Error while serving website:", err)
|
||||
quitChan <- "web err"
|
||||
}
|
||||
|
||||
type fileOrIndexHandler struct {
|
||||
baseFolder string
|
||||
appFolders []string
|
||||
}
|
||||
|
||||
func (f *fileOrIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
reqPath := strings.TrimPrefix(path.Clean(r.URL.Path), "/")
|
||||
if reqPath == "" || reqPath == "index.html" {
|
||||
http.ServeFile(w, r, path.Join(f.baseFolder, "index.html"))
|
||||
return
|
||||
}
|
||||
reqPath = path.Join(f.baseFolder, reqPath)
|
||||
if fil, err := os.Open(reqPath); err == nil {
|
||||
inf, _ := fil.Stat()
|
||||
if !inf.IsDir() {
|
||||
http.ServeFile(w, r, reqPath)
|
||||
return
|
||||
} else if _, err = os.Open(path.Join(reqPath, "index.html")); err == nil {
|
||||
http.ServeFile(w, r, path.Join(reqPath, "index.html"))
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, a := range f.appFolders {
|
||||
if strings.HasPrefix(reqPath, path.Join(f.baseFolder, a)) {
|
||||
http.ServeFile(w, r, path.Join(f.baseFolder, a, "index.html"))
|
||||
return
|
||||
}
|
||||
}
|
||||
http.ServeFile(w, r, path.Join(f.baseFolder, "index.html"))
|
||||
}
|
||||
Reference in New Issue
Block a user