# new_secret_popup.dspy - 新增凭据弹窗(值只经表单 POST,绝不进列表/编辑对话框) import json uid = await get_user() if (params_kw or {}).get('op') != 'form': # POST:保存 if not uid: return json.dumps({"success": False, "error": "未登录"}, ensure_ascii=False) name = str((params_kw or {}).get('name', '') or '').strip() value = str((params_kw or {}).get('value', '') or '') label = str((params_kw or {}).get('label', '') or '').strip() remark = str((params_kw or {}).get('remark', '') or '').strip() stype = str((params_kw or {}).get('secret_type', '') or '').strip() if not name or not value: return json.dumps({"success": False, "error": "名称与值必填"}, ensure_ascii=False) org = (await get_userorgid()) or '' from pipeline_service import secret_vault as sv async with DBPools().sqlorContext('pipeline') as sor: r = await sv.save_secret(sor, name=name, value=value, org_id=org, user_id=uid, label=label, secret_type=stype, source='manual', remark=remark, who=uid) await sor.sqlExe("COMMIT", {}) if r.get("ok"): return json.dumps({"success": True, "message": r.get("message", "已保存")}, ensure_ascii=False) return json.dumps({"success": False, "error": r.get("message", "保存失败")}, ensure_ascii=False) # GET op=form:返回弹窗 widget(结构对齐 agent_project_popup 已验模式) if not uid: return json.dumps({"widgettype": "PopupWindow", "id": "new_secret_pw", "options": {"title": "新增凭据", "cwidth": 26, "cheight": 8, "auto_open": True}, "subwidgets": [{"widgettype": "VBox", "options": {"width": "100%", "gap": "10px", "padding": "16px 20px"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "请先登录", "cfontsize": 1}}]}]}, ensure_ascii=False) _self_url = entire_url("/pipeline_core/secrets/new_secret_popup.dspy") def _field(fid, label, wtype, placeholder=""): # bricks 控件名:UiStr=单行 / UiPassword=口令掩码 / UiText=多行 textarea return {"widgettype": "VBox", "options": {"width": "100%", "gap": "2px"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": label, "cfontsize": 0.85, "color": "#64748b"}}, {"widgettype": wtype, "id": fid, "options": {"placeholder": placeholder, "width": "100%"}}]} _get_val = ("function _gv(i){var w=bricks.getWidgetById(i,bricks.app);if(!w)return '';" "var v=(typeof w.resultValue==='function')?w.resultValue():" "((w.dom_element&&w.dom_element.value)||'');" "return (v===null||v===undefined)?'':String(v);}") _save_js = (_get_val + "var nm=_gv('ns_name').trim(), vv=_gv('ns_value');" "if(!nm||!vv){var m0=new bricks.Message({title:'凭据',message:'名称与值必填'});m0.open();return;}" "var body=new URLSearchParams();" "body.append('name',nm);body.append('value',vv);" "body.append('label',_gv('ns_label'));body.append('remark',_gv('ns_remark'));" "body.append('secret_type',_gv('ns_type'));" "var rp=await fetch(" + json.dumps(_self_url) + ",{method:'POST'," "headers:{'Content-Type':'application/x-www-form-urlencoded'},body:body});" "var d=await rp.json();" "if(d&&d.success){" "var pw=bricks.getWidgetById('new_secret_pw',bricks.app);if(pw){pw.destroy();}" "var m1=new bricks.Message({title:'凭据',message:d.message||'已保存'});m1.open();" "location.reload();" "}else{var m2=new bricks.Message({title:'凭据',message:(d&&d.error)||'保存失败'});m2.open();}") return json.dumps({ "widgettype": "PopupWindow", "id": "new_secret_pw", "options": {"title": "🔑 新增凭据", "cwidth": 34, "cheight": 22, "auto_open": True}, "subwidgets": [{ "widgettype": "VBox", "options": {"width": "100%", "gap": "10px", "padding": "16px 20px"}, "subwidgets": [ {"widgettype": "Text", "options": { "text": "值加密存储、永不回显;会话用 @@sec:名称@@ 引用,命令用 $PIPELINE_SEC_名称。", "cfontsize": 0.85, "color": "#64748b"}}, _field("ns_name", "名称(大写字母/数字/下划线)", "UiStr", "如 GITHUB_TOKEN"), _field("ns_value", "值(明文,仅本次传输)", "UiPassword", "粘贴 apikey/token/口令"), _field("ns_label", "标签(可选)", "UiStr", "如 我的GitHub"), _field("ns_type", "类型(可选)", "UiStr", "如 api_key/password/token"), _field("ns_remark", "备注(可选)", "UiText", "用途说明"), {"widgettype": "HBox", "options": {"width": "100%", "gap": "10px"}, "subwidgets": [ {"widgettype": "Button", "options": {"label": "保存", "css": "primary"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self", "script": _save_js}]}]} ]}]}, ensure_ascii=False)