update permission
This commit is contained in:
parent
20e9cdbc18
commit
4c2e525e28
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue