Skip to main content
PATCH
/
api
/
threads
/
{id}
curl -X PATCH 'http://localhost:5079/api/threads/f47ac10b-58cc-4372-a567-0e02b2c3d479' \
  -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"title": "Updated Thread Title"}'
{
  "success": true,
  "message": "Thread updated successfully"
}

Authentication

Required: JWT Bearer token JWT Claims Extraction (Lines 277-281):
sub | ClaimTypes.NameIdentifier → User UUID (required)

Path Parameters

id
string
required
Thread UUIDFormat: Valid GUIDValidation: Route constraint :guid (Line 270)

Request Body

title
string
required
New thread titleValidation (Lines 305-313):
if (string.IsNullOrWhiteSpace(request?.Title)) {
    return BadRequest("Title is required");
}
Constraints:
  • MUST NOT be null
  • MUST NOT be empty string
  • MUST NOT be whitespace-only
Max Length: Not enforced by API contract (database column limit may apply)
curl -X PATCH 'http://localhost:5079/api/threads/f47ac10b-58cc-4372-a567-0e02b2c3d479' \
  -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"title": "Updated Thread Title"}'
{
  "success": true,
  "message": "Thread updated successfully"
}

Authorization

Ownership Verification (Lines 289-303):
var thread = await _threadsService.GetThreadAsync(threadId);
if (thread == null) {
    return NotFound("Thread not found");
}

if (thread.UserId != userId) {
    return 403 FORBIDDEN;
}
Permission Rules:
  • ONLY thread owner can update title
  • No delegation or sharing of update rights
  • Admins NOT exempted (no admin check in code)

Side Effects

Database Mutations (Line 315):
await _threadsService.UpdateThreadAsync(threadId, request.Title);
Tables Written:
  • UPDATE threads SET title = {request.Title}, updated_at = NOW() WHERE thread_id = {threadId}
Cascade Effects: None
  • Messages not affected
  • Thread visibility not changed
  • Ownership not changed

Permissions

Who Can Modify:
  • Thread owner only
Who Cannot Modify:
  • Other authenticated users
  • Unauthenticated users
  • Public thread viewers (even if public_sharing enabled)

Edge Cases

  1. Thread doesn’t exist: 404 (Lines 290-293)
  2. User is not owner: 403 (Lines 295-303)
  3. Title is null: 400 (Lines 305-313)
  4. Title is empty: 400 (Lines 305-313)
  5. Title is whitespace-only: 400 (Lines 305-313)
  6. Title same as current: Update proceeds (no change detection)
  7. Very long title: Not validated by controller (database may truncate or error)

Error Conditions

CodeHTTPCauseController Line
N/A401JWT missing or invalidMiddleware
N/A401User ID claim missing283-286
INVALID_REQUEST400Title null/empty/whitespace305-313
NOT_FOUND404Thread doesn’t exist290-293
FORBIDDEN403Not thread owner295-303
THREAD_UPDATE_ERROR500Service exception323-331
Exception Handling (Lines 323-331):
catch (Exception ex) {
    return StatusCode(500, new { error = ex.Message, code = "THREAD_UPDATE_ERROR" });
}

Behavioral Guarantees

Atomicity: Single UPDATE query (atomic) Idempotency: NOT idempotent
  • updated_at timestamp changes on every call
  • Even if title unchanged
Concurrency: No locking
  • Race condition possible if two updates concurrent
  • Last write wins (database-dependent)

Validation Order

  1. User ID from JWT (401 if missing)
  2. Thread existence (404 if not found)
  3. Ownership (403 if not owner)
  4. Title validation (400 if invalid)
  5. Update execution (500 if fails)
Note: Title validated AFTER ownership check (Lines 305-315)

Database Schema Impact

Column Updated: threads.title Timestamp Updated: threads.updated_at (implicit, service-level) No Triggers: Controller doesn’t document any database triggers