...
 
Commits (10)
......@@ -326,14 +326,20 @@ class blog implements Interfaces\Api
}
if ($saved && is_uploaded_file($_FILES['file']['tmp_name'])) {
/** @var Core\Media\Imagick\Manager $manager */
$manager = Core\Di\Di::_()->get('Media\Imagick\Manager');
$manager->setImage($_FILES['file']['tmp_name'])
->resize(2000, 1000);
try {
$manager->setImage($_FILES['file']['tmp_name'])
->resize(2000, 1000);
$header->write($blog, $manager->getJpeg(), isset($_POST['header_top']) ? (int) $_POST['header_top'] : 0);
$header->write($blog, $manager->getJpeg(), isset($_POST['header_top']) ? (int)$_POST['header_top'] : 0);
} catch (\ImagickException $e) {
return Factory::response([
'status' => 'error',
'message' => 'Invalid image file',
]);
}
}
if ($saved) {
......
......@@ -13,6 +13,7 @@ use Minds\Helpers;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Core\Features\Manager as FeaturesManager;
class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -28,6 +29,17 @@ class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
exit;
}
$featuresManager = new FeaturesManager();
if ($featuresManager->has('cdn-jwt')) {
error_log("{$_SERVER['REQUEST_URI']} was hit, and should not have been");
return Factory::response([
'status' => 'error',
'message' => 'This endpoint has been deprecated. Please use fs/v1/thumbnail',
]);
}
$guid = $pages[0];
Core\Security\ACL::$ignore = true;
......
......@@ -53,6 +53,7 @@ class views implements Interfaces\Api
$viewsManager->record(
(new Core\Analytics\Views\View())
->setEntityUrn($boost->getEntity()->getUrn())
->setOwnerGuid((string) $boost->getEntity()->getOwnerGuid())
->setClientMeta($_POST['client_meta'] ?? [])
);
} catch (\Exception $e) {
......@@ -105,6 +106,7 @@ class views implements Interfaces\Api
$viewsManager->record(
(new Core\Analytics\Views\View())
->setEntityUrn($activity->getUrn())
->setOwnerGuid((string) $activity->getOwnerGuid())
->setClientMeta($_POST['client_meta'] ?? [])
);
} catch (\Exception $e) {
......
......@@ -8,6 +8,7 @@ use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Core\Features\Manager as FeaturesManager;
class thumbnail extends Core\page implements Interfaces\page
{
......@@ -17,6 +18,16 @@ class thumbnail extends Core\page implements Interfaces\page
exit;
}
$featuresManager = new FeaturesManager;
if ($featuresManager->has('cdn-jwt')) {
$signedUri = new Core\Security\SignedUri();
$uri = (string) \Zend\Diactoros\ServerRequestFactory::fromGlobals()->getUri();
if (!$signedUri->confirm($uri)) {
exit;
}
}
/** @var Core\Media\Thumbnails $mediaThumbnails */
$mediaThumbnails = Di::_()->get('Media\Thumbnails');
......
......@@ -55,6 +55,7 @@ class ElasticRepository
'uuid' => $view->getUuid(),
'@timestamp' => $view->getTimestamp() * 1000,
'entity_urn' => $view->getEntityUrn(),
'owner_guid' => $view->getOwnerGuid(),
'page_token' => $view->getPageToken(),
'campaign' => $view->getCampaign(),
'delta' => (int) $view->getDelta(),
......
......@@ -104,6 +104,7 @@ class Repository
->setDay((int) $row['day'] ?: null)
->setUuid($row['uuid']->uuid() ?: null)
->setEntityUrn($row['entity_urn'])
->setOwnerGuid($row['owner_guid'])
->setPageToken($row['page_token'])
->setPosition((int) $row['position'])
->setSource($row['platform'])
......@@ -135,13 +136,14 @@ class Repository
$timestamp = $view->getTimestamp() ?: time();
$date = new DateTime("@{$timestamp}", new DateTimeZone('utc'));
$cql = "INSERT INTO views (year, month, day, uuid, entity_urn, page_token, position, platform, source, medium, campaign, delta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$cql = "INSERT INTO views (year, month, day, uuid, entity_urn, owner_guid, page_token, position, platform, source, medium, campaign, delta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$values = [
(int) ($view->getYear() ?? $date->format('Y')),
new Tinyint((int) ($view->getMonth() ?? $date->format('m'))),
new Tinyint((int) ($view->getDay() ?? $date->format('d'))),
new Timeuuid($view->getUuid() ?? $timestamp * 1000),
$view->getEntityUrn() ?: '',
(string) ($view->getOwnerGuid() ?? ''),
$view->getPageToken() ?: '',
(int) ($view->getPosition() ?? -1),
$view->getPlatform() ?: '',
......
......@@ -21,6 +21,8 @@ use Minds\Traits\MagicAttributes;
* @method string getUuid()
* @method View setEntityUrn(string $entityUrn)
* @method string getEntityUrn()
* @method View setOwnerGuid(string $ownerGuid)
* @method string getOwnerGuid()
* @method View setPageToken(string $pageToken)
* @method string getPageToken()
* @method View setPosition(int $position)
......@@ -57,6 +59,9 @@ class View
/** @var string */
protected $entityUrn;
/** @var string */
protected $ownerGuid;
/** @var string */
protected $pageToken;
......
......@@ -9,6 +9,7 @@ use Minds\Entities\RepositoryEntity;
use Minds\Entities\User;
use Minds\Helpers\Flags;
use Minds\Helpers\Unknown;
use Minds\Core\Di\Di;
/**
* Comment Entity
......@@ -284,6 +285,21 @@ class Comment extends RepositoryEntity
return "{$this->getParentGuidL1()}:{$this->getParentGuidL2()}:{$this->getGuid()}";
}
/**
* Return an array of thumbnails
* @return array
*/
public function getThumbnails(): array
{
$thumbnails = [];
$mediaManager = Di::_()->get('Media\Image\Manager');
$sizes = [ 'xlarge', 'large' ];
foreach ($sizes as $size) {
$thumbnails[$size] = $mediaManager->getPublicAssetUri($this, $size);
}
return $thumbnails;
}
/**
* Return the urn for the comment
* @return string
......@@ -384,6 +400,8 @@ class Comment extends RepositoryEntity
$output['thumbs:down:count'] = count($this->getVotesDown());
}
$output['thumbnails'] = $this->getThumbnails();
$output['can_reply'] = (bool) !$this->getParentGuidL2();
//$output['parent_guid'] = (string) $this->entityGuid;
......
......@@ -5,21 +5,40 @@
namespace Minds\Core\Data\PubSub\Redis;
use Minds\Core\Config;
use \Redis as RedisServer;
class Client
{
/**
* @var \Redis
*/
private $redis;
/**
* @var string
*/
private $host;
public function __construct($redis = null)
{
if (class_exists('\Redis')) {
$this->redis = $redis ?: new RedisServer();
$this->redis = $redis ?: new \Redis();
$config = Config::_()->get('redis');
try {
$this->redis->connect($config['pubsub'] ?: $config['master'] ?: '127.0.0.1');
} catch (\Exception $e) {
$this->host = $config['pubsub'] ?: $config['master'] ?: '127.0.0.1';
$this->connect();
}
}
/**
* @throws \Exception
*/
public function connect(): void
{
if (!$this->redis instanceof \Redis) {
$this->redis = new \Redis();
}
if (!$this->redis->isConnected()) {
if (!@$this->redis->connect($this->host)) {
throw new \Exception("Unable to connect to Redis: " . $this->redis->getLastError());
}
}
}
......@@ -34,11 +53,17 @@ class Client
}
}
/**
* @param $channel
* @param string $data
* @return bool|int
*/
public function publish($channel, $data = '')
{
if (!$this->redis) {
if (!$this->redis->isConnected()) {
return false;
}
return $this->redis->publish($channel, $data);
}
}
<?php
/**
* Image Manager
*/
namespace Minds\Core\Media\Image;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Minds\Entities\Entity;
use Minds\Entities\Activity;
use Minds\Entities\Image;
use Minds\Entities\Video;
use Minds\Core\Comments\Comment;
use Minds\Core\Security\SignedUri;
use Lcobucci\JWT;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Zend\Diactoros\Uri;
class Manager
{
/** @var Config $config */
private $config;
/** @var SignedUri $signedUri */
private $signedUri;
public function __construct($config = null, $signedUri = null)
{
$this->config = $config ?? Di::_()->get('Config');
$this->signedUri = $signedUri ?? new SignedUri;
}
/**
* Return a public asset uri for entity type
* @param Entity $entity
* @param string $size
* @return string
*/
public function getPublicAssetUri($entity, $size = 'xlarge'): string
{
$uri = null;
$asset_guid = null;
switch (get_class($entity)) {
case Activity::class:
switch ($entity->get('custom_type')) {
case "batch":
$asset_guid = $entity->get('entity_guid');
break;
default:
$asset_guid = $entity->get('entity_guid');
}
break;
case Image::class:
$asset_guid = $entity->getGuid();
break;
case Video::class:
$asset_guid = $entity->getGuid();
break;
case Comment::class:
$asset_guid = $entity->getAttachments()['attachment_guid'];
break;
}
$uri = $this->config->get('cdn_url') . 'fs/v1/thumbnail/' . $asset_guid . '/' . $size;
$uri = $this->signUri($uri);
return $uri;
}
/**
* Sign a uri and return the uri with the signature attached
* @param string $uri
* @return string
*/
private function signUri($uri, $pub = ""): string
{
$now = new \DateTime();
$expires = $now->modify('midnight + 30 days')->getTimestamp();
return $this->signedUri->sign($uri, $expires);
}
/**
* Config signed uri
* @param string $uri
* @return string
*/
public function confirmSignedUri($uri): bool
{
return $this->signedUri->confirm($uri);
}
}
......@@ -12,6 +12,12 @@ class MediaProvider extends Provider
{
public function register()
{
$this->di->bind('Media\Image\Manager', function ($di) {
return new Image\Manager();
}, ['useFactory' => true]);
$this->di->bind('Media\Video\Manager', function ($di) {
return new Video\Manager();
}, ['useFactory' => true]);
$this->di->bind('Media\Albums', function ($di) {
return new Albums(new Core\Data\Call('entities_by_time'));
}, ['useFactory' => true]);
......
<?php
/**
* Video Manager
*/
namespace Minds\Core\Media\Video;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Minds\Entities\Entity;
use Minds\Entities\Activity;
use Minds\Entities\Image;
use Minds\Entities\Video;
use Minds\Core\Comments\Comment;
use Aws\S3\S3Client;
class Manager
{
/** @var Config $config */
private $config;
/** @var S3Client $s3 */
private $s3;
public function __construct($config = null, $s3 = null)
{
$this->config = $config ?? Di::_()->get('Config');
// AWS
$awsConfig = $this->config->get('aws');
$opts = [
'region' => $awsConfig['region'],
];
if (!isset($awsConfig['useRoles']) || !$awsConfig['useRoles']) {
$opts['credentials'] = [
'key' => $awsConfig['key'],
'secret' => $awsConfig['secret'],
];
}
$this->s3 = $s3 ?: new S3Client(array_merge(['version' => '2006-03-01'], $opts));
}
/**
* Return a public asset uri for entity type
* @param Entity $entity
* @param string $size
* @return string
*/
public function getPublicAssetUri($entity, $size = '360.mp4'): string
{
$cmd = null;
switch (get_class($entity)) {
case Activity::class:
// To do
break;
case Video::class:
$cmd = $this->s3->getCommand('GetObject', [
'Bucket' => 'cinemr', // TODO: don't hard code
'Key' => $this->config->get('transcoder')['dir'] . "/" . $entity->get('cinemr_guid') . "/" . $size,
]);
break;
}
if (!$cmd) {
return null;
}
return (string) $this->s3->createPresignedRequest($cmd, '+20 minutes')->getUri();
}
}
......@@ -1446,6 +1446,8 @@ CREATE TABLE minds.email_campaign_logs (
PRIMARY KEY (receiver_guid, time_sent)
) WITH CLUSTERING ORDER BY (time_sent desc);
ALTER TABLE minds.views ADD owner_guid text;
CREATE TABLE minds.pro (
user_guid bigint,
domain text,
......
<?php
namespace Minds\Core\Security;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Lcobucci\JWT;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Zend\Diactoros\Uri;
class SignedUri
{
/** @Var JWT\Builder $jwtBuilder */
private $jwtBuilder;
/** @var JWT\Parser $jwtParser */
private $jwtParser;
/** @var Config $config */
private $config;
public function __construct($jwtBuilder = null, $jwtParser = null, $config = null)
{
$this->jwtBuilder = $jwtBuilder ?? new JWT\Builder;
$this->jwtParser = $jwtParser ?? new JWT\Parser();
$this->config = $config ?? Di::_()->get('Config');
}
/**
* Sign the uri
* @param string $uri
* @param int $ttl - defaults to 1 day
* @return string
*/
public function sign($uri, $expires = 86400): string
{
$uri = new Uri($uri);
$expires = (new \DateTime())->modify('midnight first day of next month')->modify('+1 month')->getTimestamp();
$token = (new $this->jwtBuilder)
//->setId((string) $uri)
->setExpiration($expires)
->set('uri', (string) $uri)
->set('user_guid', (string) Session::getLoggedInUser()->getGuid())
->sign(new Sha256, $this->config->get('sessions')['private_key'])
->getToken();
$signedUri = $uri->withQuery("jwtsig=$token");
return (string) $signedUri;
}
/**
* Confirm signed uri
* @param string $uri
* @return string
*/
public function confirm($uri): bool
{
$providedUri = new Uri($uri);
parse_str($providedUri->getQuery(), $queryParams);
$providedSig = $queryParams['jwtsig'];
$token = $this->jwtParser->parse($providedSig);
if (!$token->verify(new Sha256, $this->config->get('sessions')['private_key'])) {
return false;
}
return ((string) $token->getClaim('uri') === (string) $providedUri->withQuery(''));
}
}
......@@ -4,15 +4,22 @@
*/
namespace Minds\Core\Sockets;
use Minds\Core\Data\PubSub;
use Minds\Core\Di\Di;
use Minds\Core\Config;
use Minds\Entities\User;
class Events
{
/**
* @var PubSub\Redis\Client
*/
private $redis;
/**
* @var MsgPack
*/
private $msgpack;
private $prefix = 'socket.io';
private $prefix = 'socket.io#';
private $rooms = [];
private $flags = [];
......@@ -25,7 +32,6 @@ class Events
{
$this->redis = $redis ?: Di::_()->get('PubSub\Redis');
$this->msgpack = $msgpack ?: new MsgPack();
$this->prefix = (isset($config['socket-prefix']) ? $config['socket-prefix'] : 'socket.io') . '#';
}
public function emit(/*$event, ...$data*/)
......@@ -82,7 +88,7 @@ class Events
$packed = str_replace(pack('c', 0xdb), pack('c', 0xd9), $packed);
}
// Publish
// Publish - TODO: Log + track possible Redis failures if false is returned
$this->redis->publish($this->prefix . $packet['nsp'] . '#', $packed);
// Reset
......
......@@ -67,7 +67,7 @@ class S3 implements ServiceInterface
$mimeType = $finfo->buffer($data);
$write = $this->s3->putObject([
'ACL' => 'public-read',
// 'ACL' => 'public-read',
'Bucket' => Config::_()->aws['bucket'],
'Key' => $this->filepath,
'ContentType' => $mimeType,
......@@ -121,6 +121,20 @@ class S3 implements ServiceInterface
}
}
/**
* Return a signed url
* @return string
*/
public function getSignedUrl(): string
{
$cmd = $this->s3->getCommand('GetObject', [
'Bucket' => Config::_()->aws['bucket'],
'Key' => $this->filepath,
]);
$request = $this->s3->createPresignedRequest($cmd, '+20 minutes');
return (string) $request->getUri();
}
public function seek($offset = 0)
{
//not supported
......
......@@ -3,6 +3,7 @@ namespace Minds\Entities;
use Minds\Helpers;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Core\Queue;
use Minds\Core\Analytics;
......@@ -279,6 +280,8 @@ class Activity extends Entity
$export['hide_impressions'] = $this->hide_impressions;
}
$export['thumbnails'] = $this->getThumbnails();
switch ($this->custom_type) {
case 'video':
if ($this->custom_data['guid']) {
......@@ -289,7 +292,11 @@ class Activity extends Entity
// fix old images src
if (is_array($export['custom_data']) && strpos($export['custom_data'][0]['src'], '/wall/attachment') !== false) {
$export['custom_data'][0]['src'] = Core\Config::_()->cdn_url . 'fs/v1/thumbnail/' . $this->entity_guid;
$this->custom_data[0]['src'] = $export['custom_data'][0]['src'];
}
// go directly to cdn
$mediaManager = Di::_()->get('Media\Image\Manager');
$export['custom_data'][0]['src'] = $export['thumbnails']['xlarge'];
break;
}
......@@ -720,6 +727,27 @@ class Activity extends Entity
return $this->ownerObj;
}
/**
* Return thumbnails array to be used with export
* @return array
*/
public function getThumbnails(): array
{
$thumbnails = [];
switch ($this->custom_type) {
case 'video':
break;
case 'batch':
$mediaManager = Di::_()->get('Media\Image\Manager');
$sizes = [ 'xlarge', 'large' ];
foreach ($sizes as $size) {
$thumbnails[$size] = $mediaManager->getPublicAssetUri($this, $size);
}
break;
}
return $thumbnails;
}
/**
* Return a preferred urn
* @return string
......
......@@ -5,6 +5,7 @@
namespace Minds\Entities;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Helpers;
class Image extends File
......@@ -33,17 +34,18 @@ class Image extends File
$size = '';
}
if (isset($CONFIG->cdn_url) && !$this->getFlag('paywall') && !$this->getWireThreshold()) {
$base_url = $CONFIG->cdn_url;
} else {
$base_url = \elgg_get_site_url();
}
// if (isset($CONFIG->cdn_url) && !$this->getFlag('paywall') && !$this->getWireThreshold()) {
// $base_url = $CONFIG->cdn_url;
// } else {
// $base_url = \elgg_get_site_url();
// }
if ($this->access_id != 2) {
$base_url = \elgg_get_site_url();
}
// if ($this->access_id != 2) {
// $base_url = \elgg_get_site_url();
// }
$mediaManager = Di::_()->get('Media\Image\Manager');
return $base_url. 'api/v1/media/thumbnails/' . $this->guid . '/'.$size;
return $mediaManager->getPublicAssetUri($this, $size);
}
protected function getIndexKeys($ia = false)
......@@ -211,7 +213,8 @@ class Image extends File
public function export()
{
$export = parent::export();
$export['thumbnail_src'] = $this->getIconUrl();
$export['thumbnail_src'] = $this->getIconUrl('xlarge');
$export['thumbnail'] = $export['thumbnail_src'];
$export['thumbs:up:count'] = Helpers\Counters::get($this->guid, 'thumbs:up');
$export['thumbs:down:count'] = Helpers\Counters::get($this->guid, 'thumbs:down');
$export['description'] = $this->description; //videos need to be able to export html.. sanitize soon!
......
......@@ -8,6 +8,7 @@ namespace Minds\Entities;
use Minds\Core;
use Minds\Core\Media\Services\Factory as ServiceFactory;
use Minds\Core\Di\Di;
use cinemr;
use Minds\Helpers;
......@@ -38,8 +39,8 @@ class Video extends Object
*/
public function getSourceUrl($transcode = '720.mp4')
{
$url = Core\Config::_()->cinemr_url . $this->cinemr_guid . '/' . $transcode;
return $url;
$mediaManager = Di::_()->get('Media\Video\Manager');
return $mediaManager->getPublicAssetUri($this, $transcode);
}
/**
......@@ -61,13 +62,16 @@ class Video extends Object
public function getIconUrl($size = "medium")
{
$domain = elgg_get_site_url();
global $CONFIG;
if (isset($CONFIG->cdn_url) && !$this->getFlag('paywall') && !$this->getWireThreshold()) {
$domain = $CONFIG->cdn_url;
}
// $domain = elgg_get_site_url();
// global $CONFIG;
// if (isset($CONFIG->cdn_url) && !$this->getFlag('paywall') && !$this->getWireThreshold()) {
// $domain = $CONFIG->cdn_url;
// }
// return $domain . 'api/v1/media/thumbnails/' . $this->guid . '/' . $this->time_updated;
return $domain . 'api/v1/media/thumbnails/' . $this->guid . '/' . $this->time_updated;
$mediaManager = Di::_()->get('Media\Image\Manager');
return $mediaManager->getPublicAssetUri($this, 'medium');
}
public function getURL()
......
......@@ -61,6 +61,10 @@ class RepositorySpec extends ObjectBehavior
->shouldBeCalled()
->willReturn('urn:test:123123');
$view->getOwnerGuid()
->shouldBeCalled()
->wilLReturn('789');
$view->getPageToken()
->shouldBeCalled()
->willReturn('1234-qwe-qwe-1234');
......@@ -98,13 +102,14 @@ class RepositorySpec extends ObjectBehavior
$statement['values'][2]->toInt() === 29 &&
$statement['values'][3]->uuid() === 'abc-123-456-def' &&
$statement['values'][4] === 'urn:test:123123' &&
$statement['values'][5] === '1234-qwe-qwe-1234' &&
$statement['values'][6] === 5 &&
$statement['values'][7] === 'php' &&
$statement['values'][8] === 'phpspec' &&
$statement['values'][9] === 'test' &&
$statement['values'][10] === 'urn:phpspec:234234' &&
$statement['values'][11] === 100;
$statement['values'][5] === '789' &&
$statement['values'][6] === '1234-qwe-qwe-1234' &&
$statement['values'][7] === 5 &&
$statement['values'][8] === 'php' &&
$statement['values'][9] === 'phpspec' &&
$statement['values'][10] === 'test' &&
$statement['values'][11] === 'urn:phpspec:234234' &&
$statement['values'][12] === 100;
}), true)
->shouldBeCalled()
->willReturn(true);
......@@ -143,6 +148,10 @@ class RepositorySpec extends ObjectBehavior
->shouldBeCalled()
->willReturn('urn:test:123123');
$view->getOwnerGuid()
->shouldBeCalled()
->willReturn(789);
$view->getPageToken()
->shouldBeCalled()
->willReturn('1234-qwe-qwe-1234');
......@@ -180,13 +189,14 @@ class RepositorySpec extends ObjectBehavior
$statement['values'][2]->toInt() === 29 &&
$statement['values'][3]->time() === $now * 1000 &&
$statement['values'][4] === 'urn:test:123123' &&
$statement['values'][5] === '1234-qwe-qwe-1234' &&
$statement['values'][6] === 5 &&
$statement['values'][7] === 'php' &&
$statement['values'][8] === 'phpspec' &&
$statement['values'][9] === 'test' &&
$statement['values'][10] === 'urn:phpspec:234234' &&
$statement['values'][11] === 100;
$statement['values'][5] === '789' &&
$statement['values'][6] === '1234-qwe-qwe-1234' &&
$statement['values'][7] === 5 &&
$statement['values'][8] === 'php' &&
$statement['values'][9] === 'phpspec' &&
$statement['values'][10] === 'test' &&
$statement['values'][11] === 'urn:phpspec:234234' &&
$statement['values'][12] === 100;
}), true)
->shouldBeCalled()
->willReturn(true);
......
<?php
namespace Spec\Minds\Core\Media\Image;
use Minds\Core\Media\Image\Manager;
use Minds\Core\Config;
use Minds\Core\Security\SignedUri;
use Minds\Entities\Activity;
use Minds\Entities\Image;
use Minds\Entities\Video;
use Minds\Core\Comments\Comment;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ManagerSpec extends ObjectBehavior
{
private $config;
private $signedUri;
public function let(Config $config, SignedUri $signedUri)
{
$this->beConstructedWith($config, $signedUri);
$this->config = $config;
$this->signedUri = $signedUri;
}
public function it_is_initializable()
{
$this->shouldHaveType(Manager::class);
}
public function it_should_return_public_asset_uri()
{
$activity = new Activity();
$activity->set('entity_guid', 123);
$this->config->get('cdn_url')
->willReturn('https://minds.dev/');
$uri = 'https://minds.dev/fs/v1/thumbnail/123/xlarge';
$this->signedUri->sign($uri, Argument::any())
->willReturn('signed url will be here');
$this->getPublicAssetUri($activity)
->shouldBe('signed url will be here');
}
public function it_should_return_public_asset_uri_for_image()
{
$entity = new Image();
$entity->set('guid', 123);
$this->config->get('cdn_url')
->willReturn('https://minds.dev/');
$uri = 'https://minds.dev/fs/v1/thumbnail/123/xlarge';
$this->signedUri->sign($uri, Argument::any())
->willReturn('signed url will be here');
$this->getPublicAssetUri($entity)
->shouldBe('signed url will be here');
}
public function it_should_return_public_asset_uri_for_video()
{
$entity = new Video();
$entity->set('guid', 123);
$this->config->get('cdn_url')
->willReturn('https://minds.dev/');
$uri = 'https://minds.dev/fs/v1/thumbnail/123/xlarge';
$this->signedUri->sign($uri, Argument::any())
->willReturn('signed url will be here');
$this->getPublicAssetUri($entity)
->shouldBe('signed url will be here');
}
public function it_should_return_public_asset_uri_for_comment()
{
$entity = new Comment();
$entity->setAttachment('attachment_guid', '123');
$this->config->get('cdn_url')
->willReturn('https://minds.dev/');
$uri = 'https://minds.dev/fs/v1/thumbnail/123/xlarge';
$this->signedUri->sign($uri, Argument::any())
->willReturn('signed url will be here');
$this->getPublicAssetUri($entity)
->shouldBe('signed url will be here');
}
}
<?php
namespace Spec\Minds\Core\Media\Video;
use Minds\Core\Config;
use Aws\S3\S3Client;
use Minds\Core\Media\Video\Manager;
use Minds\Entities\Video;
use Psr\Http\Message\RequestInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ManagerSpec extends ObjectBehavior
{
private $config;
private $s3;
public function let(Config $config, S3Client $s3)
{
$this->beConstructedWith($config, $s3);
$this->config = $config;
$this->s3 = $s3;
}
public function it_is_initializable()
{
$this->shouldHaveType(Manager::class);
}
public function it_should_get_a_720p_video(RequestInterface $request, \Aws\CommandInterface $cmd)
{
$this->config->get('transcoder')
->willReturn([
'dir' => 'dir',
]);
$this->config->get('aws')
->willReturn([
'region' => 'us-east-1',
'useRoles' => true,
]);
$this->s3->getCommand('GetObject', [
'Bucket' => 'cinemr',
'Key' => 'dir/123/720.mp4'
])
->shouldBeCalled()
->willReturn($cmd);
$request->getUri()
->willReturn('s3-signed-url-here');
$this->s3->createPresignedRequest(Argument::any(), Argument::any())
->willReturn($request);
$video = new Video();
$video->set('cinemr_guid', 123);
$this->getPublicAssetUri($video, '720.mp4')
->shouldBe('s3-signed-url-here');
}
}
<?php
namespace Spec\Minds\Core\Security;
use Minds\Core\Security\SignedUri;
use Minds\Entities\User;
use Minds\Core\Config;
use Lcobucci\JWT;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class SignedUriSpec extends ObjectBehavior
{
public function it_is_initializable()
{
$this->shouldHaveType(SignedUri::class);
}
public function it_sign_a_uri(Config $config)
{
$user = new User();
$user->set('guid', 123);
$user->set('username', 'phpspec');
\Minds\Core\Session::setUser($user);
$this->beConstructedWith(null, null, $config);
$config->get('sessions')
->willReturn([
'private_key' => 'priv-key'
]);
$this->sign("https://minds-dev/foo")
->shouldContain("https://minds-dev/foo?jwtsig=");
}
public function it_should_verify_a_uri_was_signed(Config $config)
{
$this->beConstructedWith(null, null, $config);
$config->get('sessions')
->willReturn([
'private_key' => 'priv-key'
]);
$uri = "https://minds-dev/foo?jwtsig=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NzI1NjY0MDAsInVyaSI6Imh0dHBzOlwvXC9taW5kcy1kZXZcL2ZvbyIsInVzZXJfZ3VpZCI6IjEyMyJ9.jqOq0k-E4h1I0PHnc_WkmWqXonRU4yWq_ymoOYoaDvc";
$this->confirm($uri)
->shouldBe(true);
}
public function it_should_not_very_a_wrongly_signed_uri(Config $config)
{
$this->beConstructedWith(null, null, $config);
$config->get('sessions')
->willReturn([
'private_key' => 'priv-key'
]);
$uri = "https://minds-dev/bar?jwtsig=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NzI1NjY0MDAsInVyaSI6Imh0dHBzOlwvXC9taW5kcy1kZXZcL2ZvbyIsInVzZXJfZ3VpZCI6IjEyMyJ9.jqOq0k-E4h1I0PHnc_WkmWqXonRU4yWq_ymoOYoaDvc";
$this->confirm($uri)
->shouldBe(false);
}
}
......@@ -3,6 +3,7 @@
"description": "The core minds social engine",
"require": {
"php": "~7.1",
"ext-redis": "~4.3",
"aws/aws-sdk-php": "^3.38",
"braintree/braintree_php": "3.5.0",
"datastax/php-driver": "1.2.2",
......
......@@ -476,7 +476,8 @@ $CONFIG->set('features', [
'cassandra-notifications' => true,
'dark-mode' => true,
'allow-comments-toggle' => false,
'permissions' => false
'permissions' => false,
'pro' => false,
]);
$CONFIG->set('email', [
......