This commit is contained in:
Charles 2025-08-05 09:13:04 +02:00
parent cbdb47fb17
commit 1ee9a0110b
11 changed files with 1478 additions and 313 deletions

5
.env
View File

@ -62,3 +62,8 @@ MERCURE_PUBLIC_URL=https://example.com/.well-known/mercure
# The secret used to sign the JWTs
MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
###< symfony/mercure-bundle ###
###> aws/aws-sdk-php-symfony ###
AWS_KEY=not-a-real-key
AWS_SECRET=@@not-a-real-secret
###< aws/aws-sdk-php-symfony ###

View File

@ -8,7 +8,16 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mercure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mercure-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/firebase/php-jwt" />
<excludeFolder url="file://$MODULE_DIR$/vendor/aws/aws-crt-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/aws/aws-sdk-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/aws/aws-sdk-php-symfony" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
<excludeFolder url="file://$MODULE_DIR$/vendor/knplabs/knp-time-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/mtdowling/jmespath.php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@ -164,6 +164,15 @@
<path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
<path value="$PROJECT_DIR$/vendor/doctrine/cache" />
<path value="$PROJECT_DIR$/vendor/knplabs/knp-time-bundle" />
<path value="$PROJECT_DIR$/vendor/aws/aws-sdk-php" />
<path value="$PROJECT_DIR$/vendor/aws/aws-crt-php" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/aws/aws-sdk-php-symfony" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
<path value="$PROJECT_DIR$/vendor/mtdowling/jmespath.php" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />

View File

@ -8,6 +8,7 @@
"ext-ctype": "*",
"ext-iconv": "*",
"ext-openssl": "*",
"aws/aws-sdk-php-symfony": "^2.8",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.14",
"doctrine/doctrine-migrations-bundle": "^3.4",

1500
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -18,4 +18,5 @@ return [
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true],
Aws\Symfony\AwsBundle::class => ['all' => true],
];

11
config/packages/aws.yaml Normal file
View File

@ -0,0 +1,11 @@
aws:
version: latest
region: "%env(AWS_REGION)%"
credentials:
key: "%env(AWS_KEY)%"
secret: "%env(AWS_SECRET)%"
S3:
region: "%env(AWS_REGION)%"
endpoint: "%env(AWS_ENDPOINT)%"
use_path_style_endpoint: true
signature_version: 'v4'

View File

@ -4,6 +4,8 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
aws_url: '%env(AWS_ENDPOINT)%'
aws_public_url: '%env(AWS_ENDPOINT)%'
services:
# default configuration for services in *this* file
@ -22,6 +24,9 @@ services:
App\EventSubscriber\:
resource: '../src/EventSubscriber/'
tags: ['kernel.event_subscriber']
App\Service\AwsService:
arguments:
$awsPublicUrl: '%aws_public_url%'
App\EventSubscriber\ScopeResolveListener:
tags:
- { name: kernel.event_listener, event: league.oauth2_server.event.scope_resolve, method: onScopeResolve }

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250804121445 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE apps ADD description_small VARCHAR(255) DEFAULT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE apps DROP description_small');
}
}

206
src/Service/AwsService.php Normal file
View File

