Skip to content
Commits on Source (29)
......@@ -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;
......
......@@ -3,7 +3,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<style>
p {
p, li {
font-family: Roboto,Arial,sans-serif;
font-size: 18px;
line-height: 1.5;
......
<?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([]);
}
}
......@@ -10,7 +10,7 @@ use Minds\Interfaces;
use Minds\Core\Media\Video\Manager;
use Minds\Entities;
class transcode implements Interfaces\Api, Interfaces\ApiAdminPam
class transcode implements Interfaces\Api //, Interfaces\ApiAdminPam
{
/**
* Not yet implemented GET.
......@@ -30,7 +30,6 @@ class transcode implements Interfaces\Api, Interfaces\ApiAdminPam
public function post($pages)
{
$guid = intval($_POST['guid']);
if (!$guid) {
return Factory::response(['status' => 'error', 'message' => 'You must send a GUID.']);
}
......@@ -41,15 +40,9 @@ class transcode implements Interfaces\Api, Interfaces\ApiAdminPam
return Factory::response(['status' => 'error', 'message' => 'Entity not found.']);
}
$user = $entity->getOwnerEntity();
if (!$user) {
return Factory::response(['status' => 'error', 'message' => 'User not found.']);
}
$videoManager = new Manager();
if (!$videoManager->queueTranscoding($guid, $user->isPro())) {
if (!$videoManager->transcode($entity)) {
return Factory::response(['status' => 'error', 'message' => 'Failed to add video to transcoding queue.']);
}
......
......@@ -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']));
......
......@@ -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,8 +28,6 @@ class channel implements Interfaces\Api
*/
public function get($pages)
{
$currentUser = Session::getLoggedinUser();
$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);
......
......@@ -43,9 +43,12 @@ class content implements Interfaces\Api
}
$type = '';
$algorithm = strtolower($_GET['algorithm'] ?? 'top');
switch ($pages[1]) {
case 'activities':
$type = 'activity';
$algorithm = 'latest';
break;
case 'images':
$type = 'object:image';
......@@ -127,7 +130,7 @@ class content implements Interfaces\Api
'custom_type' => null,
'limit' => $limit,
'type' => $type,
'algorithm' => 'top',
'algorithm' => $algorithm,
'period' => '7d',
'sync' => $sync,
'from_timestamp' => $fromTimestamp,
......@@ -159,7 +162,7 @@ class content implements Interfaces\Api
try {
$result = $this->getData($entities, $opts, $asActivities, $sync);
if ($result->count() <= static::MIN_COUNT) {
if ($opts['algorithm'] !== 'latest' && $result->count() <= static::MIN_COUNT) {
$opts['algorithm'] = 'latest';
$result = $this->getData($entities, $opts, $asActivities, $sync);
}
......
<?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,13 @@ class wire implements Interfaces\Api
$amount = BigNumber::_($_POST['amount']);
$recurring = isset($_POST['recurring']) ? $_POST['recurring'] : false;
$recurringInterval = $_POST['recurring_interval'] ?? 'once';
if ($recurring && $recurringInterval === 'once') {
$recurringInterval = 'monthly';
// Client side bug we need to track down, so lets log in Sentry
\Sentry\captureMessage("Recurring Subscription was created with 'once' interval");
}
if (!$amount) {
return Factory::response(['status' => 'error', 'message' => 'you must send an amount']);
......@@ -80,6 +87,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']);
......
......@@ -17,7 +17,7 @@ class SalesEarningsMetric extends AbstractEarningsMetric
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' ];
......
......@@ -17,7 +17,7 @@ class ViewsEarningsMetric extends AbstractEarningsMetric
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 channels assets. You earn a variable RPM for every 1,000 pageviews.";
/** @var array */
protected $permissions = [ 'user', 'admin' ];
......
......@@ -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,29 +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) {
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);
......
Our team has been heads down in the lab developing open source technology that is changing the world. As always, our goal is to provide you with a platform that enables the free exchange of ideas, protects your digital rights and fairly compensates you for your contributions to the network.
Introducing Minds Pro (beta), a new revenue model for content creators.
- Get paid for your traffic and referrals
- Launch your own website
- Receive multi-currency tips and subscription payments from fans
- Supports video, images, blogs and more
| |
|:--:|
| [![Upgrade to Pro](https://cdn-assets.minds.com/emails/upgrade-to-pro.png){=150x}](https://www.minds.com/pro?__e_ct_guid=<?= $vars['guid']?>&campaign=<?= $vars['campaign']?>&topic=<?= $vars['topic'] ?>&validator=<?= $vars['validator'] ?>) |
| |
Thank you for your support!
......@@ -42,6 +42,9 @@ class FeedSyncEntity implements JsonSerializable
/** @var Entity */
protected $entity;
/** @var bool */
protected $deleted = false;
/**
* Export to public API
* @return array
......
......@@ -80,15 +80,14 @@ class Manager
/**
* Add a video to the transcoding queue
*
* @param Integer $guid - the guid of the video.
* @param boolean $fullhd - whether to transcode full_hd.
* @param Entity $entity - the entity to be re-transcoded.
* @return boolean true if video added to transcode queue.
*/
public function queueTranscoding($guid, $fullhd = false)
public function transcode($entity): bool
{
try {
$this->transcoder->setKey($guid);
$this->transcoder->setFullHD($fullhd ?? false);
$this->transcoder->setKey($entity->guid);
$this->transcoder->setFullHD($entity->getOwnerEntity()->isPro() ?? false);
$this->transcoder->transcode();
return true;
} catch (\Exception $e) {
......
......@@ -16,6 +16,7 @@ class Minds extends base
private $modules = [
Events\Module::class,
SSO\Module::class,
Email\Module::class,
Experiments\Module::class,
Helpdesk\Module::class,
......
......@@ -71,6 +71,16 @@ class Domain
return !$settings || ((string) $settings->getUserGuid() === $userGuid);
}
/**
* @param string $domain
* @return bool
*/
public function isRoot(string $domain): bool
{
$rootDomains = $this->config->get('pro')['root_domains'] ?? [];
return in_array(strtolower($domain), $rootDomains, true);
}
/**
* @param Settings $settings
* @param User|null $owner
......