Commit Graph

59 Commits

Author SHA1 Message Date
2681d304e2 feat: delete-only chat moderation and embed search and resolve
- ChatContext implements golem15.chat's MessageModerator: moderator
  group members who are chat members delete in group conversations
  only, never in DMs
- GET /chat/embeds?type=deadline|class|reading&q= (members only,
  at most 20 rows, escaped ILIKE, q at most 100 characters)
- POST /chat/embeds/resolve {refs} (members only, at most 50 distinct
  refs, 8 KiB body): current data or null per ref
2026-10-26 16:07:26 +01:00
ac4c2e6f73 test: cover chat moderation and the embed endpoints
- CanModerateMessage: group conversations only, chat members only
- parseEmbedRefs, embedKey, escapeLike
- /chat/embeds and /chat/embeds/resolve: 401, 422 before the
  database, 503 without one
2026-10-26 16:05:33 +01:00
eea171cee6 feat: open realtime tokens to chat members
The connection-token route is guarded by jz.bm.realtime-access instead
of presentations.realtime-owner: chat-group members get a token, and
when golem15.presentations is active so does everyone its owner guard
lets through (looked up by name among the activated plugins, no import).
Everyone else gets 401, 403 or 503 in the guard's error shape. The
realtime routes mount when golem15.chat or golem15.presentations is
active. /_chat, /_chatchannels and /_chatbots are reserved prefixes of
the student app.
2026-10-26 15:49:29 +01:00
cb7ba7ec8a test: cover the realtime access guard and chat prefixes
jz.bm.realtime-access admits chat-group members and, through
golem15.presentations' owner guard, presentation owners; everyone else
gets 401, 403 or 503 with Cache-Control no-cache, private. /_chat,
/_chatchannels and /_chatbots are reserved for the APIs.
2026-10-26 15:48:07 +01:00
0642fb1d08 feat: chat bootstrap, members and group sync
GET /_bm/api/v1/chat gives a chat-group member ogólny (the bm/1 group
conversation, adopted once as the system default channel under an
advisory lock), its unread and mention counts, the member's DMs newest
message first, the moderator flag and the composer limits. Every member
bootstrap syncs participants with the group: missing members join
ogólny, users no longer in the group lose their rows in every bm/1
conversation. A non-member gets only member:false and is pruned.

GET /_bm/api/v1/chat/members lists members (id, name, surname, handle,
is_bot from golem15.chatbots when active) and assigns missing handles;
non-members get 404.

The chatchannels access policy (ChatAccess) is installed from a
database hook: bm/1 for members only, nobody manages channels.
bm:chat-sync creates the groups when missing, syncs and assigns
handles. Migration 20261026130000_seed_jz_bm_chat_groups creates
studenci and moderatorzy without members; its rollback keeps them.
2026-10-26 15:46:13 +01:00
07d67be1e7 test: cover the chat access policy and bootstrap guards
ChatAccess admits only chat-group members to context bm/1 and manages
nothing; the chat context oversees nothing and its loader knows only
id 1; /chat and /chat/members need a caller and a database. The
migration count rises to 15 for the chat group seed.
2026-10-26 15:42:53 +01:00
64601f6817 feat: host the BM chat context
When golem15.chat is active, Boot registers the context alias bm (id 1)
on its registry. Membership is the user group jz.bm.chat.group (default
studenci); CanOverseeChats is always false, so nobody reads other
people's DMs or edits their messages; the broadcast channel is
chat:context:1, never empty.

GET /_bm/api/v1/chat answers the caller's membership behind jwt.auth and
the per-user bucket jz.bm.chat (240 a minute). The chat config block
(group, moderator_group, max_upload_bytes, max_embeds) is added. jz.bm
still Requires only golem15.user; all chat wiring is gated by HasPlugin.
2026-10-26 15:40:44 +01:00
67806f49a7 build: frontend with the owned-only readings filter 2026-10-26 11:19:22 +01:00
b4abf2630a build: frontend with the owned checkbox on readings 2026-10-26 11:12:08 +01:00
cf84f1d0e8 feat: per-student owned flag on readings
- new table jz_bm_reading_ownership and its migration
  20261026120000_create_jz_bm_reading_ownership
