feat(accounts): implement user accounts, sessions, and dashboards
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 1m8s

Introduce Stage 4 features to support multi-user accounts, cookie-based web sessions, and personal dashboards.

Changes include:
- Adding `/register` to bootstrap the first admin account and `/login`/`/logout` for session management.
- Creating a personal dashboard (`/app`) to display owned boxes, storage usage, and upload history.
- Implementing admin user management (`/admin/users`) for generating invite links and managing user states.
- Updating the bbolt database schema to store users, sessions, invites, and collections.
- Adding `golang.org/x/crypto` for password hashing and introducing unit tests for account handlers.
This commit is contained in:
2026-05-30 15:42:35 +03:00
parent 33d26804a0
commit 9a3cb90b17
24 changed files with 1956 additions and 21 deletions

View File

@@ -90,12 +90,17 @@ svg {
.brand,
.nav-links,
.footer-links {
.footer-links,
.inline-form {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.inline-form {
margin: 0;
}
.brand {
font-weight: 650;
text-decoration: none;
@@ -171,6 +176,125 @@ h1 {
padding: 1.5rem;
}
.auth-view {
width: min(28rem, calc(100% - 2rem));
min-height: calc(100vh - 7.25rem);
margin: 0 auto;
padding: 3rem 0;
display: grid;
place-items: center;
}
.auth-card {
box-shadow: var(--shadow);
}
.kicker {
margin: 0 0 0.5rem;
color: var(--muted-foreground);
font-size: 0.76rem;
font-weight: 700;
letter-spacing: 0;
text-transform: uppercase;
}
.muted-copy,
.auth-alt {
color: var(--muted-foreground);
font-size: 0.9rem;
line-height: 1.5;
}
.stack-form {
display: grid;
gap: 0.9rem;
margin-top: 1rem;
}
.stack-form label,
.inline-controls label,
.collection-create label {
display: grid;
gap: 0.35rem;
color: var(--muted-foreground);
font-size: 0.82rem;
}
.form-error {
margin: 0;
color: #fca5a5;
font-size: 0.86rem;
}
.app-shell {
width: min(86rem, calc(100% - 2rem));
margin: 0 auto;
padding: 2rem 0;
display: grid;
grid-template-columns: 14rem minmax(0, 1fr);
gap: 1.5rem;
}
.app-sidebar {
position: sticky;
top: 5rem;
align-self: start;
display: grid;
gap: 0.5rem;
}
.sidebar-link {
padding: 0.62rem 0.75rem;
border: 1px solid transparent;
border-radius: var(--radius);
color: var(--muted-foreground);
text-decoration: none;
}
.sidebar-link:hover,
.sidebar-link.is-active {
border-color: var(--border);
background: var(--muted);
color: var(--foreground);
}
.collection-create {
display: grid;
gap: 0.6rem;
margin-top: 1rem;
}
.app-main {
min-width: 0;
display: grid;
gap: 1rem;
}
.compact-upload .drop-zone {
min-height: 11rem;
}
.dashboard-options {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.collection-tabs,
.inline-controls {
display: flex;
align-items: end;
flex-wrap: wrap;
gap: 0.65rem;
}
.inline-controls input,
.inline-controls select {
min-width: 15rem;
}
.compact-input {
width: 10rem;
}
.drop-zone {
min-height: 19rem;
display: grid;