@@ -12,6 +12,9 @@ OC.L10N.register( | |||
"More comments..." : "Lisää kommentteja...", | |||
"Save" : "Tallenna", | |||
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}", | |||
"Error occurred while retrieving comment with id {id}" : "Virhe noutaessa kommenttia tunnisteella {id}", | |||
"Error occurred while updating comment with id {id}" : "Virhe päivittäessä kommenttia tunnisteella {id}", | |||
"Error occurred while posting comment" : "Virhe kommenttia lähettäessä", | |||
"{count} unread comments" : "{count} lukematonta kommenttia", | |||
"Comment" : "Kommentti", | |||
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>", |
@@ -10,6 +10,9 @@ | |||
"More comments..." : "Lisää kommentteja...", | |||
"Save" : "Tallenna", | |||
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}", | |||
"Error occurred while retrieving comment with id {id}" : "Virhe noutaessa kommenttia tunnisteella {id}", | |||
"Error occurred while updating comment with id {id}" : "Virhe päivittäessä kommenttia tunnisteella {id}", | |||
"Error occurred while posting comment" : "Virhe kommenttia lähettäessä", | |||
"{count} unread comments" : "{count} lukematonta kommenttia", | |||
"Comment" : "Kommentti", | |||
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>", |
@@ -12,6 +12,9 @@ OC.L10N.register( | |||
"More comments..." : "Więcej komentarzy...", | |||
"Save" : "Zapisz", | |||
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}", | |||
"Error occurred while retrieving comment with id {id}" : "W trakcie otrzymywania komentarza o identyfikatorze {id} wystąpił błąd.", | |||
"Error occurred while updating comment with id {id}" : "W trakcie aktualizacji komentarza o identyfikatorze {id} wystąpił błąd.", | |||
"Error occurred while posting comment" : "Podczas wysyłania komentarza wystąpił błąd", | |||
"{count} unread comments" : "{count} nieprzeczytanych komentarzy", | |||
"Comment" : "Komentarz", | |||
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>", |
@@ -10,6 +10,9 @@ | |||
"More comments..." : "Więcej komentarzy...", | |||
"Save" : "Zapisz", | |||
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}", | |||
"Error occurred while retrieving comment with id {id}" : "W trakcie otrzymywania komentarza o identyfikatorze {id} wystąpił błąd.", | |||
"Error occurred while updating comment with id {id}" : "W trakcie aktualizacji komentarza o identyfikatorze {id} wystąpił błąd.", | |||
"Error occurred while posting comment" : "Podczas wysyłania komentarza wystąpił błąd", | |||
"{count} unread comments" : "{count} nieprzeczytanych komentarzy", | |||
"Comment" : "Komentarz", | |||
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>", |
@@ -473,6 +473,8 @@ class FederatedShareProvider implements IShareProvider { | |||
$isOwner = false; | |||
$this->removeShareFromTable($share); | |||
// if the local user is the owner we can send the unShare request directly... | |||
if ($this->userManager->userExists($share->getShareOwner())) { | |||
$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken()); | |||
@@ -494,8 +496,6 @@ class FederatedShareProvider implements IShareProvider { | |||
} | |||
$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); | |||
} | |||
$this->removeShareFromTable($share); | |||
} | |||
/** |
@@ -2351,22 +2351,36 @@ | |||
* @param filter | |||
*/ | |||
setFilter:function(filter) { | |||
var total = 0; | |||
this._filter = filter; | |||
this.fileSummary.setFilter(filter, this.files); | |||
total = this.fileSummary.getTotal(); | |||
if (!this.$el.find('.mask').exists()) { | |||
this.hideIrrelevantUIWhenNoFilesMatch(); | |||
} | |||
var that = this; | |||
var visibleCount = 0; | |||
filter = filter.toLowerCase(); | |||
this.$fileList.find('tr').each(function(i,e) { | |||
var $e = $(e); | |||
function filterRows(tr) { | |||
var $e = $(tr); | |||
if ($e.data('file').toString().toLowerCase().indexOf(filter) === -1) { | |||
$e.addClass('hidden'); | |||
} else { | |||
visibleCount++; | |||
$e.removeClass('hidden'); | |||
} | |||
}); | |||
that.$container.trigger('scroll'); | |||
} | |||
var $trs = this.$fileList.find('tr'); | |||
do { | |||
_.each($trs, filterRows); | |||
if (visibleCount < total) { | |||
$trs = this._nextPage(false); | |||
} | |||
} while (visibleCount < total); | |||
this.$container.trigger('scroll'); | |||
}, | |||
hideIrrelevantUIWhenNoFilesMatch:function() { | |||
if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) { |
@@ -989,6 +989,17 @@ describe('OCA.Files.FileList tests', function() { | |||
expect($summary.find('.info').text()).toEqual("1 folder and 3 files"); | |||
expect($nofilterresults.hasClass('hidden')).toEqual(true); | |||
}); | |||
it('filters the list of non-rendered rows using filter()', function() { | |||
var $summary = $('#filestable .summary'); | |||
var $nofilterresults = fileList.$el.find(".nofilterresults"); | |||
fileList.setFiles(generateFiles(0, 64)); | |||
fileList.setFilter('63'); | |||
expect($('#fileList tr:not(.hidden)').length).toEqual(1); | |||
expect($summary.hasClass('hidden')).toEqual(false); | |||
expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches '63'"); | |||
expect($nofilterresults.hasClass('hidden')).toEqual(true); | |||
}); | |||
it('hides the emptyfiles notice when using filter()', function() { | |||
expect(fileList.files.length).toEqual(0); | |||
expect(fileList.files).toEqual([]); |
@@ -52,6 +52,10 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide | |||
$backendService->registerBackendProvider($this); | |||
$backendService->registerAuthMechanismProvider($this); | |||
// force-load auth mechanisms since some will register hooks | |||
// TODO: obsolete these and use the TokenProvider to get the user's password from the session | |||
$this->getAuthMechanisms(); | |||
// app developers: do NOT depend on this! it will disappear with oC 9.0! | |||
\OC::$server->getEventDispatcher()->dispatch( | |||
'OCA\\Files_External::loadAdditionalBackends' |
@@ -354,7 +354,8 @@ class Share20OCS { | |||
$share->setPermissions( | |||
\OCP\Constants::PERMISSION_READ | | |||
\OCP\Constants::PERMISSION_CREATE | | |||
\OCP\Constants::PERMISSION_UPDATE | |||
\OCP\Constants::PERMISSION_UPDATE | | |||
\OCP\Constants::PERMISSION_DELETE | |||
); | |||
} else { | |||
$share->setPermissions(\OCP\Constants::PERMISSION_READ); | |||
@@ -591,7 +592,7 @@ class Share20OCS { | |||
$newPermissions = null; | |||
if ($publicUpload === 'true') { | |||
$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; | |||
$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; | |||
} else if ($publicUpload === 'false') { | |||
$newPermissions = \OCP\Constants::PERMISSION_READ; | |||
} | |||
@@ -602,13 +603,21 @@ class Share20OCS { | |||
if ($newPermissions !== null && | |||
$newPermissions !== \OCP\Constants::PERMISSION_READ && | |||
$newPermissions !== (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) && | |||
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { | |||
// legacy | |||
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) && | |||
// correct | |||
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) | |||
) { | |||
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); | |||
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); | |||
} | |||
if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { | |||
if ( | |||
// legacy | |||
$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) || | |||
// correct | |||
$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) | |||
) { | |||
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { | |||
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); | |||
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); | |||
@@ -618,6 +627,9 @@ class Share20OCS { | |||
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); | |||
return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); | |||
} | |||
// normalize to correct public upload permissions | |||
$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; | |||
} | |||
if ($newPermissions !== null) { |
@@ -1035,7 +1035,7 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->callback(function (\OCP\Share\IShare $share) use ($path) { | |||
return $share->getNode() === $path && | |||
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && | |||
$share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && | |||
$share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && | |||
$share->getSharedBy() === 'currentUser' && | |||
$share->getPassword() === null && | |||
$share->getExpirationDate() === null; | |||
@@ -1366,7 +1366,7 @@ class Share20OCSTest extends \Test\TestCase { | |||
$date = new \DateTime('2000-01-01'); | |||
$date->setTime(0,0,0); | |||
return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE && \OCP\Constants::PERMISSION_DELETE && | |||
return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && | |||
$share->getPassword() === 'password' && | |||
$share->getExpirationDate() == $date; | |||
}) | |||
@@ -1379,6 +1379,44 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->assertEquals($expected->getData(), $result->getData()); | |||
} | |||
/** | |||
* @dataProvider publicUploadParamsProvider | |||
*/ | |||
public function testUpdateLinkShareEnablePublicUpload($params) { | |||
$ocs = $this->mockFormatShare(); | |||
$folder = $this->getMock('\OCP\Files\Folder'); | |||
$share = \OC::$server->getShareManager()->newShare(); | |||
$share->setPermissions(\OCP\Constants::PERMISSION_ALL) | |||
->setSharedBy($this->currentUser->getUID()) | |||
->setShareType(\OCP\Share::SHARE_TYPE_LINK) | |||
->setPassword('password') | |||
->setNode($folder); | |||
$this->request | |||
->method('getParam') | |||
->will($this->returnValueMap($params)); | |||
$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); | |||
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); | |||
$this->shareManager->method('getSharedWith')->willReturn([]); | |||
$this->shareManager->expects($this->once())->method('updateShare')->with( | |||
$this->callback(function (\OCP\Share\IShare $share) { | |||
return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && | |||
$share->getPassword() === 'password' && | |||
$share->getExpirationDate() === null; | |||
}) | |||
)->will($this->returnArgument(0)); | |||
$expected = new \OC_OCS_Result(null); | |||
$result = $ocs->updateShare(42); | |||
$this->assertEquals($expected->getMeta(), $result->getMeta()); | |||
$this->assertEquals($expected->getData(), $result->getData()); | |||
} | |||
public function testUpdateLinkShareInvalidDate() { | |||
$ocs = $this->mockFormatShare(); | |||
@@ -1408,7 +1446,30 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->assertEquals($expected->getData(), $result->getData()); | |||
} | |||
public function testUpdateLinkSharePublicUploadNotAllowed() { | |||
public function publicUploadParamsProvider() { | |||
return [ | |||
[[ | |||
['publicUpload', null, 'true'], | |||
['expireDate', '', null], | |||
['password', '', 'password'], | |||
]], [[ | |||
// legacy had no delete | |||
['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE], | |||
['expireDate', '', null], | |||
['password', '', 'password'], | |||
]], [[ | |||
// correct | |||
['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE], | |||
['expireDate', '', null], | |||
['password', '', 'password'], | |||
]], | |||
]; | |||
} | |||
/** | |||
* @dataProvider publicUploadParamsProvider | |||
*/ | |||
public function testUpdateLinkSharePublicUploadNotAllowed($params) { | |||
$ocs = $this->mockFormatShare(); | |||
$folder = $this->getMock('\OCP\Files\Folder'); | |||
@@ -1421,11 +1482,7 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->request | |||
->method('getParam') | |||
->will($this->returnValueMap([ | |||
['publicUpload', null, 'true'], | |||
['expireDate', '', null], | |||
['password', '', 'password'], | |||
])); | |||
->will($this->returnValueMap($params)); | |||
$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); | |||
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false); | |||
@@ -1585,7 +1642,7 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->shareManager->expects($this->once())->method('updateShare')->with( | |||
$this->callback(function (\OCP\Share\IShare $share) use ($date) { | |||
return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && | |||
return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && | |||
$share->getPassword() === 'password' && | |||
$share->getExpirationDate() === $date; | |||
}) | |||
@@ -1625,7 +1682,7 @@ class Share20OCSTest extends \Test\TestCase { | |||
$this->shareManager->expects($this->once())->method('updateShare')->with( | |||
$this->callback(function (\OCP\Share\IShare $share) use ($date) { | |||
return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && | |||
return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && | |||
$share->getPassword() === 'password' && | |||
$share->getExpirationDate() === $date; | |||
}) |
@@ -257,7 +257,13 @@ class ApiTest extends TestCase { | |||
$this->assertTrue($result->succeeded()); | |||
$data = $result->getData(); | |||
$this->assertEquals(7, $data['permissions']); | |||
$this->assertEquals( | |||
\OCP\Constants::PERMISSION_READ | | |||
\OCP\Constants::PERMISSION_CREATE | | |||
\OCP\Constants::PERMISSION_UPDATE | | |||
\OCP\Constants::PERMISSION_DELETE, | |||
$data['permissions'] | |||
); | |||
$this->assertEmpty($data['expiration']); | |||
$this->assertTrue(is_string($data['token'])); | |||
@@ -1081,7 +1087,13 @@ class ApiTest extends TestCase { | |||
$this->assertTrue($result->succeeded()); | |||
$share1 = $this->shareManager->getShareById($share1->getFullId()); | |||
$this->assertEquals(7, $share1->getPermissions()); | |||
$this->assertEquals( | |||
\OCP\Constants::PERMISSION_READ | | |||
\OCP\Constants::PERMISSION_CREATE | | |||
\OCP\Constants::PERMISSION_UPDATE | | |||
\OCP\Constants::PERMISSION_DELETE, | |||
$share1->getPermissions() | |||
); | |||
// cleanup | |||
$this->shareManager->deleteShare($share1); |
@@ -14,6 +14,7 @@ OC.L10N.register( | |||
"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s", | |||
"%1$s assigned system tag %3$s to %2$s" : "%1$s przypisywalny system etykiet%3$s do %2$s", | |||
"%1$s unassigned system tag %3$s from %2$s" : "%1$s nieprzypisany system etykiet %3$s z %2$s", | |||
"%s (restricted)" : "%s (ograniczone)", | |||
"%s (invisible)" : "%s (niewidoczny)", | |||
"No files in here" : "Brak plików", | |||
"No entries found in this folder" : "Brak wpisów w tym folderze", |
@@ -12,6 +12,7 @@ | |||
"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s", | |||
"%1$s assigned system tag %3$s to %2$s" : "%1$s przypisywalny system etykiet%3$s do %2$s", | |||
"%1$s unassigned system tag %3$s from %2$s" : "%1$s nieprzypisany system etykiet %3$s z %2$s", | |||
"%s (restricted)" : "%s (ograniczone)", | |||
"%s (invisible)" : "%s (niewidoczny)", | |||
"No files in here" : "Brak plików", | |||
"No entries found in this folder" : "Brak wpisów w tym folderze", |
@@ -61,7 +61,7 @@ Feature: sharing | |||
And the HTTP status code should be "200" | |||
And Share fields of last share match with | |||
| id | A_NUMBER | | |||
| permissions | 7 | | |||
| permissions | 15 | | |||
| expiration | +3 days | | |||
| url | AN_URL | | |||
| token | A_TOKEN | | |||
@@ -159,7 +159,7 @@ Feature: sharing | |||
| share_type | 3 | | |||
| file_source | A_NUMBER | | |||
| file_target | /FOLDER | | |||
| permissions | 7 | | |||
| permissions | 15 | | |||
| stime | A_NUMBER | | |||
| token | A_TOKEN | | |||
| storage | A_NUMBER | | |||
@@ -189,7 +189,7 @@ Feature: sharing | |||
| share_type | 3 | | |||
| file_source | A_NUMBER | | |||
| file_target | /FOLDER | | |||
| permissions | 7 | | |||
| permissions | 15 | | |||
| stime | A_NUMBER | | |||
| token | A_TOKEN | | |||
| storage | A_NUMBER | |
@@ -150,6 +150,9 @@ class DecryptAll extends Command { | |||
$output->writeln(' aborted.'); | |||
$output->writeln('Server side encryption remains enabled'); | |||
$this->config->setAppValue('core', 'encryption_enabled', 'yes'); | |||
} else if ($uid !== '') { | |||
$output->writeln('Server side encryption remains enabled'); | |||
$this->config->setAppValue('core', 'encryption_enabled', 'yes'); | |||
} | |||
$this->resetSingleUserAndTrashbin(); | |||
} else { |
@@ -162,7 +162,6 @@ | |||
text-overflow: ellipsis; | |||
overflow: hidden; | |||
display: inline-block; | |||
width: 201px; /* fallback for IE8 */ | |||
width: calc(100% - 49px); | |||
line-height: 44px; | |||
float: left; | |||
@@ -309,12 +308,6 @@ | |||
.edge #app-navigation .app-navigation-entry-menu:after { | |||
border: 1px solid #eee; | |||
} | |||
.ie8 .bubble { | |||
margin-top: 18px; | |||
} | |||
.ie8 .bubble:after { | |||
display: none; | |||
} | |||
/* miraculous border arrow stuff */ | |||
.bubble:after, | |||
#app-navigation .app-navigation-entry-menu:after { | |||
@@ -392,7 +385,6 @@ | |||
#app-navigation .app-navigation-entry-edit input { | |||
border-bottom-right-radius: 0; | |||
border-top-right-radius: 0; | |||
width: 204px; /* fallback for IE8 */ | |||
width: calc(100% - 36px); | |||
padding: 5px; | |||
margin-right: 0; |
@@ -10,125 +10,9 @@ select { | |||
height: 32px; | |||
} | |||
/* reset typeface for IE8 because OpenSans renders too small */ | |||
.ie8 body { | |||
font-family: Frutiger, Calibri, 'Myriad Pro', Myriad, Arial, sans-serif; | |||
} | |||
.lte8 .icon-delete { background-image: url('../img/actions/delete.png'); } | |||
.lte8 .icon-delete:hover, .icon-delete:focus { | |||
background-image: url('../img/actions/delete-hover.png'); | |||
} | |||
.ie8 .icon-checkmark { | |||
background-image: url('../img/actions/checkmark.png'); | |||
} | |||
.ie8 .icon-close { | |||
background-image: url('../img/actions/close.png'); | |||
} | |||
.lte9 .icon-triangle-e { | |||
background-image: url('../img/actions/triangle-e.png'); | |||
} | |||
.lte9 .icon-triangle-n { | |||
background-image: url('../img/actions/triangle-n.png'); | |||
} | |||
.lte9 .icon-triangle-s { | |||
background-image: url('../img/actions/triangle-s.png'); | |||
} | |||
.lte9 .icon-settings, | |||
.lte9 .settings-button { | |||
background-image: url('../img/actions/settings.png'); | |||
} | |||
.lte9 input[type="submit"], .lte9 input[type="button"], | |||
.lte9 button, .lte9 .button, | |||
.lte9 #quota, .lte9 select, .lte9 .pager li a { | |||
background-color: #f1f1f1; | |||
} | |||
/* IE8 needs PNG image for header logo */ | |||
.ie8 #header .logo { | |||
background-image: url(../img/logo-icon-175px.png); | |||
} | |||
/* IE8 needs background to be set to same color to make transparency look good. */ | |||
.lte9 #body-login form input[type="text"] { | |||
border: 1px solid lightgrey; /* use border to add 1px line between input fields */ | |||
background-color: white; /* don't change background on hover */ | |||
} | |||
.lte9 #body-login form input[type="password"] { | |||
/* leave out top border for 1px line between input fields*/ | |||
border-left: 1px solid lightgrey; | |||
border-right: 1px solid lightgrey; | |||
border-bottom: 1px solid lightgrey; | |||
background-color: white; /* don't change background on hover */ | |||
} | |||
.ie8 #body-login input[type="submit"] { | |||
padding: 10px 5px; | |||
margin-top: 3px; | |||
} | |||
/* for whatever unexplained reason */ | |||
.ie8 #password { | |||
width: 271px !important; | |||
min-width: auto !important; | |||
} | |||
/* disable opacity of info text on gradient | |||
since we cannot set a good backround color to use the filter&background hack as with the input labels */ | |||
.lte9 #body-login p.info { | |||
filter: initial; | |||
} | |||
/* deactivate show password toggle for IE. Does not work for 8 and 9+ have their own implementation. */ | |||
.ie #show, .ie #show+label { | |||
display: none; | |||
visibility: hidden; | |||
} | |||
/* fix installation screen rendering issue for IE8+9 */ | |||
.lte9 #body-login { | |||
min-height: 100%; | |||
height: auto !important; | |||
} | |||
/* oc-dialog only uses box shadow which is not supported by ie8 */ | |||
.ie8 .oc-dialog { | |||
border: 1px solid #888888; | |||
} | |||
/* IE8 doesn't support transparent background - let's emulate black with an opacity of .3 on a dark blue background*/ | |||
.ie8 fieldset .warning, .ie8 #body-login .error { | |||
background-color: #1B314D; | |||
} | |||
/* IE8 isn't able to display transparent background. So it is specified using a gradient */ | |||
.ie8 #nojavascript { | |||
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#4c320000', endColorstr='#4c320000'); | |||
} | |||
/* fix background of navigation popup in IE8 */ | |||
.ie8 #navigation, | |||
.ie8 #expanddiv { | |||
background-color: #111; | |||
} | |||
/* needed else IE8 will randomly hide the borders... */ | |||
.ie8 table th#headerDate, table td.date, | |||
.ie8 table th.column-last, table td.column-last { | |||
position: static; | |||
} | |||
.ie8 #controls { | |||
background-color: white; | |||
} | |||
.ie8 #content-wrapper { | |||
overflow-y: auto; | |||
} | |||
.ie8 #app-navigation .app-navigation-entry-edit input { | |||
line-height: 38px; | |||
} | |||
@@ -111,10 +111,3 @@ ul.multiselectoptions > li.creator > input { | |||
padding: 5px; | |||
margin: -5px; | |||
} | |||
.ie8 div.multiselect span:first-child { | |||
display:block; | |||
position:relative; | |||
width: 90%; | |||
margin-right:-1px; | |||
} |
@@ -189,7 +189,6 @@ a.two-factor-cancel { | |||
.emptycontent { | |||
color: #888; | |||
text-align: center; | |||
margin-top: 100px; /* ie8 */ | |||
margin-top: 30vh; | |||
width: 100%; | |||
} | |||
@@ -418,14 +417,7 @@ label.infield { | |||
-ms-user-select: none; | |||
user-select: none; | |||
} | |||
html.ie8 #body-login form input[type="checkbox"]+label { | |||
margin-left: -28px; | |||
margin-top: -3px; | |||
vertical-align: auto; | |||
} | |||
html.ie8 #body-login form input[type="checkbox"] { | |||
margin-top: 5px; | |||
} | |||
#body-login form .errors { background:#fed7d7; border:1px solid #f00; list-style-indent:inside; margin:0 0 2em; padding:1em; } | |||
#body-login .success { background:#d7fed7; border:1px solid #0f0; width: 35%; margin: 30px auto; padding:1em; text-align: center;} | |||
@@ -788,7 +788,6 @@ var OC={ | |||
$(document).trigger(new $.Event('ajaxError'), xhr); | |||
}; | |||
// FIXME: also needs an IE8 way | |||
if (xhr.addEventListener) { | |||
xhr.addEventListener('load', loadCallback); | |||
xhr.addEventListener('error', errorCallback); | |||
@@ -1857,30 +1856,10 @@ OC.Util = { | |||
* This scales the image to the element's actual size, the URL is | |||
* taken from the "background-image" CSS attribute. | |||
* | |||
* @deprecated IE8 isn't supported since 9.0 | |||
* @param {Object} $el image element | |||
*/ | |||
scaleFixForIE8: function($el) { | |||
if (!this.isIE8()) { | |||
return; | |||
} | |||
var self = this; | |||
$($el).each(function() { | |||
var url = $(this).css('background-image'); | |||
var r = url.match(/url\(['"]?([^'")]*)['"]?\)/); | |||
if (!r) { | |||
return; | |||
} | |||
url = r[1]; | |||
url = self.replaceSVGIcon(url); | |||
// TODO: escape | |||
url = url.replace(/'/g, '%27'); | |||
$(this).css({ | |||
'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + url + '\', sizingMethod=\'scale\')', | |||
'background-image': '' | |||
}); | |||
}); | |||
return $el; | |||
}, | |||
scaleFixForIE8: function($el) {}, | |||
/** | |||
* Returns whether this is IE | |||
@@ -1894,10 +1873,11 @@ OC.Util = { | |||
/** | |||
* Returns whether this is IE8 | |||
* | |||
* @return {bool} true if this is IE8, false otherwise | |||
* @deprecated IE8 isn't supported since 9.0 | |||
* @return {bool} false (IE8 isn't supported anymore) | |||
*/ | |||
isIE8: function() { | |||
return $('html').hasClass('ie8'); | |||
return false; | |||
}, | |||
/** |
@@ -215,7 +215,7 @@ | |||
var permissions = OC.PERMISSION_READ; | |||
if($checkbox.is(':checked')) { | |||
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ; | |||
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE; | |||
} | |||
this.model.saveLinkShare({ |
@@ -166,9 +166,13 @@ OC.L10N.register( | |||
"delete" : "usuń", | |||
"access control" : "kontrola dostępu", | |||
"Could not unshare" : "Nie udało się usunąć udostępnienia", | |||
"Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.", | |||
"No users or groups found for {search}" : "Nie znaleziono użytkowników lub grup dla {search}", | |||
"No users found for {search}" : "Nie znaleziono użytkowników dla {search}", | |||
"An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.", | |||
"{sharee} (group)" : "{sharee} (grupa)", | |||
"{sharee} (at {server})" : "{sharee} (na {server})", | |||
"{sharee} (remote)" : "{sharee} (zdalny)", | |||
"Share" : "Udostępnij", | |||
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Współdziel z użytkownikami innych chmur ownCloud używając wzorca uzytkownik@example.com/owncloud", | |||
"Share with users…" : "Współdziel z użytkownikami...", | |||
@@ -181,6 +185,7 @@ OC.L10N.register( | |||
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje", | |||
"restricted" : "ograniczone", | |||
"invisible" : "niewidoczny", | |||
"({scope})" : "({scope})", | |||
"Delete" : "Usuń", | |||
"Rename" : "Zmień nazwę", | |||
"The object type is not specified." : "Nie określono typu obiektu.", | |||
@@ -237,6 +242,7 @@ OC.L10N.register( | |||
"Data folder" : "Katalog danych", | |||
"Configure the database" : "Skonfiguruj bazę danych", | |||
"Only %s is available." : "Dostępne jest wyłącznie %s.", | |||
"Install and activate additional PHP modules to choose other database types." : "Zainstaluj lub aktywuj dodatkowe moduły PHP, aby uzyskać możliwość wyboru innych typów baz danych.", | |||
"For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.", | |||
"Database user" : "Użytkownik bazy danych", | |||
"Database password" : "Hasło do bazy danych", | |||
@@ -289,6 +295,7 @@ OC.L10N.register( | |||
"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Aby uniknąć timeout-ów przy większych instalacjach, możesz zamiast tego uruchomić następującą komendę w katalogu Twojej instalacji:", | |||
"Detailed logs" : "Szczegółowe logi", | |||
"Update needed" : "Wymagana aktualizacja", | |||
"Please use the command line updater because you have a big instance." : "Ze względu na rozmiar Twojej instalacji użyj programu do aktualizacji z linii poleceń.", | |||
"For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Aby uzyskać pomoc, zajrzyj do <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji</a>.", | |||
"This page will refresh itself when the %s instance is available again." : "Strona odświeży się gdy instancja %s będzie ponownie dostępna." | |||
}, |
@@ -164,9 +164,13 @@ | |||
"delete" : "usuń", | |||
"access control" : "kontrola dostępu", | |||
"Could not unshare" : "Nie udało się usunąć udostępnienia", | |||
"Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.", | |||
"No users or groups found for {search}" : "Nie znaleziono użytkowników lub grup dla {search}", | |||
"No users found for {search}" : "Nie znaleziono użytkowników dla {search}", | |||
"An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.", | |||
"{sharee} (group)" : "{sharee} (grupa)", | |||
"{sharee} (at {server})" : "{sharee} (na {server})", | |||
"{sharee} (remote)" : "{sharee} (zdalny)", | |||
"Share" : "Udostępnij", | |||
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Współdziel z użytkownikami innych chmur ownCloud używając wzorca uzytkownik@example.com/owncloud", | |||
"Share with users…" : "Współdziel z użytkownikami...", | |||
@@ -179,6 +183,7 @@ | |||
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje", | |||
"restricted" : "ograniczone", | |||
"invisible" : "niewidoczny", | |||
"({scope})" : "({scope})", | |||
"Delete" : "Usuń", | |||
"Rename" : "Zmień nazwę", | |||
"The object type is not specified." : "Nie określono typu obiektu.", | |||
@@ -235,6 +240,7 @@ | |||
"Data folder" : "Katalog danych", | |||
"Configure the database" : "Skonfiguruj bazę danych", | |||
"Only %s is available." : "Dostępne jest wyłącznie %s.", | |||
"Install and activate additional PHP modules to choose other database types." : "Zainstaluj lub aktywuj dodatkowe moduły PHP, aby uzyskać możliwość wyboru innych typów baz danych.", | |||
"For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.", | |||
"Database user" : "Użytkownik bazy danych", | |||
"Database password" : "Hasło do bazy danych", | |||
@@ -287,6 +293,7 @@ | |||
"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Aby uniknąć timeout-ów przy większych instalacjach, możesz zamiast tego uruchomić następującą komendę w katalogu Twojej instalacji:", | |||
"Detailed logs" : "Szczegółowe logi", | |||
"Update needed" : "Wymagana aktualizacja", | |||
"Please use the command line updater because you have a big instance." : "Ze względu na rozmiar Twojej instalacji użyj programu do aktualizacji z linii poleceń.", | |||
"For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Aby uzyskać pomoc, zajrzyj do <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji</a>.", | |||
"This page will refresh itself when the %s instance is available again." : "Strona odświeży się gdy instancja %s będzie ponownie dostępna." | |||
},"pluralForm" :"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" |
@@ -1,7 +1,5 @@ | |||
<!DOCTYPE html> | |||
<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]--> | |||
<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" > | |||
<head data-requesttoken="<?php p($_['requesttoken']); ?>"> | |||
<meta charset="utf-8"> | |||
<title> |
@@ -1,7 +1,5 @@ | |||
<!DOCTYPE html> | |||
<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]--> | |||
<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" > | |||
<head data-requesttoken="<?php p($_['requesttoken']); ?>"> | |||
<meta charset="utf-8"> | |||
<title> |
@@ -1,7 +1,5 @@ | |||
<!DOCTYPE html> | |||
<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]--> | |||
<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]--> | |||
<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" > | |||
<head data-user="<?php p($_['user_uid']); ?>" data-user-displayname="<?php p($_['user_displayname']); ?>" data-requesttoken="<?php p($_['requesttoken']); ?>"> | |||
<meta charset="utf-8"> | |||
<title> |
@@ -108,7 +108,11 @@ class Checker { | |||
* applicable for very specific scenarios and we should not advertise it | |||
* too prominent. So please do not add it to config.sample.php. | |||
*/ | |||
$isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false); | |||
if ($this->config !== null) { | |||
$isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false); | |||
} else { | |||
$isIntegrityCheckDisabled = false; | |||
} | |||
if($isIntegrityCheckDisabled === true) { | |||
return false; | |||
} | |||
@@ -401,7 +405,10 @@ class Checker { | |||
return json_decode($cachedResults, true); | |||
} | |||
return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true); | |||
if ($this->config !== null) { | |||
return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true); | |||
} | |||
return []; | |||
} | |||
/** | |||
@@ -416,7 +423,9 @@ class Checker { | |||
if(!empty($result)) { | |||
$resultArray[$scope] = $result; | |||
} | |||
$this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray)); | |||
if ($this->config !== null) { | |||
$this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray)); | |||
} | |||
$this->cache->set(self::CACHE_KEY, json_encode($resultArray)); | |||
} | |||
@@ -71,6 +71,25 @@ class RepairInvalidShares implements IRepairStep { | |||
} | |||
} | |||
/** | |||
* In the past link shares with public upload enabled were missing the delete permission. | |||
*/ | |||
private function addShareLinkDeletePermission(IOutput $out) { | |||
$oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; | |||
$newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; | |||
$builder = $this->connection->getQueryBuilder(); | |||
$builder | |||
->update('share') | |||
->set('permissions', $builder->expr()->literal($newPerms)) | |||
->where($builder->expr()->eq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK))) | |||
->andWhere($builder->expr()->eq('permissions', $builder->expr()->literal($oldPerms))); | |||
$updatedEntries = $builder->execute(); | |||
if ($updatedEntries > 0) { | |||
$out->info('Fixed link share permissions for ' . $updatedEntries . ' shares'); | |||
} | |||
} | |||
/** | |||
* Remove shares where the parent share does not exist anymore | |||
*/ | |||
@@ -113,6 +132,10 @@ class RepairInvalidShares implements IRepairStep { | |||
// this situation was only possible before 8.2 | |||
$this->removeExpirationDateFromNonLinkShares($out); | |||
} | |||
if (version_compare($ocVersionFromBeforeUpdate, '9.1.0.9', '<')) { | |||
// this situation was only possible before 9.1 | |||
$this->addShareLinkDeletePermission($out); | |||
} | |||
$this->removeSharesNonExistingParent($out); | |||
} |
@@ -452,14 +452,9 @@ class Manager implements IManager { | |||
throw new \InvalidArgumentException('Link shares can\'t have reshare permissions'); | |||
} | |||
// We don't allow deletion on link shares | |||
if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) { | |||
throw new \InvalidArgumentException('Link shares can\'t have delete permissions'); | |||
} | |||
// Check if public upload is allowed | |||
if (!$this->shareApiLinkAllowPublicUpload() && | |||
($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE))) { | |||
($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) { | |||
throw new \InvalidArgumentException('Public upload not allowed'); | |||
} | |||
} |
@@ -280,7 +280,7 @@ class Session implements IUserSession, Emitter { | |||
*/ | |||
public function login($uid, $password) { | |||
$this->session->regenerateId(); | |||
if ($this->validateToken($password)) { | |||
if ($this->validateToken($password, $uid)) { | |||
// When logging in with token, the password must be decrypted first before passing to login hook | |||
try { | |||
$token = $this->tokenProvider->getToken($password); | |||
@@ -584,15 +584,24 @@ class Session implements IUserSession, Emitter { | |||
* Invalidates the token if checks fail | |||
* | |||
* @param string $token | |||
* @param string $user login name | |||
* @return boolean | |||
*/ | |||
private function validateToken($token) { | |||
private function validateToken($token, $user = null) { | |||
try { | |||
$dbToken = $this->tokenProvider->getToken($token); | |||
} catch (InvalidTokenException $ex) { | |||
return false; | |||
} | |||
// Check if login names match | |||
if (!is_null($user) && $dbToken->getLoginName() !== $user) { | |||
// TODO: this makes it imposssible to use different login names on browser and client | |||
// e.g. login by e-mail 'user@example.com' on browser for generating the token will not | |||
// allow to use the client token with the login name 'user'. | |||
return false; | |||
} | |||
if (!$this->checkTokenCredentials($dbToken, $token)) { | |||
return false; | |||
} |
@@ -118,6 +118,7 @@ class AuthSettingsController extends Controller { | |||
return [ | |||
'token' => $token, | |||
'loginName' => $loginName, | |||
'deviceToken' => $deviceToken | |||
]; | |||
} |
@@ -131,11 +131,19 @@ table.nostyle td { padding: 0.2em 0; } | |||
opacity: 0.6; | |||
} | |||
#new-app-login-name, | |||
#new-app-password { | |||
width: 186px; | |||
font-family: monospace; | |||
background-color: lightyellow; | |||
} | |||
.app-password-row { | |||
display: table-row; | |||
} | |||
.app-password-label { | |||
display: table-cell; | |||
padding-right: 1em; | |||
} | |||
/* USERS */ | |||
#newgroup-init a span { margin-left: 20px; } | |||
@@ -161,10 +169,6 @@ table.nostyle td { padding: 0.2em 0; } | |||
width: 32px; | |||
} | |||
.ie8 #newgroup-form .icon-add { | |||
height: 30px; | |||
} | |||
.isgroup .groupname { | |||
width: 85%; | |||
display: block; | |||
@@ -281,10 +285,6 @@ input.userFilter {width: 200px;} | |||
width: 32px; | |||
} | |||
.ie8 table.hascontrols{border-collapse:collapse;width: 100%;} | |||
.ie8 table.hascontrols tbody tr{border-collapse:collapse;border: 1px solid #ddd !important;} | |||
/* used to highlight a user row in red */ | |||
#userlist tr.row-warning { | |||
background-color: #FDD; |
@@ -20,14 +20,14 @@ | |||
* | |||
*/ | |||
(function(OC, Backbone) { | |||
(function(OC) { | |||
'use strict'; | |||
OC.Settings = OC.Settings || {}; | |||
var AuthToken = Backbone.Model.extend({ | |||
var AuthToken = OC.Backbone.Model.extend({ | |||
}); | |||
OC.Settings.AuthToken = AuthToken; | |||
})(OC, Backbone); | |||
})(OC); |
@@ -20,12 +20,12 @@ | |||
* | |||
*/ | |||
(function(OC, Backbone) { | |||
(function(OC) { | |||
'use strict'; | |||
OC.Settings = OC.Settings || {}; | |||
var AuthTokenCollection = Backbone.Collection.extend({ | |||
var AuthTokenCollection = OC.Backbone.Collection.extend({ | |||
model: OC.Settings.AuthToken, | |||
@@ -49,4 +49,4 @@ | |||
OC.Settings.AuthTokenCollection = AuthTokenCollection; | |||
})(OC, Backbone); | |||
})(OC); |
@@ -1,4 +1,4 @@ | |||
/* global Backbone, Handlebars, moment */ | |||
/* global Handlebars, moment */ | |||
/** | |||
* @author Christoph Wurst <christoph@owncloud.com> | |||
@@ -20,7 +20,7 @@ | |||
* | |||
*/ | |||
(function(OC, _, Backbone, $, Handlebars, moment) { | |||
(function(OC, _, $, Handlebars, moment) { | |||
'use strict'; | |||
OC.Settings = OC.Settings || {}; | |||
@@ -32,7 +32,7 @@ | |||
+ '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>' | |||
+ '<tr>'; | |||
var SubView = Backbone.View.extend({ | |||
var SubView = OC.Backbone.View.extend({ | |||
collection: null, | |||
/** | |||
@@ -94,7 +94,7 @@ | |||
} | |||
}); | |||
var AuthTokenView = Backbone.View.extend({ | |||
var AuthTokenView = OC.Backbone.View.extend({ | |||
collection: null, | |||
_views: [], | |||
@@ -107,6 +107,8 @@ | |||
_result: undefined, | |||
_newAppLoginName: undefined, | |||
_newAppPassword: undefined, | |||
_hideAppPasswordBtn: undefined, | |||
@@ -136,6 +138,8 @@ | |||
this._addAppPasswordBtn.click(_.bind(this._addAppPassword, this)); | |||
this._result = $('#app-password-result'); | |||
this._newAppLoginName = $('#new-app-login-name'); | |||
this._newAppLoginName.on('focus', _.bind(this._onNewTokenLoginNameFocus, this)); | |||
this._newAppPassword = $('#new-app-password'); | |||
this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this)); | |||
this._hideAppPasswordBtn = $('#app-password-hide'); | |||
@@ -181,6 +185,7 @@ | |||
$.when(creatingToken).done(function(resp) { | |||
_this.collection.add(resp.deviceToken); | |||
_this.render(); | |||
_this._newAppLoginName.val(resp.loginName); | |||
_this._newAppPassword.val(resp.token); | |||
_this._toggleFormResult(false); | |||
_this._newAppPassword.select(); | |||
@@ -194,6 +199,10 @@ | |||
}); | |||
}, | |||
_onNewTokenLoginNameFocus: function() { | |||
this._newAppLoginName.select(); | |||
}, | |||
_onNewTokenFocus: function() { | |||
this._newAppPassword.select(); | |||
}, | |||
@@ -220,6 +229,8 @@ | |||
var destroyingToken = token.destroy(); | |||
$row.find('.icon-delete').tooltip('hide'); | |||
var _this = this; | |||
$.when(destroyingToken).fail(function() { | |||
OC.Notification.showTemporary(t('core', 'Error while deleting the token')); | |||
@@ -237,4 +248,4 @@ | |||
OC.Settings.AuthTokenView = AuthTokenView; | |||
})(OC, _, Backbone, $, Handlebars, moment); | |||
})(OC, _, $, Handlebars, moment); |
@@ -28,6 +28,7 @@ OC.L10N.register( | |||
"Email saved" : "E-mail zapisany", | |||
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.", | |||
"Unable to change full name" : "Nie można zmienić pełnej nazwy", | |||
"Redis" : "Redis", | |||
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji", | |||
"Sharing" : "Udostępnianie", | |||
"Server-side encryption" : "Szyfrowanie po stronie serwera", | |||
@@ -48,6 +49,7 @@ OC.L10N.register( | |||
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.", | |||
"Migration started …" : "Migracja rozpoczęta...", | |||
"Sending..." : "Wysyłam...", | |||
"Experimental" : "Eksperymentalny", | |||
"All" : "Wszystkie", | |||
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji", | |||
"Update to %s" : "Uaktualnij do %s", |
@@ -26,6 +26,7 @@ | |||
"Email saved" : "E-mail zapisany", | |||
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.", | |||
"Unable to change full name" : "Nie można zmienić pełnej nazwy", | |||
"Redis" : "Redis", | |||
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji", | |||
"Sharing" : "Udostępnianie", | |||
"Server-side encryption" : "Szyfrowanie po stronie serwera", | |||
@@ -46,6 +47,7 @@ | |||
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.", | |||
"Migration started …" : "Migracja rozpoczęta...", | |||
"Sending..." : "Wysyłam...", | |||
"Experimental" : "Eksperymentalny", | |||
"All" : "Wszystkie", | |||
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji", | |||
"Update to %s" : "Uaktualnij do %s", |
@@ -201,8 +201,16 @@ if($_['passwordChangeSupported']) { | |||
<button id="add-app-password" class="button"><?php p($l->t('Create new app password')); ?></button> | |||
</div> | |||
<div id="app-password-result" class="hidden"> | |||
<input id="new-app-password" type="text" readonly="readonly"/> | |||
<button id="app-password-hide" class="button"><?php p($l->t('Done')); ?></button> | |||
<span><?php p($l->t('Use the credentials below to configure your app or device.')); ?></span> | |||
<div class="app-password-row"> | |||
<span class="app-password-label"><?php p($l->t('Username')); ?></span> | |||
<input id="new-app-login-name" type="text" readonly="readonly"/> | |||
</div> | |||
<div class="app-password-row"> | |||
<span class="app-password-label"><?php p($l->t('Password')); ?></span> | |||
<input id="new-app-password" type="text" readonly="readonly"/> | |||
<button id="app-password-hide" class="button"><?php p($l->t('Done')); ?></button> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -123,6 +123,93 @@ class RepairInvalidSharesTest extends TestCase { | |||
$this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there'); | |||
} | |||
/** | |||
* Test remove expiration date for non-link shares | |||
*/ | |||
public function testAddShareLinkDeletePermission() { | |||
$oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; | |||
$newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; | |||
// share with old permissions | |||
$qb = $this->connection->getQueryBuilder(); | |||
$qb->insert('share') | |||
->values([ | |||
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK), | |||
'uid_owner' => $qb->expr()->literal('user1'), | |||
'item_type' => $qb->expr()->literal('folder'), | |||
'item_source' => $qb->expr()->literal(123), | |||
'item_target' => $qb->expr()->literal('/123'), | |||
'file_source' => $qb->expr()->literal(123), | |||
'file_target' => $qb->expr()->literal('/test'), | |||
'permissions' => $qb->expr()->literal($oldPerms), | |||
'stime' => $qb->expr()->literal(time()), | |||
]) | |||
->execute(); | |||
$bogusShareId = $this->getLastShareId(); | |||
// share with read-only permissions | |||
$qb = $this->connection->getQueryBuilder(); | |||
$qb->insert('share') | |||
->values([ | |||
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK), | |||
'uid_owner' => $qb->expr()->literal('user1'), | |||
'item_type' => $qb->expr()->literal('folder'), | |||
'item_source' => $qb->expr()->literal(123), | |||
'item_target' => $qb->expr()->literal('/123'), | |||
'file_source' => $qb->expr()->literal(123), | |||
'file_target' => $qb->expr()->literal('/test'), | |||
'permissions' => $qb->expr()->literal(\OCP\Constants::PERMISSION_READ), | |||
'stime' => $qb->expr()->literal(time()), | |||
]) | |||
->execute(); | |||
$keepThisShareId = $this->getLastShareId(); | |||
// user share to keep | |||
$qb = $this->connection->getQueryBuilder(); | |||
$qb->insert('share') | |||
->values([ | |||
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER), | |||
'share_with' => $qb->expr()->literal('recipientuser1'), | |||
'uid_owner' => $qb->expr()->literal('user1'), | |||
'item_type' => $qb->expr()->literal('folder'), | |||
'item_source' => $qb->expr()->literal(123), | |||
'item_target' => $qb->expr()->literal('/123'), | |||
'file_source' => $qb->expr()->literal(123), | |||
'file_target' => $qb->expr()->literal('/test'), | |||
'permissions' => $qb->expr()->literal(3), | |||
'stime' => $qb->expr()->literal(time()), | |||
]) | |||
->execute(); | |||
$keepThisShareId2 = $this->getLastShareId(); | |||
/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */ | |||
$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput') | |||
->disableOriginalConstructor() | |||
->getMock(); | |||
$this->repair->run($outputMock); | |||
$results = $this->connection->getQueryBuilder() | |||
->select('*') | |||
->from('share') | |||
->orderBy('permissions', 'ASC') | |||
->execute() | |||
->fetchAll(); | |||
$this->assertCount(3, $results); | |||
$untouchedShare = $results[0]; | |||
$untouchedShare2 = $results[1]; | |||
$updatedShare = $results[2]; | |||
$this->assertEquals($keepThisShareId, $untouchedShare['id'], 'sanity check'); | |||
$this->assertEquals($keepThisShareId2, $untouchedShare2['id'], 'sanity check'); | |||
$this->assertEquals($bogusShareId, $updatedShare['id'], 'sanity check'); | |||
$this->assertEquals($newPerms, $updatedShare['permissions'], 'delete permission was added'); | |||
} | |||
/** | |||
* Test remove shares where the parent share does not exist anymore | |||
*/ |
@@ -1327,24 +1327,6 @@ class ManagerTest extends \Test\TestCase { | |||
$this->invokePrivate($this->manager, 'linkCreateChecks', [$share]); | |||
} | |||
/** | |||
* @expectedException Exception | |||
* @expectedExceptionMessage Link shares can't have delete permissions | |||
*/ | |||
public function testLinkCreateChecksDeletePermissions() { | |||
$share = $this->manager->newShare(); | |||
$share->setPermissions(\OCP\Constants::PERMISSION_DELETE); | |||
$this->config | |||
->method('getAppValue') | |||
->will($this->returnValueMap([ | |||
['core', 'shareapi_allow_links', 'yes', 'yes'], | |||
])); | |||
$this->invokePrivate($this->manager, 'linkCreateChecks', [$share]); | |||
} | |||
/** | |||
* @expectedException Exception | |||
* @expectedExceptionMessage Public upload not allowed |
@@ -314,6 +314,36 @@ class SessionTest extends \Test\TestCase { | |||
$userSession->login('foo', 'bar'); | |||
} | |||
/** | |||
* When using a device token, the loginname must match the one that was used | |||
* when generating the token on the browser. | |||
*/ | |||
public function testLoginWithDifferentTokenLoginName() { | |||
$session = $this->getMock('\OC\Session\Memory', array(), array('')); | |||
$manager = $this->getMock('\OC\User\Manager'); | |||
$backend = $this->getMock('\Test\Util\User\Dummy'); | |||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); | |||
$username = 'user123'; | |||
$token = new \OC\Authentication\Token\DefaultToken(); | |||
$token->setLoginName($username); | |||
$session->expects($this->never()) | |||
->method('set'); | |||
$session->expects($this->once()) | |||
->method('regenerateId'); | |||
$this->tokenProvider->expects($this->once()) | |||
->method('getToken') | |||
->with('bar') | |||
->will($this->returnValue($token)); | |||
$manager->expects($this->once()) | |||
->method('checkPassword') | |||
->with('foo', 'bar') | |||
->will($this->returnValue(false)); | |||
$userSession->login('foo', 'bar'); | |||
} | |||
/** | |||
* @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException | |||
*/ |
@@ -25,7 +25,7 @@ | |||
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades | |||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel | |||
// when updating major/minor version number. | |||
$OC_Version = array(9, 1, 0, 9); | |||
$OC_Version = array(9, 1, 0, 10); | |||
// The human readable string | |||
$OC_VersionString = '9.1.0 beta 2'; |