Skip to content

Commit bd9be31

Browse files
committed
Adding optional random-generated IDs for anonymous access to uploaded files.
1 parent 29fa01d commit bd9be31

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

app/model/entity/ExerciseFile.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ public function __construct(
7676
int $fileSize,
7777
string $hashName,
7878
?User $user,
79-
Exercise $exercise = null,
80-
Pipeline $pipeline = null
79+
?Exercise $exercise = null,
80+
?Pipeline $pipeline = null
8181
) {
8282
parent::__construct($name, $uploadedAt, $fileSize, $user);
8383
$this->hashName = $hashName;

app/model/entity/UploadedFile.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,19 @@ public function getFileExtension(): string
4747

4848
/**
4949
* @ORM\Column(type="boolean")
50+
* If true, the file is accessible to all logged-in users.
51+
* This is useful for files associated with entries like exercises.
5052
*/
5153
protected $isPublic;
5254

55+
/**
56+
* External identification (used in URL) that allows for accessing the file without authentication.
57+
* If empty, the file is not accessible this way.
58+
* The identifier should be a generated random string.
59+
* @ORM\Column(type="string", length=16, nullable=true, unique=true)
60+
*/
61+
protected $external = null;
62+
5363
/**
5464
* @ORM\Column(type="integer")
5565
*/
@@ -113,6 +123,31 @@ public function isPublic()
113123
return $this->isPublic;
114124
}
115125

126+
public function setPublic(bool $isPublic): void
127+
{
128+
$this->isPublic = $isPublic;
129+
}
130+
131+
public function getExternal(): ?string
132+
{
133+
return $this->external;
134+
}
135+
136+
public function setExternal(?string $external): void
137+
{
138+
$this->external = $external;
139+
}
140+
141+
/**
142+
* Generate a random external ID for this file which uses only URL-safe characters.
143+
*/
144+
public function generateRandomExternalId(): void
145+
{
146+
// the + and / characters are replaced to make the string URL-safe without the need for encoding
147+
// (base64 encoding uses A-Z, a-z, 0-9, +, /)
148+
$this->external = str_replace(['+', '/'], ['-', '$'], base64_encode(random_bytes(12)));
149+
}
150+
116151
/**
117152
* Retrieve a corresponding file object from file storage.
118153
* @param FileStorageManager $manager the storage that retrieves the file
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20251113182809 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql('ALTER TABLE uploaded_file ADD external VARCHAR(16) DEFAULT NULL');
24+
$this->addSql('CREATE UNIQUE INDEX UNIQ_B40DF75D5852A1B8 ON uploaded_file (external)');
25+
}
26+
27+
public function down(Schema $schema): void
28+
{
29+
// this down() migration is auto-generated, please modify it to your needs
30+
$this->addSql('DROP INDEX UNIQ_B40DF75D5852A1B8 ON `uploaded_file`');
31+
$this->addSql('ALTER TABLE `uploaded_file` DROP external');
32+
}
33+
}

0 commit comments

Comments
 (0)