mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 16:44:23 +08:00
147 lines
5.2 KiB
Bash
Executable File
147 lines
5.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# OpenClaw state permission helper.
|
|
# Keep runtime state and managed npm plugin generations writable by the
|
|
# openclaw user. OpenClaw 2026.6.11 installs and retires these generations
|
|
# itself, so root-owned files under npm/projects break later cleanup.
|
|
|
|
oc_perm_state_dir() {
|
|
if [ -n "${1:-}" ]; then
|
|
printf '%s\n' "$1"
|
|
elif [ -n "${OPENCLAW_STATE_DIR:-}" ]; then
|
|
printf '%s\n' "$OPENCLAW_STATE_DIR"
|
|
elif [ -n "${OC_DATA:-}" ]; then
|
|
printf '%s/.openclaw\n' "$OC_DATA"
|
|
else
|
|
printf '/opt/openclaw/data/.openclaw\n'
|
|
fi
|
|
}
|
|
|
|
oc_perm_data_dir_from_state() {
|
|
local state_dir="$1"
|
|
case "$state_dir" in
|
|
*/.openclaw) printf '%s\n' "${state_dir%/.openclaw}" ;;
|
|
*) printf '%s\n' "${OC_DATA:-/opt/openclaw/data}" ;;
|
|
esac
|
|
}
|
|
|
|
oc_fix_npm_projects_permissions() {
|
|
local state_dir npm_projects
|
|
state_dir="$(oc_perm_state_dir "${1:-}")"
|
|
npm_projects="${state_dir}/npm/projects"
|
|
[ -d "$npm_projects" ] || return 0
|
|
|
|
# The official plugin installer runs as openclaw and the Gateway removes
|
|
# retired generations asynchronously. Keep the complete tree writable by
|
|
# that user, including plugin source files.
|
|
chown -R openclaw:openclaw "$npm_projects" 2>/dev/null || true
|
|
chmod -R u+rwX,go+rX "$npm_projects" 2>/dev/null || true
|
|
}
|
|
|
|
oc_fix_state_permissions() {
|
|
local state_dir data_dir ext_dir archive_dir config_file agent_dir
|
|
state_dir="$(oc_perm_state_dir "${1:-}")"
|
|
data_dir="$(oc_perm_data_dir_from_state "$state_dir")"
|
|
ext_dir="${state_dir}/extensions"
|
|
archive_dir="${state_dir}/archived-extensions"
|
|
config_file="${state_dir}/openclaw.json"
|
|
|
|
[ -d "$data_dir" ] && chown openclaw:openclaw "$data_dir" 2>/dev/null || true
|
|
[ -d "$state_dir" ] || mkdir -p "$state_dir" 2>/dev/null || true
|
|
[ -d "$state_dir" ] && chown openclaw:openclaw "$state_dir" 2>/dev/null || true
|
|
[ -d "$state_dir" ] && chmod 755 "$state_dir" 2>/dev/null || true
|
|
|
|
if [ -d "$state_dir" ]; then
|
|
find "$state_dir" -user root \
|
|
! -path "${archive_dir}*" \
|
|
! -path "${state_dir}/npm/projects*" \
|
|
-exec chown openclaw:openclaw {} \; 2>/dev/null || true
|
|
fi
|
|
|
|
[ -f "$config_file" ] && chown openclaw:openclaw "$config_file" 2>/dev/null || true
|
|
[ -f "${config_file}.bak" ] && chown openclaw:openclaw "${config_file}.bak" 2>/dev/null || true
|
|
|
|
agent_dir="${state_dir}/agents/main/agent"
|
|
if [ -d "$agent_dir" ]; then
|
|
chown openclaw:openclaw "$agent_dir" 2>/dev/null || true
|
|
chmod 755 "$agent_dir" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ -d "$ext_dir" ]; then
|
|
chown -R openclaw:openclaw "$ext_dir" 2>/dev/null || true
|
|
chmod -R 755 "$ext_dir" 2>/dev/null || true
|
|
fi
|
|
if [ -d "$archive_dir" ]; then
|
|
chown -R root:root "$archive_dir" 2>/dev/null || true
|
|
chmod -R 755 "$archive_dir" 2>/dev/null || true
|
|
fi
|
|
|
|
oc_fix_npm_projects_permissions "$state_dir"
|
|
}
|
|
|
|
oc_prepare_openclaw_workdirs() {
|
|
local data_dir state_dir npm_dir
|
|
data_dir="${1:-${OC_DATA:-/opt/openclaw/data}}"
|
|
state_dir="${data_dir}/.openclaw"
|
|
npm_dir="${state_dir}/npm/projects"
|
|
|
|
mkdir -p "${data_dir}/.npm" "${data_dir}/.tmp" "$npm_dir" "${state_dir}/extensions" 2>/dev/null || true
|
|
chown -R openclaw:openclaw "${data_dir}/.npm" "${data_dir}/.tmp" 2>/dev/null || true
|
|
chown openclaw:openclaw "$data_dir" "$state_dir" "${state_dir}/npm" "$npm_dir" 2>/dev/null || true
|
|
[ -d "${state_dir}/extensions" ] && chown -R openclaw:openclaw "${state_dir}/extensions" 2>/dev/null || true
|
|
[ -d "${state_dir}/extensions" ] && chmod -R 755 "${state_dir}/extensions" 2>/dev/null || true
|
|
chmod u+rwx,go+rx "${data_dir}/.npm" "${data_dir}/.tmp" "$state_dir" "${state_dir}/npm" "$npm_dir" "${state_dir}/extensions" 2>/dev/null || true
|
|
|
|
# During install/upgrade, allow openclaw to update npm generations.
|
|
[ -d "$npm_dir" ] && chown -R openclaw:openclaw "$npm_dir" 2>/dev/null || true
|
|
}
|
|
|
|
oc_patch_control_ui_security_headers() {
|
|
local global_dir="${1:-${OC_GLOBAL:-/opt/openclaw/global}}"
|
|
local dist_dir=""
|
|
for d in "${global_dir}/lib/node_modules/openclaw/dist" "${global_dir}/node_modules/openclaw/dist" "/opt/openclaw/global/lib/node_modules/openclaw/dist" "/opt/openclaw/node/lib/node_modules/openclaw/dist"; do
|
|
if [ -d "$d" ]; then
|
|
dist_dir="$d"
|
|
break
|
|
fi
|
|
done
|
|
[ -n "$dist_dir" ] || return 0
|
|
# 允许 LuCI 界面以 iframe 内嵌官方 Web 控制台 (Control UI / WebChat)
|
|
# 移除 X-Frame-Options: DENY 并将 frame-ancestors 放宽
|
|
for f in "$dist_dir"/control-ui-*.js; do
|
|
[ -f "$f" ] || continue
|
|
if grep -q 'res.setHeader("X-Frame-Options", "DENY");' "$f" 2>/dev/null; then
|
|
sed -i 's/res.setHeader("X-Frame-Options", "DENY");//g' "$f" 2>/dev/null || true
|
|
fi
|
|
if grep -q '"frame-ancestors '\''none'\''"' "$f" 2>/dev/null; then
|
|
sed -i "s/\"frame-ancestors 'none'\"/\"frame-ancestors *\"/g" "$f" 2>/dev/null || true
|
|
fi
|
|
done
|
|
}
|
|
|
|
if [ "${OPENCLAW_PERMISSIONS_SOURCED:-0}" = "1" ]; then
|
|
return 0
|
|
fi
|
|
|
|
case "${1:-fix-state}" in
|
|
fix-state)
|
|
shift || true
|
|
oc_fix_state_permissions "${1:-}"
|
|
;;
|
|
fix-npm-projects)
|
|
shift || true
|
|
oc_fix_npm_projects_permissions "${1:-}"
|
|
;;
|
|
prepare-workdirs)
|
|
shift || true
|
|
oc_prepare_openclaw_workdirs "${1:-}"
|
|
;;
|
|
patch-control-ui)
|
|
shift || true
|
|
oc_patch_control_ui_security_headers "${1:-}"
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {fix-state [state_dir]|fix-npm-projects [state_dir]|prepare-workdirs [data_dir]|patch-control-ui [global_dir]}" >&2
|
|
exit 2
|
|
;;
|
|
esac
|