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

View File

@@ -7,18 +7,22 @@
package feedback
import (
"context"
"embed"
"errors"
"io/fs"
"net/http"
"time"
"git.golem15.com/golem15/sm-feedback-plugin/models"
"git.golem15.com/golem15/sm-feedback-plugin/updates"
userclasses "git.golem15.com/golem15/sm-user-plugin/classes"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/pact"
"git.golem15.com/golem15/summercms/modules/party"
"git.golem15.com/golem15/summercms/modules/surf"
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)
var (
@@ -61,9 +65,28 @@ func (p *Plugin) Register(app *backpack.App) error {
return nil
}
// Boot keeps the application.
// Boot keeps the application and adds feedback_widget_hidden to every
// golem15.user payload (fetch, login, update...): the user's preference,
// false without a row. The user plugin itself is never changed.
func (p *Plugin) Boot(app *backpack.App) error {
p.app = app
if app != nil && app.Events != nil {
app.Events.Listen[*userclasses.GetApiArrayEvent]("golem15.feedback", func(ctx context.Context, e *userclasses.GetApiArrayEvent) error {
if e == nil || e.User == nil {
return nil
}
gdb, ok := app.Lookup[*gorm.DB]()
if !ok || gdb == nil {
return errors.New("feedback: user payload listener has no database")
}
hidden, err := models.IsWidgetHidden(ctx, gdb, e.User.ID)
if err != nil {
return err
}
e.Collected()["feedback_widget_hidden"] = hidden
return nil
})
}
return nil
}