aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/templates/appnavigation.php4
-rw-r--r--apps/files_external/lib/sftp.php38
-rw-r--r--apps/files_external/tests/backends/sftp.php38
-rw-r--r--apps/files_sharing/api/ocssharewrapper.php14
-rw-r--r--apps/files_sharing/api/share20ocs.php100
-rw-r--r--apps/files_sharing/tests/api/share20ocstest.php259
-rw-r--r--apps/provisioning_api/appinfo/routes.php5
-rw-r--r--apps/provisioning_api/lib/groups.php35
-rw-r--r--apps/provisioning_api/lib/users.php45
-rw-r--r--apps/provisioning_api/tests/groupstest.php376
-rw-r--r--apps/provisioning_api/tests/userstest.php381
-rw-r--r--core/css/apps.css9
-rw-r--r--core/css/inputs.css232
-rw-r--r--core/css/styles.css246
-rw-r--r--core/js/js.js6
-rw-r--r--core/l10n/ru.js2
-rw-r--r--core/l10n/ru.json2
-rw-r--r--core/shipped.json3
-rw-r--r--lib/private/share20/defaultshareprovider.php9
-rw-r--r--lib/private/share20/ishare.php21
-rw-r--r--lib/private/share20/share.php57
-rw-r--r--lib/private/template.php1
-rw-r--r--tests/lib/share20/defaultshareprovidertest.php2
23 files changed, 1429 insertions, 456 deletions
diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php
index 512300e3a58..d05a02ee7db 100644
--- a/apps/files/templates/appnavigation.php
+++ b/apps/files/templates/appnavigation.php
@@ -16,9 +16,7 @@
</button>
</div>
<div id="app-settings-content">
- <h2>
- <label for="webdavurl"><?php p($l->t('WebDAV'));?></label>
- </h2>
+ <label for="webdavurl"><?php p($l->t('WebDAV'));?></label>
<input id="webdavurl" type="text" readonly="readonly" value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>" />
<em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em>
</div>
diff --git a/apps/files_external/lib/sftp.php b/apps/files_external/lib/sftp.php
index 5dcc7686ca3..f8651727fd2 100644
--- a/apps/files_external/lib/sftp.php
+++ b/apps/files_external/lib/sftp.php
@@ -52,27 +52,37 @@ class SFTP extends \OC\Files\Storage\Common {
protected $client;
/**
+ * @param string $host protocol://server:port
+ * @return array [$server, $port]
+ */
+ private function splitHost($host) {
+ $input = $host;
+ if (strpos($host, '://') === false) {
+ // add a protocol to fix parse_url behavior with ipv6
+ $host = 'http://' . $host;
+ }
+
+ $parsed = parse_url($host);
+ if(is_array($parsed) && isset($parsed['port'])) {
+ return [$parsed['host'], $parsed['port']];
+ } else if (is_array($parsed)) {
+ return [$parsed['host'], 22];
+ } else {
+ return [$input, 22];
+ }
+ }
+
+ /**
* {@inheritdoc}
*/
public function __construct($params) {
// Register sftp://
Stream::register();
- $this->host = $params['host'];
+ $parsedHost = $this->splitHost($params['host']);
- //deals with sftp://server example
- $proto = strpos($this->host, '://');
- if ($proto != false) {
- $this->host = substr($this->host, $proto+3);
- }
-
- //deals with server:port
- $hasPort = strpos($this->host,':');
- if($hasPort != false) {
- $pieces = explode(":", $this->host);
- $this->host = $pieces[0];
- $this->port = $pieces[1];
- }
+ $this->host = $parsedHost[0];
+ $this->port = $parsedHost[1];
$this->user = $params['user'];
diff --git a/apps/files_external/tests/backends/sftp.php b/apps/files_external/tests/backends/sftp.php
index da2c0ac6ba2..aaed2b3460a 100644
--- a/apps/files_external/tests/backends/sftp.php
+++ b/apps/files_external/tests/backends/sftp.php
@@ -26,6 +26,11 @@
namespace Test\Files\Storage;
class SFTP extends Storage {
+ /**
+ * @var \OC\Files\Storage\SFTP instance
+ */
+ protected $instance;
+
private $config;
protected function setUp() {
@@ -103,6 +108,39 @@ class SFTP extends Storage {
],
'sftp::someuser@somehost:8822//remotedir/subdir/',
],
+ [
+ // ipv6 with port
+ [
+ 'run' => true,
+ 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329//remotedir/subdir/',
+ ],
+ [
+ // ipv6 without port
+ [
+ 'run' => true,
+ 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822//remotedir/subdir/',
+ ],
+ [
+ // collapsed ipv6 with port
+ [
+ 'run' => true,
+ 'host' => 'FE80::0202:B3FF:FE1E:8329:8822',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80::0202:B3FF:FE1E:8329:8822//remotedir/subdir/',
+ ],
];
}
}
diff --git a/apps/files_sharing/api/ocssharewrapper.php b/apps/files_sharing/api/ocssharewrapper.php
index 8c0d8f7d150..3ce2901dfb4 100644
--- a/apps/files_sharing/api/ocssharewrapper.php
+++ b/apps/files_sharing/api/ocssharewrapper.php
@@ -35,15 +35,16 @@ class OCSShareWrapper {
\OC::$server->getUserFolder(),
new \OC\Share20\DefaultShareProvider(
\OC::$server->getDatabaseConnection(),
- \OC::$server->getUserManager(),
- \OC::$server->getGroupManager(),
- \OC::$server->getUserFolder()
+ \OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getUserFolder()
)
),
\OC::$server->getGroupManager(),
\OC::$server->getUserManager(),
\OC::$server->getRequest(),
- \OC::$server->getUserFolder());
+ \OC::$server->getUserFolder(),
+ \OC::$server->getURLGenerator());
}
public function getAllShares($params) {
@@ -55,7 +56,8 @@ class OCSShareWrapper {
}
public function getShare($params) {
- return \OCA\Files_Sharing\API\Local::getShare($params);
+ $id = $params['id'];
+ return $this->getShare20OCS()->getShare($id);
}
public function updateShare($params) {
@@ -63,7 +65,7 @@ class OCSShareWrapper {
}
public function deleteShare($params) {
- $id = (int)$params['id'];
+ $id = $params['id'];
return $this->getShare20OCS()->deleteShare($id);
}
}
diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php
index 8a7f90c0023..aaf5a3c72b6 100644
--- a/apps/files_sharing/api/share20ocs.php
+++ b/apps/files_sharing/api/share20ocs.php
@@ -20,39 +20,125 @@
*/
namespace OCA\Files_Sharing\API;
+use OC\Share20\IShare;
+
class Share20OCS {
- /** @var OC\Share20\Manager */
+ /** @var \OC\Share20\Manager */
private $shareManager;
- /** @var OCP\IGroupManager */
+ /** @var \OCP\IGroupManager */
private $groupManager;
- /** @var OCP\IUserManager */
+ /** @var \OCP\IUserManager */
private $userManager;
- /** @var OCP\IRequest */
+ /** @var \OCP\IRequest */
private $request;
- /** @var OCP\Files\Folder */
+ /** @var \OCP\Files\Folder */
private $userFolder;
public function __construct(\OC\Share20\Manager $shareManager,
\OCP\IGroupManager $groupManager,
\OCP\IUserManager $userManager,
\OCP\IRequest $request,
- \OCP\Files\Folder $userFolder) {
+ \OCP\Files\Folder $userFolder,
+ \OCP\IURLGenerator $urlGenerator) {
$this->shareManager = $shareManager;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->request = $request;
$this->userFolder = $userFolder;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * Convert an IShare to an array for OCS output
+ *
+ * @param IShare $share
+ * @return array
+ */
+ protected function formatShare($share) {
+ $result = [
+ 'id' => $share->getId(),
+ 'share_type' => $share->getShareType(),
+ 'uid_owner' => $share->getSharedBy()->getUID(),
+ 'displayname_owner' => $share->getSharedBy()->getDisplayName(),
+ 'permissions' => $share->getPermissions(),
+ 'stime' => $share->getShareTime(),
+ 'parent' => $share->getParent(),
+ 'expiration' => null,
+ 'token' => null,
+ ];
+
+ $path = $share->getPath();
+ $result['path'] = $this->userFolder->getRelativePath($path->getPath());
+ if ($path instanceOf \OCP\Files\Folder) {
+ $result['item_type'] = 'folder';
+ } else {
+ $result['item_type'] = 'file';
+ }
+ $result['storage_id'] = $path->getStorage()->getId();
+ $result['storage'] = \OC\Files\Cache\Storage::getNumericStorageId($path->getStorage()->getId());
+ $result['item_source'] = $path->getId();
+ $result['file_source'] = $path->getId();
+ $result['file_parent'] = $path->getParent()->getId();
+ $result['file_target'] = $share->getTarget();
+
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
+ $sharedWith = $share->getSharedWith();
+ $result['share_with'] = $sharedWith->getUID();
+ $result['share_with_displayname'] = $sharedWith->getDisplayName();
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $sharedWith = $share->getSharedWith();
+ $result['share_with'] = $sharedWith->getGID();
+ $result['share_with_displayname'] = $sharedWith->getGID();
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
+
+ $result['share_with'] = $share->getPassword();
+ $result['share_with_displayname'] = $share->getPassword();
+
+ $result['token'] = $share->getToken();
+ $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
+
+ $expiration = $share->getExpirationDate();
+ if ($expiration !== null) {
+ $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
+ }
+
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
+ $result['share_with'] = $share->getSharedWith();
+ $result['share_with_displayname'] = $share->getSharedWith();
+ $result['token'] = $share->getToken();
+ }
+
+ $result['mail_send'] = $share->getMailSend() ? 1 : 0;
+
+ return $result;
+ }
+
+ /**
+ * Get a specific share by id
+ *
+ * @param string $id
+ * @return \OC_OCS_Result
+ */
+ public function getShare($id) {
+ try {
+ $share = $this->shareManager->getShareById($id);
+ } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
+ }
+
+ $share = $this->formatShare($share);
+ return new \OC_OCS_Result($share);
}
/**
* Delete a share
*
- * @param int $id
+ * @param string $id
* @return \OC_OCS_Result
*/
public function deleteShare($id) {
diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php
index 9c4377a2a7f..f74585eb47d 100644
--- a/apps/files_sharing/tests/api/share20ocstest.php
+++ b/apps/files_sharing/tests/api/share20ocstest.php
@@ -39,6 +39,9 @@ class Share20OCSTest extends \Test\TestCase {
/** @var OCP\Files\Folder */
private $userFolder;
+ /** @var OCP\IURLGenerator */
+ private $urlGenerator;
+
/** @var OCS */
private $ocs;
@@ -46,24 +49,18 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager = $this->getMockBuilder('OC\Share20\Manager')
->disableOriginalConstructor()
->getMock();
- $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder('OCP\IUserManager')
- ->disableOriginalConstructor()
- ->getMock();
- $this->request = $this->getMockBuilder('OCP\IRequest')
- ->disableOriginalConstructor()
- ->getMock();
- $this->userFolder = $this->getMockBuilder('OCP\Files\Folder')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->groupManager = $this->getMock('OCP\IGroupManager');
+ $this->userManager = $this->getMock('OCP\IUserManager');
+ $this->request = $this->getMock('OCP\IRequest');
+ $this->userFolder = $this->getMock('OCP\Files\Folder');
+ $this->urlGenerator = $this->getMock('OCP\IURLGenerator');
$this->ocs = new Share20OCS($this->shareManager,
$this->groupManager,
$this->userManager,
$this->request,
- $this->userFolder);
+ $this->userFolder,
+ $this->urlGenerator);
}
public function testDeleteShareShareNotFound() {
@@ -110,4 +107,240 @@ class Share20OCSTest extends \Test\TestCase {
$expected = new \OC_OCS_Result();
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
+
+ public function testGetGetShareNotExists() {
+ $this->shareManager
+ ->expects($this->once())
+ ->method('getShareById')
+ ->with(42)
+ ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
+
+ $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
+ $this->assertEquals($expected, $this->ocs->getShare(42));
+ }
+
+ public function createShare($id, $shareType, $sharedWith, $sharedBy, $path, $permissions,
+ $shareTime, $expiration, $parent, $target, $mail_send, $token=null,
+ $password=null) {
+ $share = $this->getMock('OC\Share20\IShare');
+ $share->method('getId')->willReturn($id);
+ $share->method('getShareType')->willReturn($shareType);
+ $share->method('getSharedWith')->willReturn($sharedWith);
+ $share->method('getSharedBy')->willReturn($sharedBy);
+ $share->method('getPath')->willReturn($path);
+ $share->method('getPermissions')->willReturn($permissions);
+ $share->method('getShareTime')->willReturn($shareTime);
+ $share->method('getExpirationDate')->willReturn($expiration);
+ $share->method('getParent')->willReturn($parent);
+ $share->method('getTarget')->willReturn($target);
+ $share->method('getMailSend')->willReturn($mail_send);
+ $share->method('getToken')->willReturn($token);
+ $share->method('getPassword')->willReturn($password);
+
+ return $share;
+ }
+
+ public function dataGetShare() {
+ $data = [];
+
+ $owner = $this->getMock('OCP\IUser');
+ $owner->method('getUID')->willReturn('ownerId');
+ $owner->method('getDisplayName')->willReturn('ownerDisplay');
+
+ $user = $this->getMock('OCP\IUser');
+ $user->method('getUID')->willReturn('userId');
+ $user->method('getDisplayName')->willReturn('userDisplay');
+
+ $group = $this->getMock('OCP\IGroup');
+ $group->method('getGID')->willReturn('groupId');
+
+ $storage = $this->getMock('OCP\Files\Storage');
+ $storage->method('getId')->willReturn('STORAGE');
+
+ $parentFolder = $this->getMock('OCP\Files\Folder');
+ $parentFolder->method('getId')->willReturn(3);
+
+ $file = $this->getMock('OCP\Files\File');
+ $file->method('getId')->willReturn(1);
+ $file->method('getPath')->willReturn('file');
+ $file->method('getStorage')->willReturn($storage);
+ $file->method('getParent')->willReturn($parentFolder);
+
+ $folder = $this->getMock('OCP\Files\Folder');
+ $folder->method('getId')->willReturn(2);
+ $folder->method('getPath')->willReturn('folder');
+ $folder->method('getStorage')->willReturn($storage);
+ $folder->method('getParent')->willReturn($parentFolder);
+
+ // File shared with user
+ $share = $this->createShare(100,
+ \OCP\Share::SHARE_TYPE_USER,
+ $user,
+ $owner,
+ $file,
+ 4,
+ 5,
+ null,
+ 6,
+ 'target',
+ 0);
+ $expected = [
+ 'id' => 100,
+ 'share_type' => \OCP\Share::SHARE_TYPE_USER,
+ 'share_with' => 'userId',
+ 'share_with_displayname' => 'userDisplay',
+ 'uid_owner' => 'ownerId',
+ 'displayname_owner' => 'ownerDisplay',
+ 'item_type' => 'file',
+ 'item_source' => 1,
+ 'file_source' => 1,
+ 'file_target' => 'target',
+ 'file_parent' => 3,
+ 'token' => null,
+ 'expiration' => null,
+ 'permissions' => 4,
+ 'stime' => 5,
+ 'parent' => 6,
+ 'storage_id' => 'STORAGE',
+ 'path' => 'file',
+ 'storage' => null, // HACK around static function
+ 'mail_send' => 0,
+ ];
+ $data[] = [$share, $expected];
+
+ // Folder shared with group
+ $share = $this->createShare(101,
+ \OCP\Share::SHARE_TYPE_GROUP,
+ $group,
+ $owner,
+ $folder,
+ 4,
+ 5,
+ null,
+ 6,
+ 'target',
+ 0);
+ $expected = [
+ 'id' => 101,
+ 'share_type' => \OCP\Share::SHARE_TYPE_GROUP,
+ 'share_with' => 'groupId',
+ 'share_with_displayname' => 'groupId',
+ 'uid_owner' => 'ownerId',
+ 'displayname_owner' => 'ownerDisplay',
+ 'item_type' => 'folder',
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_target' => 'target',
+ 'file_parent' => 3,
+ 'token' => null,
+ 'expiration' => null,
+ 'permissions' => 4,
+ 'stime' => 5,
+ 'parent' => 6,
+ 'storage_id' => 'STORAGE',
+ 'path' => 'folder',
+ 'storage' => null, // HACK around static function
+ 'mail_send' => 0,
+ ];
+ $data[] = [$share, $expected];
+
+ // Folder shared with remote
+ $share = $this->createShare(101,
+ \OCP\Share::SHARE_TYPE_REMOTE,
+ 'user@remote.com',
+ $owner,
+ $folder,
+ 4,
+ 5,
+ null,
+ 6,
+ 'target',
+ 0);
+ $expected = [
+ 'id' => 101,
+ 'share_type' => \OCP\Share::SHARE_TYPE_REMOTE,
+ 'share_with' => 'user@remote.com',
+ 'share_with_displayname' => 'user@remote.com',
+ 'uid_owner' => 'ownerId',
+ 'displayname_owner' => 'ownerDisplay',
+ 'item_type' => 'folder',
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_target' => 'target',
+ 'file_parent' => 3,
+ 'token' => null,
+ 'expiration' => null,
+ 'permissions' => 4,
+ 'stime' => 5,
+ 'parent' => 6,
+ 'storage_id' => 'STORAGE',
+ 'path' => 'folder',
+ 'storage' => null, // HACK around static function
+ 'mail_send' => 0,
+ ];
+ $data[] = [$share, $expected];
+
+ // File shared by link with Expire
+ $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
+ $share = $this->createShare(101,
+ \OCP\Share::SHARE_TYPE_LINK,
+ null,
+ $owner,
+ $folder,
+ 4,
+ 5,
+ $expire,
+ 6,
+ 'target',
+ 0,
+ 'token',
+ 'password');
+ $expected = [
+ 'id' => 101,
+ 'share_type' => \OCP\Share::SHARE_TYPE_LINK,
+ 'share_with' => 'password',
+ 'share_with_displayname' => 'password',
+ 'uid_owner' => 'ownerId',
+ 'displayname_owner' => 'ownerDisplay',
+ 'item_type' => 'folder',
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_target' => 'target',
+ 'file_parent' => 3,
+ 'token' => 'token',
+ 'expiration' => '2000-01-02 00:00:00',
+ 'permissions' => 4,
+ 'stime' => 5,
+ 'parent' => 6,
+ 'storage_id' => 'STORAGE',
+ 'path' => 'folder',
+ 'storage' => null, // HACK around static function
+ 'mail_send' => 0,
+ 'url' => 'url',
+ ];
+ $data[] = [$share, $expected];
+
+ return $data;
+ }
+
+ /**
+ * @dataProvider dataGetShare
+ */
+ public function testGetShare(\OC\Share20\IShare $share, array $result) {
+ $this->shareManager
+ ->expects($this->once())
+ ->method('getShareById')
+ ->with($share->getId())
+ ->willReturn($share);
+
+ $this->userFolder
+ ->method('getRelativePath')
+ ->will($this->returnArgument(0));
+
+ $this->urlGenerator
+ ->method('linkToRouteAbsolute')
+ ->willReturn('url');
+
+ $expected = new \OC_OCS_Result($result);
+ $this->assertEquals($expected->getData(), $this->ocs->getShare($share->getId())->getData()); }
}
diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php
index dcf18e0e53b..22a923f5c20 100644
--- a/apps/provisioning_api/appinfo/routes.php
+++ b/apps/provisioning_api/appinfo/routes.php
@@ -37,7 +37,7 @@ $users = new \OCA\Provisioning_API\Users(
\OC::$server->getLogger()
);
API::register('get', '/cloud/users', [$users, 'getUsers'], 'provisioning_api', API::SUBADMIN_AUTH);
-API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::ADMIN_AUTH);
+API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::SUBADMIN_AUTH);
API::register('get', '/cloud/users/{userid}', [$users, 'getUser'], 'provisioning_api', API::USER_AUTH);
API::register('put', '/cloud/users/{userid}', [$users, 'editUser'], 'provisioning_api', API::USER_AUTH);
API::register('delete', '/cloud/users/{userid}', [$users, 'deleteUser'], 'provisioning_api', API::SUBADMIN_AUTH);
@@ -51,7 +51,8 @@ API::register('get', '/cloud/users/{userid}/subadmins', [$users, 'getUserSubAdmi
// Groups
$groups = new \OCA\Provisioning_API\Groups(
\OC::$server->getGroupManager(),
- \OC::$server->getUserSession()
+ \OC::$server->getUserSession(),
+ \OC::$server->getRequest()
);
API::register('get', '/cloud/groups', [$groups, 'getGroups'], 'provisioning_api', API::SUBADMIN_AUTH);
API::register('post', '/cloud/groups', [$groups, 'addGroup'], 'provisioning_api', API::SUBADMIN_AUTH);
diff --git a/apps/provisioning_api/lib/groups.php b/apps/provisioning_api/lib/groups.php
index c28db35972f..7c35caca5fd 100644
--- a/apps/provisioning_api/lib/groups.php
+++ b/apps/provisioning_api/lib/groups.php
@@ -37,14 +37,20 @@ class Groups{
/** @var \OCP\IUserSession */
private $userSession;
+ /** @var \OCP\IRequest */
+ private $request;
+
/**
* @param \OCP\IGroupManager $groupManager
* @param \OCP\IUserSession $userSession
+ * @param \OCP\IRequest $request
*/
public function __construct(\OCP\IGroupManager $groupManager,
- \OCP\IUserSession $userSession) {
+ \OCP\IUserSession $userSession,
+ \OCP\IRequest $request) {
$this->groupManager = $groupManager;
$this->userSession = $userSession;
+ $this->request = $request;
}
/**
@@ -54,9 +60,16 @@ class Groups{
* @return OC_OCS_Result
*/
public function getGroups($parameters) {
- $search = !empty($_GET['search']) ? $_GET['search'] : '';
- $limit = !empty($_GET['limit']) ? $_GET['limit'] : null;
- $offset = !empty($_GET['offset']) ? $_GET['offset'] : null;
+ $search = $this->request->getParam('search', '');
+ $limit = $this->request->getParam('limit');
+ $offset = $this->request->getParam('offset');
+
+ if ($limit !== null) {
+ $limit = (int)$limit;
+ }
+ if ($offset !== null) {
+ $offset = (int)$offset;
+ }
$groups = $this->groupManager->search($search, $limit, $offset);
$groups = array_map(function($group) {
@@ -80,21 +93,23 @@ class Groups{
return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
}
+ $groupId = $parameters['groupid'];
+
// Check the group exists
- if(!$this->groupManager->groupExists($parameters['groupid'])) {
+ if(!$this->groupManager->groupExists($groupId)) {
return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested group could not be found');
}
$isSubadminOfGroup = false;
- $targetGroupObject =$this->groupManager->get($parameters['groupid']);
- if($targetGroupObject !== null) {
- $isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $targetGroupObject);
+ $group = $this->groupManager->get($groupId);
+ if ($group !== null) {
+ $isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $group);
}
// Check subadmin has access to this group
if($this->groupManager->isAdmin($user->getUID())
|| $isSubadminOfGroup) {
- $users = $this->groupManager->get($parameters['groupid'])->getUsers();
+ $users = $this->groupManager->get($groupId)->getUsers();
$users = array_map(function($user) {
/** @var IUser $user */
return $user->getUID();
@@ -114,7 +129,7 @@ class Groups{
*/
public function addGroup($parameters) {
// Validate name
- $groupId = isset($_POST['groupid']) ? $_POST['groupid'] : '';
+ $groupId = $this->request->getParam('groupid', '');
if( preg_match( '/[^a-zA-Z0-9 _\.@\-]/', $groupId ) || empty($groupId)){
\OCP\Util::writeLog('provisioning_api', 'Attempt made to create group using invalid characters.', \OCP\Util::ERROR);
return new OC_OCS_Result(null, 101, 'Invalid group name');
diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php
index 304fe901cfd..a2568425d0f 100644
--- a/apps/provisioning_api/lib/users.php
+++ b/apps/provisioning_api/lib/users.php
@@ -117,19 +117,50 @@ class Users {
public function addUser() {
$userId = isset($_POST['userid']) ? $_POST['userid'] : null;
$password = isset($_POST['password']) ? $_POST['password'] : null;
+ $groups = isset($_POST['groups']) ? $_POST['groups'] : null;
+ $user = $this->userSession->getUser();
+ $isAdmin = $this->groupManager->isAdmin($user->getUID());
+ $subAdminManager = $this->groupManager->getSubAdmin();
+
+ if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) {
+ return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+ }
+
if($this->userManager->userExists($userId)) {
$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
return new OC_OCS_Result(null, 102, 'User already exists');
+ }
+
+ if(is_array($groups)) {
+ foreach ($groups as $group) {
+ if(!$this->groupManager->groupExists($group)){
+ return new OC_OCS_Result(null, 104, 'group '.$group.' does not exist');
+ }
+ if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
+ return new OC_OCS_Result(null, 105, 'insufficient privileges for group '. $group);
+ }
+ }
} else {
- try {
- $this->userManager->createUser($userId, $password);
- $this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']);
- return new OC_OCS_Result(null, 100);
- } catch (\Exception $e) {
- $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
- return new OC_OCS_Result(null, 101, 'Bad request');
+ if(!$isAdmin) {
+ return new OC_OCS_Result(null, 106, 'no group specified (required for subadmins)');
}
}
+
+ try {
+ $newUser = $this->userManager->createUser($userId, $password);
+ $this->logger->info('Successful addUser call with userid: '.$userId, ['app' => 'ocs_api']);
+
+ if (is_array($groups)) {
+ foreach ($groups as $group) {
+ $this->groupManager->get($group)->addUser($newUser);
+ $this->logger->info('Added userid '.$userId.' to group '.$group, ['app' => 'ocs_api']);
+ }
+ }
+ return new OC_OCS_Result(null, 100);
+ } catch (\Exception $e) {
+ $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
+ return new OC_OCS_Result(null, 101, 'Bad request');
+ }
}
/**
diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php
index f67ed1c36ae..7d4beb6a368 100644
--- a/apps/provisioning_api/tests/groupstest.php
+++ b/apps/provisioning_api/tests/groupstest.php
@@ -25,79 +25,131 @@
namespace OCA\Provisioning_API\Tests;
-use OCP\IUserManager;
use OCP\IGroupManager;
use OCP\IUserSession;
+use OCP\IRequest;
-class GroupsTest extends TestCase {
- /** @var IUserManager */
- protected $userManager;
+class GroupsTest extends \Test\TestCase {
/** @var IGroupManager */
protected $groupManager;
/** @var IUserSession */
protected $userSession;
+ /** @var IRequest */
+ protected $request;
+ /** @var \OC\SubAdmin */
+ protected $subAdminManager;
/** @var \OCA\Provisioning_API\Groups */
protected $api;
protected function setup() {
- parent::setup();
+ $this->subAdminManager = $this->getMockBuilder('OC\SubAdmin')->disableOriginalConstructor()->getMock();
- $this->userManager = \OC::$server->getUserManager();
- $this->groupManager = \OC::$server->getGroupManager();
- $this->userSession = \OC::$server->getUserSession();
+ $this->groupManager = $this->getMockBuilder('OC\Group\Manager')->disableOriginalConstructor()->getMock();
+ $this->groupManager
+ ->method('getSubAdmin')
+ ->willReturn($this->subAdminManager);
+
+ $this->userSession = $this->getMock('OCP\IUserSession');
+ $this->request = $this->getMock('OCP\IRequest');
$this->api = new \OCA\Provisioning_API\Groups(
$this->groupManager,
- $this->userSession
+ $this->userSession,
+ $this->request
);
}
- public function testGetGroups() {
- $groups = [];
- $id = $this->getUniqueID();
+ private function createGroup($gid) {
+ $group = $this->getMock('OCP\IGroup');
+ $group
+ ->method('getGID')
+ ->willReturn($gid);
+ return $group;
+ }
- for ($i=0; $i < 10; $i++) {
- $groups[] = $this->groupManager->createGroup($id . '_' . $i);
- }
+ private function createUser($uid) {
+ $user = $this->getMock('OCP\IUser');
+ $user
+ ->method('getUID')
+ ->willReturn($uid);
+ return $user;
+ }
- $_GET = [];
- $result = $this->api->getGroups([]);
- $this->assertInstanceOf('OC_OCS_Result', $result);
- $this->assertTrue($result->succeeded());
- $this->assertCount(count($this->groupManager->search('')), $result->getData()['groups']);
- $this->assertContains('admin', $result->getData()['groups']);
- foreach ($groups as $group) {
- $this->assertContains($group->getGID(), $result->getData()['groups']);
- }
-
- $_GET = [
- 'search' => $id,
- 'limit' => 5,
- 'offset' => 2
+ private function asUser() {
+ $user = $this->createUser('user');
+ $this->userSession
+ ->method('getUser')
+ ->willReturn($user);
+ }
+
+ private function asAdmin() {
+ $user = $this->createUser('admin');
+ $this->userSession
+ ->method('getUser')
+ ->willReturn($user);
+
+ $this->groupManager
+ ->method('isAdmin')
+ ->with('admin')
+ ->willReturn(true);
+ }
+
+ private function asSubAdminOfGroup($group) {
+ $user = $this->createUser('subAdmin');
+ $this->userSession
+ ->method('getUser')
+ ->willReturn($user);
+
+ $this->subAdminManager
+ ->method('isSubAdminOfGroup')
+ ->will($this->returnCallback(function($_user, $_group) use ($user, $group) {
+ if ($_user === $user && $_group === $group) {
+ return true;
+ }
+ return false;
+ }));
+ }
+
+ public function dataGetGroups() {
+ return [
+ [null, null, null],
+ ['foo', null, null],
+ [null, 1, null],
+ [null, null, 2],
+ ['foo', 1, 2],
];
+ }
+
+ /**
+ * @dataProvider dataGetGroups
+ */
+ public function testGetGroups($search, $limit, $offset) {
+ $this->request
+ ->expects($this->exactly(3))
+ ->method('getParam')
+ ->will($this->returnValueMap([
+ ['search', '', $search],
+ ['limit', null, $limit],
+ ['offset', null, $offset],
+ ]));
+
+ $groups = [$this->createGroup('group1'), $this->createGroup('group2')];
+
+ $search = $search === null ? '' : $search;
+
+ $this->groupManager
+ ->expects($this->once())
+ ->method('search')
+ ->with($search, $limit, $offset)
+ ->willReturn($groups);
+
$result = $this->api->getGroups([]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
- $this->assertCount(5, $result->getData()['groups']);
- foreach (array_splice($groups, 2, 5) as $group) {
- $this->assertContains($group->getGID(), $result->getData()['groups']);
- }
-
- foreach ($groups as $group) {
- $group->delete();
- }
+ $this->assertEquals(['group1', 'group2'], $result->getData()['groups']);
}
public function testGetGroupAsUser() {
-
- $users = $this->generateUsers(2);
- $this->userSession->setUser($users[0]);
-
- $group = $this->groupManager->createGroup($this->getUniqueID());
- $group->addUser($users[1]);
-
- $result = $this->api->getGroup(array(
- 'groupid' => $group->getGID(),
- ));
+ $result = $this->api->getGroup([]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertFalse($result->succeeded());
@@ -106,80 +158,91 @@ class GroupsTest extends TestCase {
}
public function testGetGroupAsSubadmin() {
-
- $users = $this->generateUsers(2);
- $this->userSession->setUser($users[0]);
-
- $group = $this->groupManager->createGroup($this->getUniqueID());
- $group->addUser($users[0]);
- $group->addUser($users[1]);
-
- $this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group);
+ $group = $this->createGroup('group');
+ $this->asSubAdminOfGroup($group);
+
+ $this->groupManager
+ ->method('get')
+ ->with('group')
+ ->willReturn($group);
+ $this->groupManager
+ ->method('groupExists')
+ ->with('group')
+ ->willReturn(true);
+ $group
+ ->method('getUsers')
+ ->willReturn([
+ $this->createUser('user1'),
+ $this->createUser('user2')
+ ]);
$result = $this->api->getGroup([
- 'groupid' => $group->getGID(),
+ 'groupid' => 'group',
]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
$this->assertEquals(1, sizeof($result->getData()), 'Asserting the result data array only has the "users" key');
$this->assertArrayHasKey('users', $result->getData());
- $resultData = $result->getData();
- $resultData = $resultData['users'];
-
- $users = array_map(function($user) {
- return $user->getUID();
- }, $users);
-
- sort($users);
- sort($resultData);
- $this->assertEquals($users, $resultData);
-
+ $this->assertEquals(['user1', 'user2'], $result->getData()['users']);
}
public function testGetGroupAsIrrelevantSubadmin() {
-
- $users = $this->generateUsers(2);
- $this->userSession->setUser($users[0]);
-
- $group1 = $this->groupManager->createGroup($this->getUniqueID());
- $group2 = $this->groupManager->createGroup($this->getUniqueID());
- $group1->addUser($users[1]);
- $group2->addUser($users[0]);
-
- $this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group2);
+ $group = $this->createGroup('group');
+ $otherGroup = $this->createGroup('otherGroup');
+ $this->asSubAdminOfGroup($otherGroup);
+
+ $this->groupManager
+ ->method('get')
+ ->with('group')
+ ->willReturn($group);
+ $this->groupManager
+ ->method('groupExists')
+ ->with('group')
+ ->willReturn(true);
$result = $this->api->getGroup([
- 'groupid' => $group1->getGID(),
+ 'groupid' => 'group',
]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertFalse($result->succeeded());
$this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode());
-
}
public function testGetGroupAsAdmin() {
-
- $users = $this->generateUsers(2);
- $this->userSession->setUser($users[0]);
-
- $group = $this->groupManager->createGroup($this->getUniqueID());
-
- $group->addUser($users[1]);
- $this->groupManager->get('admin')->addUser($users[0]);
+ $group = $this->createGroup('group');
+ $this->asAdmin();
+
+ $this->groupManager
+ ->method('get')
+ ->with('group')
+ ->willReturn($group);
+ $this->groupManager
+ ->method('groupExists')
+ ->with('group')
+ ->willReturn(true);
+ $group
+ ->method('getUsers')
+ ->willReturn([
+ $this->createUser('user1'),
+ $this->createUser('user2')
+ ]);
$result = $this->api->getGroup([
- 'groupid' => $group->getGID(),
+ 'groupid' => 'group',
]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
- $this->assertEquals(['users' => [$users[1]->getUID()]], $result->getData());
-
+ $this->assertEquals(1, sizeof($result->getData()), 'Asserting the result data array only has the "users" key');
+ $this->assertArrayHasKey('users', $result->getData());
+ $this->assertEquals(['user1', 'user2'], $result->getData()['users']);
}
public function testGetGroupNonExisting() {
+ $this->asUser();
+
$result = $this->api->getGroup([
'groupid' => $this->getUniqueId()
]);
@@ -190,35 +253,72 @@ class GroupsTest extends TestCase {
$this->assertEquals('The requested group could not be found', $result->getMeta()['message']);
}
+ public function testGetSubAdminsOfGroupsNotExists() {
+ $result = $this->api->getSubAdminsOfGroup([
+ 'groupid' => 'NonExistingGroup',
+ ]);
+
+ $this->assertInstanceOf('OC_OCS_Result', $result);
+ $this->assertFalse($result->succeeded());
+ $this->assertEquals(101, $result->getStatusCode());
+ $this->assertEquals('Group does not exist', $result->getMeta()['message']);
+ }
+
public function testGetSubAdminsOfGroup() {
- $user1 = $this->generateUsers();
- $user2 = $this->generateUsers();
- $this->userSession->setUser($user1);
- $this->groupManager->get('admin')->addUser($user1);
- $group1 = $this->groupManager->createGroup($this->getUniqueID());
- $this->groupManager->getSubAdmin()->createSubAdmin($user2, $group1);
+ $group = $this->createGroup('GroupWithSubAdmins');
+ $this->groupManager
+ ->method('get')
+ ->with('GroupWithSubAdmins')
+ ->willReturn($group);
+
+ $this->subAdminManager
+ ->expects($this->once())
+ ->method('getGroupsSubAdmins')
+ ->with($group)
+ ->willReturn([
+ $this->createUser('SubAdmin1'),
+ $this->createUser('SubAdmin2'),
+ ]);
+
$result = $this->api->getSubAdminsOfGroup([
- 'groupid' => $group1->getGID(),
+ 'groupid' => 'GroupWithSubAdmins',
]);
+
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
- $data = $result->getData();
- $this->assertEquals($user2->getUID(), reset($data));
- $group1->delete();
+ $this->assertEquals(['SubAdmin1', 'SubAdmin2'], $result->getData());
+ }
+
+ public function testGetSubAdminsOfGroupEmptyList() {
+ $group = $this->createGroup('GroupWithOutSubAdmins');
+ $this->groupManager
+ ->method('get')
+ ->with('GroupWithOutSubAdmins')
+ ->willReturn($group);
+
+ $this->subAdminManager
+ ->expects($this->once())
+ ->method('getGroupsSubAdmins')
+ ->with($group)
+ ->willReturn([
+ ]);
- $user1 = $this->generateUsers();
- $this->userSession->setUser($user1);
- $this->groupManager->get('admin')->addUser($user1);
$result = $this->api->getSubAdminsOfGroup([
- 'groupid' => $this->getUniqueID(),
+ 'groupid' => 'GroupWithOutSubAdmins',
]);
+
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertFalse($result->succeeded());
- $this->assertEquals(101, $result->getStatusCode());
+ $this->assertEquals(102, $result->getStatusCode());
+ $this->assertEquals('Unknown error occured', $result->getMeta()['message']);
}
public function testAddGroupEmptyGroup() {
- $_POST = [];
+ $this->request
+ ->method('getParam')
+ ->with('groupid')
+ ->willReturn('');
+
$result = $this->api->addGroup([]);
$this->assertInstanceOf('OC_OCS_Result', $result);
@@ -228,40 +328,47 @@ class GroupsTest extends TestCase {
}
public function testAddGroupExistingGroup() {
- $group = $this->groupManager->createGroup($this->getUniqueID());
+ $this->request
+ ->method('getParam')
+ ->with('groupid')
+ ->willReturn('ExistingGroup');
+
+ $this->groupManager
+ ->method('groupExists')
+ ->with('ExistingGroup')
+ ->willReturn(true);
- $_POST = [
- 'groupid' => $group->getGID()
- ];
$result = $this->api->addGroup([]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertFalse($result->succeeded());
$this->assertEquals(102, $result->getStatusCode());
-
- $group->delete();
}
public function testAddGroup() {
- $group = $this->getUniqueId();
+ $this->request
+ ->method('getParam')
+ ->with('groupid')
+ ->willReturn('NewGroup');
- $_POST = [
- 'groupid' => $group
- ];
+ $this->groupManager
+ ->method('groupExists')
+ ->with('NewGroup')
+ ->willReturn(false);
+
+ $this->groupManager
+ ->expects($this->once())
+ ->method('createGroup')
+ ->with('NewGroup');
$result = $this->api->addGroup([]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
- $this->assertTrue($this->groupManager->groupExists($group));
-
- $this->groupManager->get($group)->delete();
}
public function testDeleteGroupNonExisting() {
- $group = $this->getUniqueId();
-
$result = $this->api->deleteGroup([
- 'groupid' => $group
+ 'groupid' => 'NonExistingGroup'
]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertFalse($result->succeeded());
@@ -269,6 +376,11 @@ class GroupsTest extends TestCase {
}
public function testDeleteAdminGroup() {
+ $this->groupManager
+ ->method('groupExists')
+ ->with('admin')
+ ->willReturn('true');
+
$result = $this->api->deleteGroup([
'groupid' => 'admin'
]);
@@ -278,13 +390,25 @@ class GroupsTest extends TestCase {
}
public function testDeleteGroup() {
- $group = $this->groupManager->createGroup($this->getUniqueId());
+ $this->groupManager
+ ->method('groupExists')
+ ->with('ExistingGroup')
+ ->willReturn('true');
+
+ $group = $this->createGroup('ExistingGroup');
+ $this->groupManager
+ ->method('get')
+ ->with('ExistingGroup')
+ ->willReturn($group);
+ $group
+ ->expects($this->once())
+ ->method('delete')
+ ->willReturn(true);
$result = $this->api->deleteGroup([
- 'groupid' => $group->getGID()
+ 'groupid' => 'ExistingGroup',
]);
$this->assertInstanceOf('OC_OCS_Result', $result);
$this->assertTrue($result->succeeded());
- $this->assertFalse($this->groupManager->groupExists($group->getGID()));
}
}
diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php
index ba4ed8a2e2f..63180eb3472 100644
--- a/apps/provisioning_api/tests/userstest.php
+++ b/apps/provisioning_api/tests/userstest.php
@@ -218,11 +218,95 @@ class UsersTest extends OriginalTest {
->expects($this->once())
->method('error')
->with('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
$expected = new \OC_OCS_Result(null, 102, 'User already exists');
$this->assertEquals($expected, $this->api->addUser());
}
+ public function testAddUserNonExistingGroup() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['groups'] = ['NonExistingGroup'];
+ $this->userManager
+ ->expects($this->once())
+ ->method('userExists')
+ ->with('NewUser')
+ ->willReturn(false);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('groupExists')
+ ->with('NonExistingGroup')
+ ->willReturn(false);
+
+ $expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist');
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+ public function testAddUserExistingGroupNonExistingGroup() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['groups'] = ['ExistingGroup', 'NonExistingGroup'];
+ $this->userManager
+ ->expects($this->once())
+ ->method('userExists')
+ ->with('NewUser')
+ ->willReturn(false);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
+ $this->groupManager
+ ->expects($this->exactly(2))
+ ->method('groupExists')
+ ->withConsecutive(
+ ['ExistingGroup'],
+ ['NonExistingGroup']
+ )
+ ->will($this->returnValueMap([
+ ['ExistingGroup', true],
+ ['NonExistingGroup', false]
+ ]));
+
+ $expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist');
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
public function testAddUserSuccessful() {
$_POST['userid'] = 'NewUser';
$_POST['password'] = 'PasswordOfTheNewUser';
@@ -239,6 +323,76 @@ class UsersTest extends OriginalTest {
->expects($this->once())
->method('info')
->with('Successful addUser call with userid: NewUser', ['app' => 'ocs_api']);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
+
+ $expected = new \OC_OCS_Result(null, 100);
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+ public function testAddUserExistingGroup() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['password'] = 'PasswordOfTheNewUser';
+ $_POST['groups'] = ['ExistingGroup'];
+ $this->userManager
+ ->expects($this->once())
+ ->method('userExists')
+ ->with('NewUser')
+ ->willReturn(false);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('groupExists')
+ ->with('ExistingGroup')
+ ->willReturn(true);
+ $user = $this->getMock('\OCP\IUser');
+ $this->userManager
+ ->expects($this->once())
+ ->method('createUser')
+ ->with('NewUser', 'PasswordOfTheNewUser')
+ ->willReturn($user);
+ $group = $this->getMock('\OCP\IGroup');
+ $group
+ ->expects($this->once())
+ ->method('addUser')
+ ->with($user);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('ExistingGroup')
+ ->willReturn($group);
+ $this->logger
+ ->expects($this->exactly(2))
+ ->method('info')
+ ->withConsecutive(
+ ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']],
+ ['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']]
+ );
$expected = new \OC_OCS_Result(null, 100);
$this->assertEquals($expected, $this->api->addUser());
@@ -261,11 +415,238 @@ class UsersTest extends OriginalTest {
->expects($this->once())
->method('error')
->with('Failed addUser attempt with exception: User backend not found.', ['app' => 'ocs_api']);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('adminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('adminUser')
+ ->willReturn(true);
$expected = new \OC_OCS_Result(null, 101, 'Bad request');
$this->assertEquals($expected, $this->api->addUser());
}
+ public function testAddUserAsRegularUser() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['password'] = 'PasswordOfTheNewUser';
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('regularUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('regularUser')
+ ->willReturn(false);
+ $subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+ ->disableOriginalConstructor()->getMock();
+ $subAdminManager
+ ->expects($this->once())
+ ->method('isSubAdmin')
+ ->with($loggedInUser)
+ ->willReturn(false);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getSubAdmin')
+ ->with()
+ ->willReturn($subAdminManager);
+
+ $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+ public function testAddUserAsSubAdminNoGroup() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['password'] = 'PasswordOfTheNewUser';
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('regularUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('regularUser')
+ ->willReturn(false);
+ $subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+ ->disableOriginalConstructor()->getMock();
+ $subAdminManager
+ ->expects($this->once())
+ ->method('isSubAdmin')
+ ->with($loggedInUser)
+ ->willReturn(true);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getSubAdmin')
+ ->with()
+ ->willReturn($subAdminManager);
+
+ $expected = new \OC_OCS_Result(null, 106, 'no group specified (required for subadmins)');
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+ public function testAddUserAsSubAdminValidGroupNotSubAdmin() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['password'] = 'PasswordOfTheNewUser';
+ $_POST['groups'] = ['ExistingGroup'];
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('regularUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('regularUser')
+ ->willReturn(false);
+ $existingGroup = $this->getMock('\OCP\IGroup');
+ $this->groupManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('ExistingGroup')
+ ->willReturn($existingGroup);
+ $subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+ ->disableOriginalConstructor()->getMock();
+ $subAdminManager
+ ->expects($this->once())
+ ->method('isSubAdmin')
+ ->with($loggedInUser)
+ ->willReturn(true);
+ $subAdminManager
+ ->expects($this->once())
+ ->method('isSubAdminOfGroup')
+ ->with($loggedInUser, $existingGroup)
+ ->wilLReturn(false);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getSubAdmin')
+ ->with()
+ ->willReturn($subAdminManager);
+ $this->groupManager
+ ->expects($this->once())
+ ->method('groupExists')
+ ->with('ExistingGroup')
+ ->willReturn(true);
+
+ $expected = new \OC_OCS_Result(null, 105, 'insufficient privileges for group ExistingGroup');
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+ public function testAddUserAsSubAdminExistingGroups() {
+ $_POST['userid'] = 'NewUser';
+ $_POST['password'] = 'PasswordOfTheNewUser';
+ $_POST['groups'] = ['ExistingGroup1', 'ExistingGroup2'];
+ $this->userManager
+ ->expects($this->once())
+ ->method('userExists')
+ ->with('NewUser')
+ ->willReturn(false);
+ $loggedInUser = $this->getMock('\OCP\IUser');
+ $loggedInUser
+ ->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('subAdminUser'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('isAdmin')
+ ->with('subAdminUser')
+ ->willReturn(false);
+ $this->groupManager
+ ->expects($this->exactly(2))
+ ->method('groupExists')
+ ->withConsecutive(
+ ['ExistingGroup1'],
+ ['ExistingGroup2']
+ )
+ ->willReturn(true);
+ $user = $this->getMock('\OCP\IUser');
+ $this->userManager
+ ->expects($this->once())
+ ->method('createUser')
+ ->with('NewUser', 'PasswordOfTheNewUser')
+ ->willReturn($user);
+ $existingGroup1 = $this->getMock('\OCP\IGroup');
+ $existingGroup2 = $this->getMock('\OCP\IGroup');
+ $existingGroup1
+ ->expects($this->once())
+ ->method('addUser')
+ ->with($user);
+ $existingGroup2
+ ->expects($this->once())
+ ->method('addUser')
+ ->with($user);
+ $this->groupManager
+ ->expects($this->exactly(4))
+ ->method('get')
+ ->withConsecutive(
+ ['ExistingGroup1'],
+ ['ExistingGroup2'],
+ ['ExistingGroup1'],
+ ['ExistingGroup2']
+ )
+ ->will($this->returnValueMap([
+ ['ExistingGroup1', $existingGroup1],
+ ['ExistingGroup2', $existingGroup2]
+ ]));
+ $this->logger
+ ->expects($this->exactly(3))
+ ->method('info')
+ ->withConsecutive(
+ ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']],
+ ['Added userid NewUser to group ExistingGroup1', ['app' => 'ocs_api']],
+ ['Added userid NewUser to group ExistingGroup2', ['app' => 'ocs_api']]
+ );
+ $subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+ ->disableOriginalConstructor()->getMock();
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getSubAdmin')
+ ->willReturn($subAdminManager);
+ $subAdminManager
+ ->expects($this->once())
+ ->method('isSubAdmin')
+ ->with($loggedInUser)
+ ->willReturn(true);
+ $subAdminManager
+ ->expects($this->exactly(2))
+ ->method('isSubAdminOfGroup')
+ ->withConsecutive(
+ [$loggedInUser, $existingGroup1],
+ [$loggedInUser, $existingGroup2]
+ )
+ ->wilLReturn(true);
+
+
+ $expected = new \OC_OCS_Result(null, 100);
+ $this->assertEquals($expected, $this->api->addUser());
+ }
+
+
public function testGetUserNotLoggedIn() {
$this->userSession
->expects($this->once())
diff --git a/core/css/apps.css b/core/css/apps.css
index ac2be40ac5b..e9abbe0aee1 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -563,16 +563,19 @@ button.loading {
#app-content > .section:first-child {
border-top: none;
}
-.section h2 {
+
+/* heading styles */
+h2 {
font-size: 20px;
- margin-bottom: 12px;
font-weight: 300;
+ margin-bottom: 12px;
}
-.section h3 {
+h3 {
font-size: 15px;
font-weight: 300;
margin: 12px 0;
}
+
/* slight position correction of checkboxes and radio buttons */
.section input[type="checkbox"],
.section input[type="radio"] {
diff --git a/core/css/inputs.css b/core/css/inputs.css
new file mode 100644
index 00000000000..9f440a6c359
--- /dev/null
+++ b/core/css/inputs.css
@@ -0,0 +1,232 @@
+/* INPUTS */
+
+/* specifically override browser styles */
+input, textarea, select, button {
+ font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
+}
+
+input[type="text"],
+input[type="password"],
+input[type="search"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="time"],
+input[type="date"],
+textarea,
+select,
+button, .button,
+input[type="submit"],
+input[type="button"],
+#quota,
+.pager li a {
+ width: 130px;
+ margin: 3px 3px 3px 0;
+ padding: 7px 6px 5px;
+ font-size: 13px;
+ background-color: #fff;
+ color: #333;
+ border: 1px solid #ddd;
+ outline: none;
+ border-radius: 3px;
+}
+input[type="hidden"] {
+ height: 0;
+ width: 0;
+}
+input[type="text"],
+input[type="password"],
+input[type="search"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="time"],
+textarea {
+ background: #fff;
+ color: #555;
+ cursor: text;
+ font-family: inherit; /* use default ownCloud font instead of default textarea monospace */
+}
+input[type="text"],
+input[type="password"],
+input[type="search"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="time"] {
+ -webkit-appearance:textfield; -moz-appearance:textfield;
+ -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box;
+}
+input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,
+input[type="password"]:hover, input[type="password"]:focus, input[type="password"]:active,
+input[type="number"]:hover, input[type="number"]:focus, input[type="number"]:active,
+input[type="search"]:hover, input[type="search"]:focus, input[type="search"]:active,
+input[type="email"]:hover, input[type="email"]:focus, input[type="email"]:active,
+input[type="url"]:hover, input[type="url"]:focus, input[type="url"]:active,
+input[type="time"]:hover, input[type="time"]:focus, input[type="time"]:active,
+textarea:hover, textarea:focus, textarea:active {
+ color: #333;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ opacity: 1;
+}
+
+.ie8 input[type="checkbox"] { margin:0; padding:0; height:auto; width:auto; }
+.ie8 input[type="checkbox"]:hover+label, input[type="checkbox"]:focus+label { color:#111 !important; }
+
+/* ie8 doesn't support :checked */
+html:not(.ie8) input[type="checkbox"].checkbox {
+ position: absolute;
+ left:-10000px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+html:not(.ie8) input[type="checkbox"].checkbox + label:before {
+ content: "";
+ display: inline-block;
+
+ height: 20px;
+ width: 20px;
+ vertical-align: middle;
+
+ background: url('../img/actions/checkbox.svg') left top no-repeat;
+ opacity: 0.7;
+}
+
+html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; }
+
+html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; }
+html:not(.ie8) input[type="checkbox"].checkbox.u-hidden + label:before { display: none; }
+
+html:not(.ie8) input[type="checkbox"].checkbox--white + label:before {
+ background-image: url('../img/actions/checkbox-white.svg');
+}
+
+html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before {
+ background-image: url('../img/actions/checkbox-checked.svg');
+}
+
+html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before {
+ background-image: url('../img/actions/checkbox-checked-white.svg');
+}
+
+html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before {
+ color:#111 !important;
+}
+
+input[type="time"] {
+ width: initial;
+ height: 31px;
+ -moz-box-sizing: border-box; box-sizing: border-box;
+}
+
+select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: url('../../core/img/actions/triangle-s.svg') no-repeat right 8px center rgba(240, 240, 240, 0.90);
+ outline: 0;
+ padding-right: 24px !important;
+}
+
+select:hover {
+ background-color: #fefefe;
+}
+
+.select2-choices {
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ color: #333;
+ background-image: none;
+}
+.select2-dropdown-open .select2-choices {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ border: 1px solid #3875d7;
+}
+
+/* correctly align images inside of buttons */
+input img, button img, .button img {
+ vertical-align: text-bottom;
+}
+
+input[type="submit"].enabled {
+ background-color: #66f866;
+ border: 1px solid #5e5;
+}
+
+.input-button-inline {
+ position: absolute !important;
+ right: 0;
+ background-color: transparent !important;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
+ opacity: .3;
+}
+
+
+/* BUTTONS */
+input[type="submit"], input[type="button"],
+button, .button,
+#quota, select, .pager li a {
+ width: auto;
+ min-width: 25px;
+ padding: 5px;
+ background-color: rgba(240,240,240,.9);
+ font-weight: 600;
+ color: #555;
+ border: 1px solid rgba(240,240,240,.9);
+ cursor: pointer;
+}
+select, .button.multiselect {
+ font-weight: 400;
+}
+input[type="submit"]:hover, input[type="submit"]:focus,
+input[type="button"]:hover, input[type="button"]:focus,
+button:hover, button:focus,
+.button:hover, .button:focus,
+.button a:focus,
+select:hover, select:focus, select:active {
+ background-color: rgba(255, 255, 255, .95);
+ color: #111;
+}
+input[type="submit"] img, input[type="button"] img, button img, .button img { cursor:pointer; }
+#header .button {
+ border: none;
+ box-shadow: none;
+}
+
+/* disabled input fields and buttons */
+input:disabled, input:disabled:hover, input:disabled:focus,
+button:disabled, button:disabled:hover, button:disabled:focus,
+.button:disabled, .button:disabled:hover, .button:disabled:focus,
+a.disabled, a.disabled:hover, a.disabled:focus,
+textarea:disabled {
+ background-color: rgba(230,230,230,.9);
+ color: #999;
+ cursor: default;
+}
+input:disabled+label, input:disabled:hover+label, input:disabled:focus+label {
+ color: #999 !important;
+ cursor: default;
+}
+
+/* Primary action button, use sparingly */
+.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary {
+ border: 1px solid #1d2d44;
+ background-color: #35537a;
+ color: #ddd;
+}
+.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,
+.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {
+ background-color: #304d76;
+ color: #fff;
+}
+.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,
+.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,
+.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,
+.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {
+ background-color: #1d2d44;
+ color: #bbb;
+}
diff --git a/core/css/styles.css b/core/css/styles.css
index 066087cc433..75bbb78fe52 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -12,18 +12,6 @@ table, td, th { vertical-align:middle; }
a { border:0; color:#000; text-decoration:none;}
a, a *, input, input *, select, .button span, label { cursor:pointer; }
ul { list-style:none; }
-select {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background: url('../../core/img/actions/triangle-s.svg') no-repeat right 8px center rgba(240, 240, 240, 0.90);
- outline: 0;
- padding-right: 24px !important;
-}
-
-select:hover {
- background-color: #fefefe;
-}
body {
background-color: #ffffff;
@@ -85,155 +73,6 @@ body {
color: #ddd;
}
-
-
-/* INPUTS */
-
-/* specifically override browser styles */
-input, textarea, select, button {
- font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
-}
-
-input[type="text"],
-input[type="password"],
-input[type="search"],
-input[type="number"],
-input[type="email"],
-input[type="url"],
-input[type="time"],
-input[type="date"],
-textarea,
-select,
-button, .button,
-input[type="submit"],
-input[type="button"],
-#quota,
-.pager li a {
- width: 130px;
- margin: 3px 3px 3px 0;
- padding: 7px 6px 5px;
- font-size: 13px;
- background-color: #fff;
- color: #333;
- border: 1px solid #ddd;
- outline: none;
- border-radius: 3px;
-}
-input[type="hidden"] {
- height: 0;
- width: 0;
-}
-input[type="text"],
-input[type="password"],
-input[type="search"],
-input[type="number"],
-input[type="email"],
-input[type="url"],
-input[type="time"],
-textarea {
- background: #fff;
- color: #555;
- cursor: text;
- font-family: inherit; /* use default ownCloud font instead of default textarea monospace */
-}
-input[type="text"],
-input[type="password"],
-input[type="search"],
-input[type="number"],
-input[type="email"],
-input[type="url"],
-input[type="time"] {
- -webkit-appearance:textfield; -moz-appearance:textfield;
- -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box;
-}
-input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,
-input[type="password"]:hover, input[type="password"]:focus, input[type="password"]:active,
-input[type="number"]:hover, input[type="number"]:focus, input[type="number"]:active,
-.searchbox input[type="search"]:hover, .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active,
-input[type="email"]:hover, input[type="email"]:focus, input[type="email"]:active,
-input[type="url"]:hover, input[type="url"]:focus, input[type="url"]:active,
-input[type="time"]:hover, input[type="time"]:focus, input[type="time"]:active,
-textarea:hover, textarea:focus, textarea:active {
- color: #333;
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
- opacity: 1;
-}
-
-.ie8 input[type="checkbox"] { margin:0; padding:0; height:auto; width:auto; }
-.ie8 input[type="checkbox"]:hover+label, input[type="checkbox"]:focus+label { color:#111 !important; }
-
-/* ie8 doesn't support :checked */
-html:not(.ie8) input[type="checkbox"].checkbox {
- position: absolute;
- left:-10000px;
- top: auto;
- width: 1px;
- height: 1px;
- overflow: hidden;
-}
-
-html:not(.ie8) input[type="checkbox"].checkbox + label:before {
- content: "";
- display: inline-block;
-
- height: 20px;
- width: 20px;
- vertical-align: middle;
-
- background: url('../img/actions/checkbox.svg') left top no-repeat;
- opacity: 0.7;
-}
-
-html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; }
-
-html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; }
-html:not(.ie8) input[type="checkbox"].checkbox.u-hidden + label:before { display: none; }
-
-html:not(.ie8) input[type="checkbox"].checkbox--white + label:before {
- background-image: url('../img/actions/checkbox-white.svg');
-}
-
-html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before {
- background-image: url('../img/actions/checkbox-checked.svg');
-}
-
-html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before {
- background-image: url('../img/actions/checkbox-checked-white.svg');
-}
-
-html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before {
- color:#111 !important;
-}
-
-input[type="time"] {
- width: initial;
- height: 31px;
- -moz-box-sizing: border-box; box-sizing: border-box;
-}
-
-.select2-choices {
- border: 1px solid #ddd;
- border-radius: 3px;
- color: #333;
- background-image: none;
-}
-.select2-dropdown-open .select2-choices {
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- border: 1px solid #3875d7;
-}
-
-/* correctly align images inside of buttons */
-input img, button img, .button img {
- vertical-align: text-bottom;
-}
-
-#quota {
- cursor: default;
- margin: 30px;
-}
-
-
/* SCROLLING */
::-webkit-scrollbar {
width: 8px;
@@ -245,72 +84,6 @@ input img, button img, .button img {
background: #ddd;
}
-
-/* BUTTONS */
-input[type="submit"], input[type="button"],
-button, .button,
-#quota, select, .pager li a {
- width: auto;
- min-width: 25px;
- padding: 5px;
- background-color: rgba(240,240,240,.9);
- font-weight: 600;
- color: #555;
- border: 1px solid rgba(240,240,240,.9);
- cursor: pointer;
-}
-select, .button.multiselect {
- font-weight: 400;
-}
-input[type="submit"]:hover, input[type="submit"]:focus,
-input[type="button"]:hover, input[type="button"]:focus,
-button:hover, button:focus,
-.button:hover, .button:focus,
-.button a:focus,
-select:hover, select:focus, select:active {
- background-color: rgba(255, 255, 255, .95);
- color: #111;
-}
-input[type="submit"] img, input[type="button"] img, button img, .button img { cursor:pointer; }
-#header .button {
- border: none;
- box-shadow: none;
-}
-
-/* disabled input fields and buttons */
-input:disabled, input:disabled:hover, input:disabled:focus,
-button:disabled, button:disabled:hover, button:disabled:focus,
-.button:disabled, .button:disabled:hover, .button:disabled:focus,
-a.disabled, a.disabled:hover, a.disabled:focus,
-textarea:disabled {
- background-color: rgba(230,230,230,.9);
- color: #999;
- cursor: default;
-}
-input:disabled+label, input:disabled:hover+label, input:disabled:focus+label {
- color: #999 !important;
- cursor: default;
-}
-
-/* Primary action button, use sparingly */
-.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary {
- border: 1px solid #1d2d44;
- background-color: #35537a;
- color: #ddd;
-}
- .primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,
- .primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {
- background-color: #304d76;
- color: #fff;
- }
- .primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,
- .primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,
- .primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,
- .primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {
- background-color: #1d2d44;
- color: #bbb;
- }
-
/* Searchbox */
.searchbox input[type="search"] {
position: relative;
@@ -342,21 +115,6 @@ input:disabled+label, input:disabled:hover+label, input:disabled:focus+label {
background-color: #112;
}
-input[type="submit"].enabled {
- background-color: #66f866;
- border: 1px solid #5e5;
-}
-
-.input-button-inline {
- position: absolute !important;
- right: 0;
- background-color: transparent !important;
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
- opacity: .3;
-}
-
-
-
/* CONTENT ------------------------------------------------------------------ */
#controls {
-moz-box-sizing: border-box;
@@ -437,7 +195,6 @@ input[type="submit"].enabled {
#emptycontent h2,
.emptycontent h2 {
font-weight: 600;
- font-size: 22px;
margin-bottom: 10px;
}
#emptycontent [class^="icon-"],
@@ -483,7 +240,6 @@ input[type="submit"].enabled {
}
#body-login .update h2 {
- font-size: 20px;
line-height: 130%;
margin-bottom: 30px;
}
@@ -941,6 +697,8 @@ tbody tr:active {
code { font-family:"Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", monospace; }
#quota {
+ cursor: default;
+ margin: 30px;
position: relative;
padding: 0;
}
diff --git a/core/js/js.js b/core/js/js.js
index 07320a1d225..57c9871233b 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -119,10 +119,12 @@ var OC={
/**
* Gets the base path for the given OCS API service.
* @param {string} service name
+ * @param {int} version OCS API version
* @return {string} OCS API base path
*/
- linkToOCS: function(service) {
- return window.location.protocol + '//' + window.location.host + OC.webroot + '/ocs/v1.php/' + service + '/';
+ linkToOCS: function(service, version) {
+ version = (version !== 2) ? 1 : 2;
+ return window.location.protocol + '//' + window.location.host + OC.webroot + '/ocs/v' + version + '.php/' + service + '/';
},
/**
diff --git a/core/l10n/ru.js b/core/l10n/ru.js
index 2df910a6aa4..39302e9a18e 100644
--- a/core/l10n/ru.js
+++ b/core/l10n/ru.js
@@ -177,6 +177,7 @@ OC.L10N.register(
"Hello {name}" : "Здравствуйте {name}",
"_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"],
"{version} is available. Get more information on how to update." : "Доступна версия {version}. Получить дополнительную информацию о порядке обновления.",
+ "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.",
"Updating {productName} to version {version}, this may take a while." : "Идет обновление {productName} до версии {version}, пожалуйста, подождите.",
"An error occurred." : "Произошла ошибка.",
"Please reload the page." : "Обновите страницу.",
@@ -268,6 +269,7 @@ OC.L10N.register(
"Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.",
"Thank you for your patience." : "Спасибо за терпение.",
"You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Пожалуйста, обратитесь к администратору. Если вы являетесь администратором этого экземпляра, настроить параметры \"trusted_domains\" можно в config/config.php. Пример настройки можно найти в config/config.sample.php.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.",
"Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен",
"App update required" : "Требуется обновление приложения",
diff --git a/core/l10n/ru.json b/core/l10n/ru.json
index 66d3b463899..a24ee0831a0 100644
--- a/core/l10n/ru.json
+++ b/core/l10n/ru.json
@@ -175,6 +175,7 @@
"Hello {name}" : "Здравствуйте {name}",
"_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"],
"{version} is available. Get more information on how to update." : "Доступна версия {version}. Получить дополнительную информацию о порядке обновления.",
+ "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.",
"Updating {productName} to version {version}, this may take a while." : "Идет обновление {productName} до версии {version}, пожалуйста, подождите.",
"An error occurred." : "Произошла ошибка.",
"Please reload the page." : "Обновите страницу.",
@@ -266,6 +267,7 @@
"Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.",
"Thank you for your patience." : "Спасибо за терпение.",
"You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Пожалуйста, обратитесь к администратору. Если вы являетесь администратором этого экземпляра, настроить параметры \"trusted_domains\" можно в config/config.php. Пример настройки можно найти в config/config.sample.php.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.",
"Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен",
"App update required" : "Требуется обновление приложения",
diff --git a/core/shipped.json b/core/shipped.json
index 49a649f3c9e..cd1fca4d9fe 100644
--- a/core/shipped.json
+++ b/core/shipped.json
@@ -31,7 +31,8 @@
"user_external",
"user_ldap",
"user_shibboleth",
- "windows_network_drive"
+ "windows_network_drive",
+ "password_policy"
],
"alwaysEnabled": [
"files",
diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php
index 79bc809b9b2..7f21d3aadf5 100644
--- a/lib/private/share20/defaultshareprovider.php
+++ b/lib/private/share20/defaultshareprovider.php
@@ -235,17 +235,16 @@ class DefaultShareProvider implements IShareProvider {
$share->setId((int)$data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions'])
- ->setTarget($data['file_target']);
+ ->setTarget($data['file_target'])
+ ->setShareTime((int)$data['stime'])
+ ->setMailSend((bool)$data['mail_send']);
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
$share->setSharedWith($this->userManager->get($data['share_with']));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$share->setSharedWith($this->groupManager->get($data['share_with']));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
- /*
- * TODO: Clean this up, this should be set as password not sharedWith
- */
- $share->setSharedWith($data['share_with']);
+ $share->setPassword($data['share_with']);
$share->setToken($data['token']);
} else {
$share->setSharedWith($data['share_with']);
diff --git a/lib/private/share20/ishare.php b/lib/private/share20/ishare.php
index fa7c1ea614c..a80abebd71c 100644
--- a/lib/private/share20/ishare.php
+++ b/lib/private/share20/ishare.php
@@ -134,6 +134,13 @@ interface IShare {
public function setPassword($password);
/**
+ * Is a password set for this share
+ *
+ * @return string
+ */
+ public function getPassword();
+
+ /**
* Get the token
*
* @return string
@@ -153,4 +160,18 @@ interface IShare {
* @return string
*/
public function getTarget();
+
+ /**
+ * Get the timestamp this share was created
+ *
+ * @return int
+ */
+ public function getSharetime();
+
+ /**
+ * Get mailSend
+ *
+ * @return bool
+ */
+ public function getMailSend();
}
diff --git a/lib/private/share20/share.php b/lib/private/share20/share.php
index 989edd3c079..4200816799e 100644
--- a/lib/private/share20/share.php
+++ b/lib/private/share20/share.php
@@ -28,39 +28,32 @@ class Share implements IShare {
/** @var string */
private $id;
-
/** @var Node */
private $path;
-
/** @var int */
private $shareType;
-
/** @var IUser|IGroup|string */
private $sharedWith;
-
/** @var IUser|string */
private $sharedBy;
-
/** @var IUser|string */
private $shareOwner;
-
/** @var int */
private $permissions;
-
/** @var \DateTime */
private $expireDate;
-
/** @var string */
private $password;
-
/** @var string */
private $token;
-
/** @var int */
private $parent;
-
/** @var string */
private $target;
+ /** @var int */
+ private $shareTime;
+ /** @var bool */
+ private $mailSend;
/**
* Set the id of the share
@@ -252,7 +245,7 @@ class Share implements IShare {
*
* @return string
*/
- public function getPassword($password) {
+ public function getPassword() {
return $this->password;
}
@@ -315,4 +308,44 @@ class Share implements IShare {
public function getTarget() {
return $this->target;
}
+
+ /**
+ * Set the time this share was created
+ *
+ * @param int $shareTime
+ * @return Share The modified object
+ */
+ public function setShareTime($shareTime) {
+ $this->shareTime = $shareTime;
+ return $this;
+ }
+
+ /**
+ * Get the timestamp this share was created
+ *
+ * @return int
+ */
+ public function getSharetime() {
+ return $this->shareTime;
+ }
+
+ /**
+ * Set mailSend
+ *
+ * @param bool $mailSend
+ * @return Share The modified object
+ */
+ public function setMailSend($mailSend) {
+ $this->mailSend = $mailSend;
+ return $this;
+ }
+
+ /**
+ * Get mailSend
+ *
+ * @return bool
+ */
+ public function getMailSend() {
+ return $this->mailSend;
+ }
}
diff --git a/lib/private/template.php b/lib/private/template.php
index 722194dc764..97666f0b8dc 100644
--- a/lib/private/template.php
+++ b/lib/private/template.php
@@ -114,6 +114,7 @@ class OC_Template extends \OC\Template\Base {
OC_Util::addStyle("icons",null,true);
OC_Util::addStyle("mobile",null,true);
OC_Util::addStyle("header",null,true);
+ OC_Util::addStyle("inputs",null,true);
OC_Util::addStyle("styles",null,true);
// avatars
diff --git a/tests/lib/share20/defaultshareprovidertest.php b/tests/lib/share20/defaultshareprovidertest.php
index e99290f6724..f8b6f98be7c 100644
--- a/tests/lib/share20/defaultshareprovidertest.php
+++ b/tests/lib/share20/defaultshareprovidertest.php
@@ -266,7 +266,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
- $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('sharedWith', $share->getPassword());
$this->assertEquals($sharedBy, $share->getSharedBy());
$this->assertEquals($shareOwner, $share->getShareOwner());
$this->assertEquals($path, $share->getPath());