Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Release

on:
push:
branches: [master]
branches: [master]
pull_request:
branches: [master]

Expand Down Expand Up @@ -52,12 +52,12 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.os }}
path: dist/casbin-cli-*
path: dist/casbin-python-cli-*

release:
needs: [test, build-binaries]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
if: github.event_name == 'pull_request' && github.base_ref == 'master'

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Move binaries to dist
run: |
mkdir -p dist
find artifacts -name "casbin-cli-*" -exec cp {} dist/ \;
find artifacts -name "casbin-python-cli-*" -exec cp {} dist/ \;

- name: Semantic Release
env:
Expand Down
6 changes: 4 additions & 2 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"branches": ["master"],
"repositoryUrl": "https://github.com/casbin/casbin-python-cli",
"repositoryUrl":"https://github.com/casbin/casbin-python-cli",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
Expand Down Expand Up @@ -29,7 +29,9 @@
"label": "Source Distribution"
},
{
"path": "dist/casbin-cli-*"
"path": "dist/casbin-python-cli-*",
"name": "casbin-python-cli-${nextRelease.version}",
"label": "casbin-python-cli (${nextRelease.version})"
}
]
}
Expand Down
122 changes: 98 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@
![PyPI - License](https://img.shields.io/badge/license-Apache%202.0-green)
![PyPI - PyCasbin Version](https://img.shields.io/badge/pycasbin-1.17.0%2B-orange)

## Features

- **casbin-editor Integration**: Full API compatibility with casbin-editor for multi-language backend support
- **Unified JSON Response Format**: Standardized `{"allow": boolean|null, "explain": array|null}` response format
- **Method Name Mapping**: Automatic conversion between Java-style command names and Python method names
- **Comprehensive API Coverage**: Support for policy execution, management, RBAC operations, and data retrieval
- **Cross-platform Binaries**: Automated builds for Windows, macOS, and Linux
- **Dynamic Command Execution**: Reflection-based method invocation similar to Java version

## Installation

### Prerequisites

- Python 3.6+
- pip package manager

Expand All @@ -20,16 +30,81 @@ cd casbin-python-cli
pip install -r requirements.txt
```

### Method
## Usage

### Basic Command Structure

```bash
python -m casbin_cli.client [command] [options] [args]
```

### Examples

**Policy Execution**:
```bash
# Basic enforcement
python -m casbin_cli.client enforce -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data1" "read"
{"allow":true,"explain":null}

# Enforcement with explanation
python -m casbin_cli.client enforceEx -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data1" "read"
{"allow":true,"explain":["alice","data1","read"]}
```

**Policy Management**:
```bash
# Add policy
python -m casbin_cli.client addPolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "eve" "data3" "read"
{"allow":true,"explain":null}

# Get all policies
python -m casbin_cli.client getPolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv"
{"allow":null,"explain":[["alice","data1","read"],["bob","data2","write"]]}
```

**RBAC Operations**:
```bash
# Get user roles
python -m casbin_cli.client getRolesForUser -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice"
{"allow":null,"explain":["data2_admin"]}

# Get role users
python -m casbin_cli.client getUsersForRole -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "data2_admin"
{"allow":null,"explain":["alice"]}
```

**Data Retrieval**:
```bash
# Get all subjects
python -m casbin_cli.client getAllSubjects -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv"
{"allow":null,"explain":["alice","bob","data2_admin"]}

# Get all objects
python -m casbin_cli.client getAllObjects -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv"
{"allow":null,"explain":["data1","data2"]}
```

### API Compatibility

The Python CLI maintains full compatibility with the Java version through:

- **Command Interface**: Identical command-line arguments (`-m`, `-p`, etc.)
- **Method Name Mapping**: Automatic conversion from Java camelCase to Python snake_case
- **Response Format**: Standardized JSON responses matching Java implementation
- **Error Handling**: Consistent error reporting across all backends

### Supported APIs

| Category | Commands | Status |
| --------------------- | ------------------------------------------------------------ | ------ |
| **Policy Execution** | `enforce`, `enforceEx`, `enforceWithMatcher` | ✅ |
| **Policy Management** | `addPolicy`, `removePolicy`, `getPolicy`, `hasPolicy` | ✅ |
| **RBAC Operations** | `getRolesForUser`, `getUsersForRole`, `hasRoleForUser` | ✅ |
| **Data Retrieval** | `getAllSubjects`, `getAllObjects`, `getAllActions` | ✅ |
| **Grouping Policies** | `getGroupingPolicy`, `addGroupingPolicy`, `removeGroupingPolicy` | ✅ |
| **Named Policies** | `getNamedPolicy`, `getAllNamedRoles` | ✅ |
| **Filtered Queries** | `getFilteredPolicy`, `getFilteredGroupingPolicy` | ✅ |

## Project Structure

```
Expand All @@ -42,35 +117,34 @@ casbin-python-cli/
│ └── build_binaries.py # Binary building
├── casbin_cli/
│ ├── __init__.py
│ ├── __version__.py # Version source
│ ├── client.py # Main CLI entry point
│ ├── command_executor.py # Command execution
│ ├── enforcer_factory.py # Enforcer creation
│ ├── response.py # Response formatting
│ └── utils.py # Utilities
├── examples/ # Example configurations
├── .releaserc.json # Semantic release config
├── package.json # Node.js dependencies
├── requirements.txt # Python dependencies
├── setup.py # Package setup
└── README.md
│ ├── __version__.py # Version information
│ ├── client.py # Main CLI entry point & argument parsing
│ ├── command_executor.py # Dynamic command execution & method mapping
│ ├── enforcer_factory.py # PyCasbin enforcer creation
│ ├── response.py # Standardized JSON response formatting
│ └── utils.py # Utility functions
├── examples/ # Example model and policy files
│ ├── rbac_model.conf # RBAC model configuration
│ ├── rbac_policy.csv # RBAC policy data
│ ├── basic_model.conf # Basic model configuration
│ └── basic_policy.csv # Basic policy data
├── tests/ # Test files (if any)
├── .releaserc.json # Semantic release configuration
├── package.json # Node.js dependencies for release automation
├── requirements.txt # Python dependencies
├── setup.py # Package setup and distribution
└── README.md # This file
```

### Release Process

Releases are automated via GitHub Actions:

1. Push commits to `main` branch
2. Semantic release analyzes commit messages
3. Automatically generates version numbers and changelog
4. Builds cross-platform binaries
5. Publishes to PyPI and GitHub Releases

## Requirements

- Python 3.6+
- PyCasbin 1.17.0+

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.

---

**Note**: This Python CLI is part of the Casbin ecosystem and designed to work seamlessly with casbin-editor for multi-language backend support. For more information about Casbin, visit [casbin.org](https://casbin.org).
27 changes: 16 additions & 11 deletions casbin_cli/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ def run(args=None):
if command_name in ['-h', '--help']:
Client._print_help()
return ""
#elif command_name in ['-v', '--version']:
# print(f"casbin-python-cli {__version__}")
# print("pycasbin 1.17.0")
# return ""
elif command_name in ['-v', '--version']:
print(f"casbin-python-cli {__version__}")
print("pycasbin 1.17.0")
return ""

# Handle line breaks
processed_args = [args[0]]
Expand All @@ -53,14 +53,19 @@ def run(args=None):
result = executor.execute()

print(result)
return result

except Exception as e:
error_msg = str(e) or str(e.__cause__) if e.__cause__ else "Unknown error"
print(error_msg)
sys.exit(1)
return result

return ""
except Exception as e:
if hasattr(e, '__cause__') and e.__cause__:
error_msg = f"{str(e)}: {str(e.__cause__)}"
else:
error_msg = str(e) if str(e) else f"{type(e).__name__}: {repr(e)}"

if hasattr(sys, '_called_from_test') or 'pytest' in sys.modules:
raise type(e)(error_msg) from e
else:
print(error_msg)
sys.exit(1)

@staticmethod
def _parse_args(args):
Expand Down
Loading
Loading