refactor: improve setup and maintainability (#1067)

This commit is contained in:
Jonas Plum
2024-07-08 00:16:37 +02:00
committed by GitHub
parent f5fcee0096
commit 619c5c65ce
553 changed files with 11271 additions and 91670 deletions

57
migrations/0_base.go Normal file
View File

@@ -0,0 +1,57 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models/settings"
"github.com/pocketbase/pocketbase/tools/types"
)
type baseUpFunc func(dao *daos.Dao) error
func baseUp(db dbx.Builder) error {
dao := daos.New(db)
for _, f := range []baseUpFunc{
settingsUp,
allowUserViewUp,
} {
if err := f(dao); err != nil {
return err
}
}
return nil
}
func settingsUp(dao *daos.Dao) error {
s := settings.New()
s.Meta.AppName = "Catalyst"
s.Meta.HideControls = false
return dao.SaveSettings(s)
}
func allowUserViewUp(dao *daos.Dao) error {
collection, err := dao.FindCollectionByNameOrId(UserCollectionName)
if err != nil {
return err
}
collection.ViewRule = types.Pointer("@request.auth.id != ''")
collection.ListRule = types.Pointer("@request.auth.id != ''")
return dao.SaveCollection(collection)
}
func baseDown(db dbx.Builder) error {
collection, err := daos.New(db).FindCollectionByNameOrId(UserCollectionName)
if err != nil {
return err
}
collection.ViewRule = types.Pointer("id = @request.auth.id")
collection.ListRule = types.Pointer("id = @request.auth.id")
return daos.New(db).SaveCollection(collection)
}

165
migrations/1_collections.go Normal file
View File

