Working on https://github.com/agent-substrate/substrate/issues/1563 ## Summary Initializes an embedded OpenFGA server within `ateapi` backed by PostgreSQL and updates the top-level authorization scope. ## Key Changes - **Rename scope to `global`**: Renamed `type cluster` and `parent_cluster` to `type global` and `parent_global`, adding `can_set_policy` and `can_get_policy` to `global`. - **Embedded OpenFGA server (`internal/authz/server.go`)**: - Compiles `model.fga` into OpenFGA's protobuf representation. - Runs OpenFGA PostgreSQL schema migrations (`goose_db_version`). - Serializes startup via `pg_advisory_lock` to avoid multi-replica races. - Connects OpenFGA's PostgreSQL adapter with a new dedicated `*pgxpool.Pool`. - Idempotently creates or reuses the `"substrate"` store and authorization model. - **Service wiring (`cmd/ateapi`)**: Exposes `Pool()` on `*atepg.Persistence` and initializes `authz.NewServer` on bootstrap. ## Verification - `openfga model test`: 103/103 checks passing (`model_test.fga.yaml`). - `go test -mod=mod ./internal/authz/...`: Passes against PostgreSQL (migrations, tuple writes, permission checks, and restart idempotency).
4.3 KiB
Squirrel is "complete".
Bug fixes will still be merged (slowly). Bug reports are welcome, but I will not necessarily respond to them. If another fork (or substantially similar project) actively improves on what Squirrel does, let me know and I may link to it here.
Squirrel - fluent SQL generator for Go
import "github.com/Masterminds/squirrel"
Squirrel is not an ORM. For an application of Squirrel, check out structable, a table-struct mapper
Squirrel helps you build SQL queries from composable parts:
import sq "github.com/Masterminds/squirrel"
users := sq.Select("*").From("users").Join("emails USING (email_id)")
active := users.Where(sq.Eq{"deleted_at": nil})
sql, args, err := active.ToSql()
sql == "SELECT * FROM users JOIN emails USING (email_id) WHERE deleted_at IS NULL"
sql, args, err := sq.
Insert("users").Columns("name", "age").
Values("moe", 13).Values("larry", sq.Expr("? + 5", 12)).
ToSql()
sql == "INSERT INTO users (name,age) VALUES (?,?),(?,? + 5)"
Squirrel can also execute queries directly:
stooges := users.Where(sq.Eq{"username": []string{"moe", "larry", "curly", "shemp"}})
three_stooges := stooges.Limit(3)
rows, err := three_stooges.RunWith(db).Query()
// Behaves like:
rows, err := db.Query("SELECT * FROM users WHERE username IN (?,?,?,?) LIMIT 3",
"moe", "larry", "curly", "shemp")
Squirrel makes conditional query building a breeze:
if len(q) > 0 {
users = users.Where("name LIKE ?", fmt.Sprint("%", q, "%"))
}
Squirrel wants to make your life easier:
// StmtCache caches Prepared Stmts for you
dbCache := sq.NewStmtCache(db)
// StatementBuilder keeps your syntax neat
mydb := sq.StatementBuilder.RunWith(dbCache)
select_users := mydb.Select("*").From("users")
Squirrel loves PostgreSQL:
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
// You use question marks for placeholders...
sql, _, _ := psql.Select("*").From("elephants").Where("name IN (?,?)", "Dumbo", "Verna").ToSql()
/// ...squirrel replaces them using PlaceholderFormat.
sql == "SELECT * FROM elephants WHERE name IN ($1,$2)"
/// You can retrieve id ...
query := sq.Insert("nodes").
Columns("uuid", "type", "data").
Values(node.Uuid, node.Type, node.Data).
Suffix("RETURNING \"id\"").
RunWith(m.db).
PlaceholderFormat(sq.Dollar)
query.QueryRow().Scan(&node.id)
You can escape question marks by inserting two question marks:
SELECT * FROM nodes WHERE meta->'format' ??| array[?,?]
will generate with the Dollar Placeholder:
SELECT * FROM nodes WHERE meta->'format' ?| array[$1,$2]
FAQ
-
How can I build an IN query on composite keys / tuples, e.g.
WHERE (col1, col2) IN ((1,2),(3,4))? (#104)Squirrel does not explicitly support tuples, but you can get the same effect with e.g.:
sq.Or{ sq.Eq{"col1": 1, "col2": 2}, sq.Eq{"col1": 3, "col2": 4}}WHERE (col1 = 1 AND col2 = 2) OR (col1 = 3 AND col2 = 4)(which should produce the same query plan as the tuple version)
-
Why doesn't
Eq{"mynumber": []uint8{1,2,3}}turn into anINquery? (#114)Values of type
[]byteare handled specially bydatabase/sql. In Go,byteis just an alias ofuint8, so there is no way to distinguish[]uint8from[]byte. -
Some features are poorly documented!
This isn't a frequent complaints section!
-
Some features are poorly documented?
Yes. The tests should be considered a part of the documentation; take a look at those for ideas on how to express more complex queries.
License
Squirrel is released under the MIT License.
