From e7caa27a353012e2ac7ce891b54417a01b793ae9 Mon Sep 17 00:00:00 2001 From: Derek Stevens Date: Mon, 10 Jul 2023 22:38:19 -0600 Subject: [PATCH] finish implementing registration invites --- cmd/cmd.go | 2 +- register/register.go | 50 +++++++++++++++++++++++++++++---------- static/style.css | 33 +++++++++++++++++++++++++- templates/register.html | 25 ++++++++++++++++++++ templates/registered.html | 21 ++++++++++++++++ 5 files changed, 117 insertions(+), 14 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 5218677..dd5b8f7 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -13,7 +13,7 @@ func ProcessCmd(args []string, userStore auth.UserStore, crypto register.Symmetr return false } switch args[1] { - case "register": + case "invite": now := time.Now().UnixMicro() strNow := strconv.FormatInt(now, 10) self, err := crypto.Encrypt(strNow) diff --git a/register/register.go b/register/register.go index 026d337..4a4faa5 100644 --- a/register/register.go +++ b/register/register.go @@ -1,31 +1,50 @@ package register import ( - "context" "crypto/aes" "crypto/cipher" "encoding/hex" "html/template" "net/http" + "time" + "strconv" + "fmt" + "hacklab.nilfm.cc/quartzgun/auth" "hacklab.nilfm.cc/quartzgun/renderer" "hacklab.nilfm.cc/quartzgun/router" + "hacklab.nilfm.cc/quartzgun/util" ) -var bytes = []byte{99, 207, 33, 57, 28, 01, 50, 76, 01, 92, 33, 10, 48, 07, 00, 250} - type SymmetricCrypto interface { Encode(b []byte) string Decode(s string) []byte Encrypt(text string) (string, error) Decrypt(text string) (string, error) + IsValid(text string) bool } type SymmetricCrypt struct { Secret string } +var iv []byte = []byte {107, 53, 46, 249, 52, 70, 36, 185, + 168, 139, 144, 249, 242, 2, 125, 183 } + +func (self *SymmetricCrypt) IsValid(cipher string) bool { + stringTimestamp, err := self.Decrypt(cipher) + if err != nil { + return false + } + int64Timestamp, err := strconv.ParseInt(stringTimestamp, 10, 64) + if err != nil { + return false + } + then := time.UnixMicro(int64Timestamp) + return time.Since(then).Minutes() <= 15 +} + func (self *SymmetricCrypt) Encode(b []byte) string { return hex.EncodeToString(b) } @@ -39,12 +58,13 @@ func (self *SymmetricCrypt) Decode(s string) []byte { } func (self *SymmetricCrypt) Encrypt(text string) (string, error) { + fmt.Println(text) block, err := aes.NewCipher([]byte(self.Secret)) if err != nil { return "", err } plainText := []byte(text) - cfb := cipher.NewCFBEncrypter(block, bytes) + cfb := cipher.NewCFBEncrypter(block, iv) cipherText := make([]byte, len(plainText)) cfb.XORKeyStream(cipherText, plainText) return self.Encode(cipherText), nil @@ -56,7 +76,7 @@ func (self *SymmetricCrypt) Decrypt(text string) (string, error) { return "", err } cipherText := self.Decode(text) - cfb := cipher.NewCFBDecrypter(block, bytes) + cfb := cipher.NewCFBDecrypter(block, iv) plainText := make([]byte, len(cipherText)) cfb.XORKeyStream(plainText, cipherText) return string(plainText), nil @@ -64,18 +84,24 @@ func (self *SymmetricCrypt) Decrypt(text string) (string, error) { func WithCrypto(next http.Handler, crypto SymmetricCrypto) http.Handler { handlerFunc := func(w http.ResponseWriter, req *http.Request) { - //urlParams := req.Context().Value("params").(map[string]string) - //cipher := urlParams["cipher"] - + util.AddContextValue(req, "crypto", crypto); next.ServeHTTP(w, req) } return http.HandlerFunc(handlerFunc) } -func WithUserStore(next http.Handler, udb auth.UserStore) http.Handler { +func WithUserStoreAndCrypto(next http.Handler, udb auth.UserStore, crypto SymmetricCrypto) http.Handler { handlerFunc := func(w http.ResponseWriter, req *http.Request) { - *req = *req.WithContext(context.WithValue(req.Context(), "udb", udb)) + urlParams := req.Context().Value("params").(map[string]string) + success := false + cipher := urlParams["cipher"] + username := req.FormValue("username") + password := req.FormValue("password") + if crypto.IsValid(cipher) && len(username) > 0 && len(password) > 0 { + success = udb.AddUser(username, password) == nil + } + util.AddContextValue(req, "success", success); next.ServeHTTP(w, req) } @@ -86,8 +112,8 @@ func CreateRegistrationInterface(udb auth.UserStore, secret string) http.Handler rtr := &router.Router{Fallback: *template.Must(template.ParseFiles("templates/error.html"))} crypto := &SymmetricCrypt{Secret: secret} - rtr.Get(`/(?P.*)`, WithCrypto(renderer.Template("templates/register.html"), crypto)) - rtr.Post(`/(?P.*)`, WithUserStore(WithCrypto(renderer.Template("templates/registered.html"), crypto), udb)) + rtr.Get(`/(?P\S+)`, WithCrypto(renderer.Template("templates/register.html"), crypto)) + rtr.Post(`/(?P\S+)`, WithUserStoreAndCrypto(renderer.Template("templates/registered.html"), udb, crypto)) return http.HandlerFunc(rtr.ServeHTTP) } diff --git a/static/style.css b/static/style.css index a66f294..5cda833 100644 --- a/static/style.css +++ b/static/style.css @@ -142,7 +142,7 @@ pre { } .ui_win a { - color: #1f9b92; + color: var(--main_color); } .ui_win a:hover, ui_win a:active { @@ -197,4 +197,35 @@ nav { .two_btn_list li { display: grid; grid-template-columns: 1fr auto auto; +} + +#registration { + background: var(--bg_color); + color: var(--fg_color); + width: 500px; + max-width: 80vw; + margin: 2em auto; + text-align: center; + padding: 1em; +} + +#registration h1, #registration form { + margin: 1em auto; +} + +#registration label, #registration button { + display: block; + margin: 1em; +} + +#registration button { + margin: 0 auto; +} + +#registration a { + color: var(--main_color); +} + +#registration a:hover { + color: var(--fg_color); } \ No newline at end of file diff --git a/templates/register.html b/templates/register.html index e69de29..b1e3960 100644 --- a/templates/register.html +++ b/templates/register.html @@ -0,0 +1,25 @@ +{{ $cipher := ((.Context).Value "params").cipher }} +{{ $valid := ((.Context).Value "crypto").IsValid $cipher }} + + + + + Felt — Admin Registration + + + + +
+

Felt Admin Registration

+{{ if $valid }} +
+ + + +
+{{ else }} +

The registration token you provided is invalid

+{{end}} +
+ + \ No newline at end of file diff --git a/templates/registered.html b/templates/registered.html index e69de29..37ba3c3 100644 --- a/templates/registered.html +++ b/templates/registered.html @@ -0,0 +1,21 @@ + +{{ $success := ((.Context).Value "success") }} + + + + Felt — Registration Complete + + + + +
+{{ if $success }} +

Registration Complete

+

Success! Let's game!

+{{ else }} +

Error

+

Something went wrong; please try a different username or obtain a new registration code.

+{{end}} +
+ + \ No newline at end of file