-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/likes #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/likes #41
Changes from all commits
c2cac40
87fc9d4
83db485
2fedb08
731ec2e
f9aaa4a
2a9250e
bdf6489
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "database/sql" | ||
| "embed" | ||
| "errors" | ||
| "fmt" | ||
| "io/fs" | ||
| "log" | ||
|
|
||
|
|
@@ -41,6 +44,75 @@ func main() { | |
| app.OnServe().BindFunc(func(se *core.ServeEvent) error { | ||
| Setup(se.App) | ||
|
|
||
| se.Router.POST("/api/{type}/{id}/toggle-like", func(e *core.RequestEvent) error { | ||
| requestCollection := e.Request.PathValue("type") | ||
| targetId := e.Request.PathValue("id") // 被点赞物体的 ID | ||
| userId := e.Auth.Id | ||
|
|
||
| if requestCollection != "cps" && requestCollection != "characters" { | ||
| return e.Error(400, "Invalid request data", map[string]validation.Error{ | ||
| "type": validation.NewError("validation_collection_type", "Invalid collection type."), | ||
| }) | ||
| } | ||
|
|
||
| collection, err := app.FindCollectionByNameOrId("likes") | ||
| if err != nil { | ||
| return e.InternalServerError("Internal Server Error", map[string]any{"message": "Cannot find collection", "err": err}) | ||
| } | ||
|
|
||
| existingRecord, err := app.FindFirstRecordByFilter("likes", | ||
| fmt.Sprintf("user = '%s' && target_id = '%s'", userId, targetId), | ||
| ) | ||
|
BretRen marked this conversation as resolved.
Comment on lines
+63
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, locate and examine main.go to understand the context around lines 63-65
fd -t f "main.go" | head -5Repository: pdnode-team/cp Length of output: 65 🏁 Script executed: # Get context around the flagged lines to understand the full implementation
head -120 main.go | tail -70Repository: pdnode-team/cp Length of output: 1909 🏁 Script executed: # Check if there's a schema or migration file that defines the likes collection structure
fd -t f "migrations" | grep -E "\.(go|sql)$" | head -10Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Search for "likes" collection references to understand its schema
rg "likes" -A 3 -B 1 | head -50Repository: pdnode-team/cp Length of output: 2874 🏁 Script executed: # Search for other uses of FindFirstRecordByFilter to understand the API
rg "FindFirstRecordByFilter" -B 2 -A 2Repository: pdnode-team/cp Length of output: 241 🏁 Script executed: # Search for dbx.Params usage to see if this pattern is used elsewhere
rg "dbx\.Params" -B 2 -A 2Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check imports to understand what dbx package is
head -30 main.go | grep -E "^import|dbx"Repository: pdnode-team/cp Length of output: 95 🏁 Script executed: # Search for how filters are used elsewhere in the codebase
rg "FindFirstRecordByFilter\|FindRecordById\|GetList" -A 3 | head -40Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Look at PocketBase examples or tests to understand the filter API
rg "fmt\.Sprintf.*&&\|fmt\.Sprintf.*\|\|" -B 1 -A 1 | head -30Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check if there's any documentation or comments about the filter syntax
rg "filter|Filter" --type go -B 1 -A 1 | grep -E "(//|/\*)" | head -20Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check if there are other filter usages in main.go or if dbx is imported
rg "dbx" main.goRepository: pdnode-team/cp Length of output: 235 🏁 Script executed: # Look for all filter strings to understand the pattern
rg "\&\&" main.goRepository: pdnode-team/cp Length of output: 287 🏁 Script executed: # Check PocketBase documentation via web search or examine if there are type definitions
grep -r "FindFirstRecordByFilter" . 2>/dev/null | head -5Repository: pdnode-team/cp Length of output: 130 🏁 Script executed: # Search for how dbx is actually used in query patterns
rg "Where\(dbx" -B 2 -A 3Repository: pdnode-team/cp Length of output: 263 🏁 Script executed: # Check if there's a go.mod to understand PocketBase version
cat go.mod | grep pocketbaseRepository: pdnode-team/cp Length of output: 134 🏁 Script executed: # Search for the actual signature of FindFirstRecordByFilter or related methods
rg "func.*FindFirstRecord|func.*GetOne|func.*FindRecord" --type go -A 2Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Look for any imports or examples that show how to use filters safely with PocketBase
rg "RecordFilter|Filter\(" main.go -B 2 -A 2Repository: pdnode-team/cp Length of output: 201 🏁 Script executed: # Check if there's usage of filter with parameters elsewhere
rg "filter.*:|\{:.*\}" -B 1 -A 1Repository: pdnode-team/cp Length of output: 3638 🏁 Script executed: # Check PocketBase filter documentation by looking for examples in the codebase
rg "FindFirstRecordByFilter|FindRecordsByFilter" -B 5 -A 5 | head -60Repository: pdnode-team/cp Length of output: 551 🏁 Script executed: # Look for how PocketBase filters are documented in comments or test files
find . -name "*.go" -type f -exec grep -l "filter" {} \; | xargs grep -l "user\|target" | head -3Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Search web documentation for PocketBase FindFirstRecordByFilter API
# to verify if it supports parameterized queriesRepository: pdnode-team/cp Length of output: 40 🌐 Web query:
💡 Result: In PocketBase v0.36 (latest as of 2026-04-21, with releases up to v0.36.8), the FindFirstRecordByFilter method supports parameterized queries using dbx syntax for safe binding of untrusted user input. Syntax (JSVM/Go): app.FindFirstRecordByFilter("posts", "slug = {:slug} && status = 'public'", dbx.Params{"slug": "test"}) - First argument: collection name or model. - Second: filter string with {:paramName} placeholders. - Last (variadic): dbx.Params{key: value} map(s) for binding parameters, preventing SQL injection. This works in both Go backend code and JSVM hooks/routes. Returns sql.ErrNoRows if no match. No breaking changes in v0.36 affecting this; query optimizations were added but syntax remains the same. Alternative for complex queries: use app.RecordQuery(collection).AndWhere(dbx.HashExp{"field": value}) or dbx.NewExp. Example: record := core.NewRecord(collection) $app.dao.recordQuery("posts") .andWhere(dbx.NewExp("slug = {:slug}", dbx.Params{"slug": slug})) .limit(1) .one(record) Citations:
Add The query at line 64 omits 🐛 Proposed fix existingRecord, err := app.FindFirstRecordByFilter("likes",
- fmt.Sprintf("user = '%s' && target_id = '%s'", userId, targetId),
+ "user = {:userId} && target_id = {:targetId} && target_collection = {:targetCollection}",
+ dbx.Params{
+ "userId": userId,
+ "targetId": targetId,
+ "targetCollection": requestCollection,
+ },
)🤖 Prompt for AI Agents |
||
|
|
||
| if err != nil { | ||
| if !errors.Is(err, sql.ErrNoRows) { | ||
| return e.InternalServerError("Internal Server Error", map[string]any{ | ||
| "message": "Cannot find record", | ||
| "err": err, | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| if existingRecord != nil { | ||
|
|
||
| err = app.Delete(existingRecord) | ||
| if err != nil { | ||
| return e.InternalServerError("Internal Server Error", map[string]any{ | ||
| "message": "Cannot delete record", | ||
| "err": err, | ||
| }) | ||
| } | ||
|
|
||
| return e.JSON(200, map[string]any{ | ||
| "message": "Success", | ||
| "like": false, | ||
| "data": existingRecord, | ||
| }) | ||
| } | ||
|
|
||
| record := core.NewRecord(collection) | ||
|
|
||
| record.Set("target_id", targetId) | ||
| record.Set("target_collection", requestCollection) | ||
| record.Set("user", e.Auth.Id) | ||
|
|
||
| err = app.Save(record) | ||
|
Comment on lines
+52
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's find and examine the main.go file
find . -name "main.go" -type f | head -5Repository: pdnode-team/cp Length of output: 67 🏁 Script executed: # Get the file structure to understand the repository
git ls-files | head -20Repository: pdnode-team/cp Length of output: 623 🏁 Script executed: # Read the relevant section of main.go
cat -n main.go | sed -n '50,105p'Repository: pdnode-team/cp Length of output: 2016 🏁 Script executed: # Search for FindRecordById and FindFirstRecordByFilter method definitions
rg "FindRecordById|FindFirstRecordByFilter" -A 5Repository: pdnode-team/cp Length of output: 303 🏁 Script executed: # Search for FindRecordById method definition
rg "func.*FindRecordById" -A 3Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Also check if there's a method to get records by ID
rg "func.*\(.*\).*FindRecord" | head -20Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check if this is a PocketBase application
rg "pocketbase" -iRepository: pdnode-team/cp Length of output: 5683 🏁 Script executed: # Search for method definitions on app variable
rg "app\.\w+\(" main.go | head -20Repository: pdnode-team/cp Length of output: 803 🏁 Script executed: # Look at imports to understand the framework
head -30 main.goRepository: pdnode-team/cp Length of output: 627 🏁 Script executed: # Get more context of the endpoint handler
cat -n main.go | sed -n '35,110p'Repository: pdnode-team/cp Length of output: 2820 🏁 Script executed: # Check if FindRecordById is used anywhere in the codebase
rg "FindRecordById|GetRecordById"Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check the go.mod to see the exact PocketBase version
cat go.modRepository: pdnode-team/cp Length of output: 1607 🏁 Script executed: # Search for how records are fetched in the codebase - look at other patterns
rg "app\.\w+Record" main.go config.goRepository: pdnode-team/cp Length of output: 541 🏁 Script executed: # Check PocketBase official documentation for available methods
# Let's search for any other record-fetching patterns in the codebase
rg "app\." main.go config.go | grep -i recordRepository: pdnode-team/cp Length of output: 620 🏁 Script executed: # Let's check config.go to see how records are typically accessed
cat config.goRepository: pdnode-team/cp Length of output: 3959 🏁 Script executed: # Search for any method that gets a record by ID in the entire codebase
rg "Record\(" | head -20Repository: pdnode-team/cp Length of output: 105 🏁 Script executed: # Check if there are any examples of fetching records in migrations or elsewhere
rg "FindRecord|GetRecord" --type goRepository: pdnode-team/cp Length of output: 40 🌐 Web query:
💡 Result: There is no official Go SDK for PocketBase client-side API interactions (only JS and Dart SDKs are official). Community-maintained Go SDKs exist, such as github.com/habibrosyad/pocketbase-go-sdk, but they do not have a method named FindRecordById. PocketBase core (github.com/pocketbase/pocketbase v0.36.9) has app.FindRecordById(collectionName, recordId) *core.Record, used server-side when extending PocketBase with Go. This method retrieves a single record by ID from the specified collection, returning nil and sql.ErrNoRows if not found. Example usage (server-side): record, err := app.FindRecordById("articles", "RECORD_ID") if err != nil { // handle error (e.g., sql.ErrNoRows if not found) } In community client SDKs like habibrosyad/pocketbase-go-sdk, use client.One(collectionName, recordId) map[string]any to fetch a single record by ID as a raw map, or client.OneTo(collectionName, recordId, &target) to unmarshal into a struct. Example (client-side with community SDK): record, err := client.One("posts_public", "record_id") if err != nil { log.Fatal(err) } log.Print(record["field"]) Citations:
🏁 Script executed: # Let's also check if there's a Find method with different patterns
rg "func.*Find.*Record" --type go | head -20Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Verify e.BadRequestError method exists in the codebase or is available in pocketbase
rg "BadRequestError|e\.Error" main.go | head -10Repository: pdnode-team/cp Length of output: 288 Validate that the liked target actually exists. The endpoint validates only the collection name, then saves arbitrary 🛡️ Proposed validation if requestCollection != "cps" && requestCollection != "characters" {
return e.Error(400, "Invalid request data", map[string]validation.Error{
"type": validation.NewError("validation_collection_type", "Invalid collection type."),
})
}
+
+ if _, err := app.FindRecordById(requestCollection, targetId); err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ return e.BadRequestError("Invalid request data", map[string]validation.Error{
+ "id": validation.NewError("validation_target_not_found", "Target record does not exist."),
+ })
+ }
+ return e.InternalServerError("Internal Server Error", nil)
+ }
collection, err := app.FindCollectionByNameOrId("likes")🤖 Prompt for AI Agents |
||
|
|
||
| if err != nil { | ||
| return e.InternalServerError("Internal Server Error", map[string]any{ | ||
| "message": "Cannot save record", | ||
| "err": err, | ||
| }) | ||
| } | ||
|
|
||
| return e.JSON(200, map[string]any{ | ||
| "message": "Success", | ||
| "like": true, | ||
| "data": record, | ||
| }) | ||
|
|
||
| }).Bind(apis.RequireAuth()) | ||
|
|
||
| publicFS, err := fs.Sub(embeddedFiles, "pb_public") | ||
| if err != nil { | ||
| return err | ||
|
|
@@ -82,7 +154,7 @@ func validateIdImmutable(e *core.RecordRequestEvent) error { | |
|
|
||
| // 检查用户有没有传入id | ||
| if e.Record.Id != "" { | ||
| return apis.NewBadRequestError("Invalid request data", map[string]validation.Error{ | ||
| return e.BadRequestError("Invalid request data", map[string]validation.Error{ | ||
| "id": validation.NewError("validation_id_immutable", "Custom record IDs are not allowed."), | ||
| }) | ||
| } | ||
|
|
@@ -94,7 +166,7 @@ func validateIdImmutable(e *core.RecordRequestEvent) error { | |
| func validateCharactersOwnership(e *core.RecordRequestEvent) error { | ||
|
|
||
| if e.Auth == nil { | ||
| return apis.NewUnauthorizedError("Unauthorized", nil) | ||
| return e.UnauthorizedError("Unauthorized", nil) | ||
| } | ||
|
|
||
| // Superuser 绕过 | ||
|
|
@@ -125,12 +197,12 @@ func validateCharactersOwnership(e *core.RecordRequestEvent) error { | |
| Row(&count) | ||
|
|
||
| if err != nil { | ||
| return apis.NewInternalServerError("Database query failed", err) | ||
| return e.InternalServerError("Database query failed", err) | ||
| } | ||
|
|
||
| // 如果发现有角色不属于该用户,拦截请求 | ||
| if count > 0 { | ||
| return apis.NewBadRequestError("Illegal association", map[string]validation.Error{ | ||
| return e.Error(403, "Illegal association", map[string]validation.Error{ | ||
| "characters": validation.NewError("invalid_character_owner", "One or more selected characters do not belong to you."), | ||
| }) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| package migrations | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
|
|
||
| "github.com/pocketbase/pocketbase/core" | ||
| m "github.com/pocketbase/pocketbase/migrations" | ||
| ) | ||
|
|
||
| func init() { | ||
| m.Register(func(app core.App) error { | ||
| jsonData := `{ | ||
| "createRule": null, | ||
| "deleteRule": null, | ||
| "fields": [ | ||
| { | ||
| "autogeneratePattern": "[a-z0-9]{15}", | ||
| "hidden": false, | ||
| "id": "text3208210256", | ||
| "max": 15, | ||
| "min": 15, | ||
| "name": "id", | ||
| "pattern": "^[a-z0-9]+$", | ||
| "presentable": false, | ||
| "primaryKey": true, | ||
| "required": true, | ||
| "system": true, | ||
| "type": "text" | ||
| }, | ||
| { | ||
| "cascadeDelete": true, | ||
| "collectionId": "_pb_users_auth_", | ||
| "hidden": false, | ||
| "id": "relation2375276105", | ||
| "maxSelect": 1, | ||
| "minSelect": 0, | ||
| "name": "user", | ||
| "presentable": false, | ||
| "required": true, | ||
| "system": false, | ||
| "type": "relation" | ||
| }, | ||
| { | ||
| "autogeneratePattern": "", | ||
| "hidden": false, | ||
| "id": "text361630566", | ||
| "max": 0, | ||
| "min": 0, | ||
| "name": "target_id", | ||
| "pattern": "", | ||
| "presentable": false, | ||
| "primaryKey": false, | ||
| "required": true, | ||
| "system": false, | ||
| "type": "text" | ||
| }, | ||
| { | ||
| "hidden": false, | ||
| "id": "select3466706339", | ||
| "maxSelect": 1, | ||
| "name": "target_collection", | ||
| "presentable": false, | ||
| "required": false, | ||
|
BretRen marked this conversation as resolved.
|
||
| "system": false, | ||
| "type": "select", | ||
| "values": [ | ||
| "cps", | ||
| "ccharacters" | ||
| ] | ||
| }, | ||
| { | ||
| "hidden": false, | ||
| "id": "autodate2990389176", | ||
| "name": "created", | ||
| "onCreate": true, | ||
| "onUpdate": false, | ||
| "presentable": false, | ||
| "system": false, | ||
| "type": "autodate" | ||
| }, | ||
| { | ||
| "hidden": false, | ||
| "id": "autodate3332085495", | ||
| "name": "updated", | ||
| "onCreate": true, | ||
| "onUpdate": true, | ||
| "presentable": false, | ||
| "system": false, | ||
| "type": "autodate" | ||
| } | ||
| ], | ||
| "id": "pbc_2190274710", | ||
| "indexes": [ | ||
| "CREATE UNIQUE INDEX ` + "`" + `idx_unique_user_like` + "`" + ` ON ` + "`" + `likes` + "`" + ` (\n ` + "`" + `user` + "`" + `,\n ` + "`" + `target_id` + "`" + `,\n ` + "`" + `target_collection` + "`" + `\n)" | ||
| ], | ||
| "listRule": null, | ||
| "name": "likes", | ||
| "system": false, | ||
| "type": "base", | ||
| "updateRule": null, | ||
| "viewRule": null | ||
| }` | ||
|
|
||
| collection := &core.Collection{} | ||
| if err := json.Unmarshal([]byte(jsonData), &collection); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Save(collection) | ||
| }, func(app core.App) error { | ||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Delete(collection) | ||
| }) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package migrations | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
|
|
||
| "github.com/pocketbase/pocketbase/core" | ||
| m "github.com/pocketbase/pocketbase/migrations" | ||
| ) | ||
|
|
||
| func init() { | ||
| m.Register(func(app core.App) error { | ||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // update collection data | ||
| if err := json.Unmarshal([]byte(`{ | ||
| "indexes": [ | ||
| "CREATE UNIQUE INDEX ` + "`" + `idx_unique_user_like` + "`" + ` ON ` + "`" + `likes` + "`" + ` (\n ` + "`" + `user` + "`" + `,\n ` + "`" + `target_id` + "`" + `,\n ` + "`" + `target_collection` + "`" + `\n)", | ||
| "CREATE INDEX ` + "`" + `idx_target_lookup` + "`" + ` ON ` + "`" + `likes` + "`" + ` (\n ` + "`" + `target_id` + "`" + `,\n ` + "`" + `target_collection` + "`" + `\n)" | ||
| ] | ||
| }`), &collection); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Save(collection) | ||
| }, func(app core.App) error { | ||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // update collection data | ||
| if err := json.Unmarshal([]byte(`{ | ||
| "indexes": [ | ||
| "CREATE UNIQUE INDEX ` + "`" + `idx_unique_user_like` + "`" + ` ON ` + "`" + `likes` + "`" + ` (\n ` + "`" + `user` + "`" + `,\n ` + "`" + `target_id` + "`" + `,\n ` + "`" + `target_collection` + "`" + `\n)" | ||
| ] | ||
| }`), &collection); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Save(collection) | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package migrations | ||
|
|
||
| import ( | ||
| "github.com/pocketbase/pocketbase/core" | ||
| m "github.com/pocketbase/pocketbase/migrations" | ||
| ) | ||
|
|
||
| func init() { | ||
| m.Register(func(app core.App) error { | ||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // update field | ||
| if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{ | ||
| "hidden": false, | ||
| "id": "select3466706339", | ||
| "maxSelect": 1, | ||
| "name": "target_collection", | ||
| "presentable": false, | ||
| "required": false, | ||
| "system": false, | ||
| "type": "select", | ||
| "values": [ | ||
| "cps", | ||
| "characters" | ||
| ] | ||
| }`)); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Save(collection) | ||
| }, func(app core.App) error { | ||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // update field | ||
| if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{ | ||
| "hidden": false, | ||
| "id": "select3466706339", | ||
| "maxSelect": 1, | ||
| "name": "target_collection", | ||
| "presentable": false, | ||
| "required": false, | ||
| "system": false, | ||
| "type": "select", | ||
| "values": [ | ||
| "cps", | ||
| "ccharacters" | ||
| ] | ||
| }`)); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return app.Save(collection) | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||||||||||||||
| package migrations | ||||||||||||||||||
|
|
||||||||||||||||||
| import ( | ||||||||||||||||||
| "encoding/json" | ||||||||||||||||||
|
|
||||||||||||||||||
| "github.com/pocketbase/pocketbase/core" | ||||||||||||||||||
| m "github.com/pocketbase/pocketbase/migrations" | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| func init() { | ||||||||||||||||||
| m.Register(func(app core.App) error { | ||||||||||||||||||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||||||||||||||||||
| if err != nil { | ||||||||||||||||||
| return err | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // update collection data | ||||||||||||||||||
| if err := json.Unmarshal([]byte(`{ | ||||||||||||||||||
| "listRule": "", | ||||||||||||||||||
| "viewRule": "" | ||||||||||||||||||
| }`), &collection); err != nil { | ||||||||||||||||||
|
Comment on lines
+18
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd /tmp && find . -name "*migrations*" -type d 2>/dev/null | head -5Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check if the likes migration file exists
find . -name "1776728364_updated_likes.go" 2>/dev/nullRepository: pdnode-team/cp Length of output: 98 🏁 Script executed: # Also search for the file more broadly
find . -name "*likes*" -type f 2>/dev/null | grep -E "\.(go|json)$"Repository: pdnode-team/cp Length of output: 221 🏁 Script executed: # Check the repo structure
git ls-files | head -20Repository: pdnode-team/cp Length of output: 623 🏁 Script executed: # Read the full migration file to understand the context
cat -n ./migrations/1776728364_updated_likes.goRepository: pdnode-team/cp Length of output: 1165 🏁 Script executed: # Also check the initial creation of likes to see if access was always public
cat -n ./migrations/1776715443_created_likes.goRepository: pdnode-team/cp Length of output: 3469 🏁 Script executed: # Check other migration files to see the pattern for collections
cat -n ./migrations/1776131344_created_cps.go | head -40Repository: pdnode-team/cp Length of output: 1250 🏁 Script executed: # Check if there's documentation about access rules
find . -name "*.md" -o -name "*.txt" | xargs grep -l "likes\|viewRule\|listRule" 2>/dev/nullRepository: pdnode-team/cp Length of output: 42 🏁 Script executed: # Look for any schema documentation or comments in main config
cat -n ./config.go | head -50Repository: pdnode-team/cp Length of output: 1335 🏁 Script executed: # Check other migrations to see access patterns in other collections
rg "listRule\|viewRule" migrations/ -A 2 -B 2 | head -80Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Look for any explicit justification or comments about public likes
git log --oneline migrations/1776728364_updated_likes.go 2>/dev/null | head -5Repository: pdnode-team/cp Length of output: 88 🏁 Script executed: # Check if there are any other recent migrations to understand intent
ls -la migrations/ | tail -20Repository: pdnode-team/cp Length of output: 1581 🏁 Script executed: # Check the intermediate migrations to see the progression of access rules
cat -n ./migrations/1776715655_updated_likes.goRepository: pdnode-team/cp Length of output: 1755 🏁 Script executed: # Check the next intermediate migration
cat -n ./migrations/1776715948_updated_likes.goRepository: pdnode-team/cp Length of output: 1672 🏁 Script executed: # Check the users migration to see if there's documentation about why viewRule was made public
cat -n ./migrations/1776571426_updated_users.goRepository: pdnode-team/cp Length of output: 1132 🏁 Script executed: # Check if there's a frontend or documentation explaining public likes access
find . -name "*.js" -o -name "*.ts" -o -name "*.md" | xargs grep -l "likes" 2>/dev/null | head -5Repository: pdnode-team/cp Length of output: 40 🏁 Script executed: # Check git history to see if there's a commit message explaining the change to public likes
git log --all --oneline -- migrations/1776728364_updated_likes.go 2>/dev/nullRepository: pdnode-team/cp Length of output: 88 🏁 Script executed: # Check the full git log for the likes migrations to understand the progression
git log --all --oneline -- migrations/*likes* 2>/dev/nullRepository: pdnode-team/cp Length of output: 88 🏁 Script executed: # Look for any README or documentation about the app's architecture
cat -n ./README.md 2>/dev/null | head -50Repository: pdnode-team/cp Length of output: 40 Restrict likes to authenticated owner only. Setting both 🔒 Proposed rule tightening- "listRule": "",
- "viewRule": ""
+ "listRule": "@request.auth.id != \"\" && user = `@request.auth.id`",
+ "viewRule": "@request.auth.id != \"\" && user = `@request.auth.id`"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| return err | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return app.Save(collection) | ||||||||||||||||||
| }, func(app core.App) error { | ||||||||||||||||||
| collection, err := app.FindCollectionByNameOrId("pbc_2190274710") | ||||||||||||||||||
| if err != nil { | ||||||||||||||||||
| return err | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // update collection data | ||||||||||||||||||
| if err := json.Unmarshal([]byte(`{ | ||||||||||||||||||
| "listRule": null, | ||||||||||||||||||
| "viewRule": null | ||||||||||||||||||
| }`), &collection); err != nil { | ||||||||||||||||||
| return err | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return app.Save(collection) | ||||||||||||||||||
| }) | ||||||||||||||||||
| } | ||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.