增加扩展机制定位文件;将common模块实现扩展模式;发布新版本;

This commit is contained in:
2023-09-25 17:07:38 +08:00
parent 3dcf336bbc
commit 184dae8185
65 changed files with 3093 additions and 2751 deletions

View File

@@ -0,0 +1,212 @@
<?php
namespace base\common\service;
use app\common\constants\AdminConstant;
use think\facade\Config;
use think\facade\Db;
/**
* 权限验证服务
* Class AuthService.
*/
class AuthServiceBase
{
/**
* 用户ID.
* @var null
*/
protected $adminId = null;
/**
* 默认配置.
* @var array
*/
protected $config = [
'auth_on' => true, // 权限开关
'system_admin' => 'system_admin', // 用户表
'system_auth' => 'system_auth', // 权限表
'system_node' => 'system_node', // 节点表
'system_auth_node' => 'system_auth_node', // 权限-节点表
];
/**
* 管理员信息.
* @var array|\think\Model|null
*/
protected $adminInfo;
/**
* 所有节点信息.
* @var array
*/
protected $nodeList;
/**
* 管理员所有授权节点.
* @var array
*/
protected $adminNode;
/***
* 构造方法
* AuthService constructor.
* @param null $adminId
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function __construct($adminId = null)
{
$this->adminId = $adminId;
$this->adminInfo = $this->getAdminInfo();
$this->nodeList = $this->getNodeList();
$this->adminNode = $this->getAdminNode();
return $this;
}
/**
* 检测检测权限.
* @param null $node
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function checkNode($node = null)
{
// 判断是否为超级管理员
if ($this->adminId == AdminConstant::SUPER_ADMIN_ID) {
return true;
}
// 判断权限验证开关
if ($this->config['auth_on'] == false) {
return true;
}
// 判断是否需要获取当前节点
if (empty($node)) {
$node = $this->getCurrentNode();
} else {
$node = $this->parseNodeStr($node);
}
// 判断是否加入节点控制,优先获取缓存信息
if (!isset($this->nodeList[$node])) {
return Config::get('admin.default_auth_check');
}
$nodeInfo = $this->nodeList[$node];
if ($nodeInfo['is_auth'] == 0) {
return true;
}
// 用户验证,优先获取缓存信息
if (empty($this->adminInfo) || $this->adminInfo['status'] != 1 || empty($this->adminInfo['auth_ids'])) {
return false;
}
// 判断该节点是否允许访问
if (in_array($node, $this->adminNode)) {
return true;
}
return false;
}
/**
* 获取当前节点.
* @return string
*/
public function getCurrentNode()
{
$node = $this->parseNodeStr(request()->controller() . '/' . request()->action());
return $node;
}
/**
* 获取当前管理员所有节点.
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getAdminNode()
{
$nodeList = [];
$adminInfo = $this->getAdminInfo();
if (!empty($adminInfo) && $adminInfo['status'] != 1) {
return $nodeList;
}
if (!empty($adminInfo) && !empty($adminInfo['auth_ids'])) {
$buildAuthSql = Db::name($this->config['system_auth'])
->distinct(true)
->whereIn('id', $adminInfo['auth_ids'])
->field('id')
->buildSql(true);
$buildAuthNodeSql = Db::name($this->config['system_auth_node'])
->distinct(true)
->where("auth_id IN {$buildAuthSql}")
->field('node_id')
->buildSql(true);
$nodeList = Db::name($this->config['system_node'])
->distinct(true)
->where("id IN {$buildAuthNodeSql}")
->column('node');
}
return $nodeList;
}
/**
* 获取所有节点信息.
* @time 2021-01-07
* @return array
* @author zhongshaofa <shaofa.zhong@happy-seed.com>
*/
public function getNodeList()
{
return Db::name($this->config['system_node'])
->autoCache(null, null, 'table')
->column('id,node,title,type,is_auth', 'node');
}
/**
* 获取管理员信息.
* @time 2021-01-07
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author zhongshaofa <shaofa.zhong@happy-seed.com>
*/
public function getAdminInfo()
{
return Db::name($this->config['system_admin'])
->where('id', $this->adminId)
->autoCache('info', $this->adminId)
->find();
}
/**
* 驼峰转下划线规则.
* @param string $node
* @return string
*/
public function parseNodeStr($node)
{
$array = explode('/', $node);
foreach ($array as $key => $val) {
if ($key == 0) {
$val = explode('.', $val);
foreach ($val as &$vo) {
$vo = \think\helper\Str::snake(lcfirst($vo));
}
$val = implode('.', $val);
$array[$key] = $val;
}
}
$node = implode('/', $array);
return $node;
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace base\common\service;
use app\common\constants\MenuConstant;
use app\common\service\AuthService;
use think\facade\Db;
class MenuServiceBase
{
/**
* 管理员ID.
* @var int
*/
protected $adminId;
public function __construct($adminId)
{
$this->adminId = $adminId;
return $this;
}
/**
* 获取首页信息.
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getHomeInfo()
{
$data = Db::name('system_menu')
->field('title,icon,href')
->where('delete_time', 0)
->where('pid', MenuConstant::HOME_PID)
->find();
!empty($data) && $data['href'] = __url($data['href']);
return $data;
}
/**
* 获取后台菜单树信息.
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getMenuTree()
{
/** @var AuthService $authService */
$authServer = app(AuthService::class, ['adminId' => $this->adminId]);
return $this->buildMenuChild(0, $this->getMenuData(), $authServer);
}
private function buildMenuChild($pid, $menuList, AuthService $authServer)
{
$treeList = [];
foreach ($menuList as &$v) {
$check = false;
if (!empty($v['auth_node'])) {
$check = $authServer->checkNode($v['auth_node']);
} elseif (!empty($v['href'])) {
$check = $authServer->checkNode($v['href']);
} else {
$check = true;
}
!empty($v['href']) && $v['href'] = __url($v['href']);
if ($pid == $v['pid'] && $check) {
$node = $v;
$child = $this->buildMenuChild($v['id'], $menuList, $authServer);
if (!empty($child)) {
$node['child'] = $child;
}
if (!empty($v['href']) || !empty($child)) {
$treeList[] = $node;
}
}
}
return $treeList;
}
/**
* 获取所有菜单数据.
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function getMenuData()
{
$menuData = Db::name('system_menu')
->field('id,pid,title,icon,href,target')
->where('delete_time', 0)
->where([
['status', '=', '1'],
['pid', '<>', MenuConstant::HOME_PID],
])
->order([
'sort' => 'desc',
'id' => 'asc',
])
->select();
return $menuData;
}
}

View File

@@ -0,0 +1,168 @@
<?php
namespace base\common\service;
use app\admin\model\SystemUploadfile;
use app\common\tools\PathTools;
use think\exception\ValidateException;
use think\facade\App;
use think\facade\Filesystem;
use think\facade\Validate;
use think\File;
use think\file\UploadedFile;
class UploadServiceBase
{
protected $uploadType = 'local_public';
public function __construct($upload_type = null)
{
$uploadConfig = sysconfig('upload');
empty($upload_type) && $upload_type = $uploadConfig['upload_type'];
$this->uploadType = $upload_type;
}
public function validate(File $file, $allow_ext = null, $allow_size = null, $fail_exception = false)
{
$uploadConfig = sysconfig('upload');
if (!is_null($allow_ext)) {
$uploadConfig['upload_allow_ext'] = $allow_ext;
}
if (!is_null($allow_size)) {
$uploadConfig['upload_allow_size'] = $allow_size;
}
$rule = [
'upload_type|指定上传类型有误' => "in:{$uploadConfig['upload_allow_type']}",
'file|文件' => "require|file|fileExt:{$uploadConfig['upload_allow_ext']}|fileSize:{$uploadConfig['upload_allow_size']}",
];
$validat_result = Validate::failException($fail_exception)->check([
'upload_type' => $this->uploadType,
'file' => $file,
], $rule);
if (!$validat_result) {
return $validat_result;
}
// 出于性能原因,您可以注释掉下面的代码
$file_path = $file->getRealPath();
if (strpos(file_get_contents($file_path), '<?php') !== false) {
if ($fail_exception) {
throw new ValidateException('文件含有PHP注入代码');
} else {
return '文件含有PHP注入代码';
}
}
return true;
}
public function validateException($file, $allow_ext = null, $allow_size = null)
{
return $this->validate($file, $allow_ext, $allow_size, true);
}
public function url($save_name)
{
$url = Filesystem::disk($this->uploadType)->url($save_name);
return $url;
}
/**
* 存储文件.
*
* @param File $file
* @param string|null $save_name
* @param bool $force_save 指定$save_name才可以用,设为true强制写入不报错如果存在则删除否则是驱动的默认行为覆盖、失败、异常
* @param string $upload_dir
* @param bool $disable_model
* @return mixed
*/
public function save(File $file, string $save_name = null, $force_save = false, $upload_dir = 'upload', $disable_model = false)
{
$model_file = null;
if ($force_save && !is_null($save_name)) {
$file_path = $upload_dir . '/' . $save_name;
if (Filesystem::disk($this->uploadType)->has($file_path)) {
$model_file = SystemUploadfile::where('save_name', $save_name)->where('upload_type', $this->uploadType)->find();
Filesystem::disk($this->uploadType)->delete($file_path);
}
}
if (empty($model_file)) {
$model_file = new SystemUploadfile();
}
$model_file->upload_type = $this->uploadType;
$model_file->file_ext = strtolower($file->extension());
if ($file instanceof UploadedFile) {
$model_file->original_name = $file->getOriginalName();
$model_file->mime_type = $file->getOriginalMime();
} else {
$model_file->original_name = $file->getFilename();
$model_file->mime_type = $file->getMime();
}
$save_name = Filesystem::disk($this->uploadType)->putFile($upload_dir, $file, function () use ($save_name, $file) {
if (!is_null($save_name)) {
$ext_name = $file->extension();
if (empty($ext_name)) {
return $save_name;
}
$list_name = explode('.', $save_name);
array_pop($list_name);
return implode('.', $list_name);
}
return date('Ymd') . '/' . uniqid();
});
$url = $this->url($save_name);
$model_file->url = $url;
$model_file->save_name = $save_name;
$model_file->sha1 = $file->sha1();
$model_file->file_size = $file->getSize();
if (!$disable_model) {
$model_file->save();
}
return $model_file;
}
public function saveUrlFile($url, string $save_name = null, $force_save = false, $upload_dir = 'upload', $disable_model = false)
{
$runtime_path = App::getRuntimePath() . 'upload/temp/' . basename($url);
PathTools::intiDir($runtime_path);
$file_content = file_get_contents($url);
file_put_contents($runtime_path, $file_content);
$file = new File($runtime_path);
$response = $this->save($file, $save_name, $force_save, $upload_dir, $disable_model);
unlink($runtime_path);
return $response;
}
}