Refactor: Name-Feld entfernen, Email als einziger Identifier

- Name-Spalte aus Nutzertabelle entfernt
- Anzeigename-Feld aus Nutzer-Anlegen-Dialog entfernt
- Username wird automatisch aus Email-Prefix generiert
- UserCreate Model: username jetzt optional

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-03-05 18:55:30 +01:00
Ursprung e5a11d3549
Commit af6040cbf6
4 geänderte Dateien mit 5 neuen und 11 gelöschten Zeilen

Datei anzeigen

@@ -56,7 +56,7 @@ class LicenseResponse(BaseModel):
class UserCreate(BaseModel):
email: str = Field(min_length=3, max_length=200)
username: str = Field(min_length=1, max_length=100)
username: Optional[str] = Field(default=None, max_length=100)
role: str = Field(default="member", pattern="^(org_admin|member)$")

Datei anzeigen

@@ -66,11 +66,12 @@ async def create_user(
if await cursor.fetchone():
raise HTTPException(status_code=400, detail="E-Mail bereits vergeben")
username = data.username if data.username else email.split("@")[0]
now = datetime.now(timezone.utc).isoformat()
cursor = await db.execute(
"""INSERT INTO users (email, username, password_hash, organization_id, role, is_active, created_at)
VALUES (?, ?, '', ?, ?, 1, ?)""",
(email, data.username, org_id, data.role, now),
(email, username, org_id, data.role, now),
)
user_id = cursor.lastrowid
@@ -91,7 +92,7 @@ async def create_user(
from email_utils.sender import send_email
from email_utils.templates import invite_email
link = f"{MAGIC_LINK_BASE_URL}/auth/verify?token={token}"
subject, html = invite_email(data.username, org["name"], code, link)
subject, html = invite_email(username, org["name"], code, link)
await send_email(email, subject, html)
except Exception:
pass # E-Mail-Fehler nicht fatal

Datei anzeigen

@@ -101,7 +101,6 @@
<thead>
<tr>
<th>E-Mail</th>
<th>Name</th>
<th>Rolle</th>
<th>Status</th>
<th>Aktionen</th>
@@ -234,10 +233,6 @@
<label for="newUserEmail">E-Mail</label>
<input type="email" id="newUserEmail" required>
</div>
<div class="form-group">
<label for="newUserName">Anzeigename</label>
<input type="text" id="newUserName" required>
</div>
<div class="form-group">
<label for="newUserRole">Rolle</label>
<select id="newUserRole">

Datei anzeigen

@@ -232,13 +232,12 @@ async function loadOrgUsers(orgId) {
const tbody = document.getElementById("userTable");
if (users.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" class="text-muted">Keine Nutzer</td></tr>';
tbody.innerHTML = '<tr><td colspan="4" class="text-muted">Keine Nutzer</td></tr>';
return;
}
tbody.innerHTML = users.map(u => `
<tr>
<td>${esc(u.email)}</td>
<td>${esc(u.username)}</td>
<td>
<select class="btn btn-secondary btn-small" onchange="changeRole(${u.id}, this.value)" style="padding: 4px 8px;">
<option value="member" ${u.role === "member" ? "selected" : ""}>Mitglied</option>
@@ -426,7 +425,6 @@ function setupForms() {
try {
await API.post(`/api/users?org_id=${currentOrgId}`, {
email: document.getElementById("newUserEmail").value,
username: document.getElementById("newUserName").value,
role: document.getElementById("newUserRole").value,
});
closeModal("modalNewUser");