finish implementing registration invites
This commit is contained in:
parent
b7888158b8
commit
e7caa27a35
5 changed files with 117 additions and 14 deletions
|
@ -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)
|
||||
|
|
|
@ -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<cipher>.*)`, WithCrypto(renderer.Template("templates/register.html"), crypto))
|
||||
rtr.Post(`/(?P<cipher>.*)`, WithUserStore(WithCrypto(renderer.Template("templates/registered.html"), crypto), udb))
|
||||
rtr.Get(`/(?P<cipher>\S+)`, WithCrypto(renderer.Template("templates/register.html"), crypto))
|
||||
rtr.Post(`/(?P<cipher>\S+)`, WithUserStoreAndCrypto(renderer.Template("templates/registered.html"), udb, crypto))
|
||||
|
||||
return http.HandlerFunc(rtr.ServeHTTP)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{{ $cipher := ((.Context).Value "params").cipher }}
|
||||
{{ $valid := ((.Context).Value "crypto").IsValid $cipher }}
|
||||
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Felt — Admin Registration</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link href="/table/style.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="registration">
|
||||
<h1>Felt Admin Registration</h1>
|
||||
{{ if $valid }}
|
||||
<form action="/register/{{ $cipher }}" method="post">
|
||||
<label>username <input id="username" name="username"/></label>
|
||||
<label>password <input id="password" name="password" type="password"/></label>
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
{{ else }}
|
||||
<p class="error">The registration token you provided is invalid</p>
|
||||
{{end}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
{{ $success := ((.Context).Value "success") }}
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Felt — Registration Complete</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link href="/table/style.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="registration">
|
||||
{{ if $success }}
|
||||
<h1>Registration Complete</h1>
|
||||
<p>Success! <a href="/table">Let's game!</a></p>
|
||||
{{ else }}
|
||||
<h1>Error</h1>
|
||||
<p class="error">Something went wrong; please try a different username or obtain a new registration code.</p>
|
||||
{{end}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue