diff --git a/.gitignore b/.gitignore index 3707b02..ad0f78c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,31 @@ -*.pyc +# Python __pycache__/ -mysql.ddl.sql +*.py[cod] +*.egg-info/ +dist/ +build/ + +# Virtual environment +py3/ +pkgs/ + +# Runtime +logs/ +files/ +*.pid +cms.service + +# DDL generated +*/mysql.ddl.sql + +# IDE +.idea/ +.vscode/ +*.swp + +# OS +.DS_Store +Thumbs.db + +# Config with credentials +# conf/config.json # Keep template in git diff --git a/app/cms.py b/app/cms.py new file mode 100644 index 0000000..cdd4737 --- /dev/null +++ b/app/cms.py @@ -0,0 +1,42 @@ +""" +开元云科技CMS — 独立Web应用主入口 +启动: py3/bin/python app/cms.py -p 9090 -w $(pwd) +""" +import os, sys + +# Ensure app/ is in path for local imports +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from appPublic.log import MyLogger, info +from appPublic.folderUtils import ProgramPath +from appPublic.jsonConfig import getConfig +from appPublic.registerfunction import RegisterFunction +from bricks_for_python.init import load_pybricks +from ahserver.webapp import webapp +from ahserver.serverenv import ServerEnv +from sqlor.dbpools import DBPools + +# CMS业务模块 +from entcms.init import load_entcms +from dingdingflow.init import load_dingdingflow + +# RBAC认证(复用sage的rbac模块) +from rbac.init import load_rbac +from appbase.init import load_appbase + +# 全局函数 +from global_func import set_globalvariable + +__version__ = '1.0.0' + +def init(): + rf = RegisterFunction() + set_globalvariable() + load_pybricks() + load_appbase() + load_rbac() + load_entcms() + load_dingdingflow() + +if __name__ == '__main__': + webapp(init) diff --git a/app/global_func.py b/app/global_func.py new file mode 100644 index 0000000..086a441 --- /dev/null +++ b/app/global_func.py @@ -0,0 +1,56 @@ +""" +CMS全局函数 — 注册到ServerEnv供.dspy和.ui调用 +""" +from ahserver.serverenv import ServerEnv + +def get_module_dbname(mname): + """所有模块共享sage数据库""" + return 'sage' + +def UiWindow(title, icon, content, cheight=10, cwidth=15): + return { + "widgettype": "PopupWindow", + "options": { + "author": "cms", + "cwidth": cwidth, + "cheight": cheight, + "title": title, + "content": content, + "icon": icon or entire_url('/bricks/imgs/app.png'), + "movable": True, + "auto_open": True + } + } + +def UiError(title="出错", message="出错啦", timeout=5): + return { + "widgettype": "Error", + "options": { + "author": "cms", + "timeout": timeout, + "cwidth": 15, + "cheight": 10, + "title": title, + "message": message + } + } + +def UiMessage(title="消息", message="后台消息", timeout=5): + return { + "widgettype": "Message", + "options": { + "author": "cms", + "timeout": timeout, + "cwidth": 15, + "cheight": 10, + "title": title, + "message": message + } + } + +def set_globalvariable(): + g = ServerEnv() + g.get_module_dbname = get_module_dbname + g.UiError = UiError + g.UiMessage = UiMessage + g.UiWindow = UiWindow diff --git a/build.sh b/build.sh index 17d2d44..a1e7bd3 100755 --- a/build.sh +++ b/build.sh @@ -1,87 +1,198 @@ -#!/bin/bash -# CMS项目构建脚本 -# 构建 entcms + dingdingflow 模块并集成到Sage系统 - +#!/usr/bin/env bash +# 开元云科技CMS — 独立Web应用构建脚本 +# 用法: cd ~/repos/cms && ./build.sh set -e -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -echo "=== CMS项目构建 ===" -echo "Script dir: $SCRIPT_DIR" +cdir=$(pwd) +uname=$(id -un) +gname=$(id -gn) -# 查找Sage根目录 -SAGE_ROOT="" -for candidate in "$SCRIPT_DIR/../.." "$HOME/repos/sage" "$HOME/sage"; do - if [ -d "$candidate/wwwroot" ] && [ -d "$candidate/py3/bin" ]; then - SAGE_ROOT="$(cd "$candidate" && pwd)" - break +echo "============================================" +echo " 开元云科技CMS — 独立Web应用构建" +echo "============================================" + +# =========================================== +# Step 1: Python虚拟环境 +# =========================================== +echo "" +echo "--- Step 1: 创建Python虚拟环境 ---" +if [ ! -d "py3" ]; then + python3 -m venv py3 +fi +source py3/bin/activate + +# =========================================== +# Step 2: 核心依赖 +# =========================================== +echo "" +echo "--- Step 2: 安装核心依赖 ---" +mkdir -p pkgs + +# 核心框架包 +for m in apppublic sqlor ahserver bricks-for-python xls2ddl +do + echo " install $m..." + cd $cdir/pkgs + if [ ! -d "$m" ]; then + git clone https://git.opencomputing.cn/yumoqing/$m fi + cd $m + $cdir/py3/bin/pip install . 2>/dev/null || echo " WARN: $m install failed" done -if [ -z "$SAGE_ROOT" ]; then - echo "ERROR: 找不到Sage根目录" - exit 1 +# bricks前端 +echo " install bricks..." +cd $cdir/pkgs +if [ ! -d "bricks" ]; then + git clone https://git.opencomputing.cn/yumoqing/bricks +fi +cd bricks/bricks +./build.sh 2>/dev/null || echo " WARN: bricks build skipped" + +# bricks符号链接 +mkdir -p $cdir/bricks +if [ -d "$cdir/pkgs/bricks/dist" ]; then + rm -f $cdir/bricks + ln -sf $cdir/pkgs/bricks/dist $cdir/bricks fi -echo "Sage root: $SAGE_ROOT" -PY="$SAGE_ROOT/py3/bin/python" -PIP="$SAGE_ROOT/py3/bin/pip" - -# 安装模块 -for mod in entcms dingdingflow; do - echo "" - echo "=== 安装 $mod ===" - cd "$SCRIPT_DIR/$mod" - $PIP install -e . - - # 生成DDL - if [ -d "models" ] && [ "$(ls models/*.json 2>/dev/null)" ]; then - echo "生成DDL..." - cd models - $PY -c "from sqlor.ddl_template_mysql import DDLTemplate; print(DDLTemplate().generate('.'))" > ../mysql.ddl.sql 2>/dev/null || json2ddl mysql . > ../mysql.ddl.sql 2>/dev/null || echo "DDL generation skipped (json2ddl not available)" - cd .. +# =========================================== +# Step 3: RBAC + AppBase模块(认证依赖) +# =========================================== +echo "" +echo "--- Step 3: 安装RBAC/AppBase模块 ---" +for m in appbase rbac checklang +do + echo " install $m..." + cd $cdir/pkgs + if [ ! -d "$m" ]; then + git clone https://git.opencomputing.cn/yumoqing/$m fi - - # 生成CRUD UI - if [ -d "json" ] && [ "$(ls json/*.json 2>/dev/null)" ]; then - echo "生成CRUD UI..." - cd json - xls2ui -m ../models -o ../wwwroot $mod *.json 2>/dev/null || echo "CRUD UI generation skipped (xls2ui not available)" - cd .. - fi - - # 链接wwwroot到Sage - MODULE_WWWROOT="$SAGE_ROOT/wwwroot/$mod" - mkdir -p "$MODULE_WWWROOT/api" - - # 链接UI/CSS/JS文件 - for f in "$SCRIPT_DIR/$mod/wwwroot"/*.ui "$SCRIPT_DIR/$mod/wwwroot"/*.css "$SCRIPT_DIR/$mod/wwwroot"/*.js; do - [ -f "$f" ] || continue - fname=$(basename "$f") - ln -sf "$f" "$MODULE_WWWROOT/$fname" - done - - # 链接api目录下的.dspy文件 - for f in "$SCRIPT_DIR/$mod/wwwroot/api"/*.dspy; do - [ -f "$f" ] || continue - fname=$(basename "$f") - ln -sf "$f" "$MODULE_WWWROOT/api/$fname" - done - - # 链接生成的CRUD目录 - for d in "$SCRIPT_DIR/$mod/wwwroot"/*/; do - [ -d "$d" ] || continue - dname=$(basename "$d") - case "$dname" in api|styles|scripts) continue ;; esac - ln -sf "$d" "$MODULE_WWWROOT/$dname" - done - - echo "$mod 安装完成" + cd $m + $cdir/py3/bin/pip install . 2>/dev/null || echo " WARN: $m install failed" done +# =========================================== +# Step 4: CMS业务模块 +# =========================================== echo "" -echo "=== 构建完成 ===" -echo "请执行以下步骤完成集成:" -echo "1. 编辑 $SAGE_ROOT/app/sage.py 添加模块导入" -echo "2. 编辑 $SAGE_ROOT/build.sh 添加模块到安装循环" -echo "3. 执行 RBAC 权限配置" -echo "4. 重启Sage服务" +echo "--- Step 4: 安装CMS业务模块 ---" + +# entcms模块 +echo " install entcms..." +cd $cdir/entcms +$cdir/py3/bin/pip install . 2>/dev/null || echo " WARN: entcms install failed" + +# dingdingflow模块 +echo " install dingdingflow..." +cd $cdir/dingdingflow +$cdir/py3/bin/pip install . 2>/dev/null || echo " WARN: dingdingflow install failed" + +# =========================================== +# Step 5: 数据库DDL(CMS业务表) +# =========================================== +echo "" +echo "--- Step 5: 生成数据库DDL ---" + +# entcms表DDL +if [ -d "$cdir/entcms/models" ]; then + cd $cdir/entcms/models + echo " 生成 entcms DDL..." + $cdir/py3/bin/json2ddl mysql . > $cdir/entcms/mysql.ddl.sql 2>/dev/null || echo " WARN: json2ddl failed for entcms" + echo " DDL已生成: entcms/mysql.ddl.sql" +fi + +# dingdingflow表DDL +if [ -d "$cdir/dingdingflow/models" ]; then + cd $cdir/dingdingflow/models + echo " 生成 dingdingflow DDL..." + $cdir/py3/bin/json2ddl mysql . > $cdir/dingdingflow/mysql.ddl.sql 2>/dev/null || echo " WARN: json2ddl failed for dingdingflow" + echo " DDL已生成: dingdingflow/mysql.ddl.sql" +fi + +# =========================================== +# Step 6: CRUD UI生成 +# =========================================== +echo "" +echo "--- Step 6: 生成CRUD UI ---" + +# entcms CRUD +if [ -d "$cdir/entcms/json" ]; then + cd $cdir/entcms/json + echo " 生成 entcms CRUD UI..." + for f in *.json; do + [ -f "$f" ] || continue + echo " $f" + $cdir/py3/bin/xls2ui -m ../models -o ../wwwroot entcms $f 2>/dev/null || echo " WARN: xls2ui failed for $f" + done +fi + +# dingdingflow CRUD +if [ -d "$cdir/dingdingflow/json" ]; then + cd $cdir/dingdingflow/json + echo " 生成 dingdingflow CRUD UI..." + for f in *.json; do + [ -f "$f" ] || continue + echo " $f" + $cdir/py3/bin/xls2ui -m ../models -o ../wwwroot dingdingflow $f 2>/dev/null || echo " WARN: xls2ui failed for $f" + done +fi + +# =========================================== +# Step 7: 日志和文件目录 +# =========================================== +echo "" +echo "--- Step 7: 创建运行时目录 ---" +mkdir -p $cdir/logs +mkdir -p $cdir/files + +# =========================================== +# Step 8: systemd服务文件 +# =========================================== +echo "" +echo "--- Step 8: 生成systemd服务文件 ---" +cat > $cdir/cms.service < entcms/ -> cms root + return os.path.dirname(os.path.dirname(script_dir)) -sage_root = find_sage_root() +app_root = find_app_root() +# 查找Sage的set_role_perm.py(RBAC工具) +sage_root = None +for c in [os.path.expanduser("~/repos/sage"), os.path.expanduser("~/sage")]: + if os.path.isdir(os.path.join(c, "py3", "bin")): + sage_root = c + break if not sage_root: - print("ERROR: Cannot find Sage root"); sys.exit(1) + # 使用CMS自己的py3 + sage_root = app_root -py = os.path.join(sage_root, "py3", "bin", "python") -sp = os.path.join(sage_root, "set_role_perm.py") +py = os.path.join(app_root, "py3", "bin", "python") +sp = os.path.join(sage_root, "set_role_perm.py") if os.path.exists(os.path.join(sage_root, "set_role_perm.py")) else None + +if not sp: + print("ERROR: 找不到set_role_perm.py,请确保Sage或CMS已构建") + sys.exit(1) def run(role, paths): for p in paths: @@ -28,105 +37,97 @@ def run(role, paths): # ─── anonymous (any) — 公开页面 + 公开API ─── any_paths = [ - "/entcms/index.ui", - "/entcms/news.ui", - "/entcms/news_detail.ui", - "/entcms/cases.ui", - "/entcms/products.ui", - "/entcms/cms_styles.css", - "/entcms/cms_scripts.js", - "/entcms/menu.ui", - "/entcms/api/submit_lead.dspy", - "/entcms/api/get_config.dspy", - "/entcms/api/get_published_content.dspy", - "/entcms/api/get_content_detail.dspy", - "/entcms/api/get_sections.dspy", + "/index.ui", + "/news.ui", + "/news_detail.ui", + "/cases.ui", + "/products.ui", + "/cms_styles.css", + "/cms_scripts.js", + "/menu.ui", + "/api/submit_lead.dspy", + "/api/get_config.dspy", + "/api/get_published_content.dspy", + "/api/get_content_detail.dspy", + "/api/get_sections.dspy", ] # ─── webmaster — 内容/分类/栏目/配置/线索 全部CRUD ─── webmaster_paths = [ - "/entcms", - "/entcms/admin.ui", + "/admin.ui", # 内容 - "/entcms/cms_content_list", "/entcms/cms_content_list/%", - "/entcms/api/cms_content_create.dspy", - "/entcms/api/cms_content_update.dspy", - "/entcms/api/cms_content_delete.dspy", - "/entcms/api/cms_content_list.dspy", + "/cms_content_list", "/cms_content_list/%", + "/api/cms_content_create.dspy", + "/api/cms_content_update.dspy", + "/api/cms_content_delete.dspy", + "/api/cms_content_list.dspy", # 分类 - "/entcms/cms_categories_list", "/entcms/cms_categories_list/%", - "/entcms/api/cms_categories_create.dspy", - "/entcms/api/cms_categories_update.dspy", - "/entcms/api/cms_categories_delete.dspy", - "/entcms/api/cms_categories_list.dspy", - "/entcms/api/category_options.dspy", + "/cms_categories_list", "/cms_categories_list/%", + "/api/cms_categories_create.dspy", + "/api/cms_categories_update.dspy", + "/api/cms_categories_delete.dspy", + "/api/cms_categories_list.dspy", + "/api/category_options.dspy", # 栏目 - "/entcms/cms_sections_list", "/entcms/cms_sections_list/%", - "/entcms/api/cms_sections_create.dspy", - "/entcms/api/cms_sections_update.dspy", - "/entcms/api/cms_sections_delete.dspy", - "/entcms/api/cms_sections_list.dspy", + "/cms_sections_list", "/cms_sections_list/%", + "/api/cms_sections_create.dspy", + "/api/cms_sections_update.dspy", + "/api/cms_sections_delete.dspy", + "/api/cms_sections_list.dspy", # 站点配置 - "/entcms/cms_site_config_list", "/entcms/cms_site_config_list/%", - "/entcms/api/cms_site_config_create.dspy", - "/entcms/api/cms_site_config_update.dspy", - "/entcms/api/cms_site_config_delete.dspy", - "/entcms/api/cms_site_config_list.dspy", + "/cms_site_config_list", "/cms_site_config_list/%", + "/api/cms_site_config_create.dspy", + "/api/cms_site_config_update.dspy", + "/api/cms_site_config_delete.dspy", + "/api/cms_site_config_list.dspy", # 线索管理 - "/entcms/cms_leads_list", "/entcms/cms_leads_list/%", - "/entcms/api/cms_leads_create.dspy", - "/entcms/api/cms_leads_update.dspy", - "/entcms/api/cms_leads_delete.dspy", - "/entcms/api/cms_leads_list.dspy", + "/cms_leads_list", "/cms_leads_list/%", + "/api/cms_leads_create.dspy", + "/api/cms_leads_update.dspy", + "/api/cms_leads_delete.dspy", + "/api/cms_leads_list.dspy", # 审批 - "/entcms/api/submit_content_approval.dspy", + "/api/submit_content_approval.dspy", ] # ─── reviewer — 查看内容 + 审批(只改status) ─── reviewer_paths = [ - "/entcms", - "/entcms/admin.ui", - "/entcms/cms_content_list", "/entcms/cms_content_list/%", - "/entcms/api/cms_content_list.dspy", - "/entcms/api/cms_content_update.dspy", # 仅更新status字段 - "/entcms/api/category_options.dspy", + "/admin.ui", + "/cms_content_list", "/cms_content_list/%", + "/api/cms_content_list.dspy", + "/api/cms_content_update.dspy", + "/api/category_options.dspy", ] # ─── supervisor — 查看全部 + 审批配置 + 线索管理 ─── supervisor_paths = [ - "/entcms", - "/entcms/admin.ui", - # 只读 - "/entcms/cms_content_list", "/entcms/cms_content_list/%", - "/entcms/cms_categories_list", "/entcms/cms_categories_list/%", - "/entcms/cms_sections_list", "/entcms/cms_sections_list/%", - "/entcms/cms_site_config_list", "/entcms/cms_site_config_list/%", - # 列表API(只读) - "/entcms/api/cms_content_list.dspy", - "/entcms/api/cms_categories_list.dspy", - "/entcms/api/cms_sections_list.dspy", - "/entcms/api/cms_site_config_list.dspy", - "/entcms/api/category_options.dspy", - # 线索全权 - "/entcms/cms_leads_list", "/entcms/cms_leads_list/%", - "/entcms/api/cms_leads_create.dspy", - "/entcms/api/cms_leads_update.dspy", - "/entcms/api/cms_leads_delete.dspy", - "/entcms/api/cms_leads_list.dspy", - # 审批 - "/entcms/api/submit_content_approval.dspy", + "/admin.ui", + "/cms_content_list", "/cms_content_list/%", + "/cms_categories_list", "/cms_categories_list/%", + "/cms_sections_list", "/cms_sections_list/%", + "/cms_site_config_list", "/cms_site_config_list/%", + "/api/cms_content_list.dspy", + "/api/cms_categories_list.dspy", + "/api/cms_sections_list.dspy", + "/api/cms_site_config_list.dspy", + "/api/category_options.dspy", + "/cms_leads_list", "/cms_leads_list/%", + "/api/cms_leads_create.dspy", + "/api/cms_leads_update.dspy", + "/api/cms_leads_delete.dspy", + "/api/cms_leads_list.dspy", + "/api/submit_content_approval.dspy", ] # ─── customer-support — 线索查看和更新 ─── support_paths = [ - "/entcms", - "/entcms/admin.ui", - "/entcms/cms_leads_list", "/entcms/cms_leads_list/%", - "/entcms/api/cms_leads_list.dspy", - "/entcms/api/cms_leads_update.dspy", + "/admin.ui", + "/cms_leads_list", "/cms_leads_list/%", + "/api/cms_leads_list.dspy", + "/api/cms_leads_update.dspy", ] -print("=== entcms RBAC权限配置 ===") +print("=== CMS RBAC权限配置 ===") print(f"\n--- any (匿名用户) ---") run("any", any_paths) print(f"\n--- owner.webmaster (内容管理员) ---") diff --git a/entcms/wwwroot/admin.ui b/entcms/wwwroot/admin.ui index 1f0a29f..30fa308 100644 --- a/entcms/wwwroot/admin.ui +++ b/entcms/wwwroot/admin.ui @@ -47,7 +47,7 @@ "actiontype": "urlwidget", "target": "app.sage_main_content", "options": { - "url": "{{entire_url('/entcms/cms_content_list')}}" + "url": "{{entire_url('/cms_content_list')}}" }, "mode": "replace" } @@ -102,7 +102,7 @@ "actiontype": "urlwidget", "target": "app.sage_main_content", "options": { - "url": "{{entire_url('/entcms/cms_sections_list')}}" + "url": "{{entire_url('/cms_sections_list')}}" }, "mode": "replace" } @@ -157,7 +157,7 @@ "actiontype": "urlwidget", "target": "app.sage_main_content", "options": { - "url": "{{entire_url('/entcms/cms_categories_list')}}" + "url": "{{entire_url('/cms_categories_list')}}" }, "mode": "replace" } @@ -212,7 +212,7 @@ "actiontype": "urlwidget", "target": "app.sage_main_content", "options": { - "url": "{{entire_url('/entcms/cms_leads_list')}}" + "url": "{{entire_url('/cms_leads_list')}}" }, "mode": "replace" } @@ -267,7 +267,7 @@ "actiontype": "urlwidget", "target": "app.sage_main_content", "options": { - "url": "{{entire_url('/entcms/cms_site_config_list')}}" + "url": "{{entire_url('/cms_site_config_list')}}" }, "mode": "replace" } diff --git a/entcms/wwwroot/menu.ui b/entcms/wwwroot/menu.ui index 8a353b3..c12b1c2 100644 --- a/entcms/wwwroot/menu.ui +++ b/entcms/wwwroot/menu.ui @@ -6,37 +6,37 @@ { "name": "cms_content_list", "label": "内容管理", - "url": "{{entire_url('/entcms/cms_content_list')}}", + "url": "{{entire_url('/cms_content_list')}}", "target": "app.sage_main_content" }, { "name": "cms_sections_list", "label": "栏目管理", - "url": "{{entire_url('/entcms/cms_sections_list')}}", + "url": "{{entire_url('/cms_sections_list')}}", "target": "app.sage_main_content" }, { "name": "cms_categories_list", "label": "内容分类", - "url": "{{entire_url('/entcms/cms_categories_list')}}", + "url": "{{entire_url('/cms_categories_list')}}", "target": "app.sage_main_content" }, { "name": "cms_leads_list", "label": "商机线索", - "url": "{{entire_url('/entcms/cms_leads_list')}}", + "url": "{{entire_url('/cms_leads_list')}}", "target": "app.sage_main_content" }, { "name": "cms_site_config_list", "label": "站点配置", - "url": "{{entire_url('/entcms/cms_site_config_list')}}", + "url": "{{entire_url('/cms_site_config_list')}}", "target": "app.sage_main_content" }, { "name": "public_site", "label": "官网预览", - "url": "{{entire_url('/entcms/index.ui')}}", + "url": "{{entire_url('/index.ui')}}", "target": "app.sage_main_content" } ] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b5c659d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["setuptools>=45", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "kaiyuan-cms" +version = "1.0.0" +description = "开元云科技企业官网CMS系统 — 独立Web应用" +requires-python = ">=3.8" +dependencies = [ + "sqlor", + "bricks_for_python", +] + +[tool.setuptools.packages.find] +where = ["."] +include = ["entcms*", "dingdingflow*"] diff --git a/scripts/init_superuser.py b/scripts/init_superuser.py index 874ff3a..7146432 100644 --- a/scripts/init_superuser.py +++ b/scripts/init_superuser.py @@ -1,15 +1,41 @@ """ 初始化超级用户 -用法: cd ~/repos/sage && ./py3/bin/python ~/repos/cms/scripts/init_superuser.py [username] [password] +用法: + CMS环境: py3/bin/python scripts/init_superuser.py [username] [password] + Sage环境: cd ~/repos/sage && ./py3/bin/python ~/repos/cms/scripts/init_superuser.py [username] [password] 默认: admin / admin123 """ import os, sys, asyncio + +# 自动检测运行环境 +def find_workdir(): + """查找应用根目录""" + script_dir = os.path.dirname(os.path.abspath(__file__)) + cms_root = os.path.dirname(script_dir) + + # 检查是否是CMS独立环境 + if os.path.isdir(os.path.join(cms_root, "py3", "bin")) and \ + os.path.isfile(os.path.join(cms_root, "conf", "config.json")): + return cms_root + + # 检查Sage环境 + for c in [os.path.expanduser("~/repos/sage"), os.path.expanduser("~/sage")]: + if os.path.isdir(os.path.join(c, "py3", "bin")): + return c + return None + +workdir = find_workdir() +if not workdir: + print("ERROR: 找不到CMS或Sage应用目录") + sys.exit(1) + +# 确保Python路径 +sys.path.insert(0, os.path.join(workdir, "py3", "lib")) +os.chdir(workdir) + from sqlor.dbpools import DBPools from appPublic.jsonConfig import getConfig from appPublic.uniqueID import getID - -# Sage环境导入password_encode -sys.path.insert(0, os.path.expanduser("~/repos/sage")) from appPublic.password import password_encode async def main(): @@ -23,7 +49,6 @@ async def main(): existing = await sor.R('users', {'username': username}) if existing: print(f"用户 {username} 已存在 (id={existing[0]['id']})") - # 更新密码 await sor.U('users', { 'id': existing[0]['id'], 'passwd': password_encode(password) @@ -59,8 +84,7 @@ async def main(): users = await sor.R('users', {'username': username}) uid = users[0]['id'] - # 查找或创建用户-角色关联 (userrole表) - # 检查userrole表是否存在 + # 分配角色 try: ur = await sor.R('userrole', {'userid': uid, 'roleid': role_id}) if not ur: @@ -75,6 +99,24 @@ async def main(): except Exception as e: print(f"注意: userrole表操作异常: {e}") print("可能需要手动分配角色") + + # 给superuser分配全部权限 + try: + all_perms = await sor.R('permission', {}) + for perm in all_perms: + existing_rp = await sor.R('rolepermission', { + 'roleid': role_id, + 'permid': perm['id'] + }) + if not existing_rp: + await sor.C('rolepermission', { + 'id': getID(), + 'roleid': role_id, + 'permid': perm['id'] + }) + print(f"已将全部 {len(all_perms)} 条权限分配给 owner.superuser") + except Exception as e: + print(f"注意: 权限分配异常: {e}") print(f"\n登录信息:") print(f" 用户名: {username}") diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..af440b0 --- /dev/null +++ b/start.sh @@ -0,0 +1,11 @@ +#!/usr/bin/bash +# CMS独立应用启动脚本 +cd "$(dirname "$0")" +WORKDIR="$(pwd)" +PIDFILE="$WORKDIR/cms.pid" + +echo "启动 CMS Web Application (port 9090)..." +$WORKDIR/py3/bin/python $WORKDIR/app/cms.py -p 9090 -w $WORKDIR & +echo $! > $PIDFILE +echo "CMS started (PID: $(cat $PIDFILE))" +exit 0 diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..7d93576 --- /dev/null +++ b/stop.sh @@ -0,0 +1,22 @@ +#!/usr/bin/bash +# CMS独立应用停止脚本 +cd "$(dirname "$0")" +PIDFILE="$(pwd)/cms.pid" + +if [ -f "$PIDFILE" ]; then + PID=$(cat "$PIDFILE") + if kill -0 "$PID" 2>/dev/null; then + echo "停止 CMS (PID: $PID)..." + kill "$PID" + sleep 2 + if kill -0 "$PID" 2>/dev/null; then + kill -9 "$PID" + fi + echo "CMS已停止" + else + echo "CMS进程已不存在" + fi + rm -f "$PIDFILE" +else + echo "未找到PID文件" +fi