Skip to content

Commit cf33143

Browse files
committed
Merge branch 'develop'
2 parents 4a4a5d8 + c61d786 commit cf33143

30 files changed

+1552
-1099
lines changed

Diff for: .gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
.env
88
.env.docker
99
.phpunit.result.cache
10-
/.phpunit.cache
11-
/.phpunit.cache/test-results
10+
.phpunit.cache/*
1211
Homestead.json
1312
Homestead.yaml
1413
npm-debug.log
1514
yarn-error.log
1615
clover.xml
1716
test-html
17+
.phpunit.cache/test-results

Diff for: CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44
----
55

6+
## [v2.21.0] - 2025-02-19
7+
8+
### Fixed
9+
- A few small issues
10+
611
## [v2.20.2] - 2024-09-12
712

813
### Added

Diff for: app/Http/Controllers/Auth/LoginController.php

+2
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@ public function __construct()
4747
public function authenticated()
4848
{
4949
activity('login');
50+
51+
auth()->user()->deviceLogin();
5052
}
5153
}

Diff for: app/Http/Controllers/DashboardController.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public function get()
2121
return str_replace('public', 'storage', $file);
2222
});
2323

24-
return view('dashboard', compact('images'));
24+
$chart = app(\App\View\Charts\CanChart::class)->html();
25+
26+
return view('dashboard', compact('images', 'chart'));
2527
}
2628
}

Diff for: app/Http/Controllers/User/LogoutSessionsController.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ public function __invoke(Request $request)
1212
try {
1313
auth()->logoutOtherDevices($request->password);
1414

15-
return redirect()->route('user.settings')->withMessage('Logged out of other devices.');
15+
auth()->user()->deviceLogout($request);
16+
17+
return redirect()->route('user.security')->withMessage('Logged out of other devices.');
1618
} catch (\Throwable $th) {
17-
return redirect()->route('user.settings')->withErrors($th->getMessage());
19+
return redirect()->route('user.security')->withErrors($th->getMessage());
1820
}
1921
}
2022
}

Diff for: app/Models/Concerns/HasDevices.php

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace App\Models\Concerns;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Support\Carbon;
7+
use Illuminate\Support\Facades\DB;
8+
use hisorange\BrowserDetect\Parser;
9+
10+
trait HasDevices
11+
{
12+
public function deviceLogin()
13+
{
14+
DB::table('devices')->updateOrInsert([
15+
'user_id' => auth()->user()->id,
16+
'agent' => request()->userAgent(),
17+
'ip_address' => request()->ip(),
18+
], [
19+
'session_id' => request()->session()->getId(),
20+
'last_login' => now(),
21+
]);
22+
}
23+
24+
public function deviceLogout($request)
25+
{
26+
DB::table('devices')
27+
->whereIn('id', auth()->user()->devices()->where('session_id', '!=', $request->session()->getId())->pluck('id'))
28+
->delete();
29+
}
30+
31+
public function devices()
32+
{
33+
return DB::table('devices')->where('user_id', $this->id)->get();
34+
}
35+
36+
public function getDevices()
37+
{
38+
$sessions = DB::table('devices')->where('user_id', $this->id)->orderByDesc('last_login')->get();
39+
40+
return collect($sessions)->map(function ($session) {
41+
return (object) [
42+
'agent' => $this->createAgent($session),
43+
'ip_address' => $session->ip_address,
44+
'is_current_device' => $session->session_id === request()->session()->getId(),
45+
'last_active' => Carbon::parse($session->last_login)->diffForHumans(),
46+
];
47+
});
48+
}
49+
50+
protected function createAgent($session)
51+
{
52+
$request = (new Request);
53+
$request->headers->set('User-Agent', $session->agent);
54+
55+
return new Parser(null, $request, []);
56+
}
57+
}

Diff for: app/Models/Concerns/HasSessions.php

-35
This file was deleted.

Diff for: app/Models/User.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use App\Models\Concerns\HasCachedValues;
99
use App\Models\Concerns\HasPermissions;
1010
use App\Models\Concerns\HasRoles;
11-
use App\Models\Concerns\HasSessions;
11+
use App\Models\Concerns\HasDevices;
1212
use App\Models\Concerns\HasSubscription;
1313
use App\Models\Concerns\HasTeams;
1414
use App\Models\Concerns\HasTwoFactor;
@@ -38,7 +38,7 @@ class User extends Authenticatable implements MustVerifyEmail
3838
use HasJavascriptData;
3939
use HasPermissions;
4040
use HasRoles;
41-
use HasSessions;
41+
use HasDevices;
4242
use HasSubscription;
4343
use HasTeams;
4444
use HasTwoFactor;

Diff for: app/Providers/AppServiceProvider.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
namespace App\Providers;
44

55
use App\Models\User;
6+
use Illuminate\Support\Str;
67
use Dedoc\Scramble\Scramble;
7-
use Illuminate\Pagination\Paginator;
8+
use Laravel\Cashier\Cashier;
89
use Illuminate\Routing\Route;
9-
use Illuminate\Support\Facades\Blade;
10+
use Illuminate\Support\Collection;
1011
use Illuminate\Support\Facades\URL;
12+
use Illuminate\Pagination\Paginator;
13+
use Illuminate\Support\Facades\Blade;
1114
use Illuminate\Support\ServiceProvider;
12-
use Illuminate\Support\Str;
1315
use Illuminate\Validation\Rules\Password;
14-
use Laravel\Cashier\Cashier;
1516

1617
class AppServiceProvider extends ServiceProvider
1718
{

Diff for: app/View/Charts/CanChart.php

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace App\View\Charts;
4+
5+
use Grafite\Charts\Builder\GeoChart;
6+
use Illuminate\Support\Facades\Http;
7+
8+
class CanChart extends GeoChart
9+
{
10+
public $height = 750;
11+
12+
public $showGraticule = false;
13+
14+
public $id = 'mappy';
15+
16+
public $borderWidth = 0;
17+
18+
// public $projection = 'albersUsa';
19+
// public $projection = 'mercator';
20+
// public $projection = 'naturalEarth1';
21+
// public $projection = 'equalEarth';
22+
// public $projection = 'equirectangular';
23+
// public $projection = 'conicConformal';
24+
25+
// public $projection = 'albers';
26+
// public $projection = 'conicEqualArea';
27+
// public $projection = 'conicConformal';
28+
// public $projection = 'conicEquidistant';
29+
public $projection = 'geoMercator';
30+
// public $projection = 'transverseMercator';
31+
// public $projection = 'stereographic';
32+
// public $projection = 'orthographic';
33+
// public $projection = 'gnomonic';
34+
// public $projection = 'azimuthalEquidistant';
35+
// public $projection = 'azimuthalEqualArea';
36+
37+
public $displayAxes = false;
38+
39+
/**
40+
* Initializes the chart.
41+
*
42+
* @return void
43+
*/
44+
public function collectData()
45+
{
46+
$data = Http::get('https://gist.githubusercontent.com/Brideau/2391df60938462571ca9/raw/f5a1f3b47ff671eaf2fb7e7b798bacfc6962606a/canadaprov.json')->json();
47+
48+
return $data['features'];
49+
50+
return $this->parseGeoData($data);
51+
}
52+
53+
public function labels()
54+
{
55+
return collect($this->data)->map(function ($country) {
56+
return $country['properties']['name'];
57+
});
58+
59+
}
60+
61+
public function datasets()
62+
{
63+
$data = collect($this->data)->map(function ($country) {
64+
return [
65+
'feature' => $country,
66+
'value' => rand(1, 100),
67+
];
68+
});
69+
70+
$dataset = $this->makeDataset('Words', $data)
71+
->options([
72+
'outline' => $this->data,
73+
'showOutline' => true,
74+
]);
75+
76+
return [
77+
$dataset,
78+
];
79+
}
80+
}

