...
 
Commits (18)
......@@ -26,3 +26,5 @@ node_modules
!/.travis.yml
coverage
!/.gitlab
composer.phar
settings.php-*.bak
......@@ -48,6 +48,11 @@ prepare:fpm:
--build-arg SENTRY_DSN=$SENTRY_DSN \
.
- docker push $CI_REGISTRY_IMAGE/fpm:$CI_PIPELINE_ID
- >
if [ $CI_COMMIT_BRANCH == "master" ]; then
docker tag $CI_REGISTRY_IMAGE/fpm:$CI_PIPELINE_ID $CI_REGISTRY_IMAGE/fpm:latest &&
docker push $CI_REGISTRY_IMAGE/fpm:latest
fi
prepare:runners:
stage: prepare
......@@ -64,6 +69,11 @@ prepare:runners:
--build-arg SENTRY_DSN=$SENTRY_DSN \
.
- docker push $CI_REGISTRY_IMAGE/runners:$CI_PIPELINE_ID
- >
if [ $CI_COMMIT_BRANCH == "master" ]; then
docker tag $CI_REGISTRY_IMAGE/runners:$CI_PIPELINE_ID $CI_REGISTRY_IMAGE/runners:latest &&
docker push $CI_REGISTRY_IMAGE/runners:latest
fi
prepare:all:sentry:
stage: prepare
......
......@@ -64,7 +64,8 @@ class Install extends Cli\Controller implements Interfaces\CliControllerInterfac
if ($installType == "all" || $installType == "cassandra") {
$this->out('- Provisioning Cassandra:', $this::OUTPUT_INLINE);
$isCleanCassandra = $this->getopt("cleanCassandra") != null;
$provisioner->provisionCassandra(null, $isCleanCassandra);
$exitOnFailure = (bool) $this->getopt("exitOnFailure");
$provisioner->provisionCassandra(null, $isCleanCassandra, $exitOnFailure);
$this->out('OK');
$this->out('- Emptying Cassandra pool:', $this::OUTPUT_INLINE);
......@@ -85,7 +86,7 @@ class Install extends Cli\Controller implements Interfaces\CliControllerInterfac
$provisioner->setupFirstAdmin();
$this->out('OK');
} catch (\Exception $ex) {
$this->out('Could not setup initial user');
$this->out("Could not setup initial user: {$ex->getMessage()}");
}
}
......
......@@ -70,7 +70,6 @@ class channel implements Interfaces\Api
$response['channel']['briefdescription'] = $response['channel']['briefdescription'] ?: '';
$response['channel']['city'] = $response['channel']['city'] ?: "";
$response['channel']['gender'] = $response['channel']['gender'] ?: "";
$response['channel']['dob'] = $response['channel']['dob'] ?: "";
if (!$user->merchant || !$supporters_count) {
$db = new Core\Data\Call('entities_by_time');
......@@ -234,7 +233,7 @@ class channel implements Interfaces\Api
$update = [];
foreach (['name', 'website', 'briefdescription', 'gender',
'dob', 'city', 'coordinates', 'monetized'] as $field) {
'city', 'coordinates', 'monetized'] as $field) {
if (isset($_POST[$field])) {
$update[$field] = $_POST[$field];
$owner->$field = $_POST[$field];
......
......@@ -10,6 +10,7 @@ namespace Minds\Controllers\api\v1;
use Minds\Api\Exportable;
use Minds\Core;
use Minds\Core\Data;
use Minds\Core\Router\Exceptions\UnverifiedEmailException;
use Minds\Entities;
use Minds\Exceptions\BlockedUserException;
use Minds\Interfaces;
......@@ -222,6 +223,8 @@ class comments implements Interfaces\Api
} else {
throw new \Exception('The comment couldn\'t be saved');
}
} catch (UnverifiedEmailException $e) {
throw $e;
} catch (BlockedUserException $e) {
$error = true;
......
......@@ -210,9 +210,7 @@ class group implements Interfaces\Api
->setOwnerObj($user);
}
if (Core\Security\ACL::_()->write($group)) {
$group->save();
}
$group->save();
if ($creation) {
// Join group
......
......@@ -266,10 +266,6 @@ class media implements Interfaces\Api, Interfaces\ApiIgnorePam
$entity = Core\Media\Factory::build($clientType);
if (!Security\ACL::_()->write($entity)) {
return false;
}
$container_guid = isset($data['container_guid']) && is_numeric($data['container_guid']) ? $data['container_guid'] : null;
$entity->patch([
'title' => isset($data['name']) ? $data['name'] : '',
......
......@@ -14,6 +14,7 @@ use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\SapiEmitter;
use Minds\Core\Entities\Actions\Save;
use Sentry;
class token implements Interfaces\Api, Interfaces\ApiIgnorePam
......@@ -69,6 +70,15 @@ class token implements Interfaces\Api, Interfaces\ApiIgnorePam
$tokenId = $request->getAttribute('oauth_access_token_id');
$accessTokenRepository->revokeAccessToken($tokenId);
$refreshTokenRepository->revokeRefreshToken($tokenId);
// remove surge token for push notifications.
$user = Session::getLoggedinUser();
$user->setSurgeToken('');
$save = new Save();
$save->setEntity($user)
->save();
$response = new JsonResponse([]);
} catch (\Exception $e) {
Sentry\captureException($e); // Log to sentry
......
......@@ -447,6 +447,8 @@ class Blog extends RepositoryEntity
* Returns if the entity can be edited by the current user
* @param User|null $user
* @return bool
* @throws \Minds\Core\Router\Exceptions\UnverifiedEmailException
* @throws \Minds\Exceptions\StopEventException
*/
public function canEdit(User $user = null)
{
......@@ -505,7 +507,7 @@ class Blog extends RepositoryEntity
$this->markAsDirty('nsfw');
return $this;
}
/**
* Get NSFW Lock options.
*
......@@ -523,7 +525,7 @@ class Blog extends RepositoryEntity
return $array;
}
/**
* Set NSFW lock tags for administrators. Users cannot remove these themselves.
*
......
......@@ -36,9 +36,6 @@ class Manager
/** @var PropagateProperties */
protected $propagateProperties;
/** @var ACL */
protected $acl;
/**
* Manager constructor.
* @param null $repository
......@@ -57,8 +54,7 @@ class Manager
$feeds = null,
$spam = null,
$search = null,
PropagateProperties $propagateProperties = null,
ACL $acl = null
PropagateProperties $propagateProperties = null
) {
$this->repository = $repository ?: new Repository();
$this->paywallReview = $paywallReview ?: new Delegates\PaywallReview();
......@@ -67,7 +63,6 @@ class Manager
$this->spam = $spam ?: Di::_()->get('Security\Spam');
$this->search = $search ?: new Delegates\Search();
$this->propagateProperties = $propagateProperties ?? Di::_()->get('PropagateProperties');
$this->acl = $acl?: ACL::_();
}
/**
......@@ -122,9 +117,6 @@ class Manager
*/
public function add(Blog $blog)
{
if (!$this->acl->write($blog)) {
return false;
}
if ($this->spam->check($blog)) {
return false;
......
......@@ -124,6 +124,7 @@ class Manager
* @return bool
* @throws BlockedUserException
* @throws \Minds\Exceptions\StopEventException
* @throws \Minds\Core\Router\Exceptions\UnverifiedEmailException
*/
public function add(Comment $comment)
{
......
......@@ -123,6 +123,9 @@ class Exported
if ($pro = $this->proDomain->lookup($_SERVER['HTTP_HOST'] ?? null)) {
$exported['pro'] = $pro;
} elseif (!$this->proDomain->isRoot($_SERVER['HTTP_HOST'] ?? null)) {
// If not a pro site and not root then tell frontend to redirect
$exported['redirect_to_root_on_init'] = true;
}
return $exported;
......
......@@ -23,9 +23,6 @@ class Save
/** @var Dispatcher */
protected $eventsDispatcher;
/** @var ACL */
protected $acl;
/** @var mixed */
protected $entity;
......@@ -35,12 +32,9 @@ class Save
* @param null $eventsDispatcher
*/
public function __construct(
$eventsDispatcher = null,
$acl = null,
$manager = null
$eventsDispatcher = null
) {
$this->eventsDispatcher = $eventsDispatcher ?: Di::_()->get('EventsDispatcher');
$this->acl = $acl ?: ACL::_();
}
/**
......@@ -70,10 +64,6 @@ class Save
return false;
}
if (!$this->acl->write($this->entity)) {
return false;
}
$this->beforeSave();
if (method_exists($this->entity, 'save')) {
......
......@@ -237,10 +237,11 @@ class Installer
public function provisionCassandra(
Provisioners\ProvisionerInterface $cassandraStorage = null,
$cleanData = false
$cleanData = false,
$exitOnFailure = false
) {
$cassandraStorage = $cassandraStorage ?: new Provisioners\CassandraProvisioner();
$cassandraStorage->provision($cleanData);
$cassandraStorage->provision($cleanData, $exitOnFailure);
}
public function reloadStorage()
......
......@@ -18,7 +18,7 @@ class CassandraProvisioner implements ProvisionerInterface
$this->client = $client ?: null; // Should be created on-the-fly at provision()
}
public function provision(bool $cleanData)
public function provision(bool $cleanData, bool $exitOnFailure = false)
{
// TODO: Add cleanData to provisioner.
$config = $this->config->get('cassandra');
......@@ -39,6 +39,9 @@ class CassandraProvisioner implements ProvisionerInterface
}
} catch (\Exception $e) {
error_log("Error provisioning cassandra: " . $e->getMessage());
if ($exitOnFailure) {
exit(1);
}
}
return true;
......
......@@ -5,5 +5,5 @@ use Minds\Core\Provisioner\Tasks\TaskInterface;
interface ProvisionerInterface
{
public function provision(bool $cleanData);
public function provision(bool $cleanData, bool $exitOnFailure);
}
......@@ -1545,6 +1545,7 @@ CREATE TABLE minds.experiments (
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';
CREATE INDEX experiments_key_idx ON minds.experiments (key);
ALTER TABLE minds.withdrawals ADD (status text, address text, gas varint);
......
......@@ -173,6 +173,9 @@ class ACL
return false;
}
/**
* If the user hasn't verified the email
*/
if (!$user->isTrusted()) {
throw new UnverifiedEmailException();
}
......@@ -264,6 +267,13 @@ class ACL
return false;
}
/**
* If the user hasn't verified the email
*/
if (!$user->isTrusted()) {
throw new UnverifiedEmailException();
}
/**
* Check if we are the owner
*/
......
......@@ -17,8 +17,8 @@ class XSRF
public static function validateRequest()
{
if (!Core\Session::isLoggedIn() && $_SERVER['REQUEST_METHOD'] === 'GET') {
return true; // If logged out and GET request we can accept
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
return true; // XSRF only needed for modifiers
}
if (!isset($_SERVER['HTTP_X_XSRF_TOKEN'])) {
......
......@@ -163,7 +163,7 @@ class GenericRule implements Interfaces\XSSRule
//make all urls force open in a new tab/window
if ($element->nodeName == 'a') {
$element->setAttribute('target', '_blank');
$element->setAttribute('rel', 'noopener noreferrer nofollow'); //nofollow hurts spammers
$element->setAttribute('rel', 'noopener noreferrer nofollow ugc'); //nofollow hurts spammers
}
}
......
......@@ -53,10 +53,6 @@ class Manager
'events' => true
], $options);
if (!$this->acl->write($vote)) {
return false;
}
if (!$this->acl->interact($vote->getEntity(), $vote->getActor(), "vote{$vote->getDirection()}")) {
throw new \Exception('Actor cannot interact with entity');
}
......@@ -96,10 +92,6 @@ class Manager
'events' => true
], $options);
if (!$this->acl->write($vote)) {
return false;
}
$done = $this->eventsDispatcher->trigger('vote:action:cancel', $vote->getEntity()->type, [
'vote' => $vote
], null);
......
......@@ -63,7 +63,7 @@ class Manager
/** @var Core\Blockchain\Wallets\OffChain\Cap $cap */
protected $cap;
/** @var Delegates\UpgradesDelegate */
protected $upgradesDelegate;
......@@ -82,6 +82,9 @@ class Manager
/** @var StripeIntentsManager $stripeIntentsManager */
protected $stripeIntentsManager;
/** @var Core\Security\ACL */
protected $acl;
public function __construct(
$repository = null,
$txManager = null,
......@@ -95,8 +98,10 @@ class Manager
$notificationDelegate = null,
$cacheDelegate = null,
$offchainTxs = null,
$stripeIntentsManager = null
) {
$stripeIntentsManager = null,
$acl = null
)
{
$this->repository = $repository ?: Di::_()->get('Wire\Repository');
$this->txManager = $txManager ?: Di::_()->get('Blockchain\Transactions\Manager');
$this->txRepo = $txRepo ?: Di::_()->get('Blockchain\Transactions\Repository');
......@@ -104,13 +109,13 @@ class Manager
$this->client = $client ?: Di::_()->get('Blockchain\Services\Ethereum');
$this->token = $token ?: Di::_()->get('Blockchain\Token');
$this->cap = $cap ?: Di::_()->get('Blockchain\Wallets\OffChain\Cap');
$this->upgradesDelegate = $upgradesDelegate ?? new Delegates\UpgradesDelegate();
;
$this->upgradesDelegate = $upgradesDelegate ?? new Delegates\UpgradesDelegate();;
$this->recurringDelegate = $recurringDelegate ?: new Delegates\RecurringDelegate();
$this->notificationDelegate = $notificationDelegate ?: new Delegates\NotificationDelegate();
$this->cacheDelegate = $cacheDelegate ?: new Delegates\CacheDelegate();
$this->offchainTxs = $offchainTxs ?: new Core\Blockchain\Wallets\OffChain\Transactions();
$this->stripeIntentsManager = $stripeIntentsManager ?? Di::_()->get('Stripe\Intents\Manager');
$this->acl = $acl ?: Core\Security\ACL::_();
}
/**
......@@ -194,7 +199,7 @@ class Manager
* @throws WalletNotSetupException
* @throws \Exception
*/
public function create() : bool
public function create(): bool
{
if ($this->payload['method'] == 'onchain' && (!$this->receiver->getEthWallet() || $this->receiver->getEthWallet() != $this->payload['receiver'])) {
throw new WalletNotSetupException();
......@@ -209,6 +214,10 @@ class Manager
->setTimestamp(time())
->setRecurringInterval($this->recurringInterval);
if (!$this->acl->write($wire)) {
return false;
}
switch ($this->payload['method']) {
case 'onchain':
//add transaction to the senders transaction log
......@@ -325,7 +334,7 @@ class Manager
/**
* Confirmationof wire from the blockchain.
*
* @param Wire $wire
* @param Wire $wire
* @param Transaction $transaction - the transaction from the blockchain
*/
public function confirm($wire, $transaction)
......
......@@ -81,6 +81,10 @@ class Group extends NormalizedEntity
$creation = true;
}
if (!$this->canEdit()) {
return false;
}
$saved = $this->saveToDb([
'type' => $this->type,
'guid' => $this->guid,
......@@ -126,6 +130,10 @@ class Group extends NormalizedEntity
*/
public function delete()
{
if (!$this->canEdit()) {
return false;
}
$this->unFeature();
Di::_()->get('Queue')
......@@ -422,7 +430,7 @@ class Group extends NormalizedEntity
$this->conversationDisabled = $value ? 1 : 0;
return $this;
}
/**
* Return the original `owner_guid` for the group.
* @return string guid
......@@ -803,7 +811,7 @@ class Group extends NormalizedEntity
$this->nsfw = $array;
return $this;
}
/**
* Get NSFW Lock options.
*
......@@ -821,7 +829,7 @@ class Group extends NormalizedEntity
return $array;
}
/**
* Set NSFW lock tags for administrators. Users cannot remove these themselves.
*
......
......@@ -192,4 +192,8 @@ class NormalizedEntity
}
return $export;
}
public function canEdit() {
return Core\Security\ACL::_()->write($this);
}
}
......@@ -62,6 +62,7 @@ class User extends \ElggUser
$this->attributes['mode'] = ChannelMode::OPEN;
$this->attributes['email_confirmation_token'] = null;
$this->attributes['email_confirmed_at'] = null;
$this->attributes['surge_token'] = '';
parent::initializeAttributes();
}
......@@ -1204,7 +1205,6 @@ class User extends \ElggUser
return array_merge(parent::getExportableValues(), [
'website',
'briefdescription',
'dob',
'gender',
'city',
'merchant',
......@@ -1237,6 +1237,7 @@ class User extends \ElggUser
'toaster_notifications',
'mode',
'btc_address',
'surge_token',
]);
}
......@@ -1404,4 +1405,26 @@ class User extends \ElggUser
return $this;
}
/**
* Gets the Surge Token of the user for push notifications.
*
* @return string Token.
*/
public function getSurgeToken(): string
{
return (string) $this->surge_token ?? '';
}
/**
* Sets the Surge Token of the user for push notifications.
*
* @param string $token - the token string.
* @return User instance of $this for chaining.
*/
public function setSurgeToken(string $token = ''): User
{
$this->surge_token = $token;
return $this;
}
}
......@@ -36,9 +36,6 @@ class ManagerSpec extends ObjectBehavior
/** @var PropagateProperties */
protected $propagateProperties;
/** @var ACL */
protected $acl;
public function let(
Repository $repository,
Delegates\PaywallReview $paywallReview,
......@@ -46,8 +43,7 @@ class ManagerSpec extends ObjectBehavior
Delegates\Feeds $feeds,
Spam $spam,
Delegates\Search $search,
PropagateProperties $propagateProperties,
ACL $acl
PropagateProperties $propagateProperties
) {
$this->beConstructedWith(
$repository,
......@@ -56,8 +52,7 @@ class ManagerSpec extends ObjectBehavior
$feeds,
$spam,
$search,
$propagateProperties,
$acl
$propagateProperties
);
$this->repository = $repository;
......@@ -67,7 +62,6 @@ class ManagerSpec extends ObjectBehavior
$this->spam = $spam;
$this->search = $search;
$this->propagateProperties = $propagateProperties;
$this->acl = $acl;
}
public function it_is_initializable()
......@@ -157,21 +151,8 @@ class ManagerSpec extends ObjectBehavior
->duringGetNext($blog, 'notimplemented');
}
public function it_should_fail_to_add_if_the_user_hasnt_verified_its_email(Blog $blog)
{
$this->acl->write($blog)
->shouldBeCalled()
->willThrow(UnverifiedEmailException::class);
$this->shouldThrow(UnverifiedEmailException::class)->during('add', [$blog]);
}
public function it_should_add(Blog $blog)
{
$this->acl->write($blog)
->shouldBeCalled()
->willReturn(true);
$this->spam->check($blog)
->shouldBeCalled();
......@@ -299,9 +280,6 @@ class ManagerSpec extends ObjectBehavior
public function it_should_check_for_spam(Blog $blog, Spam $spam)
{
$this->acl->write($blog)
->shouldBeCalled()
->willReturn(true);
$spamUrl = 'movieblog.tumblr.com';
$blog->getType()
......
......@@ -5,27 +5,20 @@ namespace Spec\Minds\Core\Entities\Actions;
use Minds\Core\Blogs\Blog;
use Minds\Core\Entities\Actions\Save;
use Minds\Core\Events\EventsDispatcher;
use Minds\Core\Router\Exceptions\UnverifiedEmailException;
use Minds\Core\Security\ACL;
use Minds\Entities\User;
use Minds\Entities\Activity;
use Minds\Entities\Group;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class SaveSpec extends ObjectBehavior
{
/** @var EventsDispatcher */
protected $dispatcher;
/** @var ACL */
protected $acl;
public function let(EventsDispatcher $dispatcher, ACL $acl)
public function let(EventsDispatcher $dispatcher)
{
$this->beConstructedWith($dispatcher, $acl);
$this->beConstructedWith($dispatcher);
$this->dispatcher = $dispatcher;
$this->acl = $acl;
}
public function it_is_initializable()
......@@ -58,24 +51,11 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($user)
->willReturn(true);
$this->setEntity($user);
$this->save()->shouldReturn(true);
}
public function it_should_fail_to_save_an_entity_if_the_user_is_not_trusted(User $user)
{
$this->acl->write($user, Argument::any())
->willThrow(UnverifiedEmailException::class);
$this->setEntity($user);
$this->shouldThrow(UnverifiedEmailException::class)->during('save');
}
public function it_should_saev_an_entity_via_the_entity_save_event(Blog $blog)
{
$blog->getOwnerEntity()
......@@ -96,9 +76,6 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($blog, Argument::any())
->willReturn(true);
$this->setEntity($blog);
$this->save($blog)->shouldReturn(true);
}
......@@ -140,9 +117,6 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($activity, Argument::any())
->willReturn(true);
$this->setEntity($activity);
$this->save()->shouldReturn(true);
......@@ -185,15 +159,12 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($activity, Argument::any())
->willReturn(true);
$this->setEntity($activity);
$this->save()->shouldReturn(true);
}
public function it_should_save_an_entity_using_its_save_method_with_NSFW_from_container(Activity $activity, Group $container, User $user)
public function it_should_save_an_entity_using_its_save_method_with_NSFW_from_container(Activity $activity, Group $container)
{
$nsfw = [1, 2, 3, 4, 5, 6];
$container->getNsfw()
......@@ -225,16 +196,12 @@ class SaveSpec extends ObjectBehavior
$activity->save()
->shouldBeCalled()
->willReturn(true);
$this->acl->write($activity, Argument::any())
->willReturn(true);
$this->setEntity($activity);
$this->save()->shouldReturn(true);
}
public function it_should_save_an_entity_using_its_save_method_with_NSFW_from_group(Activity $activity, Group $container, User $user)
public function it_should_save_an_entity_using_its_save_method_with_NSFW_from_group(Activity $activity, Group $container)
{
$nsfw = [1, 2, 3, 4, 5, 6];
$container->getNsfw()
......@@ -267,9 +234,6 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($activity, Argument::any())
->willReturn(true);
$this->setEntity($activity);
$this->save()->shouldReturn(true);
......@@ -311,9 +275,6 @@ class SaveSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn(true);
$this->acl->write($activity, Argument::any())
->willReturn(true);
$this->setEntity($activity);
$this->save()->shouldReturn(true);
......
......@@ -39,25 +39,25 @@ class XSSSpec extends ObjectBehavior
public function it_should_dissallow_onClick_attributes()
{
$dirty = "<a onclick=\"console.log('hmmm...')\">click me</a>";
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a target=\"_blank\" rel=\"noopener noreferrer nofollow\">click me</a>");
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a target=\"_blank\" rel=\"noopener noreferrer nofollow ugc\">click me</a>");
}
public function it_should_allow_href_on_anchor_tags()
{
$dirty = "<a href=\"https://www.minds.com\">take me home</a>";
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"https://www.minds.com\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">take me home</a>");
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"https://www.minds.com\" target=\"_blank\" rel=\"noopener noreferrer nofollow ugc\">take me home</a>");
}
public function it_should_not_allow_bad_url_schemes()
{
$dirty = "<a href=\"javascript:alert('HEYHO')\">bad scheme here</a>";
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"alert('HEYHO')\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">bad scheme here</a>");
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"alert('HEYHO')\" target=\"_blank\" rel=\"noopener noreferrer nofollow ugc\">bad scheme here</a>");
}
public function it_should_not_allow_bad_url_schemes_with_case_hacks()
{
$dirty = "<a href=\"Javascript:alert('HEYHO')\">bad scheme here</a>";
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"alert('HEYHO')\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">bad scheme here</a>");
$this->clean($dirty)->shouldReturn('<?xml encoding="utf-8" ?>'."<a href=\"alert('HEYHO')\" target=\"_blank\" rel=\"noopener noreferrer nofollow ugc\">bad scheme here</a>");
}
public function it_should_not_allow_bad_url_schemes_from_multiple_keywords()
......
......@@ -52,10 +52,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getActor()->willReturn($user);
$vote->getDirection()->willReturn('up');
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->acl->interact($entity, $user, 'voteup')
->shouldBeCalled()
->willReturn(true);
......@@ -81,10 +77,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getActor()->willReturn($user);
$vote->getDirection()->willReturn('up');
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->acl->interact($entity, $user, 'voteup')
->shouldBeCalled()
->willReturn(true);
......@@ -106,7 +98,20 @@ class ManagerSpec extends ObjectBehavior
Activity $entity,
User $user
) {
$this->acl->write($vote)
$vote->getEntity()
->shouldBeCalled()
->willReturn($entity);
$vote->getActor()
->shouldBeCalled()
->willReturn($user);
$vote->getDirection()
->shouldBeCalled()
->willReturn('up');
$this->acl->interact($entity, $user, 'voteup')
->shouldBeCalled()
->willThrow(UnverifiedEmailException::class);
......@@ -122,10 +127,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getActor()->willReturn($user);
$vote->getDirection()->willReturn('up');
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->acl->interact($entity, $user, 'voteup')
->shouldBeCalled()
->willReturn(false);
......@@ -148,10 +149,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getEntity()->willReturn($entity);
$vote->getActor()->willReturn($user);
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->counters->update($vote, -1)
->shouldBeCalled()
->willReturn(true);
......@@ -173,10 +170,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getActor()->willReturn($user);
$vote->getDirection()->willReturn('up');
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->dispatcher->trigger('vote:action:cancel', Argument::any(), ['vote' => $vote], null)
->shouldBeCalled()
->willReturn(true);
......@@ -230,10 +223,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getActor()->willReturn($user);
$vote->getDirection()->willReturn('up');
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->acl->interact($entity, $user, 'voteup')
->shouldBeCalled()
->willReturn(true);
......@@ -262,10 +251,6 @@ class ManagerSpec extends ObjectBehavior
$vote->getEntity()->willReturn($entity);
$vote->getActor()->willReturn($user);
$this->acl->write($vote)
->shouldBeCalled()
->willReturn(true);
$this->indexes->exists($vote)
->shouldBeCalled()
->willReturn(true);
......
......@@ -92,4 +92,18 @@ class UserSpec extends ObjectBehavior
$export = $this->export()->getWrappedObject();
expect($export['mode'])->shouldEqual(ChannelMode::OPEN);
}
public function it_should_get_surge_token()
{
$token = '11111';
$this->surge_token = $token;
$this->getSurgeToken()->shouldReturn($token);
}
public function it_should_set_surge_token()
{
$token = '11111';
$this->setSurgeToken($token)->shouldReturnAnInstanceOf('Minds\Entities\User');
$this->getSurgeToken()->shouldReturn($token);
}
}
......@@ -7,11 +7,11 @@
"content-hash": "8d780cdee45441b9106ff5986f7afbd0",
"packages": [
{
"name": "Minds/Surge",
"name": "minds/surge",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://bc220f12a84437201d2bc003c3afe0b543040b36@github.com/minds/Surge.git",
"url": "https://bc220f12a84437201d2bc003c3afe0b543040b36@github.com/minds/surge.git",
"reference": "28efecd8e6518869aca8e0357cdb869e82caf6d4"
},
"type": "library",
......
#!/bin/sh
# Exit script wit ERRORLEVEL if any command fails
set -e
echo "INSTALLING MINDS"
cd /var/www/Minds/engine
......@@ -18,4 +21,5 @@ php /var/www/Minds/engine/cli.php install \
--email-public-key=/.dev/minds.pub \
--phone-number-private-key=/.dev/minds.pem \
--phone-number-public-key=/.dev/minds.pub \
--cassandra-server=cassandra
--cassandra-server=cassandra \
--exitOnFailure=1
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
listen.backlog = -1
pm = static
pm.max_children = 4
pm.max_requests = 10000
pm = ondemand
pm.max_children = 75
pm.process_idle_timeout = 10s
pm.max_requests = 100
pm.status_path = /status
chdir = /
catch_workers_output = yes
slowlog = /dev/stderr
request_slowlog_timeout = 10s
request_terminate_timeout = 120s
rlimit_files = 65535
env[MINDS_VERSION] = $MINDS_VERSION
env[MINDS_ENV] = $MINDS_ENV
env[SENTRY_DSN] = $SENTRY_DSN
......@@ -6,7 +6,7 @@ ADD --chown=www-data . /var/www/Minds/engine
# Remove the local settings file (if it exists)
RUN rm -f /var/www/Minds/engine/settings.php
# RUN rm -f /var/www/Minds/engine/settings.php
# Setup our supervisor service
......
FROM minds/php:7.3
WORKDIR /var/www/Minds/engine
COPY ./containers/phpspec/phpspec.sh /var/www/Minds/phpspec.sh
ENTRYPOINT [ "../phpspec.sh" ]
CMD ["run", "--format=pretty", "--no-code-generation"]
#!/bin/sh
set -e
cd /var/www/Minds/engine
php -n -c Spec/php-test.ini bin/phpspec $@
......@@ -143,7 +143,7 @@ $CONFIG->__site_secret__ = '{{site-secret}}';
// $CONFIG->cdn_url = 'http://{{domain}}/';
$CONFIG->site_url = 'http://{{domain}}/';
$CONFIG->cdn_url = 'http://{{domain}}/';
$CONFIG->cdn_assets_url = 'http://{{domain}}/en/';
$CONFIG->cdn_assets_url = 'http://{{domain}}/';
$CONFIG->zmq_server = 'localhost';
$CONFIG->checkout_url = 'http://{{checkout_domain}}/';
......
#!/bin/sh
# Exit script wit ERRORLEVEL if any command fails
set -e
INSTALLOPTS=""
if [ "$1" == "production" ]; then
INSTALLOPTS="-a"
......@@ -10,11 +13,12 @@ rm -rf ../vendor
# Setup composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === 'c5b9b6d368201a9db6f74e2611495f369991b72d9c8cbd3ffbc63edff210eb73d46ffbfce88669ad33695ef77dc76976') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
# Optimise for package install speed
composer.phar -n global require -n "hirak/prestissimo"
php composer.phar -n global require -n "hirak/prestissimo"
# Grab dependencies
php composer.phar install $INSTALLOPTS --ignore-platform-reqs