make better login and admin session server side smooth
This commit is contained in:
@@ -17,3 +17,7 @@
|
||||
-- background may include,
|
||||
-- items are free falling
|
||||
-- computers(macentosch), black board, calculators. fun numbers(rainbow), books. coffe mugs
|
||||
|
||||
- better portifolio intergration with link to repo.
|
||||
|
||||
- company history.
|
||||
@@ -75,12 +75,42 @@ func main() {
|
||||
mux.HandleFunc("GET /42", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/42.html") })
|
||||
mux.HandleFunc("GET /secret", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/secret.html") })
|
||||
mux.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/icon.png") })
|
||||
mux.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/login.html") })
|
||||
mux.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
cookie, err := r.Cookie("session")
|
||||
if err == nil {
|
||||
sessionMu.RLock()
|
||||
expiry, ok := sessionStore[cookie.Value]
|
||||
sessionMu.RUnlock()
|
||||
// had session, but invalid
|
||||
if !ok || time.Now().After(expiry) {
|
||||
sessionMu.Lock()
|
||||
delete(sessionStore, cookie.Value)
|
||||
sessionMu.Unlock()
|
||||
} else { // valid session
|
||||
http.Redirect(w, r, "/admin", http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, "./static/login.html")
|
||||
})
|
||||
|
||||
mux.HandleFunc("GET /admin", requireAuth(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, "./static/admin.html")
|
||||
}))
|
||||
|
||||
mux.HandleFunc("GET /logout", requireAuth(func(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie("session")
|
||||
if err == nil {
|
||||
// delete session cookie token
|
||||
sessionMu.Lock()
|
||||
delete(sessionStore, cookie.Value)
|
||||
sessionMu.Unlock()
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}))
|
||||
|
||||
mux.HandleFunc("POST /newsletter/subscribe", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Email string `json:"email"`
|
||||
@@ -149,7 +179,7 @@ func main() {
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Expires: time.Now().Add(12 * time.Hour),
|
||||
Expires: time.Now().Add(48 * time.Hour),
|
||||
})
|
||||
|
||||
// htmx reads this header and does the redirect client-side
|
||||
|
||||
+2
-14
@@ -18,7 +18,7 @@
|
||||
<nav>
|
||||
<a class="nav-logo" href="#">samantha_vero_friis</a>
|
||||
<div class="nav-links">
|
||||
<a >login</a>
|
||||
<a href="/login">login</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -447,24 +447,12 @@
|
||||
</div>
|
||||
<div class="footer-copy">© 2026 — all rights reserved</div>
|
||||
</footer>
|
||||
<div id="login-overlay" style="min-width: 50%; position: fixed; inset: 0; z-index: 100; display: none; align-items: center; justify-content: center; background: rgba(0,0,0,0.35); backdrop-filter: blur(12px);">
|
||||
<div hx-get="/login" hx-trigger="load" hx-swap="outerHTML">
|
||||
<span class="spinner">Loading login page...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
// just some fun.
|
||||
console.log("%c👀 hi there!", "font-size:20px")
|
||||
|
||||
function closelogin() {
|
||||
document.getElementById('login-overlay').style.display = 'none';
|
||||
}
|
||||
|
||||
document.querySelector('.nav-links a').addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
document.getElementById('login-overlay').style.display = 'flex';
|
||||
});
|
||||
|
||||
function makeday() {
|
||||
themeRoot.classList.remove('night');
|
||||
|
||||
+39
-20
@@ -1,28 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Samantha Vero Friis</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap"
|
||||
rel="stylesheet" />
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
<link rel="stylesheet" href="/static/output.css"/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@300;400;500&display=swap" rel="stylesheet" />
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
|
||||
<style>
|
||||
.login-wrap { min-width: 50%; min-height: 520px; display: flex; align-items: center; justify-content: center; padding: 2rem 0; }
|
||||
.login-card { background: white; border: 0.5px solid var(--color-border-tertiary); border-radius: 8px; width: 100%; max-width: 400px; overflow: hidden; }
|
||||
.card-header { background: #0C447C; padding: 2rem 2rem 1.5rem; }
|
||||
.brand { font-family: 'DM Serif Display', serif; font-size: 22px; color: #E6F1FB; letter-spacing: -0.5px; margin: 0 0 4px; }
|
||||
.brand span { font-style: italic; color: #85B7EB; }
|
||||
.brand-sub { font-family: 'DM Mono', monospace; font-size: 11px; color: #378ADD; letter-spacing: 2px; text-transform: uppercase; margin: 0; }
|
||||
.card-body { padding: 1.75rem 2rem; }
|
||||
.field-group { margin-bottom: 1rem; }
|
||||
.field-label { font-family: 'DM Mono', monospace; font-size: 11px; color: var(--color-text-secondary); letter-spacing: 1px; text-transform: uppercase; display: block; margin-bottom: 6px; }
|
||||
.field-input { width: 100%; box-sizing: border-box; font-family: 'DM Mono', monospace; font-size: 14px; padding: 10px 12px; border-radius: 6px; border: 0.5px solid var(--color-border-tertiary); background: var(--color-background-secondary); color: var(--color-text-primary); transition: border-color 0.2s, box-shadow 0.2s; }
|
||||
.field-input:focus { outline: none; border-color: #378ADD; box-shadow: 0 0 0 3px rgba(55,138,221,0.15); }
|
||||
.submit-btn { width: 100%; padding: 11px; background: #185FA5; color: #E6F1FB; border: none; border-radius: 6px; font-family: 'DM Mono', monospace; font-size: 13px; letter-spacing: 1px; cursor: pointer; transition: background 0.2s, transform 0.1s; margin-top: 0.5rem; }
|
||||
.submit-btn:hover { background: #0C447C; }
|
||||
.submit-btn:active { transform: scale(0.98); }
|
||||
.htmx-indicator { opacity: 0; transition: opacity 0.2s; font-family: 'DM Mono', monospace; font-size: 11px; color: var(--color-text-secondary); text-align: center; margin-top: 8px; }
|
||||
.htmx-request .htmx-indicator { opacity: 1; }
|
||||
.htmx-request .submit-btn { background: #0C447C; cursor: not-allowed; pointer-events: none; }
|
||||
.error-banner { font-family: 'DM Mono', monospace; font-size: 11px; color: #A32D2D; background: #FCEBEB; border: 0.5px solid #F09595; border-radius: 6px; padding: 8px 12px; margin-bottom: 1rem; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="theme-root day " id="themeRoot">
|
||||
<div class="login-wrap">
|
||||
<div class="login-card">
|
||||
<div class="card-header">
|
||||
@@ -76,3 +71,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.login-wrap { z-index: 10; min-width: 50%; min-height: 520px; display: flex; align-items: center; justify-content: center; padding: 2rem 0; }
|
||||
.login-card { background: white; border: 0.5px solid var(--color-border-tertiary); border-radius: 8px; width: 100%; max-width: 400px; overflow: hidden; }
|
||||
.card-header { background: #0C447C; padding: 2rem 2rem 1.5rem; }
|
||||
.brand { font-family: 'DM Serif Display', serif; font-size: 22px; color: #E6F1FB; letter-spacing: -0.5px; margin: 0 0 4px; }
|
||||
.brand span { font-style: italic; color: #85B7EB; }
|
||||
.brand-sub { font-family: 'DM Mono', monospace; font-size: 11px; color: #378ADD; letter-spacing: 2px; text-transform: uppercase; margin: 0; }
|
||||
.card-body { padding: 1.75rem 2rem; }
|
||||
.field-group { margin-bottom: 1rem; }
|
||||
.field-label { font-family: 'DM Mono', monospace; font-size: 11px; color: var(--color-text-secondary); letter-spacing: 1px; text-transform: uppercase; display: block; margin-bottom: 6px; }
|
||||
.field-input { width: 100%; box-sizing: border-box; font-family: 'DM Mono', monospace; font-size: 14px; padding: 10px 12px; border-radius: 6px; border: 0.5px solid var(--color-border-tertiary); background: var(--color-background-secondary); color: var(--color-text-primary); transition: border-color 0.2s, box-shadow 0.2s; }
|
||||
.field-input:focus { outline: none; border-color: #378ADD; box-shadow: 0 0 0 3px rgba(55,138,221,0.15); }
|
||||
.submit-btn { width: 100%; padding: 11px; background: #185FA5; color: #E6F1FB; border: none; border-radius: 6px; font-family: 'DM Mono', monospace; font-size: 13px; letter-spacing: 1px; cursor: pointer; transition: background 0.2s, transform 0.1s; margin-top: 0.5rem; }
|
||||
.submit-btn:hover { background: #0C447C; }
|
||||
.submit-btn:active { transform: scale(0.98); }
|
||||
.htmx-indicator { opacity: 0; transition: opacity 0.2s; font-family: 'DM Mono', monospace; font-size: 11px; color: var(--color-text-secondary); text-align: center; margin-top: 8px; }
|
||||
.htmx-request .htmx-indicator { opacity: 1; }
|
||||
.htmx-request .submit-btn { background: #0C447C; cursor: not-allowed; pointer-events: none; }
|
||||
.error-banner { font-family: 'DM Mono', monospace; font-size: 11px; color: #A32D2D; background: #FCEBEB; border: 0.5px solid #F09595; border-radius: 6px; padding: 8px 12px; margin-bottom: 1rem; }
|
||||
</style>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user