Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions apps/files_sharing/lib/Controller/ShareAPIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@ private function getSharesInDir(Node $folder): array {
* @param string $subfiles Only get all shares in a folder
* @param string $path Get shares for a specific path
* @param string $include_tags Include tags in the share
* @param list<int> $types List of share types to return
*
* @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
* @throws OCSNotFoundException The folder was not found or is inaccessible
Expand All @@ -928,6 +929,7 @@ public function getShares(
string $subfiles = 'false',
string $path = '',
string $include_tags = 'false',
array $types = [],
): DataResponse {
$node = null;
if ($path !== '') {
Expand All @@ -944,13 +946,37 @@ public function getShares(
}
}

$types = array_map('intval', $types);
$validTypesFiltered = array_filter($types, function ($type) {
return match ($type) {
IShare::TYPE_USER,
IShare::TYPE_GROUP,
IShare::TYPE_LINK,
IShare::TYPE_EMAIL,
IShare::TYPE_REMOTE,
IShare::TYPE_REMOTE_GROUP,
IShare::TYPE_CIRCLE,
IShare::TYPE_ROOM,
IShare::TYPE_DECK,
IShare::TYPE_SCIENCEMESH => true,
default => false,
};
});

if (count($types) !== count($validTypesFiltered)) {
throw new OCSBadRequestException(
$this->l->t('Cannot filter by unknown share types')
);
}

$shares = $this->getFormattedShares(
$this->userId,
$node,
($shared_with_me === 'true'),
($reshares === 'true'),
($subfiles === 'true'),
($include_tags === 'true')
($include_tags === 'true'),
$types
);

return new DataResponse($shares);
Expand Down Expand Up @@ -1041,6 +1067,7 @@ private function getFormattedShares(
bool $reShares = false,
bool $subFiles = false,
bool $includeTags = false,
array $types = [],
): array {
if ($sharedWithMe) {
return $this->getSharedWithMe($node, $includeTags);
Expand All @@ -1050,7 +1077,7 @@ private function getFormattedShares(
return $this->getSharesInDir($node);
}

$shares = $this->getSharesFromNode($viewer, $node, $reShares);
$shares = $this->getSharesFromNode($viewer, $node, $reShares, $types);

$known = $formatted = $miniFormatted = [];
$resharingRight = false;
Expand All @@ -1070,6 +1097,11 @@ private function getFormattedShares(
continue;
}

// Filter out share types not requested in non-empty $types array
if (!empty($types) && !in_array($share->getShareType(), $types)) {
continue;
}

$known[] = $share->getId();
try {
/** @var IShare $share */
Expand Down Expand Up @@ -1855,7 +1887,7 @@ private function getSciencemeshShareHelper() {
*
* @return IShare[]
*/
private function getSharesFromNode(string $viewer, $node, bool $reShares): array {
private function getSharesFromNode(string $viewer, $node, bool $reShares, array $limitToProviders = []): array {
$providers = [
IShare::TYPE_USER,
IShare::TYPE_GROUP,
Expand All @@ -1867,6 +1899,10 @@ private function getSharesFromNode(string $viewer, $node, bool $reShares): array
IShare::TYPE_SCIENCEMESH
];

if (count($limitToProviders) > 0) {
$providers = $limitToProviders;
}

// Should we assume that the (currentUser) viewer is the owner of the node !?
$shares = [];
foreach ($providers as $provider) {
Expand Down
13 changes: 13 additions & 0 deletions apps/files_sharing/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,19 @@
"default": "false"
}
},
{
"name": "types[]",
"in": "query",
"description": "List of share types to return",
"schema": {
"type": "array",
"default": [],
"items": {
"type": "integer",
"format": "int64"
}
}
},
{
"name": "OCS-APIRequest",
"in": "header",
Expand Down
55 changes: 48 additions & 7 deletions apps/files_sharing/src/views/SharingTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@
:reshare="reshare"
:shares="shares"
@open-sharing-details="toggleShareDetailsView" />
<!-- Non link external shares list -->
<SharingList v-if="!loading"
:shares="externalShares"
:file-info="fileInfo"
@open-sharing-details="toggleShareDetailsView" />
<!-- link shares list -->
<SharingLinkList v-if="!loading"
ref="linkShareList"
Expand Down Expand Up @@ -214,6 +219,7 @@ export default {
reshare: null,
sharedWithMe: {},
shares: [],
externalShares: [],
linkShares: [],

sections: OCA.Sharing.ShareTabSections.getSections(),
Expand Down Expand Up @@ -270,11 +276,17 @@ export default {
const path = (this.fileInfo.path + '/' + this.fileInfo.name).replace('//', '/')

// fetch shares
const includeTypes = [ShareType.User,
ShareType.Group,
ShareType.Link,
ShareType.Email,
ShareType.ScienceMesh]
const fetchShares = axios.get(shareUrl, {
params: {
format,
path,
reshares: true,
types: includeTypes,
},
})
const fetchSharedWithMe = axios.get(shareUrl, {
Expand All @@ -285,13 +297,22 @@ export default {
},
})

const fetchRemoteShares = axios.get(shareUrl, {
params: {
format,
path,
types: [ShareType.Remote, ShareType.RemoteGroup, ShareType.Federated],
},
})

// wait for data
const [shares, sharedWithMe] = await Promise.all([fetchShares, fetchSharedWithMe])
const [shares, sharedWithMe, remoteShares] = await Promise.all([fetchShares, fetchSharedWithMe, fetchRemoteShares])
this.loading = false

// process results
this.processSharedWithMe(sharedWithMe)
this.processShares(shares)
this.processExternalShares(remoteShares)
} catch (error) {
if (error?.response?.data?.ocs?.meta?.message) {
this.error = error.response.data.ocs.meta.message
Expand Down Expand Up @@ -336,7 +357,18 @@ export default {
this.$set(this.sharedWithMe, 'subtitle', t('files_sharing', 'this share just expired.'))
}
},

/**
* Processes share data from an OCS API response.
*
* @param {object} data The OCS API response data.
* @return {Share[]|null} An array of Share objects, or null if no data is present.
*/
processShareData(data) {
if (data.ocs && data.ocs.data && data.ocs.data.length > 0) {
return data.ocs.data.map(share => new Share(share))
}
return null
},
/**
* Process the current shares data
* and init shares[]
Expand All @@ -345,9 +377,12 @@ export default {
* @param {object} share.data the request data
*/
processShares({ data }) {
if (data.ocs && data.ocs.data && data.ocs.data.length > 0) {
const shares = orderBy(
data.ocs.data.map(share => new Share(share)),

const shares = this.processShareData(data)

if (shares) {
const orderedShares = orderBy(
shares,
[
// First order by the "share with" label
(share) => share.shareWithDisplayName,
Expand All @@ -358,13 +393,19 @@ export default {
],
)

this.linkShares = shares.filter(share => share.type === ShareType.Link || share.type === ShareType.Email)
this.shares = shares.filter(share => share.type !== ShareType.Link && share.type !== ShareType.Email)
this.linkShares = orderedShares.filter(share => share.type === ShareType.Link || share.type === ShareType.Email)
this.shares = orderedShares.filter(share => share.type !== ShareType.Link && share.type !== ShareType.Email)

console.debug('Processed', this.linkShares.length, 'link share(s)')
console.debug('Processed', this.shares.length, 'share(s)')
}
},
processExternalShares({ data }) {
const shares = this.processShareData(data)
if (shares) {
this.externalShares = shares
}
},

/**
* Process the sharedWithMe share data
Expand Down
Loading