Merge branch 'feature/client-portal' into develop
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled

This commit is contained in:
Matthieu
2026-03-16 09:51:48 +01:00
143 changed files with 16602 additions and 338 deletions

View File

@@ -8,6 +8,7 @@ use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle;
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
use Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle;
use Nelmio\CorsBundle\NelmioCorsBundle;
use Symfony\AI\McpBundle\McpBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
@@ -22,4 +23,5 @@ return [
ApiPlatformBundle::class => ['all' => true],
DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
LexikJWTAuthenticationBundle::class => ['all' => true],
McpBundle::class => ['all' => true],
];

View File

@@ -0,0 +1,10 @@
services:
Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory'
http_discovery.psr17_factory:
class: Http\Discovery\Psr17Factory

23
config/packages/mcp.yaml Normal file
View File

@@ -0,0 +1,23 @@
mcp:
app: 'lesstime'
version: '1.0.0'
description: 'Lesstime project management — projects, tasks, time tracking'
instructions: |
This server provides access to the Lesstime project management system.
You can list/create/update/delete projects, tasks, and time entries.
Tasks belong to projects and have statuses, priorities, efforts, tags, and groups.
Statuses, priorities, efforts, and tags are GLOBAL (shared across all projects).
Groups are PER-PROJECT (each group belongs to one project).
Time entries track work duration and can be linked to projects and tasks.
Use list-statuses, list-priorities, list-efforts, list-tags, list-groups to discover
available metadata before creating or updating tasks.
Use list-users and list-clients to discover valid user and client IDs.
client_transports:
stdio: true
http: true
http:
path: /_mcp
session:
store: file
directory: '%kernel.cache_dir%/mcp-sessions'
ttl: 3600

View File

@@ -1,4 +1,7 @@
security:
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_CLIENT]
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
@@ -25,6 +28,12 @@ security:
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
mcp:
pattern: ^/_mcp
stateless: true
provider: app_user_provider
custom_authenticators:
- App\Security\ApiTokenAuthenticator
api:
pattern: ^/api
stateless: true
@@ -50,6 +59,7 @@ security:
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
# Version de l'application en public
- { path: ^/api/version, roles: PUBLIC_ACCESS, methods: [ GET ] }
- { path: ^/_mcp, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
when@test:

View File

@@ -1610,6 +1610,37 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* cache?: scalar|Param|null, // Storage to track blocked tokens // Default: "cache.app"
* },
* }
* @psalm-type McpConfig = array{
* app?: scalar|Param|null, // Default: "app"
* version?: scalar|Param|null, // Default: "0.0.1"
* description?: scalar|Param|null, // Default: null
* icons?: list<array{ // Default: []
* src?: scalar|Param|null,
* mime_type?: scalar|Param|null, // Default: null
* sizes?: list<scalar|Param|null>,
* }>,
* website_url?: scalar|Param|null, // Default: null
* pagination_limit?: int|Param, // Default: 50
* instructions?: scalar|Param|null, // Default: null
* client_transports?: array{
* stdio?: bool|Param, // Default: false
* http?: bool|Param, // Default: false
* },
* discovery?: array{
* scan_dirs?: list<scalar|Param|null>,
* exclude_dirs?: list<scalar|Param|null>,
* },
* http?: array{
* path?: scalar|Param|null, // Default: "/_mcp"
* session?: array{
* store?: "file"|"memory"|"cache"|Param, // Default: "file"
* directory?: scalar|Param|null, // Default: "%kernel.cache_dir%/mcp-sessions"
* cache_pool?: scalar|Param|null, // Default: "cache.mcp.sessions"
* prefix?: scalar|Param|null, // Default: "mcp-"
* ttl?: int|Param, // Default: 3600
* },
* },
* }
* @psalm-type ConfigType = array{
* imports?: ImportsConfig,
* parameters?: ParametersConfig,
@@ -1622,6 +1653,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* nelmio_cors?: NelmioCorsConfig,
* api_platform?: ApiPlatformConfig,
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
* mcp?: McpConfig,
* "when@dev"?: array{
* imports?: ImportsConfig,
* parameters?: ParametersConfig,
@@ -1634,6 +1666,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* nelmio_cors?: NelmioCorsConfig,
* api_platform?: ApiPlatformConfig,
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
* mcp?: McpConfig,
* },
* "when@prod"?: array{
* imports?: ImportsConfig,
@@ -1647,6 +1680,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* nelmio_cors?: NelmioCorsConfig,
* api_platform?: ApiPlatformConfig,
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
* mcp?: McpConfig,
* },
* "when@test"?: array{
* imports?: ImportsConfig,
@@ -1660,6 +1694,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* nelmio_cors?: NelmioCorsConfig,
* api_platform?: ApiPlatformConfig,
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
* mcp?: McpConfig,
* },
* ...<string, ExtensionType|array{ // extra keys must follow the when@%env% pattern or match an extension alias
* imports?: ImportsConfig,

3
config/routes/mcp.yaml Normal file
View File

@@ -0,0 +1,3 @@
mcp:
resource: .
type: mcp

View File

@@ -8,6 +8,7 @@
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
task_document_upload_dir: '%kernel.project_dir%/var/uploads/documents'
avatar_upload_dir: '%kernel.project_dir%/var/uploads/avatars'
imports:
- { resource: version.yaml }
@@ -39,3 +40,7 @@ services:
App\Controller\TaskDocumentDownloadController:
arguments:
$uploadDir: '%task_document_upload_dir%'
App\Controller\UserAvatarController:
arguments:
$avatarUploadDir: '%avatar_upload_dir%'