diff --git a/config/telescope.php b/config/telescope.php
index 1fed214ae..086252d4f 100644
--- a/config/telescope.php
+++ b/config/telescope.php
@@ -80,6 +80,19 @@
Authorize::class,
],
+ /*
+ |--------------------------------------------------------------------------
+ | Telescope Avatar Service
+ |--------------------------------------------------------------------------
+ |
+ | This option may be used to control how to show an avatar for authorized
+ | users. 'gravatar' will lookup an avatar by the user's email address.
+ | 'custom' requires registering a callback via Telescope::avatar().
+ |
+ */
+
+ 'avatar_driver' => 'gravatar',
+
/*
|--------------------------------------------------------------------------
| Ignored Paths & Commands
diff --git a/package.json b/package.json
index c2f3f5632..15466b819 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,6 @@
"jquery": "^3.5",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.13",
- "md5": "^2.2.1",
"moment": "^2.10.6",
"moment-timezone": "^0.5.21",
"popper.js": "^1.12",
diff --git a/resources/js/components/PreviewScreen.vue b/resources/js/components/PreviewScreen.vue
index 3a8fb66bb..a8a767d19 100644
--- a/resources/js/components/PreviewScreen.vue
+++ b/resources/js/components/PreviewScreen.vue
@@ -63,13 +63,6 @@
command() {
return _.find(this.batch, {type: 'command'})
},
-
- gravatarUrl() {
- if (this.entry.content.user.email) {
- const md5 = require('md5')
- return 'https://www.gravatar.com/avatar/' + md5(this.entry.content.user.email.toLowerCase()) + '?s=200'
- }
- }
},
@@ -242,7 +235,7 @@
Name |
-
+
{{entry.content.user.name}}
|
diff --git a/src/Avatar.php b/src/Avatar.php
new file mode 100644
index 000000000..a6c0a8d59
--- /dev/null
+++ b/src/Avatar.php
@@ -0,0 +1,63 @@
+familyHash = $familyHash;
}
+ /**
+ * Set the URL to the entry user's avatar.
+ *
+ * @return $this
+ */
+ public function generateAvatar()
+ {
+ $this->avatar = Avatar::url($this->content['user'] ?? []);
+
+ return $this;
+ }
+
/**
* Get the array representation of the entry.
*
@@ -93,7 +112,7 @@ public function __construct($id, $sequence, string $batchId, string $type, ?stri
*/
public function jsonSerialize()
{
- return [
+ return collect([
'id' => $this->id,
'sequence' => $this->sequence,
'batch_id' => $this->batchId,
@@ -102,6 +121,14 @@ public function jsonSerialize()
'tags' => $this->tags,
'family_hash' => $this->familyHash,
'created_at' => $this->createdAt->toDateTimeString(),
- ];
+ ])->when($this->avatar, function ($items) {
+ return $items->mergeRecursive([
+ 'content' => [
+ 'user' => [
+ 'avatar' => $this->avatar,
+ ],
+ ],
+ ]);
+ })->all();
}
}
diff --git a/src/Http/Controllers/EntryController.php b/src/Http/Controllers/EntryController.php
index 32dc09e71..84fd53519 100644
--- a/src/Http/Controllers/EntryController.php
+++ b/src/Http/Controllers/EntryController.php
@@ -50,7 +50,7 @@ public function index(Request $request, EntriesRepository $storage)
*/
public function show(EntriesRepository $storage, $id)
{
- $entry = $storage->find($id);
+ $entry = $storage->find($id)->generateAvatar();
return response()->json([
'entry' => $entry,
diff --git a/src/Telescope.php b/src/Telescope.php
index 05aaa3328..0d715c9b3 100644
--- a/src/Telescope.php
+++ b/src/Telescope.php
@@ -684,6 +684,18 @@ public static function night()
return new static;
}
+ /**
+ * Register the Telescope user avatar callback.
+ *
+ * @param \Closure $callback
+ */
+ public static function avatar(Closure $callback)
+ {
+ if (config('telescope.avatar_driver') === 'custom') {
+ Avatar::register($callback);
+ }
+ }
+
/**
* Get the default JavaScript variables for Telescope.
*
diff --git a/stubs/TelescopeServiceProvider.stub b/stubs/TelescopeServiceProvider.stub
index a9ddad224..f444a92bb 100644
--- a/stubs/TelescopeServiceProvider.stub
+++ b/stubs/TelescopeServiceProvider.stub
@@ -31,6 +31,10 @@ class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
$entry->isScheduledTask() ||
$entry->hasMonitoredTag();
});
+
+ Telescope::avatar(function ($id, $email) {
+ //
+ });
}
/**
diff --git a/tests/Http/AvatarTest.php b/tests/Http/AvatarTest.php
new file mode 100644
index 000000000..e332d4ec9
--- /dev/null
+++ b/tests/Http/AvatarTest.php
@@ -0,0 +1,196 @@
+withoutMiddleware(Authorize::class);
+ }
+
+ protected function getEnvironmentSetUp($app)
+ {
+ parent::getEnvironmentSetUp($app);
+
+ $app->get('config')->set('logging.default', 'syslog');
+
+ $app->get('config')->set('telescope.watchers', [
+ LogWatcher::class => true,
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function it_can_register_custom_avatar_path()
+ {
+ $user = null;
+
+ Telescope::withoutRecording(function () use (&$user) {
+ $this->loadLaravelMigrations();
+
+ $user = UserEloquent::create([
+ 'id' => 1,
+ 'name' => 'Telescope',
+ 'email' => 'telescope@laravel.com',
+ 'password' => 'secret',
+ ]);
+ });
+
+ $this->app->get('config')->set('telescope.avatar_driver', 'custom');
+
+ Telescope::avatar(function ($id) {
+ return "/images/{$id}.jpg";
+ });
+
+ $this->actingAs($user);
+
+ $this->app->get(LoggerInterface::class)->error('Avatar path will be generated.', [
+ 'exception' => 'Some error message',
+ ]);
+
+ $entry = $this->loadTelescopeEntries()->first();
+
+ $this->get("/telescope/telescope-api/logs/{$entry->uuid}")
+ ->assertOk()
+ ->assertJson([
+ 'entry' => [
+ 'content' => [
+ 'user' => [
+ 'avatar' => '/images/1.jpg',
+ ],
+ ],
+ ],
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function it_will_not_register_custom_avatar_path_when_not_configured()
+ {
+ $user = null;
+
+ Telescope::withoutRecording(function () use (&$user) {
+ $this->loadLaravelMigrations();
+
+ $user = UserEloquent::create([
+ 'id' => 1,
+ 'name' => 'Telescope',
+ 'email' => 'telescope@laravel.com',
+ 'password' => 'secret',
+ ]);
+ });
+
+ Telescope::avatar(function ($id) {
+ return "/images/{$id}.jpg";
+ });
+
+ $this->actingAs($user);
+
+ $this->app->get(LoggerInterface::class)->error('Avatar path will default to Gravatar.', [
+ 'exception' => 'Some error message',
+ ]);
+
+ $entry = $this->loadTelescopeEntries()->first();
+
+ $this->get("/telescope/telescope-api/logs/{$entry->uuid}")
+ ->assertOk()
+ ->assertJson([
+ 'entry' => [
+ 'content' => [
+ 'user' => [
+ 'avatar' => 'https://www.gravatar.com/avatar/dac001a0dfeebe3b320cefa9f3a7d813?s=200',
+ ],
+ ],
+ ],
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function it_will_not_set_avatar_path_when_the_configuration_is_empty()
+ {
+ $user = null;
+
+ Telescope::withoutRecording(function () use (&$user) {
+ $this->loadLaravelMigrations();
+
+ $user = UserEloquent::create([
+ 'id' => 1,
+ 'name' => 'Telescope',
+ 'email' => 'telescope@laravel.com',
+ 'password' => 'secret',
+ ]);
+ });
+
+ $this->app->get('config')->set('telescope.avatar_driver', '');
+
+ Telescope::avatar(function ($id) {
+ return "/images/{$id}.jpg";
+ });
+
+ $this->actingAs($user);
+
+ $this->app->get(LoggerInterface::class)->error('Avatar path will not be generated.', [
+ 'exception' => 'Some error message',
+ ]);
+
+ $entry = $this->loadTelescopeEntries()->first();
+
+ $json = $this->get("/telescope/telescope-api/logs/{$entry->uuid}")
+ ->assertOk()
+ ->json();
+
+ $this->assertArrayNotHasKey('avatar', $json['entry']['content']['user']);
+ }
+}
+
+class UserEloquent extends Model implements Authenticatable
+{
+ protected $table = 'users';
+
+ protected $guarded = [];
+
+ public function getAuthIdentifierName()
+ {
+ return $this->email;
+ }
+
+ public function getAuthIdentifier()
+ {
+ return $this->id;
+ }
+
+ public function getAuthPassword()
+ {
+ return $this->password;
+ }
+
+ public function getRememberToken()
+ {
+ return 'i-am-telescope';
+ }
+
+ public function setRememberToken($value)
+ {
+ //
+ }
+
+ public function getRememberTokenName()
+ {
+ //
+ }
+}