Skip to content

Commit d9b246f

Browse files
Add last login ts to user
1 parent c108a4d commit d9b246f

17 files changed

+213
-174
lines changed

database/01-schema.sql

+130-119
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE user
2+
ADD last_login_ts TIMESTAMP NULL COMMENT 'Last login time' AFTER update_ts;

public/index.php

+17-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Reconmap\Services\ApplicationContainer;
1111
use Reconmap\Services\Logging\LoggingConfigurator;
1212
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
13+
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1314
use Symfony\Component\HttpFoundation\Response;
1415

1516
$configFilePath = $applicationDir . '/config.json';
@@ -20,20 +21,31 @@
2021
exit;
2122
}
2223

23-
$applicationConfig = ApplicationConfig::load($configFilePath);
24-
$applicationConfig->setAppDir($applicationDir);
24+
$config = ApplicationConfig::load($configFilePath);
25+
$config->setAppDir($applicationDir);
2526

2627
$logger = new Logger('http');
27-
$loggingConfigurator = new LoggingConfigurator($logger, $applicationConfig);
28+
$loggingConfigurator = new LoggingConfigurator($logger, $config);
2829
$loggingConfigurator->configure();
2930

30-
$container = new ApplicationContainer($applicationConfig, $logger);
31+
$file = $config->getAppDir() . '/data/attachments/container.php';
32+
if (file_exists($file)) {
33+
require $file;
34+
$container = new CachedApplicationContainer();
35+
} else {
36+
$container = new ApplicationContainer();
37+
$container->compile();
38+
39+
$dumper = new PhpDumper($container);
40+
file_put_contents($file, $dumper->dump(['class' => 'CachedApplicationContainer']));
41+
}
42+
ApplicationContainer::initialise($container, $config, $logger);
3143

3244
$request = GuzzleHttp\Psr7\ServerRequest::fromGlobals();
3345
$container->set(Psr\Http\Message\ServerRequestInterface::class, $request);
3446

3547
$router = new ApiRouter();
36-
$router->mapRoutes($container, $applicationConfig);
48+
$router->mapRoutes($container, $config);
3749

3850
$response = $router->dispatch($request);
3951

