|
| 1 | +--- |
| 2 | +'@objectstack/service-analytics': patch |
| 3 | +--- |
| 4 | + |
| 5 | +fix(service-analytics): the analytics field-level read gate refuses a cube member whose `sql` names no field, instead of letting the query run (#20965) |
| 6 | + |
| 7 | +Clause-②: no |
| 8 | + |
| 9 | +**What changed.** Where the analytics field-level read gate judges a cube's |
| 10 | +object (a security service is registered and gives a field answer for that |
| 11 | +object), a query that names a cube member whose `sql` is neither a column |
| 12 | +reference (a field of the cube's object, or a relationship path ending in one) |
| 13 | +nor `'*'` is now refused `403 PERMISSION_DENIED` on |
| 14 | +`POST /api/v1/analytics/query` and `POST /api/v1/analytics/sql`, before either |
| 15 | +strategy runs. Whatever |
| 16 | +the caller may read, the member is refused. That covers an expression member |
| 17 | +of a cube that reached the service without the spec's parse (the cube |
| 18 | +registry never parses: `analyticsCubes` and `AnalyticsServicePlugin({ cubes })` |
| 19 | +arrive as written), a declared member with no `sql` string, and a member the |
| 20 | +query names itself that is not a column reference. The gate used to stand down |
| 21 | +on such a member, because it names no field, and the native-SQL strategy then |
| 22 | +compiled it into its statement as written: a read of fields no permission |
| 23 | +verdict was reached for. The refusal names the member and the object, and |
| 24 | +never the member's `sql`. |
| 25 | + |
| 26 | +**What is not affected.** A member that is a column reference is judged by the |
| 27 | +field it resolves to, as before. A `count` over `'*'` names no field and is |
| 28 | +served. A deployment with no security service, and an object the security |
| 29 | +service gives no field answer for, apply no field-level check, as before. The |
| 30 | +spec's parse already refuses an expression member, so a cube that parses is |
| 31 | +unaffected. |
| 32 | + |
| 33 | +**If a widget stopped answering,** its cube carries an expression member from |
| 34 | +before the parse refused one. Re-author the member as a column reference, or |
| 35 | +declare the derived value on an ADR-0021 dataset: a conditional count or sum |
| 36 | +is a dataset measure with its own `filter`, and a ratio of measures is |
| 37 | +`derived: { op: 'ratio', of: [...] }`. |
0 commit comments