lchat/web/wasm/signup.go

130 lines
4.0 KiB
Go

package main
import (
"bytes"
"net/url"
"strings"
"time"
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"syscall/js"
"git.ailur.dev/ailur/jsFetch"
"golang.org/x/crypto/argon2"
)
func main() {
localStorage := js.Global().Get("localStorage")
status := js.Global().Get("document").Call("getElementById", "status")
signupButton := js.Global().Get("document").Call("getElementById", "signup")
username := js.Global().Get("document").Call("getElementById", "username")
password := js.Global().Get("document").Call("getElementById", "password")
inviteCheck := js.Global().Get("document").Call("getElementById", "inviteCheck")
container := js.Global().Get("document").Call("getElementById", "container")
if localStorage.Call("getItem", "server").IsNull() {
localStorage.Call("setItem", "server", "https://chat.ailur.dev:1974")
}
if !localStorage.Call("getItem", "token").IsNull() {
js.Global().Get("location").Set("href", "../")
return
}
query, err := url.ParseQuery(strings.TrimPrefix(js.Global().Get("location").Get("search").String(), "?"))
if err != nil {
inviteCheck.Set("innerText", "Failed to parse query: "+err.Error())
return
}
if !query.Has("invite") || len(query.Get("invite")) != 16 {
inviteCheck.Set("innerText", "Sorry, your invite link is invalid.")
return
} else {
inviteCheck.Get("style").Set("display", "none")
container.Get("style").Set("display", "initial")
}
signupButton.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
username.Set("disabled", true)
password.Set("disabled", true)
signupButton.Set("disabled", true)
status.Set("innerText", "Generating encryption keys...")
hash := argon2.IDKey(
[]byte(password.Get("value").String()),
[]byte(username.Get("value").String()),
32,
19264,
1,
32,
)
status.Set("innerText", "Contacting server...")
jsonBody, err := json.Marshal(map[string]interface{}{
"username": username.Get("value").String(),
"publicKey": base64.StdEncoding.EncodeToString(ed25519.NewKeyFromSeed(hash).Public().(ed25519.PublicKey)),
"invite": query.Get("invite"),
})
if err != nil {
status.Set("innerText", "Failed to encode request: "+err.Error())
username.Set("disabled", false)
password.Set("disabled", false)
signupButton.Set("disabled", false)
return
}
response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/signup", "application/json", bytes.NewReader(jsonBody))
if err != nil {
status.Set("innerText", "Failed to contact server: "+err.Error())
username.Set("disabled", false)
password.Set("disabled", false)
signupButton.Set("disabled", false)
return
}
if response.StatusCode != 200 {
if response.StatusCode == 500 {
status.Set("innerText", "Something went wrong on our end. Please try again later.")
} else {
var body map[string]interface{}
err := json.NewDecoder(response.Body).Decode(&body)
if err != nil {
status.Set("innerText", "Failed to decode response: "+err.Error())
} else {
status.Set("innerText", body["error"].(string))
}
}
username.Set("disabled", false)
password.Set("disabled", false)
signupButton.Set("disabled", false)
return
}
var body map[string]interface{}
err = json.NewDecoder(response.Body).Decode(&body)
if err != nil {
status.Set("innerText", "Failed to decode response: "+err.Error())
username.Set("disabled", false)
password.Set("disabled", false)
signupButton.Set("disabled", false)
return
}
localStorage.Call("setItem", "token", body["token"].(string))
localStorage.Call("setItem", "username", username.Get("value").String())
localStorage.Call("setItem", "userId", body["userId"].(string))
status.Set("innerText", "Welcome, "+username.Get("value").String()+", to LChat!")
time.Sleep(300 * time.Millisecond)
js.Global().Get("location").Set("href", "../")
}()
return nil
}))
select {}
}