login
parent
7777d2782a
commit
fe4e9c4214
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
|
@ -11,6 +12,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
@ -20,13 +22,14 @@ var (
|
||||||
Port int
|
Port int
|
||||||
SessionD string
|
SessionD string
|
||||||
Debug bool
|
Debug bool
|
||||||
Semaphore sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed template.d/login.html
|
//go:embed template.d/login.html
|
||||||
htmlLogin []byte
|
htmlLogin []byte
|
||||||
//go:embed template.d/index.html
|
//go:embed template.d/index.html
|
||||||
htmlIndex []byte
|
htmlIndex []byte
|
||||||
|
//go:embed template.d/chatbot.html
|
||||||
|
htmlChatBot []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -100,30 +103,46 @@ func listenAndServe(ctx context.Context) {
|
||||||
func handle(w http.ResponseWriter, r *http.Request) {
|
func handle(w http.ResponseWriter, r *http.Request) {
|
||||||
cookie, _ := ParseCookie(r)
|
cookie, _ := ParseCookie(r)
|
||||||
if err := _handle(w, r); err != nil {
|
if err := _handle(w, r); err != nil {
|
||||||
log.Printf("%s: %s: %v", cookie.Name, r.URL.Path, err)
|
log.Printf("%s: %s %s: %v", cookie.Name, r.Method, r.URL.Path, err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("%s: %s", cookie.Name, r.URL.Path)
|
log.Printf("%s: %s %s", cookie.Name, r.Method, r.URL.Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _handle(w http.ResponseWriter, r *http.Request) error {
|
func _handle(w http.ResponseWriter, r *http.Request) error {
|
||||||
switch r.URL.Path {
|
first := strings.Split(strings.TrimLeft(r.URL.Path, "/"), "/")[0]
|
||||||
case "/login":
|
switch first {
|
||||||
|
case "login":
|
||||||
return handleLogin(w, r)
|
return handleLogin(w, r)
|
||||||
case "/":
|
|
||||||
return handleUI(w, r)
|
|
||||||
default:
|
default:
|
||||||
http.NotFound(w, r)
|
return handleLoggedIn(w, r)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleLogin(w http.ResponseWriter, r *http.Request) error {
|
func handleLogin(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
w.Write(htmlLogin)
|
w.Write(htmlLogin)
|
||||||
return nil
|
return nil
|
||||||
|
case http.MethodPost:
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cookie, err := ParseCookie(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cookie.Serialize(w)
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return errors.New("not found")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUI(w http.ResponseWriter, r *http.Request) error {
|
func handleLoggedIn(w http.ResponseWriter, r *http.Request) error {
|
||||||
cookie, err := ParseCookie(r)
|
cookie, err := ParseCookie(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
|
||||||
|
|
@ -131,10 +150,17 @@ func handleUI(w http.ResponseWriter, r *http.Request) error {
|
||||||
}
|
}
|
||||||
_ = cookie
|
_ = cookie
|
||||||
|
|
||||||
Config.Semaphore.Lock()
|
switch r.URL.Path {
|
||||||
defer Config.Semaphore.Unlock()
|
case "/":
|
||||||
|
w.Write(htmlIndex)
|
||||||
return errors.New("not impl")
|
return nil
|
||||||
|
case "/chatbot":
|
||||||
|
w.Write(htmlChatBot)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return errors.New("not found: " + r.URL.Path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Cookie struct {
|
type Cookie struct {
|
||||||
|
|
@ -142,28 +168,47 @@ type Cookie struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseCookie(r *http.Request) (Cookie, error) {
|
func ParseCookie(r *http.Request) (Cookie, error) {
|
||||||
|
if r.URL.Path != "/login" {
|
||||||
|
return parseCookieFromCookie(r)
|
||||||
|
}
|
||||||
|
cookie := Cookie{
|
||||||
|
Name: r.PostForm.Get("Name"),
|
||||||
|
}
|
||||||
|
return cookie, cookie.Verify()
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCookieFromCookie(r *http.Request) (Cookie, error) {
|
||||||
cookie, err := r.Cookie("root")
|
cookie, err := r.Cookie("root")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Cookie{}, err
|
return Cookie{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var result Cookie
|
decoded, err := base64.URLEncoding.DecodeString(cookie.Value)
|
||||||
if err := json.Unmarshal([]byte(cookie.Value), &result); err != nil {
|
if err != nil {
|
||||||
return Cookie{}, err
|
return Cookie{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Name == "" {
|
var result Cookie
|
||||||
return Cookie{}, errors.New("incomplete cookie")
|
if err := json.Unmarshal(decoded, &result); err != nil {
|
||||||
|
return Cookie{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, result.Verify()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cookie Cookie) Verify() error {
|
||||||
|
if cookie.Name == "" {
|
||||||
|
return errors.New("incomplete cookie")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cookie Cookie) Serialize(w http.ResponseWriter) {
|
func (cookie Cookie) Serialize(w http.ResponseWriter) {
|
||||||
b, _ := json.Marshal(cookie)
|
b, _ := json.Marshal(cookie)
|
||||||
|
encoded := base64.URLEncoding.EncodeToString(b)
|
||||||
c := &http.Cookie{
|
c := &http.Cookie{
|
||||||
Name: "root",
|
Name: "root",
|
||||||
Value: string(b),
|
Value: encoded,
|
||||||
}
|
}
|
||||||
http.SetCookie(w, c)
|
http.SetCookie(w, c)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<header>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
|
||||||
|
</header>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
|
|
@ -3,6 +3,11 @@
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
|
||||||
</header>
|
</header>
|
||||||
<body>
|
<body>
|
||||||
|
<form method="POST">
|
||||||
|
<label for="Name">Your Name</label>
|
||||||
|
<input name="Name" type="text"/>
|
||||||
|
<button type="submit">Sign In</button>
|
||||||
|
</form>
|
||||||
</body>
|
</body>
|
||||||
<footer>
|
<footer>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue