Token导航 LogoToken导航

Agent Skill · 开发

erpnext-errors-permissions(erpnext 错误权限)

erpnext-errors-permissions 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

erpnext-errors-permissions 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 12,835。

总安装 1,112周安装 45GitHub Stars 87下载 349核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:erpnext-errors-permissions(erpnext 错误权限)
来源仓库:https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package
仓库路径:skills/erpnext-errors-permissions
安装命令:
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-errors-permissions
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-errors-permissions

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

指导 Frappe 权限系统的错误规避方法,防止权限钩子抛出异常导致流程中断。适合在 Codex、Claude、Cursor、Gemini CLI 中设计安全的文档访问控制逻辑。强调 has_permission 应返回布尔值而非报错,确保权限检查不影响用户体验。

使用前需核对 v14/v15/v16 差异,避免因版本特性误用引发权限漏洞。erpnext-errors-permissions 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/erpnext-errors-permissions

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_de…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

erpnext-errors-permissions 怎么安装?

在终端执行 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

erpnext-errors-permissions 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

erpnext-errors-permissions 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

erpnext-errors-permissions 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

erpnext-errors-permissions 用的人多吗?

公开数据是累计安装 1,112 次,近一周安装 45 次,下载 349 次,GitHub 87 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

erpnext-errors-permissions 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
erpnext-errors-permissions

erpnext 错误权限 · 本页

1,11287需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

ERPNext Permissions - Error Handling

This skill covers error handling patterns for the Frappe permission system. For permission syntax, see erpnext-permissions. For hooks, see erpnext-syntax-hooks.

Version: v14/v15/v16 compatible


Permission Error Handling Overview

┌─────────────────────────────────────────────────────────────────────┐
│ PERMISSION ERRORS REQUIRE SPECIAL HANDLING                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ Permission Hooks (has_permission, permission_query_conditions):     │
│ ⚠️ NEVER throw errors - return False or empty string                │
│ ⚠️ Errors break document access and list views                      │
│ ⚠️ Always provide safe fallbacks                                    │
│                                                                     │
│ Permission Checks in Code:                                          │
│ ✅ Use frappe.has_permission() before operations                    │
│ ✅ Use throw=True for automatic error handling                      │
│ ✅ Catch frappe.PermissionError for custom handling                 │
│                                                                     │
│ API Endpoints:                                                      │
│ ✅ frappe.only_for() for role-restricted endpoints                  │
│ ✅ doc.has_permission() before document operations                  │
│ ✅ Return proper HTTP 403 for access denied                         │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Main Decision: Where Is the Permission Check?

┌─────────────────────────────────────────────────────────────────────────┐
│ WHERE ARE YOU HANDLING PERMISSIONS?                                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│ ► has_permission hook (hooks.py)                                        │
│   └─► NEVER throw - return False to deny, None to defer                 │
│   └─► Wrap in try/except, log errors, return None on failure            │
│                                                                         │
│ ► permission_query_conditions hook (hooks.py)                           │
│   └─► NEVER throw - return SQL condition or empty string                │
│   └─► Wrap in try/except, return restrictive fallback on failure        │
│                                                                         │
│ ► Whitelisted method / API endpoint                                     │
│   └─► Use frappe.has_permission() with throw=True                       │
│   └─► Or catch PermissionError for custom response                      │
│   └─► Use frappe.only_for() for role-restricted endpoints               │
│                                                                         │
│ ► Controller method                                                     │
│   └─► Use doc.has_permission() or doc.check_permission()                │
│   └─► Let PermissionError propagate for standard handling               │
│                                                                         │
│ ► Client Script                                                         │
│   └─► Handle in frappe.call error callback                              │
│   └─► Check exc type for PermissionError                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Permission Hook Error Handling

has_permission - NEVER Throw!

# ❌ WRONG - Breaks document access!
def has_permission(doc, ptype, user):
    if doc.status == "Locked":
        frappe.throw("Document is locked")  # DON'T DO THIS!

