Let the same choice open notes and drafts
The picker in the bell now governs both lists, so note_subscriptions is renamed to colleague_subscriptions -- a name that only mentions notes would mislead the next reader. Reading and writing a draft now reach differently far. hire_drafts_owner (for all) is split into four policies: select lets in your own drafts and those of the people you added, while insert/update/delete stay with the owner. A draft is unfinished work with no lock and no history; two people writing into the same row would overwrite each other silently. That split forces a change in the actions: a policy does not reject a write, it lets it hit no rows. saveHireDraft and deleteHireDraft now read the row count instead of reporting success over a row that never changed. The card shows a foreign draft with its author and without Fortsetzen or Loeschen -- offering a button that reliably ends in a database error is a promise without cover. check-schema-types.mjs learns `alter table ... rename to`; without it the drift check reports one rename as two errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
28
lib/kollegen.ts
Normal file
28
lib/kollegen.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { sql, type Expression, type SqlBool } from "kysely";
|
||||
|
||||
// Wen jemand hinzugewählt hat — die eine Regel hinter zwei Listen.
|
||||
//
|
||||
// Bis September 2026 galt die Auswahl nur für die Notizen in der Glocke; sie
|
||||
// hiess deshalb `note_subscriptions` und die Bedingung stand in lib/notes.ts.
|
||||
// Seit die Entwürfe derselben Auswahl folgen, steht sie hier: zwei Fassungen
|
||||
// derselben Regel driften auseinander, und dann zeigte die eine Liste
|
||||
// jemanden, den die andere nicht kennt.
|
||||
|
||||
/**
|
||||
* Ob `spalte` auf eine hinzugewählte Person zeigt.
|
||||
*
|
||||
* `spalte` ist der Name der Verfasserspalte in der umgebenden Abfrage
|
||||
* (`n.author_user_id`, `d.created_by`, …) — als Bezeichner eingesetzt, nicht
|
||||
* als Wert. Er kommt aus dem Quelltext, nie aus einer Eingabe; die Kennung
|
||||
* dagegen kommt aus der Sitzung und geht als Parameter mit.
|
||||
*
|
||||
* Die eigene Person steht bewusst **nicht** darin. Wer sich selbst sieht, ist
|
||||
* keine Frage der Auswahl, sondern die Vorgabe — und die Prüfbedingung
|
||||
* `chk_kollegen_abos_nicht_selbst` lässt ein Abo auf sich selbst gar nicht zu.
|
||||
* Die aufrufende Abfrage stellt „die eigenen" davor, mit ODER.
|
||||
*/
|
||||
export function istHinzugewaehlt(userId: string, spalte: string): Expression<SqlBool> {
|
||||
return sql<SqlBool>`exists (
|
||||
select 1 from colleague_subscriptions s
|
||||
where s.user_id = ${userId} and s.author_user_id = ${sql.ref(spalte)})`;
|
||||
}
|
||||
Reference in New Issue
Block a user