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 {
ID int `db:"id" json:"-"`
Handle string `db:"user" json:"user"`
Handle string `db:"handle" json:"handle"`
Name string `db:"name" json:"name"`
Password string `db:"password" json:"password"`
Password string `db:"password" json:"-"`
Schedule *UserSchedule `db:"schedule,omitempty" json:"schedule"`
Expires *time.Time `db:"expires,omitempty" json:"expires"`
Greeting string `db:"greeting" json:"greeting"`
TTL *TTL `db:"max_ttl,omitempty" json:"max_ttl"`
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
}
@ -140,4 +140,6 @@ func (user *User) Login(password string) error {
return nil
}
// implement interfaces
var _ = db.Record(&User{})
var _ = webauthn.User(&User{})

View File

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

View File

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

View File

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