feat: feedback submissions with screenshots, the hide-widget preference and its user payload key

- POST /_feedback/api/v1/{key}/submit validates as PHP, refuses non-image screenshots (ImageContentGuard copy) and stores the submission, its public screenshot and the G15Office job in one transaction
- PUT /_feedback/api/v1/me/hidden (jwt.auth) stores the caller's preference; feedback_widget_hidden joins every golem15.user payload
- preflights stay with the framework CORS layer
This commit is contained in:
Jakub Zych
2026-10-04 00:10:15 +02:00
parent b4b4135ad3
commit 92e1b4e09c
12 changed files with 1073 additions and 6 deletions

22
classes/sync_g15office.go Normal file
View File

@@ -0,0 +1,22 @@
package classes
// The G15Office sync job's contract: SubmitFeedback queues one per stored
// submission, the worker files it (SyncFeedbackToG15Office).
const (
// SyncG15OfficeKind is the River kind of the job.
SyncG15OfficeKind = "golem15.feedback.sync_g15office"
// SyncG15OfficeQueue is the job's queue.
SyncG15OfficeQueue = "feedback"
// SyncG15OfficeLabel is the summer_jobs label, the PHP job class.
SyncG15OfficeLabel = `Golem15\Feedback\Jobs\SyncFeedbackToG15Office`
// SyncG15OfficeAttempts is SyncFeedbackToG15Office::$tries.
SyncG15OfficeAttempts = 3
)
// SyncG15OfficeArgs is the job's argument: the submission to file.
type SyncG15OfficeArgs struct {
SubmissionID uint `json:"submission_id"`
}
// Kind is the River job kind.
func (SyncG15OfficeArgs) Kind() string { return SyncG15OfficeKind }