feat: add app and database modules
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
if (! function_exists('isImpersonating')) {
|
||||
function isImpersonating(): bool
|
||||
{
|
||||
return session()->has('impersonator_id');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('impersonatorId')) {
|
||||
function impersonatorId(): ?int
|
||||
{
|
||||
return session('impersonator_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class PasswordRuleHelper
|
||||
{
|
||||
/**
|
||||
* Aturan standar password aplikasi
|
||||
*/
|
||||
public static function rules(): array
|
||||
{
|
||||
return [
|
||||
'required',
|
||||
'string',
|
||||
'min:12',
|
||||
|
||||
// minimal 1 huruf kecil
|
||||
'regex:/[a-z]/',
|
||||
|
||||
// minimal 1 huruf besar
|
||||
'regex:/[A-Z]/',
|
||||
|
||||
// minimal 1 angka
|
||||
'regex:/[0-9]/',
|
||||
|
||||
// minimal 1 simbol
|
||||
'regex:/[@$!%*#?&^()_\-+=]/',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message error khusus password
|
||||
*/
|
||||
public static function messages(): array
|
||||
{
|
||||
return [
|
||||
'password.min' => __('Password must be at least 12 characters.'),
|
||||
'password.regex' => __('Password must contain uppercase, lowercase, number, and symbol.'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class SessionHelper
|
||||
{
|
||||
/**
|
||||
* Parses the User Agent string into friendly Browser and OS info.
|
||||
*/
|
||||
public static function parseUserAgent(?string $userAgent): array
|
||||
{
|
||||
if (! $userAgent) {
|
||||
return [
|
||||
'browser' => 'Unknown',
|
||||
'os' => 'Unknown',
|
||||
'browser_icon' => 'bi-question-circle',
|
||||
'os_icon' => 'bi-question-circle',
|
||||
];
|
||||
}
|
||||
|
||||
$browser = 'Unknown';
|
||||
$os = 'Unknown';
|
||||
$browserIcon = 'bi-globe';
|
||||
$osIcon = 'bi-display';
|
||||
|
||||
// OS Detection
|
||||
if (preg_match('/android/i', $userAgent)) {
|
||||
$os = 'Android';
|
||||
$osIcon = 'bi-phone';
|
||||
} elseif (preg_match('/iphone|ipad|ipod/i', $userAgent)) {
|
||||
$os = 'iOS';
|
||||
$osIcon = 'bi-phone';
|
||||
} elseif (preg_match('/windows|win32/i', $userAgent)) {
|
||||
$os = 'Windows';
|
||||
$osIcon = 'bi-windows';
|
||||
} elseif (preg_match('/apple|macintosh|mac os x/i', $userAgent)) {
|
||||
$os = 'macOS';
|
||||
$osIcon = 'bi-apple';
|
||||
} elseif (preg_match('/linux/i', $userAgent)) {
|
||||
$os = 'Linux';
|
||||
$osIcon = 'bi-ubuntu';
|
||||
}
|
||||
|
||||
// Browser Detection
|
||||
if (preg_match('/edge|edg/i', $userAgent)) {
|
||||
$browser = 'Edge';
|
||||
$browserIcon = 'bi-browser-edge';
|
||||
} elseif (preg_match('/chrome|chromium/i', $userAgent)) {
|
||||
$browser = 'Chrome';
|
||||
$browserIcon = 'bi-browser-chrome';
|
||||
} elseif (preg_match('/firefox/i', $userAgent)) {
|
||||
$browser = 'Firefox';
|
||||
$browserIcon = 'bi-browser-firefox';
|
||||
} elseif (preg_match('/safari/i', $userAgent)) {
|
||||
$browser = 'Safari';
|
||||
$browserIcon = 'bi-browser-safari';
|
||||
} elseif (preg_match('/opera|opr/i', $userAgent)) {
|
||||
$browser = 'Opera';
|
||||
$browserIcon = 'bi-browser-opera';
|
||||
}
|
||||
|
||||
return [
|
||||
'browser' => $browser,
|
||||
'os' => $os,
|
||||
'browser_icon' => $browserIcon,
|
||||
'os_icon' => $osIcon,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
use App\Services\SystemConfig\SystemConfigService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
// ── TAB PERMISSION HELPERS ────────────────────────────────────────────────────
|
||||
// Usage: can_view_tab('global settings', 'login-security')
|
||||
// can_manage_tab('mobile settings', 'branding')
|
||||
//
|
||||
// Backward-compat rule: if the user holds the legacy menu-level
|
||||
// 'manage {menu}' permission, they automatically pass every tab check.
|
||||
|
||||
if (! function_exists('can_view_tab')) {
|
||||
function can_view_tab(string $menu, string $tab): bool
|
||||
{
|
||||
if (! auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
$user = auth()->user();
|
||||
$tab = str_replace('_', '-', $tab);
|
||||
|
||||
// Developer gate (super-admin) — already handled by Gate::before, but
|
||||
// we check explicitly here because this is a helper, not a gate call.
|
||||
if ($user->hasRole('Developer')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Legacy menu-level manage permission grants full tab access
|
||||
if ($user->can("manage {$menu}")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Scoped view or manage grants read access to that tab
|
||||
return $user->can("view {$menu}:{$tab}")
|
||||
|| $user->can("manage {$menu}:{$tab}");
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('can_manage_tab')) {
|
||||
function can_manage_tab(string $menu, string $tab): bool
|
||||
{
|
||||
if (! auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
$user = auth()->user();
|
||||
$tab = str_replace('_', '-', $tab);
|
||||
|
||||
if ($user->hasRole('Developer')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Legacy menu-level manage = write access to all tabs
|
||||
if ($user->can("manage {$menu}")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->can("manage {$menu}:{$tab}");
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('can_view_any_tab')) {
|
||||
/**
|
||||
* Returns true if the user can access at least one tab of a given menu.
|
||||
* Used to decide whether to show the menu item in the sidebar at all.
|
||||
*/
|
||||
function can_view_any_tab(string $menu): bool
|
||||
{
|
||||
if (! auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
$user = auth()->user();
|
||||
|
||||
if ($user->hasRole('Developer')) {
|
||||
return true;
|
||||
}
|
||||
if ($user->can("view {$menu}") || $user->can("manage {$menu}")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check granular permissions (both direct and role-based)
|
||||
return $user->getAllPermissions()
|
||||
->contains(fn ($p) => str_starts_with($p->name, "view {$menu}:") || str_starts_with($p->name, "manage {$menu}:"));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('can_manage_any_tab')) {
|
||||
/**
|
||||
* Returns true if the user can manage at least one tab of a given menu.
|
||||
*/
|
||||
function can_manage_any_tab(string $menu): bool
|
||||
{
|
||||
if (! auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
$user = auth()->user();
|
||||
|
||||
if ($user->hasRole('Developer') || $user->can("manage {$menu}")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check granular permissions (both direct and role-based)
|
||||
return $user->getAllPermissions()
|
||||
->contains(fn ($p) => str_starts_with($p->name, "manage {$menu}:"));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('get_setting')) {
|
||||
function get_setting(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return app(SystemConfigService::class)->get($key, $default);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('set_setting')) {
|
||||
function set_setting(string $key, mixed $value): bool
|
||||
{
|
||||
$request = app()->bound('request') ? request() : null;
|
||||
|
||||
app(SystemConfigService::class)->update([$key => $value], [], Auth::id(), $request);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('format_date')) {
|
||||
function format_date($date): string
|
||||
{
|
||||
if (! $date) {
|
||||
return '-';
|
||||
}
|
||||
$format = get_setting('regional_date_format', 'd/m/Y');
|
||||
|
||||
return Carbon::parse($date)->format($format);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('format_time')) {
|
||||
function format_time($time): string
|
||||
{
|
||||
if (! $time) {
|
||||
return '-';
|
||||
}
|
||||
$format = get_setting('regional_time_format', 'H:i');
|
||||
|
||||
return Carbon::parse($time)->format($format);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('format_datetime')) {
|
||||
function format_datetime($datetime): string
|
||||
{
|
||||
if (! $datetime) {
|
||||
return '-';
|
||||
}
|
||||
$dateFormat = get_setting('regional_date_format', 'd/m/Y');
|
||||
$timeFormat = get_setting('regional_time_format', 'H:i');
|
||||
|
||||
return Carbon::parse($datetime)->format("{$dateFormat} {$timeFormat}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user