Skip to content

Commit

Permalink
fixed autocomplete base collection keys caching
Browse files Browse the repository at this point in the history
  • Loading branch information
ganigeorgiev committed Nov 18, 2022
1 parent 341bcc4 commit aed8367
Show file tree
Hide file tree
Showing 41 changed files with 174 additions and 159 deletions.
2 changes: 1 addition & 1 deletion apis/realtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (api *realtimeApi) canAccessRecord(client subscriptions.Client, record *mod
}

// emulate request data
requestData := &models.FilterRequestData{
requestData := &models.RequestData{
Method: "GET",
}
requestData.AuthRecord, _ = client.Get(ContextAuthRecordKey).(*models.Record)
Expand Down
4 changes: 2 additions & 2 deletions apis/record_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (api *recordAuthApi) authResponse(c echo.Context, authRecord *models.Record
expands := strings.Split(c.QueryParam(expandQueryParam), ",")
if len(expands) > 0 {
// create a copy of the cached request data and adjust it to the current auth record
requestData := *GetRequestData(e.HttpContext)
requestData := *RequestData(e.HttpContext)
requestData.Admin = nil
requestData.AuthRecord = e.Record
failed := api.app.Dao().ExpandRecord(
Expand Down Expand Up @@ -204,7 +204,7 @@ func (api *recordAuthApi) authWithOAuth2(c echo.Context) error {

record, authData, submitErr := form.Submit(func(createForm *forms.RecordUpsert, authRecord *models.Record, authUser *auth.AuthUser) error {
return createForm.DrySubmit(func(txDao *daos.Dao) error {
requestData := GetRequestData(c)
requestData := RequestData(c)
requestData.Data = form.CreateData

createRuleFunc := func(q *dbx.SelectQuery) error {
Expand Down
10 changes: 5 additions & 5 deletions apis/record_crud.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (api *recordApi) list(c echo.Context) error {
return err
}

requestData := GetRequestData(c)
requestData := RequestData(c)

if requestData.Admin == nil && collection.ListRule == nil {
// only admins can access if the rule is nil
Expand Down Expand Up @@ -110,7 +110,7 @@ func (api *recordApi) view(c echo.Context) error {
return NewNotFoundError("", nil)
}

requestData := GetRequestData(c)
requestData := RequestData(c)

if requestData.Admin == nil && collection.ViewRule == nil {
// only admins can access if the rule is nil
Expand Down Expand Up @@ -155,7 +155,7 @@ func (api *recordApi) create(c echo.Context) error {
return NewNotFoundError("", "Missing collection context.")
}

requestData := GetRequestData(c)
requestData := RequestData(c)

if requestData.Admin == nil && collection.CreateRule == nil {
// only admins can access if the rule is nil
Expand Down Expand Up @@ -251,7 +251,7 @@ func (api *recordApi) update(c echo.Context) error {
return NewNotFoundError("", nil)
}

requestData := GetRequestData(c)
requestData := RequestData(c)

if requestData.Admin == nil && collection.UpdateRule == nil {
// only admins can access if the rule is nil
Expand Down Expand Up @@ -325,7 +325,7 @@ func (api *recordApi) delete(c echo.Context) error {
return NewNotFoundError("", nil)
}

requestData := GetRequestData(c)
requestData := RequestData(c)

if requestData.Admin == nil && collection.DeleteRule == nil {
// only admins can access if the rule is nil
Expand Down
23 changes: 14 additions & 9 deletions apis/record_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,22 @@ import (

const ContextRequestDataKey = "requestData"

// GetRequestData exports common request data fields
// Deprecated: Will be removed after v0.9. Use apis.RequestData(c) instead.
func GetRequestData(c echo.Context) *models.RequestData {
return RequestData(c)
}

// RequestData exports cached common request data fields
// (query, body, logged auth state, etc.) from the provided context.
func GetRequestData(c echo.Context) *models.FilterRequestData {
// return cached to avoid reading the body multiple times
func RequestData(c echo.Context) *models.RequestData {
// return cached to avoid copying the body multiple times
if v := c.Get(ContextRequestDataKey); v != nil {
if data, ok := v.(*models.FilterRequestData); ok {
if data, ok := v.(*models.RequestData); ok {
return data
}
}

result := &models.FilterRequestData{
result := &models.RequestData{
Method: c.Request().Method,
Query: map[string]any{},
Data: map[string]any{},
Expand Down Expand Up @@ -54,7 +59,7 @@ func EnrichRecord(c echo.Context, dao *daos.Dao, record *models.Record, defaultE
// - ensures that the emails of the auth records and their expanded auth relations
// are visibe only for the current logged admin, record owner or record with manage access
func EnrichRecords(c echo.Context, dao *daos.Dao, records []*models.Record, defaultExpands ...string) error {
requestData := GetRequestData(c)
requestData := RequestData(c)

if err := autoIgnoreAuthRecordsEmailVisibility(dao, records, requestData); err != nil {
return fmt.Errorf("Failed to resolve email visibility: %v", err)
Expand All @@ -77,7 +82,7 @@ func EnrichRecords(c echo.Context, dao *daos.Dao, records []*models.Record, defa
// expandFetch is the records fetch function that is used to expand related records.
func expandFetch(
dao *daos.Dao,
requestData *models.FilterRequestData,
requestData *models.RequestData,
) daos.ExpandFetchFunc {
return func(relCollection *models.Collection, relIds []string) ([]*models.Record, error) {
records, err := dao.FindRecordsByIds(relCollection.Id, relIds, func(q *dbx.SelectQuery) error {
Expand Down Expand Up @@ -117,7 +122,7 @@ func expandFetch(
func autoIgnoreAuthRecordsEmailVisibility(
dao *daos.Dao,
records []*models.Record,
requestData *models.FilterRequestData,
requestData *models.RequestData,
) error {
if len(records) == 0 || !records[0].Collection().IsAuth() {
return nil // nothing to check
Expand Down Expand Up @@ -185,7 +190,7 @@ func autoIgnoreAuthRecordsEmailVisibility(
func hasAuthManageAccess(
dao *daos.Dao,
record *models.Record,
requestData *models.FilterRequestData,
requestData *models.RequestData,
) bool {
if !record.Collection().IsAuth() {
return false
Expand Down
6 changes: 3 additions & 3 deletions apis/record_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/pocketbase/pocketbase/tests"
)

func TestGetRequestData(t *testing.T) {
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)
Expand All @@ -28,10 +28,10 @@ func TestGetRequestData(t *testing.T) {
dummyAdmin.Id = "id2"
c.Set(apis.ContextAdminKey, dummyAdmin)

result := apis.GetRequestData(c)
result := apis.RequestData(c)

if result == nil {
t.Fatal("Expected *models.FilterRequestData instance, got nil")
t.Fatal("Expected *models.RequestData instance, got nil")
}

if result.Method != http.MethodPost {
Expand Down
2 changes: 1 addition & 1 deletion daos/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (dao *Dao) FindCollectionByNameOrId(nameOrId string) (*models.Collection, e
// IsCollectionNameUnique checks that there is no existing collection
// with the provided name (case insensitive!).
//
// Note: case sensitive check because the name is used also as a table name for the records.
// Note: case insensitive check because the name is used also as a table name for the records.
func (dao *Dao) IsCollectionNameUnique(name string, excludeIds ...string) bool {
if name == "" {
return false
Expand Down
2 changes: 1 addition & 1 deletion models/base.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package models implements all PocketBase DB models.
// Package models implements all PocketBase DB models and DTOs.
package models

import (
Expand Down
4 changes: 2 additions & 2 deletions models/filter_request_data.go → models/request_data.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package models

// FilterRequestData defines a HTTP request data struct, usually used
// RequestData defines a HTTP request data struct, usually used
// as part of the `@request.*` filter resolver.
type FilterRequestData struct {
type RequestData struct {
Method string `json:"method"`
Query map[string]any `json:"query"`
Data map[string]any `json:"data"`
Expand Down
4 changes: 2 additions & 2 deletions resolvers/record_field_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type RecordFieldResolver struct {
loadedCollections []*models.Collection
joins []join // we cannot use a map because the insertion order is not preserved
exprs []dbx.Expression
requestData *models.FilterRequestData
requestData *models.RequestData
staticRequestData map[string]any
}

Expand All @@ -67,7 +67,7 @@ type RecordFieldResolver struct {
func NewRecordFieldResolver(
dao *daos.Dao,
baseCollection *models.Collection,
requestData *models.FilterRequestData,
requestData *models.RequestData,
allowHiddenFields bool,
) *RecordFieldResolver {
r := &RecordFieldResolver{
Expand Down
6 changes: 3 additions & 3 deletions resolvers/record_field_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
t.Fatal(err)
}

requestData := &models.FilterRequestData{
requestData := &models.RequestData{
AuthRecord: authRecord,
}

Expand Down Expand Up @@ -182,7 +182,7 @@ func TestRecordFieldResolverResolveSchemaFields(t *testing.T) {
t.Fatal(err)
}

requestData := &models.FilterRequestData{
requestData := &models.RequestData{
AuthRecord: authRecord,
}

Expand Down Expand Up @@ -263,7 +263,7 @@ func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
t.Fatal(err)
}

requestData := &models.FilterRequestData{
requestData := &models.RequestData{
Method: "get",
Query: map[string]any{
"a": 123,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import{S as ke,i as be,s as ge,e as r,w as b,b as g,c as _e,f as k,g as h,h as n,m as me,x as G,P as re,Q as we,k as ve,R as Ce,n as Pe,t as J,a as Y,o as _,d as pe,L as Me,C as Se,p as $e,r as H,u as je,O as Ae}from"./index.786ddc4b.js";import{S as Be}from"./SdkTabs.af9891cd.js";function ue(a,l,o){const s=a.slice();return s[5]=l[o],s}function de(a,l,o){const s=a.slice();return s[5]=l[o],s}function fe(a,l){let o,s=l[5].code+"",m,f,i,u;function d(){return l[4](l[5])}return{key:a,first:null,c(){o=r("button"),m=b(s),f=g(),k(o,"class","tab-item"),H(o,"active",l[1]===l[5].code),this.first=o},m(v,C){h(v,o,C),n(o,m),n(o,f),i||(u=je(o,"click",d),i=!0)},p(v,C){l=v,C&4&&s!==(s=l[5].code+"")&&G(m,s),C&6&&H(o,"active",l[1]===l[5].code)},d(v){v&&_(o),i=!1,u()}}}function he(a,l){let o,s,m,f;return s=new Ae({props:{content:l[5].body}}),{key:a,first:null,c(){o=r("div"),_e(s.$$.fragment),m=g(),k(o,"class","tab-item"),H(o,"active",l[1]===l[5].code),this.first=o},m(i,u){h(i,o,u),me(s,o,null),n(o,m),f=!0},p(i,u){l=i;const d={};u&4&&(d.content=l[5].body),s.$set(d),(!f||u&6)&&H(o,"active",l[1]===l[5].code)},i(i){f||(J(s.$$.fragment,i),f=!0)},o(i){Y(s.$$.fragment,i),f=!1},d(i){i&&_(o),pe(s)}}}function Oe(a){var ae,ne;let l,o,s=a[0].name+"",m,f,i,u,d,v,C,K=a[0].name+"",U,R,q,P,D,j,W,M,N,X,Q,A,Z,V,y=a[0].name+"",I,x,L,B,E,S,O,w=[],ee=new Map,te,T,p=[],le=new Map,$;P=new Be({props:{js:`
import{S as ke,i as be,s as ge,e as r,w as b,b as g,c as _e,f as k,g as h,h as n,m as me,x as G,O as re,P as we,k as ve,Q as Ce,n as Pe,t as L,a as Y,o as _,d as pe,R as Me,C as Se,p as $e,r as H,u as je,N as Ae}from"./index.27866c98.js";import{S as Be}from"./SdkTabs.22a960f8.js";function ue(a,l,o){const s=a.slice();return s[5]=l[o],s}function de(a,l,o){const s=a.slice();return s[5]=l[o],s}function fe(a,l){let o,s=l[5].code+"",m,f,i,u;function d(){return l[4](l[5])}return{key:a,first:null,c(){o=r("button"),m=b(s),f=g(),k(o,"class","tab-item"),H(o,"active",l[1]===l[5].code),this.first=o},m(v,C){h(v,o,C),n(o,m),n(o,f),i||(u=je(o,"click",d),i=!0)},p(v,C){l=v,C&4&&s!==(s=l[5].code+"")&&G(m,s),C&6&&H(o,"active",l[1]===l[5].code)},d(v){v&&_(o),i=!1,u()}}}function he(a,l){let o,s,m,f;return s=new Ae({props:{content:l[5].body}}),{key:a,first:null,c(){o=r("div"),_e(s.$$.fragment),m=g(),k(o,"class","tab-item"),H(o,"active",l[1]===l[5].code),this.first=o},m(i,u){h(i,o,u),me(s,o,null),n(o,m),f=!0},p(i,u){l=i;const d={};u&4&&(d.content=l[5].body),s.$set(d),(!f||u&6)&&H(o,"active",l[1]===l[5].code)},i(i){f||(L(s.$$.fragment,i),f=!0)},o(i){Y(s.$$.fragment,i),f=!1},d(i){i&&_(o),pe(s)}}}function Oe(a){var ae,ne;let l,o,s=a[0].name+"",m,f,i,u,d,v,C,F=a[0].name+"",U,R,q,P,D,j,W,M,K,X,Q,A,Z,V,y=a[0].name+"",I,x,E,B,J,S,O,w=[],ee=new Map,te,T,p=[],le=new Map,$;P=new Be({props:{js:`
import PocketBase from 'pocketbase';
const pb = new PocketBase('${a[3]}');
Expand All @@ -14,7 +14,7 @@ import{S as ke,i as be,s as ge,e as r,w as b,b as g,c as _e,f as k,g as h,h as n
...
final result = await pb.collection('${(ne=a[0])==null?void 0:ne.name}').listAuthMethods();
`}});let z=a[2];const oe=e=>e[5].code;for(let e=0;e<z.length;e+=1){let t=de(a,z,e),c=oe(t);ee.set(c,w[e]=fe(c,t))}let F=a[2];const se=e=>e[5].code;for(let e=0;e<F.length;e+=1){let t=ue(a,F,e),c=se(t);le.set(c,p[e]=he(c,t))}return{c(){l=r("h3"),o=b("List auth methods ("),m=b(s),f=b(")"),i=g(),u=r("div"),d=r("p"),v=b("Returns a public list with all allowed "),C=r("strong"),U=b(K),R=b(" authentication methods."),q=g(),_e(P.$$.fragment),D=g(),j=r("h6"),j.textContent="API details",W=g(),M=r("div"),N=r("strong"),N.textContent="GET",X=g(),Q=r("div"),A=r("p"),Z=b("/api/collections/"),V=r("strong"),I=b(y),x=b("/auth-methods"),L=g(),B=r("div"),B.textContent="Responses",E=g(),S=r("div"),O=r("div");for(let e=0;e<w.length;e+=1)w[e].c();te=g(),T=r("div");for(let e=0;e<p.length;e+=1)p[e].c();k(l,"class","m-b-sm"),k(u,"class","content txt-lg m-b-sm"),k(j,"class","m-b-xs"),k(N,"class","label label-primary"),k(Q,"class","content"),k(M,"class","alert alert-info"),k(B,"class","section-title"),k(O,"class","tabs-header compact left"),k(T,"class","tabs-content"),k(S,"class","tabs")},m(e,t){h(e,l,t),n(l,o),n(l,m),n(l,f),h(e,i,t),h(e,u,t),n(u,d),n(d,v),n(d,C),n(C,U),n(d,R),h(e,q,t),me(P,e,t),h(e,D,t),h(e,j,t),h(e,W,t),h(e,M,t),n(M,N),n(M,X),n(M,Q),n(Q,A),n(A,Z),n(A,V),n(V,I),n(A,x),h(e,L,t),h(e,B,t),h(e,E,t),h(e,S,t),n(S,O);for(let c=0;c<w.length;c+=1)w[c].m(O,null);n(S,te),n(S,T);for(let c=0;c<p.length;c+=1)p[c].m(T,null);$=!0},p(e,[t]){var ie,ce;(!$||t&1)&&s!==(s=e[0].name+"")&&G(m,s),(!$||t&1)&&K!==(K=e[0].name+"")&&G(U,K);const c={};t&9&&(c.js=`
`}});let z=a[2];const oe=e=>e[5].code;for(let e=0;e<z.length;e+=1){let t=de(a,z,e),c=oe(t);ee.set(c,w[e]=fe(c,t))}let N=a[2];const se=e=>e[5].code;for(let e=0;e<N.length;e+=1){let t=ue(a,N,e),c=se(t);le.set(c,p[e]=he(c,t))}return{c(){l=r("h3"),o=b("List auth methods ("),m=b(s),f=b(")"),i=g(),u=r("div"),d=r("p"),v=b("Returns a public list with all allowed "),C=r("strong"),U=b(F),R=b(" authentication methods."),q=g(),_e(P.$$.fragment),D=g(),j=r("h6"),j.textContent="API details",W=g(),M=r("div"),K=r("strong"),K.textContent="GET",X=g(),Q=r("div"),A=r("p"),Z=b("/api/collections/"),V=r("strong"),I=b(y),x=b("/auth-methods"),E=g(),B=r("div"),B.textContent="Responses",J=g(),S=r("div"),O=r("div");for(let e=0;e<w.length;e+=1)w[e].c();te=g(),T=r("div");for(let e=0;e<p.length;e+=1)p[e].c();k(l,"class","m-b-sm"),k(u,"class","content txt-lg m-b-sm"),k(j,"class","m-b-xs"),k(K,"class","label label-primary"),k(Q,"class","content"),k(M,"class","alert alert-info"),k(B,"class","section-title"),k(O,"class","tabs-header compact left"),k(T,"class","tabs-content"),k(S,"class","tabs")},m(e,t){h(e,l,t),n(l,o),n(l,m),n(l,f),h(e,i,t),h(e,u,t),n(u,d),n(d,v),n(d,C),n(C,U),n(d,R),h(e,q,t),me(P,e,t),h(e,D,t),h(e,j,t),h(e,W,t),h(e,M,t),n(M,K),n(M,X),n(M,Q),n(Q,A),n(A,Z),n(A,V),n(V,I),n(A,x),h(e,E,t),h(e,B,t),h(e,J,t),h(e,S,t),n(S,O);for(let c=0;c<w.length;c+=1)w[c].m(O,null);n(S,te),n(S,T);for(let c=0;c<p.length;c+=1)p[c].m(T,null);$=!0},p(e,[t]){var ie,ce;(!$||t&1)&&s!==(s=e[0].name+"")&&G(m,s),(!$||t&1)&&F!==(F=e[0].name+"")&&G(U,F);const c={};t&9&&(c.js=`
import PocketBase from 'pocketbase';
const pb = new PocketBase('${e[3]}');
Expand All @@ -30,7 +30,7 @@ import{S as ke,i as be,s as ge,e as r,w as b,b as g,c as _e,f as k,g as h,h as n
...
final result = await pb.collection('${(ce=e[0])==null?void 0:ce.name}').listAuthMethods();
`),P.$set(c),(!$||t&1)&&y!==(y=e[0].name+"")&&G(I,y),t&6&&(z=e[2],w=re(w,t,oe,1,e,z,ee,O,we,fe,null,de)),t&6&&(F=e[2],ve(),p=re(p,t,se,1,e,F,le,T,Ce,he,null,ue),Pe())},i(e){if(!$){J(P.$$.fragment,e);for(let t=0;t<F.length;t+=1)J(p[t]);$=!0}},o(e){Y(P.$$.fragment,e);for(let t=0;t<p.length;t+=1)Y(p[t]);$=!1},d(e){e&&_(l),e&&_(i),e&&_(u),e&&_(q),pe(P,e),e&&_(D),e&&_(j),e&&_(W),e&&_(M),e&&_(L),e&&_(B),e&&_(E),e&&_(S);for(let t=0;t<w.length;t+=1)w[t].d();for(let t=0;t<p.length;t+=1)p[t].d()}}}function Te(a,l,o){let s,{collection:m=new Me}=l,f=200,i=[];const u=d=>o(1,f=d.code);return a.$$set=d=>{"collection"in d&&o(0,m=d.collection)},o(3,s=Se.getApiExampleUrl($e.baseUrl)),o(2,i=[{code:200,body:`
`),P.$set(c),(!$||t&1)&&y!==(y=e[0].name+"")&&G(I,y),t&6&&(z=e[2],w=re(w,t,oe,1,e,z,ee,O,we,fe,null,de)),t&6&&(N=e[2],ve(),p=re(p,t,se,1,e,N,le,T,Ce,he,null,ue),Pe())},i(e){if(!$){L(P.$$.fragment,e);for(let t=0;t<N.length;t+=1)L(p[t]);$=!0}},o(e){Y(P.$$.fragment,e);for(let t=0;t<p.length;t+=1)Y(p[t]);$=!1},d(e){e&&_(l),e&&_(i),e&&_(u),e&&_(q),pe(P,e),e&&_(D),e&&_(j),e&&_(W),e&&_(M),e&&_(E),e&&_(B),e&&_(J),e&&_(S);for(let t=0;t<w.length;t+=1)w[t].d();for(let t=0;t<p.length;t+=1)p[t].d()}}}function Te(a,l,o){let s,{collection:m=new Me}=l,f=200,i=[];const u=d=>o(1,f=d.code);return a.$$set=d=>{"collection"in d&&o(0,m=d.collection)},o(3,s=Se.getApiExampleUrl($e.baseUrl)),o(2,i=[{code:200,body:`
{
"usernamePassword": true,
"emailPassword": true,
Expand Down Expand Up @@ -61,4 +61,4 @@ import{S as ke,i as be,s as ge,e as r,w as b,b as g,c as _e,f as k,g as h,h as n
}
]
}
`}]),[m,f,i,s,u]}class Ne extends ke{constructor(l){super(),be(this,l,Te,Oe,ge,{collection:0})}}export{Ne as default};
`}]),[m,f,i,s,u]}class Ke extends ke{constructor(l){super(),be(this,l,Te,Oe,ge,{collection:0})}}export{Ke as default};
Loading

0 comments on commit aed8367

Please sign in to comment.