# ✅ CORRECT - Return False to deny, None to defer
def has_permission(doc, ptype, user):
    """
    Custom permission check.

    Returns:
        None: Defer to standard permission system
        False: Deny permission

    NEVER return True - hooks can only deny, not grant.
    """
    try:
        user = user or frappe.session.user

        # Deny editing locked documents
        if ptype == "write" and doc.get("status") == "Locked":
            if "System Manager" not in frappe.get_roles(user):
                return False

        # Deny access to confidential documents
        if doc.get("is_confidential"):
            allowed_users = get_allowed_users(doc.name)
            if user not in allowed_users:
                return False

        # ALWAYS return None to defer to standard checks
        return None

    except Exception:
        frappe.log_error(
            frappe.get_traceback(),
            f"Permission check error: {doc.name if hasattr(doc, 'name') else 'unknown'}"
        )
        # Safe fallback - defer to standard system
        return None

permission_query_conditions - NEVER Throw!

# ❌ WRONG - Breaks list views!
def query_conditions(user):
    if not user:
        frappe.throw("User required")
    return f"owner = '{user}'"  # Also SQL injection!

# ✅ CORRECT - Return safe SQL condition
def query_conditions(user):
    """
    Return SQL WHERE clause fragment for list filtering.

    Returns:
        str: SQL condition (empty string for no restriction)

    NEVER throw errors - return restrictive fallback.
    """
    try:
        if not user:
            user = frappe.session.user

        roles = frappe.get_roles(user)

        # Admins see all
        if "System Manager" in roles:
            return ""

        # Managers see team records
        if "Sales Manager" in roles:
            team_users = get_team_users(user)
            if team_users:
                escaped = ", ".join([frappe.db.escape(u) for u in team_users])
                return f"`tabSales Order`.owner IN ({escaped})"

        # Default: own records only
        return f"`tabSales Order`.owner = {frappe.db.escape(user)}"

    except Exception:
        frappe.log_error(
            frappe.get_traceback(),
            f"Permission query error for {user}"
        )
        # SAFE FALLBACK: Most restrictive - own records only
        return f"`tabSales Order`.owner = {frappe.db.escape(frappe.session.user)}"

Permission Check Error Handling

Pattern 1: Check Before Action (Recommended)

@frappe.whitelist()
def update_order_status(order_name, new_status):
    """Update order status with permission check."""
    # Check document exists
    if not frappe.db.exists("Sales Order", order_name):
        frappe.throw(
            _("Sales Order {0} not found").format(order_name),
            exc=frappe.DoesNotExistError
        )

    # Check permission - throws automatically
    frappe.has_permission("Sales Order", "write", order_name, throw=True)

    # Now safe to proceed
    frappe.db.set_value("Sales Order", order_name, "status", new_status)

    return {"status": "success"}

Pattern 2: Custom Permission Error Response

@frappe.whitelist()
def sensitive_operation(doc_name):
    """Operation with custom permission error handling."""
    try:
        doc = frappe.get_doc("Sensitive Doc", doc_name)
        doc.check_permission("write")

    except frappe.DoesNotExistError:
        frappe.throw(
            _("Document not found"),
            exc=frappe.DoesNotExistError
        )

    except frappe.PermissionError:
        # Log attempted access
        frappe.log_error(
            f"Unauthorized access attempt: {doc_name} by {frappe.session.user}",
            "Security Alert"
        )
        # Custom error message
        frappe.throw(
            _("You don't have permission to perform this action. This incident has been logged."),
            exc=frappe.PermissionError
        )

    # Proceed with operation
    return process_document(doc)

Pattern 3: Role-Restricted Endpoint

@frappe.whitelist()
def admin_dashboard_data():
    """Endpoint restricted to specific roles."""
    # This throws PermissionError if user lacks role
    frappe.only_for(["System Manager", "Dashboard Admin"])

    # Only reaches here if authorized
    return compile_dashboard_data()

@frappe.whitelist()
def manager_report():
    """Endpoint with graceful role check."""
    allowed_roles = ["Sales Manager", "General Manager", "System Manager"]
    user_roles = frappe.get_roles()

    if not any(role in user_roles for role in allowed_roles):
        frappe.throw(
            _("This report is only available to managers"),
            exc=frappe.PermissionError
        )

    return generate_report()

Error Response Patterns

