update permission

This commit is contained in:
JOSEPH LE 2024-06-10 16:30:02 +07:00
parent 20e9cdbc18
commit 4c2e525e28
11 changed files with 108 additions and 40 deletions

View File

@ -4,7 +4,7 @@
'title' => 'Reset Password Successfully',
'name' => $name,
'body' => "We wanted to let you know that your password has been successfully reset. Your account is now secured with a new password. <hr>
If you did not initiate this password reset or have any concerns about your account security, please contact our support team immediately at " . config('mail.from.address') . " or reply to this email.",
If you did not initiate this password reset or have any concerns about your account security, please contact our support team.",
'footer_detail' => "This email was sent $email.",
];
@endphp
@ -120,9 +120,9 @@
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
<tr>
<td align="center" valign="top" style="padding: 36px 24px;">
<a href="{{env('ADMIN_URL')}}" target="_blank" style="display: inline-block;">
<!-- <a href="{{env('ADMIN_URL')}}" target="_blank" style="display: inline-block;">
<img src="{{asset(\App\Models\Setting::getByCache()->value('logo'))}}" alt="Logo" border="0" width="100" style="display: block; width: 100px; max-width: 100px; min-width: 48px;">
</a>
</a> -->
</td>
</tr>
</table>

View File

@ -1,5 +1,6 @@
<?php
use App\Http\Middleware\CheckPermission;
use Illuminate\Support\Facades\Route;
use Modules\Admin\app\Http\Controllers\AdminController;
use Modules\Admin\app\Http\Controllers\BannerController;
@ -99,21 +100,21 @@ Route::middleware('api')
Route::get('/export-issues', [JiraController::class, 'exportToExcel']);
Route::get('/all-project', [JiraController::class, 'getAllProject']);
Route::get('/all-issue-by-project', [JiraController::class, 'fetchIssuesByProject']);
Route::get('/worklogs', [JiraController::class, 'getAllUserWorkLogs']);
Route::get('/worklogs', [JiraController::class, 'getAllUserWorkLogs'])->middleware('check.permission:admin');
});
Route::group([
'prefix' => 'timekeeping',
], function () {
Route::get('/', [TimekeepingController::class, 'get']);
Route::get('/', [TimekeepingController::class, 'get'])->middleware('check.permission:admin.hr.staff');
});
Route::group([
'prefix' => 'tracking',
], function () {
Route::post('/create', [TrackingController::class, 'create']);
Route::post('/update', [TrackingController::class, 'update']);
Route::get('/delete', [TrackingController::class, 'delete']);
Route::post('/create', [TrackingController::class, 'create'])->middleware('check.permission:admin.hr');
Route::post('/update', [TrackingController::class, 'update'])->middleware('check.permission:admin.hr');
Route::get('/delete', [TrackingController::class, 'delete'])->middleware('check.permission:admin.hr');
});
});
});
@ -121,7 +122,7 @@ Route::middleware('api')
Route::group([
'prefix' => 'v1/admin/tracking',
], function () {
Route::get('/', [TrackingController::class, 'get']);
Route::get('/', [TrackingController::class, 'get'])->middleware('check.permission:admin.hr.staff');
Route::post('/scan-create', [TrackingController::class, 'create']);
Route::post('/send-image', [TrackingController::class, 'saveImage']);
// Route::get('/clear-cache', [SettingController::class, 'clearCache']);

View File

@ -21,9 +21,13 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\CheckAccountStatus::class,
\App\Http\Middleware\CheckAccountStatus::class
];
protected $routeMiddleware = [
// Other middleware
'check.permission' => \App\Http\Middleware\CheckPermission::class,
];
/**
* The application's route middleware groups.
*

View File

@ -0,0 +1,36 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class CheckPermission
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, $requiredPermission): Response
{
$user = auth('admins')->user();
// dd(auth('admins')->user()->permission);
$requiredPermission = explode('.', $requiredPermission);
if ($user) {
$permission = explode(',', $user->permission);
// Kiểm tra nếu user có quyền yêu cầu
foreach ($requiredPermission as $perm) {
if (in_array($perm, $permission)) {
return $next($request);
}
}
}
// Nếu không có quyền, trả về response 403
return response()->json(['status' => false, 'message' => 'Forbidden'], 403);
}
}

View File

@ -573,6 +573,19 @@ export const DataTablePagination = ({
)
})
const removeParam = (name:string) => {
// Create a URL object
let url = new URL(window.location.href)
// Get the search parameters object
let params = url.searchParams
// Remove specific parameters
params.delete(name)
// Update the URL without reloading the page
window.history.replaceState({}, document.title, url.toString())
}
// Refresh data when useEffect start
const fetchData = async (url: string) => {
try {
@ -583,7 +596,7 @@ export const DataTablePagination = ({
page: page,
timezone: timeZone,
}
// console.log(statusSort.name)
// Add 'order_by_[field_name] to 'params'
if (statusSort.status !== 'clear') {
Object.assign(params, {
@ -669,6 +682,7 @@ export const DataTablePagination = ({
search: urlParams.toString(),
})
}
statusSort.status === 'clear' && removeParam(`order_by_${statusSort.name}`)
} catch (error) {
console.warn(error)
}

View File

@ -18,7 +18,6 @@ import {
} from '@mantine/core'
import { notifications } from '@mantine/notifications'
import {
IconBrush,
IconCalendar,
IconLayoutSidebarLeftExpand,
IconLayoutSidebarRightExpand,
@ -28,7 +27,6 @@ import {
IconPasswordUser,
IconReport,
IconScan,
IconSettings,
IconSubtask,
IconSun
} from '@tabler/icons-react'
@ -43,8 +41,8 @@ const data = [
{ link: '/tracking', label: 'Check in/out', icon: IconScan },
{ link: '/worklogs', label: 'Worklogs', icon: IconReport },
{ link: '/jira', label: 'Jira', icon: IconSubtask },
{ link: '/custom-theme', label: 'Custom Theme', icon: IconBrush },
{ link: '/general-setting', label: 'General Setting', icon: IconSettings },
// { link: '/custom-theme', label: 'Custom Theme', icon: IconBrush },
// { link: '/general-setting', label: 'General Setting', icon: IconSettings },
// { link: '/packages', label: 'Packages', icon: IconPackages },
// { link: '/discounts', label: 'Discounts', icon: IconDiscount2 },
// { link: '/client', label: 'Clients', icon: IconUsersGroup },
@ -200,10 +198,10 @@ const Navbar = ({
>
<div className={classes.navbarMain}>
<Group className={classes.header} justify="space-between">
<Image
{/* <Image
src="https://littlepay.com/wp-content/uploads/2021/11/animation-elements-2.svg"
w={isCompactMenu ? '120%' : '50%'}
></Image>
></Image> */}
<Code fw={700} className={classes.version}>
v1.0.1
</Code>
@ -361,7 +359,6 @@ const Navbar = ({
loading === false &&
dataChange.password !== '' &&
passwordRegex.test(dataChange.new_password) &&
passwordRegex.test(dataChange.password) &&
dataChange.new_password === dataChange.confirm_password &&
dataChange.new_password !== ''
? false

View File

@ -2,7 +2,7 @@
height: rem(100%);
display: flex;
flex-direction: column;
background-color: #2d353c;
background-color: #1c4a73;
width: 100%;
}
@ -20,7 +20,7 @@
/* z-index: 1000; */
background-image: linear-gradient(rgba(27, 26, 26, 0.5),
rgba(29, 27, 27, 0.5)),
url('https://upload.wikimedia.org/wikipedia/commons/5/5c/Dark_mountain_panorama.jpg');
url('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT-bB7j40qe-mSJ-howmBO7T6tAghPrtfLvDw&s');
height: rem(100px);
background-repeat: no-repeat;
background-size: cover;
@ -66,7 +66,7 @@
&,
&:hover {
box-shadow: var(--mantine-shadow-sm);
background-color: #576470b7;
background-color: #6089afb7;
color: var(--mantine-color-white);
.linkIcon {

View File

@ -4,6 +4,7 @@ import { Box, Image, Select, Table, Text, Tooltip } from '@mantine/core'
import { IconCheck, IconX } from '@tabler/icons-react'
import { useEffect, useState } from 'react'
import classes from './Timekeeping.module.css'
import { notifications } from '@mantine/notifications'
interface User {
id: number
@ -39,7 +40,6 @@ interface UserData {
}
const Timekeeping = () => {
let permission = ['staff']
const [daysInMonth, setDaysInMonth] = useState(
Array.from({ length: 31 }, (_, index) => index + 1),
)
@ -58,15 +58,20 @@ const Timekeeping = () => {
if (res.status) {
setData(
res.data.filter((u: UserData) =>
permission.includes(u.user.permission),
!u.user.email.includes('admin'),
),
)
setDaysInMonth(
Array.from({ length: getDaysInMonth() }, (_, index) => index + 1),
)
}
} catch (error) {
} catch (error:any) {
console.log(error)
notifications.show({
title: 'Error',
message: error.message??error,
color: 'red',
})
}
}
@ -175,7 +180,7 @@ const Timekeeping = () => {
<Tooltip
multiline
label={
<div>
<div key={d}>
{`Total: ${(total / 60 / 60).toFixed(1)}h`}
{user.history
.find((h) => h.day === d)

View File

@ -17,6 +17,7 @@ import { IconEdit, IconTrash } from '@tabler/icons-react'
import moment from 'moment'
import { useEffect, useState } from 'react'
import classes from './Tracking.module.css'
import { notifications } from '@mantine/notifications'
type TLog = {
id: number
@ -156,8 +157,12 @@ const Tracking = () => {
if (res.status) {
setListTracking(res)
}
} catch (error) {
console.log(error)
} catch (error:any) {
notifications.show({
title: 'Error',
message: error.message??error,
color: 'red',
})
}
}
@ -205,14 +210,14 @@ const Tracking = () => {
}
useEffect(() => {
if (listTracking.data.length === 0) {
// if (listTracking.data.length === 0) {
getAllTracking()
}
setInterval(() => {
if (window.location.pathname.includes('tracking')) {
getAllTracking()
}
}, 7000)
// }
// setInterval(() => {
// if (window.location.pathname.includes('tracking')) {
// getAllTracking()
// }
// }, 60000)
}, [])
return (
<div>
@ -268,7 +273,7 @@ const Tracking = () => {
<Box pl={'md'} pr={'md'}>
<Select
label={'Name'}
placeholder="Banner x"
placeholder="Jonh"
maxLength={255}
required
data={listTracking.users.map((i: User) => i.name)}
@ -326,7 +331,7 @@ const Tracking = () => {
position={{ top: 30, right: 10 }}
>
<Text className={classes.dialogText} size="sm" mb="xs" fw={500}>
Do you want to delete this discount?
Do you want to delete this record?
<Group justify="center" m={10}>
<Button
disabled={activeBtn}

View File

@ -13,6 +13,7 @@ import { DateInput } from '@mantine/dates'
import moment from 'moment'
import { useEffect, useState } from 'react'
import classes from './Worklogs.module.css'
import { notifications } from '@mantine/notifications'
interface WorkLog {
self: string
@ -155,8 +156,13 @@ const Worklogs = () => {
}
setUpdating(true)
} catch (error) {
} catch (error:any) {
console.log(error)
notifications.show({
title: 'Error',
message: error.message??error,
color: 'red',
})
}
}

View File

@ -36,7 +36,7 @@ export const create = async (
if (res.status === false) {
notifications.show({
title: 'Error',
message: _NOTIFICATION_MESS.create_error,
message: res.message??_NOTIFICATION_MESS.create_error,
color: 'red',
})
}
@ -87,7 +87,7 @@ export const update = async (
if (res.status === false) {
notifications.show({
title: 'Error',
message: _NOTIFICATION_MESS.update_error,
message: res.message??_NOTIFICATION_MESS.update_error,
color: 'red',
})
}
@ -127,7 +127,7 @@ export const Xdelete = async (url: string, data: any, fnc?: () => void) => {
if (res.status === false) {
notifications.show({
title: 'Error',
message: _NOTIFICATION_MESS.delete_error,
message: res.message??_NOTIFICATION_MESS.delete_error,
color: 'red',
})
}