From 07727dbde6b3e2a6d827b9995e72c032a06ad3d9 Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Thu, 2 Mar 2023 15:15:00 +0200
Subject: [PATCH 1/8] [#1956] normalized _requests.method to UPPERCASE
---
CHANGELOG.md | 5 +++++
apis/middlewares.go | 2 +-
.../logs/1677760279_uppsercase_method.go | 18 ++++++++++++++++++
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 migrations/logs/1677760279_uppsercase_method.go
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99844924..39b5a4b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## (WIP) v0.14.0
+
+- Normalized the request logs `method` value to UPPERCASE, eg. "get" => "GET" ([#1956](https://github.com/pocketbase/pocketbase/discussions/1956)).
+
+
## v0.13.0
- Added new "View" collection type allowing you to create a read-only collection from a custom SQL `SELECT` statement. It supports:
diff --git a/apis/middlewares.go b/apis/middlewares.go
index b0561dca..a1c0a51d 100644
--- a/apis/middlewares.go
+++ b/apis/middlewares.go
@@ -321,7 +321,7 @@ func ActivityLogger(app core.App) echo.MiddlewareFunc {
model := &models.Request{
Url: httpRequest.URL.RequestURI(),
- Method: strings.ToLower(httpRequest.Method),
+ Method: strings.ToUpper(httpRequest.Method),
Status: status,
Auth: requestAuth,
UserIp: realUserIp(httpRequest, ip),
diff --git a/migrations/logs/1677760279_uppsercase_method.go b/migrations/logs/1677760279_uppsercase_method.go
new file mode 100644
index 00000000..459b4bff
--- /dev/null
+++ b/migrations/logs/1677760279_uppsercase_method.go
@@ -0,0 +1,18 @@
+package logs
+
+import (
+ "github.com/pocketbase/dbx"
+)
+
+// This migrations converts all logs "method" valus to all UPPERCASE (eg. "get" => "GET").
+func init() {
+ LogsMigrations.Register(func(db dbx.Builder) error {
+ _, err := db.NewQuery("UPDATE {{_requests}} SET method=UPPER(method)").Execute()
+
+ return err
+ }, func(db dbx.Builder) error {
+ _, err := db.NewQuery("UPDATE {{_requests}} SET method=LOWER(method)").Execute()
+
+ return err
+ })
+}
From 56a77fd5ff54ac11ee143e8e2a36574e65c65cfb Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Thu, 2 Mar 2023 15:16:47 +0200
Subject: [PATCH 2/8] updated migrations comment
---
migrations/logs/1677760279_uppsercase_method.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/migrations/logs/1677760279_uppsercase_method.go b/migrations/logs/1677760279_uppsercase_method.go
index 459b4bff..cef96960 100644
--- a/migrations/logs/1677760279_uppsercase_method.go
+++ b/migrations/logs/1677760279_uppsercase_method.go
@@ -4,7 +4,7 @@ import (
"github.com/pocketbase/dbx"
)
-// This migrations converts all logs "method" valus to all UPPERCASE (eg. "get" => "GET").
+// This migration normalizes the request logs method to UPPERCASE (eg. "get" => "GET").
func init() {
LogsMigrations.Register(func(db dbx.Builder) error {
_, err := db.NewQuery("UPDATE {{_requests}} SET method=UPPER(method)").Execute()
From 19faa0d8e73505f728a5a17366119999ef7b4f86 Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Thu, 2 Mar 2023 16:10:56 +0200
Subject: [PATCH 3/8] updated calendar styles
---
ui/src/scss/_flatpickr.scss | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/ui/src/scss/_flatpickr.scss b/ui/src/scss/_flatpickr.scss
index 5a38e84a..e9a671a5 100644
--- a/ui/src/scss/_flatpickr.scss
+++ b/ui/src/scss/_flatpickr.scss
@@ -21,7 +21,9 @@
input, select {
box-shadow: none;
min-height: 0;
- height: var(--inputHeight);
+ height: var(--smBtnHeight);
+ padding-top: 3px;
+ padding-bottom: 3px;
background: none;
border-radius: var(--baseRadius);
border: 1px solid var(--baseAlt1Color);
@@ -143,13 +145,16 @@
}
.flatpickr-months {
display: flex;
- margin: 0 0 4px;
+ align-items: center;
+ padding: 5px 0;
}
.flatpickr-months .flatpickr-month {
+ display: flex;
+ align-items: center;
+ justify-content: center;
background: transparent;
color: var(--txtPrimaryColor);
fill: var(--txtPrimaryColor);
- height: 34px;
line-height: 1;
text-align: center;
position: relative;
@@ -164,12 +169,12 @@
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
+ display: flex;
+ align-items: center;
text-decoration: none;
cursor: pointer;
- position: absolute;
- top: 0;
height: 34px;
- padding: 10px;
+ padding: 5px 12px;
z-index: 3;
color: var(--txtPrimaryColor);
fill: var(--txtPrimaryColor);
@@ -210,6 +215,7 @@
.numInputWrapper {
position: relative;
height: auto;
+ border-radius: var(--baseRadius);
}
.numInputWrapper input,
.numInputWrapper span {
@@ -276,7 +282,7 @@
fill: rgba(0,0,0,0.5);
}
.numInputWrapper:hover {
- background: var(--baseAlt2Color);
+ background: var(--baseAlt1Color);
}
.numInputWrapper:hover span {
opacity: 1;
@@ -284,12 +290,11 @@
.flatpickr-current-month {
line-height: inherit;
color: inherit;
- position: absolute;
- width: 75%;
- left: 12.5%;
+ width: 85%;
padding: 1px 0;
line-height: 1;
display: flex;
+ gap: 10px;
align-items: center;
justify-content: center;
text-align: center;
@@ -303,14 +308,13 @@
padding: 0;
}
.flatpickr-current-month span.cur-month:hover {
- background: var(--baseAlt2Color);
+ background: var(--baseAlt1Color);
}
.flatpickr-current-month .numInputWrapper {
display: inline-flex;
align-items: center;
justify-content: center;
- width: 63px;
- margin: 0 5px;
+ width: 62px;
}
.flatpickr-current-month .numInputWrapper span.arrowUp:after {
border-bottom-color: var(--txtPrimaryColor);
@@ -362,7 +366,7 @@
outline: none;
}
.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
- background: var(--baseAlt2Color);
+ background: var(--baseAlt1Color);
}
.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
background-color: transparent;
From a67c14c3688f145fce48a2ba2f3da3f3140cd290 Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Thu, 2 Mar 2023 18:56:18 +0200
Subject: [PATCH 4/8] added support for @request.headers.*
---
apis/record_helpers.go | 15 ++++++++++++---
apis/record_helpers_test.go | 7 +++++++
models/request_data.go | 11 ++++++-----
resolvers/record_field_resolver.go | 3 +++
resolvers/record_field_resolver_test.go | 11 +++++++++++
.../base/FilterAutocompleteInput.svelte | 1 +
.../collections/CollectionRulesTab.svelte | 2 +-
7 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/apis/record_helpers.go b/apis/record_helpers.go
index 96e7de31..d8e9ad75 100644
--- a/apis/record_helpers.go
+++ b/apis/record_helpers.go
@@ -30,9 +30,18 @@ func RequestData(c echo.Context) *models.RequestData {
}
result := &models.RequestData{
- Method: c.Request().Method,
- Query: map[string]any{},
- Data: map[string]any{},
+ Method: c.Request().Method,
+ Query: map[string]any{},
+ Data: map[string]any{},
+ Headers: map[string]string{},
+ }
+
+ // extract the first value of all headers and normalizes the keys
+ // ("X-Token" is converted to "x_token")
+ for k, v := range c.Request().Header {
+ if len(v) > 0 {
+ result.Headers[strings.ToLower(strings.ReplaceAll(k, "-", "_"))] = v[0]
+ }
}
result.AuthRecord, _ = c.Get(ContextAuthRecordKey).(*models.Record)
diff --git a/apis/record_helpers_test.go b/apis/record_helpers_test.go
index 7f96c2ff..765182ce 100644
--- a/apis/record_helpers_test.go
+++ b/apis/record_helpers_test.go
@@ -17,6 +17,7 @@ func TestRequestData(t *testing.T) {
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/?test=123", strings.NewReader(`{"test":456}`))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
+ req.Header.Set("X-Token-Test", "123")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
@@ -38,6 +39,12 @@ func TestRequestData(t *testing.T) {
t.Fatalf("Expected Method %v, got %v", http.MethodPost, result.Method)
}
+ rawHeaders, _ := json.Marshal(result.Headers)
+ expectedHeaders := `{"content_type":"application/json","x_token_test":"123"}`
+ if v := string(rawHeaders); v != expectedHeaders {
+ t.Fatalf("Expected Query %v, got %v", expectedHeaders, v)
+ }
+
rawQuery, _ := json.Marshal(result.Query)
expectedQuery := `{"test":"123"}`
if v := string(rawQuery); v != expectedQuery {
diff --git a/models/request_data.go b/models/request_data.go
index 693795c3..e574c0c7 100644
--- a/models/request_data.go
+++ b/models/request_data.go
@@ -9,11 +9,12 @@ import (
// RequestData defines a HTTP request data struct, usually used
// as part of the `@request.*` filter resolver.
type RequestData struct {
- Method string `json:"method"`
- Query map[string]any `json:"query"`
- Data map[string]any `json:"data"`
- AuthRecord *Record `json:"authRecord"`
- Admin *Admin `json:"admin"`
+ Method string `json:"method"`
+ Query map[string]any `json:"query"`
+ Data map[string]any `json:"data"`
+ Headers map[string]string `json:"headers"`
+ AuthRecord *Record `json:"authRecord"`
+ Admin *Admin `json:"admin"`
}
// HasModifierDataKeys loosely checks if the current struct has any modifier Data keys.
diff --git a/resolvers/record_field_resolver.go b/resolvers/record_field_resolver.go
index 220abbfe..9bd18af2 100644
--- a/resolvers/record_field_resolver.go
+++ b/resolvers/record_field_resolver.go
@@ -84,6 +84,7 @@ func NewRecordFieldResolver(
`^\@request\.auth\.[\w\.\:]*\w+$`,
`^\@request\.data\.[\w\.\:]*\w+$`,
`^\@request\.query\.[\w\.\:]*\w+$`,
+ `^\@request\.headers\.\w+$`,
`^\@collection\.\w+\.[\w\.\:]*\w+$`,
},
}
@@ -92,6 +93,7 @@ func NewRecordFieldResolver(
if r.requestData != nil {
r.staticRequestData["method"] = r.requestData.Method
r.staticRequestData["query"] = r.requestData.Query
+ r.staticRequestData["headers"] = r.requestData.Headers
r.staticRequestData["data"] = r.requestData.Data
r.staticRequestData["auth"] = nil
if r.requestData.AuthRecord != nil {
@@ -132,6 +134,7 @@ func (r *RecordFieldResolver) UpdateQuery(query *dbx.SelectQuery) error {
// project.screen.status
// @request.status
// @request.query.filter
+// @request.headers.x_token
// @request.auth.someRelation.name
// @request.data.someRelation.name
// @request.data.someField
diff --git a/resolvers/record_field_resolver_test.go b/resolvers/record_field_resolver_test.go
index 206e32c4..28d6d34c 100644
--- a/resolvers/record_field_resolver_test.go
+++ b/resolvers/record_field_resolver_test.go
@@ -23,6 +23,10 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
}
requestData := &models.RequestData{
+ Headers: map[string]string{
+ "a": "123",
+ "b": "456",
+ },
Query: map[string]any{
"a": nil,
"b": 123,
@@ -438,6 +442,9 @@ func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
"b": 456,
"c": map[string]int{"sub": 1},
},
+ Headers: map[string]string{
+ "d": "789",
+ },
AuthRecord: authRecord,
}
@@ -456,6 +463,10 @@ func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
{"@request.query", true, ``},
{"@request.query.a", false, `123`},
{"@request.query.a.missing", false, ``},
+ {"@request.headers", true, ``},
+ {"@request.headers.missing", false, ``},
+ {"@request.headers.d", false, `456`},
+ {"@request.headers.d.sub", true, ``},
{"@request.data", true, ``},
{"@request.data.b", false, `456`},
{"@request.data.number", false, `10`}, // number field normalization
diff --git a/ui/src/components/base/FilterAutocompleteInput.svelte b/ui/src/components/base/FilterAutocompleteInput.svelte
index 4e8e6c0d..152979ee 100644
--- a/ui/src/components/base/FilterAutocompleteInput.svelte
+++ b/ui/src/components/base/FilterAutocompleteInput.svelte
@@ -256,6 +256,7 @@
result.push("@request.method");
result.push("@request.query.");
result.push("@request.data.");
+ result.push("@request.headers.");
result.push("@request.auth.id");
result.push("@request.auth.collectionId");
result.push("@request.auth.collectionName");
diff --git a/ui/src/components/collections/CollectionRulesTab.svelte b/ui/src/components/collections/CollectionRulesTab.svelte
index 6fcfed3c..74ece011 100644
--- a/ui/src/components/collections/CollectionRulesTab.svelte
+++ b/ui/src/components/collections/CollectionRulesTab.svelte
@@ -45,7 +45,7 @@
The request fields could be accessed with the special @request filter:
-
@request.method
+
@request.headers.*
@request.query.*
@request.data.*
@request.auth.*
From e8d61e7b45e734d2c4c42d6c645d187796eec3bd Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Sat, 4 Mar 2023 13:05:55 +0200
Subject: [PATCH 5/8] simplified rules ui
---
.../collections/CollectionRulesTab.svelte | 5 -----
ui/src/components/collections/RuleField.svelte | 15 +++------------
2 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/ui/src/components/collections/CollectionRulesTab.svelte b/ui/src/components/collections/CollectionRulesTab.svelte
index 74ece011..eb5f0a0d 100644
--- a/ui/src/components/collections/CollectionRulesTab.svelte
+++ b/ui/src/components/collections/CollectionRulesTab.svelte
@@ -77,22 +77,17 @@
-
{#if !collection?.isView}
-
-
-
{/if}
{#if collection?.isAuth}
-
{:else}
@@ -93,20 +93,11 @@
bind:value={rule}
baseCollection={collection}
disabled={isAdminOnly}
+ placeholder={!isAdminOnly ? "Leave empty to grant everyone access..." : ""}
/>
-
-
- {#if isAdminOnly}
- Only admins will be able to perform this action (
-
- ).
- {:else}
- Leave empty to grant everyone access.
- {/if}
-
-
+
{/if}
From 01f0af7af634c52535528e975856a2595f0645de Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Sat, 4 Mar 2023 13:06:15 +0200
Subject: [PATCH 6/8] added errors slide transition
---
ui/src/components/base/Field.svelte | 3 ++-
ui/src/scss/_alert.scss | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/ui/src/components/base/Field.svelte b/ui/src/components/base/Field.svelte
index 122ef0ef..a9b8c033 100644
--- a/ui/src/components/base/Field.svelte
+++ b/ui/src/components/base/Field.svelte
@@ -1,5 +1,6 @@
-
+