mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 16:26:59 -04:00
Merge pull request #56342 from nextcloud/backport/54953/stable31
Some checks are pending
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
Some checks are pending
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
[stable31] fix(team-api): get all teams details in a single request
This commit is contained in:
commit
aec7253ddd
9 changed files with 203 additions and 51 deletions
|
|
@ -2525,6 +2525,11 @@
|
|||
<code><![CDATA[$path]]></code>
|
||||
</InvalidReturnStatement>
|
||||
</file>
|
||||
<file src="lib/private/Teams/TeamManager.php">
|
||||
<UndefinedDocblockClass>
|
||||
<code><![CDATA[Circle]]></code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="lib/private/User/Database.php">
|
||||
<FalsableReturnStatement>
|
||||
<code><![CDATA[false]]></code>
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ use OCP\AppFramework\Http\DataResponse;
|
|||
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 \OCP\AppFramework\OCSController {
|
||||
|
|
@ -43,13 +45,10 @@ class TeamsApiController extends \OCP\AppFramework\OCSController {
|
|||
#[NoAdminRequired]
|
||||
#[ApiRoute(verb: 'GET', url: '/{teamId}/resources', root: '/teams')]
|
||||
public function resolveOne(string $teamId): DataResponse {
|
||||
/**
|
||||
* @var list<CoreTeamResource> $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)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,7 +56,7 @@ class TeamsApiController extends \OCP\AppFramework\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<Http::STATUS_OK, array{teams: list<CoreTeam>}, array{}>
|
||||
* @return DataResponse<Http::STATUS_OK, array{teams: list<CoreTeamWithResources>}, array{}>
|
||||
*
|
||||
* 200: Teams returned
|
||||
*/
|
||||
|
|
@ -66,16 +65,16 @@ class TeamsApiController extends \OCP\AppFramework\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<CoreTeam> $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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,19 +148,30 @@ 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<CoreTeamResource>,
|
||||
* }
|
||||
*
|
||||
*
|
||||
*
|
||||
* @psalm-type CoreTaskProcessingShape = array{
|
||||
* name: string,
|
||||
|
|
|
|||
|
|
@ -869,19 +869,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
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -893,12 +894,12 @@
|
|||
"url",
|
||||
"iconSvg",
|
||||
"iconURL",
|
||||
"iconEmoji"
|
||||
"iconEmoji",
|
||||
"provider"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
|
|
@ -917,9 +918,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": [
|
||||
|
|
@ -5379,7 +5420,7 @@
|
|||
"teams": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Team"
|
||||
"$ref": "#/components/schemas/TeamWithResources"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -869,19 +869,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
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -893,12 +894,12 @@
|
|||
"url",
|
||||
"iconSvg",
|
||||
"iconURL",
|
||||
"iconEmoji"
|
||||
"iconEmoji",
|
||||
"provider"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
|
|
@ -917,9 +918,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": [
|
||||
|
|
@ -5379,7 +5420,7 @@
|
|||
"teams": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Team"
|
||||
"$ref": "#/components/schemas/TeamWithResources"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,24 +83,38 @@ class TeamManager implements ITeamManager {
|
|||
return array_values($resources);
|
||||
}
|
||||
|
||||
public function getSharedWithList(array $teams, string $userId): array {
|
||||
if (!$this->hasTeamSupport()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$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_values(array_filter(array_map(function ($teamId) use ($userId) {
|
||||
$team = $this->getTeam($teamId, $userId);
|
||||
if ($team === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -116,4 +130,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,12 @@ interface ITeamManager {
|
|||
* @since 29.0.0
|
||||
*/
|
||||
public function getTeamsForResource(string $providerId, string $resourceId, string $userId): array;
|
||||
|
||||
/**
|
||||
* @param list<Team> $teams
|
||||
* @return array<string, list<TeamResource>>
|
||||
*
|
||||
* @since 31.0.11
|
||||
*/
|
||||
public function getSharedWithList(array $teams, string $userId): array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ class Team implements \JsonSerializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array{
|
||||
* teamId: string,
|
||||
* displayName: string,
|
||||
* link: ?string,
|
||||
* }
|
||||
*
|
||||
* @since 29.0.0
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue