Skip to content

Commit 0768c79

Browse files
author
Sam Stevens
committed
implement custom callbacks and refactor the user setting code into a callback
1 parent 73a2daf commit 0768c79

File tree

13 files changed

+361
-94
lines changed

13 files changed

+361
-94
lines changed

BugsnagBundle.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Bugsnag\BugsnagBundle;
44

5+
use Bugsnag\BugsnagBundle\DependencyInjection\Compiler\CallbackRegisteringPass;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
57
use Symfony\Component\HttpKernel\Bundle\Bundle;
68

79
class BugsnagBundle extends Bundle
@@ -12,4 +14,16 @@ class BugsnagBundle extends Bundle
1214
* @return string
1315
*/
1416
const VERSION = '1.0.0';
17+
18+
/**
19+
* {@inheritdoc}
20+
*
21+
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
22+
*
23+
* @return void
24+
*/
25+
public function build(ContainerBuilder $container)
26+
{
27+
$container->addCompilerPass(new CallbackRegisteringPass());
28+
}
1529
}

Callbacks/UserSettingCallback.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
namespace Bugsnag\BugsnagBundle\Callbacks;
4+
5+
use Bugsnag\Report;
6+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
7+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
8+
use Symfony\Component\Security\Core\User\UserInterface;
9+
10+
class UserSettingCallback
11+
{
12+
/**
13+
* The token resolver.
14+
*
15+
* @var \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface|null
16+
*/
17+
protected $tokens;
18+
19+
/**
20+
* The auth checker.
21+
*
22+
* @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|null
23+
*/
24+
protected $checker;
25+
26+
/**
27+
* @var bool
28+
*/
29+
protected $setUser;
30+
31+
/**
32+
* @param null|\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokens
33+
* @param null|\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface $checker
34+
* @param bool $setUser
35+
*/
36+
public function __construct(
37+
TokenStorageInterface $tokens = null,
38+
AuthorizationCheckerInterface $checker = null,
39+
$setUser = true
40+
) {
41+
$this->tokens = $tokens;
42+
$this->checker = $checker;
43+
$this->setUser = $setUser;
44+
}
45+
46+
/**
47+
* @param \Bugsnag\Report $report
48+
*
49+
* @return void
50+
*/
51+
public function registerCallback(Report $report)
52+
{
53+
// If told to not set the user, or the security services were not passed in
54+
// (not registered in the container), then exit early
55+
if (!$this->setUser || is_null($this->tokens) || is_null($this->checker)) {
56+
return;
57+
}
58+
59+
$token = $this->tokens->getToken();
60+
61+
if (!$token || !$this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
62+
return;
63+
}
64+
65+
$user = $token->getUser();
66+
67+
if ($user instanceof UserInterface) {
68+
$bugsnagUser = ['id' => $user->getUsername()];
69+
} else {
70+
$bugsnagUser = ['id' => (string) $user];
71+
}
72+
73+
$report->setUser($bugsnagUser);
74+
}
75+
}

DependencyInjection/ClientFactory.php

Lines changed: 16 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@
44

55
use Bugsnag\BugsnagBundle\BugsnagBundle;
66
use Bugsnag\BugsnagBundle\Request\SymfonyResolver;
7-
use Bugsnag\Callbacks\CustomUser;
87
use Bugsnag\Client;
98
use Bugsnag\Configuration as Config;
10-
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
11-
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
12-
use Symfony\Component\Security\Core\User\UserInterface;
139

