more test cleanups

This commit is contained in:
Dennis Eichhorn 2019-12-01 19:57:42 +01:00
parent 5700c30859
commit 07f83fc57e
6 changed files with 96 additions and 21 deletions

View File

@ -52,8 +52,14 @@
"type": "TINYINT", "type": "TINYINT",
"null": false "null": false
}, },
"media_encryptionhash": { "media_nonce": {
"name": "media_encryptionhash", "name": "media_nonce",
"type": "VARCHAR(255)",
"null": true,
"default": null
},
"media_password": {
"name": "media_password",
"type": "VARCHAR(255)", "type": "VARCHAR(255)",
"null": true, "null": true,
"default": null "default": null

View File

@ -83,7 +83,9 @@ final class ApiController extends Controller
$request->getFiles(), $request->getFiles(),
$request->getHeader()->getAccount(), $request->getHeader()->getAccount(),
(string) ($request->getData('path') ?? __DIR__ . '/../../../Modules/Media/Files'), (string) ($request->getData('path') ?? __DIR__ . '/../../../Modules/Media/Files'),
(string) ($request->getData('virtualPath') ?? '/') (string) ($request->getData('virtualPath') ?? '/'),
(string) ($request->getData('password') ?? ''),
(string) ($request->getData('encrypt') ?? '')
); );
$ids = []; $ids = [];
@ -109,7 +111,9 @@ final class ApiController extends Controller
array $files, array $files,
int $account, int $account,
string $basePath = 'Modules/Media/Files', string $basePath = 'Modules/Media/Files',
string $virtualPath = '/' string $virtualPath = '/',
string $password = '',
string $encryptionKey = ''
) : array ) : array
{ {
$mediaCreated = []; $mediaCreated = [];
@ -118,7 +122,7 @@ final class ApiController extends Controller
$upload = new UploadFile(); $upload = new UploadFile();
$upload->setOutputDir(self::createMediaPath($basePath)); $upload->setOutputDir(self::createMediaPath($basePath));
$status = $upload->upload($files, $name); $status = $upload->upload($files, $name, $encryptionKey);
$mediaCreated = $this->createDbEntries($status, $account, $virtualPath); $mediaCreated = $this->createDbEntries($status, $account, $virtualPath);
} }

View File

@ -122,12 +122,20 @@ class Media implements \JsonSerializable
protected string $descriptionRaw = ''; protected string $descriptionRaw = '';
/** /**
* Media encryption hash. * Media encryption nonce.
* *
* @var null|string * @var null|string
* @since 1.0.0 * @since 1.0.0
*/ */
protected ?string $encryptionHash = null; protected ?string $nonce = null;
/**
* Media password hash.
*
* @var null|string
* @since 1.0.0
*/
protected ?string $password = null;
/** /**
* Constructor. * Constructor.
@ -182,17 +190,17 @@ class Media implements \JsonSerializable
} }
/** /**
* Set encryption hash * Set encryption nonce
* *
* @param null|string $encryptionHash Hash from encryption password * @param null|string $nonce Nonce from encryption password
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function setEncryptionHash(?string $encryptionHash) : void public function setNonce(?string $nonce) : void
{ {
$this->encryptionHash = $encryptionHash; $this->nonce = $nonce;
} }
/** /**
@ -204,21 +212,49 @@ class Media implements \JsonSerializable
*/ */
public function isEncrypted() : bool public function isEncrypted() : bool
{ {
return $this->encryptionHash !== null; return $this->nonce !== null;
} }
/** /**
* Compare hash with encryption hash of the media file * Set encryption password
* *
* @param string $hash User hash * @param null|string $password Password
*
* @return void
*
* @since 1.0.0
*/
public function setPassword(?string $password) : void
{
$this->password = $password;
}
/**
* Compare user password with password of the media file
*
* @param string $password User password
* *
* @return bool * @return bool
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function compareEncryptionHash(string $hash) : bool public function comparePassword(string $password) : bool
{ {
return \hash_equals($this->encryptionHash, $hash); return \password_verify($password, $this->password ?? '');
}
/**
* Compare nonce with encryption nonce of the media file
*
* @param string $nonce User nonce
*
* @return bool
*
* @since 1.0.0
*/
public function compareNonce(string $nonce) : bool
{
return \hash_equals($this->nonce, $nonce);
} }
/** /**

View File

@ -44,7 +44,8 @@ class MediaMapper extends DataMapperAbstract
'media_file' => ['name' => 'media_file', 'type' => 'string', 'internal' => 'path', 'autocomplete' => true], 'media_file' => ['name' => 'media_file', 'type' => 'string', 'internal' => 'path', 'autocomplete' => true],
'media_virtual' => ['name' => 'media_virtual', 'type' => 'string', 'internal' => 'virtualPath', 'autocomplete' => true], 'media_virtual' => ['name' => 'media_virtual', 'type' => 'string', 'internal' => 'virtualPath', 'autocomplete' => true],
'media_absolute' => ['name' => 'media_absolute', 'type' => 'bool', 'internal' => 'isAbsolute'], 'media_absolute' => ['name' => 'media_absolute', 'type' => 'bool', 'internal' => 'isAbsolute'],
'media_encryptionhash' => ['name' => 'media_encryptionhash', 'type' => 'string', 'internal' => 'encryptionHash'], 'media_nonce' => ['name' => 'media_nonce', 'type' => 'string', 'internal' => 'nonce'],
'media_password' => ['name' => 'media_password', 'type' => 'string', 'internal' => 'password'],
'media_extension' => ['name' => 'media_extension', 'type' => 'string', 'internal' => 'extension'], 'media_extension' => ['name' => 'media_extension', 'type' => 'string', 'internal' => 'extension'],
'media_size' => ['name' => 'media_size', 'type' => 'int', 'internal' => 'size'], 'media_size' => ['name' => 'media_size', 'type' => 'int', 'internal' => 'size'],
'media_created_by' => ['name' => 'media_created_by', 'type' => 'int', 'internal' => 'createdBy'], 'media_created_by' => ['name' => 'media_created_by', 'type' => 'int', 'internal' => 'createdBy'],

View File

@ -87,9 +87,10 @@ class UploadFile
/** /**
* Upload file to server. * Upload file to server.
* *
* @param array $files File data ($_FILE) * @param array $files File data ($_FILE)
* @param string $name File name * @param string $name File name
* @param string $encoding Encoding used for uploaded file. Empty string will not convert file content. * @param string $encryptionKey Encryption key
* @param string $encoding Encoding used for uploaded file. Empty string will not convert file content.
* *
* @return array * @return array
* *
@ -97,7 +98,7 @@ class UploadFile
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function upload(array $files, string $name = '', string $encoding = 'UTF-8') : array public function upload(array $files, string $name = '', string $encryptionKey = '', string $encoding = 'UTF-8') : array
{ {
$result = []; $result = [];
@ -179,6 +180,32 @@ class UploadFile
return $result; return $result;
} }
if ($encryptionKey !== '') {
$nonce = \sodium_randombytes_buf(24);
$fpSource = \fopen($dest, 'r+');
$fpEncoded = \fopen($dest . '.tmp', 'w');
if ($fpSource === false || $fpEncoded === false) {
$result[$key]['status'] = UploadStatus::NOT_ENCRYPTABLE;
return $result;
}
while (($buffer = \fgets($fpSource, 4096)) !== false) {
$encrypted = \sodium_crypto_secretbox($buffer, $nonce, $encryptionKey);
\fwrite($fpEncoded, $encrypted);
}
\fclose($fpSource);
\fclose($fpEncoded);
\unlink($dest);
\rename($dest . '.tmp', $dest);
$result[$key]['nonce'] = $nonce;
}
/* /*
if ($this->isInterlaced && \in_array($extension, FileUtils::IMAGE_EXTENSION)) { if ($this->isInterlaced && \in_array($extension, FileUtils::IMAGE_EXTENSION)) {
// todo: interlacing somehow messes up some images (tested with logo.png from assets) // todo: interlacing somehow messes up some images (tested with logo.png from assets)

View File

@ -36,4 +36,5 @@ abstract class UploadStatus extends Enum
public const NOT_UPLOADED = -7; public const NOT_UPLOADED = -7;
public const NOT_MOVABLE = -8; public const NOT_MOVABLE = -8;
public const FAILED_HASHING = -9; public const FAILED_HASHING = -9;
public const NOT_ENCRYPTABLE = -10;
} }