@@ -0,0 +1,165 @@
package migrations
import (
"fmt"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/models/schema"
"github.com/pocketbase/pocketbase/tools/types"
)
const (
TimelineCollectionName = "timeline"
CommentCollectionName = "comments"
fileCollectionName = "files"
LinkCollectionName = "links"
TaskCollectionName = "tasks"
TicketCollectionName = "tickets"
TypeCollectionName = "types"
WebhookCollectionName = "webhooks"
FeatureCollectionName = "features"
UserCollectionName = "_pb_users_auth_"
)
func collectionsUp(db dbx.Builder) error {
collections := []*models.Collection{
internalCollection(&models.Collection{
Name: TypeCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "singular", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "plural", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "icon", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "schema", Type: schema.FieldTypeJson, Required: true, Options: &schema.JsonOptions{MaxSize: 50_000}},
),
}),
internalCollection(&models.Collection{
Name: TicketCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "name", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "type", Type: schema.FieldTypeRelation, Options: &schema.RelationOptions{CollectionId: TypeCollectionName, MaxSelect: types.Pointer(1)}},
&schema.SchemaField{Name: "description", Type: schema.FieldTypeText},
&schema.SchemaField{Name: "open", Type: schema.FieldTypeBool},
&schema.SchemaField{Name: "resolution", Type: schema.FieldTypeText},
&schema.SchemaField{Name: "schema", Type: schema.FieldTypeJson, Options: &schema.JsonOptions{MaxSize: 50_000}},
&schema.SchemaField{Name: "state", Type: schema.FieldTypeJson, Options: &schema.JsonOptions{MaxSize: 50_000}},
&schema.SchemaField{Name: "owner", Type: schema.FieldTypeRelation, Options: &schema.RelationOptions{CollectionId: UserCollectionName, MaxSelect: types.Pointer(1)}},
),
}),
internalCollection(&models.Collection{
Name: TaskCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "ticket", Type: schema.FieldTypeRelation, Required: true, Options: &schema.RelationOptions{CollectionId: TicketCollectionName, MaxSelect: types.Pointer(1), CascadeDelete: true}},
&schema.SchemaField{Name: "name", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "open", Type: schema.FieldTypeBool},
&schema.SchemaField{Name: "owner", Type: schema.FieldTypeRelation, Options: &schema.RelationOptions{CollectionId: UserCollectionName, MaxSelect: types.Pointer(1)}},
),
}),
internalCollection(&models.Collection{
Name: CommentCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "ticket", Type: schema.FieldTypeRelation, Required: true, Options: &schema.RelationOptions{CollectionId: TicketCollectionName, MaxSelect: types.Pointer(1), CascadeDelete: true}},
&schema.SchemaField{Name: "author", Type: schema.FieldTypeRelation, Options: &schema.RelationOptions{CollectionId: UserCollectionName, MaxSelect: types.Pointer(1)}},
&schema.SchemaField{Name: "message", Type: schema.FieldTypeText, Required: true},
),
}),
internalCollection(&models.Collection{
Name: TimelineCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "ticket", Type: schema.FieldTypeRelation, Required: true, Options: &schema.RelationOptions{CollectionId: TicketCollectionName, MaxSelect: types.Pointer(1), CascadeDelete: true}},
&schema.SchemaField{Name: "time", Type: schema.FieldTypeDate, Required: true},
&schema.SchemaField{Name: "message", Type: schema.FieldTypeText, Required: true},
),
}),
internalCollection(&models.Collection{
Name: LinkCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "ticket", Type: schema.FieldTypeRelation, Required: true, Options: &schema.RelationOptions{CollectionId: TicketCollectionName, MaxSelect: types.Pointer(1), CascadeDelete: true}},
&schema.SchemaField{Name: "name", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "url", Type: schema.FieldTypeUrl, Required: true},
),
}),
internalCollection(&models.Collection{
Name: fileCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "ticket", Type: schema.FieldTypeRelation, Required: true, Options: &schema.RelationOptions{CollectionId: TicketCollectionName, MaxSelect: types.Pointer(1), CascadeDelete: true}},
&schema.SchemaField{Name: "name", Type: schema.FieldTypeText, Required: true},
&schema.SchemaField{Name: "size", Type: schema.FieldTypeNumber, Required: true},
&schema.SchemaField{Name: "blob", Type: schema.FieldTypeFile, Required: true, Options: &schema.FileOptions{MaxSelect: 1, MaxSize: 1024 * 1024 * 100}},
),
}),
{
BaseModel: models.BaseModel{
Id: FeatureCollectionName,
},
Name: FeatureCollectionName,
Type: models.CollectionTypeBase,
Schema: schema.NewSchema(
&schema.SchemaField{Name: "name", Type: schema.FieldTypeText, Required: true},
),
ListRule: types.Pointer("@request.auth.id != ''"),
ViewRule: types.Pointer("@request.auth.id != ''"),
Indexes: types.JsonArray[string]{
fmt.Sprintf("CREATE UNIQUE INDEX `unique_name` ON `%s` (`name`)", FeatureCollectionName),
},
},
}
dao := daos.New(db)
for _, c := range collections {
if err := dao.SaveCollection(c); err != nil {
return err
}
}
return nil
}
func internalCollection(c *models.Collection) *models.Collection {
c.Id = c.Name
c.ListRule = types.Pointer("@request.auth.id != ''")
c.ViewRule = types.Pointer("@request.auth.id != ''")
c.CreateRule = types.Pointer("@request.auth.id != ''")
c.UpdateRule = types.Pointer("@request.auth.id != ''")
c.DeleteRule = types.Pointer("@request.auth.id != ''")
return c
}
func collectionsDown(db dbx.Builder) error {
collections := []string{
TicketCollectionName,
TypeCollectionName,
fileCollectionName,
LinkCollectionName,
TaskCollectionName,
CommentCollectionName,
TimelineCollectionName,
FeatureCollectionName,
}
dao := daos.New(db)
for _, name := range collections {
id, err := dao.FindCollectionByNameOrId(name)
if err != nil {
return err
}
if err := dao.DeleteCollection(id); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,51 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/security"
)
func defaultDataUp(db dbx.Builder) error {
dao := daos.New(db)
for _, records := range [][]*models.Record{typeRecords(dao)} {
for _, record := range records {
if err := dao.SaveRecord(record); err != nil {
return err
}
}
}
return nil
}
func typeRecords(dao *daos.Dao) []*models.Record {
collection, err := dao.FindCollectionByNameOrId(TypeCollectionName)
if err != nil {
panic(err)
}
var records []*models.Record
record := models.NewRecord(collection)
record.SetId("y_" + security.PseudorandomString(5))
record.Set("singular", "Incident")
record.Set("plural", "Incidents")
record.Set("icon", "Flame")
record.Set("schema", `{"type":"object","properties":{"tlp":{"title":"TLP","type":"string"}}}`)
records = append(records, record)
record = models.NewRecord(collection)
record.SetId("y_" + security.PseudorandomString(5))
record.Set("singular", "Alert")
record.Set("plural", "Alerts")
record.Set("icon", "AlertTriangle")
record.Set("schema", `{"type":"object","properties":{"severity":{"title":"Severity","type":"string"}},"required": ["severity"]}`)
records = append(records, record)
return records
}

70
migrations/4_views.go Normal file
View File

@@ -0,0 +1,70 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/types"
)
const (
dashboardCountsViewName = "dashboard_counts"
sidebarViewName = "sidebar"
)
const dashboardCountsViewQuery = `SELECT id, count FROM (
SELECT 'users' as id, COUNT(users.id) as count FROM users
UNION
SELECT 'tickets' as id, COUNT(tickets.id) as count FROM tickets
UNION
SELECT 'tasks' as id, COUNT(tasks.id) as count FROM tasks
) as counts;`
const sidebarViewQuery = `SELECT types.id as id, types.singular as singular, types.plural as plural, types.icon as icon, (SELECT COUNT(tickets.id) FROM tickets WHERE tickets.type = types.id AND tickets.open = true) as count
FROM types
ORDER BY types.plural;`
func viewsUp(db dbx.Builder) error {
collections := []*models.Collection{
internalView(dashboardCountsViewName, dashboardCountsViewQuery),
internalView(sidebarViewName, sidebarViewQuery),
}
dao := daos.New(db)
for _, c := range collections {
if err := dao.SaveCollection(c); err != nil {
return err
}
}
return nil
}
func internalView(name, query string) *models.Collection {
return &models.Collection{
Name: name,
Type: models.CollectionTypeView,
Options: types.JsonMap{"query": query},
ListRule: types.Pointer("@request.auth.id != ''"),
ViewRule: types.Pointer("@request.auth.id != ''"),
}
}
func viewsDown(db dbx.Builder) error {
dao := daos.New(db)
collections := []string{dashboardCountsViewName, sidebarViewName}
for _, c := range collections {
id, err := dao.FindCollectionByNameOrId(c)
if err != nil {
return err
}
if err := dao.DeleteCollection(id); err != nil {
return err
}
}
return nil
}

12
migrations/migrations.go Normal file
View File

@@ -0,0 +1,12 @@
package migrations
import (
"github.com/pocketbase/pocketbase/migrations"
)
func Register() {
migrations.Register(baseUp, baseDown, "1700000000_base.go")
migrations.Register(collectionsUp, collectionsDown, "1700000001_collections.go")
migrations.Register(defaultDataUp, nil, "1700000003_defaultdata.go")
migrations.Register(viewsUp, viewsDown, "1700000004_views.go")
}