admin panel, login page with auth session.
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
package website
|
||||
|
||||
import (
|
||||
"Portifolio/internal/middleware"
|
||||
"Portifolio/internal/model"
|
||||
"Portifolio/internal/service"
|
||||
"crypto/rand"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/FuLygon/go-totp/v2"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
@@ -21,13 +27,136 @@ func Getsite() http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed static/styles.css
|
||||
var styleCSS []byte
|
||||
//go:embed static/login.html
|
||||
var loginxHTML []byte
|
||||
|
||||
func Getstylesheet() http.HandlerFunc {
|
||||
func GetAdminLogin() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Write(loginxHTML)
|
||||
}
|
||||
}
|
||||
|
||||
type contextKey string
|
||||
|
||||
const ContextKeyRequestTime contextKey = "requestTime"
|
||||
|
||||
func LoginHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// checked once when the handler is registered
|
||||
envUsername := os.Getenv("username")
|
||||
envPassword := os.Getenv("password")
|
||||
envTOTPSecret := os.Getenv("AUTH_TOTP_SECRET")
|
||||
if envUsername == "" || envPassword == "" || envTOTPSecret == "" {
|
||||
http.Error(w, "env var missing", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
ts, ok := r.Context().Value(ContextKeyRequestTime).(time.Time)
|
||||
if !ok {
|
||||
ts = time.Now()
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, "invalid form data", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
password := r.FormValue("password")
|
||||
username := r.FormValue("username")
|
||||
code := r.FormValue("auth_code")
|
||||
fmt.Println(username, password, code)
|
||||
|
||||
if password == "" || username == "" || code == "" {
|
||||
http.Error(w, "form value is empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if password != envPassword || username != envUsername {
|
||||
http.Error(w, "username or password is not valid", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
v := totp.Validator{
|
||||
Algorithm: totp.AlgorithmSHA1,
|
||||
Digits: 6,
|
||||
Period: 30,
|
||||
Secret: envTOTPSecret,
|
||||
}
|
||||
|
||||
valid, err := v.ValidateWithTimestamp(code, ts.Unix())
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error validating TOTP code: %s", err), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if !valid {
|
||||
http.Error(w, "invalid auth code", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// In your login POST handler, after setting the cookie:
|
||||
token := generateSessionToken()
|
||||
middleware.RegisterSession(token) // <-- register before writing cookie
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "session",
|
||||
Value: token,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
MaxAge: 86400,
|
||||
})
|
||||
w.Header().Set("HX-Redirect", "/admin")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// Simple session token generator
|
||||
func generateSessionToken() string {
|
||||
b := make([]byte, 32)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(b)
|
||||
}
|
||||
|
||||
//go:embed static/admin.html
|
||||
var adminHTML []byte
|
||||
|
||||
func GetAdmin() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Write(adminHTML)
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed static/styles.css
|
||||
var styleCSSmain []byte
|
||||
|
||||
func GetstylesheetMain() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/css; charset=utf-8")
|
||||
w.Write(styleCSS)
|
||||
w.Write(styleCSSmain)
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed static/login.css
|
||||
var styleCSSlogin []byte
|
||||
|
||||
func GetstylesheetLogin() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/css; charset=utf-8")
|
||||
w.Write(styleCSSlogin)
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed static/admin.css
|
||||
var styleCSSadmin []byte
|
||||
|
||||
func GetstylesheetAdmin() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/css; charset=utf-8")
|
||||
w.Write(styleCSSadmin)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user