- PUT and DELETE /_bm/api/v1/readings/{id}/owned, idempotent
- owned_at on every reading in /readings and /courses/{id}
- read semantics, progress routes and counts unchanged
2026-10-26 11:11:22 +01:00
Jakub Zych
85cae45cb9 build: frontend with Microsoft 365 sign-in
The student app's login page offers Microsoft 365 when the provider is
configured, /auth/oauth/callback redeems the one-time code, a consent
screen finishes a first sign-in, the profile attaches Microsoft through
a link ticket, and the service worker leaves /oauth alone. The build
also carries the summer presentation theme already committed in the
frontend sources.
2026-10-21 00:23:38 +02:00
Jakub Zych
438c0b9761 fix: reserve /oauth for social sign-in
The SPA fallback no longer answers /oauth and the paths below it with
index.html, so golem15.sociallogin's start and provider callback routes
reach the backend; /oauthy is still a client route.
2026-10-21 00:15:31 +02:00
Jakub Zych
2536bcb959 Management API: record routes for courses, meetings, class sessions, readings and deadlines (Fillable + Rules + TemporalErrors, PATCH, filters) 2026-10-17 18:05:39 +02:00
Jakub Zych
996b4d1542 Management API: POST/DELETE /materials/{id}/files (attach.Store, 50 MB, 20 files), DELETE /materials/{id} removes files; download keeps the file name 2026-10-17 17:53:22 +02:00
Jakub Zych
584d15257c Sylabusy: PDF-y w public/sylabusy, typ application/pdf w serwerze statycznym 2026-10-17 12:06:24 +02:00
Jakub Zych
76f559b6d9 build: rebuild the student app (multi-line course descriptions) 2026-10-17 12:01:15 +02:00
Jakub Zych
ebd9117f8c feat: lecturer on class sessions and in the session course ref
The schedule showed a lecturer only where the session notes named one
(Globalizacja), so the student plan had nobody under the other courses.
The session JSON now carries the course lecturer in its course ref and an
optional per-session lecturer (new nullable column, admin field, seed key)
for courses shared between two people. The student app shows the
session's own lecturer or, failing that, the course's.
2026-10-17 11:20:11 +02:00
Jakub Zych
d2096e2128 feat(manage): GET and PUT /api/v1/bm/materials/{id}
The management API could only upsert a material on its title and course,
so a renamed note became a second material. PUT /materials/{id} applies the
same body to one material (422 when the new title and course belong to
another one), GET /materials/{id} shows a draft or published material with
its public files, and the upsert, update and validation share one path.
The README documents the management API.
2026-10-16 20:40:47 +02:00
Jakub Zych
2a8cdac282 public: slide counter in the public deck toolbar 2026-10-16 00:44:06 +02:00
Jakub Zych
b32668029c build: rebuild the student app (deadline card padding) 2026-10-15 23:23:16 +02:00
Jakub Zych
67e04b3101 build: rebuild the student app (deck themes, scheme switch) 2026-10-13 10:18:10 +02:00
Jakub Zych
b86cbbcd2d build: rebuild the student app (pwa) 2026-10-09 02:47:29 +02:00
Jakub Zych
a406a514d3 build: rebuild the student app (title-slide notes, pilot key order) 2026-10-09 02:31:53 +02:00
Jakub Zych
9aa620f975 build: rebuild the student app (phone remote review fixes) 2026-10-08 18:53:25 +02:00
Jakub Zych
5563e080cf fix: stop throttling the realtime subscribe proxy
Centrifugo calls the proxy from 127.0.0.1 for every client, so the
per-IP fallback put every subscribe into one bucket that any token
holder could exhaust. Throttle only the token route, per user.
2026-10-08 18:47:20 +02:00
Jakub Zych
2365bf6df9 build: rebuild the student app (phone remote layout) 2026-10-08 18:26:12 +02:00
Jakub Zych
e0a60e0f35 build: rebuild the student app (phone remote) 2026-10-08 18:14:15 +02:00
Jakub Zych
a740373b0e feat: wire the lighthouse realtime service
- Boot builds the realtime service and installs the user lookup
- the Centrifugo driver ships with the app; config keeps the null driver
- token and subscribe-proxy routes mount only with golem15.presentations,
  the token route behind presentations.realtime-owner
- jz.bm.realtime per-user throttle bucket and websockets:health
2026-10-08 17:53:54 +02:00
Jakub Zych
4b36eb940d build: rebuild the student app (speaker clock fix) 2026-10-08 14:01:00 +02:00
Jakub Zych
977b380f70 fix: stop prev-slide focus outline from slicing the deck 2026-10-06 23:45:21 +02:00
Jakub Zych
904c7b07d5 fix: pin dark lecture tokens in the deck viewer 2026-10-06 23:37:15 +02:00
Jakub Zych
8aefdab027 fix: follow system dark scheme in the deck viewer 2026-10-06 23:29:46 +02:00
Jakub Zych
30c424c814 build: rebuild presentation viewer 2026-10-06 22:42:04 +02:00
Jakub Zych
3f4829a6f2 feat(02-03): bundle the speaker clock and images
- Private toolbar and clock stay in the speaker chunk
- Speaker image fetches are not part of the public view
2026-10-06 19:36:03 +02:00
Jakub Zych
febf74c6c9 feat(02-03): bundle the owner list and speaker route
- The shell includes Moje prezentacje and the bare speaker tab
- Speaker copy stays in its own chunk, off the public deck
2026-10-06 19:20:10 +02:00
Jakub Zych
2eb9dfccd2 feat(02-02): bundle the public toolbar and reading layout
- rebuild the visitor assets with local fonts
- drop the previous hashed bundles replaced by this build
2026-10-06 18:46:46 +02:00
Jakub Zych
913fddb36b feat(02-02): bundle the public deck without external fonts
- Rebuild the embedded student app with self-hosted font files
- Drop the previous hashed assets replaced by this build
2026-10-06 18:35:49 +02:00
Jakub Zych
30df20c48d feat(02-01): gate the public presentation path
- 404 /_presentations before the SPA shell
- serve /prezentacje/{slugHash} only when presentations is active
- rebuild the embedded student app
2026-10-06 18:14:24 +02:00
Jakub Zych
9986df32a4 test(02-01): add failing test for the presentations prefix
- /_presentations must be a plain 404, not the SPA shell
- A router without the presentations plugin has no public document route
2026-10-06 18:05:09 +02:00
Jakub Zych
840935d22d refactor: drop the quiz import and the golem15.quizzes dependency
golem15.quizzes now serves its own import at /api/v1/quizzes/import behind
the same shared API token.
2026-10-04 23:15:01 +02:00
Jakub Zych
97000dcd1e feat: add the management API behind the shared golem15.user API token
Serve /api/v1/bm (seed, quiz import, materials, courses, me) behind
user.api_token, user.scope and user.permission. jz.bm now requires
golem15.quizzes for the quiz import.
2026-10-04 23:11:21 +02:00
Jakub Zych
71b848a376 Adopt SummerCMS v0.1.1 admin features
Datepickers on native time.Time / lagoon.Date fields, file uploads on
materials, readings and class sessions managed from the course form
(course_id made nullable).
2026-10-03 06:03:34 +02:00
Jakub Zych
ac2e2ddd7b build: add the calendar feed section to the profile 2026-10-02 17:42:16 +02:00
Jakub Zych
57e4ff7cea docs: document the calendar feed routes and jz.bm.public_url 2026-10-02 17:38:48 +02:00
Jakub Zych
b39f627fe3 test: cover the ICS writer and the calendar feed routes 2026-10-02 17:38:48 +02:00
Jakub Zych
90247a460d feat: serve a subscribable ICS calendar feed 2026-10-02 17:38:48 +02:00
Jakub Zych
bccb747171 feat: add the calendar feed model and migration 2026-10-02 17:38:48 +02:00
Jakub Zych
28f68d002f feat: add --prune and a rolled-back --dry-run to bm:seed 2026-10-02 17:28:07 +02:00
Jakub Zych
e8411adac3 build: redirect the old /quiz address to the review quiz 2026-10-02 15:30:00 +02:00
Jakub Zych
7110b1ab12 build: reveal quiz answers locally 2026-10-02 14:45:16 +02:00