Compare commits
74 Commits
dav-push-sync
...
v14.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
| d96adc01b7 | |||
| 884ac1e117 | |||
| c35401110a | |||
| 62b9ae21fe | |||
| 1f714124bb | |||
| 4d8f69f7a4 | |||
| e77bd8a894 | |||
| ea73f30d77 | |||
| 0c85cb1ea9 | |||
| a0f2bd8d28 | |||
| e5176960ce | |||
| 9a4ad9cd17 | |||
| 2153bcfea8 | |||
| 6718bfb83d | |||
| 3a179b2519 | |||
| 8dff9460b8 | |||
| 43889d1a49 | |||
| fcda1f7124 | |||
| efbd98183d | |||
| d69ddd94de | |||
| ccb8838854 | |||
| 19350c4b95 | |||
| 258330d64d | |||
| c02c63f53a | |||
| 86a2d1fecd | |||
| e2991d55c7 | |||
| bea36f9992 | |||
| 64d8f74c32 | |||
| cfca80ef69 | |||
| 27a3867094 | |||
| 7b3e3ee898 | |||
| 5e13368299 | |||
| b66b2de6ff | |||
| 43f73ad808 | |||
| 4cc8cdc276 | |||
| 3a30fa1235 | |||
| d50fa1bdb8 | |||
| fbc1f5cd38 | |||
| 896c8df6ad | |||
| a9fa17eb7e | |||
| fb9379db3e | |||
| 5058333445 | |||
| 5bf377463e | |||
| 2823d7a6f5 | |||
| 72588b69bb | |||
| 843df1c009 | |||
| 53ecdfec51 | |||
| 4165f332de | |||
| 8e3e25a057 | |||
| 2518cdd2d9 | |||
| 73e870bd78 | |||
| 5209348c64 | |||
| 9b64c27ce2 | |||
| e296f7d348 | |||
| 5b89eff367 | |||
| b580ef18c8 | |||
| c83ac2472d | |||
| 54859329ef | |||
| 1b35dc1cba | |||
| b619e8ddde | |||
| 51b978d3f0 | |||
| 2e424d84a4 | |||
| e7d4d3a34b | |||
| 7c851b5b77 | |||
| b14425ef6f | |||
| 3c63850117 | |||
| 6b7e049288 | |||
| 3ee07ac770 | |||
| da75c7ff6d | |||
| 4173f9d588 | |||
| 2bdc407a82 | |||
| b08f67085d | |||
| b0d9030388 | |||
| 209b3bee68 |
@@ -22,6 +22,9 @@
|
||||
padding: 10px;
|
||||
min-height: 44px;
|
||||
margin: 0;
|
||||
|
||||
/* Prevent the text from overlapping with the submit button. */
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
#commentsTabView .newCommentForm {
|
||||
@@ -130,7 +133,7 @@
|
||||
adding this brings them closer to the element**/
|
||||
margin-top: 5px;
|
||||
}
|
||||
#commentsTabView .comments li .message .avatar-name-wrapper,
|
||||
|
||||
.atwho-view-ul * .avatar-name-wrapper,
|
||||
#commentsTabView .comment .authorRow {
|
||||
position: relative;
|
||||
@@ -141,24 +144,34 @@
|
||||
|
||||
#commentsTabView .comment:not(.newCommentRow) .message .avatar-name-wrapper:not(.currentUser),
|
||||
#commentsTabView .comment:not(.newCommentRow) .message .avatar-name-wrapper:not(.currentUser) .avatar,
|
||||
#commentsTabView .comment:not(.newCommentRow) .message .avatar-name-wrapper:not(.currentUser) .avatar img,
|
||||
#commentsTabView .comment .authorRow .avatar:not(.currentUser),
|
||||
#commentsTabView .comment .authorRow .author:not(.currentUser) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.atwho-view-ul .avatar-name-wrapper,
|
||||
.atwho-view-ul .avatar-name-wrapper .avatar {
|
||||
.atwho-view-ul .avatar-name-wrapper .avatar,
|
||||
.atwho-view-ul .avatar-name-wrapper .avatar img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#commentsTabView .comments li .message .atwho-inserted,
|
||||
#commentsTabView .newCommentForm .atwho-inserted {
|
||||
.avatar-name-wrapper {
|
||||
/* Make the wrapper the positioning context of its child contacts
|
||||
* menu. */
|
||||
position: relative;
|
||||
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
background-color: var(--color-background-dark);
|
||||
border-radius: 50vh;
|
||||
padding: 1px 7px 1px 1px;
|
||||
|
||||
/* Ensure that the avatar and the user name will be kept together. */
|
||||
white-space: nowrap;
|
||||
|
||||
.avatar {
|
||||
img {
|
||||
vertical-align: top;
|
||||
@@ -171,6 +184,15 @@
|
||||
margin-left: 0;
|
||||
margin-right: 2px;
|
||||
}
|
||||
strong {
|
||||
/* Ensure that the user name is shown in bold, as different browsers
|
||||
* use different font weights for strong elements. */
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.avatar-name-wrapper.currentUser {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,4 +253,4 @@
|
||||
|
||||
.app-files .action-comment {
|
||||
padding: 16px 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,24 +196,26 @@
|
||||
sorter: function (q, items) { return items; }
|
||||
},
|
||||
displayTpl: function (item) {
|
||||
return '<li>'
|
||||
+ '<span class="avatar-name-wrapper">'
|
||||
+ '<div class="avatar" '
|
||||
+ ' data-username="' + escapeHTML(item.id) + '"' // for avatars
|
||||
+ ' data-user="' + escapeHTML(item.id) + '"' // for contactsmenu
|
||||
+ ' data-user-display-name="' + escapeHTML(item.label) + '"></div>'
|
||||
+ ' <strong>' + escapeHTML(item.label) + '</strong>'
|
||||
+ '</span></li>';
|
||||
return '<li>' +
|
||||
'<span class="avatar-name-wrapper">' +
|
||||
'<span class="avatar" ' +
|
||||
'data-username="' + escapeHTML(item.id) + '" ' + // for avatars
|
||||
'data-user="' + escapeHTML(item.id) + '" ' + // for contactsmenu
|
||||
'data-user-display-name="' + escapeHTML(item.label) + '">' +
|
||||
'</span>' +
|
||||
'<strong>' + escapeHTML(item.label) + '</strong>' +
|
||||
'</span></li>';
|
||||
},
|
||||
insertTpl: function (item) {
|
||||
return ''
|
||||
+ '<span class="avatar-name-wrapper">'
|
||||
+ '<div class="avatar" '
|
||||
+ ' data-username="' + escapeHTML(item.id) + '"' // for avatars
|
||||
+ ' data-user="' + escapeHTML(item.id) + '"' // for contactsmenu
|
||||
+ ' data-user-display-name="' + escapeHTML(item.label) + '"></div>'
|
||||
+ ' <strong>' + escapeHTML(item.label) + '</strong>'
|
||||
+ '</span>';
|
||||
return '' +
|
||||
'<span class="avatar-name-wrapper">' +
|
||||
'<span class="avatar" ' +
|
||||
'data-username="' + escapeHTML(item.id) + '" ' + // for avatars
|
||||
'data-user="' + escapeHTML(item.id) + '" ' + // for contactsmenu
|
||||
'data-user-display-name="' + escapeHTML(item.label) + '">' +
|
||||
'</span>' +
|
||||
'<strong>' + escapeHTML(item.label) + '</strong>' +
|
||||
'</span>';
|
||||
},
|
||||
searchKey: "label"
|
||||
});
|
||||
@@ -224,7 +226,7 @@
|
||||
// passing the whole comments form would re-apply and request
|
||||
// avatars from the server
|
||||
$(je.target).find(
|
||||
'div[data-username="' + $el.find('[data-username]').data('username') + '"]'
|
||||
'span[data-username="' + $el.find('[data-username]').data('username') + '"]'
|
||||
).parent(),
|
||||
editionMode
|
||||
);
|
||||
@@ -486,20 +488,22 @@
|
||||
},
|
||||
|
||||
_composeHTMLMention: function(uid, displayName) {
|
||||
var avatar = '<div class="avatar" '
|
||||
+ 'data-username="' + _.escape(uid) + '"'
|
||||
+ ' data-user="' + _.escape(uid) + '"'
|
||||
+ ' data-user-display-name="'
|
||||
+ _.escape(displayName) + '"></div>';
|
||||
var avatar = '' +
|
||||
'<span class="avatar" ' +
|
||||
'data-username="' + _.escape(uid) + '" ' +
|
||||
'data-user="' + _.escape(uid) + '" ' +
|
||||
'data-user-display-name="' + _.escape(displayName) + '">' +
|
||||
'</span>';
|
||||
|
||||
var isCurrentUser = (uid === OC.getCurrentUser().uid);
|
||||
|
||||
return ''
|
||||
+ '<span class="atwho-inserted" contenteditable="false">'
|
||||
+ '<span class="avatar-name-wrapper' + (isCurrentUser ? ' currentUser' : '') + '">'
|
||||
+ avatar + ' <strong>'+ _.escape(displayName)+'</strong>'
|
||||
+ '</span>'
|
||||
+ '</span>';
|
||||
return '' +
|
||||
'<span class="atwho-inserted" contenteditable="false">' +
|
||||
'<span class="avatar-name-wrapper' + (isCurrentUser ? ' currentUser' : '') + '">' +
|
||||
avatar +
|
||||
'<strong>' + _.escape(displayName) + '</strong>' +
|
||||
'</span>' +
|
||||
'</span>';
|
||||
},
|
||||
|
||||
nextPage: function() {
|
||||
|
||||
@@ -309,7 +309,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
||||
|
||||
expect(createStub.calledOnce).toEqual(false);
|
||||
expect($newCommentForm.find('.message').html()).toContain('Mention to <span');
|
||||
expect($newCommentForm.find('.message').html()).toContain('<div class="avatar"');
|
||||
expect($newCommentForm.find('.message').html()).toContain('<span class="avatar"');
|
||||
expect($newCommentForm.find('.message').html()).toContain('<strong>User Name</strong>');
|
||||
expect($newCommentForm.find('.message').text()).not.toContain('@');
|
||||
// In this case the default behaviour is prevented by the
|
||||
|
||||
@@ -28,10 +28,16 @@ class Plugin extends \Sabre\CalDAV\Plugin {
|
||||
const SYSTEM_CALENDAR_ROOT = 'system-calendars';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* Returns the path to a principal's calendar home.
|
||||
*
|
||||
* The return url must not end with a slash.
|
||||
* This function should return null in case a principal did not have
|
||||
* a calendar home.
|
||||
*
|
||||
* @param string $principalUrl
|
||||
* @return string|null
|
||||
*/
|
||||
function getCalendarHomeForPrincipal($principalUrl):string {
|
||||
|
||||
function getCalendarHomeForPrincipal($principalUrl) {
|
||||
if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
|
||||
list(, $principalId) = \Sabre\Uri\split($principalUrl);
|
||||
return self::CALENDAR_ROOT . '/' . $principalId;
|
||||
@@ -44,8 +50,6 @@ class Plugin extends \Sabre\CalDAV\Plugin {
|
||||
list(, $principalId) = \Sabre\Uri\split($principalUrl);
|
||||
return self::SYSTEM_CALENDAR_ROOT . '/calendar-rooms/' . $principalId;
|
||||
}
|
||||
|
||||
throw new \LogicException('This is not supposed to happen');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,10 +39,9 @@ class Plugin extends \Sabre\CardDAV\Plugin {
|
||||
* Returns the addressbook home for a given principal
|
||||
*
|
||||
* @param string $principal
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getAddressbookHomeForPrincipal($principal) {
|
||||
|
||||
if (strrpos($principal, 'principals/users', -strlen($principal)) !== false) {
|
||||
list(, $principalId) = \Sabre\Uri\split($principal);
|
||||
return self::ADDRESSBOOK_ROOT . '/users/' . $principalId;
|
||||
@@ -55,8 +54,6 @@ class Plugin extends \Sabre\CardDAV\Plugin {
|
||||
list(, $principalId) = \Sabre\Uri\split($principal);
|
||||
return self::ADDRESSBOOK_ROOT . '/system/' . $principalId;
|
||||
}
|
||||
|
||||
throw new \LogicException('This is not supposed to happen');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,11 +63,7 @@ class PluginTest extends TestCase {
|
||||
$this->assertSame($expected, $this->plugin->getCalendarHomeForPrincipal($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage This is not supposed to happen
|
||||
*/
|
||||
public function testGetCalendarHomeForUnknownPrincipal() {
|
||||
$this->plugin->getCalendarHomeForPrincipal('FOO/BAR/BLUB');
|
||||
$this->assertNull($this->plugin->getCalendarHomeForPrincipal('FOO/BAR/BLUB'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
height: 36px;
|
||||
display:inline-block;
|
||||
text-align: center;
|
||||
|
||||
.ui-progressbar-value {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
#uploadprogressbar .ui-progressbar-value.ui-widget-header.ui-corner-left {
|
||||
height: 100%;
|
||||
|
||||
@@ -176,7 +176,6 @@ class ViewController extends Controller {
|
||||
$currentCount = 0;
|
||||
foreach ($favElements['folders'] as $dir) {
|
||||
|
||||
$id = substr($dir, strrpos($dir, '/') + 1, strlen($dir));
|
||||
$link = $this->urlGenerator->linkToRoute('files.view.index', ['dir' => $dir, 'view' => 'files']);
|
||||
$sortingValue = ++$currentCount;
|
||||
$element = [
|
||||
@@ -186,7 +185,7 @@ class ViewController extends Controller {
|
||||
'dir' => $dir,
|
||||
'order' => $navBarPositionPosition,
|
||||
'folderPosition' => $sortingValue,
|
||||
'name' => $id,
|
||||
'name' => basename($dir),
|
||||
'icon' => 'files',
|
||||
'quickaccesselement' => 'true'
|
||||
];
|
||||
|
||||
@@ -176,8 +176,53 @@ class ViewControllerTest extends TestCase {
|
||||
'active' => false,
|
||||
'icon' => '',
|
||||
'type' => 'link',
|
||||
'classes' => '',
|
||||
'sublist' => [],
|
||||
'classes' => 'collapsible',
|
||||
'sublist' => [
|
||||
[
|
||||
'id' => '-test1',
|
||||
'view' => 'files',
|
||||
'href' => '',
|
||||
'dir' => '/test1',
|
||||
'order' => 6,
|
||||
'folderPosition' => 1,
|
||||
'name' => 'test1',
|
||||
'icon' => 'files',
|
||||
'quickaccesselement' => 'true',
|
||||
],
|
||||
[
|
||||
'name' => 'test2',
|
||||
'id' => '-test2-',
|
||||
'view' => 'files',
|
||||
'href' => '',
|
||||
'dir' => '/test2/',
|
||||
'order' => 7,
|
||||
'folderPosition' => 2,
|
||||
'icon' => 'files',
|
||||
'quickaccesselement' => 'true',
|
||||
],
|
||||
[
|
||||
'name' => 'sub4',
|
||||
'id' => '-test3-sub4',
|
||||
'view' => 'files',
|
||||
'href' => '',
|
||||
'dir' => '/test3/sub4',
|
||||
'order' => 8,
|
||||
'folderPosition' => 3,
|
||||
'icon' => 'files',
|
||||
'quickaccesselement' => 'true',
|
||||
],
|
||||
[
|
||||
'name' => 'sub6',
|
||||
'id' => '-test5-sub6-',
|
||||
'view' => 'files',
|
||||
'href' => '',
|
||||
'dir' => '/test5/sub6/',
|
||||
'order' => 9,
|
||||
'folderPosition' => 4,
|
||||
'icon' => 'files',
|
||||
'quickaccesselement' => 'true',
|
||||
],
|
||||
],
|
||||
'defaultExpandedState' => false,
|
||||
'expandedState' => 'show_Quick_Access'
|
||||
],
|
||||
@@ -303,6 +348,22 @@ class ViewControllerTest extends TestCase {
|
||||
'id' => 'shareoverview',
|
||||
'content' => null,
|
||||
],
|
||||
'-test1' => [
|
||||
'id' => '-test1',
|
||||
'content' => '',
|
||||
],
|
||||
'-test2-' => [
|
||||
'id' => '-test2-',
|
||||
'content' => '',
|
||||
],
|
||||
'-test3-sub4' => [
|
||||
'id' => '-test3-sub4',
|
||||
'content' => '',
|
||||
],
|
||||
'-test5-sub6-' => [
|
||||
'id' => '-test5-sub6-',
|
||||
'content' => '',
|
||||
],
|
||||
],
|
||||
'hiddenFields' => [],
|
||||
]
|
||||
@@ -315,7 +376,12 @@ class ViewControllerTest extends TestCase {
|
||||
->with($this->user->getUID())
|
||||
->willReturn([
|
||||
'item' => [],
|
||||
'folders' => [],
|
||||
'folders' => [
|
||||
'/test1',
|
||||
'/test2/',
|
||||
'/test3/sub4',
|
||||
'/test5/sub6/',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView'));
|
||||
|
||||
@@ -142,7 +142,7 @@ class Cache extends CacheJail {
|
||||
} else {
|
||||
$entry['path'] = $path;
|
||||
}
|
||||
$sharePermissions = $this->storage->getPermissions($path);
|
||||
$sharePermissions = $this->storage->getPermissions($entry['path']);
|
||||
if (isset($entry['permissions'])) {
|
||||
$entry['permissions'] &= $sharePermissions;
|
||||
} else {
|
||||
|
||||
@@ -195,7 +195,8 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
|
||||
if (!$this->isValid()) {
|
||||
return 0;
|
||||
}
|
||||
$permissions = $this->superShare->getPermissions();
|
||||
$permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
|
||||
|
||||
// part files and the mount point always have delete permissions
|
||||
if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
|
||||
$permissions |= \OCP\Constants::PERMISSION_DELETE;
|
||||
@@ -257,11 +258,17 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
|
||||
case 'xb':
|
||||
case 'a':
|
||||
case 'ab':
|
||||
$creatable = $this->isCreatable($path);
|
||||
$creatable = $this->isCreatable(dirname($path));
|
||||
$updatable = $this->isUpdatable($path);
|
||||
// if neither permissions given, no need to continue
|
||||
if (!$creatable && !$updatable) {
|
||||
return false;
|
||||
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
|
||||
$updatable = $this->isUpdatable(dirname($path));
|
||||
}
|
||||
|
||||
if (!$updatable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$exists = $this->file_exists($path);
|
||||
|
||||
@@ -134,14 +134,14 @@ class PermissionsTest extends TestCase {
|
||||
* Test that the permissions of shared directory are returned correctly
|
||||
*/
|
||||
function testGetPermissions() {
|
||||
$sharedDirPerms = $this->sharedStorage->getPermissions('shareddir');
|
||||
$sharedDirPerms = $this->sharedStorage->getPermissions('');
|
||||
$this->assertEquals(31, $sharedDirPerms);
|
||||
$sharedDirPerms = $this->sharedStorage->getPermissions('shareddir/textfile.txt');
|
||||
$this->assertEquals(31, $sharedDirPerms);
|
||||
$sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted');
|
||||
$this->assertEquals(7, $sharedDirRestrictedPerms);
|
||||
$sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted/textfile.txt');
|
||||
$this->assertEquals(7, $sharedDirRestrictedPerms);
|
||||
$sharedDirPerms = $this->sharedStorage->getPermissions('textfile.txt');
|
||||
$this->assertEquals(27, $sharedDirPerms);
|
||||
$sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('');
|
||||
$this->assertEquals(15, $sharedDirRestrictedPerms);
|
||||
$sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('textfile1.txt');
|
||||
$this->assertEquals(3, $sharedDirRestrictedPerms);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -74,7 +74,7 @@ class SettingsController extends Controller {
|
||||
public function addClient(string $name,
|
||||
string $redirectUri): JSONResponse {
|
||||
|
||||
if (filter_var($redirectUri, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED|FILTER_FLAG_HOST_REQUIRED) === false) {
|
||||
if (filter_var($redirectUri, FILTER_VALIDATE_URL) === false) {
|
||||
return new JSONResponse(['message' => $this->l->t('Your redirect URL needs to be a full URL for example: https://yourdomain.com/path')], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ abstract class AUserData extends OCSController {
|
||||
/**
|
||||
* creates a array with all user data
|
||||
*
|
||||
* @param $userId
|
||||
* @param string $userId
|
||||
* @return array
|
||||
* @throws OCSException
|
||||
*/
|
||||
|
||||
@@ -186,26 +186,25 @@ class GroupsController extends AUserData {
|
||||
* @throws OCSException
|
||||
*/
|
||||
public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse {
|
||||
$user = $this->userSession->getUser();
|
||||
$isSubadminOfGroup = false;
|
||||
$currentUser = $this->userSession->getUser();
|
||||
|
||||
// Check the group exists
|
||||
$group = $this->groupManager->get($groupId);
|
||||
if ($group !== null) {
|
||||
$isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminOfGroup($user, $group);
|
||||
$isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $group);
|
||||
} else {
|
||||
throw new OCSException('The requested group could not be found', \OCP\API::RESPOND_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check subadmin has access to this group
|
||||
if($this->groupManager->isAdmin($user->getUID())
|
||||
|| $isSubadminOfGroup) {
|
||||
$users = $this->groupManager->get($groupId)->searchUsers($search, $limit, $offset);
|
||||
if($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
|
||||
$users = $group->searchUsers($search, $limit, $offset);
|
||||
|
||||
// Extract required number
|
||||
$users = array_keys($users);
|
||||
$usersDetails = [];
|
||||
foreach ($users as $userId) {
|
||||
foreach ($users as $user) {
|
||||
/** @var IUser $user */
|
||||
$userId = (string) $user->getUID();
|
||||
$userData = $this->getUserData($userId);
|
||||
// Do not insert empty entry
|
||||
if(!empty($userData)) {
|
||||
|
||||
@@ -46,6 +46,7 @@ use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\L10N\IFactory;
|
||||
@@ -154,29 +155,31 @@ class UsersController extends AUserData {
|
||||
* returns a list of users and their data
|
||||
*/
|
||||
public function getUsersDetails(string $search = '', $limit = null, $offset = 0): DataResponse {
|
||||
$user = $this->userSession->getUser();
|
||||
$currentUser = $this->userSession->getUser();
|
||||
$users = [];
|
||||
|
||||
// Admin? Or SubAdmin?
|
||||
$uid = $user->getUID();
|
||||
$uid = $currentUser->getUID();
|
||||
$subAdminManager = $this->groupManager->getSubAdmin();
|
||||
if ($this->groupManager->isAdmin($uid)){
|
||||
$users = $this->userManager->search($search, $limit, $offset);
|
||||
} else if ($subAdminManager->isSubAdmin($user)) {
|
||||
$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
|
||||
$users = array_keys($users);
|
||||
} else if ($subAdminManager->isSubAdmin($currentUser)) {
|
||||
$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
|
||||
foreach ($subAdminOfGroups as $key => $group) {
|
||||
$subAdminOfGroups[$key] = $group->getGID();
|
||||
}
|
||||
|
||||
$users = [];
|
||||
foreach ($subAdminOfGroups as $group) {
|
||||
$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
|
||||
$users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
|
||||
}
|
||||
$users = array_merge(...$users);
|
||||
}
|
||||
|
||||
$users = array_keys($users);
|
||||
$usersDetails = [];
|
||||
foreach ($users as $key => $userId) {
|
||||
foreach ($users as $userId) {
|
||||
$userId = (string) $userId;
|
||||
$userData = $this->getUserData($userId);
|
||||
// Do not insert empty entry
|
||||
if (!empty($userData)) {
|
||||
|
||||
@@ -174,9 +174,7 @@ class ThemingDefaults extends \OC_Defaults {
|
||||
$legalLinks = ''; $divider = '';
|
||||
foreach($links as $link) {
|
||||
if($link['url'] !== ''
|
||||
&& filter_var($link['url'], FILTER_VALIDATE_URL, [
|
||||
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
|
||||
])
|
||||
&& filter_var($link['url'], FILTER_VALIDATE_URL)
|
||||
) {
|
||||
$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
|
||||
' rel="noreferrer noopener">' . $link['text'] . '</a>';
|
||||
@@ -339,7 +337,7 @@ class ThemingDefaults extends \OC_Defaults {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increases the cache buster key
|
||||
*/
|
||||
|
||||
@@ -108,7 +108,7 @@ class Notifier implements INotifier {
|
||||
$notification->setParsedSubject($l->t('Update to %1$s is available.', [$parameters['version']]));
|
||||
|
||||
if ($this->isAdmin()) {
|
||||
$notification->setLink($this->url->linkToRouteAbsolute('settings.AdminSettings.index') . '#updater');
|
||||
$notification->setLink($this->url->linkToRouteAbsolute('settings.AdminSettings.index', ['section' => 'overview']) . '#version');
|
||||
}
|
||||
} else {
|
||||
$appInfo = $this->getAppInfo($notification->getObjectType());
|
||||
|
||||
@@ -366,10 +366,10 @@ class ClientFlowLoginController extends Controller {
|
||||
|
||||
$serverPath = $protocol . "://" . $this->request->getServerHost() . $serverPostfix;
|
||||
$redirectUri = 'nc://login/server:' . $serverPath . '&user:' . urlencode($loginName) . '&password:' . urlencode($token);
|
||||
}
|
||||
|
||||
// Clear the token from the login here
|
||||
$this->tokenProvider->invalidateToken($sessionId);
|
||||
// Clear the token from the login here
|
||||
$this->tokenProvider->invalidateToken($sessionId);
|
||||
}
|
||||
|
||||
return new Http\RedirectResponse($redirectUri);
|
||||
}
|
||||
|
||||
@@ -1043,6 +1043,27 @@ $popovericon-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* "app-*" descendants use border-box sizing, so the height of the icon must be
|
||||
* set to the height of the item (as well as its width to make it squared). */
|
||||
#content[class*='app-'] {
|
||||
.bubble,
|
||||
.app-navigation-entry-menu,
|
||||
.popovermenu {
|
||||
li {
|
||||
> button,
|
||||
> a,
|
||||
> .menuitem {
|
||||
/* DEPRECATED! old img in popover fallback
|
||||
* TODO: to remove */
|
||||
> img {
|
||||
width: $popoveritem-height;
|
||||
height: $popoveritem-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CONTENT LIST ------------------------------------------------------------ */
|
||||
.app-content-list {
|
||||
width: 300px;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// SCSS darken/lighten function override
|
||||
@function nc-darken($color, $value) {
|
||||
@return darken($color, $value);
|
||||
@@ -60,8 +60,8 @@ $color-text-maxcontrast: nc-lighten($color-main-text, 46.2%) !default;
|
||||
$color-text-light: nc-lighten($color-main-text, 15%) !default;
|
||||
$color-text-lighter: nc-lighten($color-main-text, 30%) !default;
|
||||
|
||||
$image-logo: url('../img/logo.svg?v=1');
|
||||
$image-login-background: url('../img/background.png?v=2');
|
||||
$image-logo: url('../img/logo.svg?v=1') !default;
|
||||
$image-login-background: url('../img/background.png?v=2') !default;
|
||||
|
||||
$color-loading-light: #ccc !default;
|
||||
$color-loading-dark: #777 !default;
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
* @return {Array.<FileInfo>} array of file info
|
||||
*/
|
||||
_parseFileInfo: function(response) {
|
||||
var path = response.href;
|
||||
var path = decodeURIComponent(response.href);
|
||||
if (path.substr(0, this._root.length) === this._root) {
|
||||
path = path.substr(this._root.length);
|
||||
}
|
||||
|
||||
@@ -100,16 +100,28 @@
|
||||
{escape: false}
|
||||
);
|
||||
} else if (this.model.getReshareType() === OC.Share.SHARE_TYPE_ROOM) {
|
||||
sharedByText = t(
|
||||
'core',
|
||||
'Shared with you and the conversation {conversation} by {owner}',
|
||||
{
|
||||
conversation: this.model.getReshareWithDisplayName(),
|
||||
owner: ownerDisplayName
|
||||
},
|
||||
undefined,
|
||||
{escape: false}
|
||||
);
|
||||
if (this.model.get('reshare').share_with_displayname) {
|
||||
sharedByText = t(
|
||||
'core',
|
||||
'Shared with you and the conversation {conversation} by {owner}',
|
||||
{
|
||||
conversation: this.model.getReshareWithDisplayName(),
|
||||
owner: ownerDisplayName
|
||||
},
|
||||
undefined,
|
||||
{escape: false}
|
||||
);
|
||||
} else {
|
||||
sharedByText = t(
|
||||
'core',
|
||||
'Shared with you in a conversation by {owner}',
|
||||
{
|
||||
owner: ownerDisplayName
|
||||
},
|
||||
undefined,
|
||||
{escape: false}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
sharedByText = t(
|
||||
'core',
|
||||
|
||||
@@ -326,7 +326,23 @@
|
||||
|
||||
var suggestions = exactMatches.concat(users).concat(groups).concat(remotes).concat(remoteGroups).concat(emails).concat(circles).concat(rooms).concat(lookup);
|
||||
|
||||
deferred.resolve(suggestions, exactMatches);
|
||||
var moreResultsAvailable =
|
||||
(
|
||||
oc_config['sharing.maxAutocompleteResults'] > 0
|
||||
&& Math.min(perPage, oc_config['sharing.maxAutocompleteResults'])
|
||||
<= Math.max(
|
||||
users.length + exactUsers.length,
|
||||
groups.length + exactGroups.length,
|
||||
remoteGroups.length + exactRemoteGroups.length,
|
||||
remotes.length + exactRemotes.length,
|
||||
emails.length + exactEmails.length,
|
||||
circles.length + exactCircles.length,
|
||||
rooms.length + exactRooms.length,
|
||||
lookup.length
|
||||
)
|
||||
);
|
||||
|
||||
deferred.resolve(suggestions, exactMatches, moreResultsAvailable);
|
||||
} else {
|
||||
deferred.reject(result.ocs.meta.message);
|
||||
}
|
||||
@@ -380,12 +396,12 @@
|
||||
$shareWithField.removeClass('error')
|
||||
.tooltip('hide');
|
||||
|
||||
var perPage = 200;
|
||||
var perPage = parseInt(oc_config['sharing.maxAutocompleteResults'], 10) || 200;
|
||||
this._getSuggestions(
|
||||
search.term.trim(),
|
||||
perPage,
|
||||
view.model
|
||||
).done(function(suggestions) {
|
||||
).done(function(suggestions, exactMatches, moreResultsAvailable) {
|
||||
view._pendingOperationsCount--;
|
||||
if (view._pendingOperationsCount === 0) {
|
||||
$loading.addClass('hidden');
|
||||
@@ -401,10 +417,7 @@
|
||||
|
||||
// show a notice that the list is truncated
|
||||
// this is the case if one of the search results is at least as long as the max result config option
|
||||
if(oc_config['sharing.maxAutocompleteResults'] > 0 &&
|
||||
Math.min(perPage, oc_config['sharing.maxAutocompleteResults'])
|
||||
<= Math.max(users.length, groups.length, remotes.length, emails.length, lookup.length)) {
|
||||
|
||||
if(moreResultsAvailable) {
|
||||
var message = t('core', 'This list is maybe truncated - please refine your search term to see more results.');
|
||||
$('.ui-autocomplete').append('<li class="autocomplete-note">' + message + '</li>');
|
||||
}
|
||||
@@ -557,7 +570,7 @@
|
||||
$shareWithField.focus();
|
||||
};
|
||||
|
||||
var perPage = 200;
|
||||
var perPage = parseInt(oc_config['sharing.maxAutocompleteResults'], 10) || 200;
|
||||
var onlyExactMatches = true;
|
||||
this._getSuggestions(
|
||||
$shareWithField.val(),
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
/* global oc_appconfig, sinon */
|
||||
describe('OC.Share.ShareDialogView', function() {
|
||||
var $container;
|
||||
var oldConfig;
|
||||
var oldAppConfig;
|
||||
var autocompleteStub;
|
||||
var avatarStub;
|
||||
@@ -40,6 +41,9 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
// horrible parameters
|
||||
$('#testArea').append('<input id="allowShareWithLink" type="hidden" value="yes">');
|
||||
$container = $('#shareContainer');
|
||||
oldConfig = window.oc_config;
|
||||
window.oc_config = window.oc_config || {};
|
||||
window.oc_config['sharing.maxAutocompleteResults'] = 0;
|
||||
/* jshint camelcase:false */
|
||||
oldAppConfig = _.extend({}, oc_appconfig.core);
|
||||
oc_appconfig.core.enforcePasswordForPublicLink = false;
|
||||
@@ -108,6 +112,7 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
});
|
||||
afterEach(function() {
|
||||
OC.currentUser = oldCurrentUser;
|
||||
window.oc_config = oldConfig;
|
||||
/* jshint camelcase:false */
|
||||
oc_appconfig.core = oldAppConfig;
|
||||
|
||||
@@ -357,9 +362,10 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([], [])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([], [], false)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
});
|
||||
|
||||
it('single partial match', function() {
|
||||
var doneStub = sinon.stub();
|
||||
var failStub = sinon.stub();
|
||||
@@ -407,11 +413,14 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([{
|
||||
'label': 'bobby',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'imbob'}
|
||||
}], [
|
||||
])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bobby',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'imbob'}
|
||||
}],
|
||||
[],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
});
|
||||
it('single exact match', function() {
|
||||
@@ -461,13 +470,17 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
});
|
||||
it('mixed matches', function() {
|
||||
@@ -548,28 +561,140 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}, {
|
||||
'label': 'bobby',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'imbob'}
|
||||
}, {
|
||||
'label': 'bob the second',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user2'}
|
||||
}, {
|
||||
'label': 'bobfans',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'fans'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}, {
|
||||
'label': 'bobby',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'imbob'}
|
||||
}, {
|
||||
'label': 'bob the second',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user2'}
|
||||
}, {
|
||||
'label': 'bobfans',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'fans'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
});
|
||||
|
||||
it('capped mixed matches', function() {
|
||||
window.oc_config['sharing.maxAutocompleteResults'] = 3;
|
||||
var doneStub = sinon.stub();
|
||||
var failStub = sinon.stub();
|
||||
|
||||
dialog._getSuggestions('bob', 42, shareModel).done(doneStub).fail(failStub);
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_GROUP,
|
||||
'shareWith': 'group1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'remotes': [],
|
||||
'remote_groups': [],
|
||||
},
|
||||
'users': [
|
||||
{
|
||||
'label': 'bobby',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'imbob'
|
||||
}
|
||||
},
|
||||
{
|
||||
'label': 'bob the second',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user2'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [
|
||||
{
|
||||
'label': 'bobfans',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_GROUP,
|
||||
'shareWith': 'fans'
|
||||
}
|
||||
}
|
||||
],
|
||||
'remotes': [],
|
||||
'remote_groups': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(doneStub.called).toEqual(false);
|
||||
expect(failStub.called).toEqual(false);
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}, {
|
||||
'label': 'bobby',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'imbob'}
|
||||
}, {
|
||||
'label': 'bob the second',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user2'}
|
||||
}, {
|
||||
'label': 'bobfans',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'fans'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}, {
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_GROUP, 'shareWith': 'group1'}
|
||||
}],
|
||||
true
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
});
|
||||
|
||||
@@ -620,13 +745,16 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
|
||||
var done2Stub = sinon.stub();
|
||||
@@ -638,13 +766,17 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
expect(failStub.called).toEqual(false);
|
||||
|
||||
expect(done2Stub.calledOnce).toEqual(true);
|
||||
expect(done2Stub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}])).toEqual(true);
|
||||
expect(done2Stub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(fail2Stub.called).toEqual(false);
|
||||
});
|
||||
|
||||
@@ -695,13 +827,17 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
);
|
||||
|
||||
expect(doneStub.calledOnce).toEqual(true);
|
||||
expect(doneStub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}])).toEqual(true);
|
||||
expect(doneStub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(failStub.called).toEqual(false);
|
||||
|
||||
var done2Stub = sinon.stub();
|
||||
@@ -741,13 +877,17 @@ describe('OC.Share.ShareDialogView', function() {
|
||||
expect(fail2Stub.called).toEqual(false);
|
||||
|
||||
expect(done3Stub.calledOnce).toEqual(true);
|
||||
expect(done3Stub.calledWithExactly([{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}], [{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}])).toEqual(true);
|
||||
expect(done3Stub.calledWithExactly(
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
[{
|
||||
'label': 'bob',
|
||||
'value': {'shareType': OC.Share.SHARE_TYPE_USER, 'shareWith': 'user1'}
|
||||
}],
|
||||
false
|
||||
)).toEqual(true);
|
||||
expect(fail3Stub.called).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-3
@@ -441,7 +441,7 @@ class OC {
|
||||
// session timeout
|
||||
if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
|
||||
if (isset($_COOKIE[session_name()])) {
|
||||
setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
|
||||
setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
|
||||
}
|
||||
\OC::$server->getUserSession()->logout();
|
||||
}
|
||||
@@ -895,8 +895,6 @@ class OC {
|
||||
self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
|
||||
} catch (\Exception $ex) {
|
||||
}
|
||||
|
||||
self::$composerAutoloader->setApcuPrefix($instanceId . '-mainComposer');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ class DefaultTokenProvider implements IProvider {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
|
||||
if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
|
||||
if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
|
||||
throw new ExpiredTokenException($token);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class PublicKeyTokenProvider implements IProvider {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
|
||||
if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
|
||||
if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
|
||||
throw new ExpiredTokenException($token);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class PublicKeyTokenProvider implements IProvider {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
|
||||
if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
|
||||
if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
|
||||
throw new ExpiredTokenException($token);
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +244,25 @@ class Factory implements IFactory {
|
||||
return 'en_US';
|
||||
}
|
||||
|
||||
/**
|
||||
* find the matching lang from the locale
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $locale
|
||||
* @return null|string
|
||||
*/
|
||||
public function findLanguageFromLocale(string $app = 'core', string $locale = null) {
|
||||
if ($this->languageExists($app, $locale)) {
|
||||
return $locale;
|
||||
}
|
||||
|
||||
// Try to split e.g: fr_FR => fr
|
||||
$locale = explode('_', $locale)[0];
|
||||
if ($this->languageExists($app, $locale)) {
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all available languages for an app
|
||||
*
|
||||
|
||||
@@ -54,7 +54,7 @@ class Internal extends Session {
|
||||
try {
|
||||
$this->invoke('session_start');
|
||||
} catch (\Exception $e) {
|
||||
setcookie($this->invoke('session_name'), null, -1, \OC::$WEBROOT ?: '/');
|
||||
setcookie($this->invoke('session_name'), '', -1, \OC::$WEBROOT ?: '/');
|
||||
}
|
||||
restore_error_handler();
|
||||
if (!isset($_SESSION)) {
|
||||
|
||||
@@ -47,7 +47,7 @@ class IconsCacher {
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var string */
|
||||
private $iconVarRE = '/--(icon-[a-zA-Z0-9-]+): url\(["\']([a-zA-Z0-9-_\~\/\.\?\=]+)[^;]+;/m';
|
||||
private $iconVarRE = '/--(icon-[a-zA-Z0-9-]+):\s?url\(["\']([a-zA-Z0-9-_\~\/\.\?\=]+)[^;]+;/m';
|
||||
|
||||
/** @var string */
|
||||
private $fileName = 'icons-vars.css';
|
||||
|
||||
@@ -139,9 +139,12 @@ class TemplateLayout extends \OC_Template {
|
||||
}
|
||||
// Send the language and the locale to our layouts
|
||||
$lang = \OC::$server->getL10NFactory()->findLanguage();
|
||||
$locale = \OC::$server->getL10NFactory()->findLocale($lang);
|
||||
$localeLang = \OC::$server->getL10NFactory()->findLanguageFromLocale('lib', $locale);
|
||||
|
||||
$lang = str_replace('_', '-', $lang);
|
||||
$this->assign('language', $lang);
|
||||
$this->assign('locale', \OC::$server->getL10NFactory()->findLocale($lang));
|
||||
$this->assign('locale', $locale);
|
||||
|
||||
if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
|
||||
if (empty(self::$versionHash)) {
|
||||
@@ -159,7 +162,7 @@ class TemplateLayout extends \OC_Template {
|
||||
if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
|
||||
if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
|
||||
$jsConfigHelper = new JSConfigHelper(
|
||||
\OC::$server->getL10N('lib'),
|
||||
\OC::$server->getL10N('lib', $localeLang ?: $lang),
|
||||
\OC::$server->query(Defaults::class),
|
||||
\OC::$server->getAppManager(),
|
||||
\OC::$server->getSession(),
|
||||
|
||||
@@ -67,7 +67,7 @@ interface ICloudFederationProviderManager {
|
||||
*
|
||||
* @param string $resourceType
|
||||
* @return ICloudFederationProvider
|
||||
* @throws Exceptions\ProviderDoesNotExistsException;
|
||||
* @throws Exceptions\ProviderDoesNotExistsException
|
||||
*
|
||||
* @since 14.0.0
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,16 @@ interface IFactory {
|
||||
*/
|
||||
public function findLocale($lang = null);
|
||||
|
||||
/**
|
||||
* find the matching lang from the locale
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $locale
|
||||
* @return null|string
|
||||
* @since 14.0.1
|
||||
*/
|
||||
public function findLanguageFromLocale(string $app = 'core', string $locale = null);
|
||||
|
||||
/**
|
||||
* Find all available languages for an app
|
||||
*
|
||||
|
||||
@@ -543,7 +543,7 @@ Raw output
|
||||
* @return array
|
||||
*/
|
||||
protected function getAppDirsWithDifferentOwner(): array {
|
||||
$currentUser = posix_getpwuid(posix_getuid());
|
||||
$currentUser = posix_getuid();
|
||||
$appDirsWithDifferentOwner = [[]];
|
||||
|
||||
foreach (OC::$APPSROOTS as $appRoot) {
|
||||
@@ -561,11 +561,11 @@ Raw output
|
||||
/**
|
||||
* Tests if the directories for one apps directory are writable by the current user.
|
||||
*
|
||||
* @param array $currentUser The current user
|
||||
* @param int $currentUser The current user
|
||||
* @param array $appRoot The app root config
|
||||
* @return string[] The none writable directory paths inside the app root
|
||||
*/
|
||||
private function getAppDirsWithDifferentOwnerForAppRoot(array $currentUser, array $appRoot): array {
|
||||
private function getAppDirsWithDifferentOwnerForAppRoot(int $currentUser, array $appRoot): array {
|
||||
$appDirsWithDifferentOwner = [];
|
||||
$appsPath = $appRoot['path'];
|
||||
$appsDir = new DirectoryIterator($appRoot['path']);
|
||||
@@ -573,7 +573,7 @@ Raw output
|
||||
foreach ($appsDir as $fileInfo) {
|
||||
if ($fileInfo->isDir() && !$fileInfo->isDot()) {
|
||||
$absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
|
||||
$appDirUser = posix_getpwuid(fileowner($absAppPath));
|
||||
$appDirUser = fileowner($absAppPath);
|
||||
if ($appDirUser !== $currentUser) {
|
||||
$appDirsWithDifferentOwner[] = $absAppPath;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div id="version" class="section">
|
||||
<!-- should be the last part, so Updater can follow if enabled (it has no heading therefore). -->
|
||||
<h2><?php p($l->t('Version'));?></h2>
|
||||
<p><strong><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" rel="noreferrer noopener" target="_blank"><?php p($theme->getTitle()); ?></a> <?php p(OC_Util::getHumanVersion()) ?></strong></p>
|
||||
|
||||
@@ -206,6 +206,8 @@ su --shell /bin/bash --login www-data --command "cd $NEXTCLOUD_DIR && $ACCEPTANC
|
||||
|
||||
echo "Saving the default state so acceptance tests can reset to it"
|
||||
find . -name ".gitignore" -exec rm --force {} \;
|
||||
# Create dummy files in empty directories to force Git to save the directories.
|
||||
find . -not -path "*.git*" -type d -empty -exec touch {}/.keep \;
|
||||
git add --all && echo 'Default state' | git -c user.name='John Doe' -c user.email='john@doe.org' commit --quiet --file=-
|
||||
|
||||
cd tests/acceptance
|
||||
|
||||
@@ -171,4 +171,31 @@ class L10nTest extends TestCase {
|
||||
$l = \OC::$server->getL10N('lib', 'de');
|
||||
$this->assertEquals('Mo.', $l->l('weekdayName', new \DateTime('2017-11-6'), ['width' => 'abbreviated']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider findLanguageFromLocaleData
|
||||
* @param $locale
|
||||
* @param $language
|
||||
*/
|
||||
public function testFindLanguageFromLocale($locale, $language) {
|
||||
$this->assertEquals(
|
||||
$language,
|
||||
\OC::$server->getL10NFactory()->findLanguageFromLocale('lib', $locale)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function findLanguageFromLocaleData(): array {
|
||||
return [
|
||||
'en_US' => ['en_US', 'en'],
|
||||
'en_UK' => ['en_UK', 'en'],
|
||||
'de_DE' => ['de_DE', 'de_DE'],
|
||||
'de_AT' => ['de_AT', 'de'],
|
||||
'es_EC' => ['es_EC', 'es_EC'],
|
||||
'fi_FI' => ['fi_FI', 'fi'],
|
||||
'zh_CN' => ['zh_CN', 'zh_CN'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -29,10 +29,10 @@
|
||||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
||||
// when updating major/minor version number.
|
||||
|
||||
$OC_Version = array(14, 0, 0, 18);
|
||||
$OC_Version = array(14, 0, 1, 1);
|
||||
|
||||
// The human readable string
|
||||
$OC_VersionString = '14.0.0 RC 2';
|
||||
$OC_VersionString = '14.0.1';
|
||||
|
||||
$OC_VersionCanBeUpgradedFrom = [
|
||||
'nextcloud' => [
|
||||
|
||||
Reference in New Issue
Block a user