This commit is contained in:
Sabudaki 2024-09-03 22:34:04 +03:00
commit 0deed94a83
7 changed files with 224 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*_templ.go

20
db.go Normal file
View file

@ -0,0 +1,20 @@
package main
import "fmt"
type DBLoginResult struct {
Idx int
}
func DBLogin(username string, password string) (DBLoginResult, error) {
row := db.QueryRow("SELECT idx FROM Users WHERE username = $1 AND password = $2", username, password)
login := DBLoginResult{}
err := row.Scan(&login.Idx)
if err != nil {
fmt.Println(err)
}
return login, err
}

7
go.mod Normal file
View file

@ -0,0 +1,7 @@
module git.synapse.enterprises/synent/rpg
go 1.22.3
require github.com/a-h/templ v0.2.771
require github.com/lib/pq v1.10.9 // indirect

4
go.sum Normal file
View file

@ -0,0 +1,4 @@
github.com/a-h/templ v0.2.771 h1:4KH5ykNigYGGpCe0fRJ7/hzwz72k3qFqIiiLLJskbSo=
github.com/a-h/templ v0.2.771/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=

7
initdb.sql Normal file
View file

@ -0,0 +1,7 @@
DROP TABLE IF EXISTS Users;
CREATE TABLE Users (
idx SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) UNIQUE NOT NULL
);

146
main.go Normal file
View file

@ -0,0 +1,146 @@
package main
import (
"crypto/rand"
"database/sql"
"encoding/base64"
"sync"
_ "github.com/lib/pq"
"fmt"
"net/http"
)
type UserSession struct {
AccountIDX int
Username string
}
type PageData struct {
session *UserSession
}
var sessionsMutex sync.Mutex
var sessions = map[string]*UserSession{}
var db *sql.DB
func SendError(w http.ResponseWriter, r *http.Request, code int) {
w.WriteHeader(code)
errorString := fmt.Sprintf("Error %d", code)
page := tPage(tError(errorString))
page.Render(r.Context(), w)
}
func AttemptCookieAuth(req *http.Request) *UserSession {
cookie, err := req.Cookie("session")
if err != nil {
return nil
}
sessionsMutex.Lock()
session := sessions[cookie.Value]
sessionsMutex.Unlock()
return session
}
func RootHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
SendError(w, r, http.StatusBadRequest)
return
}
session := AttemptCookieAuth(r)
if session != nil {
page := tPage(tHello(session))
page.Render(r.Context(), w)
return
} else {
page := tPage(tLoginForm(""))
page.Render(r.Context(), w)
return
}
}
func LoginHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
SendError(w, r, http.StatusBadRequest)
return
}
err := r.ParseForm()
if err != nil {
SendError(w, r, http.StatusBadRequest)
return
}
session := AttemptCookieAuth(r)
if session != nil {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
username := r.FormValue("username")
password := r.FormValue("password")
loginResult, err := DBLogin(username, password)
if err != nil {
loginForm := tLoginForm("Invalid username or password")
page := tPage(loginForm)
page.Render(r.Context(), w)
return
}
var cookieBytes [24]byte
rand.Read(cookieBytes[:])
cookie := base64.URLEncoding.EncodeToString(cookieBytes[:])
session = &UserSession{
AccountIDX: loginResult.Idx,
Username: username,
}
sessionsMutex.Lock()
sessions[cookie] = session
sessionsMutex.Unlock()
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: cookie,
HttpOnly: true,
Path: "/",
})
pageContents := tHello(session)
page := tPage(pageContents)
page.Render(r.Context(), w)
}
func main() {
var err error
conninfo := "host=localhost user=postgres password=work dbname=rpg sslmode=disable"
listenEndpoint := "localhost:8000"
db, err = sql.Open("postgres", conninfo)
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Connected to database")
http.HandleFunc("/login", LoginHandler)
http.HandleFunc("/", RootHandler)
fmt.Printf("Listening on %s\n", listenEndpoint)
http.ListenAndServe(listenEndpoint, nil)
}

39
templates.templ Normal file
View file

@ -0,0 +1,39 @@
package main
templ tLoginForm(err string) {
<form action="/login" method="POST">
<h2>Login</h2>
Username: <input name="username"><br>
Password: <input name="password" type="password"><br>
if err != "" {
<div style="color:red">{err}</div>
}
<input type="submit">
</form>
}
templ tHello(session *UserSession) {
<div>Hello {session.Username}</div>
}
templ tError(err string) {
<div style="color:red;">err</div>
}
templ tPage(contents templ.Component) {
<html>
<head>
<title>The Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>THE GAME</h1>
@contents
</body>
</html>
}