Commit 4ad0a7b3 authored by 朱招明's avatar 朱招明

权限相关接口

parent 116df568
...@@ -64,3 +64,5 @@ VITE_PUSHER_PORT="${PUSHER_PORT}" ...@@ -64,3 +64,5 @@ VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
L5_SWAGGER_GENERATE_ALWAYS = true
...@@ -17,3 +17,5 @@ yarn-error.log ...@@ -17,3 +17,5 @@ yarn-error.log
/.fleet /.fleet
/.idea /.idea
/.vscode /.vscode
/storage/api-docs/api-docs.json
/storage/api-docs/*.json
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/10/23
* @copyright
*/
namespace Modules\Admin\ApiDocs;
/**
*
* @OA\OpenApi(
* @OA\Info(
* version="1.0.0",
* title="OA系统接口",
* description="<b>通用状态码</b>:
* 200 成功
* 201 成功创建
* 204 执行成功,没有返回内容
*
* 401 没有登陆
* 403 没有权限
* 404 要操作的资源不存在
* 405 操作方法不允许
* 422 参数验证错误
* 500 程序出现错误
*",
* )
* )
*
*/
class Base
{
}
\ No newline at end of file
<?php <?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
...@@ -65,6 +66,24 @@ return new class extends Migration ...@@ -65,6 +66,24 @@ return new class extends Migration
$table->timestamps(); $table->timestamps();
}); });
DB::transaction(function (){
DB::table("admin_users")->insert([
"id" => "1",
"username" => "admin",
"name" => "admin",
"salt" => "4IpZw+?%MD1c",
"password" => password_hash(md5('1234564IpZw+?%MD1c'), PASSWORD_DEFAULT),
]);
DB::table("admin_roles")->insert([
"id" => "1",
"name" => "超级管理员",
"slug" => "超级管理员",
]);
DB::table("admin_role_users")->insert([
"role_id" => "1",
"user_id" => "1",
]);
});
} }
/** /**
......
...@@ -16,25 +16,5 @@ class AdminDatabaseSeeder extends Seeder ...@@ -16,25 +16,5 @@ class AdminDatabaseSeeder extends Seeder
public function run() public function run()
{ {
DB::transaction(function (){
DB::table("admin_users")->insert([
"id" => "1",
"username" => "admin",
"name" => "admin",
"salt" => "4IpZw+?%MD1c",
"password" => password_hash(md5('1234564IpZw+?%MD1c'), PASSWORD_DEFAULT),
]);
DB::table("admin_roles")->insert([
"id" => "1",
"name" => "超级管理员",
"slug" => "超级管理员",
]);
DB::table("admin_role_users")->insert([
"role_id" => "1",
"user_id" => "1",
]);
});
} }
} }
...@@ -10,10 +10,21 @@ namespace Modules\Admin\Entities; ...@@ -10,10 +10,21 @@ namespace Modules\Admin\Entities;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Modules\Admin\Http\Utils\Helper;
class AdminMenu extends Model class AdminMenu extends Model
{ {
protected $fillable = [ protected $fillable = [
'title','uri', 'parent_id', 'icon' 'title','uri', 'parent_id', 'icon'
]; ];
public static function boot()
{
parent::boot();
static::saving(function ($model) {
Helper::getAllMenu(true);
});
}
} }
\ No newline at end of file
...@@ -6,6 +6,7 @@ namespace Modules\Admin\Http\Controllers; ...@@ -6,6 +6,7 @@ namespace Modules\Admin\Http\Controllers;
use Exception; use Exception;
use Dingo\Api\Http\Request; use Dingo\Api\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Modules\Admin\Entities\AdminMenu; use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
...@@ -15,11 +16,41 @@ use Modules\Admin\Http\Utils\Helper; ...@@ -15,11 +16,41 @@ use Modules\Admin\Http\Utils\Helper;
class AuthController extends BaseController class AuthController extends BaseController
{ {
/** /**
* 登录授权 * @OA\Post(
* tags={"基础接口"},
* summary="登录",
* path="api/auth/login",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"username","password"},
* @OA\Property(
* property="username",
* type="string"
* ),
* @OA\Property(
* property="password",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="登陆成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
* *
* @param Request $request
*/ */
public function login(Request $request) public function login(Request $request)
{ {
...@@ -44,22 +75,47 @@ class AuthController extends BaseController ...@@ -44,22 +75,47 @@ class AuthController extends BaseController
} }
/** /**
* 刷新token *
* @desc * @OA\Put(
* @author [ZZM] * tags={"基础接口"},
* @since 2023/10/21 * summary="刷新token",
* @modify * path="api/auth/refresh",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="201",
* description="刷新成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
*
*/ */
public function refreshToken(){ public function refreshToken(){
return $this->response->item($this->user, new AccessTokenTransformer(true))->setStatusCode(201); return $this->response->item($this->user, new AccessTokenTransformer(true))->setStatusCode(201);
} }
/** /**
* 登出 *
* @desc * @OA\Put(
* @author [ZZM] * tags={"基础接口"},
* @since 2023/10/21 * summary="登出",
* @modify * path="api/auth/login_out",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="204",
* description="登出成功",
* )
* )
*
*/ */
public function loginOut(){ public function loginOut(){
auth('api')->logout(true); auth('api')->logout(true);
...@@ -67,31 +123,34 @@ class AuthController extends BaseController ...@@ -67,31 +123,34 @@ class AuthController extends BaseController
} }
/** /**
* 获取配置
* @desc
* *
* @param Request $request * @OA\Put(
* tags={"基础接口"},
* summary="获取配置",
* path="api/configs",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Menu")
* )
* )
* )
* )
* *
* @return \Dingo\Api\Http\Response
* @author [ZZM]
* @since 2023/10/21
* @modify
*/ */
public function apiConfig(Request $request) public function apiConfig(Request $request)
{ {
$user = $this->user; $user = $this->user;
#角色
$role = $user->roles()->first(); $role = $user->roles()->first();
if($role->id == 1){
#超级管理员默认获取全部菜单
$menu = AdminMenu::get();
}else{
#菜单
$menu = $role->menu;
}
$menu = $menu->toArray(); $menu = Helper::getRoleMenu($role,true);
$menu = Helper::makeTree($menu); $menu = Helper::makeTree($menu);
$data = [ $data = [
...@@ -100,4 +159,6 @@ class AuthController extends BaseController ...@@ -100,4 +159,6 @@ class AuthController extends BaseController
return $this->response->array(['data'=>$data]); return $this->response->array(['data'=>$data]);
} }
} }
...@@ -9,18 +9,83 @@ ...@@ -9,18 +9,83 @@
namespace Modules\Admin\Http\Controllers; namespace Modules\Admin\Http\Controllers;
use Dingo\Api\Http\Request; use Dingo\Api\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Admin\Entities\AdminMenu; use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminRoleMenu;
use Modules\Admin\Http\Requests\MenuRequest; use Modules\Admin\Http\Requests\MenuRequest;
use Modules\Admin\Http\Transformers\AdminMenuTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class MenuController extends BaseController class MenuController extends BaseController
{ {
/**
* @OA\Get(
* tags={"菜单"},
* summary="列表",
* path="api/menu/list",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/Menu"),
* description="列表"
* ),
* )
* )
* )
* )
*
*/
public function list(){ public function list(){
$menu = AdminMenu::all()->toArray(); $menu = AdminMenu::all();
$menu = Helper::makeTree($menu); return $this->response->collection($menu,new AdminMenuTransformer());
return $this->response->array(['data'=>$menu]);
} }
/**
* @OA\Post(
* tags={"菜单"},
* summary="添加",
* path="api/menu/add",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"title"},
* @OA\Property(
* property="title",
* type="string"
* ),
* @OA\Property(
* property="uri",
* type="string"
* ),
* @OA\Property(
* property="parent_id",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="",
* )
* )
*
*/
public function add(MenuRequest $request){ public function add(MenuRequest $request){
$params = $request->all(['title','uri','parent_id']); $params = $request->all(['title','uri','parent_id']);
...@@ -29,16 +94,117 @@ class MenuController extends BaseController ...@@ -29,16 +94,117 @@ class MenuController extends BaseController
return $this->response->noContent()->statusCode(201); return $this->response->noContent()->statusCode(201);
} }
public function detail(){ /**
* @OA\Get(
* tags={"菜单"},
* summary="详情",
* path="api/menu/{id}/detail",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Menu")
* )
* )
* )
* )
*
*/
public function detail($id){
$menu = AdminMenu::where('id',$id)->first();
if(!$menu){
abort(500,'菜单不存在');
}
return $this->response->item($menu,new AdminMenuTransformer());
} }
public function edit(){ /**
* @OA\Put(
* tags={"菜单"},
* summary="编辑",
* path="api/menu/{id}/edit",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"title"},
* @OA\Property(
* property="title",
* type="string"
* ),
* @OA\Property(
* property="uri",
* type="string"
* ),
* @OA\Property(
* property="parent_id",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function edit(MenuRequest $request,$id){
$params = $request->all(['title','uri','parent_id']);
$menu = AdminMenu::where('id',$id)->first();
if(!$menu){
abort(500,'菜单不存在');
}
if($params['uri'] && $menu->uri != $params['uri'] && AdminMenu::where('uri',$params['uri'])->first()){
abort(500,'uri重复');
}
$menu->update($params);
return $this->response->noContent()->statusCode(204);
} }
public function delete(){ /**
* @OA\Delete(
* tags={"菜单"},
* summary="删除",
* path="api/menu/{id}/delete",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function delete($id){
$menu = AdminMenu::where('id',$id)->first();
if($menu){
DB::transaction(function () use ($menu){
$menu->delete();
AdminRoleMenu::where('menu_id',$menu->id)->delete();
});
}
return $this->response->noContent()->statusCode(204);
} }
} }
\ No newline at end of file
...@@ -13,14 +13,76 @@ use Illuminate\Support\Facades\DB; ...@@ -13,14 +13,76 @@ use Illuminate\Support\Facades\DB;
use Modules\Admin\Entities\AdminMenu; use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminRole; use Modules\Admin\Entities\AdminRole;
use Modules\Admin\Entities\AdminRoleMenu; use Modules\Admin\Entities\AdminRoleMenu;
use Modules\Admin\Entities\AdminRoleUser;
use Modules\Admin\Http\Requests\RoleRequest; use Modules\Admin\Http\Requests\RoleRequest;
use Modules\Admin\Http\Transformers\AdminRoleTransformer;
class RoleController extends BaseController class RoleController extends BaseController
{ {
/**
* @OA\Get(
* tags={"角色"},
* summary="列表",
* path="api/role/list",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/Role"),
* description="列表"
* ),
* )
* )
* )
* )
*
*/
public function list(){ public function list(){
$roles = AdminRole::all();
return $this->response->collection($roles,new AdminRoleTransformer());
} }
/**
* @OA\Post(
* tags={"角色"},
* summary="添加",
* path="api/role/add",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"name","slug",},
* @OA\Property(
* property="name",
* type="string"
* ),
* @OA\Property(
* property="slug",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="",
* )
* )
*
*/
public function add(RoleRequest $request){ public function add(RoleRequest $request){
$params = $request->all(['name','slug']); $params = $request->all(['name','slug']);
...@@ -29,22 +91,79 @@ class RoleController extends BaseController ...@@ -29,22 +91,79 @@ class RoleController extends BaseController
return $this->response->noContent()->statusCode(201); return $this->response->noContent()->statusCode(201);
} }
public function detail(){ /**
* @OA\Get(
} * tags={"角色"},
* summary="详情",
public function edit(){ * path="api/role/{id}/detail",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Role")
* )
* )
* )
* )
*
*/
public function detail($role_id){
$role = AdminRole::where('id',$role_id)->first();
if(!$role){
abort(500,'角色不存在');
}
return $this->response->item($role,new AdminRoleTransformer(true));
} }
public function delete(){ /**
* @OA\Put(
* tags={"角色"},
* summary="编辑",
* path="api/role/{id}/edit",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"name","slug",},
* @OA\Property(
* property="name",
* type="string"
* ),
* @OA\Property(
* property="slug",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function edit(RoleRequest $request,$role_id){
$params = $request->all(['name','slug','menus']);
$role = AdminRole::where('id',$role_id)->first();
} if(!$role){
abort(500,'角色不存在');
}
public function setRoleMenu(Request $request,$role_id){
$params = $request->all(['menus']);
if(!is_array($params['menus'])){ if(!is_array($params['menus'])){
abort(422,'格式错误'); abort(422,'菜单格式错误');
} }
if($role_id == 1){ if($role_id == 1){
...@@ -56,7 +175,11 @@ class RoleController extends BaseController ...@@ -56,7 +175,11 @@ class RoleController extends BaseController
abort(500,$error); abort(500,$error);
} }
DB::transaction(function () use ($params,$role_id){ DB::transaction(function () use ($role,$params,$role_id){
$role->name = $params['name'];
$role->slug = $params['slug'];
$role->save();
AdminRoleMenu::where('role_id',$role_id)->delete(); AdminRoleMenu::where('role_id',$role_id)->delete();
$insert = []; $insert = [];
...@@ -70,6 +193,38 @@ class RoleController extends BaseController ...@@ -70,6 +193,38 @@ class RoleController extends BaseController
AdminRoleMenu::insert($insert); AdminRoleMenu::insert($insert);
} }
}); });
return $this->response->noContent()->statusCode(204);
}
/**
* @OA\Delete(
* tags={"角色"},
* summary="删除",
* path="api/role/{id}/delete",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function delete($role_id){
$role = AdminRole::where('id',$role_id)->first();
if($role){
if(AdminRoleUser::where('role_id',$role->id)->count() > 0){
abort("此角色还有关联的用户,无法删除");
}
DB::transaction(function () use ($role){
$role->delete();
AdminRoleMenu::where('role_id',$role->id)->delete();
});
}
return $this->response->noContent()->statusCode(204); return $this->response->noContent()->statusCode(204);
} }
......
...@@ -18,11 +18,88 @@ use Modules\Admin\Http\Utils\Helper; ...@@ -18,11 +18,88 @@ use Modules\Admin\Http\Utils\Helper;
class UserController extends BaseController class UserController extends BaseController
{ {
/**
* @OA\Get(
* tags={"用户"},
* summary="列表",
* path="api/user/list",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/User"),
* description="列表"
* ),
* )
* )
* )
* )
*
*/
public function list(){ public function list(){
$list = AdminUser::all(); $list = AdminUser::all();
return $this->response->collection($list,new AdminUserTransformer()); return $this->response->collection($list,new AdminUserTransformer());
} }
/**
* @OA\Post(
* tags={"用户"},
* summary="添加",
* path="api/user/add",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"username","password","name","avatar","role_id",},
* @OA\Property(
* property="username",
* type="string",
* description="用户名",
* ),
* @OA\Property(
* property="password",
* type="string",
* description="密码",
* ),
* @OA\Property(
* property="name",
* type="string",
* description="名称",
* ),
* @OA\Property(
* property="avatar",
* type="string",
* description="头像",
* ),
* @OA\Property(
* property="role_id",
* type="string",
* description="角色ID",
* ),
*
* )
* )
* ),
* @OA\Response(
* response="201",
* description="",
* )
* )
*
*/
public function add(UserRequest $request){ public function add(UserRequest $request){
$params = $request->all(['username','password','name','avatar','role_id']); $params = $request->all(['username','password','name','avatar','role_id']);
...@@ -34,7 +111,6 @@ class UserController extends BaseController ...@@ -34,7 +111,6 @@ class UserController extends BaseController
$params['salt'] = Helper::generateRandomString(); $params['salt'] = Helper::generateRandomString();
$params['password'] = password_hash(md5($params['password'].$params['salt']), PASSWORD_DEFAULT); $params['password'] = password_hash(md5($params['password'].$params['salt']), PASSWORD_DEFAULT);
$user = DB::transaction(function () use ($params){ $user = DB::transaction(function () use ($params){
$role_id = $params['role_id']; $role_id = $params['role_id'];
unset($params['role_id']); unset($params['role_id']);
...@@ -49,15 +125,146 @@ class UserController extends BaseController ...@@ -49,15 +125,146 @@ class UserController extends BaseController
return $this->response->item($user,new AdminUserTransformer()); return $this->response->item($user,new AdminUserTransformer());
} }
public function detail(){ /**
* @OA\Get(
* tags={"用户"},
* summary="详情",
* path="api/user/{id}/detail",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/User")
* )
* )
* )
* )
*
*/
public function detail($id){
$user = AdminUser::where('id',$id)->first();
if(!$user){
abort(500,'用户不存在');
}
return $this->response->item($user,new AdminUserTransformer());
} }
public function edit(){ /**
* @OA\Put(
* tags={"用户"},
* summary="编辑",
* path="api/user/{id}/edit",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"username","password","name","avatar","role_id",},
* @OA\Property(
* property="username",
* type="string",
* description="用户名",
* ),
* @OA\Property(
* property="password",
* type="string",
* description="密码",
* ),
* @OA\Property(
* property="name",
* type="string",
* description="名称",
* ),
* @OA\Property(
* property="avatar",
* type="string",
* description="头像",
* ),
* @OA\Property(
* property="role_id",
* type="string",
* description="角色ID",
* ),
*
* )
* )
* ),
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function edit(UserRequest $request,$id){
$params = $request->all(['username','password','name','avatar','role_id']);
$user = AdminUser::where('id',$id)->first();
if(!$user){
abort(500,'用户不存在');
}
if($user->username != $params['username'] && AdminUser::where('username',$params['username'])->first()){
abort(500,'用户名重复');
}
if(!empty($params['password'])){
$params['password'] = password_hash(md5($params['password'].$user->salt), PASSWORD_DEFAULT);
}else{
unset($params['password']);
}
DB::transaction(function () use ($user,$params){
$role_id = $params['role_id'];
unset($params['role_id']);
$user->update($params);
if($role_id && !AdminRoleUser::where(['user_id'=>$user->id,'role_id'=>$role_id])->first()){
AdminRoleUser::where('user_id',$user->id)->delete();
AdminRoleUser::create(['role_id'=>$role_id,'user_id'=>$user->id]);
}
});
return $this->response->noContent()->statusCode(204);
} }
public function delete(){ /**
* @OA\Delete(
* tags={"用户"},
* summary="删除",
* path="api/user/{id}/delete",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="204",
* description="",
* )
* )
*
*/
public function delete($id){
$user = AdminUser::where('id',$id)->first();
if($user){
DB::transaction(function () use ($user){
$user->delete();
AdminRoleUser::where('user_id',$user->id)->delete();
});
}
return $this->response->noContent()->statusCode(204);
} }
} }
\ No newline at end of file
<?php
namespace Modules\Admin\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Dingo\Api\Facade\Route;
use Modules\Admin\Http\Utils\Helper;
class RoleMenu
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$user = auth()->user();
#角色
$role = $user->roles()->first();
$menus = Helper::getRoleMenu($role);
$role_uris = array_filter(array_column($menus,'uri'));
$uris = array_filter(array_column(Helper::getAllMenu(),'uri'));
$route = str_replace(".", "/", Route::currentRouteName());
#验证菜单权限
if(
!Helper::isAdministrator($role->id)
&& in_array($route,$uris)
&& !in_array($route,$role_uris)
){
abort(403,'没有权限');
}
return $next($request);
}
}
...@@ -11,8 +11,37 @@ class MenuRequest extends BaseRequest ...@@ -11,8 +11,37 @@ class MenuRequest extends BaseRequest
*/ */
public function postRules() public function postRules()
{ {
if(empty($this->parent_id)){
$this['parent_id'] = 0;
$parent_id_rule = [];
}else{
$parent_id_rule = ['exists:admin_menus,id'];
}
if(empty($this->uri)){
$uri_rule = [];
}else{
$uri_rule = ['unique:admin_menus,uri'];
}
return [
'parent_id' => $parent_id_rule,
'title' => 'bail|required',
'uri' => $uri_rule,
];
}
public function putRules()
{
if(empty($this->parent_id)){
$this->parent_id = 0;
$parent_id_rule = ['integer'];
}else{
$parent_id_rule = ['integer','exists:admin_menus,id'];
}
return [ return [
'parent_id' => 'integer|exists:admin_menus', 'parent_id' => $parent_id_rule,
'title' => 'bail|required', 'title' => 'bail|required',
]; ];
} }
...@@ -22,6 +51,7 @@ class MenuRequest extends BaseRequest ...@@ -22,6 +51,7 @@ class MenuRequest extends BaseRequest
return [ return [
'title.required' => '菜单名称必须', 'title.required' => '菜单名称必须',
'parent_id.exists' => '父菜单不存在', 'parent_id.exists' => '父菜单不存在',
'uri.unique' => 'uri重复',
]; ];
} }
} }
...@@ -4,11 +4,6 @@ namespace Modules\Admin\Http\Requests; ...@@ -4,11 +4,6 @@ namespace Modules\Admin\Http\Requests;
class RoleRequest extends BaseRequest class RoleRequest extends BaseRequest
{ {
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function postRules() public function postRules()
{ {
return [ return [
...@@ -17,6 +12,14 @@ class RoleRequest extends BaseRequest ...@@ -17,6 +12,14 @@ class RoleRequest extends BaseRequest
]; ];
} }
public function putRules()
{
return [
'name' => 'bail|required',
'slug' => 'bail|required',
];
}
public function messages() public function messages()
{ {
return [ return [
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
namespace Modules\Admin\Http\Requests; namespace Modules\Admin\Http\Requests;
use Illuminate\Validation\Rule;
use Modules\Admin\Entities\AdminUser;
class UserRequest extends BaseRequest class UserRequest extends BaseRequest
{ {
/** /**
...@@ -18,6 +21,15 @@ class UserRequest extends BaseRequest ...@@ -18,6 +21,15 @@ class UserRequest extends BaseRequest
]; ];
} }
public function putRules()
{
return [
'username' => ['bail','required'],
'name' => 'bail|required',
'role_id' => 'bail|required|exists:admin_roles,id',
];
}
public function messages() public function messages()
{ {
return [ return [
......
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 11:12
*/
namespace Modules\Admin\Http\Transformers;
use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminRole;
use Modules\Admin\Entities\AdminUser;
use Modules\Admin\Http\Utils\Helper;
class AdminMenuTransformer extends BaseTransformer
{
use Macroable;
public function __construct()
{
parent::__construct();
}
/**
* @OA\Schema(
* description="菜单信息",
* type="object",
* schema="Menu",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="parent_id", type="string", description="上级ID"),
* @OA\Property(property="title", type="string", description="标题"),
* @OA\Property(property="uri", type="string", description="uri"),
* @OA\Property(property="created_at", type="string", description="创建时间"),
* )
*/
public function transform(AdminMenu $menu)
{
$return = ['id','parent_id','title','uri','created_at'];
return Helper::mapAttr($menu,$return);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 11:12
*/
namespace Modules\Admin\Http\Transformers;
use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminRole;
use Modules\Admin\Entities\AdminUser;
use Modules\Admin\Http\Utils\Helper;
class AdminRoleTransformer extends BaseTransformer
{
use Macroable;
protected $show_menu;
public function __construct($show_menu = false)
{
$this->show_menu = $show_menu;
parent::__construct();
}
/**
* @OA\Schema(
* description="角色信息",
* type="object",
* schema="Role",
* @OA\Property(property="name", type="integer", description="名称"),
* @OA\Property(property="slug", type="string", description="描述"),
* @OA\Property(property="created_at", type="string", description="创建时间"),
* )
*/
public function transform(AdminRole $role)
{
$return = ['name','slug','created_at'];
$return = Helper::mapAttr($role,$return);
if($this->show_menu){
$return['menu_ids'] = array_column($role->menu->toArray(),'id');
}
return $return;
}
}
...@@ -29,16 +29,16 @@ class AdminUserTransformer extends BaseTransformer ...@@ -29,16 +29,16 @@ class AdminUserTransformer extends BaseTransformer
* type="object", * type="object",
* schema="User", * schema="User",
* @OA\Property(property="id", type="integer", description="用户ID"), * @OA\Property(property="id", type="integer", description="用户ID"),
* @OA\Property(property="name", type="string", description="用户名"), * @OA\Property(property="username", type="string", description="用户名"),
* @OA\Property(property="email", type="string", description="邮箱"), * @OA\Property(property="avatar", type="string", description="头像"),
* @OA\Property(property="phone", type="string", description="手机号"), * @OA\Property(property="name", type="string", description="名称"),
* @OA\Property(property="created_at", type="string", description="注册时间"), * @OA\Property(property="created_at", type="string", description="注册时间"),
* @OA\Property(property="updated_at", type="string", description="更新时间") * @OA\Property(property="updated_at", type="string", description="更新时间")
* ) * )
*/ */
public function transform(AdminUser $user) public function transform(AdminUser $user)
{ {
$return = ['id', 'username', 'avatar', 'name', 'sex', 'created_at', 'updated_at']; $return = ['id', 'username', 'avatar', 'name', 'created_at', 'updated_at'];
return Helper::mapAttr($user,$return); return Helper::mapAttr($user,$return);
} }
......
...@@ -4,8 +4,76 @@ declare(strict_types=1); ...@@ -4,8 +4,76 @@ declare(strict_types=1);
namespace Modules\Admin\Http\Utils; namespace Modules\Admin\Http\Utils;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Modules\Admin\Entities\AdminMenu;
class Helper { class Helper {
/**
* 获取全部菜单
* @desc
* @return mixed|mixed[]
* @since 2023/10/23
* @modify
* @author [ZZM]
*/
static function getAllMenu($refresh = false){
if(!$refresh && $menu = Cache::get("ALL_MENU")){
return json_decode($menu,true);
}
$menu = AdminMenu::all()->toArray();
if($menu){
Cache::put("ALL_MENU",json_encode($menu));
}
return $menu;
}
/**
* 获取角色菜单
* @desc
*
* @param $role
*
* @return mixed|mixed[]
* @author [ZZM]
* @since 2023/10/23
* @modify
*/
static function getRoleMenu($role,$refresh = false){
if(Helper::isAdministrator($role->id)){
#超级管理员默认获取全部菜单
return self::getAllMenu();
}
if(!$refresh && $menu = Cache::get("ROLE_MENU_{$role->id}")){
return json_decode($menu,true);
}
$menu = $role->menu;
$menu = $menu->toArray();
if($menu){
Cache::put("ROLE_MENU_{$role->id}",json_encode($menu));
}
return $menu;
}
/**
* 是否超级管理员
* @desc
*
* @param $role_id
*
* @return bool
* @author [ZZM]
* @since 2023/10/23
* @modify
*/
static function isAdministrator($role_id){
return $role_id == 1;
}
static function makeTree(array $elements, $parentId = 0) { static function makeTree(array $elements, $parentId = 0) {
$branch = []; $branch = [];
......
...@@ -8,14 +8,14 @@ use Illuminate\Support\Facades\Route; ...@@ -8,14 +8,14 @@ use Illuminate\Support\Facades\Route;
class RouteRegister { class RouteRegister {
public static function registerApi($api,$route, $controller) { public static function registerApi($api,$route, $controller) {
#列表 #列表
$api->get("{$route}/list", "{$controller}@list"); $api->get("{$route}/list", "{$controller}@list")->name("{$route}.list");
#添加 #添加
$api->post("{$route}/add", "{$controller}@add"); $api->post("{$route}/add", "{$controller}@add")->name("{$route}.add");
#详情 #详情
$api->get("{$route}/{id}/show", "{$controller}@detail"); $api->get("{$route}/{id}/detail", "{$controller}@detail")->name("{$route}.detail");
#编辑 #编辑
$api->put("{$route}/{id}/edit", "{$controller}@edit"); $api->put("{$route}/{id}/edit", "{$controller}@edit")->name("{$route}.edit");
#删除 #删除
$api->delete("{$route}/{id}/delete", "{$controller}@delete"); $api->delete("{$route}/{id}/delete", "{$controller}@delete")->name("{$route}.delete");
} }
} }
...@@ -23,23 +23,24 @@ $api->version('v1', [ ...@@ -23,23 +23,24 @@ $api->version('v1', [
$api->post('auth/login', 'AuthController@login'); $api->post('auth/login', 'AuthController@login');
$api->group(['middleware' => 'api.auth'], function ($api) { $api->group(['middleware' => 'api.auth'], function ($api) {
#刷新token #刷新token
$api->get('auth/refresh', 'AuthController@refreshToken'); $api->put('auth/refresh', 'AuthController@refreshToken');
#登出 #登出
$api->put('auth/login_out', 'AuthController@loginOut'); $api->put('auth/login_out', 'AuthController@loginOut');
#配置 #配置
$api->get('configs', 'AuthController@apiConfig'); $api->get('configs', 'AuthController@apiConfig');
#菜单 $api->group(['middleware' => 'role_menu'], function ($api){
\Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'menu','MenuController'); #菜单
\Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'menu','MenuController');
#用户 #用户
\Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'user','UserController'); \Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'user','UserController');
#角色
\Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'role','RoleController');
#角色权限
$api->put('role/{id}/set_menu', 'RoleController@setRoleMenu');
#角色
\Modules\Admin\Http\Utils\RouteRegister::registerApi($api,'role','RoleController');
#角色权限
$api->put('role/{id}/set_menu', 'RoleController@setRoleMenu')->name("role.set_menu");;
});
}); });
}); });
<?php
namespace App\Admin\Controllers;
use Encore\Admin\Controllers\AuthController as BaseAuthController;
class AuthController extends BaseAuthController
{
}
<?php
namespace App\Admin\Controllers;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class ExampleController extends AdminController
{
/**
* Title for current resource.
*
* @var string
*/
protected $title = 'Example controller';
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new ExampleModel);
$grid->column('id', __('ID'))->sortable();
$grid->column('created_at', __('Created at'));
$grid->column('updated_at', __('Updated at'));
return $grid;
}
/**
* Make a show builder.
*
* @param mixed $id
* @return Show
*/
protected function detail($id)
{
$show = new Show(ExampleModel::findOrFail($id));
$show->field('id', __('ID'));
$show->field('created_at', __('Created at'));
$show->field('updated_at', __('Updated at'));
return $show;
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$form = new Form(new ExampleModel);
$form->display('id', __('ID'));
$form->display('created_at', __('Created At'));
$form->display('updated_at', __('Updated At'));
return $form;
}
}
<?php
namespace App\Admin\Controllers;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\Dashboard;
use Encore\Admin\Layout\Column;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
class HomeController extends Controller
{
public function index(Content $content)
{
return $content
->title('Dashboard')
->description('Description...')
->row(Dashboard::title())
->row(function (Row $row) {
$row->column(4, function (Column $column) {
$column->append(Dashboard::environment());
});
$row->column(4, function (Column $column) {
$column->append(Dashboard::extensions());
});
$row->column(4, function (Column $column) {
$column->append(Dashboard::dependencies());
});
});
}
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace App\Http; namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Modules\Admin\Http\Middleware\RoleMenu;
class Kernel extends HttpKernel class Kernel extends HttpKernel
{ {
...@@ -64,5 +65,6 @@ class Kernel extends HttpKernel ...@@ -64,5 +65,6 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class, 'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'role_menu' => RoleMenu::class,
]; ];
} }
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
<?php
/**
* @OA\Info(title="My First API", version="0.1")
*/
/**
* @OA\SecurityScheme(
* securityScheme="jwt_auth",
* type="http",
* scheme="bearer",
* bearerFormat="JWT",
* )
*
* @OA\Get(
* tags={"基础接口"},
* summary="获取验证码",
* path="/api/captcha",
* @OA\Response(
* response="200",
* description="验证码信息",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Verify")
* )
* )
* )
* )
*
*
* @OA\Get(
* tags={"基础接口"},
* summary="缩略图",
* path="/imagecache/{template}/{image_path}",
* @OA\Parameter(
* name="template",
* in="path",
* description="图片处理模板,默认有 small,medium,large三种",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="image_path",
* in="path",
* description="储存的文件名,程序保存时的路径",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response="200",
* description="处理后的图片",
* @OA\MediaType(
* mediaType="image/png",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/jpg",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/jpeg",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/gif",
* @OA\Schema(
* type="string",
* format="binary",
* )
* )
* )
* )
*
* @OA\Schema(
* description="请求验证错误422",
* type="object",
* schema="error422",
* @OA\Property(property="message", type="string", description="422 Unprocessable Entity"),
* @OA\Property(property="error", type="object", description="错误",
* @OA\Property(property="key", type="array", description="请求键值",
* @OA\Items(type="string", description="具体错误"),
* ),
* ),
* @OA\Property(property="status_code", type="integer", description="状态码422", example=422),
* @OA\Property(property="debug", type="object", description="错误调试信息")
* )
*
*
*
* @OA\Schema(
* description="验证码信息",
* type="object",
* schema="Verify",
* @OA\Property(property="sensitive", type="boolean", description="验证码是否大小写敏感"),
* @OA\Property(property="key", type="string", description="验证码KEY"),
* @OA\Property(property="img", type="string", description="验证码图片(base64图片编码)")
* )
*
* @OA\Schema(
* description="手机号",
* type="string",
* schema="phone",
* minLength=11
* )
*
* @OA\Schema(
* description="密码",
* type="string",
* schema="password",
* minLength=6
* )
*
* @OA\Schema(
* description="手机短信验证码",
* type="string",
* schema="phone_code",
* minLength=4
* )
*
* @OA\Schema(
* description="邮箱",
* type="string",
* schema="email"
* )
*
* @OA\Schema(
* description="1为是,0为否",
* type="integer",
* enum={0,1},
* schema="yesno"
* )
*
* @OA\Schema(
* description="验证码KEY",
* type="string",
* schema="captcha_key"
* )
*
* @OA\Schema(
* description="验证码",
* type="string",
* schema="captcha_code"
* )
*
*/
\ No newline at end of file
...@@ -6,14 +6,16 @@ ...@@ -6,14 +6,16 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"api-ecosystem-for-laravel/dingo-api": "^4.1", "api-ecosystem-for-laravel/dingo-api": "4.1.*",
"darkaonline/l5-swagger": "^8.5",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "10.*", "laravel/framework": "10.*",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",
"namshi/jose": "^7.2", "namshi/jose": "^7.2",
"nesbot/carbon": "^2.71", "nesbot/carbon": "^2.71",
"nwidart/laravel-modules": "^10.0", "nwidart/laravel-modules": "^10.0",
"php-open-source-saver/jwt-auth": "^2.1" "php-open-source-saver/jwt-auth": "^2.1",
"zircote/swagger-php": "^4.7"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",
......
This diff is collapsed.
...@@ -70,7 +70,7 @@ return [ ...@@ -70,7 +70,7 @@ return [
| |
*/ */
'timezone' => 'UTC', 'timezone' => 'Asia/Shanghai',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
......
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{config('l5-swagger.documentations.'.$documentation.'.api.title')}}</title>
<link rel="stylesheet" type="text/css" href="{{ l5_swagger_asset($documentation, 'swagger-ui.css') }}">
<link rel="icon" type="image/png" href="{{ l5_swagger_asset($documentation, 'favicon-32x32.png') }}" sizes="32x32"/>
<link rel="icon" type="image/png" href="{{ l5_swagger_asset($documentation, 'favicon-16x16.png') }}" sizes="16x16"/>
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body {
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="{{ l5_swagger_asset($documentation, 'swagger-ui-bundle.js') }}"></script>
<script src="{{ l5_swagger_asset($documentation, 'swagger-ui-standalone-preset.js') }}"></script>
<script>
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
dom_id: '#swagger-ui',
url: "{!! $urlToDocs !!}",
operationsSorter: {!! isset($operationsSorter) ? '"' . $operationsSorter . '"' : 'null' !!},
configUrl: {!! isset($configUrl) ? '"' . $configUrl . '"' : 'null' !!},
validatorUrl: {!! isset($validatorUrl) ? '"' . $validatorUrl . '"' : 'null' !!},
oauth2RedirectUrl: "{{ route('l5-swagger.'.$documentation.'.oauth2_callback', [], $useAbsolutePath) }}",
requestInterceptor: function(request) {
request.headers['X-CSRF-TOKEN'] = '{{ csrf_token() }}';
return request;
},
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
docExpansion : "{!! config('l5-swagger.defaults.ui.display.doc_expansion', 'none') !!}",
deepLinking: true,
filter: {!! config('l5-swagger.defaults.ui.display.filter') ? 'true' : 'false' !!},
persistAuthorization: "{!! config('l5-swagger.defaults.ui.authorization.persist_authorization') ? 'true' : 'false' !!}",
})
window.ui = ui
@if(in_array('oauth2', array_column(config('l5-swagger.defaults.securityDefinitions.securitySchemes'), 'type')))
ui.initOAuth({
usePkceWithAuthorizationCodeGrant: "{!! (bool)config('l5-swagger.defaults.ui.authorization.oauth2.use_pkce_with_authorization_code_grant') !!}"
})
@endif
}
</script>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment