mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-03-19 14:17:48 +02:00
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
|
package core
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/pocketbase/pocketbase/tools/hook"
|
||
|
"github.com/pocketbase/pocketbase/tools/router"
|
||
|
)
|
||
|
|
||
|
const CollectionNameSuperusers = "_superusers"
|
||
|
|
||
|
func (app *BaseApp) registerSuperuserHooks() {
|
||
|
app.OnRecordDelete(CollectionNameSuperusers).Bind(&hook.Handler[*RecordEvent]{
|
||
|
Id: "pbSuperusersRecordDelete",
|
||
|
Func: func(e *RecordEvent) error {
|
||
|
originalApp := e.App
|
||
|
txErr := e.App.RunInTransaction(func(txApp App) error {
|
||
|
e.App = txApp
|
||
|
|
||
|
total, err := e.App.CountRecords(CollectionNameSuperusers)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to fetch total superusers count: %w", err)
|
||
|
}
|
||
|
|
||
|
if total == 1 {
|
||
|
return router.NewBadRequestError("You can't delete the only existing superuser", nil)
|
||
|
}
|
||
|
|
||
|
return e.Next()
|
||
|
})
|
||
|
e.App = originalApp
|
||
|
|
||
|
return txErr
|
||
|
},
|
||
|
Priority: -99,
|
||
|
})
|
||
|
|
||
|
recordSaveHandler := &hook.Handler[*RecordEvent]{
|
||
|
Id: "pbSuperusersRecordSaveExec",
|
||
|
Func: func(e *RecordEvent) error {
|
||
|
e.Record.SetVerified(true) // always mark superusers as verified
|
||
|
return e.Next()
|
||
|
},
|
||
|
Priority: -99,
|
||
|
}
|
||
|
app.OnRecordCreateExecute(CollectionNameSuperusers).Bind(recordSaveHandler)
|
||
|
app.OnRecordUpdateExecute(CollectionNameSuperusers).Bind(recordSaveHandler)
|
||
|
|
||
|
collectionSaveHandler := &hook.Handler[*CollectionEvent]{
|
||
|
Id: "pbSuperusersCollectionSaveExec",
|
||
|
Func: func(e *CollectionEvent) error {
|
||
|
// don't allow name change even if executed with SaveNoValidate
|
||
|
e.Collection.Name = CollectionNameSuperusers
|
||
|
|
||
|
// for now don't allow superusers OAuth2 since we don't want
|
||
|
// to accidentally create a new superuser by just OAuth2 signin
|
||
|
e.Collection.OAuth2.Enabled = false
|
||
|
e.Collection.OAuth2.Providers = nil
|
||
|
|
||
|
// force password auth
|
||
|
e.Collection.PasswordAuth.Enabled = true
|
||
|
|
||
|
// for superusers we don't allow for now standalone OTP auth and always require to be combined with MFA
|
||
|
if e.Collection.OTP.Enabled {
|
||
|
e.Collection.MFA.Enabled = true
|
||
|
}
|
||
|
|
||
|
return e.Next()
|
||
|
},
|
||
|
Priority: 99,
|
||
|
}
|
||
|
app.OnCollectionCreateExecute(CollectionNameSuperusers).Bind(collectionSaveHandler)
|
||
|
app.OnCollectionUpdateExecute(CollectionNameSuperusers).Bind(collectionSaveHandler)
|
||
|
}
|
||
|
|
||
|
// IsSuperuser returns whether the current record is a superuser, aka.
|
||
|
// whether the record is from the _superusers collection.
|
||
|
func (m *Record) IsSuperuser() bool {
|
||
|
return m.Collection().Name == CollectionNameSuperusers
|
||
|
}
|