mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-03-20 06:21:06 +02:00
added extra html escaping for the RECORD:* placeholders as extra measure in case the email are stored as plain html
This commit is contained in:
parent
3098c2dcd8
commit
e34c25858c
@ -1,8 +1,10 @@
|
|||||||
package mails
|
package mails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/mails/templates"
|
"github.com/pocketbase/pocketbase/mails/templates"
|
||||||
@ -232,6 +234,13 @@ func SendRecordChangeEmail(app core.App, authRecord *core.Record, newEmail strin
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nonescapeTypes = []string{
|
||||||
|
core.FieldTypeAutodate,
|
||||||
|
core.FieldTypeDate,
|
||||||
|
core.FieldTypeBool,
|
||||||
|
core.FieldTypeNumber,
|
||||||
|
}
|
||||||
|
|
||||||
func resolveEmailTemplate(
|
func resolveEmailTemplate(
|
||||||
app core.App,
|
app core.App,
|
||||||
authRecord *core.Record,
|
authRecord *core.Record,
|
||||||
@ -258,7 +267,15 @@ func resolveEmailTemplate(
|
|||||||
|
|
||||||
fieldPlacehodler := "{RECORD:" + field.GetName() + "}"
|
fieldPlacehodler := "{RECORD:" + field.GetName() + "}"
|
||||||
if _, ok := placeholders[fieldPlacehodler]; !ok {
|
if _, ok := placeholders[fieldPlacehodler]; !ok {
|
||||||
placeholders[fieldPlacehodler] = authRecord.Get(field.GetName())
|
val := authRecord.GetString(field.GetName())
|
||||||
|
|
||||||
|
// note: the escaping is not strictly necessary but for just in case
|
||||||
|
// the user decide to store and render the email as plain html
|
||||||
|
if !slices.Contains(nonescapeTypes, field.Type()) {
|
||||||
|
val = html.EscapeString(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
placeholders[fieldPlacehodler] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package mails_test
|
package mails_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -16,6 +17,9 @@ func TestSendRecordAuthAlert(t *testing.T) {
|
|||||||
|
|
||||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||||
|
|
||||||
|
// to test that it is escaped
|
||||||
|
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||||
|
|
||||||
err := mails.SendRecordAuthAlert(testApp, user)
|
err := mails.SendRecordAuthAlert(testApp, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -26,7 +30,7 @@ func TestSendRecordAuthAlert(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedParts := []string{
|
expectedParts := []string{
|
||||||
user.GetString("name") + "{RECORD:tokenKey}", // public and private record placeholder checks
|
html.EscapeString(user.GetString("name")) + "{RECORD:tokenKey}", // public and private record placeholder checks
|
||||||
"login to your " + testApp.Settings().Meta.AppName + " account from a new location",
|
"login to your " + testApp.Settings().Meta.AppName + " account from a new location",
|
||||||
"If this was you",
|
"If this was you",
|
||||||
"If this wasn't you",
|
"If this wasn't you",
|
||||||
@ -46,6 +50,9 @@ func TestSendRecordPasswordReset(t *testing.T) {
|
|||||||
|
|
||||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||||
|
|
||||||
|
// to test that it is escaped
|
||||||
|
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||||
|
|
||||||
err := mails.SendRecordPasswordReset(testApp, user)
|
err := mails.SendRecordPasswordReset(testApp, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -56,7 +63,7 @@ func TestSendRecordPasswordReset(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedParts := []string{
|
expectedParts := []string{
|
||||||
user.GetString("name") + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
html.EscapeString(user.GetString("name")) + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
||||||
"http://localhost:8090/_/#/auth/confirm-password-reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
"http://localhost:8090/_/#/auth/confirm-password-reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
||||||
}
|
}
|
||||||
for _, part := range expectedParts {
|
for _, part := range expectedParts {
|
||||||
@ -74,6 +81,9 @@ func TestSendRecordVerification(t *testing.T) {
|
|||||||
|
|
||||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||||
|
|
||||||
|
// to test that it is escaped
|
||||||
|
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||||
|
|
||||||
err := mails.SendRecordVerification(testApp, user)
|
err := mails.SendRecordVerification(testApp, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -84,7 +94,7 @@ func TestSendRecordVerification(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedParts := []string{
|
expectedParts := []string{
|
||||||
user.GetString("name") + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
html.EscapeString(user.GetString("name")) + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
||||||
"http://localhost:8090/_/#/auth/confirm-verification/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
"http://localhost:8090/_/#/auth/confirm-verification/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
||||||
}
|
}
|
||||||
for _, part := range expectedParts {
|
for _, part := range expectedParts {
|
||||||
@ -102,6 +112,9 @@ func TestSendRecordChangeEmail(t *testing.T) {
|
|||||||
|
|
||||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||||
|
|
||||||
|
// to test that it is escaped
|
||||||
|
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||||
|
|
||||||
err := mails.SendRecordChangeEmail(testApp, user, "new_test@example.com")
|
err := mails.SendRecordChangeEmail(testApp, user, "new_test@example.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -112,7 +125,7 @@ func TestSendRecordChangeEmail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedParts := []string{
|
expectedParts := []string{
|
||||||
user.GetString("name") + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
html.EscapeString(user.GetString("name")) + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
||||||
"http://localhost:8090/_/#/auth/confirm-email-change/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
"http://localhost:8090/_/#/auth/confirm-email-change/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.",
|
||||||
}
|
}
|
||||||
for _, part := range expectedParts {
|
for _, part := range expectedParts {
|
||||||
@ -130,6 +143,9 @@ func TestSendRecordOTP(t *testing.T) {
|
|||||||
|
|
||||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||||
|
|
||||||
|
// to test that it is escaped
|
||||||
|
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||||
|
|
||||||
err := mails.SendRecordOTP(testApp, user, "test_otp_id", "test_otp_code")
|
err := mails.SendRecordOTP(testApp, user, "test_otp_id", "test_otp_code")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -140,7 +156,7 @@ func TestSendRecordOTP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedParts := []string{
|
expectedParts := []string{
|
||||||
user.GetString("name") + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
html.EscapeString(user.GetString("name")) + "{RECORD:tokenKey}", // the record name as {RECORD:name}
|
||||||
"one-time password",
|
"one-time password",
|
||||||
"test_otp_code",
|
"test_otp_code",
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user