src/AppVersion.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
class AppVersion
66
{
7-
public const Current = 2_02_00;
7+
public const int Current = 2_10_00;
88

99
/**
1010
* @param int $numeric

src/Cli/Commands/EmailProcessorCommand.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Reconmap\Cli\Commands;
44

5-
use Reconmap\QueueProcessor;
5+
use Reconmap\Services\QueueProcessor;
66
use Reconmap\Tasks\EmailTaskProcessor;
77
use Symfony\Component\Console\Command\Command;
88
use Symfony\Component\Console\Input\InputInterface;

src/Cli/Commands/TaskProcessorCommand.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
namespace Reconmap\Cli\Commands;
44

5-
use Reconmap\QueueProcessor;
5+
use Reconmap\Services\QueueProcessor;
66
use Reconmap\Tasks\TaskResultProcessor;
77
use Symfony\Component\Console\Command\Command;
88
use Symfony\Component\Console\Input\InputInterface;
99
use Symfony\Component\Console\Output\OutputInterface;
1010

1111
class TaskProcessorCommand extends Command
1212
{
13-
public function __construct(private QueueProcessor $queueProcessor,
14-
private TaskResultProcessor $taskResultProcessor)
13+
public function __construct(private readonly QueueProcessor $queueProcessor,
14+
private readonly TaskResultProcessor $taskResultProcessor)
1515
{
1616
parent::__construct();
1717
}

src/Cli/app.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
unset($argv[array_search('--use-test-database', $argv)]);
3636
}
3737

38-
$container = new ApplicationContainer($config, $logger);
38+
$container = new ApplicationContainer();
39+
$container->compile();
40+
ApplicationContainer::initialise($container, $config, $logger);
3941

4042
$app = new Application('Reconmap internal CLI');
4143
$app->add($container->get(DatabaseMigratorCommand::class));

src/Controllers/Auth/LoginController.php

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ protected function process(ApplicationRequest $request): ResponseInterface
5151
$cookie = new Cookie('reconmap-static', $staticToken, time() + (3600 * 24), path: '/', secure: false, httpOnly: false);
5252
$response->headers->setCookie($cookie);
5353

54+
$this->userRepository->updateLastLoginTime($requestUser->id);
55+
5456
$psr17Factory = new HttpFactory();
5557
$psrHttpFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
5658

src/Controllers/System/ExportDataController.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use GuzzleHttp\Psr7\Response;
66
use GuzzleHttp\Psr7\Utils;
7+
use Psr\Container\ContainerInterface;
78
use Psr\Http\Message\ResponseInterface;
89
use Psr\Http\Message\ServerRequestInterface;
910
use Reconmap\Controllers\Controller;
@@ -14,7 +15,7 @@
1415

1516
class ExportDataController extends Controller
1617
{
17-
public function __construct(private readonly AuditLogService $auditLogService)
18+
public function __construct(private readonly AuditLogService $auditLogService, private readonly ContainerInterface $container)
1819
{
1920
}
2021

src/Controllers/System/ImportDataController.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Reconmap\Controllers\System;
44

5+
use Psr\Container\ContainerInterface;
56
use Psr\Http\Message\ServerRequestInterface;
67
use Psr\Http\Message\UploadedFileInterface;
78
use Reconmap\Controllers\Controller;
@@ -12,7 +13,7 @@
1213

1314
class ImportDataController extends Controller
1415
{
15-
public function __construct(private readonly AuditLogService $auditLogService)
16+
public function __construct(private readonly AuditLogService $auditLogService, private readonly ContainerInterface $container)
1617
{
1718
}
1819

src/Models/Project.php

+13-14
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@
55
/**
66
* Autogenerated file, do not edit manually. @see https://github.com/reconmap/model-definitions
77
*/
8-
class Project
9-
{
8+
class Project {
109

11-
public ?int $id = null;
12-
public ?int $creator_uid;
13-
public ?int $client_id;
14-
public ?string $name;
15-
public ?string $description;
16-
public ?string $visibility = 'public';
17-
public bool $is_template = false;
18-
public ?int $category_id;
19-
public ?string $engagement_start_date;
20-
public ?string $engagement_end_date;
21-
public ?string $external_id;
22-
public ?string $vulnerability_metrics;
10+
public ?int $id = null;
11+
public ?int $creator_uid;
12+
public ?int $client_id;
13+
public ?string $name;
14+
public ?string $description;
15+
public ?string $visibility = 'public';
16+
public bool $is_template = false;
17+
public ?int $category_id;
18+
public ?string $engagement_start_date;
19+
public ?string $engagement_end_date;
20+
public ?string $external_id;
21+
public ?string $vulnerability_metrics;
2322
}

src/Models/User.php

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
class User {
99

1010
public ?int $id;
11+
public ?string $insert_ts;
12+
public ?string $update_ts;
13+
public ?string $last_login_ts;
1114
public ?string $subject_id;
1215
public ?bool $active = true;
1316
public string $full_name;

src/Repositories/UserRepository.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class UserRepository extends MysqlRepository
1010
{
11-
public const UPDATABLE_COLUMNS_TYPES = [
11+
public const array UPDATABLE_COLUMNS_TYPES = [
1212
'active' => 'i',
1313
'full_name' => 's',
1414
'short_bio' => 's',
@@ -61,7 +61,7 @@ public function findBySubjectId(string $subjectId): ?array
6161
protected function getBaseSelectQueryBuilder(): SelectQueryBuilder
6262
{
6363
$queryBuilder = new SelectQueryBuilder('user u');
64-
$queryBuilder->setColumns('u.id, u.insert_ts, u.update_ts, u.subject_id, u.active, u.full_name, u.short_bio, u.username, u.email, u.role, u.timezone, u.preferences');
64+
$queryBuilder->setColumns('u.id, u.insert_ts, u.update_ts, u.last_login_ts, u.subject_id, u.active, u.full_name, u.short_bio, u.username, u.email, u.role, u.timezone, u.preferences');
6565
return $queryBuilder;
6666
}
6767

@@ -126,4 +126,10 @@ public function updateById(int $id, array $newColumnValues): bool
126126
{
127127
return $this->updateByTableId('user', $id, $newColumnValues);
128128
}
129+
130+
public function updateLastLoginTime(int $userId): bool
131+
{
132+
$stmt = $this->db->prepare('UPDATE user SET last_login_ts = NOW() WHERE id = ?');
133+
return $stmt->execute([$userId]);
134+
}
129135
}

src/Services/ApplicationContainer.php

+21-22
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,23 @@
33
namespace Reconmap\Services;
44

55
use Monolog\Logger;
6+
use Psr\Container\ContainerInterface;
67
use Psr\Http\Message\ServerRequestInterface;
78
use Reconmap\CommandOutputParsers\ProcessorFactory;
89
use Reconmap\Database\ConnectionFactory;
910
use Symfony\Component\Config\FileLocator;
1011
use Symfony\Component\DependencyInjection\ContainerBuilder;
1112
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
1213
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
14+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
1315
use Symfony\Component\Filesystem\Filesystem;
1416

1517
class ApplicationContainer extends ContainerBuilder
1618
{
17-
public function __construct(ApplicationConfig $config, Logger $logger)
19+
public function __construct(?ParameterBagInterface $parameterBag = null)
1820
{
19-
parent::__construct();
21+
parent::__construct($parameterBag);
2022

21-
$this->initialise($config, $logger);
22-
}
23-
24-
public function initialise(ApplicationConfig $config, Logger $logger)
25-
{
2623
$loader = new PhpFileLoader($this, new FileLocator(__DIR__));
2724

2825
$instanceof = [];
@@ -31,11 +28,15 @@ public function initialise(ApplicationConfig $config, Logger $logger)
3128
$this->configure($configurator);
3229

3330
$this->register(Filesystem::class);
34-
$this->compile();
35-
$this->set(ApplicationConfig::class, $config);
36-
$this->set(\mysqli::class, ConnectionFactory::createConnection($config));
37-
$this->set(Logger::class, $logger);
38-
$this->set(ProcessorFactory::class, new ProcessorFactory());
31+
}
32+
33+
public static function initialise(ContainerInterface $container, ApplicationConfig $config, Logger $logger): void
34+
{
35+
$container->set(ApplicationConfig::class, $config);
36+
$container->set(\mysqli::class, ConnectionFactory::createConnection($config));
37+
$container->set(Logger::class, $logger);
38+
$container->set(ProcessorFactory::class, new ProcessorFactory());
39+
$container->set(ContainerInterface::class, $container);
3940
}
4041

4142
private function configure(ContainerConfigurator $containerConfigurator): void
@@ -51,19 +52,17 @@ private function configure(ContainerConfigurator $containerConfigurator): void
5152
->load('Reconmap\\Services\\', $prefix . 'Services/*')
5253
->exclude([$prefix . 'Services/QueryParams/OrderByRequestHandler.php'])
5354
->load('Reconmap\\Repositories\\', $prefix . 'Repositories/*')
55+
->load('Reconmap\\Database\\', $prefix . 'Database/*')
56+
->load('Reconmap\\Tasks\\', $prefix . 'Tasks/*')
5457
->load('Reconmap\\Http\\', $prefix . 'Http/*')
5558
->exclude($prefix . 'Http/ApplicationRequest.php')
5659
->load('Reconmap\\Controllers\\', $prefix . 'Controllers/*')
57-
->set(ServerRequestInterface::class)
58-
->synthetic()
59-
->set(Logger::class)
60-
->synthetic()
61-
->set(ApplicationConfig::class)
62-
->synthetic()
63-
->set(ProcessorFactory::class)
64-
->synthetic()
65-
->set(\mysqli::class)
66-
->synthetic();
60+
->set(ServerRequestInterface::class)->synthetic()
61+
->set(Logger::class)->synthetic()
62+
->set(ApplicationConfig::class)->synthetic()
63+
->set(ProcessorFactory::class)->synthetic()
64+
->set(ContainerInterface::class)->synthetic()
65+
->set(\mysqli::class)->synthetic();
6766
}
6867
}
6968

src/QueueProcessor.php src/Services/QueueProcessor.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<?php declare(strict_types=1);
22

3-
namespace Reconmap;
3+
namespace Reconmap\Services;
44

55
use Monolog\Logger;
6-
use Reconmap\Services\RedisServer;
6+
use Reconmap\ExitCode;
77
use Reconmap\Tasks\ItemProcessor;
88

9-
class QueueProcessor
9+
readonly class QueueProcessor
1010
{
1111
public function __construct(private RedisServer $redis,
1212
private Logger $logger)

tests/Cli/Commands/EmailProcessorCommandTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Reconmap\Cli\Commands;
44

55
use PHPUnit\Framework\TestCase;
6-
use Reconmap\QueueProcessor;
6+
use Reconmap\Services\QueueProcessor;
77
use Reconmap\Tasks\EmailTaskProcessor;
88
use Symfony\Component\Console\Input\InputInterface;
99
use Symfony\Component\Console\Output\OutputInterface;

tests/QueueProcessorTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Monolog\Logger;
66
use PHPUnit\Framework\TestCase;
7+
use Reconmap\Services\QueueProcessor;
78
use Reconmap\Services\RedisServer;
89
use Reconmap\Tasks\ItemProcessor;
910

0 commit comments

Comments
 (0)