1410
class ClientFactory
1511
{
@@ -20,20 +16,6 @@ class ClientFactory
2016
*/
2117
protected $resolver;
2218

23-
/**
24-
* The token resolver.
25-
*
26-
* @var \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface|null
27-
*/
28-
protected $tokens;
29-
30-
/**
31-
* The auth checker.
32-
*
33-
* @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|null
34-
*/
35-
protected $checker;
36-
3719
/**
3820
* The api key.
3921
*
@@ -55,13 +37,6 @@ class ClientFactory
5537
*/
5638
protected $callbacks;
5739

58-
/**
59-
* User detection enabled.
60-
*
61-
* @var bool
62-
*/
63-
protected $user;
64-
6540
/**
6641
* The type.
6742
*
@@ -149,36 +124,30 @@ class ClientFactory
149124
/**
150125
* Create a new client factory instance.
151126
*
152-
* @param \Bugsnag\BugsnagBundle\Request\SymfonyResolver $resolver
153-
* @param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface|null $tokens
154-
* @param \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|null $checker
155-
* @param string|null $key
156-
* @param string|null $endpoint
157-
* @param bool $callbacks
158-
* @param bool $user
159-
* @param string|null $type
160-
* @param string|null $version
161-
* @param bool $batch
162-
* @param string|null $hostname
163-
* @param bool $code
164-
* @param string|null $strip
165-
* @param string|null $project
166-
* @param string|null $root
167-
* @param string|null $env
168-
* @param string|null $stage
169-
* @param string[]|null $stages
170-
* @param string[]|null $filters
127+
* @param \Bugsnag\BugsnagBundle\Request\SymfonyResolver $resolver
128+
* @param string|null $key
129+
* @param string|null $endpoint
130+
* @param bool $callbacks
131+
* @param string|null $type
132+
* @param string|null $version
133+
* @param bool $batch
134+
* @param string|null $hostname
135+
* @param bool $code
136+
* @param string|null $strip
137+
* @param string|null $project
138+
* @param string|null $root
139+
* @param string|null $env
140+
* @param string|null $stage
141+
* @param string[]|null $stages
142+
* @param string[]|null $filters
171143
*
172144
* @return void
173145
*/
174146
public function __construct(
175147
SymfonyResolver $resolver,
176-
TokenStorageInterface $tokens = null,
177-
AuthorizationCheckerInterface $checker = null,
178148
$key = null,
179149
$endpoint = null,
180150
$callbacks = true,
181-
$user = true,
182151
$type = null,
183152
$version = true,
184153
$batch = null,
@@ -193,12 +162,9 @@ public function __construct(
193162
array $filters = null
194163
) {
195164
$this->resolver = $resolver;
196-
$this->tokens = $tokens;
197-
$this->checker = $checker;
198165
$this->key = $key;
199166
$this->endpoint = $endpoint;
200167
$this->callbacks = $callbacks;
201-
$this->user = $user;
202168
$this->type = $type;
203169
$this->version = $version;
204170
$this->batch = $batch;
@@ -228,10 +194,6 @@ public function make()
228194
$client->registerDefaultCallbacks();
229195
}
230196

231-
if ($this->tokens && $this->checker && $this->user) {
232-
$this->setupUserDetection($client, $this->tokens, $this->checker);
233-
}
234-
235197
$this->setupPaths($client, $this->strip, $this->project, $this->root);
236198

237199
$client->setReleaseStage($this->stage ?: ($this->env === 'prod' ? 'production' : $this->env));
@@ -261,34 +223,6 @@ public function make()
261223
return $client;
262224
}
263225

264-
/**
265-
* Setup user detection.
266-
*
267-
* @param \Bugsnag\Client $client
268-
* @param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokens
269-
* @param \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface $checker
270-
*
271-
* @return void
272-
*/
273-
protected function setupUserDetection(Client $client, TokenStorageInterface $tokens, AuthorizationCheckerInterface $checker)
274-
{
275-
$client->registerCallback(new CustomUser(function () use ($tokens, $checker) {
276-
$token = $tokens->getToken();
277-
278-
if (!$token || !$checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
279-
return;
280-
}
281-
282-
$user = $token->getUser();
283-
284-
if ($user instanceof UserInterface) {
285-
return ['id' => $user->getUsername()];
286-
}
287-
288-
return ['id' => (string) $user];
289-
}));
290-
}
291-
292226
/**
293227
* Setup the client paths.
294228
*
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Bugsnag\BugsnagBundle\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
use Symfony\Component\DependencyInjection\Reference;
8+
9+
class CallbackRegisteringPass implements CompilerPassInterface
10+
{
11+
const BUGSNAG_SERVICE_NAME = 'bugsnag';
12+
const TAG_NAME = 'bugsnag.callback';
13+
14+
/**
15+
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
16+
*
17+
* @return void
18+
*/
19+
public function process(ContainerBuilder $container)
20+
{
21+
if (!$container->has(self::BUGSNAG_SERVICE_NAME)) {
22+
return;
23+
}
24+
25+
// Get the Bugsnag service
26+
$bugsnag = $container->findDefinition(self::BUGSNAG_SERVICE_NAME);
27+
28+
// Get all services tagged as a callback
29+
$callbackServices = $container->findTaggedServiceIds(self::TAG_NAME);
30+
31+
// Register each callback on the bugsnag service
32+
foreach ($callbackServices as $id => $tags) {
33+
foreach ($tags as $attributes) {
34+
// Get the method name to call on the service from the tag definition,
35+
// defaulting to registerCallback
36+
$method = isset($attributes['method']) ? $attributes['method'] : 'registerCallback';
37+
$bugsnag->addMethodCall('registerCallback', [[new Reference($id), $method]]);
38+
}
39+
}
40+
}
41+
}

Resources/config/services.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@ services:
66
class: '%bugsnag.factory%'
77
arguments:
88
- '@bugsnag.resolver'
9-
- '@?security.token_storage'
10-
- '@?security.authorization_checker'
119
- '%bugsnag.api_key%'
1210
- '%bugsnag.endpoint%'
1311
- '%bugsnag.callbacks%'
14-
- '%bugsnag.user%'
1512
- '%bugsnag.app_type%'
1613
- '%bugsnag.app_version%'
1714
- '%bugsnag.batch_sending%'
@@ -39,3 +36,12 @@ services:
3936
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 256 }
4037
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 128 }
4138
- { name: kernel.event_listener, event: console.exception, method: onConsoleException, priority: 128 }
39+
40+
bugsnag.callbacks.user_setting:
41+
class: Bugsnag\BugsnagBundle\Callbacks\UserSettingCallback
42+
arguments:
43+
- '@?security.token_storage'
44+
- '@?security.authorization_checker'
45+
- '%bugsnag.user%'
46+
tags:
47+
- { name: 'bugsnag.callback' }

0 commit comments

Comments
 (0)