diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 7b037a7a201..5eb8ac05499 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -4269,6 +4269,11 @@
+
+
+
+
+
diff --git a/core/Controller/TeamsApiController.php b/core/Controller/TeamsApiController.php
index 2eb33a0c254..0dac1920ff8 100644
--- a/core/Controller/TeamsApiController.php
+++ b/core/Controller/TeamsApiController.php
@@ -17,10 +17,12 @@ use OCP\AppFramework\OCSController;
use OCP\IRequest;
use OCP\Teams\ITeamManager;
use OCP\Teams\Team;
+use OCP\Teams\TeamResource;
/**
* @psalm-import-type CoreTeamResource from ResponseDefinitions
* @psalm-import-type CoreTeam from ResponseDefinitions
+ * @psalm-import-type CoreTeamWithResources from ResponseDefinitions
* @property $userId string
*/
class TeamsApiController extends OCSController {
@@ -44,13 +46,10 @@ class TeamsApiController extends OCSController {
#[NoAdminRequired]
#[ApiRoute(verb: 'GET', url: '/{teamId}/resources', root: '/teams')]
public function resolveOne(string $teamId): DataResponse {
- /**
- * @var list $resolvedResources
- * @psalm-suppress PossiblyNullArgument The route is limited to logged-in users
- */
+ /** @psalm-suppress PossiblyNullArgument The route is limited to logged-in users */
$resolvedResources = $this->teamManager->getSharedWith($teamId, $this->userId);
- return new DataResponse(['resources' => $resolvedResources]);
+ return new DataResponse(['resources' => array_map(static fn (TeamResource $resource) => $resource->jsonSerialize(), $resolvedResources)]);
}
/**
@@ -58,7 +57,7 @@ class TeamsApiController extends OCSController {
*
* @param string $providerId Identifier of the provider (e.g. deck, talk, collectives)
* @param string $resourceId Unique id of the resource to list teams for (e.g. deck board id)
- * @return DataResponse}, array{}>
+ * @return DataResponse}, array{}>
*
* 200: Teams returned
*/
@@ -67,16 +66,15 @@ class TeamsApiController extends OCSController {
public function listTeams(string $providerId, string $resourceId): DataResponse {
/** @psalm-suppress PossiblyNullArgument The route is limited to logged-in users */
$teams = $this->teamManager->getTeamsForResource($providerId, $resourceId, $this->userId);
- /** @var list $teams */
- $teams = array_values(array_map(function (Team $team) {
+ $sharesPerTeams = $this->teamManager->getSharedWithList(array_map(fn (Team $team): string => $team->getId(), $teams), $this->userId);
+ $listTeams = array_values(array_map(function (Team $team) use ($sharesPerTeams) {
$response = $team->jsonSerialize();
- /** @psalm-suppress PossiblyNullArgument The route is limited to logged in users */
- $response['resources'] = $this->teamManager->getSharedWith($team->getId(), $this->userId);
+ $response['resources'] = array_map(static fn (TeamResource $resource) => $resource->jsonSerialize(), $sharesPerTeams[$team->getId()] ?? []);
return $response;
}, $teams));
return new DataResponse([
- 'teams' => $teams,
+ 'teams' => $listTeams,
]);
}
}
diff --git a/core/ResponseDefinitions.php b/core/ResponseDefinitions.php
index 5a0c00524ee..a52b8a0bc0b 100644
--- a/core/ResponseDefinitions.php
+++ b/core/ResponseDefinitions.php
@@ -149,19 +149,28 @@ namespace OC\Core;
* }
*
* @psalm-type CoreTeam = array{
- * id: string,
- * name: string,
- * icon: string,
+ * teamId: string,
+ * displayName: string,
+ * link: ?string,
* }
*
* @psalm-type CoreTeamResource = array{
- * id: int,
- * label: string,
- * url: string,
- * iconSvg: ?string,
- * iconURL: ?string,
- * iconEmoji: ?string,
- * }
+ * id: string,
+ * label: string,
+ * url: string,
+ * iconSvg: ?string,
+ * iconURL: ?string,
+ * iconEmoji: ?string,
+ * provider: array{
+ * id: string,
+ * name: string,
+ * icon: string,
+ * },
+ * }
+ *
+ * @psalm-type CoreTeamWithResources = CoreTeam&array{
+ * resources: list,
+ * }
*
* @psalm-type CoreTaskProcessingShape = array{
* name: string,
diff --git a/core/openapi-full.json b/core/openapi-full.json
index a029ee84d9c..805944296b7 100644
--- a/core/openapi-full.json
+++ b/core/openapi-full.json
@@ -898,19 +898,20 @@
"Team": {
"type": "object",
"required": [
- "id",
- "name",
- "icon"
+ "teamId",
+ "displayName",
+ "link"
],
"properties": {
- "id": {
+ "teamId": {
"type": "string"
},
- "name": {
+ "displayName": {
"type": "string"
},
- "icon": {
- "type": "string"
+ "link": {
+ "type": "string",
+ "nullable": true
}
}
},
@@ -922,12 +923,12 @@
"url",
"iconSvg",
"iconURL",
- "iconEmoji"
+ "iconEmoji",
+ "provider"
],
"properties": {
"id": {
- "type": "integer",
- "format": "int64"
+ "type": "string"
},
"label": {
"type": "string"
@@ -946,9 +947,49 @@
"iconEmoji": {
"type": "string",
"nullable": true
+ },
+ "provider": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "icon"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "icon": {
+ "type": "string"
+ }
+ }
}
}
},
+ "TeamWithResources": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Team"
+ },
+ {
+ "type": "object",
+ "required": [
+ "resources"
+ ],
+ "properties": {
+ "resources": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TeamResource"
+ }
+ }
+ }
+ }
+ ]
+ },
"TextProcessingTask": {
"type": "object",
"required": [
@@ -6306,7 +6347,7 @@
"teams": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Team"
+ "$ref": "#/components/schemas/TeamWithResources"
}
}
}
diff --git a/core/openapi.json b/core/openapi.json
index 471e6567b84..f1f04cb02d9 100644
--- a/core/openapi.json
+++ b/core/openapi.json
@@ -898,19 +898,20 @@
"Team": {
"type": "object",
"required": [
- "id",
- "name",
- "icon"
+ "teamId",
+ "displayName",
+ "link"
],
"properties": {
- "id": {
+ "teamId": {
"type": "string"
},
- "name": {
+ "displayName": {
"type": "string"
},
- "icon": {
- "type": "string"
+ "link": {
+ "type": "string",
+ "nullable": true
}
}
},
@@ -922,12 +923,12 @@
"url",
"iconSvg",
"iconURL",
- "iconEmoji"
+ "iconEmoji",
+ "provider"
],
"properties": {
"id": {
- "type": "integer",
- "format": "int64"
+ "type": "string"
},
"label": {
"type": "string"
@@ -946,9 +947,49 @@
"iconEmoji": {
"type": "string",
"nullable": true
+ },
+ "provider": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "icon"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "icon": {
+ "type": "string"
+ }
+ }
}
}
},
+ "TeamWithResources": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Team"
+ },
+ {
+ "type": "object",
+ "required": [
+ "resources"
+ ],
+ "properties": {
+ "resources": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TeamResource"
+ }
+ }
+ }
+ }
+ ]
+ },
"TextProcessingTask": {
"type": "object",
"required": [
@@ -6306,7 +6347,7 @@
"teams": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Team"
+ "$ref": "#/components/schemas/TeamWithResources"
}
}
}
diff --git a/lib/private/Teams/TeamManager.php b/lib/private/Teams/TeamManager.php
index 13d6cc459a9..c5ede021d6d 100644
--- a/lib/private/Teams/TeamManager.php
+++ b/lib/private/Teams/TeamManager.php
@@ -84,24 +84,38 @@ class TeamManager implements ITeamManager {
return array_values($resources);
}
- public function getTeamsForResource(string $providerId, string $resourceId, string $userId): array {
+ public function getSharedWithList(array $teams, string $userId): array {
if (!$this->hasTeamSupport()) {
return [];
}
- $provider = $this->getProvider($providerId);
- return array_values(array_filter(array_map(function ($teamId) use ($userId) {
- $team = $this->getTeam($teamId, $userId);
- if ($team === null) {
- return null;
+ $resources = [];
+ foreach ($this->getProviders() as $provider) {
+ if (method_exists($provider, 'getSharedWithList')) {
+ $resources[] = $provider->getSharedWithList($teams, $userId);
+ } else {
+ foreach ($teams as $team) {
+ $resources[] = [$team->getId() => $provider->getSharedWith($team->getId())];
+ }
}
+ }
+ return array_merge_recursive(...$resources);
+ }
+
+ public function getTeamsForResource(string $providerId, string $resourceId, string $userId): array {
+ if (!$this->hasTeamSupport()) {
+ return [];
+ }
+
+ $provider = $this->getProvider($providerId);
+ return array_map(function (Circle $team) {
return new Team(
- $teamId,
+ $team->getSingleId(),
$team->getDisplayName(),
- $this->urlGenerator->linkToRouteAbsolute('contacts.contacts.directcircle', ['singleId' => $teamId]),
+ $this->urlGenerator->linkToRouteAbsolute('contacts.contacts.directcircle', ['singleId' => $team->getSingleId()]),
);
- }, $provider->getTeamsForResource($resourceId))));
+ }, $this->getTeams($provider->getTeamsForResource($resourceId), $userId));
}
private function getTeam(string $teamId, string $userId): ?Circle {
@@ -117,4 +131,17 @@ class TeamManager implements ITeamManager {
return null;
}
}
+
+ /**
+ * @return Circle[]
+ */
+ private function getTeams(array $teams, string $userId): array {
+ if (!$this->hasTeamSupport()) {
+ return [];
+ }
+
+ $federatedUser = $this->circlesManager->getFederatedUser($userId, Member::TYPE_USER);
+ $this->circlesManager->startSession($federatedUser);
+ return $this->circlesManager->getCirclesByIds($teams);
+ }
}
diff --git a/lib/public/Teams/ITeamManager.php b/lib/public/Teams/ITeamManager.php
index 3f737b4229c..b39b8da157b 100644
--- a/lib/public/Teams/ITeamManager.php
+++ b/lib/public/Teams/ITeamManager.php
@@ -40,4 +40,12 @@ interface ITeamManager {
* @since 29.0.0
*/
public function getTeamsForResource(string $providerId, string $resourceId, string $userId): array;
+
+ /**
+ * @param list $teams
+ * @return array>
+ *
+ * @since 33.0.0
+ */
+ public function getSharedWithList(array $teams, string $userId): array;
}
diff --git a/lib/public/Teams/Team.php b/lib/public/Teams/Team.php
index 474ebaed84f..cc70f6fbd45 100644
--- a/lib/public/Teams/Team.php
+++ b/lib/public/Teams/Team.php
@@ -50,6 +50,12 @@ class Team implements \JsonSerializable {
}
/**
+ * @return array{
+ * teamId: string,
+ * displayName: string,
+ * link: ?string,
+ * }
+ *
* @since 29.0.0
*/
public function jsonSerialize(): array {
diff --git a/lib/public/Teams/TeamResource.php b/lib/public/Teams/TeamResource.php
index acb98380562..a15faacf79b 100644
--- a/lib/public/Teams/TeamResource.php
+++ b/lib/public/Teams/TeamResource.php
@@ -94,6 +94,20 @@ class TeamResource implements \JsonSerializable {
}
/**
+ * @return array{
+ * id: string,
+ * label: string,
+ * url: string,
+ * iconSvg: ?string,
+ * iconURL: ?string,
+ * iconEmoji: ?string,
+ * provider: array{
+ * id: string,
+ * name: string,
+ * icon: string,
+ * },
+ * }
+ *
* @since 29.0.0
*/
public function jsonSerialize(): array {
diff --git a/openapi.json b/openapi.json
index 8307e44dda7..e86802a938d 100644
--- a/openapi.json
+++ b/openapi.json
@@ -940,19 +940,20 @@
"CoreTeam": {
"type": "object",
"required": [
- "id",
- "name",
- "icon"
+ "teamId",
+ "displayName",
+ "link"
],
"properties": {
- "id": {
+ "teamId": {
"type": "string"
},
- "name": {
+ "displayName": {
"type": "string"
},
- "icon": {
- "type": "string"
+ "link": {
+ "type": "string",
+ "nullable": true
}
}
},
@@ -964,12 +965,12 @@
"url",
"iconSvg",
"iconURL",
- "iconEmoji"
+ "iconEmoji",
+ "provider"
],
"properties": {
"id": {
- "type": "integer",
- "format": "int64"
+ "type": "string"
},
"label": {
"type": "string"
@@ -988,9 +989,49 @@
"iconEmoji": {
"type": "string",
"nullable": true
+ },
+ "provider": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "icon"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "icon": {
+ "type": "string"
+ }
+ }
}
}
},
+ "CoreTeamWithResources": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/CoreTeam"
+ },
+ {
+ "type": "object",
+ "required": [
+ "resources"
+ ],
+ "properties": {
+ "resources": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/CoreTeamResource"
+ }
+ }
+ }
+ }
+ ]
+ },
"CoreTextProcessingTask": {
"type": "object",
"required": [
@@ -9819,7 +9860,7 @@
"teams": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/CoreTeam"
+ "$ref": "#/components/schemas/CoreTeamWithResources"
}
}
}