lol, 64bit integer overflows are fun to debug
specially when running a multi-arch cluster and HA with poor observability. a `time.Duration` was being casted to an `int` (because I clearly have no clue of what I'm doing). All is well on 64-bit processors, but 32-bit processors choke on the very long micro-second precision int, overflow, and turn `7d`, around `604800` seconds into `-114753536` seconds, which the browser happily (and correctly) turns into a cookie sent to /dev/null. lol.
This commit is contained in:
parent
e57ebc7108
commit
038e09b202
|
@ -130,30 +130,30 @@
|
|||
</div>
|
||||
</header>
|
||||
<form action="/api/user/:id" class="user-info-panel-details hidden">
|
||||
<label for="name">Nombre</label>
|
||||
<input name="name" value="" placeholder="João Gilberto" required />
|
||||
<label for="edit-name">Nombre</label>
|
||||
<input id="edit-name" name="name" value="" placeholder="João Gilberto" required />
|
||||
|
||||
<label for="greeting">Saludo</label>
|
||||
<input name="greeting" placeholder="Olá Joãzinho!" />
|
||||
<label for="edit-edit-greeting">Saludo</label>
|
||||
<input id="edit-greeting" name="greeting" placeholder="Olá Joãzinho!" />
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" />
|
||||
<label for="edit-password">Password</label>
|
||||
<input id="edit-password" type="password" name="password" />
|
||||
|
||||
<label for="schedule">Horarios</label>
|
||||
<input type="text" name="schedule" placeholder="days=1-5 hours=8-20:35" autocorrect="off"/>
|
||||
<label for="edit-schedule">Horarios</label>
|
||||
<input id="edit-schedule" type="text" name="schedule" placeholder="days=1-5 hours=8-20:35" autocorrect="off"/>
|
||||
|
||||
<label for="expires">Expires</label>
|
||||
<input type="datetime-local" name="expires" placeholder="2023-01-01T00:00:00Z" />
|
||||
<label for="edit-expires">Expires</label>
|
||||
<input id="edit-expires" type="datetime-local" name="expires" placeholder="2023-01-01T00:00:00Z" />
|
||||
|
||||
<label for="ttl">TTL</label>
|
||||
<input type="text" name="max_ttl" placeholder="30d" autocorrect="off"/>
|
||||
<label for="edit-ttl">TTL</label>
|
||||
<input id="edit-max_ttl" type="text" name="max_ttl" placeholder="30d" autocorrect="off"/>
|
||||
|
||||
<div>
|
||||
<input type="checkbox" name="is_admin" /><label for="admin">Admin?</label>
|
||||
<input id="edit-is_admin" type="checkbox" name="is_admin" /><label for="edit-admin">Admin?</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="checkbox" name="second_factor" /><label for="admin">Requiere 2FA?</label>
|
||||
<input id="edit-second_factor" type="checkbox" name="second_factor" /><label for="edit-second_factor">Requiere 2FA?</label>
|
||||
</div>
|
||||
|
||||
<div id="actions">
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<link rel="stylesheet" href="https://cdn.rob.mx/css/fonts.css" />
|
||||
<link rel="stylesheet" href="https://cdn.rob.mx/nidito/index.css" />
|
||||
<link rel="stylesheet" href="/static/index.css" />
|
||||
<!-- link rel="manifest" href="/static/manifest.webmanifest" /-->
|
||||
</head>
|
||||
<body>
|
||||
<header id="main-header">
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<link rel="stylesheet" href="https://cdn.rob.mx/css/fonts.css" />
|
||||
<link rel="stylesheet" href="https://cdn.rob.mx/nidito/index.css" />
|
||||
<link rel="stylesheet" href="/static/index.css" />
|
||||
<!--link rel="manifest" href="/static/manifest.webmanifest" /-->
|
||||
</head>
|
||||
<body>
|
||||
<header id="main-header">
|
||||
|
@ -19,12 +20,12 @@
|
|||
</header>
|
||||
<main class="container">
|
||||
<form id="login" method="post" action="/api/login">
|
||||
<span class="error"></span>
|
||||
<h2 class="error"></h2>
|
||||
<label for="user">Usuario</label>
|
||||
<input type="text" name="user" autocorrect="false" />
|
||||
<input id="user" type="text" name="user" autocorrect="false" />
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" />
|
||||
<input id="password" type="password" name="password" />
|
||||
<button id="auth" type="submit">Iniciar Sesión</button>
|
||||
</form>
|
||||
</main>
|
||||
|
|
|
@ -11,6 +11,10 @@ button {
|
|||
transition: all ease-in-out .5s;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#rex {
|
||||
font-size: 5em;
|
||||
border-radius: 100%;
|
||||
|
@ -76,13 +80,16 @@ input[type=checkbox] {
|
|||
height: .8em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
input {
|
||||
max-width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
input {
|
||||
max-width: 100%;
|
||||
}
|
||||
button {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"background_color": "#ffc6d7",
|
||||
"description": "Abre la puerta del Castillo de Chapultebob",
|
||||
"display": "fullscreen",
|
||||
"icons": [
|
||||
{
|
||||
"src": "static/icon@192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"name": "Puerta Nidito",
|
||||
"short_name": "Puerta",
|
||||
"start_url": "/"
|
||||
}
|
|
@ -6,13 +6,12 @@ importScripts(
|
|||
|
||||
workbox.loadModule('workbox-strategies');
|
||||
|
||||
|
||||
self.addEventListener("install", event => {
|
||||
console.log("Service worker installed");
|
||||
|
||||
const urlsToCache = ["/login", "/", "index.css", "/index.js", "/login.js", "/webauthn.js"];
|
||||
event.waitUntil(
|
||||
caches.open("pwa-assets")
|
||||
caches.open("assets")
|
||||
.then(cache => {
|
||||
return cache.addAll(urlsToCache);
|
||||
})
|
||||
|
|
|
@ -66,7 +66,7 @@ func (ttl *TTL) Scan(value any) error {
|
|||
}
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
if src == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ func (ttl *TTL) FromNow() time.Time {
|
|||
}
|
||||
|
||||
func (ttl *TTL) Seconds() int {
|
||||
return int(ttl.duration)
|
||||
return int(ttl.duration.Seconds())
|
||||
}
|
||||
|
||||
var _ sql.Scanner = &TTL{}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package user_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.rob.mx/nidito/puerta/internal/user"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ttl := user.TTL{}
|
||||
err := ttl.Scan("")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed scanning empty string: %s", err)
|
||||
}
|
||||
|
||||
err = ttl.Scan("7d")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed scanning 7d: %s", err)
|
||||
}
|
||||
|
||||
if ttl.Seconds() != 604800 {
|
||||
t.Fatalf("parsed bad seconds %d", ttl.Seconds())
|
||||
}
|
||||
|
||||
// conn := sqlite.ConnectionURL{
|
||||
// Database: "test.db",
|
||||
// Options: map[string]string{
|
||||
// "_journal": "WAL",
|
||||
// "_busy_timeout": "5000",
|
||||
// },
|
||||
// }
|
||||
|
||||
// _db, err := sqlite.Open(conn)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
|
||||
// user := &user.User{}
|
||||
// if err := _db.Get(user, db.Cond{"handle": "test"}); err != nil {
|
||||
// t.Fatalf("could not get user: %s", err)
|
||||
// }
|
||||
|
||||
// t.Fatalf("user ttl (%v): %d, from now: %s", user.TTL, user.TTL.Seconds(), user.TTL.FromNow())
|
||||
|
||||
}
|
||||
|
||||
func TestMarshalDB(t *testing.T) {
|
||||
ttl := user.TTL{}
|
||||
|
||||
err := ttl.Scan("7d")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed scanning 7d: %s", err)
|
||||
}
|
||||
|
||||
if ttl.Seconds() != 60*60*24*7 {
|
||||
t.Fatalf("parsed bad seconds %d", ttl.Seconds())
|
||||
}
|
||||
|
||||
data, err := ttl.MarshalDB()
|
||||
if err != nil {
|
||||
t.Fatalf("could not marshal ttl %s", err)
|
||||
}
|
||||
|
||||
expected := `"7d"`
|
||||
if fmt.Sprintf("%s", data) != expected {
|
||||
t.Fatalf("encoded data mismatch. expected %s, got %s", expected, data)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue