* initial commit * add lists * update permissions * fix waypoint create * needs_full_sync for activitypub trails * fixes build issues * fix list get * further CSRF protection * update API docs * adds rate limiter * fix tiptap mentions * a bit more cleanup of main.go * Fix migration order * fixes reviewed notes * require context for activitpub server calls * improve hashing for identifier * fix copy paste error * fix sync trail/list issues * fix summit log/comment duplicates * adaptions after trail merge * fix dockerignore --------- Co-authored-by: Christian Beutel <> Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
package hooks
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"pocketbase/util"
|
|
|
|
"github.com/pocketbase/pocketbase/apis"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/tools/security"
|
|
)
|
|
|
|
func ListIntegrationHandler() func(e *core.RecordsListRequestEvent) error {
|
|
return func(e *core.RecordsListRequestEvent) error {
|
|
if e.HasSuperuserAuth() {
|
|
return e.Next()
|
|
}
|
|
for _, r := range e.Records {
|
|
|
|
err := censorIntegrationSecrets(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return e.Next()
|
|
}
|
|
}
|
|
|
|
func CreateIntegrationHandler() func(e *core.RecordEvent) error {
|
|
return func(e *core.RecordEvent) error {
|
|
err := encryptIntegrationSecrets(e.App, e.Record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return e.Next()
|
|
}
|
|
}
|
|
|
|
func CreateUpdateIntegrationSuccessHandler() func(e *core.RecordEvent) error {
|
|
return func(e *core.RecordEvent) error {
|
|
err := censorIntegrationSecrets(e.Record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return e.Next()
|
|
}
|
|
}
|
|
|
|
func UpdateIntegrationHandler() func(e *core.RecordEvent) error {
|
|
return func(e *core.RecordEvent) error {
|
|
err := encryptIntegrationSecrets(e.App, e.Record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return e.Next()
|
|
}
|
|
}
|
|
|
|
func censorIntegrationSecrets(r *core.Record) error {
|
|
secrets := map[string][]string{
|
|
"strava": {"clientSecret", "refreshToken", "accessToken", "expiresAt"},
|
|
"komoot": {"password"},
|
|
"hammerhead": {"password"},
|
|
}
|
|
for key, secretKeys := range secrets {
|
|
if integrationString := r.GetString(key); integrationString != "" {
|
|
var integration map[string]interface{}
|
|
if err := json.Unmarshal([]byte(integrationString), &integration); err != nil {
|
|
return err
|
|
}
|
|
if integration == nil {
|
|
continue
|
|
}
|
|
for _, secretKey := range secretKeys {
|
|
integration[secretKey] = ""
|
|
}
|
|
b, err := json.Marshal(integration)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.Set(key, string(b))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func encryptIntegrationSecrets(app core.App, r *core.Record) error {
|
|
encryptionKey := os.Getenv("POCKETBASE_ENCRYPTION_KEY")
|
|
if len(encryptionKey) == 0 {
|
|
return apis.NewBadRequestError("POCKETBASE_ENCRYPTION_KEY not set", nil)
|
|
}
|
|
|
|
secrets := map[string][]string{
|
|
"strava": {"clientSecret", "refreshToken", "accessToken", "expiresAt"},
|
|
"komoot": {"password"},
|
|
"hammerhead": {"password"},
|
|
}
|
|
|
|
original, _ := app.FindRecordById("integrations", r.Id)
|
|
|
|
for key, secretKeys := range secrets {
|
|
if integrationString := r.GetString(key); integrationString != "" {
|
|
var integration map[string]interface{}
|
|
if err := json.Unmarshal([]byte(integrationString), &integration); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, secretKey := range secretKeys {
|
|
// If the secret is already encrypted, we don't re-encrypt it.
|
|
// TODO: This is a bit of a hack, we should handle this in a more robust way (e.g.
|
|
// storing flag on the record or prefixing encrypted strings with enc: or smilar).
|
|
// Doing that would also potentially allow us to support key rotation in the future.
|
|
if secret, ok := integration[secretKey].(string); ok && len(secret) > 0 && !util.CanDecryptSecret(secret) {
|
|
encryptedSecret, err := security.Encrypt([]byte(secret), encryptionKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
integration[secretKey] = encryptedSecret
|
|
} else if original != nil {
|
|
|
|
originalString := original.GetString(key)
|
|
var originalIntegration map[string]interface{}
|
|
if err := json.Unmarshal([]byte(originalString), &originalIntegration); err != nil {
|
|
return err
|
|
}
|
|
if integration == nil {
|
|
continue
|
|
}
|
|
integration[secretKey] = originalIntegration[secretKey]
|
|
}
|
|
}
|
|
|
|
b, err := json.Marshal(integration)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.Set(key, string(b))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|