From f3847644157c5bcbd6a1b9a3ee2c9da04b2f7116 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 22:25:30 +0800
Subject: [PATCH 01/35] feat: Upgrade to PHP 8.0 and PHP-Casbin 4.0
---
composer.json | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/composer.json b/composer.json
index ab8bcf3..8cb8692 100644
--- a/composer.json
+++ b/composer.json
@@ -2,6 +2,7 @@
"name": "casbin/webman-permission",
"keywords": [
"webman",
+ "workerman",
"casbin",
"permission",
"access-control",
@@ -21,12 +22,12 @@
"type": "library",
"license": "MIT",
"require": {
- "php": ">=7.4",
- "casbin/casbin": "^3.20",
- "topthink/think-orm": "^2.0|^3.0",
- "php-di/php-di": "^6.3|^7.0",
+ "php": ">=8.0",
+ "casbin/casbin": "~4.0",
+ "topthink/think-orm": "^3.0",
+ "php-di/php-di": "^7.0",
"doctrine/annotations": "^1.13",
- "workerman/redis": "^1.0|^2.0"
+ "workerman/redis": "^2.0"
},
"autoload": {
"psr-4": {
@@ -39,7 +40,7 @@
}
},
"require-dev": {
- "phpunit/phpunit": "~7.0|~8.0|~9.0",
+ "phpunit/phpunit": "~8.0|~9.0",
"php-coveralls/php-coveralls": "^2.1",
"workerman/webman": "^1.0",
"vlucas/phpdotenv": "^5.5",
From da3f7fe94065dd641619420225f6102c28b25002 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 22:26:41 +0800
Subject: [PATCH 02/35] feat: Upgrade to PHP 8.0 and PHP-Casbin 4.0
---
.github/workflows/default.yml | 87 +++++++++++++++++++++++++++++++++++
.github/workflows/php.yml | 39 ----------------
2 files changed, 87 insertions(+), 39 deletions(-)
create mode 100644 .github/workflows/default.yml
delete mode 100644 .github/workflows/php.yml
diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
new file mode 100644
index 0000000..6189d18
--- /dev/null
+++ b/.github/workflows/default.yml
@@ -0,0 +1,87 @@
+name: Default
+
+on: [push, pull_request]
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ services:
+ mysql:
+ image: mysql:5.7
+ env:
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
+ MYSQL_DATABASE: tauthz
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+
+ strategy:
+ fail-fast: true
+ matrix:
+ php: [ 8.0, 8.1, 8.2, 8.3 ]
+
+ name: PHP${{ matrix.php }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: composer:v2
+ coverage: xdebug
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-${{ matrix.php }}
+
+ - name: Install dependencies
+ if: steps.composer-cache.outputs.cache-hit != 'true'
+ run: composer install --prefer-dist --no-progress --no-suggest
+
+ - name: Run test suite
+ run: ./vendor/bin/phpunit
+
+ - name: Run Coveralls
+ env:
+ COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COVERALLS_PARALLEL: true
+ COVERALLS_FLAG_NAME: ${{ runner.os }} - ${{ matrix.php }}
+ run: |
+ composer global require php-coveralls/php-coveralls:^2.4
+ php-coveralls --coverage_clover=build/logs/clover.xml -v
+
+ upload-coverage:
+ runs-on: ubuntu-latest
+ needs: [ test ]
+ steps:
+ - name: Coveralls Finished
+ uses: coverallsapp/github-action@master
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ parallel-finished: true
+
+ semantic-release:
+ runs-on: ubuntu-latest
+ needs: [ test ]
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 'lts/*'
+
+ - name: Run semantic-release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
+ run: npx semantic-release
\ No newline at end of file
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
deleted file mode 100644
index 1ef7894..0000000
--- a/.github/workflows/php.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: PHP Composer
-
-on:
- push:
- branches: [ "main" ]
- pull_request:
- branches: [ "main" ]
-
-permissions:
- contents: read
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Validate composer.json and composer.lock
- run: composer validate --strict
-
- - name: Cache Composer packages
- id: composer-cache
- uses: actions/cache@v3
- with:
- path: vendor
- key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
- restore-keys: |
- ${{ runner.os }}-php-
-
- - name: Install dependencies
- run: composer install --prefer-dist --no-progress
-
- # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
- # Docs: https://getcomposer.org/doc/articles/scripts.md
-
- # - name: Run test suite
- # run: composer run-script test
From d4aa0b6eb24b99c3e8b25c487438d4ba09f40ebd Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 22:29:38 +0800
Subject: [PATCH 03/35] feat: Upgrade to PHP 8.0 and PHP-Casbin 4.0
---
composer.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/composer.json b/composer.json
index 8cb8692..518ade5 100644
--- a/composer.json
+++ b/composer.json
@@ -48,7 +48,6 @@
"illuminate/database": "^8.83",
"illuminate/pagination": "^8.83",
"illuminate/events": "^8.83",
- "symfony/var-dumper": "^6.2",
"webman/think-orm": "^1.0"
}
}
From 8fb08da3575c4cf6ccbad0a23ff2666115509423 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 22:32:34 +0800
Subject: [PATCH 04/35] feat: Upgrade to PHP 8.0 and PHP-Casbin 4.0
---
composer.json | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/composer.json b/composer.json
index 518ade5..859e515 100644
--- a/composer.json
+++ b/composer.json
@@ -40,10 +40,8 @@
}
},
"require-dev": {
- "phpunit/phpunit": "~8.0|~9.0",
"php-coveralls/php-coveralls": "^2.1",
- "workerman/webman": "^1.0",
- "vlucas/phpdotenv": "^5.5",
+ "workerman/webman": "^1.5",
"psr/container": "^1.1.1",
"illuminate/database": "^8.83",
"illuminate/pagination": "^8.83",
From 98e06baf26396bafd721c8b56322a9a37d06ec76 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 22:36:34 +0800
Subject: [PATCH 05/35] feat: Upgrade to PHP 8.0 and PHP-Casbin 4.0
---
.github/workflows/default.yml | 38 +----------------------------------
1 file changed, 1 insertion(+), 37 deletions(-)
diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
index 6189d18..7333927 100644
--- a/.github/workflows/default.yml
+++ b/.github/workflows/default.yml
@@ -48,40 +48,4 @@ jobs:
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
- run: composer install --prefer-dist --no-progress --no-suggest
-
- - name: Run test suite
- run: ./vendor/bin/phpunit
-
- - name: Run Coveralls
- env:
- COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- COVERALLS_PARALLEL: true
- COVERALLS_FLAG_NAME: ${{ runner.os }} - ${{ matrix.php }}
- run: |
- composer global require php-coveralls/php-coveralls:^2.4
- php-coveralls --coverage_clover=build/logs/clover.xml -v
-
- upload-coverage:
- runs-on: ubuntu-latest
- needs: [ test ]
- steps:
- - name: Coveralls Finished
- uses: coverallsapp/github-action@master
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- parallel-finished: true
-
- semantic-release:
- runs-on: ubuntu-latest
- needs: [ test ]
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
- with:
- node-version: 'lts/*'
-
- - name: Run semantic-release
- env:
- GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- run: npx semantic-release
\ No newline at end of file
+ run: composer install --prefer-dist --no-progress --no-suggest
\ No newline at end of file
From 2ada6ff2d0bd8ef87c762637ed1a742915b5b500 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Fri, 1 Nov 2024 23:58:57 +0800
Subject: [PATCH 06/35] feat: Casbin Logger, Supported:
\Psr\Log\LoggerInterface
---
src/Permission.php | 23 +++++++++++++++----
.../casbin/webman-permission/permission.php | 10 ++++++--
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/src/Permission.php b/src/Permission.php
index b708f52..3654f48 100644
--- a/src/Permission.php
+++ b/src/Permission.php
@@ -13,7 +13,11 @@
use Casbin\Enforcer;
use Casbin\Exceptions\CasbinException;
+use Casbin\Log\Logger\DefaultLogger;
use Casbin\Model\Model;
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+use Psr\Log\LoggerInterface;
use support\Container;
use Casbin\WebmanPermission\Watcher\RedisWatcher;
@@ -67,10 +71,11 @@ class Permission
protected static array $_manager = [];
/**
- * @param string|null $driver
+ * @desc driver
+ * @param string|null $driver
* @return Enforcer
* @throws CasbinException
- * @author Lyt8384
+ * @author Tinywan(ShaoBo Wan)
*/
public static function driver(?string $driver = null): Enforcer
{
@@ -87,7 +92,15 @@ public static function driver(?string $driver = null): Enforcer
} elseif ('text' == $config['model']['config_type']) {
$model->loadModel($config['model']['config_text']);
}
- static::$_manager[$driver] = new Enforcer($model, Container::make($config['adapter'], [$driver]), false);
+ $logConfig = self::getConfig('log');
+ $logger = null;
+ if (true === $logConfig['enabled']) {
+ /** @var LoggerInterface $casbinLogger 创建一个 Monolog 日志记录器 */
+ $casbinLogger = new Logger($logConfig['logger']);
+ $casbinLogger->pushHandler(new StreamHandler($logConfig['path'], Logger::DEBUG));
+ $logger = new DefaultLogger($casbinLogger);
+ }
+ static::$_manager[$driver] = new Enforcer($model, Container::make($config['adapter'], [$driver]), $logger, $logConfig['enabled']);
$watcher = new RedisWatcher(config('redis.default'), $driver);
static::$_manager[$driver]->setWatcher($watcher);
@@ -112,7 +125,7 @@ public static function getAllDriver(): array
* @return mixed
* @author Tinywan(ShaoBo Wan)
*/
- public static function getDefaultDriver()
+ public static function getDefaultDriver(): mixed
{
return self::getConfig('default');
}
@@ -124,7 +137,7 @@ public static function getDefaultDriver()
* @return mixed
* @author Tinywan(ShaoBo Wan)
*/
- public static function getConfig(string $name = null, $default = null)
+ public static function getConfig(string $name = null, $default = null): mixed
{
if (!is_null($name)) {
return config('plugin.casbin.webman-permission.permission.' . $name, $default);
diff --git a/src/config/plugin/casbin/webman-permission/permission.php b/src/config/plugin/casbin/webman-permission/permission.php
index ce867ac..2460f33 100644
--- a/src/config/plugin/casbin/webman-permission/permission.php
+++ b/src/config/plugin/casbin/webman-permission/permission.php
@@ -6,7 +6,13 @@
*/
return [
'default' => 'basic',
- // 默认配置
+ /** 日志配置 */
+ 'log' => [
+ 'enabled' => true, // changes will log messages to the Logger.
+ 'logger' => 'Casbin', // Casbin Logger, Supported: \Psr\Log\LoggerInterface|string
+ 'path' => runtime_path() . '/logs/casbin.log' // log path
+ ],
+ /** 默认配置 */
'basic' => [
// 策略模型Model设置
'model' => [
@@ -24,7 +30,7 @@
'rules_name' => null
],
],
- // 其他扩展配置,只需要按照基础配置一样,复制一份,指定相关策略模型和适配器即可
+ /** 其他扩展配置,只需要按照基础配置一样,复制一份,指定相关策略模型和适配器即可 */
'restful' => [
'model' => [
'config_type' => 'file',
From d3e893a2b56c97118c8d3504b478f5fab6a6fcb4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:06:24 +0800
Subject: [PATCH 07/35] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 5fb99e3..26bb5b9 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
Webman Authorization Plugin
+[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
[](https://packagist.org/packages/casbin/webman-permission)
[](https://packagist.org/packages/casbin/webman-permission)
[](https://packagist.org/packages/casbin/webman-permission)
From cb04496e45c30cb3f6c988e847aff53e16cee487 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:10:53 +0800
Subject: [PATCH 08/35] feat: Casbin Logger, Supported:
\Psr\Log\LoggerInterface
---
src/Adapter/DatabaseAdapter.php | 36 ++++++++++++++++++++------
src/Adapter/LaravelDatabaseAdapter.php | 3 ++-
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/src/Adapter/DatabaseAdapter.php b/src/Adapter/DatabaseAdapter.php
index d440ec5..e28219d 100644
--- a/src/Adapter/DatabaseAdapter.php
+++ b/src/Adapter/DatabaseAdapter.php
@@ -18,6 +18,9 @@
use Casbin\Persist\FilteredAdapter;
use Casbin\Persist\Adapters\Filter;
use Casbin\Exceptions\InvalidFilterTypeException;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use Casbin\WebmanPermission\Model\RuleModel;
@@ -80,7 +83,7 @@ public function filterRule(array $rule): array
*
* @return void
*/
- public function savePolicyLine($ptype, array $rule)
+ public function savePolicyLine(string $ptype, array $rule): void
{
$col['ptype'] = $ptype;
foreach ($rule as $key => $value) {
@@ -93,6 +96,9 @@ public function savePolicyLine($ptype, array $rule)
* loads all policy rules from the storage.
*
* @param Model $model
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
*/
public function loadPolicy(Model $model): void
{
@@ -168,7 +174,10 @@ public function addPolicies(string $sec, string $ptype, array $rules): void
*
* @param string $sec
* @param string $ptype
- * @param array $rule
+ * @param array $rule
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
*/
public function removePolicy(string $sec, string $ptype, array $rule): void
{
@@ -205,12 +214,14 @@ public function removePolicies(string $sec, string $ptype, array $rules): void
}
/**
- * @param string $sec
- * @param string $ptype
- * @param int $fieldIndex
+ * @param string $sec
+ * @param string $ptype
+ * @param int $fieldIndex
* @param string|null ...$fieldValues
* @return array
- * @throws Throwable
+ * @throws DbException
+ * @throws ModelNotFoundException
+ * @throws DataNotFoundException
*/
public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): array
{
@@ -244,8 +255,11 @@ public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldInde
*
* @param string $sec
* @param string $ptype
- * @param int $fieldIndex
+ * @param int $fieldIndex
* @param string ...$fieldValues
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
*/
public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): void
{
@@ -260,6 +274,9 @@ public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex
* @param string $ptype
* @param string[] $oldRule
* @param string[] $newPolicy
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
*/
public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
{
@@ -342,6 +359,10 @@ public function setFiltered(bool $filtered): void
*
* @param Model $model
* @param mixed $filter
+ * @throws InvalidFilterTypeException
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
*/
public function loadFilteredPolicy(Model $model, $filter): void
{
@@ -351,7 +372,6 @@ public function loadFilteredPolicy(Model $model, $filter): void
$instance = $instance->whereRaw($filter);
} elseif ($filter instanceof Filter) {
foreach ($filter->p as $k => $v) {
- $where[$v] = $filter->g[$k];
$instance = $instance->where($v, $filter->g[$k]);
}
} elseif ($filter instanceof \Closure) {
diff --git a/src/Adapter/LaravelDatabaseAdapter.php b/src/Adapter/LaravelDatabaseAdapter.php
index 39a3c3b..4a13689 100644
--- a/src/Adapter/LaravelDatabaseAdapter.php
+++ b/src/Adapter/LaravelDatabaseAdapter.php
@@ -368,7 +368,8 @@ public function loadFilteredPolicy(Model $model, $filter): void
*
* @return Builder[]|Collection
*/
- protected function getCollection(string $ptype, int $fieldIndex, array $fieldValues) {
+ protected function getCollection(string $ptype, int $fieldIndex, array $fieldValues): Collection|array
+ {
$where = [
'ptype' => $ptype,
];
From 501f05592dcbb1d34d6c58d6dc9f71f2740dd65d Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:20:15 +0800
Subject: [PATCH 09/35] feat: Dependency Injection configuration
---
README.md | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 26bb5b9..3751801 100644
--- a/README.md
+++ b/README.md
@@ -9,17 +9,18 @@
An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin
-# 安装
+# Install
+Composer Install
```sh
composer require -W casbin/webman-permission
```
-# 使用
+# Use
-## 依赖注入配置
+## Dependency Injection configuration
-修改配置`config/container.php`,其最终内容如下:
+Modify the `config/container.php` configuration to perform the following final contents:
```php
$builder = new \DI\ContainerBuilder();
@@ -28,7 +29,7 @@ $builder->useAutowiring(true);
return $builder->build();
```
-## 数据库配置
+## Database configuration
默认策略存储是使用的ThinkORM。
From 16cb99db1466b12825c922e09122174cb09a5606 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:23:56 +0800
Subject: [PATCH 10/35] feat: Dependency Injection configuration
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 3751801..1bf313a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
- Webman Authorization Plugin
-
+
+
+**🐇 Webman Authorization Plugin Base Casbin. 🐇
**
[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
[](https://packagist.org/packages/casbin/webman-permission)
From 3ebb313f07d5ab49091515d0dd282def50796752 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:26:02 +0800
Subject: [PATCH 11/35] feat: Webman Authorization Plugin Base Casbin
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 1bf313a..90b81cc 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
**🐇 Webman Authorization Plugin Base Casbin. 🐇
**
+# 🐇 Webman Authorization Plugin Base Casbin. 🐇
+
[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
[](https://packagist.org/packages/casbin/webman-permission)
[](https://packagist.org/packages/casbin/webman-permission)
From 8439762387e4319227bcea9b450af109c8b87526 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:31:26 +0800
Subject: [PATCH 12/35] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 90b81cc..42b6c2f 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
**🐇 Webman Authorization Plugin Base Casbin. 🐇
**
-# 🐇 Webman Authorization Plugin Base Casbin. 🐇
+# 🐇 Webman Authorization Plugin Base Casbin. 🐇
[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
[](https://packagist.org/packages/casbin/webman-permission)
From 3a800be970fe86c596fb18b265ccc4f136c9d5f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:32:45 +0800
Subject: [PATCH 13/35] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 42b6c2f..d23b3c5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@

-**🐇 Webman Authorization Plugin Base Casbin. 🐇
**
+**🐇 An Authorization Dor Webman plugin Plugin. 🐇
**
# 🐇 Webman Authorization Plugin Base Casbin. 🐇
From 13af728a5eda4a8823dcc7f7f80741946a6ce850 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Sat, 2 Nov 2024 00:33:08 +0800
Subject: [PATCH 14/35] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d23b3c5..2feefa6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@

-**🐇 An Authorization Dor Webman plugin Plugin. 🐇
**
+**🐇 An Authorization For Webman plugin Plugin. 🐇
**
# 🐇 Webman Authorization Plugin Base Casbin. 🐇
From 857bc6d8a39b0d03bcf914878fd83130a0c8e998 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Sat, 2 Nov 2024 01:14:54 +0800
Subject: [PATCH 15/35] feat: default close log
---
src/config/plugin/casbin/webman-permission/permission.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/config/plugin/casbin/webman-permission/permission.php b/src/config/plugin/casbin/webman-permission/permission.php
index 2460f33..ff00a4b 100644
--- a/src/config/plugin/casbin/webman-permission/permission.php
+++ b/src/config/plugin/casbin/webman-permission/permission.php
@@ -8,7 +8,7 @@
'default' => 'basic',
/** 日志配置 */
'log' => [
- 'enabled' => true, // changes will log messages to the Logger.
+ 'enabled' => false, // changes will log messages to the Logger.
'logger' => 'Casbin', // Casbin Logger, Supported: \Psr\Log\LoggerInterface|string
'path' => runtime_path() . '/logs/casbin.log' // log path
],
From 628604375bd52572d1f940f0f69f335ef733e417 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Mon, 4 Nov 2024 09:27:40 +0800
Subject: [PATCH 16/35] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2feefa6..4fc0c20 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@

-**🐇 An Authorization For Webman plugin Plugin. 🐇
**
+**🐇 An Authorization For Webman Plugin. 🐇
**
# 🐇 Webman Authorization Plugin Base Casbin. 🐇
From 3b9943fb5467c86d40a84cb9d9bbd2dbdc93f86f Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Mon, 4 Nov 2024 09:39:55 +0800
Subject: [PATCH 17/35] test:phpunit
---
.github/workflows/default.yml | 5 ++++-
composer.json | 5 +++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
index 7333927..e98f8e4 100644
--- a/.github/workflows/default.yml
+++ b/.github/workflows/default.yml
@@ -48,4 +48,7 @@ jobs:
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
- run: composer install --prefer-dist --no-progress --no-suggest
\ No newline at end of file
+ run: composer install --prefer-dist --no-progress --no-suggest
+
+ - name: Run test suite
+ run: ./vendor/bin/phpunit
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 859e515..42fcf40 100644
--- a/composer.json
+++ b/composer.json
@@ -40,12 +40,13 @@
}
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.1",
+ "php-coveralls/php-coveralls": "^2.7",
"workerman/webman": "^1.5",
"psr/container": "^1.1.1",
"illuminate/database": "^8.83",
"illuminate/pagination": "^8.83",
"illuminate/events": "^8.83",
- "webman/think-orm": "^1.0"
+ "webman/think-orm": "^1.0",
+ "phpunit/phpunit": "^11.4"
}
}
From c5fd2654a5cbb49566dd2d3dc70e9aff8a9fa143 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Mon, 4 Nov 2024 09:47:15 +0800
Subject: [PATCH 18/35] test:phpunit
---
phpunit.xml | 17 ++++++
tests/bootstrap.php | 133 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 150 insertions(+)
create mode 100644 phpunit.xml
create mode 100644 tests/bootstrap.php
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..640cb16
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ ./tests
+
+
+
\ No newline at end of file
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..d9471e6
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,133 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Dotenv\Dotenv;
+use support\Log;
+use Webman\Bootstrap;
+use Webman\Config;
+use Webman\Middleware;
+use Webman\Route;
+use Webman\Util;
+
+$worker = $worker ?? null;
+
+set_error_handler(function ($level, $message, $file = '', $line = 0) {
+ if (error_reporting() & $level) {
+ throw new ErrorException($message, 0, $level, $file, $line);
+ }
+});
+
+if ($worker) {
+ register_shutdown_function(function ($startTime) {
+ if (time() - $startTime <= 0.1) {
+ sleep(1);
+ }
+ }, time());
+}
+
+if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
+ if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
+ Dotenv::createUnsafeMutable(base_path(false))->load();
+ } else {
+ Dotenv::createMutable(base_path(false))->load();
+ }
+}
+
+Config::clear();
+support\App::loadAllConfig(['route']);
+if ($timezone = config('app.default_timezone')) {
+ date_default_timezone_set($timezone);
+}
+
+foreach (config('autoload.files', []) as $file) {
+ include_once $file;
+}
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project)) {
+ continue;
+ }
+ foreach ($project['autoload']['files'] ?? [] as $file) {
+ include_once $file;
+ }
+ }
+ foreach ($projects['autoload']['files'] ?? [] as $file) {
+ include_once $file;
+ }
+}
+
+Middleware::load(config('middleware', []));
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project) || $name === 'static') {
+ continue;
+ }
+ Middleware::load($project['middleware'] ?? []);
+ }
+ Middleware::load($projects['middleware'] ?? [], $firm);
+ if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
+ Middleware::load(['__static__' => $staticMiddlewares], $firm);
+ }
+}
+Middleware::load(['__static__' => config('static.middleware', [])]);
+
+foreach (config('bootstrap', []) as $className) {
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+}
+
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project)) {
+ continue;
+ }
+ foreach ($project['bootstrap'] ?? [] as $className) {
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+ }
+ }
+ foreach ($projects['bootstrap'] ?? [] as $className) {
+ /** @var string $className */
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+ }
+}
+
+$directory = base_path() . '/plugin';
+$paths = [config_path()];
+foreach (Util::scanDir($directory) as $path) {
+ if (is_dir($path = "$path/config")) {
+ $paths[] = $path;
+ }
+}
+Route::load($paths);
+
From 6f0bdbe14d28df58e46c8b364c3d79e9418af530 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Mon, 4 Nov 2024 09:47:18 +0800
Subject: [PATCH 19/35] test:phpunit
---
.github/workflows/default.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
index e98f8e4..2030629 100644
--- a/.github/workflows/default.yml
+++ b/.github/workflows/default.yml
@@ -50,5 +50,5 @@ jobs:
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest
- - name: Run test suite
- run: ./vendor/bin/phpunit
\ No newline at end of file
+# - name: Run test suite
+# run: ./vendor/bin/phpunit
\ No newline at end of file
From ffa0bedffc643c6744436e7843c502e9394c630c Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Tue, 10 Dec 2024 17:56:47 +0800
Subject: [PATCH 20/35] feat:doctrine/annotations 2.x support
---
composer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index 42fcf40..601f61b 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
"casbin/casbin": "~4.0",
"topthink/think-orm": "^3.0",
"php-di/php-di": "^7.0",
- "doctrine/annotations": "^1.13",
+ "doctrine/annotations": "^2.0",
"workerman/redis": "^2.0"
},
"autoload": {
From 53d0353404e32a3cd6c3246ae3e187ce9915ce31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?ShaoBo=20Wan=28=E7=84=A1=E5=B0=98=29?= <756684177@qq.com>
Date: Fri, 21 Feb 2025 21:49:38 +0800
Subject: [PATCH 21/35] Update composer.json
---
composer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index 601f61b..f44bc7d 100644
--- a/composer.json
+++ b/composer.json
@@ -41,7 +41,7 @@
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.7",
- "workerman/webman": "^1.5",
+ "workerman/webman": "^1.5||^2.0",
"psr/container": "^1.1.1",
"illuminate/database": "^8.83",
"illuminate/pagination": "^8.83",
From ec825f0fc7f63a693be6b90136b7962030771bca Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Wed, 30 Apr 2025 11:20:18 +0800
Subject: [PATCH 22/35] Q:resolveConnection
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 4fc0c20..4482e3b 100644
--- a/README.md
+++ b/README.md
@@ -158,3 +158,8 @@ if (is_null(static::$_manager)) {
```
耦合太高,不建议这么搞,更多了解:https://www.workerman.net/doc/webman/di.html
+
+## 问题
+
+* Laravel的驱动报错:`Call to a member function connection() on null|webman2.1/vendor/illuminate/database/Eloquent/Model.
+ php|1918`。解决方案,请检查本地数据库代理是否正常,如使用了Docker容器主机地址`dnmp-mysql`可能会导致该问题出现。
From 2cccd09d20c96caeafdf0bce157801b971ba088d Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Wed, 30 Apr 2025 11:40:56 +0800
Subject: [PATCH 23/35] fix:LaravelDatabaseAdapter removePolicies errorA facade
root has not been set
---
src/Adapter/LaravelDatabaseAdapter.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Adapter/LaravelDatabaseAdapter.php b/src/Adapter/LaravelDatabaseAdapter.php
index 4a13689..4bc75b8 100644
--- a/src/Adapter/LaravelDatabaseAdapter.php
+++ b/src/Adapter/LaravelDatabaseAdapter.php
@@ -21,7 +21,7 @@
use Casbin\WebmanPermission\Model\LaravelRuleModel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
-use Illuminate\Support\Facades\DB;
+use support\Db;
use Throwable;
/**
@@ -208,7 +208,7 @@ public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldInde
*/
public function removePolicies(string $sec, string $ptype, array $rules): void
{
- DB::transaction(function () use ($sec, $ptype, $rules) {
+ Db::transaction(function () use ($sec, $ptype, $rules) {
foreach ($rules as $rule) {
$this->removePolicy($sec, $ptype, $rule);
}
@@ -269,7 +269,7 @@ public function updatePolicy(string $sec, string $ptype, array $oldRule, array $
*/
public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
{
- DB::transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
+ Db::transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
foreach ($oldRules as $i => $oldRule) {
$this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
}
@@ -289,7 +289,7 @@ public function updatePolicies(string $sec, string $ptype, array $oldRules, arra
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
{
$oldRules = [];
- DB::transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
+ Db::transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
$oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
$this->addPolicies($sec, $ptype, $newPolicies);
});
From 60b5e4ba93d96a90433d18737f31db7ae063f224 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Wed, 30 Apr 2025 11:49:10 +0800
Subject: [PATCH 24/35] matrix:8.4
---
.github/workflows/default.yml | 2 +-
composer.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
index 2030629..2d2596d 100644
--- a/.github/workflows/default.yml
+++ b/.github/workflows/default.yml
@@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- php: [ 8.0, 8.1, 8.2, 8.3 ]
+ php: [ 8.1, 8.2, 8.3, 8.4]
name: PHP${{ matrix.php }}
diff --git a/composer.json b/composer.json
index f44bc7d..f6ada65 100644
--- a/composer.json
+++ b/composer.json
@@ -47,6 +47,6 @@
"illuminate/pagination": "^8.83",
"illuminate/events": "^8.83",
"webman/think-orm": "^1.0",
- "phpunit/phpunit": "^11.4"
+ "phpunit/phpunit": "^10.5"
}
}
From ba2deea01cda17c09d22f48343cf34291bbce29d Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Wed, 30 Apr 2025 11:51:50 +0800
Subject: [PATCH 25/35] Create status badge
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4482e3b..a3fc832 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# 🐇 Webman Authorization Plugin Base Casbin. 🐇
-[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
+[](https://github.com/php-casbin/webman-permission/actions/workflows/default.yml)
[](https://packagist.org/packages/casbin/webman-permission)
[](https://packagist.org/packages/casbin/webman-permission)
[](https://packagist.org/packages/casbin/webman-permission)
From 843f93a95efd3391dfd93702b666e9a294dca679 Mon Sep 17 00:00:00 2001
From: Tinywan <756684177@qq.com>
Date: Wed, 30 Apr 2025 11:52:54 +0800
Subject: [PATCH 26/35] workbunny-logo.png
---
README.md | 2 +-
workbunny-logo.png | Bin 0 -> 52246 bytes
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 workbunny-logo.png
diff --git a/README.md b/README.md
index a3fc832..603aab6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
**🐇 An Authorization For Webman Plugin. 🐇
**
diff --git a/workbunny-logo.png b/workbunny-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f70df3eb98aacf4c8421d7e2f1dc7d63f84f68a
GIT binary patch
literal 52246
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