aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/templates/appnavigation.php4
-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.php2
-rw-r--r--apps/provisioning_api/lib/users.php45
-rw-r--r--apps/provisioning_api/tests/userstest.php381
-rw-r--r--bower.json2
-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/vendor/strengthify/.bower.json10
-rw-r--r--core/vendor/strengthify/LICENSE2
-rw-r--r--core/vendor/strengthify/jquery.strengthify.js55
-rw-r--r--core/vendor/strengthify/strengthify.css6
-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
21 files changed, 1123 insertions, 340 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_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..d2cba549846 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);
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/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/bower.json b/bower.json
index 1fe270d9f3c..e8bb9a35f32 100644
--- a/bower.json
+++ b/bower.json
@@ -24,7 +24,7 @@
"select2": "~3.4.8",
"zxcvbn": "*",
"snapjs": "~2.0.0-rc1",
- "strengthify": "0.4.1",
+ "strengthify": "0.4.2",
"underscore": "~1.8.0",
"bootstrap": "~3.3.5",
"backbone": "~1.2.1"
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/vendor/strengthify/.bower.json b/core/vendor/strengthify/.bower.json
index b86b43f17b7..d0baec6ed73 100644
--- a/core/vendor/strengthify/.bower.json
+++ b/core/vendor/strengthify/.bower.json
@@ -1,6 +1,6 @@
{
"name": "strengthify",
- "version": "0.4.1",
+ "version": "0.4.2",
"homepage": "https://github.com/MorrisJobke/strengthify",
"authors": [
"Morris Jobke <hey@morrisjobke.de>"
@@ -8,13 +8,13 @@
"description": "Combine jQuery and zxcvbn to create a password strength meter.",
"main": "jquery.strengthify.js",
"license": "MIT",
- "_release": "0.4.1",
+ "_release": "0.4.2",
"_resolution": {
"type": "version",
- "tag": "0.4.1",
- "commit": "fe9d1c80156d3fcdd16434ebc789007d045c1d1f"
+ "tag": "v0.4.2",
+ "commit": "b3df9344d829063564cdced3c6328b001bc4bad1"
},
"_source": "git://github.com/MorrisJobke/strengthify.git",
- "_target": "0.4.1",
+ "_target": "0.4.2",
"_originalSource": "strengthify"
} \ No newline at end of file
diff --git a/core/vendor/strengthify/LICENSE b/core/vendor/strengthify/LICENSE
index 3c04738f789..b249b595978 100644
--- a/core/vendor/strengthify/LICENSE
+++ b/core/vendor/strengthify/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2013 Morris Jobke
+Copyright (c) 2013-2015 Morris Jobke
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
diff --git a/core/vendor/strengthify/jquery.strengthify.js b/core/vendor/strengthify/jquery.strengthify.js
index 4fcc4d7c7c4..26d06a5d301 100644
--- a/core/vendor/strengthify/jquery.strengthify.js
+++ b/core/vendor/strengthify/jquery.strengthify.js
@@ -1,15 +1,15 @@
/**
* Strengthify - show the weakness of a password (uses zxcvbn for this)
- * https://github.com/kabum/strengthify
+ * https://github.com/MorrisJobke/strengthify
*
- * Version: 0.4.1
- * Author: Morris Jobke (github.com/kabum)
+ * Version: 0.4.2
+ * Author: Morris Jobke (github.com/MorrisJobke)
*
* License:
*
* The MIT License (MIT)
*
- * Copyright (c) 2013 Morris Jobke <morris.jobke@gmail.com>
+ * Copyright (c) 2013-2015 Morris Jobke <morris.jobke@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
@@ -43,23 +43,9 @@
'Perfect'
]
},
- options = $.extend(defaults, paramOptions);
-
- // add elements
- $('.strengthify-wrapper')
- .append('<div class="strengthify-bg" />')
- .append('<div class="strengthify-container" />')
- .append('<div class="strengthify-separator" style="left: 25%" />')
- .append('<div class="strengthify-separator" style="left: 50%" />')
- .append('<div class="strengthify-separator" style="left: 75%" />');
-
- $.ajax({
- cache: true,
- dataType: 'script',
- url: options.zxcvbn
- }).done(function() {
- me.bind('keyup input change', function() {
- var password = $(this).val(),
+ options = $.extend(defaults, paramOptions),
+ drawStrengthify = function() {
+ var password = $(me).val(),
// hide strengthigy if no input is provided
opacity = (password === '') ? 0 : 1,
// calculate result
@@ -107,15 +93,15 @@
$wrapper.attr(
'title',
options.titles[result.score]
- ).tipsy({
+ ).tooltip({
+ placement: 'bottom',
trigger: 'manual',
- opacity: opacity
- }).tipsy(
+ }).tooltip(
'show'
);
if(opacity === 0) {
- $wrapper.tipsy(
+ $wrapper.tooltip(
'hide'
);
}
@@ -125,7 +111,24 @@
$container.css('width', 0);
}
- });
+ };
+
+ // add elements
+ $('.strengthify-wrapper')
+ .append('<div class="strengthify-bg" />')
+ .append('<div class="strengthify-container" />')
+ .append('<div class="strengthify-separator" style="left: 25%" />')
+ .append('<div class="strengthify-separator" style="left: 50%" />')
+ .append('<div class="strengthify-separator" style="left: 75%" />');
+
+ me.parents().on('scroll', drawStrengthify);
+
+ $.ajax({
+ cache: true,
+ dataType: 'script',
+ url: options.zxcvbn
+ }).done(function() {
+ me.bind('keyup input change', drawStrengthify);
});
return me;
diff --git a/core/vendor/strengthify/strengthify.css b/core/vendor/strengthify/strengthify.css
index 9340270ecfb..5555cbdf334 100644
--- a/core/vendor/strengthify/strengthify.css
+++ b/core/vendor/strengthify/strengthify.css
@@ -1,7 +1,7 @@
/**
* Strengthify - show the weakness of a password (uses zxcvbn for this)
- * https://github.com/kabum/strengthify
- * Version: 0.3
+ * https://github.com/MorrisJobke/strengthify
+ * Version: 0.4.2
* License: The MIT License (MIT)
* Copyright (c) 2013 Morris Jobke <morris.jobke@gmail.com>
*/
@@ -45,4 +45,4 @@
}
.password-good {
background-color: #3C3;
-} \ No newline at end of file
+}
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());