fix webcomponent

This commit is contained in:
Roberto Hidalgo 2023-01-02 01:44:34 -06:00
parent bf7e3d7785
commit eee573eb47
4 changed files with 52 additions and 49 deletions

View File

@ -41,15 +41,15 @@ func UserFromContext(req *http.Request) *User {
type User struct { type User struct {
ID int `db:"id" json:"-"` ID int `db:"id" json:"-"`
Handle string `db:"user" json:"user"` Handle string `db:"handle" json:"handle"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
Password string `db:"password" json:"password"` Password string `db:"password" json:"-"`
Schedule *UserSchedule `db:"schedule,omitempty" json:"schedule"` Schedule *UserSchedule `db:"schedule,omitempty" json:"schedule"`
Expires *time.Time `db:"expires,omitempty" json:"expires"` Expires *time.Time `db:"expires,omitempty" json:"expires"`
Greeting string `db:"greeting" json:"greeting"` Greeting string `db:"greeting" json:"greeting"`
TTL *TTL `db:"max_ttl,omitempty" json:"max_ttl"` TTL *TTL `db:"max_ttl,omitempty" json:"max_ttl"`
Require2FA bool `db:"second_factor" json:"second_factor"` Require2FA bool `db:"second_factor" json:"second_factor"`
IsAdmin bool `db:"is_admin" json:"admin"` IsAdmin bool `db:"is_admin" json:"is_admin"`
credentials []*Credential credentials []*Credential
} }
@ -140,4 +140,6 @@ func (user *User) Login(password string) error {
return nil return nil
} }
// implement interfaces
var _ = db.Record(&User{}) var _ = db.Record(&User{})
var _ = webauthn.User(&User{})

View File

@ -18,7 +18,7 @@
</div> </div>
</header> </header>
<main class="container"> <main class="container">
<section id="create-user"> <section id="create-user" style="display:none">
<h2>Crear usuario</h2> <h2>Crear usuario</h2>
<form id="create-user" method="post" action="/api/user"> <form id="create-user" method="post" action="/api/user">
<label for="user">Handle</label> <label for="user">Handle</label>
@ -61,14 +61,13 @@
</main> </main>
<script type="module" src="/static/admin.js"></script> <script type="module" src="/static/admin.js"></script>
<template id="user-info-panel"> <template id="user-info-panel"><li class="user-info-panel">
<li class="user-info-panel {{ if .IsAdmin }}user-info-panel-admin{{ end }}">
<header> <header>
<h3><slot name="name">{{ .Name }}</h3> <h3><slot name="name">Alguien</h3>
<code><pre>{{ .Handle }}</pre></code> <code><pre>alguien</pre></code>
<button class="user-edit">Modificar</button> <button class="user-edit">Modificar</button>
</header> </header>
<div class="user-info-panel-details"> <form action="/api/user/:id" class="user-info-panel-details">
<label for="name">Nombre</label> <label for="name">Nombre</label>
<input name="name" value="" placeholder="João Gilberto" /> <input name="name" value="" placeholder="João Gilberto" />
@ -95,8 +94,7 @@
<button class="user-delete">Eliminar</button> <button class="user-delete">Eliminar</button>
<button class="user-save">Guardar cambios</button> <button class="user-save">Guardar cambios</button>
</div> </form>
</li> </li></template>
</template>
</body> </body>
</html> </html>

View File

@ -180,8 +180,7 @@ func Initialize(config *Config) (http.Handler, error) {
router.POST("/api/rex", am.Enforce2FA(rex)) router.POST("/api/rex", am.Enforce2FA(rex))
router.GET("/admin", am.RequireAdmin(renderTemplate(adminTemplate))) router.GET("/admin", am.RequireAdmin(renderTemplate(adminTemplate)))
router.GET("/api/user", am.RequireAdmin(listUsers)) router.GET("/api/user", am.RequireAdmin(listUsers))
// router.GET("/api/user/:id", am.RequireAdmin(getUser)) router.GET("/api/user/:id", am.RequireAdmin(getUser))
router.GET("/api/user/:id", getUser)
router.PUT("/api/user", am.RequireAdmin(am.Enforce2FA(createUser))) router.PUT("/api/user", am.RequireAdmin(am.Enforce2FA(createUser)))
router.POST("/api/user/:id", am.RequireAdmin(am.Enforce2FA(updateUser))) router.POST("/api/user/:id", am.RequireAdmin(am.Enforce2FA(updateUser)))
router.DELETE("/api/user/:id", am.RequireAdmin(am.Enforce2FA(deleteUser))) router.DELETE("/api/user/:id", am.RequireAdmin(am.Enforce2FA(deleteUser)))

View File

@ -1,32 +1,35 @@
const button = document.querySelector("#open button") const button = document.querySelector("#open button")
const form = document.querySelector("#open") const form = document.querySelector("#open")
const { create: createCredentials, get: getCredentials } = hankoWebAuthn;
const userList = document.querySelector("#user-list > ul") const userList = document.querySelector("#user-list > ul")
class UserInfoPanel extends HTMLElement {
customElements.define( constructor(user) {
"user-info-panel",
class extends HTMLElement {
constructor() {
super() super()
let template = document.getElementById("user-info-panel") let template = document.getElementById("user-info-panel")
const shadowRoot = this.attachShadow({ mode: "open" }) const shadowRoot = this.attachShadow({ mode: "open" })
const panel = template.content.cloneNode(true) const panel = template.content.cloneNode(true)
panel.querySelector('h3').textContent = this.getAttribute('name') let handle = user.handle
panel.querySelector('name').value = this.getAttribute('name') panel.querySelector('h3').innerHTML = user.name
panel.querySelector('pre').textContent = this.getAttribute('handle') panel.querySelector('input[name=name]').value = user.name
panel.querySelector('greeting').value = this.getAttribute('greeting') panel.querySelector('form').action = panel.querySelector('form').action.replace(":id", handle)
panel.querySelector('schedule').value = this.getAttribute('schedule') panel.querySelector('pre').textContent = handle
panel.querySelector('expires').value = this.getAttribute('expires')
panel.querySelector('max_ttl').value = this.getAttribute('ttl') panel.querySelector('input[name=greeting]').value = user.greeting
panel.querySelector('is_admin').checked = this.hasAttribute('admin') panel.querySelector('input[name=schedule]').value = user.schedule
panel.querySelector('second_factor').checked = this.hasAttribute('second_factor') panel.querySelector('input[name=expires]').value = user.expires
panel.querySelector('input[name=max_ttl]').value = user.max_ttl
panel.querySelector('input[name=is_admin]').checked = user.is_admin
panel.querySelector('input[name=second_factor]').checked = user.second_factor
shadowRoot.appendChild(panel) shadowRoot.appendChild(panel)
} }
} }
customElements.define(
"user-info-panel",
UserInfoPanel
); );
async function fetchUsers() { async function fetchUsers() {
@ -46,25 +49,26 @@ async function fetchUsers() {
return return
} }
userList.replaceChildren(json.map(u => { json.forEach(u => {
const ip = document.createElement("user-info-panel") const ip = new UserInfoPanel(u)
ip.setAttribute("name", u.name) ip.setAttribute("data-name", u.name)
ip.setAttribute("handle", u.handle) ip.setAttribute("data-handle", u.handle)
ip.setAttribute('greeting', u.greeting) ip.setAttribute('data-greeting', u.greeting)
ip.setAttribute('schedule', u.schedule) ip.setAttribute('data-schedule', u.schedule)
ip.setAttribute('expires', u.expires) ip.setAttribute('data-expires', u.expires)
ip.setAttribute('max_ttl', u.ttl) ip.setAttribute('data-max_ttl', u.max_ttl)
if (u.admin) { if (u.admin) {
ip.setAttribute('is_admin', "") ip.setAttribute('data-is_admin', "")
} }
if (u.second_factor) { if (u.second_factor) {
ip.setAttribute('second_factor', "") ip.setAttribute('data-second_factor', "")
} }
return ip return userList.append(ip)
})) })
} }
window.addEventListener("load", async function() {
await fetchUsers()
})