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:
@@ -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)$")
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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");
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren