Security hardening: go-live review fixes
- TV tokens upgraded from 4 to 6 digits; Regen Token button in Admin - Nginx rate limiting on TV dashboard and WebSocket endpoints - Login lockout after 5 failed attempts (15 min); clears on admin password reset - HSTS header added; CSP unsafe-inline removed from script-src; CORS restricted to explicit methods/headers - Dependency CVE fixes: PyJWT 2.12.0, aiomysql 0.3.0, cryptography 46.0.5, python-multipart 0.0.22 - datetime.utcnow() replaced with datetime.now(timezone.utc) throughout - SQL identifier whitelist for startup migration queries - README updated: security notes section, lockout docs, token regen, NPM proxy guidance Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,16 @@ export const useChildrenStore = defineStore('children', () => {
|
||||
children.value = children.value.filter((c) => c.id !== id)
|
||||
}
|
||||
|
||||
async function regenerateToken(id) {
|
||||
const res = await api.post(`/api/children/${id}/regenerate-token`)
|
||||
const idx = children.value.findIndex((c) => c.id === id)
|
||||
if (idx !== -1) children.value[idx] = res.data
|
||||
return res.data
|
||||
}
|
||||
|
||||
function setActiveChild(child) {
|
||||
activeChild.value = child
|
||||
}
|
||||
|
||||
return { children, activeChild, fetchChildren, createChild, updateChild, deleteChild, setActiveChild }
|
||||
return { children, activeChild, fetchChildren, createChild, updateChild, deleteChild, regenerateToken, setActiveChild }
|
||||
})
|
||||
|
||||
@@ -48,11 +48,13 @@
|
||||
<div class="item-color" :style="{ background: child.color }"></div>
|
||||
<span class="item-name">{{ child.name }}</span>
|
||||
<span class="item-meta">{{ child.is_active ? 'Active' : 'Inactive' }}</span>
|
||||
<span class="item-meta token-meta" title="TV token">📺 {{ child.tv_token }}</span>
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm" @click="startEditChild(child)">Edit</button>
|
||||
<button class="btn-sm" @click="toggleChild(child)">
|
||||
{{ child.is_active ? 'Deactivate' : 'Activate' }}
|
||||
</button>
|
||||
<button class="btn-sm" @click="regenToken(child)" title="Generate a new TV token (old URL will stop working)">Regen Token</button>
|
||||
<button class="btn-sm btn-danger" @click="deleteChild(child.id)">Delete</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -536,6 +538,12 @@ async function deleteChild(id) {
|
||||
}
|
||||
}
|
||||
|
||||
async function regenToken(child) {
|
||||
if (confirm(`Regenerate TV token for ${child.name}? The old TV URL will stop working immediately.`)) {
|
||||
await childrenStore.regenerateToken(child.id)
|
||||
}
|
||||
}
|
||||
|
||||
// Subjects
|
||||
const showSubjectForm = ref(false)
|
||||
const newSubject = ref({ name: '', icon: '📚', color: '#10B981' })
|
||||
|
||||
Reference in New Issue
Block a user