Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge 2.2 into 2.x #10184

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f90b1eb
fix(boot): boot cache now respects system cache setting
mrclay Aug 11, 2016
01f4f1d
fix(access): updates no longer mistakenly blocked in some scenarios
mrclay Aug 20, 2016
b0f8d16
Merge pull request #10103 from mrclay/10098_update
mrclay Aug 23, 2016
1ee8fe9
fix(web_services): create_api_user() and create_user_token() work again
Wouter0100 Aug 19, 2016
7ccf5fe
Merge pull request #10106 from mrclay/Wouter0100-patch-7
mrclay Aug 23, 2016
3467829
fix(discussions): removes site "Discussions" menu item added in 2.2.0
mrclay Aug 24, 2016
c7c4476
fix(core): boot no longer throws DB exception in some edge cases
mrclay Aug 26, 2016
5a58317
fix(views): some functions that use views fallback to default viewtype
mrclay Aug 27, 2016
a8052f9
fix(js): output deprecation messages to admins in browser console only
iionly Aug 27, 2016
580b070
Merge pull request #10085 from mrclay/boot_cache
mrclay Aug 28, 2016
1db4994
docs(license): clarifies dual licensing in LICENSE.txt
mrclay Aug 17, 2016
110dd8a
Merge pull request #10136 from mrclay/license_clarification_112
mrclay Aug 28, 2016
7f808d6
security(htmlawed): upgrades htmLawed to latest, currently 1.1.22
mrclay Aug 29, 2016
5243256
Merge pull request #10143 from mrclay/10126_htmlawed
mrclay Aug 29, 2016
97edc29
Merge branch '1.12' into merge112
mrclay Aug 29, 2016
5398f0e
Merge pull request #10145 from mrclay/merge112
mrclay Aug 30, 2016
11845f4
Merge pull request #10134 from iionly/js-deprecation-messages
mrclay Aug 30, 2016
8a81845
Merge pull request #10123 from mrclay/10119_boot
mrclay Sep 1, 2016
739259f
fix(reportedcontent): Reported Content admin widget works again
mrclay Sep 4, 2016
98843dc
Merge pull request #10152 from mrclay/10151_reported
hypeJunction Sep 4, 2016
a78aa35
fix(members): Don't rely on newest members tab set as default tab in …
iionly Sep 5, 2016
af103c7
fix(views): input/select view can select options more reliably
mrclay Sep 6, 2016
f288215
fix(likes): don't emit notice if a listing's `$vars['list_class']` is…
mrclay Sep 6, 2016
c568a08
Merge pull request #10162 from iionly/newest-member-tab
hypeJunction Sep 6, 2016
57f97a9
Merge pull request #10163 from mrclay/notices2
hypeJunction Sep 6, 2016
9465a4d
Merge pull request #10164 from mrclay/likes_notice
hypeJunction Sep 6, 2016
bc5f414
fix(pages): operations keep track of more than 10 child pages
mrclay Sep 6, 2016
e395620
chore(bookmarks): Removal of unused 'shares' code and unused language…
iionly Sep 6, 2016
3002bf0
Merge pull request #10168 from iionly/remove-unused-share-references
hypeJunction Sep 7, 2016
353a1ef
Merge pull request #10167 from mrclay/pages_limits
hypeJunction Sep 8, 2016
4139233
Merge pull request #10127 from mrclay/10114_excerpt
hypeJunction Sep 8, 2016
fc5cf62
Merge pull request #10111 from mrclay/9731_discussions_menu
hypeJunction Sep 8, 2016
e05d78f
chore(tests): test entity accessibility in the notifications flow
mrclay Aug 29, 2016
c1369cf
Merge pull request #10175 from hypeJunction/notif-access-test
hypeJunction Sep 8, 2016
74dfbf1
Merge remote-tracking branch 'upstream/1.12' into merge_1.12_2.2
hypeJunction Sep 8, 2016
6c17c21
Merge pull request #10177 from hypeJunction/merge_1.12_2.2
hypeJunction Sep 8, 2016
915865b
fix(plugins): Make activate/deactivate all plugins to work also on Fi…
iionly Sep 8, 2016
65d63d8
Merge pull request #10180 from iionly/toggle-all-plugins
mrclay Sep 8, 2016
b349be9
Merge branch '2.2' into merge22
mrclay Sep 10, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 6 additions & 5 deletions COPYRIGHT.txt
@@ -1,14 +1,15 @@
The follow individuals, companies, or entities have contributed significant
code to the Elgg project and share the copyright. (In alphabetical order.)

Organizations:
The MITRE Corportation (jricher@mitre.org)
Curverider Ltd (info@elgg.com)

Individuals:
Steve Clay (steve@mrclay.org)
Cash Costello (cash.costello@gmail.com)
Brett Profitt (brett.profitt@gmail.com)
Dave Tosh (davidgtosh@gmail.com)
Ben Werdmuller (ben@benwerd.com)
Evan Winslow (evan.b.winslow@gmail.com)

Organizations:
The MITRE Corportation (jricher@mitre.org)
Curverider Ltd (info@elgg.com)

When adding to this list, update the list of copyright owners in LICENSE.txt.
45 changes: 45 additions & 0 deletions LICENSE.txt
@@ -1,3 +1,48 @@
Bundled plugins (the contents of the "/mod" directory) are available
only under the GPLv2 license.

The remainder of the project is available under either MIT or GPLv2.

Both licenses can be found below.

More info: http://learn.elgg.org/en/latest/intro/license.html

------------------------------------------------------------------------

The MIT License (MIT)
Copyright (c) 2016 The following parties:

Steve Clay (steve@mrclay.org)
Cash Costello (cash.costello@gmail.com)
Brett Profitt (brett.profitt@gmail.com)
Dave Tosh (davidgtosh@gmail.com)
Ben Werdmuller (ben@benwerd.com)
Evan Winslow (evan.b.winslow@gmail.com)

The MITRE Corportation (jricher@mitre.org)
Curverider Ltd (info@elgg.com)

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

------------------------------------------------------------------------

GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Expand Down
30 changes: 16 additions & 14 deletions engine/classes/Elgg/BootData.php
Expand Up @@ -125,20 +125,22 @@ public function populate(\stdClass $config, Database $db, EntityTable $entities,
$guids = array_values($guids);
$guids = array_diff($guids, $unsuitable_guids);

// get the settings
$set = implode(',', $guids);
$rows = $db->getData("
SELECT entity_guid, `name`, `value`
FROM {$db->prefix}private_settings
WHERE entity_guid IN ($set)
AND name NOT LIKE 'plugin:user_setting:%'
AND name NOT LIKE 'elgg:internal:%'
ORDER BY entity_guid
");
// make sure we show all entities as loaded
$this->plugin_settings = array_fill_keys($guids, []);
foreach ($rows as $i => $row) {
$this->plugin_settings[$row->entity_guid][$row->name] = $row->value;
if ($guids) {
// get the settings
$set = implode(',', $guids);
$rows = $db->getData("
SELECT entity_guid, `name`, `value`
FROM {$db->prefix}private_settings
WHERE entity_guid IN ($set)
AND name NOT LIKE 'plugin:user_setting:%'
AND name NOT LIKE 'elgg:internal:%'
ORDER BY entity_guid
");
// make sure we show all entities as loaded
$this->plugin_settings = array_fill_keys($guids, []);
foreach ($rows as $i => $row) {
$this->plugin_settings[$row->entity_guid][$row->name] = $row->value;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion engine/classes/Elgg/BootService.php
Expand Up @@ -141,7 +141,9 @@ public function boot() {

// finish boot sequence
_elgg_session_boot();
_elgg_services()->systemCache->loadAll();
if ($CONFIG->system_cache_enabled) {
_elgg_services()->systemCache->loadAll();
}
_elgg_services()->translator->loadTranslations();

// we always need site->email and user->icontime, so load them together
Expand Down
3 changes: 3 additions & 0 deletions engine/classes/Elgg/Database/AccessCollections.php
Expand Up @@ -393,6 +393,9 @@ public function getWhereSql(array $options = array()) {
* @return bool
*/
public function hasAccessToEntity($entity, $user = null) {
if (!$entity instanceof \ElggEntity) {
return false;
}

// See #7159. Must not allow ignore access to affect query
$ia = elgg_set_ignore_access(false);
Expand Down
10 changes: 5 additions & 5 deletions engine/classes/ElggCrypto.php
Expand Up @@ -25,15 +25,15 @@ class ElggCrypto {
/**
* @var SiteSecret
*/
private $siteSecret;
private $site_secret;

/**
* Constructor
*
* @param SiteSecret $siteSecret Secret service
* @param SiteSecret $site_secret Secret service
*/
public function __construct(SiteSecret $siteSecret) {
$this->siteSecret = $siteSecret;
public function __construct(SiteSecret $site_secret = null) {
$this->site_secret = $site_secret;
}

/**
Expand Down Expand Up @@ -185,7 +185,7 @@ public function getRandomBytes($length) {
*/
public function getHmac($data, $algo = 'sha256', $key = '') {
if (!$key) {
$key = $this->siteSecret->get(true);
$key = $this->site_secret->get(true);
}
return new Elgg\Security\Hmac($key, [$this, 'areEqual'], $data, $algo);
}
Expand Down
6 changes: 0 additions & 6 deletions engine/classes/ElggEntity.php
Expand Up @@ -1608,12 +1608,6 @@ protected function update() {

_elgg_services()->boot->invalidateCache($this->guid);

if (!has_access_to_entity($this)) {
// Why worry about this case? If access control was off when the user fetched $this, but
// was turned back on again. Better to just bail than to turn access control off again.
return false;
}

if (!$this->canEdit()) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion engine/classes/ElggSession.php
Expand Up @@ -213,7 +213,7 @@ public function setLoggedInUser(\ElggUser $user) {
/**
* Gets the logged in user
*
* @return \ElggUser
* @return \ElggUser|null
* @since 1.9
*/
public function getLoggedInUser() {
Expand Down
5 changes: 4 additions & 1 deletion engine/lib/output.php
Expand Up @@ -70,11 +70,14 @@ function elgg_autop($string) {
* @since 1.7.2
*/
function elgg_get_excerpt($text, $num_chars = 250) {
$view = 'output/excerpt';
$vars = [
'text' => $text,
'num_chars' => $num_chars,
];
return elgg_view('output/excerpt', $vars);
$viewtype = elgg_view_exists($view) ? '' : 'default';

return _elgg_view_under_viewtype($view, $vars, $viewtype);
}

/**
Expand Down
33 changes: 31 additions & 2 deletions engine/lib/views.php
Expand Up @@ -1140,9 +1140,12 @@ function elgg_view_title($title, array $vars = array()) {
* @since 1.7.2
*/
function elgg_view_friendly_time($time) {
return elgg_view('output/friendlytime', array('time' => $time));
}
$view = 'output/friendlytime';
$vars = ['time' => $time];
$viewtype = elgg_view_exists($view) ? '' : 'default';

return _elgg_view_under_viewtype($view, $vars, $viewtype);
}

/**
* Returns rendered comments and a comment form for an entity.
Expand Down Expand Up @@ -1927,6 +1930,32 @@ function _elgg_get_js_page_data() {
return $elgg;
}

/**
* Render a view while the global viewtype is temporarily changed. This makes sure that
* nested views use the same viewtype.
*
* @param string $view View name
* @param array $vars View vars
* @param string $viewtype Temporary viewtype ('' to leave current)
*
* @return mixed
* @access private
*/
function _elgg_view_under_viewtype($view, $vars, $viewtype) {
if ($viewtype) {
$old = elgg_get_viewtype();
elgg_set_viewtype($viewtype);
}

$ret = elgg_view($view, $vars);

if ($viewtype) {
elgg_set_viewtype($old);
}

return $ret;
}

return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
$events->registerHandler('boot', 'system', 'elgg_views_boot');
$hooks->registerHandler('view_vars', 'all', '_elgg_manage_pagesetup', 1000);
Expand Down
45 changes: 44 additions & 1 deletion engine/tests/ElggCoreAccessSQLTest.php
Expand Up @@ -179,6 +179,49 @@ public function testAccessPluginHookAddAnd() {
$this->assertTrue($this->assertSqlEqual($ans, $sql), "$sql does not match $ans");
}

public function testHasAccessToEntity() {
$session = elgg_get_session();
$test_user = $session->getLoggedInUser();

$object = new ElggObject();
$object->access_id = ACCESS_PRIVATE;
$object->save();

$session->removeLoggedInUser();
$this->assertFalse(has_access_to_entity($object));
$this->assertFalse(has_access_to_entity($object, $this->user));
$session->setLoggedInUser($test_user);

$object->access_id = ACCESS_PUBLIC;
$object->save();

$session->removeLoggedInUser();
$this->assertTrue(has_access_to_entity($object));
$this->assertTrue(has_access_to_entity($object, $this->user));
$session->setLoggedInUser($test_user);

$object->access_id = ACCESS_LOGGED_IN;
$object->save();

$session->removeLoggedInUser();
$this->assertFalse(has_access_to_entity($object));
$this->assertTrue(has_access_to_entity($object, $this->user));
$session->setLoggedInUser($test_user);

$test_user->addFriend($this->user->guid);

$object->access_id = ACCESS_FRIENDS;
$object->save();

$session->removeLoggedInUser();
$this->assertFalse(has_access_to_entity($object));
$this->assertTrue(has_access_to_entity($object, $this->user));
$session->setLoggedInUser($test_user);

$test_user->removeFriend($this->user->guid);
$object->delete();
}

public function addAndCallback($hook, $type, $clauses, $params) {
$clauses['ands'][] = '57 > 32';
return $clauses;
Expand Down Expand Up @@ -215,4 +258,4 @@ protected function getLoggedOutAccessListClause($table_alias) {
$table_alias = $table_alias ? $table_alias . '.' : '';
return "{$table_alias}access_id IN (2)";
}
}
}
7 changes: 3 additions & 4 deletions engine/tests/ElggCoreMetadataAPITest.php
Expand Up @@ -161,8 +161,7 @@ public function test_elgg_metadata_multiple_values() {

// need to fake different logins.
// good times without mocking.
$original_user = elgg_get_logged_in_user_entity();
$_SESSION['user'] = $u1;
$original_user = $this->replaceSession($u1);

elgg_set_ignore_access(false);

Expand All @@ -182,7 +181,7 @@ public function test_elgg_metadata_multiple_values() {
}

// add md w/ same name as a different user
$_SESSION['user'] = $u2;
$this->replaceSession($u2);
$md_values2 = array(
'four',
'five',
Expand All @@ -202,7 +201,7 @@ public function test_elgg_metadata_multiple_values() {
$this->assertEqual('test', $md->name);
}

$_SESSION['user'] = $original_user;
$this->replaceSession($original_user);

$obj->delete();
$u1->delete();
Expand Down
17 changes: 17 additions & 0 deletions engine/tests/ElggCoreUnitTest.php
Expand Up @@ -48,6 +48,23 @@ public function assertIdenticalEntities(\ElggEntity $first, \ElggEntity $second,
return $this->assert(new IdenticalEntityExpectation($first), $second, $message);
}

/**
* Replace the current user session
*
* @param ElggUser $user New user to login as (null to log out)
* @return ElggUser|null Removed session user (or null)
*/
public function replaceSession(ElggUser $user = null) {
$session = elgg_get_session();
$old = $session->getLoggedInUser();
if ($user) {
$session->setLoggedInUser($user);
} else {
$session->removeLoggedInUser();
}
return $old;
}

}

/**
Expand Down
33 changes: 33 additions & 0 deletions engine/tests/ElggEntityTest.php
Expand Up @@ -379,4 +379,37 @@ public function testCreateWithContainerGuidEqualsZero() {
$user->delete();

}

public function testUpdateAbilityDependsOnCanEdit() {
$this->entity->access_id = ACCESS_PRIVATE;

$this->assertTrue($this->entity->save());

// even owner can't bypass permissions
elgg_register_plugin_hook_handler('permissions_check', 'object', [Elgg\Values::class, 'getFalse'], 999);
$this->assertFalse($this->entity->save());
elgg_unregister_plugin_hook_handler('permissions_check', 'object', [Elgg\Values::class, 'getFalse']);

$user = new ElggUser();
$user->save();
$old_user = $this->replaceSession($user);

$this->assertFalse($this->entity->save());

elgg_register_plugin_hook_handler('permissions_check', 'object', [Elgg\Values::class, 'getTrue']);

// even though this user can't look up the entity via the DB, permission allows update.
$this->assertFalse(has_access_to_entity($this->entity, $user));
$this->assertTrue($this->entity->save());

elgg_unregister_plugin_hook_handler('permissions_check', 'object', [Elgg\Values::class, 'getTrue']);

// can save with access ignore
$ia = elgg_set_ignore_access();
$this->assertTrue($this->entity->save());
elgg_set_ignore_access($ia);

$this->replaceSession($old_user);
$user->delete();
}
}