feat: use sessionStorage by default for UUID/tokens, add opt-in remember-me with warning

This commit is contained in:
2026-02-08 14:02:46 +01:00
parent 8073003460
commit 5493148551
10 changed files with 95 additions and 11 deletions

View File

@@ -110,6 +110,14 @@ class AuthModal extends HTMLElement {
</div>
` : ''}
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="remember-me" ${auth.getRememberMe() ? 'checked' : ''}>
<span>${t('auth.rememberMe')}</span>
</label>
<p class="field-hint">${t('auth.rememberMeHint')}</p>
</div>
<button type="submit" class="btn btn-primary btn-lg btn-block" ${this.loading ? 'disabled' : ''}>
${this.loading ? t('auth.loggingIn') : t('auth.login')}
</button>
@@ -247,6 +255,9 @@ class AuthModal extends HTMLElement {
this.error = null
this.render()
const rememberMe = this.querySelector('#remember-me')?.checked || false
auth.setRememberMe(rememberMe)
const result = await auth.login(uuid)
this.loading = false
@@ -469,6 +480,26 @@ style.textContent = /* css */`
auth-modal .link-btn:hover {
color: var(--color-accent-hover);
}
auth-modal .checkbox-label {
display: flex;
align-items: center;
gap: var(--space-sm);
cursor: pointer;
font-size: var(--font-size-sm);
}
auth-modal .checkbox-label input {
width: 16px;
height: 16px;
accent-color: var(--color-accent);
}
auth-modal .field-hint {
font-size: var(--font-size-xs);
color: var(--color-text-muted);
margin-top: var(--space-xs);
}
`
document.head.appendChild(style)

View File

@@ -7,6 +7,7 @@
*/
import { directus } from './directus.js'
import { setPersist, getPersist } from './directus/client.js'
import { i18n } from '../i18n.js'
const AUTH_DOMAIN = 'dgray.io'
@@ -16,6 +17,9 @@ class AuthService {
this.currentUser = null
this.listeners = new Set()
this.hashCache = new Map()
if (localStorage.getItem('dgray_remember') === '1') {
setPersist(true)
}
}
/**
@@ -136,6 +140,8 @@ class AuthService {
this.currentUser = null
this.clearStoredUuid()
localStorage.removeItem('dgray_remember')
setPersist(false)
this.resetPreferencesToDefaults()
this.notifyListeners()
}
@@ -227,7 +233,8 @@ class AuthService {
* @param {string} uuid
*/
storeUuid(uuid) {
localStorage.setItem('dgray_uuid', uuid)
const storage = getPersist() ? localStorage : sessionStorage
storage.setItem('dgray_uuid', uuid)
}
/**
@@ -235,16 +242,30 @@ class AuthService {
* @returns {string|null}
*/
getStoredUuid() {
return localStorage.getItem('dgray_uuid')
return sessionStorage.getItem('dgray_uuid') || localStorage.getItem('dgray_uuid')
}
/**
* Clears stored UUID
*/
clearStoredUuid() {
sessionStorage.removeItem('dgray_uuid')
localStorage.removeItem('dgray_uuid')
}
setRememberMe(value) {
setPersist(value)
if (value) {
localStorage.setItem('dgray_remember', '1')
} else {
localStorage.removeItem('dgray_remember')
}
}
getRememberMe() {
return localStorage.getItem('dgray_remember') === '1'
}
/**
* Subscribe to auth state changes
* @param {Function} callback

View File

@@ -1,5 +1,19 @@
const DIRECTUS_URL = 'https://api.dgray.io'
let _persist = false
export function setPersist(value) {
_persist = value
}
export function getPersist() {
return _persist
}
function _storage() {
return _persist ? localStorage : sessionStorage
}
class DirectusError extends Error {
constructor(status, message, data = {}) {
super(message)
@@ -37,13 +51,16 @@ class DirectusClient {
// ── Token Management ──
loadTokens() {
const stored = localStorage.getItem('dgray_auth')
const stored = sessionStorage.getItem('dgray_auth') || localStorage.getItem('dgray_auth')
if (stored) {
try {
const { accessToken, refreshToken, expiry } = JSON.parse(stored)
this.accessToken = accessToken
this.refreshToken = refreshToken
this.tokenExpiry = expiry
if (localStorage.getItem('dgray_auth')) {
_persist = true
}
this.scheduleTokenRefresh()
} catch (e) {
this.clearTokens()
@@ -56,7 +73,7 @@ class DirectusClient {
this.refreshToken = refreshToken
this.tokenExpiry = Date.now() + (expiresIn * 1000)
localStorage.setItem('dgray_auth', JSON.stringify({
_storage().setItem('dgray_auth', JSON.stringify({
accessToken: this.accessToken,
refreshToken: this.refreshToken,
expiry: this.tokenExpiry
@@ -69,6 +86,7 @@ class DirectusClient {
this.accessToken = null
this.refreshToken = null
this.tokenExpiry = null
sessionStorage.removeItem('dgray_auth')
localStorage.removeItem('dgray_auth')
if (this.refreshTimeout) {