58 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	List with changes from v0.8.x to v0.15.x. For the most recent versions, please refer to CHANGELOG.md
v0.15.3
- 
Updated the Admin UI to use the latest JS SDK to resolve the isNewrecord field conflict (#2385).
- 
Fixed editorfield fullscreenz-index(#2410).
- 
Inserts the default app settings as part of the system init migration so that they are always available when accessed from within a user defined migration (#2423). 
v0.15.2
- 
Fixed View query SELECT DISTINCTidentifiers parsing (#2349-5706019).
- 
Fixed View collection schema incorrectly resolving multiple aliased fields originating from the same field source (#2349-5707675). 
- 
Added OAuth2 redirect fallback message to notify the user to go back to the app in case the browser window is not auto closed. 
v0.15.1
- 
Trigger the related Recordmodel realtime subscription events on custom model struct save (#2325).
- 
Fixed Ctrl + Sin theeditorfield not propagating the quick save shortcut to the parent form.
- 
Added ⌘ + Salias for the record quick save shortcut (I have no Mac device to test it but it should work based one.metaKeydocs).
- 
Enabled RTL for the TinyMCE editor (#2327). 
- 
Reduced the record form vertical layout shifts and slightly improved the rendering speed when loading multiple relationfields.
- 
Enabled Admin UI assets cache. 
v0.15.0
- 
Simplified the OAuth2 authentication flow in a single "all in one" call (#55). Requires JS SDK v0.14.0+ or Dart SDK v0.9.0+. The manual code-token exchange flow is still supported but the SDK method is renamed to authWithOAuth2Code()(to minimize the breaking changes the JS SDK has a function overload that will proxy the existingauthWithOauth2calls toauthWithOAuth2Code). For more details and example, you could check https://pocketbase.io/docs/authentication/#oauth2-integration.
- 
Added support for protected files (#215). Requires JS SDK v0.14.0+ or Dart SDK v0.9.0+. It works with a short lived (~5min) file token passed as query param with the file url. For more details and example, you could check https://pocketbase.io/docs/files-handling/#protected-files. 
- 
⚠️ Fixed typo in Record.WithUnkownData()->Record.WithUnknownData().
- 
Added simple loose wildcard search term support in the Admin UI. 
- 
Added auto "draft" to allow restoring previous record state in case of accidental reload or power outage. 
- 
Added Ctrl + Sshortcut to save the record changes without closing the panel.
- 
Added "drop files" support for the file upload field. 
- 
Refreshed the OAuth2 Admin UI. 
v0.14.5
- 
Added checks for nilhooks informs.RecordUpsertwhen used with customDao(#2277).
- 
Fixed unique detailed field error not returned on record create failure (#2287). 
v0.14.4
- Fixed concurrent map write pannic on list.ExistInSliceWithRegex()cache (#2272).
v0.14.3
- 
Fixed Admin UI Logs metavisualization in Firefox (#2221).
- 
Downgraded to v1 of the aws/aws-sdk-gopackage since v2 has compatibility issues with GCS (#2231).
- 
Upgraded the GitHub action to use min Go 1.20.3 for the prebuilt executable since it contains some minor net/httpsecurity fixes.
v0.14.2
- Reverted part of the old COALESCEhandling as a fallback to support empty string comparison with missing joined relation fields.
v0.14.1
- 
Fixed realtime events firing before the files upload completion. 
- 
Updated the underlying S3 lib to use aws-sdk-go-v2(#1346; thanks @yuxiang-gao).
- 
Updated TinyMCE to v6.4.1. 
- 
Updated the godoc of Dao.Save*methods.
v0.14.0
- 
Added experimental Apple OAuth2 integration. 
- 
Added @request.headers.*filter rule support.
- 
Added support for advanced unique constraints and indexes management (#345, #544) 
- 
Simplified the collections fields UI to allow easier and quicker scaffolding of the data schema. 
- 
Deprecated SchemaField.Unique. Unique constraints are now managed via indexes. TheUniquefield is a no-op and will be removed in future version.
- 
Removed the COALESCEwrapping from some of the generated filter conditions to make better use of the indexes (#1939).
- 
Detect idaliased view columns as singlerelationfields (#2029).
- 
Optimized single relation lookups. 
- 
Normalized record values on maxSelectfield option change (select,file,relation). When changing from single to multiple all already inserted single values are converted to an array. When changing from multiple to single only the last item of the already inserted array items is kept.
- 
Changed the cost/round factor of bcrypt hash generation from 13 to 12 since several users complained about the slow authWithPassword responses on lower spec hardware. The change will affect only new users. Depending on the demand, we might make it configurable from the auth options. 
- 
Simplified the default mail template styles to allow more control over the template layout (#1904). 
- 
Added option to explicitly set the record id from the Admin UI (#2118). 
- 
Added migrate history-synccommand to clean_migrationshistory table from deleted migration files references.
- 
Added new fields to the core.RecordAuthWithOAuth2Eventstruct:IsNewRecord bool, // boolean field indicating whether the OAuth2 action created a new auth record ProviderName string, // the name of the OAuth2 provider (eg. "google") ProviderClient auth.Provider, // the loaded Provider client instance
- 
Added CGO linux target for the prebuilt executable. 
- 
⚠️ Renamed daos.GetTableColumns()todaos.TableColumns()for consistency with the other Dao table related helpers.
- 
⚠️ Renamed daos.GetTableInfo()todaos.TableInfo()for consistency with the other Dao table related helpers.
- 
⚠️ Changed types.JsonArrayto support specifying a generic type, aka.types.JsonArray[T]. If you have previously usedtypes.JsonArray, you'll have to update it totypes.JsonArray[any].
- 
⚠️ Registered the RemoveTrailingSlashmiddleware only for the/api/*routes since it is causing issues with subpath file serving endpoints (#2072).
- 
⚠️ Changed the request logs methodvalue to UPPERCASE, eg. "get" => "GET" (#1956).
- 
Other minor UI improvements. 
v0.13.4
- Removed eager unique collection name check to support lazy validation during bulk import.
v0.13.3
- 
Fixed view collections import (#2044). 
- 
Updated the records picker Admin UI to show properly view collection relations. 
v0.13.2
- Fixed Admin UI js error when selecting multiple filefield asrelation"Display fields" (#1989).
v0.13.1
- Added HEADrequest method support for the/api/files/:collection/:recordId/:filenameroute (#1976).
v0.13.0
- 
Added new "View" collection type allowing you to create a read-only collection from a custom SQL SELECTstatement. It supports:- aggregations (COUNT(),MIN(),MAX(),GROUP BY, etc.)
- column and table aliases
- CTEs and subquery expressions
- auto relationfields association
- filefields proxying (up to 5 linked relations, eg. view1->view2->...->base)
- filter,- sortand- expand
- List and View API rules
 
- aggregations (
- 
Added auto fail/retry (default to 8 attempts) for the SELECTqueries to gracefully handle thedatabase is lockederrors (#1795). The default max attempts can be accessed or changed viaDao.MaxLockRetries.
- 
Added default max query execution timeout (30s). The default timeout can be accessed or changed via Dao.ModelQueryTimeout. For the prebuilt executables it can be also changed via the--queryTimeout=10flag.
- 
Added support for dao.RecordQuery(collection)to scan directly theOne()andAll()results in*models.Recordor[]*models.Recordwithout the need of explicitNullStringMap.
- 
Added support to overwrite the default file serve headers if an explicit response header is set. 
- 
Added file thumbs when visualizing relationdisplay file fields.
- 
Added "Min select" relationfield option.
- 
Enabled process.envin JS migrations to allow accessingos.Environ().
- 
Added UploadedFilesfield to theRecordCreateEventandRecordUpdateEventevent structs.
- 
⚠️ Moved file upload after the record persistent to allow setting custom record id safely from the OnModelBeforeCreatehook.
- 
⚠️ Changed System.GetFile()to return directly*blob.Readerinstead of theio.ReadCloserinterface.
- 
⚠️ Changed To,CcandBccofmailer.Messageto[]mail.Addressfor consistency and to allow multiple recipients and optional name.If you are sending custom emails, you'll have to replace: message := &mailer.Message{ ... // (old) To: mail.Address{Address: "to@example.com"} To: []mail.Address{{Address: "to@example.com", Name: "Some optional name"}}, // (old) Cc: []string{"cc@example.com"} Cc: []mail.Address{{Address: "cc@example.com", Name: "Some optional name"}}, // (old) Bcc: []string{"bcc@example.com"} Bcc: []mail.Address{{Address: "bcc@example.com", Name: "Some optional name"}}, ... }
- 
⚠️ Refactored the Authentik integration as a more generic "OpenID Connect" provider ( oidc) to support any OIDC provider (Okta, Keycloak, etc.). If you've previously used Authentik, make sure to rename the provider key in your code tooidc. To enable more than one OIDC provider you can use the additionaloidc2andoidc3provider keys.
- 
⚠️ Removed the previously deprecated Dao.Block()andDao.Continue()helpers in favor ofDao.NonconcurrentDB().
- 
Updated the internal redirects to allow easier subpath deployment when behind a reverse proxy. 
- 
Other minor Admin UI improvements. 
v0.12.3
- 
Fixed "Toggle column" reactivity when navigating between collections (#1836). 
- 
Logged the current datetime on server start (#1822). 
v0.12.2
- 
Fixed the "Clear" button of the datepicker component not clearing the value (#1730). 
- 
Increased slightly the fields contrast (#1742). 
- 
Auto close the multi-select dropdown if "Max select" is reached. 
v0.12.1
- 
Fixed js error on empty relation save. 
- 
Fixed overlay-activecss class not being removed on nested overlay panel close (#1718).
- 
Added the collection name in the page title (#1711). 
v0.12.0
- 
Refactored the relation picker UI to allow server-side search, sort, create, update and delete of relation records (#976). 
- 
Added new RelationOptions.DisplayFieldsoption to specify custom relation field(s) visualization in the Admin UI.
- 
Added Authentik OAuth2 provider (#1377; thanks @pr0ton11). 
- 
Added LiveChat OAuth2 provider (#1573; thanks @mariosant). 
- 
Added Gitea OAuth2 provider (#1643; thanks @hlanderdev). 
- 
Added PDF file previews (#1548; thanks @mjadobson). 
- 
Added video and audio file previews. 
- 
Added rich text editor ( editor) field for HTML content based on TinyMCE (#370). Currently the new field doesn't have any configuration options or validations but this may change in the future depending on how devs ended up using it.
- 
Added "Duplicate" Collection and Record options in the Admin UI (#1656). 
- 
Added filesystem.GetFile()helper to read files through the FileSystem abstraction (#1578; thanks @avarabyeu).
- 
Added new auth event hooks for finer control and more advanced auth scenarios handling: // auth record OnRecordBeforeAuthWithPasswordRequest() OnRecordAfterAuthWithPasswordRequest() OnRecordBeforeAuthWithOAuth2Request() OnRecordAfterAuthWithOAuth2Request() OnRecordBeforeAuthRefreshRequest() OnRecordAfterAuthRefreshRequest() // admin OnAdminBeforeAuthWithPasswordRequest() OnAdminAfterAuthWithPasswordRequest() OnAdminBeforeAuthRefreshRequest() OnAdminAfterAuthRefreshRequest() OnAdminBeforeRequestPasswordResetRequest() OnAdminAfterRequestPasswordResetRequest() OnAdminBeforeConfirmPasswordResetRequest() OnAdminAfterConfirmPasswordResetRequest()
- 
Added models.Record.CleanCopy()helper that creates a new record copy with only the latest data state of the existing one and all other options reset to their defaults.
- 
Added new helper apis.RecordAuthResponse(app, httpContext, record, meta)to return a standard Record auth API response (#1623).
- 
Refactored models.Recordexpand and data change operations to be concurrent safe.
- 
Refactored all formsSubmit interceptors to use a generic data type as their payload.
- 
Added several store.Storehelpers:store.Reset(newData map[string]T) store.Length() int store.GetAll() map[string]T
- 
Added "tags" support for all Record and Model related event hooks. The "tags" allow registering event handlers that will be called only on matching table name(s) or colleciton id(s)/name(s). For example: app.OnRecordBeforeCreateRequest("articles").Add(func(e *core.RecordCreateEvent) error { // called only on "articles" record creation log.Println(e.Record) return nil })For all those event hooks *hook.Hookwas replaced with*hooks.TaggedHook, but the hook methods signatures are the same so it should behave as it was previously if no tags were specified.
- 
⚠️ Fixed the jsonfield string value normalization (#1703).In order to support seamlessly both application/jsonandmultipart/form-datarequests, the following normalization rules are applied if thejsonfield is a plain string value:- "true" is converted to the json true
- "false" is converted to the json false
- "null" is converted to the json null
- "[1,2,3]" is converted to the json [1,2,3]
- "{"a":1,"b":2}" is converted to the json {"a":1,"b":2}
- numeric strings are converted to json number
- double quoted strings are left as they are (aka. without normalizations)
- any other string (empty string too) is double quoted
 Additionally, the "Nonempty" jsonfield constraint now checks fornull,[],{}and""(empty string).
- "true" is converted to the json 
- 
Added aria-labelto some of the buttons in the Admin UI for better accessibility (#1702; thanks @ndarilek).
- 
Updated the filename extension checks in the Admin UI to be case-insensitive (#1707; thanks @hungcrush). 
- 
Other minor improvements (more detailed API file upload errors, UI optimizations, docs improvements, etc.) 
v0.11.4
- Fixed cascade delete for rel records with the same id as the main record (#1689).
v0.11.3
- 
Fix realtime API panic on concurrent clients iteration (#1628) - 
app.SubscriptionsBroker().Clients()now returns a shallow copy of the underlying map.
- 
Added Discard()andIsDiscarded()helper methods to thesubscriptions.Clientinterface.
- 
Slow clients should no longer "block" the main action completion. 
 
- 
v0.11.2
- 
Fixed fs.DeleteByPrefix()hang on invalid S3 settings (#1575).
- 
Updated file(s) delete to run in the background on record/collection delete to avoid blocking the delete model transaction. Currently the cascade files delete operation is treated as "non-critical" and in case of an error it is just logged during debug. This will be improved in the near future with the planned async job queue implementation. 
v0.11.1
- Unescaped path parameter values (#1552).
v0.11.0
- 
Added +and-body field modifiers fornumber,files,selectandrelationfields.{ // oldValue + 2 "someNumber+": 2, // oldValue + ["id1", "id2"] - ["id3"] "someRelation+": ["id1", "id2"], "someRelation-": ["id3"], // delete single file by its name (file fields supports only the "-" modifier!) "someFile-": "filename.png", }Note1: @request.data.someFieldwill contain the final resolved value.Note2: The old index ( "field.0":null) and filename ("field.filename.png":null) based suffixed syntax for deleting files is still supported.
- 
⚠️ Added support for multi-match/match-all request data and collection multi-valued fields ( select,relation) conditions. If you want a "at least one of" type of condition, you can prefix the operator with?.// for each someRelA.someRelB record require the "status" field to be "active" someRelA.someRelB.status = "active" // OR for "at least one of" condition someRelA.someRelB.status ?= "active"Note: Previously the behavior for multi-valued fields was as the "at least one of" type. The release comes with system db migration that will update your existing API rules (if needed) to preserve the compatibility. If you have multi-select or multi-relation filter checks in your client-side code and want to preserve the old behavior, you'll have to prefix with ?your operators.
- 
Added support for querying @request.data.someRelField.*relation fields.// example submitted data: {"someRel": "REL_RECORD_ID"} @request.data.someRel.status = "active"
- 
Added :issetmodifier for the static request data fields.// prevent changing the "role" field @request.data.role:isset = false
- 
Added :lengthmodifier for the arrayable request data and collection fields (select,file,relation).// example submitted data: {"someSelectField": ["val1", "val2"]} @request.data.someSelectField:length = 2 // check existing record field length someSelectField:length = 2
- 
Added :eachmodifier support for the multi-selectrequest data and collection field.// check if all selected rows has "pb_" prefix roles:each ~ 'pb_%'
- 
Improved the Admin UI filters autocomplete. 
- 
Added @randomsort key forRANDOM()sorted list results.
- 
Added Strava OAuth2 provider (#1443; thanks @szsascha). 
- 
Added Gitee OAuth2 provider (#1448; thanks @yuxiang-gao). 
- 
Added IME status check to the textarea keydown handler (#1370; thanks @tenthree). 
- 
Added filesystem.NewFileFromBytes()helper (#1420; thanks @dschissler).
- 
Added support for reordering uploaded multiple files. 
- 
Added webpto the default images mime type presets list (#1469; thanks @khairulhaaziq).
- 
Added the OAuth2 refresh token to the auth meta response (#1487). 
- 
Fixed the text wrapping in the Admin UI listing searchbar (#1416). 
- 
Fixed number field value output in the records listing (#1447). 
- 
Fixed duplicated settings view pages caused by uncompleted transitions (#1498). 
- 
Allowed sending Authorizationheader with the/auth-with-passwordrecord and admin login requests (#1494).
- 
migrate downnow reverts migrations in the applied order.
- 
Added additional list-bucket check in the S3 config test API. 
- 
Other minor improvements. 
v0.10.4
- Fixed Record.MergeExpandpanic when the main model expand map is not initialized (#1365).
v0.10.3
- 
⚠️ Renamed the metadata key original_filenametooriginal-filenamedue to an S3 file upload error caused by the underscore character (#1343; thanks @yuxiang-gao).
- 
Fixed request verification docs api url (#1332; thanks @JoyMajumdar2001) 
- 
Excluded collectionIdandcollectionNamefrom the displayable relation props list (1322; thanks @dhall2).
v0.10.2
- Fixed nested multiple expands with shared path (#586).
A new helper method models.Record.MergeExpand(map[string]any)was also added to simplify the expand handling and unit testing.
v0.10.1
- Fixed nested transactions deadlock when authenticating with OAuth2 (#1291).
v0.10.0
- 
Added /api/healthendpoint (thanks @MarvinJWendt).
- 
Added support for SMTP LOGINauth for Microsoft/Outlook and other providers that don't support thePLAINauth method (#1217).
- 
Reduced memory consumption (you can expect ~20% less allocated memory). 
- 
Added support for split (concurrent and nonconcurrent) DB connections pool increasing even further the concurrent throughput without blocking reads on heavy write load. 
- 
Improved record references delete performance. 
- 
Removed the unnecessary parenthesis in the generated filter SQL query, reducing the "parse stack overflow" errors. 
- 
Fixed ~expressions backslash literal escaping (#1231).
- 
Refactored the core.app.Bootstrap()to be called before starting the cobra commands (#1267).
- 
⚠️ Changed pocketbase.NewWithConfig(config Config)topocketbase.NewWithConfig(config *Config)and added 4 new config settings:DataMaxOpenConns int // default to core.DefaultDataMaxOpenConns DataMaxIdleConns int // default to core.DefaultDataMaxIdleConns LogsMaxOpenConns int // default to core.DefaultLogsMaxOpenConns LogsMaxIdleConns int // default to core.DefaultLogsMaxIdleConns
- 
Added new helper method core.App.IsBootstrapped()to check the current app bootstrap state.
- 
⚠️ Changed core.NewBaseApp(dir, encryptionEnv, isDebug)toNewBaseApp(config *BaseAppConfig).
- 
⚠️ Removed rest.UploadedFilestruct (see belowfilesystem.File).
- 
Added generic file resource struct that allows loading and uploading file content from different sources (at the moment multipart/form-data requests and from the local filesystem). filesystem.File{} filesystem.NewFileFromPath(path) filesystem.NewFileFromMultipart(multipartHeader) filesystem/System.UploadFile(file)
- 
Refactored forms.RecordUpsertto allow more easily loading and removing files programmatically.forms.RecordUpsert.AddFiles(key, filesystem.File...) // add new filesystem.File to the form for upload forms.RecordUpsert.RemoveFiles(key, filenames...) // marks the filenames for deletion
- 
Trigger the passwordvalidators if any of the others password change fields is set.
v0.9.2
- Fixed field column name conflict on record deletion (#1220).
v0.9.1
- 
Moved the record file upload and delete out of the db transaction to minimize the locking times. 
- 
Added Daoquery semaphore and base fail/retry handling to improve the concurrent writes throughput (#1187).
- 
Fixed records cascade deletion when there are "A<->B" relation references. 
- 
Replaced c.QueryString()withc.QueryParams().Encode()to allow loading middleware modified query parameters in the default crud actions (#1210).
- 
Fixed the datetime field not triggering the onChangeevent on manual field edit and added a "Clear" button (#1219).
- 
Updated the GitHub goreleaser action to use go 1.19.4 since it comes with some security fixes. 
v0.9.0
- 
Fixed concurrent multi-relation cascade update/delete (#1138). 
- 
Added the raw OAuth2 user data ( meta.rawUser) and OAuth2 access token (meta.accessToken) to the auth response (#654).
- 
BaseModel.UnmarkAsNew()method was renamed toBaseModel.MarkAsNotNew(). Additionally, to simplify the insert model queries with custom IDs, it is no longer required to callMarkAsNew()for manually initialized models with set ID since now this is the default state. When the model is populated with values from the database (eg. after rowScan) it will be marked automatically as "not new".
- 
Added Record.OriginalCopy()method that returns a newRecordcopy populated with the initially loaded record data (useful if you want to compare old and new field values).
- 
Added new event hooks: app.OnBeforeBootstrap() app.OnAfterBootstrap() app.OnBeforeApiError() app.OnAfterApiError() app.OnRealtimeDisconnectRequest() app.OnRealtimeBeforeMessageSend() app.OnRealtimeAfterMessageSend() app.OnRecordBeforeRequestPasswordResetRequest() app.OnRecordAfterRequestPasswordResetRequest() app.OnRecordBeforeConfirmPasswordResetRequest() app.OnRecordAfterConfirmPasswordResetRequest() app.OnRecordBeforeRequestVerificationRequest() app.OnRecordAfterRequestVerificationRequest() app.OnRecordBeforeConfirmVerificationRequest() app.OnRecordAfterConfirmVerificationRequest() app.OnRecordBeforeRequestEmailChangeRequest() app.OnRecordAfterRequestEmailChangeRequest() app.OnRecordBeforeConfirmEmailChangeRequest() app.OnRecordAfterConfirmEmailChangeRequest()
- 
The original uploaded file name is now stored as metadata under the original_filenamekey. It could be accessed via:fs, _ := app.NewFilesystem() defer fs.Close() attrs, _ := fs.Attributes(fikeKey) attrs.Metadata["original_name"]
- 
Added support for Partial/Rangefile requests (#1125). This is a minor breaking change if you are usingfilesystem.Serve(eg. as part of a customOnFileDownloadRequesthook):// old filesystem.Serve(res, e.ServedPath, e.ServedName) // new filesystem.Serve(res, req, e.ServedPath, e.ServedName)
- 
Refactored the migratecommand to support external JavaScript migration files using an embedded JS interpreter (goja). This allow writing custom migration scripts such as programmatically creating collections, initializing default settings, running data imports, etc., with a JavaScript API very similar to the Go one (more documentation will be available soon).The migratecommand is available by default for the prebuilt executable, but if you use PocketBase as framework you need register it manually:migrationsDir := "" // default to "pb_migrations" (for js) and "migrations" (for go) // load js files if you want to allow loading external JavaScript migrations jsvm.MustRegisterMigrations(app, &jsvm.MigrationsOptions{ Dir: migrationsDir, }) // register the `migrate` command migratecmd.MustRegister(app, app.RootCmd, &migratecmd.Options{ TemplateLang: migratecmd.TemplateLangJS, // or migratecmd.TemplateLangGo (default) Dir: migrationsDir, Automigrate: true, })The refactoring also comes with automigrations support. If Automigrateis enabled (trueby default for the prebuilt executable; can be disabled with--automigrate=0), PocketBase will generate seamlessly in the background JS (or Go) migration file with your collection changes. The directory with the JS migrations can be committed to your git repo. All migrations (Go and JS) are automatically executed on server start. Also note that the auto generated migrations are granural (in contrast to themigrate collectionssnapshot command) and allow multiple developers to do changes on the collections independently (even editing the same collection) miniziming the eventual merge conflicts. Here is a sample JS migration file that will be generated if you for example edit a single collection name:// pb_migrations/1669663597_updated_posts_old.js migrate((db) => { // up const dao = new Dao(db) const collection = dao.findCollectionByNameOrId("lngf8rb3dqu86r3") collection.name = "posts_new" return dao.saveCollection(collection) }, (db) => { // down const dao = new Dao(db) const collection = dao.findCollectionByNameOrId("lngf8rb3dqu86r3") collection.name = "posts_old" return dao.saveCollection(collection) })
- 
Added new Daohelpers to make it easier fetching and updating the app settings from a migration:dao.FindSettings([optEncryptionKey]) dao.SaveSettings(newSettings, [optEncryptionKey])
- 
Moved core.Settingstomodels/settings.Settings:core.Settings{} -> settings.Settings{} core.NewSettings() -> settings.New() core.MetaConfig{} -> settings.MetaConfig{} core.LogsConfig{} -> settings.LogsConfig{} core.SmtpConfig{} -> settings.SmtpConfig{} core.S3Config{} -> settings.S3Config{} core.TokenConfig{} -> settings.TokenConfig{} core.AuthProviderConfig{} -> settings.AuthProviderConfig{}
- 
Changed the mailer.Mailerinterface (minor breaking if you are sending custom emails):// Old: app.NewMailClient().Send(from, to, subject, html, attachments?) // New: app.NewMailClient().Send(&mailer.Message{ From: from, To: to, Subject: subject, HTML: html, Attachments: attachments, // new configurable fields Bcc: []string{"bcc1@example.com", "bcc2@example.com"}, Cc: []string{"cc1@example.com", "cc2@example.com"}, Headers: map[string]string{"Custom-Header": "test"}, Text: "custom plain text version", })The new *mailer.Messagestruct is also now a member of theMailerRecordEventandMailerAdminEventevents.
- 
Other minor UI fixes and improvements 
v0.8.0
⚠️ This release contains breaking changes and requires some manual migration steps!
The biggest change is the merge of the User models and the profiles collection per #376.
There is no longer user type field and the users are just an "auth" collection (we now support collection types, currently only "base" and "auth").
This should simplify the users management and at the same time allow us to have unlimited multiple "auth" collections each with their own custom fields and authentication options (eg. staff, client, etc.).
In addition to the Users and profiles merge, this release comes with several other improvements:
- 
Added indirect expand support #312. 
- 
The jsonfield type now supports filtering and sorting #423.
- 
The relationfield now allows unlimitedmaxSelect(aka. without upper limit).
- 
Added support for combined email/username + password authentication (see below authWithPassword()).
- 
Added support for full "manager-subordinate" users management, including a special API rule to allow directly changing system fields like email, password, etc. without requiring oldPasswordor other user verification.
- 
Enabled OAuth2 account linking on authorized request from the same auth collection (this is useful for example if the OAuth2 provider doesn't return an email and you want to associate it with the current logged in user). 
- 
Added option to toggle the record columns visibility from the table listing. 
- 
Added support for collection schema fields reordering. 
- 
Added several new OAuth2 providers (Microsoft Azure AD, Spotify, Twitch, Kakao). 
- 
Improved memory usage on large file uploads #835. 
- 
More detailed API preview docs and site documentation (the repo is located at https://github.com/pocketbase/site). 
- 
Other minor performance improvements (mostly related to the search apis). 
Migrate from v0.7.x
Data
The merge of users and profiles comes with several required db changes.
The easiest way to apply them is to use the new temporary upgrade command:
# make sure to have a copy of your pb_data in case something fails
cp -r ./pb_data ./pb_data_backup
# run the upgrade command
./pocketbase08 upgrade
# start the application as usual
./pocketbase08 serve
The upgrade command:
- Creates a new userscollection with merged fields from the_userstable and theprofilescollection. The new user records will have the ids from theprofilescollection.
- Changes all usertype fields torelationand update the references to point to the new user ids.
- Renames all @collection.profiles.*,@request.user.*and@request.user.profile.*filters to@collection.users.*and@request.auth.*.
- Appends 2to all schema field names and api filter rules that conflicts with the new system reserved ones:collectionId => collectionId2 collectionName => collectionName2 expand => expand2 // only for the "profiles" collection fields: username => username2 email => email2 emailVisibility => emailVisibility2 verified => verified2 tokenKey => tokenKey2 passwordHash => passwordHash2 lastResetSentAt => lastResetSentAt2 lastVerificationSentAt => lastVerificationSentAt2
SDKs
Please check the individual SDK package changelog and apply the necessary changes in your code:
- 
npm install pocketbase@latest --save
- 
dart pub add pocketbase:^0.5.0 # or with Flutter: flutter pub add pocketbase:^0.5.0
API
You don't have to read this if you are using an official SDK.
- 
The authorization schema is no longer necessary. Now it is auto detected from the JWT token payload: Old New Authorization: Admin TOKEN Authorization: TOKEN Authorization: User TOKEN Authorization: TOKEN 
- 
All datetime stings are now returned in ISO8601 format - with Z suffix and space as separator between the date and time part: Old New 2022-01-02 03:04:05.678 2022-01-02 03:04:05.678Z 
- 
Removed the @prefix from the system record fields for easier json parsing:Old New @collectionId collectionId @collectionName collectionName @expand expand 
- 
All users api handlers are moved under /api/collections/:collection/:Old New GET /api/users/auth-methods GET /api/collections/:collection/auth-methods POST /api/users/refresh POST /api/collections/:collection/auth-refresh POST /api/users/auth-via-oauth2 POST /api/collections/:collection/auth-with-oauth2 
 You can now also pass optionalcreateDataobject on OAuth2 sign-up.
 Also please note that now required user/profile fields are properly validated when creating new auth model on OAuth2 sign-up.POST /api/users/auth-via-email POST /api/collections/:collection/auth-with-password 
 Handles username/email + password authentication.
 {"identity": "usernameOrEmail", "password": "123456"}POST /api/users/request-password-reset POST /api/collections/:collection/request-password-reset POST /api/users/confirm-password-reset POST /api/collections/:collection/confirm-password-reset POST /api/users/request-verification POST /api/collections/:collection/request-verification POST /api/users/confirm-verification POST /api/collections/:collection/confirm-verification POST /api/users/request-email-change POST /api/collections/:collection/request-email-change POST /api/users/confirm-email-change POST /api/collections/:collection/confirm-email-change GET /api/users GET /api/collections/:collection/records GET /api/users/:id GET /api/collections/:collection/records/:id POST /api/users POST /api/collections/:collection/records PATCH /api/users/:id PATCH /api/collections/:collection/records/:id DELETE /api/users/:id DELETE /api/collections/:collection/records/:id GET /api/users/:id/external-auths GET /api/collections/:collection/records/:id/external-auths DELETE /api/users/:id/external-auths/:provider DELETE /api/collections/:collection/records/:id/external-auths/:provider In relation to the above changes, the userproperty in the auth response is renamed torecord.
- 
The admins api was also updated for consistency with the users api changes: Old New POST /api/admins/refresh POST /api/admins/auth-refresh POST /api/admins/auth-via-email POST /api/admins/auth-with-password 
 {"identity": "test@example.com", "password": "123456"}
 (notice that theemailbody field was renamed toidentity)
- 
To prevent confusion with the auth method responses, the following endpoints now returns 204 with empty body (previously 200 with token and auth model): POST /api/admins/confirm-password-reset POST /api/collections/:collection/confirm-password-reset POST /api/collections/:collection/confirm-verification POST /api/collections/:collection/confirm-email-change
- 
Renamed the "user" related settings fields returned by GET /api/settings:Old New userAuthToken recordAuthToken userPasswordResetToken recordPasswordResetToken userEmailChangeToken recordEmailChangeToken userVerificationToken recordVerificationToken 
Internals
You don't have to read this if you are not using PocketBase as framework.
- 
Removed forms.New*WithConfig()factories to minimize ambiguities. If you need to pass a transaction Dao you can use the newSetDao(dao)method available to the form instances.
- 
forms.RecordUpsert.LoadData(data map[string]any)now can bulk load external data from a map. To load data from a request instance, you could useforms.RecordUpsert.LoadRequest(r, optKeysPrefix = "").
- 
schema.RelationOptions.MaxSelecthas new type*int(you can use the newtypes.Pointer(123)helper to assign pointer values).
- 
Renamed the constant apis.ContextUserKey("user") toapis.ContextAuthRecordKey("authRecord").
- 
Replaced user related middlewares with their auth record alternative: Old New apis.RequireUserAuth() apis.RequireRecordAuth(optCollectionNames ...string) apis.RequireAdminOrUserAuth() apis.RequireAdminOrRecordAuth(optCollectionNames ...string) N/A RequireSameContextRecordAuth() 
 (requires the auth record to be from the same context collection)
- 
The following record Dao helpers now uses the collection id or name instead of *models.Collectioninstance to reduce the verbosity when fetching records:Old New dao.FindRecordById(collection, ...) dao.FindRecordById(collectionNameOrId, ...) dao.FindRecordsByIds(collection, ...) dao.FindRecordsByIds(collectionNameOrId, ...) dao.FindRecordsByExpr(collection, ...) dao.FindRecordsByExpr(collectionNameOrId, ...) dao.FindFirstRecordByData(collection, ...) dao.FindFirstRecordByData(collectionNameOrId, ...) dao.IsRecordValueUnique(collection, ...) dao.IsRecordValueUnique(collectionNameOrId, ...) 
- 
Replaced all User related Dao helpers with Record equivalents: Old New dao.UserQuery() dao.RecordQuery(collection) dao.FindUserById(id) dao.FindRecordById(collectionNameOrId, id) dao.FindUserByToken(token, baseKey) dao.FindAuthRecordByToken(token, baseKey) dao.FindUserByEmail(email) dao.FindAuthRecordByEmail(collectionNameOrId, email) N/A dao.FindAuthRecordByUsername(collectionNameOrId, username) 
- 
Moved the formatted ApiErrorstruct and factories to thegithub.com/pocketbase/pocketbase/apissubpackage:Old New Import path github.com/pocketbase/pocketbase/tools/rest github.com/pocketbase/pocketbase/apis Fields rest.ApiError{} apis.ApiError{} rest.NewNotFoundError() apis.NewNotFoundError() rest.NewBadRequestError() apis.NewBadRequestError() rest.NewForbiddenError() apis.NewForbiddenError() rest.NewUnauthorizedError() apis.NewUnauthorizedError() rest.NewApiError() apis.NewApiError() 
- 
Renamed models.Recordhelper getters:Old New SetDataValue Set GetDataValue Get GetBoolDataValue GetBool GetStringDataValue GetString GetIntDataValue GetInt GetFloatDataValue GetFloat GetTimeDataValue GetTime GetDateTimeDataValue GetDateTime GetStringSliceDataValue GetStringSlice 
- 
Added new auth collection models.Recordhelpers:func (m *Record) Username() string func (m *Record) SetUsername(username string) error func (m *Record) Email() string func (m *Record) SetEmail(email string) error func (m *Record) EmailVisibility() bool func (m *Record) SetEmailVisibility(visible bool) error func (m *Record) IgnoreEmailVisibility(state bool) func (m *Record) Verified() bool func (m *Record) SetVerified(verified bool) error func (m *Record) TokenKey() string func (m *Record) SetTokenKey(key string) error func (m *Record) RefreshTokenKey() error func (m *Record) LastResetSentAt() types.DateTime func (m *Record) SetLastResetSentAt(dateTime types.DateTime) error func (m *Record) LastVerificationSentAt() types.DateTime func (m *Record) SetLastVerificationSentAt(dateTime types.DateTime) error func (m *Record) ValidatePassword(password string) bool func (m *Record) SetPassword(password string) error
- 
Added option to return serialized custom models.Recordfields data:func (m *Record) UnknownData() map[string]any func (m *Record) WithUnknownData(state bool)
- 
Deleted model.User. Now the user data is stored as an authmodels.Record.Old New User.Email Record.Email() User.TokenKey Record.TokenKey() User.Verified Record.Verified() User.SetPassword() Record.SetPassword() User.RefreshTokenKey() Record.RefreshTokenKey() etc. 
- 
Replaced Userrelated event hooks with theirRecordalternative:Old New OnMailerBeforeUserResetPasswordSend() *hook.Hook[*MailerUserEvent] OnMailerBeforeRecordResetPasswordSend() *hook.Hook[*MailerRecordEvent] OnMailerAfterUserResetPasswordSend() *hook.Hook[*MailerUserEvent] OnMailerAfterRecordResetPasswordSend() *hook.Hook[*MailerRecordEvent] OnMailerBeforeUserVerificationSend() *hook.Hook[*MailerUserEvent] OnMailerBeforeRecordVerificationSend() *hook.Hook[*MailerRecordEvent] OnMailerAfterUserVerificationSend() *hook.Hook[*MailerUserEvent] OnMailerAfterRecordVerificationSend() *hook.Hook[*MailerRecordEvent] OnMailerBeforeUserChangeEmailSend() *hook.Hook[*MailerUserEvent] OnMailerBeforeRecordChangeEmailSend() *hook.Hook[*MailerRecordEvent] OnMailerAfterUserChangeEmailSend() *hook.Hook[*MailerUserEvent] OnMailerAfterRecordChangeEmailSend() *hook.Hook[*MailerRecordEvent] OnUsersListRequest() *hook.Hook[*UserListEvent] OnRecordsListRequest() *hook.Hook[*RecordsListEvent] OnUserViewRequest() *hook.Hook[*UserViewEvent] OnRecordViewRequest() *hook.Hook[*RecordViewEvent] OnUserBeforeCreateRequest() *hook.Hook[*UserCreateEvent] OnRecordBeforeCreateRequest() *hook.Hook[*RecordCreateEvent] OnUserAfterCreateRequest() *hook.Hook[*UserCreateEvent] OnRecordAfterCreateRequest() *hook.Hook[*RecordCreateEvent] OnUserBeforeUpdateRequest() *hook.Hook[*UserUpdateEvent] OnRecordBeforeUpdateRequest() *hook.Hook[*RecordUpdateEvent] OnUserAfterUpdateRequest() *hook.Hook[*UserUpdateEvent] OnRecordAfterUpdateRequest() *hook.Hook[*RecordUpdateEvent] OnUserBeforeDeleteRequest() *hook.Hook[*UserDeleteEvent] OnRecordBeforeDeleteRequest() *hook.Hook[*RecordDeleteEvent] OnUserAfterDeleteRequest() *hook.Hook[*UserDeleteEvent] OnRecordAfterDeleteRequest() *hook.Hook[*RecordDeleteEvent] OnUserAuthRequest() *hook.Hook[*UserAuthEvent] OnRecordAuthRequest() *hook.Hook[*RecordAuthEvent] OnUserListExternalAuths() *hook.Hook[*UserListExternalAuthsEvent] OnRecordListExternalAuths() *hook.Hook[*RecordListExternalAuthsEvent] OnUserBeforeUnlinkExternalAuthRequest() *hook.Hook[*UserUnlinkExternalAuthEvent] OnRecordBeforeUnlinkExternalAuthRequest() *hook.Hook[*RecordUnlinkExternalAuthEvent] OnUserAfterUnlinkExternalAuthRequest() *hook.Hook[*UserUnlinkExternalAuthEvent] OnRecordAfterUnlinkExternalAuthRequest() *hook.Hook[*RecordUnlinkExternalAuthEvent] 
- 
Replaced forms.UserEmailLogin{}withforms.RecordPasswordLogin{}(for both username and email depending on which is enabled for the collection).
- 
Renamed user related core.Settingsfields:Old New core.Settings.UserAuthToken{} core.Settings.RecordAuthToken{} core.Settings.UserPasswordResetToken{} core.Settings.RecordPasswordResetToken{} core.Settings.UserEmailChangeToken{} core.Settings.RecordEmailChangeToken{} core.Settings.UserVerificationToken{} core.Settings.RecordVerificationToken{} 
- 
Marked as "Deprecated" and will be removed in v0.9+: core.Settings.EmailAuth{} core.EmailAuthConfig{} schema.FieldTypeUser schema.UserOptions{}
- 
The second argument of apis.StaticDirectoryHandler(fileSystem, enableIndexFallback)now is used to enable/disable index.html forwarding on missing file (eg. in case of SPA).