Skip to content

Commit

Permalink
Add user event to Laravel 8
Browse files Browse the repository at this point in the history
  • Loading branch information
estringana committed Feb 7, 2024
1 parent d2d9d2f commit 22b29fe
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ docker-compose.override.yml
tests/Sapi/Roadrunner/rr-*
github-actions-helpers/_build.csproj.DotSettings
.nuke
cookies.txt
27 changes: 27 additions & 0 deletions src/Integrations/Integrations/Laravel/LaravelIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,33 @@ function ($This, $scope, $args) use ($integration) {
}
);

\DDTrace\hook_method(
'Illuminate\Auth\Events\Authenticated',
'__construct',
null,
function ($This, $scope, $args) use ($integration) {
$authClass = 'Illuminate\Contracts\Auth\Authenticatable';
if (
!isset($args[1]) ||
!$args[1] ||
!($args[1] instanceof $authClass)
) {
return;
}

$meta = [];
$user = $args[1];
if (isset($user->name)) {
$meta['name'] = $user->name;
}
if (isset($user->email)) {
$meta['email'] = $user->email;
}

\DDTrace\set_user($user->getAuthIdentifier(), $meta);
}
);

return Integration::LOADED;
}

Expand Down
17 changes: 17 additions & 0 deletions tests/Common/WebFrameworkTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,25 @@ abstract class WebFrameworkTestCase extends IntegrationTestCase
const PORT = 9999;

const ERROR_LOG_NAME = 'phpunit_error.log';
const COOKIE_JAR = 'cookies.txt';

/**
* @var WebServer|null
*/
private static $appServer;
protected $checkWebserverErrors = true;
protected $cookiesFile;

protected function ddSetUp()
{
parent::ddSetUp();
$this->cookiesFile = realpath(dirname(static::getAppIndexScript()) . '/' . static::COOKIE_JAR);
$f = @fopen($this->cookiesFile, "r+");
if ($f !== false) {
ftruncate($f, 0);
fclose($f);
}
}

public static function ddSetUpBeforeClass()
{
Expand Down Expand Up @@ -192,6 +205,10 @@ protected function sendRequest($method, $url, $headers = [], $body = [], $change
curl_setopt($ch, CURLOPT_RETURNTRANSFER, $options[CURLOPT_RETURNTRANSFER]);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $options[CURLOPT_FOLLOWLOCATION]);
curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookiesFile);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiesFile);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($body) ? json_encode($body) : $body);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ public function register(Request $request): RedirectResponse

return redirect(RouteServiceProvider::HOME);
}

public function behind_auth()
{
return "page behind auth";
}
}
1 change: 1 addition & 0 deletions tests/Frameworks/Laravel/Version_8_x/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
Route::get('queue/workOn', [QueueTestController::class, 'workOn']);
Route::get('login/auth', [LoginTestController::class, 'auth']);
Route::get('login/signup', [LoginTestController::class, 'register']);
Route::get('/behind_auth', [LoginTestController::class, 'behind_auth'])->name('behind_auth')->middleware('auth');

// This route has to remain unnamed so we test both route cached and not cached.
Route::get('/unnamed-route', [RouteCachingController::class, 'unnamed']);
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use DDTrace\Tests\Frameworks\Util\Request\GetSpec;
use datadog\appsec\AppsecStatus;

class AutomatedLoginEventsTest extends WebFrameworkTestCase
class LoginEventsTest extends WebFrameworkTestCase
{
protected static function getAppIndexScript()
{
Expand Down Expand Up @@ -39,18 +39,24 @@ public static function ddTearDownAfterClass()

protected function login($email)
{
$this->call(
GetSpec::create('Login success event', '/login/auth?email='.$email)
);
return $this->tracesFromWebRequest(function () use ($email) {
$this->call(
GetSpec::create('Login success event', '/login/auth?email='.$email)
);
});
}

protected function createUser($id, $name, $email) {
//Password is password
$this->connection()->exec("insert into users (id, name, email, password) VALUES (".$id.", '".$name."', '".$email."', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi')");
}

public function testUserLoginSuccessEvent()
{
$id = 1234;
$name = 'someName';
$email = '[email protected]';
//Password is password
$this->connection()->exec("insert into users (id, name, email, password) VALUES (".$id.", '".$name."', '".$email."', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi')");
$this->createUser($id, $name, $email);

$this->login($email);

Expand All @@ -63,6 +69,42 @@ public function testUserLoginSuccessEvent()
$this->assertEquals('track_user_login_success_event', $events[0]['eventName']);
}

public function testLoggedInCalls()
{
$id = 1234;
$name = 'someName';
$email = '[email protected]';
$this->createUser($id, $name, $email);

//First log in
$traces = $this->login($email);

$meta = $traces[0][0]['meta'];
$this->assertEquals($id, $meta['usr.id']);
$this->assertEquals($name, $meta['usr.name']);
$this->assertEquals($email, $meta['usr.email']);

$events = AppsecStatus::getInstance()->getEvents();
$this->assertEquals(1, count($events));
$this->assertEquals($id, $events[0]['userId']);
$this->assertEquals($name, $events[0]['metadata']['name']);
$this->assertEquals($email, $events[0]['metadata']['email']);
$this->assertTrue($events[0]['automated']);
$this->assertEquals('track_user_login_success_event', $events[0]['eventName']);

//Now we are logged in lets do another call
AppsecStatus::getInstance()->setDefaults(); //Remove all events
$traces = $this->tracesFromWebRequest(function () {
$this->call(GetSpec::create('Behind auth', '/behind_auth'));
});

$meta = $traces[0][0]['meta'];
$this->assertEquals(0, count($events)); //Auth does not generate appsec events
$this->assertEquals($id, $meta['usr.id']);
$this->assertEquals($name, $meta['usr.name']);
$this->assertEquals($email, $meta['usr.email']);
}

public function testUserLoginFailureEvent()
{
$email = '[email protected]';
Expand Down

0 comments on commit 22b29fe

Please sign in to comment.