1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-03-29 17:10:44 +02:00

restore crc32 checksum for the colelction and field ids

This commit is contained in:
Gani Georgiev 2024-11-04 10:51:32 +02:00
parent 83d91b3dd5
commit 8d0e4a0460
3 changed files with 81 additions and 36 deletions

View File

@ -3,8 +3,10 @@ package core
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/tools/dbutils"
"github.com/pocketbase/pocketbase/tools/hook"
"github.com/pocketbase/pocketbase/tools/security"
@ -309,6 +311,7 @@ type baseCollection struct {
BaseModel
disableIntegrityChecks bool
autogeneratedId string
ListRule *string `db:"listRule" json:"listRule" form:"listRule"`
ViewRule *string `db:"viewRule" json:"viewRule" form:"viewRule"`
@ -364,6 +367,7 @@ func NewBaseCollection(name string, optId ...string) *Collection {
m.Name = name
m.Type = CollectionTypeBase
// @todo consider removing once inferred composite literals are supported
if len(optId) > 0 {
m.Id = optId[0]
}
@ -383,6 +387,7 @@ func NewViewCollection(name string, optId ...string) *Collection {
m.Name = name
m.Type = CollectionTypeView
// @todo consider removing once inferred composite literals are supported
if len(optId) > 0 {
m.Id = optId[0]
}
@ -402,6 +407,7 @@ func NewAuthCollection(name string, optId ...string) *Collection {
m.Name = name
m.Type = CollectionTypeAuth
// @todo consider removing once inferred composite literals are supported
if len(optId) > 0 {
m.Id = optId[0]
}
@ -689,49 +695,82 @@ func onCollectionDeleteExecute(e *CollectionEvent) error {
// save hook
// -------------------------------------------------------------------
func (c *Collection) initDefaultId() {
if c.Id != "" {
return // already set
}
func (c *Collection) idChecksum() string {
return "pbc_" + crc32Checksum(c.Type+c.Name)
}
if c.System && c.Name != "" {
// for system collections we use crc32 checksum for consistency because they cannot be renamed
c.Id = "pbc_" + crc32Checksum(c.Name)
} else {
c.Id = "pbc_" + security.RandomStringWithAlphabet(11, DefaultIdAlphabet)
func (c *Collection) initDefaultId() {
if c.Id == "" {
c.Id = c.idChecksum()
c.autogeneratedId = c.Id
}
}
func (c *Collection) savePrepare() error {
if c.Type == "" {
c.Type = CollectionTypeBase
func (c *Collection) updateGeneratedIdIfExists(app App) {
if !c.IsNew() ||
// the id was explicitly cleared
c.Id == "" ||
// the id was manually set
c.Id != c.autogeneratedId {
return
}
if c.IsNew() {
c.initDefaultId()
c.Created = types.NowDateTime()
// generate an up-to-date checksum
newId := c.idChecksum()
// add a number to the current id (if already exists)
for i := 2; i < 1000; i++ {
var exists bool
_ = app.CollectionQuery().Select("(1)").AndWhere(dbx.HashExp{"id": newId}).Limit(1).Row(&exists)
if !exists {
break
}
newId = c.idChecksum() + strconv.Itoa(i)
}
c.Updated = types.NowDateTime()
// recreate the fields list to ensure that all normalizations
// like default field id are applied
c.Fields = NewFieldsList(c.Fields...)
c.initDefaultFields()
if c.IsAuth() {
c.unsetMissingOAuth2MappedFields()
// no change
if c.Id == newId {
return
}
return nil
// replace the old id in the index names (if any)
for i, idx := range c.Indexes {
parsed := dbutils.ParseIndex(idx)
original := parsed.IndexName
parsed.IndexName = strings.ReplaceAll(parsed.IndexName, c.Id, newId)
if parsed.IndexName != original {
c.Indexes[i] = parsed.Build()
}
}
// update model id
c.Id = newId
}
func onCollectionSave(e *CollectionEvent) error {
if err := e.Collection.savePrepare(); err != nil {
return err
if e.Collection.Type == "" {
e.Collection.Type = CollectionTypeBase
}
if e.Collection.IsNew() {
e.Collection.initDefaultId()
e.Collection.Created = types.NowDateTime()
}
e.Collection.Updated = types.NowDateTime()
// recreate the fields list to ensure that all normalizations
// like default field id are applied
e.Collection.Fields = NewFieldsList(e.Collection.Fields...)
e.Collection.initDefaultFields()
if e.Collection.IsAuth() {
e.Collection.unsetMissingOAuth2MappedFields()
}
e.Collection.updateGeneratedIdIfExists(e.App)
return e.Next()
}

View File

@ -65,6 +65,10 @@ type optionsValidator interface {
}
func (validator *collectionValidator) run() error {
if validator.original.IsNew() {
validator.new.updateGeneratedIdIfExists(validator.app)
}
// generate fields from the query (overwriting any explicit user defined fields)
if validator.new.IsView() {
validator.new.Fields, _ = validator.app.CreateViewFields(validator.new.ViewQuery)

View File

@ -4,8 +4,7 @@ import (
"database/sql/driver"
"encoding/json"
"fmt"
"github.com/pocketbase/pocketbase/tools/security"
"strconv"
)
// NewFieldsList creates a new FieldsList instance with the provided fields.
@ -171,12 +170,16 @@ func (l *FieldsList) add(newField Field) {
// set default id
if newFieldId == "" {
replaceByName = true
if newField.GetSystem() && newField.GetName() != "" {
// for system fields we use crc32 checksum for consistency because they cannot be renamed
newFieldId = newField.Type() + crc32Checksum(newField.GetName())
} else {
newFieldId = newField.Type() + security.RandomString(7)
baseId := newField.Type() + crc32Checksum(newField.GetName())
newFieldId = baseId
for i := 2; i < 1000; i++ {
if l.GetById(newFieldId) == nil {
break // already unique
}
newFieldId = baseId + strconv.Itoa(i)
}
newField.SetId(newFieldId)
}
// replace existing
@ -196,7 +199,6 @@ func (l *FieldsList) add(newField Field) {
}
// add new field
newField.SetId(newFieldId)
*l = append(fields, newField)
}