Diff for: app/View/Charts/GlobalChart.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace App\View\Charts;
4+
5+
use Grafite\Charts\Builder\GeoChart;
6+
use Illuminate\Support\Facades\Http;
7+
8+
class GlobalChart extends GeoChart
9+
{
10+
public $height = 750;
11+
12+
public $id = 'mappy';
13+
14+
public $borderWidth = 0;
15+
16+
public $displayAxes = false;
17+
18+
/**
19+
* Initializes the chart.
20+
*
21+
* @return void
22+
*/
23+
public function collectData()
24+
{
25+
$data = json_encode(Http::get('https://unpkg.com/world-atlas/countries-50m.json')->json());
26+
27+
return $this->parseGeoData($data);
28+
}
29+
30+
public function labels()
31+
{
32+
return collect($this->data['countries']->features)->map(function ($country) {
33+
return $country->properties->name;
34+
});
35+
36+
}
37+
38+
public function datasets()
39+
{
40+
$data = collect($this->data['countries']->features)->map(function ($country) {
41+
return [
42+
'feature' => $country,
43+
'value' => rand(1, 100),
44+
];
45+
});
46+
47+
$dataset = $this->makeDataset('Words', $data)
48+
->options([
49+
'borderWidth' => 0,
50+
]);
51+
52+
return [
53+
$dataset,
54+
];
55+
}
56+
}

Diff for: app/View/Charts/UsChart.php

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace App\View\Charts;
4+
5+
use Grafite\Charts\Builder\GeoChart;
6+
use Illuminate\Support\Facades\Http;
7+
8+
class UsChart extends GeoChart
9+
{
10+
public $height = 750;
11+
12+
public $id = 'mappy';
13+
14+
public $borderWidth = 0;
15+
16+
public $projection = 'albersUsa';
17+
18+
public $displayAxes = false;
19+
20+
/**
21+
* Initializes the chart.
22+
*
23+
* @return void
24+
*/
25+
public function collectData()
26+
{
27+
$data = json_encode(Http::get('https://unpkg.com/us-atlas/states-10m.json')->json());
28+
29+
return $this->parseGeoData($data);
30+
}
31+
32+
public function labels()
33+
{
34+
return collect($this->data['states']->features)->map(function ($country) {
35+
return $country->properties->name;
36+
});
37+
38+
}
39+
40+
public function datasets()
41+
{
42+
$data = collect($this->data['states']->features)->map(function ($country) {
43+
return [
44+
'feature' => $country,
45+
'value' => rand(1, 100),
46+
];
47+
});
48+
49+
$nation = $this->data['nation']->features[0];
50+
51+
$dataset = $this->makeDataset('Words', $data)
52+
->options([
53+
'outline' => $nation,
54+
'showOutline' => true,
55+
]);
56+
57+
return [
58+
$dataset,
59+
];
60+
}
61+
}

0 commit comments

Comments
 (0)