progmune-runtime 3.7.13 → 3.7.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/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/extract-ir-go.js +42 -6
- package/dist/extract-ir-go.test.js +17 -0
- package/dist/frameworks/django-detector.js +6 -0
- package/dist/frameworks/django-detector.test.js +29 -0
- package/dist/frameworks/express-detector.js +59 -32
- package/dist/frameworks/express-detector.test.js +69 -0
- package/dist/frameworks/fastify-detector.js +91 -27
- package/dist/frameworks/fastify-detector.test.js +99 -0
- package/dist/frameworks/fiber-detector.js +266 -9
- package/dist/frameworks/fiber-detector.test.js +188 -0
- package/dist/frameworks/gin-detector.js +123 -10
- package/dist/frameworks/gin-detector.test.js +183 -0
- package/dist/frameworks/hapi-detector.js +105 -31
- package/dist/frameworks/hapi-detector.test.js +91 -0
- package/dist/frameworks/koa-detector.js +25 -10
- package/dist/frameworks/koa-detector.test.js +38 -0
- package/dist/frameworks/nestjs-detector.js +145 -3
- package/dist/frameworks/nestjs-detector.test.js +103 -0
- package/dist/frameworks/nextjs-detector.js +4 -1
- package/dist/frameworks/nextjs-detector.test.js +35 -0
- package/dist/frameworks/route-window.js +124 -0
- package/dist/frameworks/trpc-detector.js +82 -16
- package/dist/frameworks/trpc-detector.test.js +177 -0
- package/dist/sdk.js +1 -1
- package/package.json +2 -2
- package/tools/extract_framework_django.py +62 -1
- package/tools/extract_framework_flask.py +3 -1
- package/tools/extract_framework_py.py +6 -2
|
@@ -161,14 +161,68 @@ class UrlCollector(ast.NodeVisitor):
|
|
|
161
161
|
def __init__(self, filepath):
|
|
162
162
|
self.file = filepath
|
|
163
163
|
self.routes = []
|
|
164
|
+
# DRF ViewSet/DefaultRouter(REALWORLD_STRUCTURAL_V3:router.register
|
|
165
|
+
# + include(router.urls) 的路由由运行时生成,urlpatterns 解析不可见)
|
|
166
|
+
self.router_regs = {} # router 变量 -> [(prefix, viewName)]
|
|
167
|
+
self.router_slash = {} # router 变量 -> trailing_slash
|
|
168
|
+
self.router_uses = [] # (prefixBase, routerVar) urlpatterns 里的 include
|
|
164
169
|
|
|
165
170
|
def visit_Assign(self, node):
|
|
166
171
|
for t in node.targets:
|
|
167
|
-
if isinstance(t, ast.Name)
|
|
172
|
+
if not isinstance(t, ast.Name):
|
|
173
|
+
continue
|
|
174
|
+
# DefaultRouter 定义(trailing_slash 关键字,默认 True)
|
|
175
|
+
if isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) \
|
|
176
|
+
and node.value.func.id == "DefaultRouter":
|
|
177
|
+
slash = True
|
|
178
|
+
for kw in node.value.keywords:
|
|
179
|
+
if kw.arg == "trailing_slash" and isinstance(kw.value, ast.Constant):
|
|
180
|
+
slash = bool(kw.value.value)
|
|
181
|
+
self.router_slash[t.id] = slash
|
|
182
|
+
self.router_regs.setdefault(t.id, [])
|
|
183
|
+
# urlpatterns:扫描直连条目,并展开 include(router.urls) 的 ViewSet
|
|
184
|
+
if t.id == "urlpatterns" and isinstance(node.value, (ast.List, ast.Tuple)):
|
|
168
185
|
for elt in node.value.elts:
|
|
169
186
|
self._scan_entry(elt)
|
|
187
|
+
for (prefix, var) in self.router_uses:
|
|
188
|
+
self._expand_router_routes(prefix, var)
|
|
170
189
|
self.generic_visit(node)
|
|
171
190
|
|
|
191
|
+
def visit_Expr(self, node):
|
|
192
|
+
# router.register(r'articles', ArticleViewSet, ...) 语句
|
|
193
|
+
call = node.value
|
|
194
|
+
if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute) \
|
|
195
|
+
and call.func.attr == "register":
|
|
196
|
+
var = name_of(call.func.value)
|
|
197
|
+
if not var or var not in self.router_regs:
|
|
198
|
+
return
|
|
199
|
+
prefix = ""
|
|
200
|
+
if call.args and isinstance(call.args[0], ast.Constant):
|
|
201
|
+
prefix = str(call.args[0].value)
|
|
202
|
+
view = None
|
|
203
|
+
if len(call.args) > 1:
|
|
204
|
+
a1 = call.args[1]
|
|
205
|
+
if isinstance(a1, ast.Name):
|
|
206
|
+
view = a1.id
|
|
207
|
+
elif isinstance(a1, ast.Attribute):
|
|
208
|
+
view = a1.attr
|
|
209
|
+
if view:
|
|
210
|
+
self.router_regs.setdefault(var, []).append((prefix, view))
|
|
211
|
+
self.generic_visit(node)
|
|
212
|
+
|
|
213
|
+
def _expand_router_routes(self, prefix_base, var):
|
|
214
|
+
# 本工具不做 include 前缀传播(urlconf 各文件 pattern 独立)——
|
|
215
|
+
# prefix_base 仅作路由存在性触发,不拼进 pattern
|
|
216
|
+
for (prefix, view) in self.router_regs.get(var, []):
|
|
217
|
+
base = "^" + prefix
|
|
218
|
+
# DRF 默认 action 路由:list/create 集合级、retrieve/update/
|
|
219
|
+
# destroy 详情级(权限由 views 表判定,规则在 TS 检测器侧)
|
|
220
|
+
for pat in (base + "/?$", base + "/(?P<pk>[^/.]+)/?$"):
|
|
221
|
+
self.routes.append({
|
|
222
|
+
"pattern": pat, "urlname": "", "view": view, "kind": "cbv",
|
|
223
|
+
"file": self.file, "viewset": True,
|
|
224
|
+
})
|
|
225
|
+
|
|
172
226
|
def _scan_entry(self, elt):
|
|
173
227
|
if not isinstance(elt, ast.Call):
|
|
174
228
|
return
|
|
@@ -199,6 +253,13 @@ class UrlCollector(ast.NodeVisitor):
|
|
|
199
253
|
elif isinstance(view_ref, ast.Call) and isinstance(view_ref.func, ast.Name):
|
|
200
254
|
if view_ref.func.id == "include":
|
|
201
255
|
kind = "include"
|
|
256
|
+
# include(router.urls):记录 router 变量(同一文件的
|
|
257
|
+
# router.register 展开见 _expand_router_routes)
|
|
258
|
+
if view_ref.args and isinstance(view_ref.args[0], ast.Attribute) \
|
|
259
|
+
and view_ref.args[0].attr == "urls":
|
|
260
|
+
rvar = name_of(view_ref.args[0].value)
|
|
261
|
+
if rvar:
|
|
262
|
+
self.router_uses.append((pattern, rvar))
|
|
202
263
|
else:
|
|
203
264
|
kind = "fbv"
|
|
204
265
|
view_name = view_ref.func.id
|
|
@@ -26,8 +26,10 @@ SKIP_DIRS = {"tests", "test", "deps", "venv", "env", "node_modules", "vendor",
|
|
|
26
26
|
".git", "migrations", "__pycache__", "scripts", "docs",
|
|
27
27
|
"staticfiles", "static"}
|
|
28
28
|
|
|
29
|
+
# jwt 必在词表:flask_jwt_extended 的 @jwt_required 是生态头号认证装饰器
|
|
30
|
+
# (REALWORLD_STRUCTURAL_V4:缺 "jwt" → 10 个受保护 mutation 全误报 FP)
|
|
29
31
|
AUTH_WORDS = ("auth", "login", "permission", "token", "credential", "session",
|
|
30
|
-
"user")
|
|
32
|
+
"user", "jwt")
|
|
31
33
|
|
|
32
34
|
MUTATION_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
|
|
33
35
|
|
|
@@ -30,9 +30,13 @@ import sys
|
|
|
30
30
|
|
|
31
31
|
# 认证词表(依赖函数名命中即视为 auth-like;与 TS 侧 annotation-suggest 词表同源)
|
|
32
32
|
# 注意:扫描器只做「结构提取」,规则判定(豁免词/方法门控)在 TS 检测器侧。
|
|
33
|
+
# 注意:不含裸 "user"——get_profile_by_username_from_path 等 DB 查询
|
|
34
|
+
# 依赖名含 user 会被误标认证(REALWORLD_STRUCTURAL_V2 假保护 FN)。
|
|
35
|
+
# 真认证依赖用 current_user/authorizer 等强词识别(get_current_user
|
|
36
|
+
# 含 current_user ✓)。
|
|
33
37
|
AUTH_WORDS = (
|
|
34
|
-
"auth", "login", "token", "
|
|
35
|
-
"bearer", "permission", "current_user", "api_key", "oauth",
|
|
38
|
+
"auth", "login", "token", "credential", "session",
|
|
39
|
+
"bearer", "permission", "current_user", "api_key", "oauth", "jwt",
|
|
36
40
|
)
|
|
37
41
|
|
|
38
42
|
SKIP_DIRS = {"tests", "test", "deps", "venv", "env", "node_modules", "vendor",
|