...
 
Commits (56)
image: minds/php:latest
services:
- docker:dind
image: minds/php:7.3
stages:
- build
......@@ -16,7 +13,7 @@ stages:
build:
stage: build
script:
- apk update && apk add --no-cache git
- apk add --no-cache git
- sh tools/setup.sh production
artifacts:
name: '$CI_COMMIT_REF_SLUG'
......@@ -26,19 +23,21 @@ build:
test:
stage: test
image: minds/php-tests:latest
image: minds/php:7.3
script:
- bin/phpspec run
- php -n -c Spec/php-test.ini bin/phpspec run
lint:
stage: test
image: minds/php-tests:latest
image: minds/php:7.3
script:
- bin/php-cs-fixer fix --allow-risky=yes --verbose --dry-run
prepare:fpm:
stage: prepare
image: minds/ci:latest
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
- |
......@@ -53,6 +52,8 @@ prepare:fpm:
prepare:runners:
stage: prepare
image: minds/ci:latest
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
- |
......@@ -136,6 +137,8 @@ qa:manual:
staging:fpm:
stage: deploy:staging
image: minds/ci:latest
services:
- docker:dind
script:
- IMAGE_LABEL="staging"
- $(aws ecr get-login --no-include-email --region us-east-1)
......@@ -162,6 +165,8 @@ staging:fpm:
canary:fpm:
stage: deploy:canary
image: minds/ci:latest
services:
- docker:dind
script:
- IMAGE_LABEL="canary"
- $(aws ecr get-login --no-include-email --region us-east-1)
......@@ -190,6 +195,8 @@ canary:fpm:
production:fpm:
stage: deploy:production
image: minds/ci:latest
services:
- docker:dind
script:
- IMAGE_LABEL="production"
- $(aws ecr get-login --no-include-email --region us-east-1)
......@@ -218,6 +225,8 @@ production:fpm:
production:runners:
stage: deploy:production
image: minds/ci:latest
services:
- docker:dind
script:
- IMAGE_LABEL="production"
- $(aws ecr get-login --no-include-email --region us-east-1)
......
......@@ -2,10 +2,7 @@
namespace Minds\Api;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Domain\Security as ProDomainSecurity;
use Minds\Interfaces;
use Minds\Helpers;
use Minds\Core\Security;
use Minds\Core\Session;
......@@ -111,11 +108,17 @@ class Factory
static::setCORSHeader();
$code = !Security\XSRF::validateRequest() ? 403 : 401;
if (isset($_SERVER['HTTP_APP_VERSION'])) {
$code = 401; // Mobile requires 401 errors
}
header('Content-type: application/json');
header('HTTP/1.1 401 Unauthorized', true, 401);
http_response_code($code);
echo json_encode([
'error' => 'Sorry, you are not authenticated',
'code' => 401,
'code' => $code,
'loggedin' => false
]);
exit;
......
......@@ -40,12 +40,14 @@ class CustomerSync extends Cli\Controller implements Interfaces\CliControllerInt
$guid = $data[29];
try {
$insert = new Core\Data\Cassandra\Prepared\Custom();
$insert->query("INSERT INTO user_index_to_guid (key, column1, value) VALUES (?, ?, ?)",
[
$insert->query(
"INSERT INTO user_index_to_guid (key, column1, value) VALUES (?, ?, ?)",
[
"$guid:payments",
"customer_id",
$id
]);
]
);
$this->db->request($insert);
$this->out("$guid with customer id $id done");
} catch (\Exception $e) {
......
......@@ -56,18 +56,21 @@ class SubscriptionSync extends Cli\Controller implements Interfaces\CliControlle
$amount = ($result->quantity * $result->plan->amount) / 100;
$insert = new Core\Data\Cassandra\Prepared\Custom();
$insert->query("INSERT INTO plans (user_guid, plan, entity_guid, amount) VALUES (?, ?, ?, ?)",
[
$insert->query(
"INSERT INTO plans (user_guid, plan, entity_guid, amount) VALUES (?, ?, ?, ?)",
[
$plan['user_guid'],
$plan['plan'],
$plan['entity_guid'],
(int) $amount
]);
]
);
$this->db->request($insert);
if ($plan['plan'] == 'exclusive') {
$query = new Core\Data\Cassandra\Prepared\Custom();
$query->query("INSERT INTO wire
$query->query(
"INSERT INTO wire
(receiver_guid, sender_guid, method, timestamp, entity_guid, wire_guid, amount, recurring, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
[
......@@ -80,7 +83,8 @@ class SubscriptionSync extends Cli\Controller implements Interfaces\CliControlle
new \Cassandra\Decimal($amount),
true,
'success'
]);
]
);
$this->db->request($query);
}
......
......@@ -36,8 +36,12 @@ class report implements Interfaces\Api
/** @var Core\Reports\Repository $repository */
$repository = Di::_()->get('Reports\Repository');
$done = $repository->create($pages[0], Core\Session::getLoggedinUser(),
$reason, $reason_note);
$done = $repository->create(
$pages[0],
Core\Session::getLoggedinUser(),
$reason,
$reason_note
);
return Factory::response([
'done' => $done
......
......@@ -85,7 +85,7 @@ class media implements Interfaces\Api, Interfaces\ApiIgnorePam
Security\ACL::$ignore = $ignore;
}
/* No break */
/* no break */
default:
$entity->fullExport = true;
$response['entity'] = $entity->export();
......
......@@ -7,13 +7,13 @@
*/
namespace Minds\Controllers\api\v1\media;
use Minds\Api\Factory;
use Minds\Common;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Helpers;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Core\Features\Manager as FeaturesManager;
class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -29,24 +29,33 @@ class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
exit;
}
$featuresManager = new FeaturesManager();
$guid = $pages[0];
if ($featuresManager->has('cdn-jwt')) {
error_log("{$_SERVER['REQUEST_URI']} was hit, and should not have been");
Core\Security\ACL::$ignore = true;
$size = isset($pages[1]) ? $pages[1] : null;
$last_cache = isset($pages[2]) ? $pages[2] : time();
$entity = Entities\Factory::build($guid);
if (!$entity) {
return Factory::response([
'status' => 'error',
'message' => 'This endpoint has been deprecated. Please use fs/v1/thumbnail',
'message' => 'Entity not found'
]);
}
$guid = $pages[0];
Core\Security\ACL::$ignore = true;
$featuresManager = new FeaturesManager();
$size = isset($pages[1]) ? $pages[1] : null;
if ($entity->access_id !== Common\Access::PUBLIC && $featuresManager->has('cdn-jwt')) {
error_log("{$_SERVER['REQUEST_URI']} was hit, and should not have been");
$last_cache = isset($pages[2]) ? $pages[2] : time();
return Factory::response([
'status' => 'error',
'message' => 'This endpoint has been deprecated. Please use fs/v1/thumbnail',
]);
}
$etag = $last_cache . $guid;
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
......@@ -54,7 +63,7 @@ class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
exit;
}
$thumbnail = Di::_()->get('Media\Thumbnails')->get($guid, $size);
$thumbnail = Di::_()->get('Media\Thumbnails')->get($entity, $size);
if ($thumbnail instanceof \ElggFile) {
$thumbnail->open('read');
......
......@@ -299,28 +299,6 @@ class merchant implements Interfaces\Api
$response['uploaded'] = true;
}
break;
case "charge":
$sale = (new Payments\Sale)
->setId($pages[1]);
try {
Payments\Factory::build('braintree', ['gateway'=>'merchants'])->chargeSale($sale);
} catch (\Exception $e) {
var_dump($e);
exit;
}
exit;
break;
case "void":
$sale = (new Payments\Sale)
->setId($pages[1]);
Payments\Factory::build('braintree', ['gateway'=>'merchants'])->voidSale($sale);
break;
case "refund":
$sale = (new Payments\Sale)
->setId($pages[1]);
Payments\Factory::build('braintree', ['gateway'=>'merchants'])->refundSale($sale);
break;
}
return Factory::response($response);
......
......@@ -7,9 +7,7 @@
namespace Minds\Controllers\api\v1\minds;
use Minds;
use Minds\Core;
use Minds\Core\Rewards\Contributions\ContributionValues;
use Minds\Interfaces;
use Minds\Api\Factory;
......@@ -22,33 +20,10 @@ class config implements Interfaces\Api, Interfaces\ApiIgnorePam
*/
public function get($pages)
{
$minds = [
"cdn_url" => Minds\Core\Config::_()->get('cdn_url') ?: Minds\Core\Config::_()->cdn_url,
"cinemr_url" => Minds\Core\Config::_()->get('cinemr_url') ?: Minds\Core\Config::_()->cinemr_url,
"site_url" => Minds\Core\Config::_()->get('site_url') ?: Minds\Core\Config::_()->site_url,
"socket_server" => Minds\Core\Config::_()->get('sockets-server-uri') ?: 'ha-socket-io-us-east-1.minds.com:3030',
"thirdpartynetworks" => Minds\Core\Di\Di::_()->get('ThirdPartyNetworks\Manager')->availableNetworks(),
"categories" => Minds\Core\Config::_()->get('categories') ?: [],
"stripe_key" => Minds\Core\Config::_()->get('payments')['stripe']['public_key'],
"recaptchaKey" => Minds\Core\Config::_()->get('google')['recaptcha']['site_key'],
"max_video_length" => (Core\Session::getLoggedInUser() && Core\Session::getLoggedInUser()->isPlus())
? Minds\Core\Config::_()->get('max_video_length_plus')
: Minds\Core\Config::_()->get('max_video_length'),
"max_video_file_size" => Minds\Core\Config::_()->get('max_video_file_size') ?: 0,
"features" => (object) (Minds\Core\Config::_()->get('features') ?: []),
"blockchain" => (object) Minds\Core\Di\Di::_()->get('Blockchain\Manager')->getPublicSettings(),
"plus" => Minds\Core\Config::_()->get('plus'),
"report_reasons" => Minds\Core\Config::_()->get('report_reasons'),
"last_tos_update" => (Minds\Core\Config::_()->get('last_tos_update') ?: time()),
'handlers' => [
'plus' => Minds\Core\Di\Di::_()->get('Config')->get('plus')['handler'] ?? null,
'pro' => Minds\Core\Di\Di::_()->get('Config')->get('pro')['handler'] ?? null,
],
'upgrades' => Minds\Core\Di\Di::_()->get('Config')->get('upgrades'),
'contribution_values' => ContributionValues::export(),
];
return Factory::response($minds);
return Factory::response(
Core\Di\Di::_()->get('Config\Exported')
->export()
);
}
/**
......
......@@ -379,7 +379,7 @@ class newsfeed implements Interfaces\Api
->setTitle($embeded->title)
->setBlurb($embeded->description)
->export()
)
)
->setMessage($message);
}
$save->setEntity($activity)
......@@ -417,7 +417,7 @@ class newsfeed implements Interfaces\Api
->setTitle($embeded->title)
->setBlurb($embeded->description)
->export()
)
)
->setMessage($message);
}
$save->setEntity($activity)
......
<?php
/**
* Minds Payments API:: braintree
*
* @version 1
* @author Mark Harding
*/
namespace Minds\Controllers\api\v1\payments;
use Minds\Core;
use Minds\Helpers;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Core\Payments;
class braintree implements Interfaces\Api
{
/**
* Returns merchant information
* @param array $pages
*
* API:: /v1/merchant/:slug
*/
public function get($pages)
{
$response = [];
switch ($pages[0]) {
case "token":
$gateway = isset($pages[1]) ? $pages[1] : 'default';
$response['token'] = Payments\Factory::build('braintree', ['gateway'=>$gateway])->getToken();
break;
}
return Factory::response($response);
}
public function post($pages)
{
$response = [];
switch ($pages[0]) {
case "charge":
$amount = $_POST['amount'];
$fee = $amount * 0.05 + 0.30; //5% + $.30
if (!isset($_POST['merchant'])) {
$merchant = Core\Session::getLoggedInUser();
}
$sale = (new Payments\Sale())
->setAmount($amount)
->setMerchant($merchant)
->setFee($fee)
->setCustomerId(Core\Session::getLoggedInUser()->guid)
->setNonce($_POST['nonce']);
try {
$result = Payments\Factory::build('braintree', ['gateway'=>'merchants'])->setSale($sale);
} catch (\Exception $e) {
$response['status'] = "error";
$response['message'] = $e->getMessage();
}
break;
case "charge-master":
$amount = $_POST['amount'];
$sale = (new Payments\Sale())
->setAmount($amount)
->setCustomerId(Core\Session::getLoggedInUser()->guid)
->setSettle(true)
->setFee(0)
->setNonce($_POST['nonce']);
try {
$result = Payments\Factory::build('braintree', ['gateway'=>'merchants'])->setSale($sale);
} catch (\Exception $e) {
$response['status'] = "error";
$response['message'] = $e->getMessage();
}
break;
}
return Factory::response($response);
}
public function put($pages)
{
return Factory::response([]);
}
public function delete($pages)
{
return Factory::response([]);
}
}
......@@ -97,9 +97,6 @@ class subscriptions implements Interfaces\Api
}
$stripe = Core\Di\Di::_()->get('StripePayments');
$stripe->cancelSubscription($subscription);
} else {
$braintree = Payments\Factory::build("Braintree", ['gateway'=>'default']);
$braintree->cancelSubscription($subscription);
}
}
......
<?php
/**
* Minds Webhook: Braintree
*
* @version 1
* @author Mark Harding
*/
namespace Minds\Controllers\api\v1\webhooks;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers;
use Minds\Core\Payments;
use Braintree_WebhookNotification;
class braintree implements Interfaces\Api, Interfaces\ApiIgnorePam
{
/**
* NOT AVAILABLE
*/
public function get($pages)
{
return Factory::response(['status'=>'error', 'message'=>'GET is not supported for this endpoint']);
}
/**
*/
public function post($pages)
{
error_log("[webhooks]:: hit first entrace point");
/*$gateway = isset($pages[0]) ? $pages[0] : 'default';
$bt = Payments\Factory::build('braintree', ['gateway'=>$gateway]);
$hooks = new Payments\Hooks();
$hooks->loadDefaults();
$webhooks = new Payments\Braintree\Webhooks($hooks, $bt);
$webhooks->setSignature($_POST['bt_signature'])
->setPayload($_POST['bt_payload'])
->run();*/
}
public function put($pages)
{
}
public function delete($pages)
{
}
}
......@@ -48,24 +48,9 @@ class stripe implements Interfaces\Api, Interfaces\ApiIgnorePam
$hooks->run();
// Do something with $event_json
http_response_code(200); // PHP 5.4 or greater
exit;
/*$gateway = isset($pages[0]) ? $pages[0] : 'default';
$bt = Payments\Factory::build('braintree', ['gateway'=>$gateway]);
$hooks = new Payments\Hooks();
$hooks->loadDefaults();
$webhooks = new Payments\Braintree\Webhooks($hooks, $bt);
$webhooks->setSignature($_POST['bt_signature'])
->setPayload($_POST['bt_payload'])
->run();*/
return Factory::response([]);
}
......
<?php
namespace Minds\Controllers\api\v2\admin\rewards;
use Minds\Api\Exportable;
use Minds\Core\Rewards\Withdraw\Repository;
use Exception;
use Minds\Common\Repository\Response;
use Minds\Core\Di\Di;
use Minds\Core\Rewards\Withdraw\Manager;
use Minds\Core\Rewards\Withdraw\Request;
use Minds\Entities\User;
use Minds\Interfaces;
use Minds\Api\Factory;
......@@ -11,32 +14,38 @@ class withdrawals implements Interfaces\Api, Interfaces\ApiAdminPam
{
/**
* Equivalent to HTTP GET method
* @param array $pages
* @param array $pages
* @return mixed|null
* @throws Exception
*/
public function get($pages)
{
$repository = new Repository();
$username = $_GET['user'];
/** @var Manager $manager */
$manager = Di::_()->get('Rewards\Withdraw\Manager');
if (!$username) {
return Factory::response([
'withdrawals' => [],
'load-next' => '',
]);
$userGuid = null;
if ($_GET['user']) {
$userGuid = (new User(strtolower($_GET['user'])))->guid;
}
$user = new User(strtolower($username));
$status = $_GET['status'] ?? null;
$withdrawals = $repository->getList([
$opts = [
'status' => $status,
'user_guid' => $userGuid,
'limit' => isset($_GET['limit']) ? (int) $_GET['limit'] : 12,
'offset' => isset($_GET['offset']) ? $_GET['offset'] : '',
'user_guid' => $user->guid
]);
'hydrate' => true,
'admin' => true,
];
/** @var Response $withdrawals */
$withdrawals = $manager->getList($opts);
return Factory::response([
'withdrawals' => Exportable::_($withdrawals['withdrawals']),
'load-next' => (string) base64_encode($withdrawals['token']),
'withdrawals' => $withdrawals,
'load-next' => $withdrawals->getPagingToken(),
]);
}
......@@ -57,6 +66,37 @@ class withdrawals implements Interfaces\Api, Interfaces\ApiAdminPam
*/
public function put($pages)
{
/** @var Manager $manager */
$manager = Di::_()->get('Rewards\Withdraw\Manager');
$request = $manager->get(
(new Request())
->setUserGuid((string) $pages[0] ?? null)
->setTimestamp((int) $pages[1] ?? null)
->setTx((string) $pages[2] ?? null)
);
if (!$request) {
return Factory::response([
'status' => 'error',
'message' => $errorMessage ?? 'Missing request',
]);
}
try {
$success = $manager->approve($request);
} catch (Exception $exception) {
$success = false;
$errorMessage = $exception->getMessage();
}
if (!$success) {
return Factory::response([
'status' => 'error',
'message' => $errorMessage ?? 'Cannot approve request',
]);
}
return Factory::response([]);
}
......@@ -67,6 +107,37 @@ class withdrawals implements Interfaces\Api, Interfaces\ApiAdminPam
*/
public function delete($pages)
{
/** @var Manager $manager */
$manager = Di::_()->get('Rewards\Withdraw\Manager');
$request = $manager->get(
(new Request())
->setUserGuid((string) $pages[0] ?? null)
->setTimestamp((int) $pages[1] ?? null)
->setTx((string) $pages[2] ?? null)
);
if (!$request) {
return Factory::response([
'status' => 'error',
'message' => $errorMessage ?? 'Missing request',
]);
}
try {
$success = $manager->reject($request);
} catch (Exception $exception) {
$success = false;
$errorMessage = $exception->getMessage();
}
if (!$success) {
return Factory::response([
'status' => 'error',
'message' => $errorMessage ?? 'Cannot reject request',
]);
}
return Factory::response([]);
}
}
......@@ -11,6 +11,14 @@ class analytics implements Interfaces\Api, Interfaces\ApiIgnorePam
{
public function get($pages)
{
// Temporary require admin
if (!Core\Session::isAdmin()) {
return Factory::response([
'status' => 'error',
'message' => 'Only admins can view these analytics. Use the dashboards instead.',
]);
}
if (!isset($pages[0])) {
return Factory::response([
'status' => 'error',
......
......@@ -123,10 +123,11 @@ class transactions implements Interfaces\Api
break;
case "withdraw":
$request = new Withdraw\Request();
$request->setTx($_POST['tx'])
$request
->setUserGuid(Session::getLoggedInUser()->guid)
->setAddress($_POST['address'])
->setTimestamp(time())
->setTx($_POST['tx'])
->setAddress($_POST['address'])
->setGas($_POST['gas'])
->setAmount((string) BigNumber::_($_POST['amount']));
......
......@@ -50,7 +50,10 @@ class wallet implements Interfaces\Api
$offChainBalanceVal = BigNumber::_($offChainBalance->get());
$offchainAvailableVal = BigNumber::_($offChainBalance->getAvailable());
$balance = $onChainBalanceVal->add($offChainBalanceVal);
$balance = $onChainBalanceVal
? $onChainBalanceVal->add($offChainBalanceVal)
: $offChainBalanceVal;
$wireCap = Di::_()->get('Blockchain\Wallets\OffChain\Cap')
->setUser(Session::getLoggedinUser())
......
......@@ -48,8 +48,10 @@ class peer implements Interfaces\Api
case 'inbox':
default:
$review->setType(Core\Session::getLoggedinUser()->guid);
$boosts = $review->getReviewQueue(isset($_GET['limit']) ? $_GET['limit'] : 12,
isset($_GET['offset']) ? $_GET['offset'] : "");
$boosts = $review->getReviewQueue(
isset($_GET['limit']) ? $_GET['limit'] : 12,
isset($_GET['offset']) ? $_GET['offset'] : ""
);
$response['boosts'] = Factory::exportable($boosts['data']);
......
......@@ -65,7 +65,11 @@ class scheduled implements Interfaces\Api
return Factory::response([
'status' => 'success',
'count' => $manager->getScheduledCount(['container_guid' => $container_guid, 'type' => $type])
'count' => $manager->getScheduledCount([
'container_guid' => $container_guid,
'type' => $type,
'owner_guid' => $currentUser->guid,
])
]);
default:
return Factory::response([
......@@ -148,6 +152,7 @@ class scheduled implements Interfaces\Api
'single_owner_threshold' => 0,
'pinned_guids' => $type === 'activity' ? array_reverse($container->getPinnedPosts()) : null,
'time_created_upper' => false,
'owner_guid' => $currentUser->guid,
];
if (isset($_GET['nsfw'])) {
......
......@@ -39,9 +39,14 @@ class keys implements Interfaces\Api
// $priv = helpers\openssl::temporaryPrivateKey($priv, $unlock_password, $unlock_password);
// \elgg_set_plugin_user_setting('privatekey', $priv, elgg_get_logged_in_user_guid(), 'gatherings');
//}
$keystore->unlockPrivateKey($unlock_password, null);
$tmp = $keystore->getUnlockedPrivateKey();
try {
$keystore->unlockPrivateKey($unlock_password, null);
$tmp = $keystore->getUnlockedPrivateKey();
} catch (\Exception $e) {
$response['status'] = 'error';
$response['message'] = $e->getMessage();
return Factory::response($response);
}
if (!$tmp || !$unlock_password) {
$response['status'] = 'error';
......
......@@ -14,6 +14,7 @@ use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\SapiEmitter;
use Sentry;
class token implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -70,9 +71,10 @@ class token implements Interfaces\Api, Interfaces\ApiIgnorePam
$refreshTokenRepository->revokeRefreshToken($tokenId);
$response = new JsonResponse([]);
} catch (\Exception $e) {
Sentry\captureException($e); // Log to sentry
$body = [
'status' => 'error',
'message' => $exception->getMessage(),
'message' => $e->getMessage(),
];
$response = new JsonResponse($body, 500);
}
......
......@@ -28,9 +28,7 @@ class channel implements Interfaces\Api
*/
public function get($pages)
{
$currentUser = Session::getLoggedinUser();
$channel = new User($pages[0]);
$channel = new User(strtolower($pages[0]));
$channel->fullExport = true; //get counts
$channel->exportCounts = true;
......@@ -41,6 +39,8 @@ class channel implements Interfaces\Api
]);
}
$currentUser = Session::getLoggedinUser();
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager->setUser($channel);
......
......@@ -34,7 +34,7 @@ class settings implements Interfaces\Api
]);
}
$user = new User($pages[0]);
$user = new User(strtolower($pages[0]));
}
/** @var Manager $manager */
......@@ -66,7 +66,7 @@ class settings implements Interfaces\Api
]);
}
$user = new User($pages[0]);
$user = new User(strtolower($pages[0]));
}
/** @var Manager $manager */
......
......@@ -53,7 +53,7 @@ class assets implements Interfaces\Api
]);
}
$user = new User($pages[1]);
$user = new User(strtolower($pages[1]));
}
// Check uploaded file
......
......@@ -34,7 +34,7 @@ class domain implements Interfaces\Api
]);
}
$user = new User($pages[0]);
$user = new User(strtolower($pages[0]));
}
/** @var ProDomain $proDomain */
......
<?php
/**
* authorize
* @author edgebal
*/
namespace Minds\Controllers\api\v2\sso;
use Exception;
use Minds\Api\Factory;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Minds\Core\SSO\Manager;
use Minds\Entities\User;
use Minds\Interfaces;
use Zend\Diactoros\ServerRequest;
class authorize implements Interfaces\Api, Interfaces\ApiIgnorePam
{
/** @var ServerRequest */
public $request;
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
*/
public function get($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed|null
* @throws Exception
*/
public function post($pages)
{
$origin = $this->request->getServerParams()['HTTP_ORIGIN'] ?? '';
if (!$origin) {
return Factory::response([
'status' => 'error',
'message' => 'No HTTP Origin header'
]);
}
$domain = parse_url($origin, PHP_URL_HOST);
/** @var Manager $sso */
$sso = Di::_()->get('SSO');
$sso
->setDomain($domain);
try {
$sso
->authorize($_POST['token']);
} catch (Exception $e) {
error_log((string) $e);
return Factory::response([
'status' => 'error',
'message' => 'Cannot authorize',
]);
}
/** @var User $currentUser */
$currentUser = Session::getLoggedinUser();
return Factory::response([
'user' => $currentUser ? $currentUser->export() : null,
]);
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed|null
*/
public function delete($pages)
{
return Factory::response([]);
}
}
<?php
/**
* connect
* @author edgebal
*/
namespace Minds\Controllers\api\v2\sso;
use Exception;
use Minds\Api\Factory;
use Minds\Core\Di\Di;
use Minds\Core\SSO\Manager;
use Minds\Interfaces;
use Zend\Diactoros\ServerRequest;
class connect implements Interfaces\Api, Interfaces\ApiIgnorePam
{
/** @var ServerRequest */
public $request;
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
*/
public function get($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed|null
* @throws Exception
*/
public function post($pages)
{
$origin = $this->request->getServerParams()['HTTP_ORIGIN'] ?? '';
if (!$origin) {
return Factory::response([
'status' => 'error',
'message' => 'No HTTP Origin header'
]);
}
$domain = parse_url($origin, PHP_URL_HOST);
/** @var Manager $sso */
$sso = Di::_()->get('SSO');
$sso
->setDomain($domain);
try {
return Factory::response([
'token' => $sso->generateToken()
]);
} catch (Exception $e) {
error_log((string) $e);
return Factory::response([
'status' => 'error',
'message' => 'Cannot connect',
]);
}
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed|null
*/
public function delete($pages)
{
return Factory::response([]);
}
}
......@@ -59,6 +59,7 @@ class wire implements Interfaces\Api
$amount = BigNumber::_($_POST['amount']);
$recurring = isset($_POST['recurring']) ? $_POST['recurring'] : false;
$recurringInterval = $_POST['recurring_interval'] ?? 'once';
if (!$amount) {
return Factory::response(['status' => 'error', 'message' => 'you must send an amount']);
......@@ -80,6 +81,7 @@ class wire implements Interfaces\Api
$manager
->setAmount((string) BigNumber::toPlain($amount, $digits))
->setRecurring($recurring)
->setRecurringInterval($recurringInterval)
->setSender(Core\Session::getLoggedInUser())
->setEntity($entity)
->setPayload((array) $_POST['payload']);
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class avatars implements Interfaces\FS
{
......@@ -59,10 +59,8 @@ class avatars implements Interfaces\FS
$contents = file_get_contents($filepath);
}
if ($filepath) {
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, $filepath);
finfo_close($finfo);
if (!empty($contents)) {
$mimetype = File::getMime($contents);
} else {
$mimetype = 'image/jpeg';
}
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class banners implements Interfaces\FS
{
......@@ -56,6 +56,7 @@ class banners implements Interfaces\FS
$f->owner_guid = $entity->owner_guid ?: $entity->getOwnerObj()->guid;
$f->setFilename("group/{$entity->getGuid()}.jpg");
$f->open('read');
// no break
case "object":
break;
}
......@@ -101,9 +102,7 @@ class banners implements Interfaces\FS
}
}
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_buffer($finfo, $content);
finfo_close($finfo);
$mimetype = File::getMime($content);
header('Content-Type: '.$mimetype);
header('Expires: ' . date('r', time() + 864000));
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class paywall implements Interfaces\FS
{
......@@ -31,9 +31,7 @@ class paywall implements Interfaces\FS
$contents = file_get_contents(Core\Di\Di::_()->get('Config')->get('path') . 'engine/Assets/photos/andromeda-galaxy.jpg');
}
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, $filepath);
finfo_close($finfo);
$mimetype = File::getMime($contents);
header('Content-Type: '.$mimetype);
header('Expires: ' . date('r', time() + 864000));
header("Pragma: public");
......
......@@ -31,6 +31,10 @@ class pro implements Interfaces\FS
$contents = $file->read();
if (!$contents) {
$this->fallback($pages);
}
header(sprintf("Content-Type: %s", $asset->getMimeType()));
header(sprintf("Expires: %s", date('r', time() + 864000)));
header('Pragma: public');
......@@ -39,4 +43,25 @@ class pro implements Interfaces\FS
echo $contents;
exit;
}
/**
* Fallback
* @param array $pages
* @return void
*/
private function fallback($pages): void
{
switch ($pages[1]) {
case "background":
$bannersFs = new banners();
$bannersFs->get([ $pages[0] ]);
exit;
break;
case "logo":
$avatarsFs = new avatars();
$avatarsFs->get([ $pages[0], 'large' ]);
exit;
break;
}
}
}
......@@ -4,11 +4,14 @@
*/
namespace Minds\Controllers\fs\v1;
use Minds\Api\Factory;
use Minds\Common;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Helpers\File;
class thumbnail extends Core\page implements Interfaces\page
{
......@@ -18,9 +21,30 @@ class thumbnail extends Core\page implements Interfaces\page
exit;
}
Core\Security\ACL::$ignore = true;
$guid = $pages[0] ?? null;
if (!$guid) {
return Factory::response([
'status' => 'error',
'message' => 'guid must be provided'
]);
}
$size = isset($pages[1]) ? $pages[1] : null;
$entity = Entities\Factory::build($guid);
if (!$entity) {
return Factory::response([
'status' => 'error',
'message' => 'Entity not found'
]);
}
$featuresManager = new FeaturesManager;
if ($featuresManager->has('cdn-jwt')) {
if ($entity->access_id !== Common\Access::PUBLIC && $featuresManager->has('cdn-jwt')) {
$signedUri = new Core\Security\SignedUri();
$uri = (string) \Zend\Diactoros\ServerRequestFactory::fromGlobals()->getUri();
if (!$signedUri->confirm($uri)) {
......@@ -31,9 +55,8 @@ class thumbnail extends Core\page implements Interfaces\page
/** @var Core\Media\Thumbnails $mediaThumbnails */
$mediaThumbnails = Di::_()->get('Media\Thumbnails');
Core\Security\ACL::$ignore = true;
$size = isset($pages[1]) ? $pages[1] : null;
$thumbnail = $mediaThumbnails->get($pages[0], $size);
$thumbnail = $mediaThumbnails->get($entity, $size);
if ($thumbnail instanceof \ElggFile) {
$thumbnail->open('read');
......@@ -47,8 +70,7 @@ class thumbnail extends Core\page implements Interfaces\page
}
try {
$finfo = new \finfo(FILEINFO_MIME);
$contentType = $finfo->buffer($contents) ?: 'image/jpeg';
$contentType = File::getMime($contents);
} catch (\Exception $e) {
error_log($e);
$contentType = 'image/jpeg';
......
......@@ -4,6 +4,7 @@ namespace Minds\Core\Analytics\Dashboards;
class Manager
{
const DASHBOARDS = [
'summary' => SummaryDashboard::class,
'traffic' => TrafficDashboard::class,
'trending' => TrendingDashboard::class,
'earnings' => EarningsDashboard::class,
......
......@@ -14,7 +14,7 @@ class ReferralsEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_referrals';
/** @var string */
protected $label = 'Referrals USD';
protected $label = 'Referrals';
/** @var string */
protected $description = "Total earnings for your active referrals. You earn $0.10 for every active referral. A referral must log in at least 3 of 7 days after registration to be credited.";
......
......@@ -14,10 +14,10 @@ class SalesEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_sales';
/** @var string */
protected $label = 'Sales USD';
protected $label = 'Sales';
/** @var string */
protected $description = "Total earnings for the sales you have referred. You earn a 25% commission when your referrals purchase Plus, Pro or Minds Tokens.";
protected $description = "Total earnings for the sales you have referred. You earn a 25% commission when your referrals purchase Pro or Minds Tokens.";
/** @var array */
protected $permissions = [ 'user', 'admin' ];
......
......@@ -14,10 +14,10 @@ class ViewsEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_views';
/** @var string */
protected $label = 'Pageviews USD';
protected $label = 'Pageviews';
/** @var string */
protected $description = "Total earnings for the pageviews on your channel's assets. You earn $1 for every 1,000 pageviews.";
protected $description = "Total earnings for the pageviews on your channel’s assets. You earn a variable RPM for every 1,000 pageviews.";
/** @var array */
protected $permissions = [ 'user', 'admin' ];
......
......@@ -14,7 +14,7 @@ class SubscribersMetric extends AbstractEngagementMetric
protected $id = 'subscribers';
/** @var string */
protected $label = 'Subscribes';
protected $label = 'Subscribers';
/** @var string */
protected $description = "Number of subscribers your channel has gained";
......
<?php
/**
* Summary Dashboard
*/
namespace Minds\Core\Analytics\Dashboards;
use Minds\Entities\User;
use Minds\Traits\MagicAttributes;
/**
* @method TrafficDashboard setTimespanId(string $timespanId)
* @method TrafficDashboard setFilterIds(array $filtersIds)
* @method TrafficDashboard setUser(User $user)
*/
class SummaryDashboard implements DashboardInterface
{
use MagicAttributes;
/** @var string */
private $timespanId = '30d';
/** @var string[] */
private $filterIds = [ 'platform::browser' ];
/** @var string */
private $metricId = 'active_users';
/** @var Timespans\TimespansCollection */
private $timespansCollection;
/** @var Metrics\MetricsCollection */
private $metricsCollection;
/** @var Filters\FiltersCollection */
private $filtersCollection;
/** @var User */
private $user;
public function __construct(
$timespansCollection = null,
$metricsCollection = null,
$filtersCollection = null
) {
$this->timespansCollection = $timespansCollection ?? new Timespans\TimespansCollection();
$this->metricsCollection = $metricsCollection ?? new Metrics\MetricsCollection();
$this->filtersCollection = $filtersCollection ?? new Filters\FiltersCollection();
}
/**
* Build the dashboard
* @return self
*/
public function build(): self
{
$this->timespansCollection
->setSelectedId($this->timespanId)
->addTimespans(
new Timespans\TodayTimespan(),
new Timespans\_30dTimespan(),
new Timespans\_1yTimespan(),
new Timespans\MtdTimespan(),
new Timespans\YtdTimespan()
);
$this->filtersCollection
->setSelectedIds($this->filterIds)
->setUser($this->user)
->addFilters(
// new Filters\PlatformFilter(),
new Filters\ViewTypeFilter(),
new Filters\ChannelFilter()
);
$this->metricsCollection
->setTimespansCollection($this->timespansCollection)
->setFiltersCollection($this->filtersCollection)
->setSelectedId($this->metricId)
->setUser($this->user)
->addMetrics(
new Metrics\ActiveUsersMetric()
)
->build();
return $this;
}
/**
* Export
* @param array $extras
* @return array
*/
public function export(array $extras = []): array
{
$this->build();
return [
'category' => 'summary',
'label' => 'Summary',
'description' => null,
'timespan' => $this->timespansCollection->getSelected()->getId(),
'timespans' => $this->timespansCollection->export(),
'metric' => $this->metricsCollection->getSelected()->getId(),
'metrics' => $this->metricsCollection->export(),
'filter' => $this->filtersCollection->getSelectedIds(),
'filters' => $this->filtersCollection->export(),
];
}
}
......@@ -74,11 +74,11 @@ class TokenSaleEvent implements BlockchainEventInterface
$purchase = $this->manager->getPurchase($transaction->getData()['phone_number_hash'], $transaction->getTx());
if (!$purchase) {
echo "purchase not found";
error_log("purchase not found");
return; //purchase not found
}
var_dump($log);
error_log(print_r($log, true));
//is the requested amount below what has already been recorded
if ($transaction->getAmount() > $purchase->getUnissuedAmount()) {
return; //requested more than can issue
......
......@@ -8,30 +8,39 @@
namespace Minds\Core\Blockchain\Events;
use Minds\Core\Blockchain\Contracts\MindsToken;
use Minds\Core\Blockchain\Transactions\Manager;
use Exception;
use Minds\Core\Blockchain\Transactions\Repository as TransactionsRepository;
use Minds\Core\Blockchain\Transactions\Transaction;
use Minds\Core\Blockchain\Util;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\Rewards\Withdraw;
use Minds\Core\Rewards\Withdraw\Manager;
use Minds\Core\Rewards\Withdraw\Request;
use Minds\Core\Util\BigNumber;
class WithdrawEvent implements BlockchainEventInterface
{
/** @var array $eventsMap */
/** @var array */
public static $eventsMap = [
'0x317c0f5ab60805d3e3fb6aaa61ccb77253bbb20deccbbe49c544de4baa4d7f8f' => 'onRequest',
'blockchain:fail' => 'withdrawFail',
];
/** @var Manager $manager */
private $manager;
/** @var Manager */
protected $manager;
/** @var Repository $repository **/
/** @var TransactionsRepository **/
protected $txRepository;
/** @var Config $config */
private $config;
/** @var Config */
protected $config;
/**
* WithdrawEvent constructor.
* @param Manager $manager
* @param TransactionsRepository $txRepository
* @param Config $config
*/
public function __construct($manager = null, $txRepository = null, $config = null)
{
$this->txRepository = $txRepository ?: Di::_()->get('Blockchain\Transactions\Repository');
......@@ -50,30 +59,31 @@ class WithdrawEvent implements BlockchainEventInterface
/**
* @param $topic
* @param array $log
* @throws \Exception
* @param $transaction
* @throws Exception
*/
public function event($topic, array $log, $transaction)
{
$method = static::$eventsMap[$topic];
if ($log['address'] != $this->config->get('blockchain')['contracts']['withdraw']['contract_address']) {
throw new \Exception('Event does not match address');
throw new Exception('Event does not match address');
}
if (method_exists($this, $method)) {
$this->{$method}($log, $transaction);
} else {
throw new \Exception('Method not found');
throw new Exception('Method not found');
}
}
public function onRequest($log, $transaction)
public function onRequest($log, Transaction $transaction)
{
$address = $log['address'];
if ($address != $this->config->get('blockchain')['contracts']['withdraw']['contract_address']) {
$this->withdrawFail($log, $transaction);
throw new \Exception('Incorrect address sent the withdraw event');
throw new Exception('Incorrect address sent the withdraw event');
}
$tx = $log['transactionHash'];
......@@ -82,30 +92,43 @@ class WithdrawEvent implements BlockchainEventInterface
$gas = (string) BigNumber::fromHex($gas);
$amount = (string) BigNumber::fromHex($amount);
//double check the details of this transaction match with what the user actually requested
$request = new Withdraw\Request();
$request
->setTx($tx)
->setAddress($address)
->setUserGuid($user_guid)
->setGas($gas)
->setTimestamp($transaction->getTimestamp())
->setAmount($amount);
try {
$this->manager->complete($request, $transaction);
} catch (\Exception $e) {
var_dump($e);
error_log(print_r($e, true));
$request = $this->manager->get(
(new Request())
->setUserGuid($user_guid)
->setTimestamp($transaction->getTimestamp())
->setTx($tx)
);
if (!$request) {
throw new \Exception('Unknown withdrawal');
}
if ((string) $address !== (string) $request->getAddress()) {
throw new \Exception('Wrong address value');
} elseif ((string) $gas !== (string) $request->getGas()) {
throw new \Exception('Wrong gas value');
} elseif ((string) $amount !== (string) $request->getAmount()) {
throw new \Exception('Wrong amount value');
}
$this->manager->confirm($request, $transaction);
} catch (Exception $e) {
$this->manager->fail(
(new Request())
->setUserGuid($user_guid)
->setTimestamp($transaction->getTimestamp())
->setTx($tx)
);
error_log($e);
}
}
public function withdrawFail($log, $transaction)
{
if ($transaction->getContract() !== 'withdraw') {
throw new \Exception("Failed but not a withdrawal");
return;
throw new Exception("Failed but not a withdrawal");
}
$transaction->setFailed(true);
......
......@@ -85,11 +85,13 @@ class Pending
public function delete($type, $tx_id)
{
$query = new Core\Data\Cassandra\Prepared\Custom();
$query->query("DELETE FROM blockchain_pending WHERE type = ? AND tx_id = ?",
$query->query(
"DELETE FROM blockchain_pending WHERE type = ? AND tx_id = ?",
[
(string) $type,
(string) $tx_id
]);
]
);
try {
return (bool) $this->db->request($query);
......
......@@ -46,14 +46,16 @@ class Sums
$query = new Custom();
if ($this->user) {
$query->query("SELECT
$query->query(
"SELECT
SUM(amount) as balance
FROM blockchain_transactions_mainnet_by_address
WHERE user_guid = ?
AND wallet_address = 'offchain'",
[
new Varint((int) $this->user->guid)
]);
]
);
$query->setOpts([
'consistency' => \Cassandra::CONSISTENCY_ALL
]);
......
......@@ -49,14 +49,16 @@ class TestnetSums
throw new \Exception('User is not set');
}
$query->query("SELECT
$query->query(
"SELECT
SUM(amount) as balance
FROM blockchain_transactions_by_address
WHERE user_guid = ?
AND wallet_address = 'offchain'",
[
new Varint((int) $this->user->guid)
]);
]
);
$query->setOpts([
'consistency' => \Cassandra::CONSISTENCY_ALL
]);
......
......@@ -60,6 +60,11 @@ class Balance
}
$balance = $this->token->balanceOf($address);
if ($balance === null) {
return null;
}
$this->cache->set($cacheKey, serialize($balance), 60);
return $balance;
......
......@@ -47,7 +47,8 @@ class Navigation
->setVisibility(0); //only show for loggedin
$link = new Item();
NavigationManager::add($link
NavigationManager::add(
$link
->setPriority(4)
->setIcon('subject')
->setName('Blogs')
......
......@@ -244,8 +244,10 @@ class Iterator implements \Iterator
foreach ($boosts as $boost) {
$owner_guids[] = $boost->owner_guid;
}
$blocked = array_flip(Core\Security\ACL\Block::_()->isBlocked($owner_guids,
Core\Session::getLoggedInUserGuid()));
$blocked = array_flip(Core\Security\ACL\Block::_()->isBlocked(
$owner_guids,
Core\Session::getLoggedInUserGuid()
));
foreach ($boosts as $i => $boost) {
if (isset($blocked[$boost->owner_guid])) {
......
......@@ -97,10 +97,12 @@ class Repository
return $this;
}
foreach ($this->categories as $category) {
$query->query("INSERT INTO categories
$query->query(
"INSERT INTO categories
(type, category, filter, guid)
VALUES (?, ?, ?, ?)",
[ $this->type, $category, $this->filter, (string) $guid ]);
[ $this->type, $category, $this->filter, (string) $guid ]
);
try {
$result = $this->db->request($query);
} catch (\Exception $e) {
......@@ -116,9 +118,11 @@ class Repository
return $this;
}
foreach ($this->categories as $category) {
$query->query("DELETE FROM categories
$query->query(
"DELETE FROM categories
WHERE type = ? AND category = ? AND filter = ? AND guid = ?",
[ $this->type, $category, $this->filter, (string) $guid ]);
[ $this->type, $category, $this->filter, (string) $guid ]
);
try {
$result = $this->db->request($query);
} catch (\Exception $e) {
......
<?php
/**
* @author: eiennohi.
*/
namespace Minds\Core\Channels\Delegates;
use Minds\Core\Analytics\Metrics\Event;
use Minds\Entities\User;
class MetricsDelegate
{
public function onDelete(User $user)
{
$event = new Event();
$event->setType('action')
->setAction('delete')
->setProduct('platform')
->setUserGuid((string) $user->guid)
->setUserPhoneNumberHash($user->getPhoneNumberHash())
->push();
}
}
......@@ -5,6 +5,7 @@
namespace Minds\Core\Channels;
use Minds\Core\Channels\Delegates\MetricsDelegate;
use Minds\Core\Di\Di;
use Minds\Core\Queue\Interfaces\QueueClient;
use Minds\Entities\User;
......@@ -30,6 +31,9 @@ class Manager
/** @var Delegates\Artifacts\Factory */
protected $artifactsDelegatesFactory;
/** @var MetricsDelegate */
protected $metricsDelegate;
/** @var Delegates\Logout */
protected $logoutDelegate;
......@@ -44,10 +48,12 @@ class Manager
*/
public function __construct(
$artifactsDelegatesFactory = null,
$metricsDelegate = null,
$logoutDelegate = null,
$queueClient = null
) {
$this->artifactsDelegatesFactory = $artifactsDelegatesFactory ?: new Delegates\Artifacts\Factory();
$this->metricsDelegate = $metricsDelegate ?: new MetricsDelegate();
$this->logoutDelegate = $logoutDelegate ?: new Delegates\Logout();
$this->queueClient = $queueClient ?: Di::_()->get('Queue');
}
......@@ -139,6 +145,7 @@ class Manager
}
}
$this->metricsDelegate->onDelete($this->user);
$this->logoutDelegate->logout($this->user);
return true;
......
......@@ -9,6 +9,7 @@ use Minds\Entities\RepositoryEntity;
use Minds\Entities\User;
use Minds\Helpers\Flags;
use Minds\Helpers\Unknown;
use Minds\Helpers\Export;
use Minds\Core\Di\Di;
/**
......@@ -406,6 +407,8 @@ class Comment extends RepositoryEntity
//$output['parent_guid'] = (string) $this->entityGuid;
$output = Export::sanitize($output);
return $output;
}
}
......@@ -17,5 +17,9 @@ class ConfigProvider extends Provider
$this->di->bind('Config', function ($di) {
return new Config();
}, ['useFactory'=>true]);
$this->di->bind('Config\Exported', function ($di) {
return new Exported();
}, ['useFactory' => true]);
}
}
<?php
/**
* Exported
* @author edgebal
*/
namespace Minds\Core\Config;
use Minds\Core\Blockchain\Manager as BlockchainManager;
use Minds\Core\Di\Di;
use Minds\Core\I18n\I18n;
use Minds\Core\Navigation\Manager as NavigationManager;
use Minds\Core\Rewards\Contributions\ContributionValues;
use Minds\Core\Session;
use Minds\Core\ThirdPartyNetworks\Manager as ThirdPartyNetworksManager;
use Minds\Entities\User;
use Minds\Helpers\Counters;
class Exported
{
/** @var Config */
protected $config;
/** @var ThirdPartyNetworksManager */
protected $thirdPartyNetworks;
/** @var I18n */
protected $i18n;
/**
* Exported constructor.
* @param Config $config
* @param ThirdPartyNetworksManager $thirdPartyNetworks
* @param I18n $i18n
* @param BlockchainManager $blockchain
*/
public function __construct(
$config = null,
$thirdPartyNetworks = null,
$i18n = null,
$blockchain = null
) {
$this->config = $config ?: Di::_()->get('Config');
$this->thirdPartyNetworks = $thirdPartyNetworks ?: Di::_()->get('ThirdPartyNetworks\Manager');
$this->i18n = $i18n ?: Di::_()->get('I18n');
$this->blockchain = $blockchain ?: Di::_()->get('Blockchain\Manager');
}
/**
* @return array
*/
public function export(): array
{
$context = defined('__MINDS_CONTEXT__') ? __MINDS_CONTEXT__ : 'app';
$exported = [
'MindsContext' => $context,
'LoggedIn' => Session::isLoggedIn() ? true : false,
'Admin' => Session::isAdmin() ? true : false,
'cdn_url' => $this->config->get('cdn_url'),
'cdn_assets_url' => $this->config->get('cdn_assets_url'),
'site_url' => $this->config->get('site_url'),
'cinemr_url' => $this->config->get('cinemr_url'),
'socket_server' => $this->config->get('sockets-server-uri') ?: 'ha-socket-io-us-east-1.minds.com:3030',
'navigation' => NavigationManager::export(),
'thirdpartynetworks' => $this->thirdPartyNetworks->availableNetworks(),
'language' => $this->i18n->getLanguage(),
'languages' => $this->i18n->getLanguages(),
'categories' => $this->config->get('categories') ?: [],
'stripe_key' => $this->config->get('payments')['stripe']['public_key'],
'recaptchaKey' => $this->config->get('google')['recaptcha']['site_key'],
'max_video_length' => $this->config->get('max_video_length'),
'max_video_file_size' => $this->config->get('max_video_file_size'),
'features' => (object) ($this->config->get('features') ?: []),
'blockchain' => (object) $this->blockchain->getPublicSettings(),
'sale' => $this->config->get('blockchain')['sale'],
'last_tos_update' => $this->config->get('last_tos_update') ?: time(),
'tags' => $this->config->get('tags') ?: [],
'plus' => $this->config->get('plus'),
'report_reasons' => $this->config->get('report_reasons'),
'handlers' => [
'plus' => $this->config->get('plus')['handler'] ?? null,
'pro' => $this->config->get('pro')['handler'] ?? null,
],
'upgrades' => $this->config->get('upgrades'),
'contribution_values' => ContributionValues::export(),
'environment' => getenv('MINDS_ENV') ?: 'development',
];
if (Session::isLoggedIn()) {
/** @var User $user */
$user = Session::getLoggedinUser();
$exported['user'] = $user->export();
$exported['user']['rewards'] = (bool) $user->getPhoneNumberHash();
$exported['wallet'] = [
'balance' => Counters::get($user->guid, 'points', false),
];
if ($user->isPlus()) {
$exported['max_video_length'] = $this->config->get('max_video_length_plus');
}
}
if ($context === 'embed') {
$exported['MindsEmbed'] = $embedded_entity ?? null;
}
return $exported;
}
}
......@@ -161,13 +161,15 @@ class Call
array_push(self::$keys, $key);
$options = array_merge(
[
[
'multi' => false,
'offset' => "",
'finish' => "",
'limit' => 500,
'reversed' => true
], $options);
],
$options
);
$query = new Cassandra\Prepared\Custom();
......
......@@ -41,13 +41,13 @@ class Client implements Interfaces\ClientInterface
try {
$statement = $this->session->prepare($cql['string']);
$future = $this->session->executeAsync(
$statement,
@new Driver\ExecutionOptions(array_merge(
[
$statement,
@new Driver\ExecutionOptions(array_merge(
[
'arguments' => $cql['values']
],
$request->getOpts()
))
$request->getOpts()
))
);
if ($silent) {
return $future;
......
......@@ -75,14 +75,16 @@ class DataProvider extends Provider
$sslmode = isset($config['sslmode']) ? $config['sslmode'] : 'disable';
$username = isset($config['username']) ? $config['username'] : 'php';
// This is a generic data object using the postgres driver to connect to cockroachdb.
return new PDO("pgsql:host=$host;port=$port;dbname=$name;sslmode=$sslmode",
return new PDO(
"pgsql:host=$host;port=$port;dbname=$name;sslmode=$sslmode",
$username,
null,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_PERSISTENT => isset($config['persistent']) ? $config['persistent'] : false,
]);
]
);
}, ['useFactory'=>true]);
/**
* Locks
......
......@@ -11,13 +11,15 @@ class Client
public function __construct($dbh = null)
{
$this->dbh = $dbh ?: new PDO('pgsql:host=cockroachdb;port=26257;dbname=minds;sslmode=disable',
$this->dbh = $dbh ?: new PDO(
'pgsql:host=cockroachdb;port=26257;dbname=minds;sslmode=disable',
'maxroach',
null,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => true,
]);
]
);
}
/**
......
......@@ -72,8 +72,10 @@ class EndFacebookSupport
foreach ($this->getUsers() as $user) {
if (!$user instanceof \Minds\Entities\User || !$user->guid || $user->disabled_emails || $user->enabled != "yes") {
$skipped++;
echo "\r [emails]: $queued queued | $skipped skipped | " . date('d-m-Y',
$user->time_created) . " | $user->guid ";
echo "\r [emails]: $queued queued | $skipped skipped | " . date(
'd-m-Y',
$user->time_created
) . " | $user->guid ";
continue;
}
$queued++;
......@@ -95,8 +97,10 @@ class EndFacebookSupport
if (!$this->dryRun) {
$this->mailer->queue($message);
}
echo "\r [emails]: $queued queued | $skipped skipped | " . date('d-m-Y',
$user->time_created) . " | $user->guid ";
echo "\r [emails]: $queued queued | $skipped skipped | " . date(
'd-m-Y',
$user->time_created
) . " | $user->guid ";
}
echo "[emails]: Completed ($queued queued | $skipped skipped) \n";
}
......
......@@ -59,8 +59,10 @@ class GlobalTips extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -70,8 +70,10 @@ class InactiveUsers extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -65,8 +65,10 @@ class Invoice
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1('invoice' . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1('invoice' . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -76,8 +76,10 @@ class MissedSinceLogin extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -73,8 +73,10 @@ class News extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -70,8 +70,10 @@ class Promotion extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -62,8 +62,10 @@ class GoneCold extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -62,8 +62,10 @@ class WelcomeComplete extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -62,8 +62,10 @@ class WelcomeIncomplete extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -60,8 +60,10 @@ class WhenBoost extends EmailCampaign
$subject = 'Your boost is complete';
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -49,8 +49,10 @@ class WhenNotifications extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign.$this->topic.time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -75,8 +75,10 @@ class WhenWire extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -118,8 +118,10 @@ class WirePayment
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->template . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->template . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -75,8 +75,10 @@ class WirePromotions extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($this->subject)
->setHtml($this->template);
......
......@@ -58,8 +58,10 @@ class WithActivity extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -72,8 +72,10 @@ class WithBlogs extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -50,8 +50,10 @@ class WithChannelTips extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -39,8 +39,10 @@ class WithImprovementTips extends EmailCampaign
$message = new Message();
$message->setTo($this->user)
->setMessageId(implode('-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]))
->setMessageId(implode(
'-',
[$this->user->guid, sha1($this->user->getEmail()), sha1($this->campaign . $this->topic . time())]
))
->setSubject($subject)
->setHtml($this->template);
......
......@@ -3,6 +3,12 @@ namespace Minds\Core\Email;
use Minds\Traits\MagicAttributes;
/**
* Class EmailSubscription
* @package Minds\Core\Email
*
* @method string getUserGuid()
*/
class EmailSubscription
{
use MagicAttributes;
......
......@@ -38,10 +38,14 @@ class Manager
$result = $this->repository->getList($options);
if (!$result || count($result['data'] === 0)) {
if (!$result || count($result['data']) === 0) {
return [];
}
/*$guids = [];
foreach($result['data'] as $subscription) {
$guids[] = $subscription->getUserGuid();
}*/
$guids = array_map(function ($item) {
return $item->getUserGuid();
}, $result['data']);
......
......@@ -42,6 +42,9 @@ class FeedSyncEntity implements JsonSerializable
/** @var Entity */
protected $entity;
/** @var bool */
protected $deleted = false;
/**
* Export to public API
* @return array
......
......@@ -79,8 +79,8 @@ class Manager
public function save(
$entity,
User $moderator,
int $time = null)
{
int $time = null
) {
if (!$time) {
$time = time();
}
......@@ -92,8 +92,8 @@ class Manager
private function saveEntity(
$entity,
User $moderator,
int $time = null)
{
int $time = null
) {
$entity->setModeratorGuid($moderator->getGUID());
$entity->setTimeModerated($time);
......
......@@ -28,6 +28,7 @@ class Repository
$opts = array_merge([
'container_guid' => null,
'type' => null,
'owner_guid' => null,
], $opts);
if (!$opts['type']) {
......@@ -64,6 +65,16 @@ class Repository
]
];
if ($opts['owner_guid']) {
$ownerGuids = Text::buildArray($opts['owner_guid']);
$query['body']['query']['bool']['must'][] = [
'terms' => [
'owner_guid' => $ownerGuids,
],
];
}
$prepared = new Prepared\Count();
$prepared->query($query);
......
......@@ -34,7 +34,8 @@ class Entities
* @param ACL $acl
*/
public function __construct(
$entitiesBuilder = null, $acl = null
$entitiesBuilder = null,
$acl = null
) {
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
$this->acl = $acl ?: ACL::_();
......
<?php
/**
* Index
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Core\Config\Exported;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Domain as ProDomain;
use Minds\Core\Pro\Settings;
use Minds\Core\SEO\Manager;
class Index
{
/** @var Exported */
protected $configExported;
/** @var ProDomain */
protected $proDomain;
/** @var string[] */
protected $meta = [];
/** @var string[] */
protected $head = [];
/** @var string[] */
protected $tail = [];
/** @var string */
protected $context = 'app';
/** @var string */
protected $title = '';
/**
* Index constructor.
* @param Exported $configExported
* @param ProDomain $proDomain
*/
public function __construct(
$configExported = null,
$proDomain = null
) {
$this->configExported = $configExported ?: Di::_()->get('Config\Exported');
$this->proDomain = $proDomain ?: Di::_()->get('Pro\Domain');
$this->build();
}
public function build(): void
{
$this->meta = [];
$this->head = [];
$this->tail = [];
//
/** @var Settings|null $pro */
$pro = $this->proDomain->lookup($_SERVER['HTTP_HOST'] ?? null);
// Config variable
$minds = $this->configExported->export();
if ($pro) {
$minds['pro'] = $pro;
}
// Title
$this->title = 'Minds';
if ($pro) {
$this->title = $pro->getTitle() ?: $pro->getDomain();
}
// Favicons
$icons = [
[
'type' => 'image/svg',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb.svg",
],
[
'rel' => 'apple-touch-icon',
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-apple-touch-icon.png",
'sizes' => '180x180',
],
[
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-32x32.png",
'sizes' => '32x32',
],
[
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-16x16.png",
'sizes' => '16x16',
],
];
if ($pro) {
$icons = [
[
'type' => 'image/jpeg',
'href' => $this->proDomain->getIcon($pro),
],
];
}
foreach ($icons as $icon) {
$attrs = [];
foreach (array_merge(['rel' => 'icon'], $icon) as $key => $value) {
$attrs[] = sprintf("%s=%s", $key, htmlspecialchars($value));
}
$this->meta[] = sprintf("<link %s />", implode(' ', $attrs));
}
// SEO Meta + Title Override
$meta = Manager::get();
foreach ($meta as $name => $content) {
$name = htmlspecialchars($name);
$content = htmlspecialchars($content);
if ($name === 'title') {
$this->title = $content;
continue;
}
$nameAttr = 'name';
if (
strpos($name, ":") !== false &&
strpos($name, "smartbanner") === false
) {
// Attributes with a colon that are not smartbanner
// should use property="<name>"
$nameAttr = 'property';
}
$this->meta[] = sprintf(
"<meta %s=\"%s\" content=\"%s\" />",
$nameAttr,
$name,
$content
);
}
// Head
if ($pro) {
$this->head[] = sprintf(
"<!-- Minds Pro: %s -->\n%s\n<!-- End -->",
$pro->getUserGuid(),
$pro->getCustomHead() ?: '<!-- (no custom head) -->'
);
}
// Tail
$this->tail[] = sprintf("<script>window.Minds = %s;</script>", json_encode($minds));
}
/**
* @return string
*/
public function getMetaHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->meta) . PHP_EOL;
}
/**
* @return string
*/
public function getHeadHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->head) . PHP_EOL;
}
/**
* @return string
*/
public function getTailHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->tail) . PHP_EOL;
}
/**
* @return string
*/
public function getContext(): string
{
return $this->context;
}
/**
* @return string
*/
public function getTitle(): string
{
return $this->title;
}
}
<?php
/**
* Module
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Interfaces\ModuleInterface;
class Module implements ModuleInterface
{
/**
* Executed onInit
* @return void
*/
public function onInit(): void
{
(new Provider())->register();
}
}
<?php
/**
* Provider
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Core\Di\Provider as DiProvider;
class Provider extends DiProvider
{
public function register()
{
$this->di->bind('Front\Index', function () {
return new Index();
}, [ 'useFactory' => true ]);
}
}
......@@ -42,7 +42,6 @@ class Notifications
$cql = null,
$notifications = null,
$notificationBatches = null
) {
$this->relDB = $relDb ?: Di::_()->get('Database\Cassandra\Relationships');
$this->indexDb = $indexDb ?: Di::_()->get('Database\Cassandra\Indexes');
......
......@@ -27,7 +27,10 @@ class CurlWrapper
curl_setopt($this->handle, CURLOPT_BUFFERSIZE, 128);
curl_setopt($this->handle, CURLOPT_NOPROGRESS, false);
curl_setopt($this->handle, CURLOPT_PROGRESSFUNCTION, function (
$downloadSize, $downloaded, $uploadSize, $uploaded
$downloadSize,
$downloaded,
$uploadSize,
$uploaded
) use ($limitKb) {
error_log($downloaded);
if ($downloaded) {
......
......@@ -20,7 +20,7 @@ class Image implements AssetsInterface
public function upload(array $media, array $data)
{
$filename = "/image/{$this->entity->batch_guid}/{$this->entity->guid}/master.jpg";
$filename = "image/{$this->entity->batch_guid}/{$this->entity->guid}/master.jpg";
// @note: legacy file handling
$file = new \ElggFile();
......
......@@ -64,7 +64,10 @@ class Manager
}
$uri = $this->config->get('cdn_url') . 'fs/v1/thumbnail/' . $asset_guid . '/' . $size;
$uri = $this->signUri($uri);
if ($entity->access_id !== ACCESS_PUBLIC) {
$uri = $this->signUri($uri);
}
return $uri;
}
......
......@@ -127,38 +127,17 @@ class Resize
$params = $this->getResizeParameters();
// If is animated,
if ($this->image->getNumberImages() > 1) {
foreach ($this->image as $frame) {
// Crop into square.
$frame->cropImage(
$params['selectionwidth'],
$params['selectionheight'],
$params['xoffset'],
$params['yoffset']
);
// Resize canvas to new image
$frame->setImagePage(0, 0, 0, 0);
// If selected with / height differ from selection width/height, then we need to resize
if ($params['selectionwidth'] !== $params['newwidth'] || $params['selectionheight'] !== $params['newheight']) {
$frame->thumbnailImage($params['newwidth'], $params['newheight']);
}
}
} else {
// Crop the image to selection dimensions
$this->image->cropImage(
$params['selectionwidth'],
$params['selectionheight'],
$params['xoffset'],
$params['yoffset']
);
// If selected with / height differ from selection width/height, then we need to resize
if ($params['selectionwidth'] !== $params['newwidth'] || $params['selectionheight'] !== $params['newheight']) {
$this->image->thumbnailImage($params['newwidth'], $params['newheight']);
}
// First crop the image
$this->image->cropImage(
$params['selectionwidth'],
$params['selectionheight'],
$params['xoffset'],
$params['yoffset']
);
// If selected with / height differ from selection width/height, then we need to resize
if ($params['selectionwidth'] !== $params['newwidth'] || $params['selectionheight'] !== $params['newheight']) {
$this->image->thumbnailImage($params['newwidth'], $params['newheight']);
}
$this->output = $this->image;
......
......@@ -9,6 +9,7 @@
namespace Minds\Core\Media\Proxy;
use Minds\Core\Di\Di;
use Minds\Helpers\File;
use Minds\Core\Http\Curl\Client;
use Minds\Traits\MagicAttributes;
......@@ -99,8 +100,7 @@ class Download
throw new \Exception('Invalid image');
}
$finfo = new \finfo(FILEINFO_MIME);
$mime = $finfo->buffer($content);
$mime = File::getMime($content);
if (!$mime) {
throw new \Exception('Cannot read image MIME');
......
......@@ -34,21 +34,26 @@ class SEO
$type = ucfirst($slugs[0]);
switch ($slugs[1]) {
case 'top':
return $this->getInfo("Top $type",
return $this->getInfo(
"Top $type",
"$type from channels I'm subscribed to",
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs));
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs)
);
break;
case 'network':
return $this->getInfo("$type from your Network",
return $this->getInfo(
"$type from your Network",
"$type from channels you're subscribed to",
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs));
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs)
);
break;
case 'my':
return $this->getInfo(
"Your $type",
"List of your $type",
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs));
Core\Di\Di::_()->get('Config')->site_url . implode('/', $slugs)
);
break;
}
}
......
......@@ -54,6 +54,7 @@ class FFMpeg implements ServiceInterface
'ffmpeg.binaries' => '/usr/bin/ffmpeg',
'ffprobe.binaries' => '/usr/bin/ffprobe',
'ffmpeg.threads' => $this->config->get('transcoder')['threads'],
'timeout' => 0,
]);
$this->ffprobe = $ffprobe ?: FFProbeClient::create([
'ffprobe.binaries' => '/usr/bin/ffprobe',
......@@ -237,8 +238,10 @@ class FFMpeg implements ServiceInterface
}
$video->filters()
->resize(new \FFMpeg\Coordinate\Dimension($opts['width'], $opts['height']),
$rotated ? ResizeFilter::RESIZEMODE_FIT : ResizeFilter::RESIZEMODE_SCALE_WIDTH)
->resize(
new \FFMpeg\Coordinate\Dimension($opts['width'], $opts['height']),
$rotated ? ResizeFilter::RESIZEMODE_FIT : ResizeFilter::RESIZEMODE_SCALE_WIDTH
)
->synchronize();
$formatMap = [
......@@ -251,19 +254,25 @@ class FFMpeg implements ServiceInterface
$pfx = ($rotated ? $opts['width'] : $opts['height']).'.'.$format;
$path = $sourcePath.'-'.$pfx;
try {
echo "\nTranscoding: $path ($this->key)";
echo "\nTranscoding: $path ($this->key)\n";
$formatMap[$format]->on('progress', function ($a, $b, $pct) {
echo "\r$pct% transcoded";
// also emit out to cassandra so frontend can keep track
});
$formatMap[$format]
->setKiloBitRate($opts['bitrate'])
->setAudioChannels(2)
// ->setAudioChannels(2)
->setAudioKiloBitrate($opts['audio_bitrate']);
$video->save($formatMap[$format], $path);
//now upload to s3
$this->uploadTranscodedFile($path, $pfx);
//cleanup tmp file
@unlink($path);
} catch (\Exception $e) {
echo " failed {$e->getMessage()}";
//cleanup tmp file
@unlink($path);
}
}
}
......
......@@ -8,16 +8,27 @@ use Minds\Entities;
class Thumbnails
{
/** @var Core\Config */
protected $config;
/** @var Core\EntitiesBuilder */
protected $entitiesBuilder;
public function __construct($config = null)
public function __construct($config = null, $entitiesBuilder = null)
{
$this->config = $config ?: Di::_()->get('Config');
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
}
public function get($guid, $size)
/**
* @param $entity Entities\Entity|string
* @param $size
* @return bool|\ElggFile|mixed|string
*/
public function get($entity, $size)
{
$entity = Entities\Factory::build($guid);
if (is_string($entity)) {
$entity = $this->entitiesBuilder->build($entity);
}
if (!$entity || !Core\Security\ACL::_()->read($entity)) {
return false;
}
......
......@@ -4,15 +4,13 @@
*/
namespace Minds\Core\Media\Video;
use Aws\S3\S3Client;
use Minds\Common;
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\Entity;
use Minds\Entities\Video;
use Minds\Core\Comments\Comment;
use Aws\S3\S3Client;
class Manager
{
......@@ -64,7 +62,12 @@ class Manager
if (!$cmd) {
return null;
}
if ($entity->access_id !== Common\Access::PUBLIC) {
$url = (string)$this->s3->createPresignedRequest($cmd, '+48 hours')->getUri();
} else {
$url = $this->config->get('cinemr_url') . $entity->cinemr_guid . '/' . $size;
}
return (string) $this->s3->createPresignedRequest($cmd, '+48 hours')->getUri();
return $url;
}
}
......@@ -110,7 +110,7 @@ class OpenSSL implements EncryptionInterface
{
$private_key = openssl_get_privatekey($private_key, $password);
if (!$private_key) {
throw new \Exception('Could not decrypt private key');
throw new \Exception('Failed to unlock private key.');
}
openssl_pkey_export($private_key, $pkeyout, $newpass);
return $pkeyout;
......
......@@ -17,6 +17,7 @@ class Minds extends base
private $modules = [
Events\Module::class,
SSO\Module::class,
Email\Module::class,
Experiments\Module::class,
Helpdesk\Module::class,
......@@ -29,6 +30,7 @@ class Minds extends base
Reports\Module::class,
VideoChat\Module::class,
Feeds\Module::class,
Front\Module::class,
];
/**
......
......@@ -116,7 +116,10 @@ class Ads
$dateRange = $payouts->getPayoutDateRange();
$list = $dateRange ? $this->getList(
$dateRange['start'], $dateRange['end'], $offset, $count
$dateRange['start'],
$dateRange['end'],
$offset,
$count
) : [];
return [
......
......@@ -101,14 +101,16 @@ class Repository
public function add(EarningsDeposit $deposit): bool
{
$prepared = new Prepared();
$prepared->query("INSERT INTO partner_earnings_ledger (user_guid, timestamp, item, amount_cents, amount_tokens) VALUES (?,?,?,?,?)",
$prepared->query(
"INSERT INTO partner_earnings_ledger (user_guid, timestamp, item, amount_cents, amount_tokens) VALUES (?,?,?,?,?)",
[
new Bigint($deposit->getUserGuid()),
new Timestamp($deposit->getTimestamp()),
$deposit->getItem(),
$deposit->getAmountCents() ? (int) $deposit->getAmountCents() : null,
$deposit->getAmountTokens() ? new Bigint($deposit->getAmountTokens()) : null,
]);
]
);
return (bool) $this->db->request($prepared);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.