feat: login history or activity
This commit is contained in:
parent
688a764ea6
commit
614dd4c589
@ -14,6 +14,7 @@
|
|||||||
use App\Models\IssueManagement;
|
use App\Models\IssueManagement;
|
||||||
use App\Models\Journalist;
|
use App\Models\Journalist;
|
||||||
use App\Models\Location;
|
use App\Models\Location;
|
||||||
|
use App\Models\LoginHistory;
|
||||||
use App\Models\Media;
|
use App\Models\Media;
|
||||||
use App\Models\MediaMonitoring;
|
use App\Models\MediaMonitoring;
|
||||||
use App\Models\MediaOrder;
|
use App\Models\MediaOrder;
|
||||||
@ -1968,4 +1969,69 @@ public function role(Request $request){
|
|||||||
return response()->json(['error' => 'Unauthorized'], 401);
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function loginHistory(Request $request){
|
||||||
|
if ($request->ajax()) {
|
||||||
|
|
||||||
|
$year = $request->input('year', null);
|
||||||
|
$month = $request->input('month', null);
|
||||||
|
$date = $request->input('date', null);
|
||||||
|
$role = $request->input('role', null);
|
||||||
|
|
||||||
|
$query = LoginHistory::with(['user']);
|
||||||
|
|
||||||
|
if ($year) {
|
||||||
|
$query->whereYear('logged_in_at', $year);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($month) {
|
||||||
|
$monthYear = Carbon::parse($month);
|
||||||
|
$query->whereYear('logged_in_at', $monthYear->year)
|
||||||
|
->whereMonth('logged_in_at', $monthYear->month);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($date) {
|
||||||
|
$query->whereDate('logged_in_at', $date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($role !== 'all'){
|
||||||
|
if($role === 'admin'){
|
||||||
|
$query->whereHas('user', function ($q) use ($role) {
|
||||||
|
$q->where('role_id', 1);
|
||||||
|
});
|
||||||
|
}else if($role === 'company'){
|
||||||
|
$query->whereHas('user', function ($q) use ($role) {
|
||||||
|
$q->where('role_id', 3);
|
||||||
|
});
|
||||||
|
}else if($role === 'monitoring_admin'){
|
||||||
|
$query->whereHas('user', function ($q) use ($role) {
|
||||||
|
$q->where('role_id', 2);
|
||||||
|
});
|
||||||
|
}else if($role === 'content_admin'){
|
||||||
|
$query->whereHas('user', function ($q) use ($role) {
|
||||||
|
$q->where('role_id', 4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $query->get();
|
||||||
|
|
||||||
|
return DataTables::of($data)
|
||||||
|
->addIndexColumn()
|
||||||
|
->addColumn('name', function ($data) {
|
||||||
|
return $data->user->name;
|
||||||
|
})
|
||||||
|
->addColumn('role', function ($data) {
|
||||||
|
return $data->user->role->name;
|
||||||
|
})
|
||||||
|
->addColumn('logged_in_at', function ($data) {
|
||||||
|
return '<span class="text-info">'.idn_date($data->logged_in_at, 'H:i').'</span>'. '<span class="text-primary"> <span class="text-dark"> - </span> '.idn_date($data->logged_in_at, 'd F Y').'</span>';
|
||||||
|
})
|
||||||
|
->rawColumns(['logged_in_at'])
|
||||||
|
->make(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
app/Http/Controllers/Dashboard/LoginHistoryController.php
Normal file
30
app/Http/Controllers/Dashboard/LoginHistoryController.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Dashboard;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class LoginHistoryController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request){
|
||||||
|
return view('dashboard.login-history.index', [
|
||||||
|
'title' => 'Aktivitas Login',
|
||||||
|
'year' => $request->input('year', null),
|
||||||
|
'month' => $request->input('month', null),
|
||||||
|
'date' => $request->input('date', null),
|
||||||
|
'role' => $request->input('role', null),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filter(Request $request){
|
||||||
|
|
||||||
|
$filteredRequest = $request->except('_token');
|
||||||
|
|
||||||
|
$filterField = array_filter($filteredRequest, function ($value) {
|
||||||
|
return filled($value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('dashboard.login.history.index', $filterField);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
app/Listeners/LogUserLogin.php
Normal file
32
app/Listeners/LogUserLogin.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\LoginHistory;
|
||||||
|
use Illuminate\Auth\Events\Login;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
|
||||||
|
class LogUserLogin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*/
|
||||||
|
public function handle(Login $event): void
|
||||||
|
{
|
||||||
|
LoginHistory::create([
|
||||||
|
'user_id' => $event->user->id,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'user_agent' => request()->userAgent(),
|
||||||
|
'logged_in_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
app/Models/LoginHistory.php
Normal file
21
app/Models/LoginHistory.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class LoginHistory extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'login_histories';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id',
|
||||||
|
'ip_address',
|
||||||
|
'user_agent',
|
||||||
|
'logged_in_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user(){
|
||||||
|
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('login_histories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('ip_address');
|
||||||
|
$table->text('user_agent');
|
||||||
|
$table->timestamp('logged_in_at');
|
||||||
|
$table->unsignedBigInteger('user_id');
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('login_histories');
|
||||||
|
}
|
||||||
|
};
|
||||||
105
resources/views/dashboard/login-history/index.blade.php
Normal file
105
resources/views/dashboard/login-history/index.blade.php
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
@include('partials.dashboard.head')
|
||||||
|
@include('partials.dashboard.sidebar', ['page' => 'login_histories'])
|
||||||
|
@include('partials.dashboard.header')
|
||||||
|
<!-- content @s -->
|
||||||
|
<div class="nk-content ">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="nk-content-inner">
|
||||||
|
<div class="nk-content-body">
|
||||||
|
<div class="nk-block-head nk-block-head-sm">
|
||||||
|
<div class="nk-block-between">
|
||||||
|
<div class="nk-block-head-content">
|
||||||
|
<h3 class="nk-block-title page-title">{{$title}}</h3>
|
||||||
|
</div><!-- .nk-block-head-content -->
|
||||||
|
<div class="nk-block-head-content">
|
||||||
|
<div class="toggle-wrap nk-block-tools-toggle">
|
||||||
|
<a href="#" class="btn btn-icon btn-trigger toggle-expand me-n1" data-target="pageMenu"><em class="icon ni ni-more-v"></em></a>
|
||||||
|
<div class="toggle-expand-content" data-content="pageMenu">
|
||||||
|
<ul class="nk-block-tools g-3">
|
||||||
|
<li>
|
||||||
|
<div class="drodown">
|
||||||
|
<a href="javascript: void(0);" class="btn btn-white btn-dim btn-outline-light" data-bs-toggle="modal" data-bs-target="#modalFilter"><em class="d-none d-sm-inline icon ni ni-filter"></em><span><span class="d-none d-md-inline">Filter</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- .nk-block-between -->
|
||||||
|
</div><!-- .nk-block-head -->
|
||||||
|
<div class="nk-block nk-block-lg">
|
||||||
|
<div class="card card-bordered card-preview">
|
||||||
|
<div class="card-inner">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-bordered nowrap" id="loginHistoriesTable" border="1">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 10% !important;">No</th>
|
||||||
|
<th>Akun</th>
|
||||||
|
<th>Role/Hak Akses</th>
|
||||||
|
<th>Waktu Login</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="modalFilter">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Filter</h5>
|
||||||
|
<a href="javascript:void(0);" class="close" data-bs-dismiss="modal" aria-label="Close">
|
||||||
|
<em class="icon ni ni-cross"></em>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<form action="{{route('dashboard.login.history.filter')}}" class="form-validate is-alter" method="post">
|
||||||
|
@csrf
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="year">Tahun</label>
|
||||||
|
<div class="form-control-wrap">
|
||||||
|
<input type="number" class="form-control" id="year" placeholder="Data login pada tahun" name="year" value="{{$year}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="month">Bulan</label>
|
||||||
|
<div class="form-control-wrap">
|
||||||
|
<input type="month" class="form-control" id="month" placeholder="Data login pada bulan dan tahun" name="month">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="date">Tanggal</label>
|
||||||
|
<div class="form-control-wrap">
|
||||||
|
<input type="date" class="form-control" id="date" placeholder="Data login pada tanggal" name="date">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">Role/Hak Akses</label>
|
||||||
|
<div class="form-control-wrap">
|
||||||
|
<select class="form-select js-select2" name="role">
|
||||||
|
<option value="all">Semua</option>
|
||||||
|
<option value="admin">Administrator</option>
|
||||||
|
<option value="company">Perusahaan</option>
|
||||||
|
<option value="monitoring_admin">Admin Monitoring</option>
|
||||||
|
<option value="content_admin">Admin Konten</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer bg-light">
|
||||||
|
<span class="sub-text">
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary">Filter</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- content @e -->
|
||||||
|
@include('partials.dashboard.footer' ,['datatable' => 'login_history'])
|
||||||
@ -945,3 +945,38 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($datatable === 'login_history')
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#loginHistoriesTable').DataTable({
|
||||||
|
processing: true,
|
||||||
|
serverSide: true,
|
||||||
|
ajax: {
|
||||||
|
url: '{{ route('dashboard.login.history.data') }}',
|
||||||
|
type: 'GET',
|
||||||
|
data: function(d) {
|
||||||
|
d.year = '{{ $year }}';
|
||||||
|
d.month = '{{ $month }}';
|
||||||
|
d.date = '{{ $date }}';
|
||||||
|
d.role = '{{ $role }}';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ data: 'DT_RowIndex', name: 'DT_RowIndex', orderable: false, searchable: false },
|
||||||
|
{ data: 'name', name: 'name' },
|
||||||
|
{ data: 'role', name: 'role' },
|
||||||
|
{ data: 'logged_in_at', name: 'logged_in_at' },
|
||||||
|
{ data: 'created_at', name: 'created_at', visible: false },
|
||||||
|
{ data: 'id', name: 'id', orderable: true, searchable: false, visible: false },
|
||||||
|
],
|
||||||
|
language: datatableLanguage,
|
||||||
|
autoWidth: false,
|
||||||
|
order: [[4, 'desc']],
|
||||||
|
pagingType: "simple",
|
||||||
|
lengthMenu: [[10, 25, 50, 100, -1], ['Tampilkan 10 data', 'Tampilkan 25 data', 'Tampilkan 50 data', 'Tampilkan 100 data', 'Tampilkan semua']],
|
||||||
|
scrollX: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|||||||
@ -212,6 +212,12 @@
|
|||||||
<span class="nk-menu-text">Role</span>
|
<span class="nk-menu-text">Role</span>
|
||||||
</a>
|
</a>
|
||||||
</li><!-- .nk-menu-item -->
|
</li><!-- .nk-menu-item -->
|
||||||
|
<li class="nk-menu-item">
|
||||||
|
<a href="{{route('dashboard.login.history.index')}}" class="nk-menu-link {{$page === 'login_histories' ? 'active-page' : ''}}">
|
||||||
|
<span class="nk-menu-icon"><em class="icon ni ni-activity"></em></span>
|
||||||
|
<span class="nk-menu-text">Aktivitas Login</span>
|
||||||
|
</a>
|
||||||
|
</li><!-- .nk-menu-item -->
|
||||||
@endif
|
@endif
|
||||||
</ul><!-- .nk-menu -->
|
</ul><!-- .nk-menu -->
|
||||||
</div><!-- .nk-sidebar-menu -->
|
</div><!-- .nk-sidebar-menu -->
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
use App\Http\Controllers\Dashboard\IssueManagementController;
|
use App\Http\Controllers\Dashboard\IssueManagementController;
|
||||||
use App\Http\Controllers\Dashboard\JournalistController;
|
use App\Http\Controllers\Dashboard\JournalistController;
|
||||||
use App\Http\Controllers\Dashboard\LocationController;
|
use App\Http\Controllers\Dashboard\LocationController;
|
||||||
|
use App\Http\Controllers\Dashboard\LoginHistoryController;
|
||||||
use App\Http\Controllers\Dashboard\MediaController;
|
use App\Http\Controllers\Dashboard\MediaController;
|
||||||
use App\Http\Controllers\Dashboard\MediaCooperationController;
|
use App\Http\Controllers\Dashboard\MediaCooperationController;
|
||||||
use App\Http\Controllers\Dashboard\MediaMonitoringController;
|
use App\Http\Controllers\Dashboard\MediaMonitoringController;
|
||||||
@ -488,6 +489,17 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::middleware('role:1')->group(function(){
|
||||||
|
Route::prefix('login-activities')->name('login.history.')->group(function(){
|
||||||
|
Route::controller(LoginHistoryController::class)->group(function(){
|
||||||
|
Route::get('/', 'index')->name('index');
|
||||||
|
Route::post('/filter', 'filter')->name('filter');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::get('/data', [DatatableController::class, 'loginHistory'])->name('data');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user