@ -0,0 +1,206 @@
<?php
namespace App\Service;
use Aws\S3\S3Client;
class AwsService
{
public function __construct(
private S3Client $s3Client,
private string $awsPublicUrl
) {
}
/**
* Function to generate UUID Version 4
*
* @return string
*/
public function generateUUIDv4():string {
$uuid = uuid_create(4);
$isValid = uuid_is_valid($uuid);
if( $isValid == true){
$retour = $uuid;
}else{
$retour = 'une erreur est survenue !';
}
return $retour;
}
/**
* Get public url for files download or visualisation
*
* @param string $bucket nom du conteneur S3
* @return string
*/
public function getPublicUrl(string $bucket): string{
$publicUrl = substr_replace($this->awsPublicUrl, $bucket.'.', 8, 0);
$publicUrl .= '/';
return $publicUrl;
}
/**
* CREATE bucket S3 for new project
*
* @return string|array
*/
public function createBucket(): string|array{
$bucket = $this->generateUUIDv4();
$result = $this->s3Client->createBucket([
'Bucket' => $bucket,
'ObjectOwnership' => 'BucketOwnerPreferred'
]);
if ( $result['@metadata']['statusCode'] == 200){
return $bucket;
}else{
return $result['@metadata'];
}
}
/**
* DELETE bucket S3
*
* @param string $bucket nom du conteneur S3
* @return string|array
*/
public function DeleteBucket(string $bucket): string|array{
$result = $this->s3Client->deleteBucket([
'Bucket' => $bucket,
]);
if ( $result['@metadata']['statusCode'] == 200){
return $bucket;
}else{
return $result['@metadata'];
}
}
/**
* Get list files infos in the Bucket S3
* If prefix NULL get ALL FILES else get FILES in this prefix
*
* @param string $bucket nom du conteneur S3
* @param string|null $prefix arborescence dans le bucket
* @return array|null
*/
public function getListObject(string $bucket, string|null $prefix = null):array|null{
$results = $this->s3Client->listObjectsV2([
'Bucket' => $bucket,
'Prefix' => $prefix
]);
if( isset($results['Contents']) ){
$return = $results['Contents'];
}
return $return;
}
/**
* PUT file Object in bucket S3
*
* @param string $bucket nom du conteneur S3
* @param object $file fichier à déposer dans le bucket
* @param string $filename nom du fichier enregistré dans la bdd métier
* @param string $mimeType type du fichier
* @param string|null $prefix arborescence dans le bucket
* @return bool
*/
public function PutDocObj(string $bucket, object $file, string $filename, $mimeType, string|null $prefix = null): int{
$body = fopen( $file, 'r');
$hashRaw = hash_file('sha256', $file, true);
$hash = base64_encode($hashRaw);
rewind($body);
$doc = $this->s3Client->putObject([
'Bucket' => $bucket,
'ChecksumAlgorithm' => 'SHA256',
'ChecksumSHA256' => $hash,
'Key' => $prefix.$filename,
'Body' => $body,
'ACL' => 'public-read',
'ContentType' => $mimeType // pour rendre l'image publique si besoin
]);
return $doc['@metadata']['statusCode'];
}
/**
* DELETE file Object in bucket S3
*
* @param string $bucket nom du conteneur S3
* @param string $filename nom du fichier
* @param string|null $prefix arborescence dans le bucket
* @return bool
*/
public function DeleteDocObj(string $bucket, string $filename, string|null $prefix = null): int{
$doc = $this->s3Client->deleteObject([
'Bucket' => $bucket,
'Key' => $prefix.$filename,
]);
return $doc['@metadata']['statusCode'];
}
/**
* RENAME file Object in bucket S3
*
* @param string $bucket nom du conteneur S3
* @param string $filename nom du fichier
* @param string $newFilename
* @param string|null $prefix arborescence dans le bucket
* @return bool
*/
public function renameDocObj(string $bucket, string $filename, string $newFilename, string|null $prefix = null): int{
$doc = $this->s3Client->copyObject([
'Bucket' => $bucket,
'CopySource' => $prefix.$filename,
'Key' => $prefix.$newFilename,
]);
$this->DeleteDocObj($bucket, $filename, $prefix);
return $doc['@metadata']['statusCode'];
}
/**
* MOVE file Object in bucket S3
*
* @param string $bucket nom du conteneur S3
* @param string $filename nom du fichier
* @param string|null $prefix arborescence dans le bucket
* @param string|null $newPrefix nouvel emplacement dans le bucket
* @return bool
*/
public function moveDocObj(string $bucket, string $filename, string|null $prefix = null, string|null $newPrefix = null): int{
$doc = $this->s3Client->copyObject([
'Bucket' => $bucket,
'CopySource' => $prefix.$filename,
'Key' => $newPrefix.$filename,
]);
$this->DeleteDocObj($bucket, $filename, $prefix);
return $doc['@metadata']['statusCode'];
}
}

View File

@ -1,4 +1,16 @@
{
"aws/aws-sdk-php-symfony": {
"version": "2.8",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "1.3",
"ref": "d1753f9e2a669c464b2b0618af9b0123426b67b4"
},
"files": [
"config/packages/aws.yaml"
]
},
"doctrine/deprecations": {
"version": "1.1",
"recipe": {