Complete TODO items: security, features, polish

Security:
- Encrypt Gitea tokens at rest (AES-256-GCM with MH_SECRET)
- Secure cookie flag when behind HTTPS (X-Forwarded-Proto)
- Password complexity (min 8 chars)
- TOTP: defer persist until verified (totp_pending column)
- Audit log table + logging on login/rename/password change

Features:
- Rename files/folders (double-click in tree, /api/files/rename)
- beforeunload warning for unsaved changes
- Mobile hamburger menu
- PWA icons (192px, 512px)
- Max file size enforcement (10MB)
- Shared file read access (cross-user with permission check)

Polish:
- Toast notifications replace all alert() calls
- Keyboard shortcut help overlay (Ctrl+/)
- File rename via double-click in FileTree
This commit is contained in:
2026-05-26 23:51:02 +02:00
parent f60d223c06
commit 68eaee0b9f
12 changed files with 310 additions and 49 deletions
+30
View File
@@ -4,6 +4,8 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"errors"
"io"
@@ -15,6 +17,34 @@ func DeriveKey(password []byte, salt []byte) []byte {
return argon2.IDKey(password, salt, 3, 64*1024, 4, 32)
}
// KeyFromSecret derives a 256-bit AES key from a string secret (for token encryption).
func KeyFromSecret(secret string) []byte {
h := sha256.Sum256([]byte(secret))
return h[:]
}
// EncryptString encrypts a string and returns base64-encoded ciphertext.
func EncryptString(plaintext string, key []byte) (string, error) {
ct, err := Encrypt([]byte(plaintext), key)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(ct), nil
}
// DecryptString decrypts a base64-encoded ciphertext to a string.
func DecryptString(encoded string, key []byte) (string, error) {
ct, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return "", err
}
pt, err := Decrypt(ct, key)
if err != nil {
return "", err
}
return string(pt), nil
}
// GenerateSalt returns a random 16-byte salt.
func GenerateSalt() ([]byte, error) {
salt := make([]byte, 16)