feat: Implement admin role and permission management, employee management APIs, and user profile extensions.

This commit is contained in:
pbao9
2026-03-10 11:43:19 +07:00
parent a70900f542
commit cf0f2cf686
14 changed files with 924 additions and 187 deletions
@@ -0,0 +1,170 @@
<?php
namespace App\Http\Controllers\Api\Admin\Employee;
use App\Http\Controllers\Controller;
use App\Http\Requests\EmployeeRequest;
use App\Repositories\Employee\EmployeeRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Role;
class EmployeeController extends Controller
{
public function __construct(
private readonly EmployeeRepositoryInterface $employeeRepository
) {}
public function index(Request $request): JsonResponse
{
$employees = $this->employeeRepository->filter($request->all());
return response()->json([
'error' => false,
'data' => $employees,
]);
}
public function store(EmployeeRequest $request): JsonResponse
{
$request->validated();
try {
DB::beginTransaction();
$employee = $this->employeeRepository->create([
'firstname' => $request->firstname,
'lastname' => $request->lastname,
'username' => $request->username,
'email' => $request->email,
'phone' => $request->phone,
'birthday' => $request->birthday,
'address' => $request->address,
'password' => Hash::make($request->password),
]);
$employee->syncRoles([$request->role]);
DB::commit();
return response()->json([
'error' => false,
'message' => 'Employee created successfully',
'data' => $employee->load('roles'),
], 201);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'error' => true,
'message' => $e->getMessage(),
], 500);
}
}
public function show(int $id): JsonResponse
{
$employee = $this->employeeRepository->find($id);
if (!$employee) {
return response()->json([
'error' => true,
'message' => "Can't find employee by ID #" . $id,
], 404);
}
return response()->json([
'error' => false,
'data' => $employee->load('roles'),
]);
}
public function update(int $id, EmployeeRequest $request): JsonResponse
{
$employee = $this->employeeRepository->find($id);
if (!$employee) {
return response()->json([
'error' => true,
'message' => "Can't find employee by ID #" . $id,
], 404);
}
$request->validated();
try {
DB::beginTransaction();
$data = [
'firstname' => $request->firstname,
'lastname' => $request->lastname,
'username' => $request->username,
'email' => $request->email,
'phone' => $request->phone,
'birthday' => $request->birthday,
'address' => $request->address,
];
if ($request->filled('password')) {
$data['password'] = Hash::make($request->password);
}
$this->employeeRepository->update($id, $data);
$employee->syncRoles([$request->role]);
DB::commit();
return response()->json([
'error' => false,
'message' => 'Employee updated successfully',
'data' => $this->employeeRepository->find($id)->load('roles'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'error' => true,
'message' => $e->getMessage(),
], 500);
}
}
public function destroy(int $id): JsonResponse
{
$employee = $this->employeeRepository->find($id);
if (!$employee) {
return response()->json([
'error' => true,
'message' => "Can't find employee by ID #" . $id,
], 404);
}
try {
DB::beginTransaction();
$this->employeeRepository->delete($id);
DB::commit();
return response()->json([
'error' => false,
'message' => 'Employee deleted successfully',
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'error' => true,
'message' => $e->getMessage(),
], 500);
}
}
public function roles(): JsonResponse
{
$roles = Role::where('guard_name', 'admin')->get(['id', 'name']);
return response()->json([
'error' => false,
'data' => $roles,
]);
}
}
@@ -0,0 +1,266 @@
<?php
namespace App\Http\Controllers\Api\Admin\Role;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RolePermissionController extends Controller
{
private function ensureFullAdmin(): bool
{
$user = auth('admin')->user();
return $user && $user->hasRole('Full Administrator');
}
/**
* GET /v1/administrator/role-permissions
* Danh sách tất cả roles (trừ Full Administrator) kèm permissions hiện tại
*/
public function index(): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$roles = Role::where('guard_name', 'admin')
->where('name', '!=', 'Full Administrator')
->with('permissions')
->get()
->map(fn ($role) => [
'id' => $role->id,
'name' => $role->name,
'permissions' => $role->permissions->pluck('name')->values(),
]);
return response()->json([
'error' => false,
'data' => $roles,
]);
}
/**
* GET /v1/administrator/role-permissions/all-permissions
* Tất cả permissions nhóm theo module
*/
public function allPermissions(): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$grouped = Permission::where('guard_name', 'admin')
->orderBy('id')
->get(['id', 'name'])
->groupBy(function ($p) {
// Format: module.action (e.g., product-service.view, customer.manager)
$parts = explode('.', $p->name);
return $parts[0] ?? $p->name;
})
->map(function ($group, $module) {
return [
'module' => $module,
'permissions' => $group->map(fn ($p) => [
'id' => $p->id,
'name' => $p->name,
'action' => explode('.', $p->name)[1] ?? $p->name,
])->values(),
];
})
->values();
return response()->json([
'error' => false,
'data' => $grouped,
]);
}
/**
* GET /v1/administrator/role-permissions/mine
* Trả về permissions hiệu lực của user đang đăng nhập (qua role của họ).
* Accessible bởi mọi admin đã xác thực — không yêu cầu Full Administrator.
*/
public function mine(): JsonResponse
{
$user = auth('admin')->user();
if (!$user) {
return response()->json(['error' => true, 'message' => 'Unauthorized'], 401);
}
$isFullAdmin = $user->hasRole('Full Administrator', 'admin');
return response()->json([
'error' => false,
'data' => [
'isFullAdmin' => $isFullAdmin,
'permissions' => $isFullAdmin
? ['*']
: $user->getAllPermissions()->pluck('name')->toArray(),
],
]);
}
/**
* POST /v1/administrator/role-permissions/permissions
* Tạo một nhóm permissions mới theo module (chỉ Full Administrator)
*/
public function createPermissionGroup(Request $request): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$module = trim($request->input('module', ''));
$actions = $request->input('actions', ['view', 'create', 'edit', 'destroy', 'manager']);
if (!$module) {
return response()->json(['error' => true, 'message' => 'Tên module không được trống'], 422);
}
// Kiểm tra module đã tồn tại chưa
$existing = Permission::where('guard_name', 'admin')
->where('name', 'like', $module . '.%')
->exists();
if ($existing) {
return response()->json(['error' => true, 'message' => "Module \"{$module}\" đã tồn tại"], 422);
}
$created = [];
foreach ($actions as $action) {
$name = $module . '.' . $action;
$perm = Permission::firstOrCreate([
'name' => $name,
'guard_name' => 'admin',
]);
$created[] = [
'id' => $perm->id,
'name' => $perm->name,
'action' => $action,
];
}
// Full Administrator tự động được cấp permissions mới
$fullAdmin = Role::where('name', 'Full Administrator')
->where('guard_name', 'admin')
->first();
if ($fullAdmin) {
$fullAdmin->givePermissionTo(array_column($created, 'name'));
}
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
return response()->json([
'error' => false,
'data' => [
'module' => $module,
'permissions' => $created,
],
], 201);
}
/**
* DELETE /v1/administrator/role-permissions/permissions/group/{module}
* Xóa toàn bộ permissions của một module (chỉ Full Administrator)
*/
public function deletePermissionGroup(string $module): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$deleted = Permission::where('guard_name', 'admin')
->where('name', 'like', $module . '.%')
->get();
if ($deleted->isEmpty()) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy nhóm quyền'], 404);
}
foreach ($deleted as $perm) {
$perm->delete();
}
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
return response()->json([
'error' => false,
'message' => "Đã xóa nhóm quyền \"{$module}\"",
'data' => ['module' => $module, 'deleted' => $deleted->count()],
]);
}
/**
* PATCH /v1/administrator/role-permissions/permissions/{id}
* Đổi tên một permission (chỉ Full Administrator)
*/
public function renamePermission(int $id, Request $request): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$permission = Permission::where('guard_name', 'admin')->find($id);
if (!$permission) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy permission'], 404);
}
$newName = trim($request->input('name', ''));
if (!$newName) {
return response()->json(['error' => true, 'message' => 'Tên permission không được trống'], 422);
}
if (Permission::where('guard_name', 'admin')->where('name', $newName)->where('id', '!=', $id)->exists()) {
return response()->json(['error' => true, 'message' => 'Tên permission đã tồn tại'], 422);
}
$permission->update(['name' => $newName]);
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
return response()->json([
'error' => false,
'data' => ['id' => $permission->id, 'name' => $permission->name],
]);
}
/**
* PUT /v1/administrator/role-permissions/{roleId}
* Sync permissions cho một role
*/
public function update(int $roleId, Request $request): JsonResponse
{
if (!$this->ensureFullAdmin()) {
return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập'], 403);
}
$role = Role::where('guard_name', 'admin')
->where('name', '!=', 'Full Administrator')
->find($roleId);
if (!$role) {
return response()->json([
'error' => true,
'message' => 'Không tìm thấy vai trò',
], 404);
}
$permissions = $request->input('permissions', []);
$role->syncPermissions($permissions);
// Xóa cache để /mine endpoint trả về permissions mới nhất
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
return response()->json([
'error' => false,
'message' => "Đã cập nhật quyền cho vai trò \"{$role->name}\"",
'data' => [
'id' => $role->id,
'name' => $role->name,
'permissions' => $role->permissions()->pluck('name')->values(),
],
]);
}
}
+1
View File
@@ -70,5 +70,6 @@ class Kernel extends HttpKernel
'Staff' => \App\Http\Middleware\StaffCheck::class,
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
'api.auth' => \App\Http\Middleware\ApiAuthCheck::class,
'perm' => \App\Http\Middleware\CheckPermission::class,
];
}
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckPermission
{
public function handle(Request $request, Closure $next, string $permission): mixed
{
$user = auth('admin')->user();
if (!$user) {
return response()->json([
'error' => true,
'message' => 'Vui lòng đăng nhập để thực hiện!',
], 401);
}
// Full Administrator luôn có tất cả quyền
if ($user->hasRole('Full Administrator')) {
return $next($request);
}
if (!$user->hasPermissionTo($permission)) {
return response()->json([
'error' => true,
'message' => "Bạn không có quyền: \"{$permission}\".",
], 403);
}
return $next($request);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class EmployeeRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$employeeId = $this->route('id');
$rules = [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'username' => ['required', 'string', 'max:255', Rule::unique('user', 'username')->ignore($employeeId)],
'email' => ['required', 'email', 'max:255', Rule::unique('user', 'email')->ignore($employeeId)],
'role' => ['required', Rule::in(['Administrator', 'Sale', 'IT', 'Customer Service', 'Marketing'])],
'phone' => 'nullable|string|max:20',
'birthday' => 'nullable|date',
'address' => 'nullable|string|max:500',
];
if ($this->isMethod('POST')) {
$rules['password'] = 'required|string|min:8|confirmed';
} else {
$rules['password'] = 'nullable|string|min:8|confirmed';
}
return $rules;
}
}
+6 -1
View File
@@ -14,6 +14,8 @@ class User extends Authenticatable implements JWTSubject
use HasRoles;
protected $table = 'user';
protected $guard_name = 'admin';
/**
* The attributes that are mass assignable.
*
@@ -25,7 +27,10 @@ class User extends Authenticatable implements JWTSubject
'lastname',
'username',
'email',
'email_verified_at'
'email_verified_at',
'birthday',
'address',
'phone',
];
/**
+4
View File
@@ -53,6 +53,10 @@ class AppServiceProvider extends ServiceProvider
\App\Repositories\Admin\Product\AdminProductRepositoryInterface::class,
\App\Repositories\Admin\Product\AdminProductRepository::class
);
$this->app->bind(
\App\Repositories\Employee\EmployeeRepositoryInterface::class,
\App\Repositories\Employee\EmployeeRepository::class
);
if (File::exists(base_path('app/Http/Helpers/function_helper.php'))) {
File::requireOnce(base_path('app/Http/Helpers/function_helper.php'));
@@ -0,0 +1,37 @@
<?php
namespace App\Repositories\Employee;
use App\Models\User;
use App\Repositories\BaseRepository;
class EmployeeRepository extends BaseRepository implements EmployeeRepositoryInterface
{
public function getModel(): string
{
return User::class;
}
public function filter(array $data): mixed
{
$query = $this->model->with('roles');
if (!empty($data['search'])) {
$search = $data['search'];
$query->where(function ($q) use ($search) {
$q->where('firstname', 'like', "%{$search}%")
->orWhere('lastname', 'like', "%{$search}%")
->orWhere('username', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
}
if (!empty($data['role'])) {
$query->whereHas('roles', fn($q) => $q->where('name', $data['role']));
}
$perPage = $data['per_page'] ?? 15;
return $query->orderBy('id', 'desc')->paginate($perPage);
}
}
@@ -0,0 +1,10 @@
<?php
namespace App\Repositories\Employee;
use App\Repositories\BaseRepositoryInterface;
interface EmployeeRepositoryInterface extends BaseRepositoryInterface
{
public function filter(array $data): mixed;
}
@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('user', function (Blueprint $table) {
$table->date('birthday')->nullable()->after('email');
$table->string('address')->nullable()->after('birthday');
$table->string('phone', 20)->nullable()->after('address');
});
}
public function down(): void
{
Schema::table('user', function (Blueprint $table) {
$table->dropColumn(['birthday', 'address', 'phone']);
});
}
};
+94
View File
@@ -0,0 +1,94 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
/**
* Sửa guard_name từ 'admins' → 'admin' cho tất cả roles & permissions.
* Chạy 1 lần: php artisan db:seed --class=FixRoleGuardSeeder
*/
class FixRoleGuardSeeder extends Seeder
{
public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Cập nhật permissions
DB::table('permissions')
->where('guard_name', 'admins')
->update(['guard_name' => 'admin']);
// Cập nhật roles
DB::table('roles')
->where('guard_name', 'admins')
->update(['guard_name' => 'admin']);
$this->command->info('✅ Đã cập nhật guard_name: admins → admin cho ' .
Role::where('guard_name', 'admin')->count() . ' roles, ' .
Permission::where('guard_name', 'admin')->count() . ' permissions.');
// Đảm bảo 6 roles tồn tại với guard admin
$roles = [
'Full Administrator',
'Administrator',
'Sale',
'IT',
'Customer Service',
'Marketing',
];
foreach ($roles as $name) {
Role::firstOrCreate([
'name' => $name,
'guard_name' => 'admin',
]);
}
// Full Administrator luôn có tất cả permissions
$fullAdmin = Role::where('name', 'Full Administrator')
->where('guard_name', 'admin')
->first();
if ($fullAdmin) {
$fullAdmin->syncPermissions(
Permission::where('guard_name', 'admin')->get()
);
$this->command->info('✅ Full Administrator đã được cấp tất cả quyền.');
}
// Administrator được cấp một số quyền cơ bản
$admin = Role::where('name', 'Administrator')
->where('guard_name', 'admin')
->first();
if ($admin) {
$adminPermissions = [
'customer.view',
'customer.create',
'customer.edit',
'customer.manager',
'product-service.view',
'product-service.create',
'product-service.edit',
'product-service.manager',
'order.view',
'order.create',
'order.edit',
'order.manager',
'administrator.view',
'administrator.manager',
];
$perms = Permission::whereIn('name', $adminPermissions)
->where('guard_name', 'admin')
->get();
$admin->syncPermissions($perms);
$this->command->info('✅ Administrator đã được cấp quyền: ' . implode(', ', $adminPermissions));
}
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
}
}
+16 -11
View File
@@ -2,22 +2,27 @@
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
public function run(): void
{
Role::create([
'name' => 'Full Administrator',
'guard_name' => 'admins'
]);
$roles = [
'Full Administrator',
'Administrator',
'Sale',
'IT',
'Customer Service',
'Marketing',
];
foreach ($roles as $name) {
Role::firstOrCreate([
'name' => $name,
'guard_name' => 'admin',
]);
}
}
}
+124 -101
View File
@@ -2,135 +2,158 @@
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RolesAndPermissions extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
public function run(): void
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// create client permissions
Permission::create(['name' => 'manager customer']);
Permission::create(['name' => 'add customer']);
Permission::create(['name' => 'edit customer']);
Permission::create(['name' => 'delete customer']);
$permissions = [
// Khách hàng
'customer.view',
'customer.create',
'customer.edit',
'customer.destroy',
'customer.manager',
// create admin permissions
Permission::create(['name' => 'manager administrator']);
Permission::create(['name' => 'add administrator']);
Permission::create(['name' => 'edit administrator']);
Permission::create(['name' => 'delete administrator']);
// Nhân sự
'administrator.view',
'administrator.create',
'administrator.edit',
'administrator.destroy',
'administrator.manager',
// create product permissions
Permission::create(['name' => 'manager product']);
Permission::create(['name' => 'add product']);
Permission::create(['name' => 'edit product']);
Permission::create(['name' => 'delete product']);
// Sản phẩm / Dịch vụ
'product-service.view',
'product-service.create',
'product-service.edit',
'product-service.destroy',
'product-service.manager',
// create order permissions
Permission::create(['name' => 'manager order']);
Permission::create(['name' => 'add order']);
Permission::create(['name' => 'edit order']);
Permission::create(['name' => 'delete order']);
// Đơn hàng
'order.view',
'order.create',
'order.edit',
'order.destroy',
'order.manager',
// create invoice permissions
Permission::create(['name' => 'manager invoice']);
Permission::create(['name' => 'add invoice']);
Permission::create(['name' => 'edit invoice']);
Permission::create(['name' => 'delete invoice']);
// Hóa đơn
'invoice.view',
'invoice.create',
'invoice.edit',
'invoice.destroy',
'invoice.manager',
// Create Coupon Permissions
Permission::create(['name' => 'manager coupon']);
Permission::create(['name' => 'add coupon']);
Permission::create(['name' => 'edit coupon']);
Permission::create(['name' => 'delete coupon']);
// Mã giảm giá
'coupon.view',
'coupon.create',
'coupon.edit',
'coupon.destroy',
'coupon.manager',
// Create post Permissions
Permission::create(['name' => 'manager post']);
Permission::create(['name' => 'add post']);
Permission::create(['name' => 'edit post']);
Permission::create(['name' => 'delete post']);
// Bài viết
'post.view',
'post.create',
'post.edit',
'post.destroy',
'post.manager',
// Create support Permissions
Permission::create(['name' => 'manager support']);
Permission::create(['name' => 'add support']);
Permission::create(['name' => 'edit support']);
Permission::create(['name' => 'delete support']);
// Hỗ trợ
'support.view',
'support.create',
'support.edit',
'support.destroy',
'support.manager',
// Create Payment Permissions
Permission::create(['name' => 'manager payment']);
Permission::create(['name' => 'add payment']);
Permission::create(['name' => 'edit payment']);
Permission::create(['name' => 'delete payment']);
// Thanh toán
'payment.view',
'payment.create',
'payment.edit',
'payment.destroy',
'payment.manager',
// create module dns permissions
Permission::create(['name' => 'manager module dns']);
Permission::create(['name' => 'add module dns']);
Permission::create(['name' => 'edit module dns']);
Permission::create(['name' => 'delete module dns']);
// Module DNS
'module-dns.view',
'module-dns.create',
'module-dns.edit',
'module-dns.destroy',
'module-dns.manager',
// create module hosting permissions
Permission::create(['name' => 'manager module hosting']);
Permission::create(['name' => 'add module hosting']);
Permission::create(['name' => 'edit module hosting']);
Permission::create(['name' => 'delete module hosting']);
// Module Hosting
'module-hosting.view',
'module-hosting.create',
'module-hosting.edit',
'module-hosting.destroy',
'module-hosting.manager',
// create module vcenter permissions
Permission::create(['name' => 'manager module vcenter']);
Permission::create(['name' => 'add module vcenter']);
Permission::create(['name' => 'edit module vcenter']);
Permission::create(['name' => 'delete module vcenter']);
// Module vCenter
'module-vcenter.view',
'module-vcenter.create',
'module-vcenter.edit',
'module-vcenter.destroy',
'module-vcenter.manager',
// create module ippool permissions
Permission::create(['name' => 'manager module ippool']);
Permission::create(['name' => 'add module ippool']);
Permission::create(['name' => 'edit module ippool']);
Permission::create(['name' => 'delete module ippool']);
// IP Pool
'module-ippool.view',
'module-ippool.create',
'module-ippool.edit',
'module-ippool.destroy',
'module-ippool.manager',
// create package permissions
Permission::create(['name' => 'manager package module']);
Permission::create(['name' => 'add package module']);
Permission::create(['name' => 'edit package module']);
Permission::create(['name' => 'delete package module']);
// Gói dịch vụ
'package-module.view',
'package-module.create',
'package-module.edit',
'package-module.destroy',
'package-module.manager',
// create email template permissions
Permission::create(['name' => 'manager email template']);
Permission::create(['name' => 'add email template']);
Permission::create(['name' => 'edit email template']);
Permission::create(['name' => 'delete email template']);
// Email Template
'email-template.view',
'email-template.create',
'email-template.edit',
'email-template.destroy',
'email-template.manager',
// create setting permissions
Permission::create(['name' => 'manager setting']);
Permission::create(['name' => 'manager smtp']);
Permission::create(['name' => 'manager auto banking']);
Permission::create(['name' => 'manager system log']);
// Cài đặt
'setting.manager',
'smtp.manager',
'auto-banking.manager',
'system-log.manager',
// create role permissions
Permission::create(['name' => 'manager role']);
Permission::create(['name' => 'add role']);
Permission::create(['name' => 'edit role']);
Permission::create(['name' => 'delete role']);
// Vai trò & Phân quyền
'role.view',
'role.create',
'role.edit',
'role.destroy',
'role.manager',
// Menu
'menu.view',
'menu.create',
'menu.edit',
'menu.destroy',
'menu.manager',
];
// Create Menu Permissions
Permission::create(['name' => 'manager menu']);
Permission::create(['name' => 'add menu']);
Permission::create(['name' => 'edit menu']);
Permission::create(['name' => 'delete menu']);
// this can be done as separate statements
$role = Role::find(1);
foreach ($permissions as $name) {
Permission::firstOrCreate([
'name' => $name,
'guard_name' => 'admin',
]);
}
$role->givePermissionTo(Permission::all());
// Full Administrator nhận tất cả quyền
$fullAdmin = Role::where('name', 'Full Administrator')
->where('guard_name', 'admin')
->first();
if ($fullAdmin) {
$fullAdmin->syncPermissions(Permission::where('guard_name', 'admin')->get());
}
}
}
+99 -74
View File
@@ -2,6 +2,8 @@
use App\Http\Controllers\Api\Admin\Auth\AuthController;
use App\Http\Controllers\Api\Admin\Customer\CustomerController;
use App\Http\Controllers\Api\Admin\Employee\EmployeeController;
use App\Http\Controllers\Api\Admin\Role\RolePermissionController;
use App\Http\Controllers\Api\Admin\Invoice\InvoiceController;
use App\Http\Controllers\Api\Admin\Order\OrderController;
use App\Http\Controllers\Api\Admin\Payment\PaymentController;
@@ -38,105 +40,128 @@ Route::prefix('v1')
Route::post('refresh', [AuthController::class, 'refresh']);
Route::get('me', [AuthController::class, 'me']);
// Customers
// Role Permissions
Route::prefix('role-permissions')->group(function () {
// Accessible bởi mọi admin — trả về permissions hiệu lực của user hiện tại
Route::get('mine', [RolePermissionController::class, 'mine']);
// Các endpoint sau chỉ dành cho Full Administrator (kiểm tra trong controller)
Route::get('/', [RolePermissionController::class, 'index']);
Route::get('all-permissions', [RolePermissionController::class, 'allPermissions']);
Route::post('permissions', [RolePermissionController::class, 'createPermissionGroup']);
Route::delete('permissions/group/{module}', [RolePermissionController::class, 'deletePermissionGroup']);
Route::patch('permissions/{id}', [RolePermissionController::class, 'renamePermission']);
Route::put('{roleId}', [RolePermissionController::class, 'update']);
});
// Employees (module: administrator)
Route::prefix('employees')->group(function () {
Route::get('roles', [EmployeeController::class, 'roles'])->middleware('perm:administrator.view');
Route::get('/', [EmployeeController::class, 'index'])->middleware('perm:administrator.view');
Route::post('/', [EmployeeController::class, 'store'])->middleware('perm:administrator.create');
Route::get('{id}', [EmployeeController::class, 'show'])->middleware('perm:administrator.view');
Route::put('{id}', [EmployeeController::class, 'update'])->middleware('perm:administrator.edit');
Route::delete('{id}', [EmployeeController::class, 'destroy'])->middleware('perm:administrator.destroy');
});
// Customers (module: customer)
Route::prefix('customers')->group(function () {
Route::get('/', [CustomerController::class, 'index']);
Route::get('/datatable', [CustomerController::class, 'datatable']);
Route::post('/', [CustomerController::class, 'store']);
Route::get('{id}', [CustomerController::class, 'show']);
Route::put('{id}', [CustomerController::class, 'update']);
Route::delete('{id}', [CustomerController::class, 'destroy']);
Route::post('{id}/reset-password', [CustomerController::class, 'resetPassword']);
Route::post('{id}/add-credit', [CustomerController::class, 'addCredit']);
Route::get('{id}/products', [CustomerController::class, 'getProducts']);
Route::get('{id}/invoices', [CustomerController::class, 'getInvoices']);
Route::get('{id}/transactions', [CustomerController::class, 'getTransactions']);
Route::get('{id}/domains', [CustomerController::class, 'getDomains']);
Route::get('trash', [CustomerController::class, 'trash']);
Route::post('{id}/restore', [CustomerController::class, 'restore']);
Route::delete('{id}/force', [CustomerController::class, 'forceDelete']);
Route::get('trash', [CustomerController::class, 'trash'])->middleware('perm:customer.view');
Route::get('/', [CustomerController::class, 'index'])->middleware('perm:customer.view');
Route::get('/datatable', [CustomerController::class, 'datatable'])->middleware('perm:customer.view');
Route::post('/', [CustomerController::class, 'store'])->middleware('perm:customer.create');
Route::get('{id}', [CustomerController::class, 'show'])->middleware('perm:customer.view');
Route::put('{id}', [CustomerController::class, 'update'])->middleware('perm:customer.edit');
Route::delete('{id}', [CustomerController::class, 'destroy'])->middleware('perm:customer.destroy');
Route::post('{id}/reset-password', [CustomerController::class, 'resetPassword'])->middleware('perm:customer.edit');
Route::post('{id}/add-credit', [CustomerController::class, 'addCredit'])->middleware('perm:customer.edit');
Route::get('{id}/products', [CustomerController::class, 'getProducts'])->middleware('perm:customer.view');
Route::get('{id}/invoices', [CustomerController::class, 'getInvoices'])->middleware('perm:customer.view');
Route::get('{id}/transactions', [CustomerController::class, 'getTransactions'])->middleware('perm:customer.view');
Route::get('{id}/domains', [CustomerController::class, 'getDomains'])->middleware('perm:customer.view');
Route::post('{id}/restore', [CustomerController::class, 'restore'])->middleware('perm:customer.edit');
Route::delete('{id}/force', [CustomerController::class, 'forceDelete'])->middleware('perm:customer.destroy');
});
// Products
// Products (module: product-service)
Route::prefix('products')->group(function () {
Route::get('/', [ProductController::class, 'index']);
Route::post('/', [ProductController::class, 'store']);
Route::get('{id}', [ProductController::class, 'show']);
Route::put('{id}', [ProductController::class, 'update']);
Route::delete('{id}', [ProductController::class, 'destroy']);
Route::post('{id}/duplicate', [ProductController::class, 'duplicate']);
Route::post('import', [ProductController::class, 'import']);
Route::get('export', [ProductController::class, 'export']);
Route::get('export', [ProductController::class, 'export'])->middleware('perm:product-service.manager');
Route::get('/', [ProductController::class, 'index'])->middleware('perm:product-service.view');
Route::post('/', [ProductController::class, 'store'])->middleware('perm:product-service.create');
Route::post('import', [ProductController::class, 'import'])->middleware('perm:product-service.create');
Route::get('{id}', [ProductController::class, 'show'])->middleware('perm:product-service.view');
Route::put('{id}', [ProductController::class, 'update'])->middleware('perm:product-service.edit');
Route::delete('{id}', [ProductController::class, 'destroy'])->middleware('perm:product-service.destroy');
Route::post('{id}/duplicate', [ProductController::class, 'duplicate'])->middleware('perm:product-service.create');
});
// Product Categories (Groups)
// Product Categories / Groups (module: product-service)
Route::prefix('product-categories')->group(function () {
Route::get('/', [ProductCategoryController::class, 'index']);
Route::post('/', [ProductCategoryController::class, 'store']);
Route::get('{id}', [ProductCategoryController::class, 'show']);
Route::put('{id}', [ProductCategoryController::class, 'update']);
Route::delete('{id}', [ProductCategoryController::class, 'destroy']);
Route::get('/', [ProductCategoryController::class, 'index'])->middleware('perm:product-service.view');
Route::post('/', [ProductCategoryController::class, 'store'])->middleware('perm:product-service.create');
Route::get('{id}', [ProductCategoryController::class, 'show'])->middleware('perm:product-service.view');
Route::put('{id}', [ProductCategoryController::class, 'update'])->middleware('perm:product-service.edit');
Route::delete('{id}', [ProductCategoryController::class, 'destroy'])->middleware('perm:product-service.destroy');
});
// Orders
// Orders (module: order)
Route::prefix('orders')->group(function () {
Route::get('/', [OrderController::class, 'index']);
Route::get('/datatable', [OrderController::class, 'datatable']);
Route::post('/', [OrderController::class, 'store']);
Route::get('{id}', [OrderController::class, 'show']);
Route::put('{id}', [OrderController::class, 'update']);
Route::delete('{id}', [OrderController::class, 'destroy']);
Route::post('{id}/accept', [OrderController::class, 'accept']);
Route::post('{id}/cancel', [OrderController::class, 'cancel']);
Route::get('/', [OrderController::class, 'index'])->middleware('perm:order.view');
Route::get('/datatable', [OrderController::class, 'datatable'])->middleware('perm:order.view');
Route::post('/', [OrderController::class, 'store'])->middleware('perm:order.create');
Route::get('{id}', [OrderController::class, 'show'])->middleware('perm:order.view');
Route::put('{id}', [OrderController::class, 'update'])->middleware('perm:order.edit');
Route::delete('{id}', [OrderController::class, 'destroy'])->middleware('perm:order.destroy');
Route::post('{id}/accept', [OrderController::class, 'accept'])->middleware('perm:order.edit');
Route::post('{id}/cancel', [OrderController::class, 'cancel'])->middleware('perm:order.edit');
});
// Invoices
// Invoices (module: invoice)
Route::prefix('invoices')->group(function () {
Route::get('/', [InvoiceController::class, 'index']);
Route::get('/datatable', [InvoiceController::class, 'datatable']);
Route::post('/', [InvoiceController::class, 'store']);
Route::get('{id}', [InvoiceController::class, 'show']);
Route::put('{id}', [InvoiceController::class, 'update']);
Route::delete('{id}', [InvoiceController::class, 'destroy']);
Route::post('{id}/paid', [InvoiceController::class, 'markAsPaid']);
Route::post('{id}/cancel', [InvoiceController::class, 'cancel']);
Route::get('/', [InvoiceController::class, 'index'])->middleware('perm:invoice.view');
Route::get('/datatable', [InvoiceController::class, 'datatable'])->middleware('perm:invoice.view');
Route::post('/', [InvoiceController::class, 'store'])->middleware('perm:invoice.create');
Route::get('{id}', [InvoiceController::class, 'show'])->middleware('perm:invoice.view');
Route::put('{id}', [InvoiceController::class, 'update'])->middleware('perm:invoice.edit');
Route::delete('{id}', [InvoiceController::class, 'destroy'])->middleware('perm:invoice.destroy');
Route::post('{id}/paid', [InvoiceController::class, 'markAsPaid'])->middleware('perm:invoice.edit');
Route::post('{id}/cancel', [InvoiceController::class, 'cancel'])->middleware('perm:invoice.edit');
});
// Payments
// Payments (module: payment)
Route::prefix('payments')->group(function () {
Route::get('/', [PaymentController::class, 'index']);
Route::post('/', [PaymentController::class, 'store']);
Route::get('{id}', [PaymentController::class, 'show']);
Route::put('{id}', [PaymentController::class, 'update']);
Route::delete('{id}', [PaymentController::class, 'destroy']);
Route::get('/', [PaymentController::class, 'index'])->middleware('perm:payment.view');
Route::post('/', [PaymentController::class, 'store'])->middleware('perm:payment.create');
Route::get('{id}', [PaymentController::class, 'show'])->middleware('perm:payment.view');
Route::put('{id}', [PaymentController::class, 'update'])->middleware('perm:payment.edit');
Route::delete('{id}', [PaymentController::class, 'destroy'])->middleware('perm:payment.destroy');
});
// VPS
// VPS (module: module-vcenter)
Route::prefix('vps')->group(function () {
Route::get('/', [VPSController::class, 'index']);
Route::get('{id}', [VPSController::class, 'show']);
Route::put('{id}', [VPSController::class, 'update']);
Route::post('{id}/power-on', [VPSController::class, 'powerOn']);
Route::post('{id}/power-off', [VPSController::class, 'powerOff']);
Route::post('{id}/restart', [VPSController::class, 'restart']);
Route::get('{id}/console-ticket', [VPSController::class, 'getConsoleTicket']);
Route::get('/', [VPSController::class, 'index'])->middleware('perm:module-vcenter.view');
Route::get('{id}', [VPSController::class, 'show'])->middleware('perm:module-vcenter.view');
Route::put('{id}', [VPSController::class, 'update'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-on', [VPSController::class, 'powerOn'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-off', [VPSController::class, 'powerOff'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/restart', [VPSController::class, 'restart'])->middleware('perm:module-vcenter.edit');
Route::get('{id}/console-ticket', [VPSController::class, 'getConsoleTicket'])->middleware('perm:module-vcenter.view');
});
// vCenter
// vCenter (module: module-vcenter)
Route::prefix('vcenter')->group(function () {
Route::get('tree', [VCenterController::class, 'tree']);
Route::get('console-ticket', [VCenterController::class, 'consoleTicket']);
Route::post('/', [VCenterController::class, 'store']);
Route::post('sync', [VCenterController::class, 'sync']);
Route::put('node/{type}/{id}', [VCenterController::class, 'updateNode']);
Route::delete('node/{type}/{id}', [VCenterController::class, 'destroyNode']);
Route::get('tree', [VCenterController::class, 'tree'])->middleware('perm:module-vcenter.view');
Route::get('console-ticket', [VCenterController::class, 'consoleTicket'])->middleware('perm:module-vcenter.view');
Route::post('/', [VCenterController::class, 'store'])->middleware('perm:module-vcenter.create');
Route::post('sync', [VCenterController::class, 'sync'])->middleware('perm:module-vcenter.edit');
Route::put('node/{type}/{id}', [VCenterController::class, 'updateNode'])->middleware('perm:module-vcenter.edit');
Route::delete('node/{type}/{id}', [VCenterController::class, 'destroyNode'])->middleware('perm:module-vcenter.destroy');
});
// vCenter Manager Power Operations
// vCenter Manager Power Operations (module: module-vcenter)
Route::prefix('vcenter-manager')->group(function () {
Route::post('vm/power-on', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOn']);
Route::post('vm/power-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOff']);
Route::get('vms/powered-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'getPoweredOffVms']);
Route::post('vm/power-on', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOn'])->middleware('perm:module-vcenter.edit');
Route::post('vm/power-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOff'])->middleware('perm:module-vcenter.edit');
Route::get('vms/powered-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'getPoweredOffVms'])->middleware('perm:module-vcenter.view');
});
});
});