Browse Source
Implement guest avatar endpoint
Implement guest avatar endpoint
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>pull/10248/head
committed by
Morris Jobke
No known key found for this signature in database
GPG Key ID: FE03C3A163FEDE68
25 changed files with 1130 additions and 260 deletions
-
1core/Controller/AvatarController.php
-
107core/Controller/GuestAvatarController.php
-
1core/routes.php
-
8lib/composer/composer/autoload_classmap.php
-
8lib/composer/composer/autoload_static.php
-
287lib/private/Avatar/Avatar.php
-
14lib/private/Avatar/AvatarManager.php
-
119lib/private/Avatar/GuestAvatar.php
-
336lib/private/Avatar/UserAvatar.php
-
2lib/private/Repair.php
-
3lib/private/Repair/ClearGeneratedAvatarCache.php
-
1lib/private/Server.php
-
9lib/public/AppFramework/Http/FileDisplayResponse.php
-
137lib/public/Files/SimpleFS/InMemoryFile.php
-
9lib/public/IAvatarManager.php
-
4tests/Core/Controller/AvatarControllerTest.php
-
90tests/Core/Controller/GuestAvatarControllerTest.php
-
5tests/data/guest_avatar_einstein_32.svg
-
BINtests/data/test.pdf
-
12tests/lib/Avatar/AvatarManagerTest.php
-
80tests/lib/Avatar/GuestAvatarTest.php
-
8tests/lib/Avatar/UserAvatarTest.php
-
145tests/lib/Files/SimpleFS/InMemoryFileTest.php
-
2tests/lib/Repair/ClearGeneratedAvatarCacheTest.php
-
2tests/lib/ServerTest.php
@ -0,0 +1,107 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2019, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace OC\Core\Controller; |
|||
|
|||
use OCP\AppFramework\Controller; |
|||
use OCP\AppFramework\Http; |
|||
use OCP\AppFramework\Http\FileDisplayResponse; |
|||
use OCP\IAvatarManager; |
|||
use OCP\ILogger; |
|||
use OCP\IRequest; |
|||
|
|||
/** |
|||
* This controller handles guest avatar requests. |
|||
*/ |
|||
class GuestAvatarController extends Controller { |
|||
|
|||
/** |
|||
* @var ILogger |
|||
*/ |
|||
private $logger; |
|||
|
|||
/** |
|||
* @var IAvatarManager |
|||
*/ |
|||
private $avatarManager; |
|||
|
|||
/** |
|||
* GuestAvatarController constructor. |
|||
* |
|||
* @param $appName |
|||
* @param IRequest $request |
|||
* @param IAvatarManager $avatarManager |
|||
* @param ILogger $logger |
|||
*/ |
|||
public function __construct( |
|||
$appName, |
|||
IRequest $request, |
|||
IAvatarManager $avatarManager, |
|||
ILogger $logger |
|||
) { |
|||
parent::__construct($appName, $request); |
|||
$this->avatarManager = $avatarManager; |
|||
$this->logger = $logger; |
|||
} |
|||
|
|||
/** |
|||
* Returns a guest avatar image response. |
|||
* |
|||
* @PublicPage |
|||
* @NoCSRFRequired |
|||
* |
|||
* @param string $guestName The guest name, e.g. "Albert" |
|||
* @param string $size The desired avatar size, e.g. 64 for 64x64px |
|||
* @return FileDisplayResponse|Http\Response |
|||
*/ |
|||
public function getAvatar($guestName, $size) { |
|||
$size = (int) $size; |
|||
|
|||
// min/max size
|
|||
if ($size > 2048) { |
|||
$size = 2048; |
|||
} elseif ($size <= 0) { |
|||
$size = 64; |
|||
} |
|||
|
|||
try { |
|||
$avatar = $this->avatarManager->getGuestAvatar($guestName); |
|||
$avatarFile = $avatar->getFile($size); |
|||
|
|||
$resp = new FileDisplayResponse( |
|||
$avatarFile, |
|||
$avatar->isCustomAvatar() ? Http::STATUS_OK : Http::STATUS_CREATED, |
|||
['Content-Type' => $avatarFile->getMimeType()] |
|||
); |
|||
} catch (\Exception $e) { |
|||
$this->logger->error('error while creating guest avatar', [ |
|||
'err' => $e, |
|||
]); |
|||
$resp = new Http\Response(); |
|||
$resp->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR); |
|||
return $resp; |
|||
} |
|||
|
|||
// Cache for 30 minutes
|
|||
$resp->cacheFor(1800); |
|||
return $resp; |
|||
} |
|||
} |
|||
@ -0,0 +1,119 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace OC\Avatar; |
|||
|
|||
use OCP\Files\SimpleFS\InMemoryFile; |
|||
use OCP\ILogger; |
|||
|
|||
/** |
|||
* This class represents a guest user's avatar. |
|||
*/ |
|||
class GuestAvatar extends Avatar { |
|||
/** |
|||
* Holds the guest user display name. |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $userDisplayName; |
|||
|
|||
/** |
|||
* GuestAvatar constructor. |
|||
* |
|||
* @param string $userDisplayName The guest user display name |
|||
* @param ILogger $logger The logger |
|||
*/ |
|||
public function __construct(string $userDisplayName, ILogger $logger) { |
|||
parent::__construct($logger); |
|||
$this->userDisplayName = $userDisplayName; |
|||
} |
|||
|
|||
/** |
|||
* Tests if the user has an avatar. |
|||
* |
|||
* @return true Guests always have an avatar. |
|||
*/ |
|||
public function exists() { |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Returns the guest user display name. |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getDisplayName(): string { |
|||
return $this->userDisplayName; |
|||
} |
|||
|
|||
/** |
|||
* Setting avatars isn't implemented for guests. |
|||
* |
|||
* @param \OCP\IImage|resource|string $data |
|||
* @return void |
|||
*/ |
|||
public function set($data) { |
|||
// unimplemented for guest user avatars
|
|||
} |
|||
|
|||
/** |
|||
* Removing avatars isn't implemented for guests. |
|||
*/ |
|||
public function remove() { |
|||
// unimplemented for guest user avatars
|
|||
} |
|||
|
|||
/** |
|||
* Generates an avatar for the guest. |
|||
* |
|||
* @param int $size The desired image size. |
|||
* @return InMemoryFile |
|||
*/ |
|||
public function getFile($size) { |
|||
$avatar = $this->getAvatarVector($size); |
|||
return new InMemoryFile('avatar.svg', $avatar); |
|||
} |
|||
|
|||
/** |
|||
* Updates the display name if changed. |
|||
* |
|||
* @param string $feature The changed feature |
|||
* @param mixed $oldValue The previous value |
|||
* @param mixed $newValue The new value |
|||
* @return void |
|||
*/ |
|||
public function userChanged($feature, $oldValue, $newValue) { |
|||
if ($feature === 'displayName') { |
|||
$this->userDisplayName = $newValue; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Guests don't have custom avatars. |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isCustomAvatar(): bool { |
|||
return false; |
|||
} |
|||
} |
|||
@ -0,0 +1,336 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace OC\Avatar; |
|||
|
|||
use OC\NotSquareException; |
|||
use OC\User\User; |
|||
use OC_Image; |
|||
use OCP\Files\NotFoundException; |
|||
use OCP\Files\NotPermittedException; |
|||
use OCP\Files\SimpleFS\ISimpleFile; |
|||
use OCP\Files\SimpleFS\ISimpleFolder; |
|||
use OCP\IConfig; |
|||
use OCP\IImage; |
|||
use OCP\IL10N; |
|||
use OCP\ILogger; |
|||
|
|||
/** |
|||
* This class represents a registered user's avatar. |
|||
*/ |
|||
class UserAvatar extends Avatar { |
|||
/** @var IConfig */ |
|||
private $config; |
|||
|
|||
/** @var ISimpleFolder */ |
|||
private $folder; |
|||
|
|||
/** @var IL10N */ |
|||
private $l; |
|||
|
|||
/** @var User */ |
|||
private $user; |
|||
|
|||
/** |
|||
* UserAvatar constructor. |
|||
* |
|||
* @param IConfig $config The configuration |
|||
* @param ISimpleFolder $folder The avatar files folder |
|||
* @param IL10N $l The localization helper |
|||
* @param User $user The user this class manages the avatar for |
|||
* @param ILogger $logger The logger |
|||
*/ |
|||
public function __construct( |
|||
ISimpleFolder $folder, |
|||
IL10N $l, |
|||
$user, |
|||
ILogger $logger, |
|||
IConfig $config) { |
|||
parent::__construct($logger); |
|||
$this->folder = $folder; |
|||
$this->l = $l; |
|||
$this->user = $user; |
|||
$this->config = $config; |
|||
} |
|||
|
|||
/** |
|||
* Check if an avatar exists for the user |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function exists() { |
|||
return $this->folder->fileExists('avatar.jpg') || $this->folder->fileExists('avatar.png'); |
|||
} |
|||
|
|||
/** |
|||
* Sets the users avatar. |
|||
* |
|||
* @param IImage|resource|string $data An image object, imagedata or path to set a new avatar |
|||
* @throws \Exception if the provided file is not a jpg or png image |
|||
* @throws \Exception if the provided image is not valid |
|||
* @throws NotSquareException if the image is not square |
|||
* @return void |
|||
*/ |
|||
public function set($data) { |
|||
$img = $this->getAvatarImage($data); |
|||
$data = $img->data(); |
|||
|
|||
$this->validateAvatar($img); |
|||
|
|||
$this->remove(); |
|||
$type = $this->getAvatarImageType($img); |
|||
$file = $this->folder->newFile('avatar.' . $type); |
|||
$file->putContent($data); |
|||
|
|||
try { |
|||
$generated = $this->folder->getFile('generated'); |
|||
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', 'false'); |
|||
$generated->delete(); |
|||
} catch (NotFoundException $e) { |
|||
//
|
|||
} |
|||
|
|||
$this->user->triggerChange('avatar', $file); |
|||
} |
|||
|
|||
/** |
|||
* Returns an image from several sources. |
|||
* |
|||
* @param IImage|resource|string $data An image object, imagedata or path to the avatar |
|||
* @return IImage |
|||
*/ |
|||
private function getAvatarImage($data) { |
|||
if ($data instanceof IImage) { |
|||
return $data; |
|||
} |
|||
|
|||
$img = new OC_Image(); |
|||
if (is_resource($data) && get_resource_type($data) === 'gd') { |
|||
$img->setResource($data); |
|||
} elseif (is_resource($data)) { |
|||
$img->loadFromFileHandle($data); |
|||
} else { |
|||
try { |
|||
// detect if it is a path or maybe the images as string
|
|||
$result = @realpath($data); |
|||
if ($result === false || $result === null) { |
|||
$img->loadFromData($data); |
|||
} else { |
|||
$img->loadFromFile($data); |
|||
} |
|||
} catch (\Error $e) { |
|||
$img->loadFromData($data); |
|||
} |
|||
} |
|||
|
|||
return $img; |
|||
} |
|||
|
|||
/** |
|||
* Returns the avatar image type. |
|||
* |
|||
* @param IImage $avatar |
|||
* @return string |
|||
*/ |
|||
private function getAvatarImageType(IImage $avatar) { |
|||
$type = substr($avatar->mimeType(), -3); |
|||
if ($type === 'peg') { |
|||
$type = 'jpg'; |
|||
} |
|||
return $type; |
|||
} |
|||
|
|||
/** |
|||
* Validates an avatar image: |
|||
* - must be "png" or "jpg" |
|||
* - must be "valid" |
|||
* - must be in square format |
|||
* |
|||
* @param IImage $avatar The avatar to validate |
|||
* @throws \Exception if the provided file is not a jpg or png image |
|||
* @throws \Exception if the provided image is not valid |
|||
* @throws NotSquareException if the image is not square |
|||
*/ |
|||
private function validateAvatar(IImage $avatar) { |
|||
$type = $this->getAvatarImageType($avatar); |
|||
|
|||
if ($type !== 'jpg' && $type !== 'png') { |
|||
throw new \Exception($this->l->t('Unknown filetype')); |
|||
} |
|||
|
|||
if (!$avatar->valid()) { |
|||
throw new \Exception($this->l->t('Invalid image')); |
|||
} |
|||
|
|||
if (!($avatar->height() === $avatar->width())) { |
|||
throw new NotSquareException($this->l->t('Avatar image is not square')); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Removes the users avatar. |
|||
* @return void |
|||
* @throws \OCP\Files\NotPermittedException |
|||
* @throws \OCP\PreConditionNotMetException |
|||
*/ |
|||
public function remove() { |
|||
$avatars = $this->folder->getDirectoryListing(); |
|||
|
|||
$this->config->setUserValue($this->user->getUID(), 'avatar', 'version', |
|||
(int) $this->config->getUserValue($this->user->getUID(), 'avatar', 'version', 0) + 1); |
|||
|
|||
foreach ($avatars as $avatar) { |
|||
$avatar->delete(); |
|||
} |
|||
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', 'true'); |
|||
$this->user->triggerChange('avatar', ''); |
|||
} |
|||
|
|||
/** |
|||
* Get the extension of the avatar. If there is no avatar throw Exception |
|||
* |
|||
* @return string |
|||
* @throws NotFoundException |
|||
*/ |
|||
private function getExtension() { |
|||
if ($this->folder->fileExists('avatar.jpg')) { |
|||
return 'jpg'; |
|||
} elseif ($this->folder->fileExists('avatar.png')) { |
|||
return 'png'; |
|||
} |
|||
throw new NotFoundException; |
|||
} |
|||
|
|||
/** |
|||
* Returns the avatar for an user. |
|||
* |
|||
* If there is no avatar file yet, one is generated. |
|||
* |
|||
* @param int $size |
|||
* @return ISimpleFile |
|||
* @throws NotFoundException |
|||
* @throws \OCP\Files\NotPermittedException |
|||
* @throws \OCP\PreConditionNotMetException |
|||
*/ |
|||
public function getFile($size) { |
|||
$size = (int) $size; |
|||
|
|||
try { |
|||
$ext = $this->getExtension(); |
|||
} catch (NotFoundException $e) { |
|||
if (!$data = $this->generateAvatarFromSvg(1024)) { |
|||
$data = $this->generateAvatar($this->getDisplayName(), 1024); |
|||
} |
|||
$avatar = $this->folder->newFile('avatar.png'); |
|||
$avatar->putContent($data); |
|||
$ext = 'png'; |
|||
|
|||
$this->folder->newFile('generated'); |
|||
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', 'true'); |
|||
} |
|||
|
|||
if ($size === -1) { |
|||
$path = 'avatar.' . $ext; |
|||
} else { |
|||
$path = 'avatar.' . $size . '.' . $ext; |
|||
} |
|||
|
|||
try { |
|||
$file = $this->folder->getFile($path); |
|||
} catch (NotFoundException $e) { |
|||
if ($size <= 0) { |
|||
throw new NotFoundException; |
|||
} |
|||
|
|||
if ($this->folder->fileExists('generated')) { |
|||
if (!$data = $this->generateAvatarFromSvg($size)) { |
|||
$data = $this->generateAvatar($this->getDisplayName(), $size); |
|||
} |
|||
|
|||
} else { |
|||
$avatar = new OC_Image(); |
|||
$file = $this->folder->getFile('avatar.' . $ext); |
|||
$avatar->loadFromData($file->getContent()); |
|||
$avatar->resize($size); |
|||
$data = $avatar->data(); |
|||
} |
|||
|
|||
try { |
|||
$file = $this->folder->newFile($path); |
|||
$file->putContent($data); |
|||
} catch (NotPermittedException $e) { |
|||
$this->logger->error('Failed to save avatar for ' . $this->user->getUID()); |
|||
throw new NotFoundException(); |
|||
} |
|||
|
|||
} |
|||
|
|||
if ($this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', null) === null) { |
|||
$generated = $this->folder->fileExists('generated') ? 'true' : 'false'; |
|||
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', $generated); |
|||
} |
|||
|
|||
return $file; |
|||
} |
|||
|
|||
/** |
|||
* Returns the user display name. |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getDisplayName(): string { |
|||
return $this->user->getDisplayName(); |
|||
} |
|||
|
|||
/** |
|||
* Handles user changes. |
|||
* |
|||
* @param string $feature The changed feature |
|||
* @param mixed $oldValue The previous value |
|||
* @param mixed $newValue The new value |
|||
* @throws NotPermittedException |
|||
* @throws \OCP\PreConditionNotMetException |
|||
*/ |
|||
public function userChanged($feature, $oldValue, $newValue) { |
|||
// We only change the avatar on display name changes
|
|||
if ($feature !== 'displayName') { |
|||
return; |
|||
} |
|||
|
|||
// If the avatar is not generated (so an uploaded image) we skip this
|
|||
if (!$this->folder->fileExists('generated')) { |
|||
return; |
|||
} |
|||
|
|||
$this->remove(); |
|||
} |
|||
|
|||
/** |
|||
* Check if the avatar of a user is a custom uploaded one |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isCustomAvatar(): bool { |
|||
return $this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', 'false') !== 'true'; |
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace OCP\Files\SimpleFS; |
|||
|
|||
use OCP\Files\NotPermittedException; |
|||
|
|||
/** |
|||
* This class represents a file that is only hold in memory. |
|||
* |
|||
* @package OC\Files\SimpleFS |
|||
*/ |
|||
class InMemoryFile implements ISimpleFile { |
|||
/** |
|||
* Holds the file name. |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $name; |
|||
|
|||
/** |
|||
* Holds the file contents. |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $contents; |
|||
|
|||
/** |
|||
* InMemoryFile constructor. |
|||
* |
|||
* @param string $name The file name |
|||
* @param string $contents The file contents |
|||
*/ |
|||
public function __construct(string $name, string $contents) { |
|||
$this->name = $name; |
|||
$this->contents = $contents; |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getName() { |
|||
return $this->name; |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getSize() { |
|||
return strlen($this->contents); |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getETag() { |
|||
return ''; |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getMTime() { |
|||
return time(); |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getContent() { |
|||
return $this->contents; |
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function putContent($data) { |
|||
$this->contents = $data; |
|||
} |
|||
|
|||
/** |
|||
* In memory files can't be deleted. |
|||
*/ |
|||
public function delete() { |
|||
// unimplemented for in memory files
|
|||
} |
|||
|
|||
/** |
|||
* @inheritdoc |
|||
*/ |
|||
public function getMimeType() { |
|||
$fileInfo = new \finfo(FILEINFO_MIME_TYPE); |
|||
return $fileInfo->buffer($this->contents); |
|||
} |
|||
|
|||
/** |
|||
* Stream reading is unsupported for in memory files. |
|||
* |
|||
* @throws NotPermittedException |
|||
*/ |
|||
public function read() { |
|||
throw new NotPermittedException( |
|||
'Stream reading is unsupported for in memory files' |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Stream writing isn't available for in memory files. |
|||
* |
|||
* @throws NotPermittedException |
|||
*/ |
|||
public function write() { |
|||
throw new NotPermittedException( |
|||
'Stream writing is unsupported for in memory files' |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
<?php |
|||
|
|||
namespace Core\Controller; |
|||
|
|||
use OC\Core\Controller\GuestAvatarController; |
|||
use OCP\AppFramework\Http\FileDisplayResponse; |
|||
use OCP\Files\SimpleFS\ISimpleFile; |
|||
use OCP\IAvatar; |
|||
use OCP\IAvatarManager; |
|||
use OCP\ILogger; |
|||
use OCP\IRequest; |
|||
|
|||
/** |
|||
* This class provides tests for the guest avatar controller. |
|||
*/ |
|||
class GuestAvatarControllerTest extends \Test\TestCase { |
|||
|
|||
/** |
|||
* @var GuestAvatarController |
|||
*/ |
|||
private $guestAvatarController; |
|||
|
|||
/** |
|||
* @var IRequest|\PHPUnit_Framework_MockObject_MockObject |
|||
*/ |
|||
private $request; |
|||
|
|||
/** |
|||
* @var IAvatarManager|\PHPUnit_Framework_MockObject_MockObject |
|||
*/ |
|||
private $avatarManager; |
|||
|
|||
/** |
|||
* @var IAvatar|\PHPUnit_Framework_MockObject_MockObject |
|||
*/ |
|||
private $avatar; |
|||
|
|||
/** |
|||
* @var \OCP\Files\File|\PHPUnit_Framework_MockObject_MockObject |
|||
*/ |
|||
private $file; |
|||
|
|||
/** |
|||
* @var ILogger|\PHPUnit_Framework_MockObject_MockObject |
|||
*/ |
|||
private $logger; |
|||
|
|||
/** |
|||
* Sets up the test environment. |
|||
*/ |
|||
protected function setUp() { |
|||
parent::setUp(); |
|||
|
|||
$this->logger = $this->getMockBuilder(ILogger::class)->getMock(); |
|||
$this->request = $this->getMockBuilder(IRequest::class)->getMock(); |
|||
$this->avatar = $this->getMockBuilder(IAvatar::class)->getMock(); |
|||
$this->avatarManager = $this->getMockBuilder(IAvatarManager::class)->getMock(); |
|||
$this->file = $this->getMockBuilder(ISimpleFile::class)->getMock(); |
|||
$this->guestAvatarController = new GuestAvatarController( |
|||
'core', |
|||
$this->request, |
|||
$this->avatarManager, |
|||
$this->logger |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Tests getAvatar returns the guest avatar. |
|||
*/ |
|||
public function testGetAvatar() { |
|||
$this->avatarManager->expects($this->once()) |
|||
->method('getGuestAvatar') |
|||
->with('Peter') |
|||
->willReturn($this->avatar); |
|||
|
|||
$this->avatar->expects($this->once()) |
|||
->method('getFile') |
|||
->with(128) |
|||
->willReturn($this->file); |
|||
|
|||
$this->file->method('getMimeType') |
|||
->willReturn('image/svg+xml'); |
|||
|
|||
$response = $this->guestAvatarController->getAvatar('Peter', 128); |
|||
|
|||
$this->assertGreaterThanOrEqual(201, $response->getStatus()); |
|||
$this->assertInstanceOf(FileDisplayResponse::class, $response); |
|||
$this->assertSame($this->file, $response->getFile()); |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<svg width="32" height="32" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> |
|||
<rect width="100%" height="100%" fill="#499aa2"></rect> |
|||
<text x="50%" y="350" style="font-weight:normal;font-size:279px;font-family:'Nunito';text-anchor:middle;fill:#fff">E</text> |
|||
</svg> |
|||
@ -0,0 +1,80 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace Test\Avatar; |
|||
|
|||
use OC\Avatar\GuestAvatar; |
|||
use OCP\Files\SimpleFS\InMemoryFile; |
|||
use OCP\ILogger; |
|||
use PHPUnit\Framework\MockObject\MockObject; |
|||
use Test\TestCase; |
|||
|
|||
/** |
|||
* This class provides test cases for the GuestAvatar class. |
|||
* |
|||
* @package Test\Avatar |
|||
*/ |
|||
class GuestAvatarTest extends TestCase { |
|||
/** |
|||
* @var GuestAvatar |
|||
*/ |
|||
private $guestAvatar; |
|||
|
|||
/** |
|||
* Setups a guest avatar instance for tests. |
|||
* |
|||
* @before |
|||
* @return void |
|||
*/ |
|||
public function setupGuestAvatar() { |
|||
/* @var MockObject|ILogger $logger */ |
|||
$logger = $this->getMockBuilder(ILogger::class)->getMock(); |
|||
$this->guestAvatar = new GuestAvatar('einstein', $logger); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that testGet() returns the expected avatar. |
|||
* |
|||
* For the test a static name "einstein" is used and |
|||
* the generated image is compared with an expected one. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGet() { |
|||
$avatar = $this->guestAvatar->getFile(32); |
|||
self::assertInstanceOf(InMemoryFile::class, $avatar); |
|||
$expectedFile = file_get_contents( |
|||
__DIR__ . '/../../data/guest_avatar_einstein_32.svg' |
|||
); |
|||
self::assertEquals(trim($expectedFile), trim($avatar->getContent())); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that "testIsCustomAvatar" returns false for guests. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testIsCustomAvatar() { |
|||
self::assertFalse($this->guestAvatar->isCustomAvatar()); |
|||
} |
|||
} |
|||
@ -0,0 +1,145 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
*/ |
|||
|
|||
namespace Test\File\SimpleFS; |
|||
|
|||
use OCP\Files\NotPermittedException; |
|||
use OCP\Files\SimpleFS\InMemoryFile; |
|||
use Test\TestCase; |
|||
|
|||
/** |
|||
* This class provide test casesf or the InMemoryFile. |
|||
* |
|||
* @package Test\File\SimpleFS |
|||
*/ |
|||
class InMemoryFileTest extends TestCase { |
|||
/** |
|||
* Holds a pdf file with know attributes for tests. |
|||
* |
|||
* @var InMemoryFile |
|||
*/ |
|||
private $testPdf; |
|||
|
|||
/** |
|||
* Sets the test file from "./resources/test.pdf". |
|||
* |
|||
* @before |
|||
* @return void |
|||
*/ |
|||
public function setupTestPdf() { |
|||
$fileContents = file_get_contents( |
|||
__DIR__ . '/../../../data/test.pdf' |
|||
); |
|||
$this->testPdf = new InMemoryFile('test.pdf', $fileContents); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that putContent replaces the file contents. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testPutContent() { |
|||
$this->testPdf->putContent('test'); |
|||
self::assertEquals('test', $this->testPdf->getContent()); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that delete() doesn't rise an exception. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testDelete() { |
|||
$this->testPdf->delete(); |
|||
// assert true, otherwise phpunit complains about not doing any assert
|
|||
self::assertTrue(true); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that getName returns the name passed on file creation. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetName() { |
|||
self::assertEquals('test.pdf', $this->testPdf->getName()); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that the file size is the size of the test file. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetSize() { |
|||
self::assertEquals(7083, $this->testPdf->getSize()); |
|||
} |
|||
|
|||
/** |
|||
* Asserts the file contents are the same than the original file contents. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetContent() { |
|||
self::assertEquals( |
|||
file_get_contents(__DIR__ . '/../../../data/test.pdf'), |
|||
$this->testPdf->getContent() |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Asserts the test file modification time is an integer. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetMTime() { |
|||
self::assertTrue(is_int($this->testPdf->getMTime())); |
|||
} |
|||
|
|||
/** |
|||
* Asserts the test file mime type is "application/json". |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetMimeType() { |
|||
self::assertEquals('application/pdf', $this->testPdf->getMimeType()); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Asserts that read() raises an NotPermittedException. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testRead() { |
|||
self::expectException(NotPermittedException::class); |
|||
$this->testPdf->read(); |
|||
} |
|||
|
|||
/** |
|||
* Asserts that write() raises an NotPermittedException. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testWrite() { |
|||
self::expectException(NotPermittedException::class); |
|||
$this->testPdf->write(); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue