...
 
Commits (11)
......@@ -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];
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
}
}
......
......@@ -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();
}
......@@ -1194,7 +1195,6 @@ class User extends \ElggUser
return array_merge(parent::getExportableValues(), [
'website',
'briefdescription',
'dob',
'gender',
'city',
'merchant',
......@@ -1227,6 +1227,7 @@ class User extends \ElggUser
'toaster_notifications',
'mode',
'btc_address',
'surge_token',
]);
}
......@@ -1394,4 +1395,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;
}
}
......@@ -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()
......
......@@ -71,4 +71,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