diff --git a/admin_manual/configuration_files/index.rst b/admin_manual/configuration_files/index.rst index 375c888d5f7..af493628a26 100644 --- a/admin_manual/configuration_files/index.rst +++ b/admin_manual/configuration_files/index.rst @@ -8,6 +8,7 @@ File sharing and management file_sharing_configuration federated_cloud_sharing_configuration + team_folders big_file_upload_configuration default_files_configuration primary_storage diff --git a/admin_manual/configuration_files/team_folders.rst b/admin_manual/configuration_files/team_folders.rst new file mode 100644 index 00000000000..62f149bffd7 --- /dev/null +++ b/admin_manual/configuration_files/team_folders.rst @@ -0,0 +1,125 @@ +============================ +Team folders and team spaces +============================ + +Team folders are folders that are mounted for a set of groups or teams rather than owned by one account. They are +provided by the **Team folders** app, whose app id is ``groupfolders`` - the name you will see in :command:`occ` +commands, in the app store and in log entries. + +A **team space** is a team folder in an exclusive relationship with a single team: it belongs to that team, follows +the team's membership, and has its own quota. Team spaces were introduced in Nextcloud 35. + +Team folder or team space? +-------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 30 35 35 + + * - + - Team folder + - Team space + * - Mounted for + - any number of groups and teams + - exactly one team + * - Created by + - an administrator or a delegated group + - the team owner, or an administrator + * - Membership follows + - the groups and teams you assign + - the team's own membership + * - Quota + - set per folder + - set per space + +Which teams can have a space +---------------------------- + +A team is not eligible for a team space if it is: + +- a **personal** team, +- a **hidden** team, +- a **system** team, or +- a team provided by an **external backend**. + +For every other team, the **owner** or a server administrator can add a space. Members, moderators and team admins +cannot. + +Configuration +------------- + +Team space provisioning is controlled by two app settings of the ``circles`` app. Neither is exposed in the +administration interface, so set them with :command:`occ`: + +.. code-block:: bash + + # allow teams to be created with a space, and existing teams to be upgraded (default: yes) + occ config:app:set circles team_folder_auto_create --value=1 --type=boolean + + # default quota in bytes for a new team space; 0 means unlimited (default: 0) + occ config:app:set circles team_folder_default_quota --value=0 --type=integer + +With provisioning disabled, requests to create or upgrade a team space are refused, and existing spaces are left +untouched. + +.. note:: + + A team space is only created at team-creation time if the person creating the team asks for one. Teams created + without a space are not upgraded automatically; someone has to upgrade them deliberately. + +Detaching versus deleting +------------------------- + +.. warning:: + + These two actions look similar and are not. + +**Detaching** ends the exclusive relationship and **keeps the folder and its contents**. The folder remains as an +ordinary team folder that you can reassign to groups, teams or nobody. This is the intended way to recover access to +the contents of a team that is being disbanded. + +**Deleting** removes the team folder and everything in it. + +How team folders interact with other features +--------------------------------------------- + +Team folders behave differently from ordinary user storage in several areas that are documented elsewhere: + +- :doc:`encryption_configuration` - encrypting team folders and other non-home mount points. +- :doc:`primary_storage` - how team folder contents are stored on object storage. +- :doc:`trashbin_configuration` - deleted files from a team folder go to the team folder's own trash. +- :doc:`../configuration_server/activity_configuration` - activities for team folders, and why they can be missing. + +Frequently asked questions +-------------------------- + +**What is the difference between a team folder and a team space?** + A team folder is mounted for any number of groups and teams and is administered centrally. A team space is a team + folder in an **exclusive** relationship with one team: it belongs to that team, follows its membership, and has + its own quota. See the comparison above. + +**A user says their team cannot own any files. Is that expected?** + Yes. A team is a membership list; anything shared with it stays owned by the account that shared it. For storage + owned by the team, the team needs a space, which its owner can add if provisioning is enabled. + +**Why is the option to add a space missing for one particular team?** + Either provisioning is disabled server-wide, or the team is not eligible - personal, hidden, system and + backend-provided teams cannot have a space. The person asking may also not be the team's owner. + +**Can I convert an existing team folder into a team's space?** + Yes. An existing team folder can be linked to a team instead of creating a new one, which is the way to migrate a + folder that predates team spaces. + +**How do I take a space away from a team without losing the data?** + Detach it. The folder and its contents survive; only the exclusive relationship ends. + +**Does a team space count against the members' quotas?** + No. It has its own quota, set per space, where zero means unlimited. + +**Can I limit the size of a team space?** + Yes. A new space is created with the quota from ``team_folder_default_quota``, and the quota of an existing space + can be changed afterwards. Zero means unlimited. + +**Which apps can contribute resources to a team?** + Files, Talk and Deck out of the box, and any app implementing the team resource provider interface described in + the developer manual under *Digging deeper* → *Teams*. diff --git a/developer_manual/digging_deeper/index.rst b/developer_manual/digging_deeper/index.rst index bf10a488549..0643bf0393d 100644 --- a/developer_manual/digging_deeper/index.rst +++ b/developer_manual/digging_deeper/index.rst @@ -10,6 +10,7 @@ Digging deeper auth direct_editing groupware_workflows + teams discovery devtools internals diff --git a/developer_manual/digging_deeper/teams.rst b/developer_manual/digging_deeper/teams.rst new file mode 100644 index 00000000000..4c2ac674cc0 --- /dev/null +++ b/developer_manual/digging_deeper/teams.rst @@ -0,0 +1,114 @@ +===== +Teams +===== + +Teams are user-defined groups of accounts, provided by the **Teams** app (app id ``circles``). Apps do not store +anything in a team themselves: they *contribute* to it, by telling the server which of their own resources are shared +with a given team. A team's overview is assembled from every app that does so. + +The API lives in the ``OCP\Teams`` namespace and has been available since Nextcloud 29. + +Contributing resources to a team +-------------------------------- + +Implement ``OCP\Teams\ITeamResourceProvider`` and register it from your ``Application`` class: + +.. code-block:: php + + registerTeamResourceProvider(MyAppResourceProvider::class); + } + + public function boot(IBootContext $context): void { + } + } + +The provider answers three questions about your app's resources: + +.. code-block:: php + + interface ITeamResourceProvider { + public function getId(): string; // your provider id, e.g. 'deck' + public function getName(): string; // translated, shown to users + public function getIconSvg(): string; // inline SVG + + /** @return TeamResource[] resources of yours shared with this team */ + public function getSharedWith(string $teamId): array; + + public function isSharedWithTeam(string $teamId, string $resourceId): bool; + + /** @return string[] team ids a resource of yours is shared with */ + public function getTeamsForResource(string $resourceId): array; + } + +Each resource is returned as an ``OCP\Teams\TeamResource``, carrying the provider, an id, a label, a URL and an icon +- as inline SVG, a URL or an emoji. + +.. note:: + + A resource contributed this way is still owned by whoever created it. Nothing about registering a provider makes + the team the owner of anything. + +Reading teams and their resources +--------------------------------- + +``OCP\Teams\ITeamManager`` is the consumer side: + +.. code-block:: php + + $providers = $teamManager->getProviders(); // since 29.0.0 + $provider = $teamManager->getProvider('deck'); // since 29.0.0 + $resources = $teamManager->getSharedWith($teamId, $userId); // since 29.0.0 + $teams = $teamManager->getTeamsForResource('deck', $boardId, $userId); // since 29.0.0 + $teams = $teamManager->getTeamsForUser($userId); // since 33.0.0 + $lists = $teamManager->getSharedWithList($teams, $userId, $resourceId); // since 33.0.0 + $members = $teamManager->getMembersOfTeam($teamId, $userId); // since 34.0.0 + +``getSharedWithList()`` gained its ``$resourceId`` parameter in 34.0.0, so guard for the server version if your app +supports older releases. + +The team folder provider +------------------------ + +Since Nextcloud 35 a team can also have **one exclusive folder** - a team space. That folder is supplied by an +implementation of ``OCP\Teams\ITeamFolderProvider``, which extends ``ITeamResourceProvider``: + +.. code-block:: php + + interface ITeamFolderProvider extends ITeamResourceProvider { + public function getTeamFolder(string $teamId): ?TeamFolder; + public function createTeamFolder(Team $team, int $quota = 0): TeamFolder; // quota 0 = unlimited + public function getLinkableTeamFolders(string $circleId): array; + public function linkTeamFolder(string $circleId, int $folderId): TeamFolder; + public function updateTeamFolderQuota(string $teamId, int $quota): TeamFolder; + public function unlinkTeamFolder(string $teamId): ?TeamFolder; // keeps the folder + public function removeTeamFolder(string $teamId): bool; // deletes the folder + } + +Implementations are registered the same way as any other resource provider, through +``registerTeamResourceProvider()``. Retrieve the active one with ``ITeamManager::getTeamFolderProvider()``, which +returns ``null`` when no app provides team folders - always handle that case. + +.. warning:: + + ``unlinkTeamFolder()`` ends the relationship and preserves the folder and its contents; ``removeTeamFolder()`` + deletes them. If you expose either in a user interface, make the difference obvious. + +Implementations to look at +-------------------------- + +- **Files** - ``FileSharingTeamResourceProvider`` in the ``circles`` app, for files and folders shared with a team. +- **Talk** - ``TalkTeamResourceProvider`` in ``spreed``, for conversations. +- **Deck** - ``DeckTeamResourceProvider``, for boards. +- **Team folders** - ``TeamSpaceProvider`` in ``groupfolders``, the reference implementation of + ``ITeamFolderProvider``. diff --git a/user_manual/groupware/index.rst b/user_manual/groupware/index.rst index abfea4355be..ce5d4cdf3d2 100644 --- a/user_manual/groupware/index.rst +++ b/user_manual/groupware/index.rst @@ -15,6 +15,7 @@ You can find out more about Nextcloud Groupware `on our website