Standard Permission Error

# Uses frappe.PermissionError - returns HTTP 403
frappe.throw(
    _("You don't have permission to access this resource"),
    exc=frappe.PermissionError
)

Permission Error with Context

def check_access(doc):
    """Check access with helpful error message."""
    if not doc.has_permission("read"):
        owner_name = frappe.db.get_value("User", doc.owner, "full_name")
        frappe.throw(
            _("This document belongs to {0}. You can only view your own documents.").format(owner_name),
            exc=frappe.PermissionError
        )

Soft Permission Denial (No Error)

@frappe.whitelist()
def get_dashboard_widgets():
    """Return widgets based on user permissions."""
    widgets = []

    # Add widgets based on permissions
    if frappe.has_permission("Sales Order", "read"):
        widgets.append(get_sales_widget())

    if frappe.has_permission("Purchase Order", "read"):
        widgets.append(get_purchase_widget())

    if frappe.has_permission("Employee", "read"):
        widgets.append(get_hr_widget())

    # No error if no widgets - just return empty
    return widgets

Client-Side Permission Error Handling

JavaScript Error Handling

// Handle permission errors in frappe.call
frappe.call({
    method: "myapp.api.sensitive_operation",
    args: { doc_name: "DOC-001" },
    callback: function(r) {
        if (r.message) {
            frappe.show_alert({
                message: __("Operation completed"),
                indicator: "green"
            });
        }
    },
    error: function(r) {
        // Check if it's a permission error
        if (r.exc_type === "PermissionError") {
            frappe.msgprint({
                title: __("Access Denied"),
                message: __("You don't have permission to perform this action."),
                indicator: "red"
            });
        } else {
            // Generic error handling
            frappe.msgprint({
                title: __("Error"),
                message: r.exc || __("An error occurred"),
                indicator: "red"
            });
        }
    }
});

Permission Check Before Action

// Check permission before showing button
frappe.ui.form.on("Sales Order", {
    refresh: function(frm) {
        // Only show button if user has write permission
        if (frm.doc.docstatus === 0 && frappe.perm.has_perm("Sales Order", 0, "write")) {
            frm.add_custom_button(__("Special Action"), function() {
                perform_special_action(frm);
            });
        }
    }
});

// Or use frappe.call to check server-side
frappe.call({
    method: "frappe.client.has_permission",
    args: {
        doctype: "Sales Order",
        docname: frm.doc.name,
        ptype: "write"
    },
    async: false,
    callback: function(r) {
        if (r.message) {
            // Has permission - show button
        }
    }
});

Critical Rules

✅ ALWAYS

  1. Return None in has_permission hooks - Never return True
  2. Use frappe.db.escape() in query conditions - Prevent SQL injection
  3. Wrap hooks in try/except - Errors break access entirely
  4. Log permission errors - Security audit trail
  5. Use throw=True in permission checks - Automatic error handling
  6. Provide helpful error messages - Tell users what they can do

❌ NEVER

  1. Don't throw in permission hooks - Return False instead
  2. Don't use string concatenation in SQL - SQL injection risk
  3. Don't return True in has_permission - Hooks can only deny
  4. Don't ignore permission errors - Security risk
  5. Don't expose sensitive info in errors - Security risk

Quick Reference: Permission Error Handling

ContextError MethodFallback
has_permission hookReturn FalseReturn None
permission_query_conditionsReturn restrictive SQLOwn records filter
Whitelisted methodfrappe.throw(exc=PermissionError)N/A
Controllerdoc.check_permission()Let propagate
Client Scripterror callbackShow user message

Reference Files

FileContents
references/patterns.mdComplete error handling patterns
references/examples.mdFull working examples
references/anti-patterns.mdCommon mistakes to avoid

See Also

  • erpnext-permissions - Permission system overview
  • erpnext-errors-hooks - Hook error handling
  • erpnext-errors-api - API error handling
  • erpnext-syntax-hooks - Hook syntax

平台分布

Codex

38.25%
按下载量换算133

Claude

28.98%
按下载量换算101

Cursor

17.63%
按下载量换算62

Gemini CLI

8.81%
按下载量换算31

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills