@omnifyjp/ts 5.8.13 → 5.8.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/php/policy-generator.d.ts +19 -1
- package/dist/php/policy-generator.js +51 -10
- package/dist/types.d.ts +11 -0
- package/package.json +1 -1
|
@@ -7,7 +7,25 @@
|
|
|
7
7
|
import { SchemaReader } from './schema-reader.js';
|
|
8
8
|
import type { GeneratedFile, PhpConfig } from './types.js';
|
|
9
9
|
import type { SchemaDefinition, SingleCondition } from '../types.js';
|
|
10
|
-
/** Generate Laravel Policy classes for
|
|
10
|
+
/** Generate Laravel Policy classes for project-owned visible schemas.
|
|
11
|
+
*
|
|
12
|
+
* Issue #98 v5.8.14: every `kind: object` schema now gets a generated
|
|
13
|
+
* policy base + editable stub by default — Laravel's policy
|
|
14
|
+
* auto-discovery (`App\\Models\\<Name>` → `App\\Policies\\<Name>Policy`)
|
|
15
|
+
* works out of the box without per-project Gate::policy(...) wiring.
|
|
16
|
+
*
|
|
17
|
+
* Skip rules:
|
|
18
|
+
* - `kind: pivot` — pivots have no API surface
|
|
19
|
+
* - `options.policy: false` — explicit per-schema opt-out
|
|
20
|
+
*
|
|
21
|
+
* Two code paths per schema:
|
|
22
|
+
* - Explicit Cedar-style `policies: [...]` → existing rule-based body
|
|
23
|
+
* generator (forbid / permit / when conditions).
|
|
24
|
+
* - No `policies:` declared → standard CRUD scaffolding (viewAny /
|
|
25
|
+
* view / create / update / delete + restore / forceDelete on
|
|
26
|
+
* softDelete). Default body: `return true;`. Project secures by
|
|
27
|
+
* overriding the method in the editable child.
|
|
28
|
+
*/
|
|
11
29
|
export declare function generatePolicies(reader: SchemaReader, config: PhpConfig): GeneratedFile[];
|
|
12
30
|
/** Convert a single condition to a PHP expression. */
|
|
13
31
|
export declare function conditionToPhp(cond: SingleCondition, schema: SchemaDefinition, reader: SchemaReader): string;
|
|
@@ -24,11 +24,31 @@ const RECORD_ACTIONS = new Set(['view', 'edit', 'delete']);
|
|
|
24
24
|
// ============================================================================
|
|
25
25
|
// Public API
|
|
26
26
|
// ============================================================================
|
|
27
|
-
/** Generate Laravel Policy classes for
|
|
27
|
+
/** Generate Laravel Policy classes for project-owned visible schemas.
|
|
28
|
+
*
|
|
29
|
+
* Issue #98 v5.8.14: every `kind: object` schema now gets a generated
|
|
30
|
+
* policy base + editable stub by default — Laravel's policy
|
|
31
|
+
* auto-discovery (`App\\Models\\<Name>` → `App\\Policies\\<Name>Policy`)
|
|
32
|
+
* works out of the box without per-project Gate::policy(...) wiring.
|
|
33
|
+
*
|
|
34
|
+
* Skip rules:
|
|
35
|
+
* - `kind: pivot` — pivots have no API surface
|
|
36
|
+
* - `options.policy: false` — explicit per-schema opt-out
|
|
37
|
+
*
|
|
38
|
+
* Two code paths per schema:
|
|
39
|
+
* - Explicit Cedar-style `policies: [...]` → existing rule-based body
|
|
40
|
+
* generator (forbid / permit / when conditions).
|
|
41
|
+
* - No `policies:` declared → standard CRUD scaffolding (viewAny /
|
|
42
|
+
* view / create / update / delete + restore / forceDelete on
|
|
43
|
+
* softDelete). Default body: `return true;`. Project secures by
|
|
44
|
+
* overriding the method in the editable child.
|
|
45
|
+
*/
|
|
28
46
|
export function generatePolicies(reader, config) {
|
|
29
47
|
const files = [];
|
|
30
48
|
for (const [name, schema] of Object.entries(reader.getProjectVisibleObjectSchemas())) {
|
|
31
|
-
if (
|
|
49
|
+
if (schema.kind === 'pivot')
|
|
50
|
+
continue;
|
|
51
|
+
if (schema.options?.policy === false)
|
|
32
52
|
continue;
|
|
33
53
|
files.push(...generateForSchema(name, schema, reader, config));
|
|
34
54
|
}
|
|
@@ -45,7 +65,16 @@ function generateForSchema(name, schema, reader, config) {
|
|
|
45
65
|
}
|
|
46
66
|
function generateBasePolicyClass(name, schema, reader, config) {
|
|
47
67
|
const modelName = toPascalCase(name);
|
|
48
|
-
|
|
68
|
+
// Issue #98 v5.8.15: legacy structure must nest the policy base's
|
|
69
|
+
// `namespace ...;` declaration by group folder so it matches the
|
|
70
|
+
// grouped path on disk. Pre-fix every base emitted
|
|
71
|
+
// `namespace App\\Omnify\\Policies;` (FLAT) while the file lived at
|
|
72
|
+
// `app/Omnify/Policies/<Group>/<Name>Policy.php` — PSR-4 autoload
|
|
73
|
+
// failed at runtime for every grouped policy. Same template fix
|
|
74
|
+
// that v5.8.2 applied to Requests / Resources / Services.
|
|
75
|
+
const baseNamespace = config.structure === 'modular'
|
|
76
|
+
? resolveModularBaseNamespace(config, name, 'Policies', config.policies.baseNamespace)
|
|
77
|
+
: nestByGroup({ path: '', namespace: config.policies.baseNamespace }, schema.group).namespace;
|
|
49
78
|
// Issue #98 v5.8.13: policy method signatures (`view(User $user,
|
|
50
79
|
// <Model> $record): bool`) must type-hint the USER-EDITABLE Model
|
|
51
80
|
// class. Same root cause + fix as the v5.8.11 service / controller
|
|
@@ -59,24 +88,36 @@ function generateBasePolicyClass(name, schema, reader, config) {
|
|
|
59
88
|
: (config.models.userEditableGroupByFolder
|
|
60
89
|
? nestByGroup({ path: '', namespace: config.models.userEditableNamespace }, schema.group).namespace
|
|
61
90
|
: config.models.userEditableNamespace);
|
|
62
|
-
|
|
91
|
+
// Issue #98 v5.8.14: when no Cedar-style `policies:` array is defined,
|
|
92
|
+
// emit the standard CRUD scaffold with `return true;` bodies.
|
|
93
|
+
// The project secures the policy by overriding methods in the
|
|
94
|
+
// editable child (e.g. `return $user->hasPermission('manage.banner');`).
|
|
95
|
+
const policies = schema.policies ?? [];
|
|
96
|
+
const hasExplicitPolicies = policies.length > 0;
|
|
63
97
|
const hasSoftDelete = schema.options?.softDelete ?? false;
|
|
64
|
-
const needsCidrHelper = policiesUseCidr(policies);
|
|
65
|
-
// Collect all actions that have policies
|
|
66
|
-
|
|
98
|
+
const needsCidrHelper = hasExplicitPolicies ? policiesUseCidr(policies) : false;
|
|
99
|
+
// Collect all actions that have policies (only relevant for the
|
|
100
|
+
// explicit-policy path; standard CRUD doesn't need wildcard expansion).
|
|
101
|
+
const expandedPolicies = hasExplicitPolicies ? expandWildcards(policies) : policies;
|
|
67
102
|
// Build methods
|
|
68
103
|
const methods = [];
|
|
69
104
|
for (const action of ALL_ACTIONS) {
|
|
70
105
|
const methodName = ACTION_METHOD_MAP[action];
|
|
71
106
|
const hasRecord = RECORD_ACTIONS.has(action);
|
|
72
|
-
const body =
|
|
107
|
+
const body = hasExplicitPolicies
|
|
108
|
+
? generateMethodBody(action, expandedPolicies, schema, reader, hasRecord)
|
|
109
|
+
: ' return true;';
|
|
73
110
|
methods.push(buildMethod(methodName, modelName, hasRecord, body));
|
|
74
111
|
}
|
|
75
112
|
// SoftDelete: restore + forceDelete
|
|
76
113
|
if (hasSoftDelete) {
|
|
77
|
-
const restoreBody =
|
|
114
|
+
const restoreBody = hasExplicitPolicies
|
|
115
|
+
? generateMethodBody('delete', expandedPolicies, schema, reader)
|
|
116
|
+
: ' return true;';
|
|
78
117
|
methods.push(buildMethod('restore', modelName, true, restoreBody));
|
|
79
|
-
const forceDeleteBody =
|
|
118
|
+
const forceDeleteBody = hasExplicitPolicies
|
|
119
|
+
? generateMethodBody('delete', expandedPolicies, schema, reader)
|
|
120
|
+
: ' return true;';
|
|
80
121
|
methods.push(buildMethod('forceDelete', modelName, true, forceDeleteBody));
|
|
81
122
|
}
|
|
82
123
|
const cidrHelper = needsCidrHelper ? buildCidrHelper() : '';
|
package/dist/types.d.ts
CHANGED
|
@@ -208,6 +208,17 @@ export interface SchemaOptions {
|
|
|
208
208
|
* generate time).
|
|
209
209
|
*/
|
|
210
210
|
readonly service?: ServiceOptions | false;
|
|
211
|
+
/**
|
|
212
|
+
* Per-schema opt-out for the auto-generated Policy. Issue #98 v5.8.14:
|
|
213
|
+
* every `kind: object` schema gets a generated policy base + editable
|
|
214
|
+
* stub by default. Set `policy: false` on schemas that should NOT have
|
|
215
|
+
* an authorization policy (translation tables, internal sidecars, etc).
|
|
216
|
+
* Cedar-style ABAC `policies:` array on the root schema definition
|
|
217
|
+
* still drives the generated method bodies when present; otherwise the
|
|
218
|
+
* generator emits a standard 5-method CRUD scaffold with
|
|
219
|
+
* `return true;` bodies for the project to override in the editable.
|
|
220
|
+
*/
|
|
221
|
+
readonly policy?: false;
|
|
211
222
|
/** Schema-level default ordering — generates a global Eloquent scope. Issue #40. */
|
|
212
223
|
readonly defaultOrder?: readonly OrderByItem[];
|
|
213
224
|
}
|