Let session owners reassign their session to another user

Previously a session could only be reassigned to another user via a
manual DB UPDATE. This adds it to the session edit UI for every owner of
a session (not just admins) - the ownership check in HandleUpdate
(existing.UserId == userId) already guarantees the caller owns the
session, so handing over one's own session is safe.

Backend:
- ProfileEndpoint: new GET /api/users returning a minimal user directory
  (userId/username/displayName only) for any logged-in user. The
  admin-gated /api/admin/users stays the source for sensitive fields
  (defaultPath/canUseCli/isAdmin).
- SessionEndpoint.HandleUpdate: validate the target user exists (400 if
  not) and pass allowUserReassign: true to UpdateSession.
- DatabaseService.UpdateSession: new allowUserReassign flag; only then is
  a non-empty userId applied as user_id (empty/null is ignored - a
  session must always have an owner).

Frontend:
- index.html: hidden #sessionOwnerRow with a user picker card in the
  session edit form (existing sessions only).
- cards.js: buildUserCard helper for the picker.
- session-page.js: initSessionUserPicker loads users via apiGetUsers(),
  preselects the current owner, and on an actual owner change asks for
  confirmation (irreversible - the session leaves the user's own list).
- api.js: apiGetUsers() -> /api/users.
- ARCHITECTURE.md: document /api/users.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.8 committed 2026-06-13 11:52:53 +02:00
1 parent 483aa471a1
commit b23eba32b4
8 files changed
+155 -2

No files matched your search

+11 -1
View File
@@ -112,7 +112,7 @@ public partial class DatabaseService
new { sessionId, now = DateTime.UtcNow.ToString("o") });
}
public async Task UpdateSession(string sessionId, System.Text.Json.JsonElement body, ImageService imageService = null)
public async Task UpdateSession(string sessionId, System.Text.Json.JsonElement body, ImageService imageService = null, bool allowUserReassign = false)
{
using var conn = CreateConnection();
var sets = new List<string> { "updated_at = @now" };
@@ -120,6 +120,16 @@ public partial class DatabaseService
p.Add("sessionId", sessionId);
p.Add("now", DateTime.UtcNow.ToString("o"));
// Session einem anderen Benutzer zuweisen – nur wenn explizit erlaubt (Admin).
// Leerer/null userId wird ignoriert (eine Session muss immer einen Besitzer haben).
if (allowUserReassign && body.TryGetProperty("userId", out var uid)
&& uid.ValueKind == System.Text.Json.JsonValueKind.String
&& !string.IsNullOrWhiteSpace(uid.GetString()))
{
sets.Add("user_id = @newUserId");
p.Add("newUserId", uid.GetString());
}
if (body.TryGetProperty("name", out var n)) { sets.Add("name = @name"); p.Add("name", n.GetString()); }
if (body.TryGetProperty("description", out var d)) { sets.Add("description = @desc"); p.Add("desc", d.GetString()); }
if (body.TryGetProperty("image", out var img))