wrap async calls into promises
safari complains about bare async calls not being triggered by user action after a click allow admins to have multiple open sessions general webapp tweaks to background colors and button widths
This commit is contained in:
parent
81fbcba5a0
commit
a8d18d8812
|
@ -55,10 +55,10 @@ func LoginHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params
|
||||||
if err := user.Login(password); err != nil {
|
if err := user.Login(password); err != nil {
|
||||||
code := http.StatusBadRequest
|
code := http.StatusBadRequest
|
||||||
status := http.StatusText(code)
|
status := http.StatusText(code)
|
||||||
if err, ok := err.(*errors.InvalidCredentials); ok {
|
if invalidCreds, ok := err.(*errors.InvalidCredentials); ok {
|
||||||
code = err.Code()
|
code = invalidCreds.Code()
|
||||||
status = err.Error()
|
status = invalidCreds.Error()
|
||||||
err.Log()
|
invalidCreds.Log()
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorf("could not login %s: %s", username, err.Error())
|
logrus.Errorf("could not login %s: %s", username, err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,10 @@ func NewSession(user *user.User, table db.Collection) (*Session, error) {
|
||||||
Expires: user.TTL.FromNow(),
|
Expires: user.TTL.FromNow(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !user.IsAdmin {
|
||||||
// delete previous sessions
|
// delete previous sessions
|
||||||
table.Find(db.Cond{"user": user.ID}).Delete()
|
table.Find(db.Cond{"user": user.ID}).Delete()
|
||||||
|
}
|
||||||
// insert new one
|
// insert new one
|
||||||
_, err := table.Insert(sess)
|
_, err := table.Insert(sess)
|
||||||
return sess, err
|
return sess, err
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
<title>puerta@nidi.to</title>
|
<title>puerta@nidi.to</title>
|
||||||
<link rel="stylesheet" href="https://cdn.rob.mx/css/fonts.css" />
|
<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="https://cdn.rob.mx/nidito/index.css" />
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/icon/152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="/static/icon/152.png">
|
||||||
<link rel="apple-touch-icon" sizes="384x384" href="/static/icon/384.png">
|
<link rel="apple-touch-icon" sizes="384x384" href="/static/icon/384.png">
|
||||||
<link rel="apple-touch-icon" sizes="192x192" href="/static/icon/192.png">
|
<link rel="apple-touch-icon" sizes="192x192" href="/static/icon/192.png">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<style>
|
<style>
|
||||||
#user-list {
|
#user-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -250,7 +251,7 @@
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script type="module" src="https://unpkg.com/@github/webauthn-json@2.0.2/dist/esm/webauthn-json.browser-ponyfill.js"></script>
|
<script type="module" src="https://unpkg.com/@github/webauthn-json@2.1.1/dist/esm/webauthn-json.browser-ponyfill.js"></script>
|
||||||
<script>window._PushKey = "$PUSH_KEY$"</script>
|
<script>window._PushKey = "$PUSH_KEY$"</script>
|
||||||
<script type="module" src="/static/admin.js"></script>
|
<script type="module" src="/static/admin.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
|
|
||||||
<title>puerta@nidi.to</title>
|
<title>puerta@nidi.to</title>
|
||||||
<link rel="stylesheet" href="https://cdn.rob.mx/css/fonts.css" />
|
<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="https://cdn.rob.mx/nidito/index.css" />
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/icon/152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="/static/icon/152.png">
|
||||||
<link rel="apple-touch-icon" sizes="384x384" href="/static/icon/384.png">
|
<link rel="apple-touch-icon" sizes="384x384" href="/static/icon/384.png">
|
||||||
<link rel="apple-touch-icon" sizes="192x192" href="/static/icon/192.png">
|
<link rel="apple-touch-icon" sizes="192x192" href="/static/icon/192.png">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header id="main-header">
|
<header id="main-header">
|
||||||
|
@ -29,7 +31,7 @@
|
||||||
<button id="rex">Abrir</button>
|
<button id="rex">Abrir</button>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
<script type="module" src="https://unpkg.com/@github/webauthn-json@2.0.2/dist/esm/webauthn-json.browser-ponyfill.js"></script>
|
<script type="module" src="https://unpkg.com/@github/webauthn-json@2.1.1/dist/esm/webauthn-json.browser-ponyfill.js"></script>
|
||||||
<script type="module" src="/static/index.js" async="async"></script>
|
<script type="module" src="/static/index.js" async="async"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
<title>puerta@nidi.to</title>
|
<title>puerta@nidi.to</title>
|
||||||
<link rel="stylesheet" href="https://cdn.rob.mx/css/fonts.css" />
|
<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="https://cdn.rob.mx/nidito/index.css" />
|
||||||
<link rel="stylesheet" href="/static/index.css" />
|
<link rel="stylesheet" href="/static/index.css" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<!--link rel="manifest" href="/static/manifest.webmanifest" /-->
|
<!--link rel="manifest" href="/static/manifest.webmanifest" /-->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rob.mx/nidito/puerta/internal/auth"
|
"git.rob.mx/nidito/puerta/internal/auth"
|
||||||
|
@ -223,7 +224,7 @@ func Initialize(config *Config) (http.Handler, error) {
|
||||||
|
|
||||||
wan, err := webauthn.New(&webauthn.Config{
|
wan, err := webauthn.New(&webauthn.Config{
|
||||||
RPDisplayName: config.Name,
|
RPDisplayName: config.Name,
|
||||||
RPID: config.HTTP.Origin,
|
RPID: strings.Split(config.HTTP.Origin, ":")[0],
|
||||||
RPOrigins: origins,
|
RPOrigins: origins,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -299,6 +299,7 @@ window.addEventListener("load", async function() {
|
||||||
type: "module",
|
type: "module",
|
||||||
scope: "/"
|
scope: "/"
|
||||||
})
|
})
|
||||||
|
console.info(`Registered service worker`, reg)
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log(`Could not register serviceworker: ${err}`)
|
console.log(`Could not register serviceworker: ${err}`)
|
||||||
pnb.style.display = "none"
|
pnb.style.display = "none"
|
||||||
|
@ -317,6 +318,7 @@ window.addEventListener("load", async function() {
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error("Could not get pushmanager subscription", err)
|
console.error("Could not get pushmanager subscription", err)
|
||||||
|
pnb.style.display = "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,14 +330,6 @@ window.addEventListener("load", async function() {
|
||||||
console.error("Could not get pushmanager subscription", err)
|
console.error("Could not get pushmanager subscription", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sub) {
|
|
||||||
pnb.classList.add("subscribed")
|
|
||||||
pnb.innerHTML = "🔕"
|
|
||||||
} else {
|
|
||||||
pnb.classList.remove("subscribed")
|
|
||||||
pnb.innerHTML = "🔔"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pnb.classList.contains("subscribed")) {
|
if (!pnb.classList.contains("subscribed")) {
|
||||||
if (await createPushSubscription()) {
|
if (await createPushSubscription()) {
|
||||||
pnb.classList.add("subscribed")
|
pnb.classList.add("subscribed")
|
||||||
|
@ -347,6 +341,14 @@ window.addEventListener("load", async function() {
|
||||||
pnb.innerHTML = "🔔"
|
pnb.innerHTML = "🔔"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sub) {
|
||||||
|
pnb.classList.add("subscribed")
|
||||||
|
pnb.innerHTML = "🔕"
|
||||||
|
} else {
|
||||||
|
pnb.classList.remove("subscribed")
|
||||||
|
pnb.innerHTML = "🔔"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
/* SPDX-License-Identifier: Apache-2.0
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
Copyright © 2022 Roberto Hidalgo <nidito@un.rob.mx> */
|
Copyright © 2022 Roberto Hidalgo <nidito@un.rob.mx> */
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background: rgba(255,255,255,.6);
|
background: rgba(255,255,255,.6);
|
||||||
font-family: "Aestetico", sans-serif;
|
font-family: "Aestetico", sans-serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: block;
|
|
||||||
color: #c11145;
|
color: #c11145;
|
||||||
border: 5px solid #c11145;
|
border: 5px solid #c11145;
|
||||||
transition: all ease-in-out .5s;
|
transition: all ease-in-out .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main.container button {
|
||||||
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.5em;
|
||||||
|
border-radius: .4em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
@ -85,11 +94,38 @@ input[type=checkbox] {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
|
html { height: -webkit-fill-available; }
|
||||||
|
body {
|
||||||
|
background-color: #c11145;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
min-height: -webkit-fill-available;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
background-color: rgb(255, 198, 215);
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-header {
|
||||||
|
position: sticky;
|
||||||
|
padding-top: env(safe-area-inset-top);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#auth {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,9 @@ export async function withAuth(target, config) {
|
||||||
if (step == "register") {
|
if (step == "register") {
|
||||||
// server told us to register new credentials
|
// server told us to register new credentials
|
||||||
// we try to do that
|
// we try to do that
|
||||||
await register(challenge, target)
|
await new Promise((res,rej) => {
|
||||||
|
register(challenge, target).then(res).catch(rej)
|
||||||
|
})
|
||||||
// and retry the original request if successful
|
// and retry the original request if successful
|
||||||
return await new Promise((res, rej) => {
|
return await new Promise((res, rej) => {
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
|
@ -51,7 +53,9 @@ export async function withAuth(target, config) {
|
||||||
})
|
})
|
||||||
} else if (step == "login") {
|
} else if (step == "login") {
|
||||||
// server told us to use existing credential for request
|
// server told us to use existing credential for request
|
||||||
return await login(challenge, target, config)
|
return await new Promise((res,rej) => {
|
||||||
|
return login(challenge, target, config).then(res).catch(rej)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
throw `Unknown webauthn step: <${step}>`
|
throw `Unknown webauthn step: <${step}>`
|
||||||
|
|
Loading…
Reference in New Issue