Skip to content
Commits on Source (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'])) {
......